Revert "Merge backports 3.19-rc1."
This reverts commit 8d993c265e5f74b4489d9423bc2ad2c37e8f77ab.
because of an inadvertent non-merge commit.
Change-Id: I83179943b19a386729a691f850ab6fda48f237ed
diff --git a/.local-symbols b/.local-symbols
index ab02e9a..82cfa7c 100644
--- a/.local-symbols
+++ b/.local-symbols
@@ -1,25 +1,24 @@
-BACKPORT_DIR=
BACKPORTS_VERSION=
BACKPORTED_KERNEL_VERSION=
BACKPORTED_KERNEL_NAME=
WIRELESS=
NET_CORE=
EXPERT=
-BPAUTO_BUILD_CORDIC=
-BPAUTO_CORDIC=
-BPAUTO_BUILD_AVERAGE=
-BPAUTO_AVERAGE=
-BPAUTO_MII=
-BPAUTO_BUILD_DMA_SHARED_HELPERS=
-BPAUTO_BUILD_LEDS=
-BPAUTO_NEW_LEDS=
-BPAUTO_LEDS_CLASS=
-BPAUTO_LEDS_TRIGGERS=
-BPAUTO_USERSEL_BUILD_ALL=
-BPAUTO_CRYPTO_CCM=
-BPAUTO_BUILD_CRYPTO_CCM=
-BPAUTO_WANT_DEV_COREDUMP=
-BPAUTO_BUILD_WANT_DEV_COREDUMP=
+BACKPORT_BUILD_CORDIC=
+BACKPORT_CORDIC=
+BACKPORT_BUILD_AVERAGE=
+BACKPORT_AVERAGE=
+BACKPORT_MII=
+BACKPORT_BUILD_DMA_SHARED_HELPERS=
+BACKPORT_BUILD_LEDS=
+BACKPORT_NEW_LEDS=
+BACKPORT_LEDS_CLASS=
+BACKPORT_LEDS_TRIGGERS=
+BACKPORT_USERSEL_BUILD_ALL=
+BACKPORT_CRYPTO_CCM=
+BACKPORT_BUILD_CRYPTO_CCM=
+BACKPORT_WANT_DEV_COREDUMP=
+BACKPORT_BUILD_WANT_DEV_COREDUMP=
CFG80211=
NL80211_TESTMODE=
CFG80211_DEVELOPER_WARNINGS=
@@ -40,7 +39,6 @@
MAC80211_HAS_RC=
MAC80211_RC_MINSTREL=
MAC80211_RC_MINSTREL_HT=
-MAC80211_RC_MINSTREL_VHT=
MAC80211_RC_DEFAULT_MINSTREL=
MAC80211_RC_DEFAULT=
MAC80211_MESH=
@@ -53,7 +51,6 @@
MAC80211_MLME_DEBUG=
MAC80211_STA_DEBUG=
MAC80211_HT_DEBUG=
-MAC80211_OCB_DEBUG=
MAC80211_IBSS_DEBUG=
MAC80211_PS_DEBUG=
MAC80211_MPL_DEBUG=
@@ -65,8 +62,6 @@
MAC80211_TDLS_DEBUG=
MAC80211_DEBUG_COUNTERS=
BT=
-BT_BREDR=
-BT_LE=
BT_6LOWPAN=
BT_RFCOMM=
BT_RFCOMM_TTY=
@@ -125,7 +120,6 @@
ATH5K=
ATH5K_DEBUG=
ATH5K_TRACER=
-ATH5K_AHB=
ATH5K_PCI=
ATH5K_TEST_CHANNELS=
ATH9K_HW=
@@ -143,7 +137,6 @@
ATH9K_WOW=
ATH9K_RFKILL=
ATH9K_CHANNEL_CONTEXT=
-ATH9K_PCOEM=
ATH9K_HTC=
ATH9K_HTC_DEBUGFS=
CARL9170=
@@ -545,12 +538,10 @@
IR_MCEUSB=
IR_ITE_CIR=
IR_FINTEK=
-IR_MESON=
IR_NUVOTON=
IR_REDRAT3=
IR_STREAMZAP=
IR_WINBOND_CIR=
-IR_IGORPLUGUSB=
IR_IGUANA=
IR_TTUSBIR=
IR_RX51=
@@ -632,6 +623,7 @@
VIDEO_PVRUSB2_DVB=
VIDEO_PVRUSB2_DEBUGIFC=
VIDEO_HDPVR=
+VIDEO_TLG2300=
VIDEO_USBVISION=
VIDEO_STK1160_COMMON=
VIDEO_STK1160_AC97=
@@ -763,12 +755,12 @@
DVB_HOPPER=
DVB_NGENE=
DVB_DDBRIDGE=
-DVB_SMIPCIE=
V4L_PLATFORM_DRIVERS=
VIDEO_VIA_CAMERA=
VIDEO_SH_VOU=
VIDEO_VIU=
VIDEO_TIMBERDALE=
+VIDEO_VINO=
VIDEO_M32R_AR=
VIDEO_M32R_AR_M64278=
VIDEO_OMAP3=
@@ -787,7 +779,7 @@
VIDEO_TI_VPE=
VIDEO_TI_VPE_DEBUG=
V4L_TEST_DRIVERS=
-VIDEO_VIM2M=
+VIDEO_MEM2MEM_TESTDEV=
VIDEO_CAFE_CCIC=
VIDEO_MMP_CAMERA=
VIDEO_DAVINCI_VPIF_DISPLAY=
@@ -828,6 +820,11 @@
VIDEO_SAMSUNG_S5P_MIXER_DEBUG=
VIDEO_VIVID=
SMS_SDIO_DRV=
+MEDIA_PARPORT_SUPPORT=
+VIDEO_BWQCAM=
+VIDEO_CQCAM=
+VIDEO_PMS=
+VIDEO_W9966=
RADIO_ADAPTERS=
RADIO_TEA575X=
RADIO_SI470X=
@@ -917,6 +914,7 @@
VIDEO_ML86V7667=
VIDEO_SAA7110=
VIDEO_SAA711X=
+VIDEO_SAA7191=
VIDEO_TVP514X=
VIDEO_TVP5150=
VIDEO_TVP7002=
@@ -1009,7 +1007,6 @@
MEDIA_TUNER_E4000=
MEDIA_TUNER_FC2580=
MEDIA_TUNER_M88TS2022=
-MEDIA_TUNER_M88RS6000T=
MEDIA_TUNER_TUA9001=
MEDIA_TUNER_SI2157=
MEDIA_TUNER_IT913X=
@@ -1116,11 +1113,11 @@
DVB_AF9033=
DVB_DUMMY_FE=
DVB_DRX39XYJ=
-6LOWPAN=
IEEE802154=
IEEE802154_6LOWPAN=
MAC802154=
IEEE802154_DRIVERS=
+IEEE802154_FAKEHARD=
IEEE802154_FAKELB=
IEEE802154_AT86RF230=
IEEE802154_MRF24J40=
diff --git a/Kconfig b/Kconfig
index 9684574..b14a268 100644
--- a/Kconfig
+++ b/Kconfig
@@ -1,8 +1,5 @@
-mainmenu "Backports from $BACKPORTED_KERNEL_NAME $BACKPORTED_KERNEL_VERSION (backports $BACKPORTS_VERSION)"
+mainmenu "Linux Backports from $BACKPORTED_KERNEL_NAME $BACKPORTED_KERNEL_VERSION (with backports $BACKPORTS_VERSION)"
-config BACKPORT_DIR
- string
- option env="BACKPORT_DIR"
config BACKPORTS_VERSION
string
option env="BACKPORTS_VERSION"
@@ -13,12 +10,38 @@
string
option env="BACKPORTED_KERNEL_NAME"
-# Packaging hacks
-source "$BACKPORT_DIR/Kconfig.package.hacks"
-
-# Code we backport
-source "$BACKPORT_DIR/Kconfig.sources"
-
# these will be generated
-source "$BACKPORT_DIR/Kconfig.kernel"
-source "$BACKPORT_DIR/Kconfig.versions"
+source Kconfig.kernel
+source Kconfig.versions
+
+# some hacks ...
+config WIRELESS
+ def_bool y
+config NET_CORE
+ def_bool y
+config EXPERT
+ def_bool y
+
+# this has the configuration for the backport code
+source compat/Kconfig
+
+# these are copied from the kernel
+source net/wireless/Kconfig
+source net/mac80211/Kconfig
+source net/bluetooth/Kconfig
+source drivers/net/wireless/Kconfig
+source drivers/net/ethernet/Kconfig
+source drivers/net/usb/Kconfig
+
+source drivers/ssb/Kconfig
+source drivers/bcma/Kconfig
+
+source net/nfc/Kconfig
+
+source drivers/media/Kconfig
+
+source net/ieee802154/Kconfig
+source net/mac802154/Kconfig
+source drivers/net/ieee802154/Kconfig
+
+source drivers/usb/class/Kconfig
diff --git a/Kconfig.package.hacks b/Kconfig.package.hacks
deleted file mode 100644
index 6a429dd..0000000
--- a/Kconfig.package.hacks
+++ /dev/null
@@ -1,8 +0,0 @@
-# some hacks for when we use backports to generate a package
-# to build modules out of tree.
-config WIRELESS
- def_bool y
-config NET_CORE
- def_bool y
-config EXPERT
- def_bool y
diff --git a/Kconfig.sources b/Kconfig.sources
deleted file mode 100644
index 5711433..0000000
--- a/Kconfig.sources
+++ /dev/null
@@ -1,24 +0,0 @@
-# this has the configuration for the backport code
-source "$BACKPORT_DIR/compat/Kconfig"
-
-# these are copied from the kernel
-source "$BACKPORT_DIR/net/wireless/Kconfig"
-source "$BACKPORT_DIR/net/mac80211/Kconfig"
-source "$BACKPORT_DIR/net/bluetooth/Kconfig"
-source "$BACKPORT_DIR/drivers/net/wireless/Kconfig"
-source "$BACKPORT_DIR/drivers/net/ethernet/Kconfig"
-source "$BACKPORT_DIR/drivers/net/usb/Kconfig"
-
-source "$BACKPORT_DIR/drivers/ssb/Kconfig"
-source "$BACKPORT_DIR/drivers/bcma/Kconfig"
-
-source "$BACKPORT_DIR/net/nfc/Kconfig"
-
-source "$BACKPORT_DIR/drivers/media/Kconfig"
-
-source "$BACKPORT_DIR/net/6lowpan/Kconfig"
-source "$BACKPORT_DIR/net/ieee802154/Kconfig"
-source "$BACKPORT_DIR/net/mac802154/Kconfig"
-source "$BACKPORT_DIR/drivers/net/ieee802154/Kconfig"
-
-source "$BACKPORT_DIR/drivers/usb/class/Kconfig"
diff --git a/MAINTAINERS b/MAINTAINERS
index ddb9ac8..a20df9b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -618,16 +618,6 @@
F: drivers/iommu/amd_iommu*.[ch]
F: include/linux/amd-iommu.h
-AMD KFD
-M: Oded Gabbay <oded.gabbay@amd.com>
-L: dri-devel@lists.freedesktop.org
-T: git git://people.freedesktop.org/~gabbayo/linux.git
-S: Supported
-F: drivers/gpu/drm/amd/amdkfd/
-F: drivers/gpu/drm/radeon/radeon_kfd.c
-F: drivers/gpu/drm/radeon/radeon_kfd.h
-F: include/uapi/linux/kfd_ioctl.h
-
AMD MICROCODE UPDATE SUPPORT
M: Andreas Herrmann <herrmann.der.user@googlemail.com>
L: amd64-microcode@amd64.org
@@ -860,7 +850,6 @@
M: Carlo Caione <carlo@caione.org>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: drivers/media/rc/meson-ir.c
N: meson[x68]
ARM/ATMEL AT91RM9200 AND AT91SAM ARM ARCHITECTURES
@@ -872,7 +861,6 @@
W: http://www.linux4sam.org
S: Supported
F: arch/arm/mach-at91/
-F: include/soc/at91/
F: arch/arm/boot/dts/at91*.dts
F: arch/arm/boot/dts/at91*.dtsi
F: arch/arm/boot/dts/sama*.dts
@@ -930,15 +918,6 @@
S: Maintained
F: arch/arm/mach-ep93xx/micro9.c
-ARM/CORESIGHT FRAMEWORK AND DRIVERS
-M: Mathieu Poirier <mathieu.poirier@linaro.org>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Maintained
-F: drivers/coresight/*
-F: Documentation/trace/coresight.txt
-F: Documentation/devicetree/bindings/arm/coresight.txt
-F: Documentation/ABI/testing/sysfs-bus-coresight-devices-*
-
ARM/CORGI MACHINE SUPPORT
M: Richard Purdie <rpurdie@rpsys.net>
S: Maintained
@@ -1329,22 +1308,30 @@
F: drivers/*/*/*rockchip*
F: sound/soc/rockchip/
-ARM/SAMSUNG EXYNOS ARM ARCHITECTURES
-M: Kukjin Kim <kgene@kernel.org>
+ARM/SAMSUNG ARM ARCHITECTURES
+M: Ben Dooks <ben-linux@fluff.org>
+M: Kukjin Kim <kgene.kim@samsung.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+W: http://www.fluff.org/ben/linux/
S: Maintained
F: arch/arm/boot/dts/s3c*
F: arch/arm/boot/dts/exynos*
F: arch/arm/plat-samsung/
F: arch/arm/mach-s3c24*/
F: arch/arm/mach-s3c64xx/
-F: arch/arm/mach-s5p*/
-F: arch/arm/mach-exynos*/
F: drivers/*/*s3c2410*
F: drivers/*/*/*s3c2410*
F: drivers/spi/spi-s3c*
F: sound/soc/samsung/*
+
+ARM/S5P EXYNOS ARM ARCHITECTURES
+M: Kukjin Kim <kgene.kim@samsung.com>
+L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
+L: linux-samsung-soc@vger.kernel.org (moderated for non-subscribers)
+S: Maintained
+F: arch/arm/mach-s5p*/
+F: arch/arm/mach-exynos*/
N: exynos
ARM/SAMSUNG MOBILE MACHINE SUPPORT
@@ -1394,12 +1381,12 @@
F: arch/arm/configs/ape6evm_defconfig
F: arch/arm/configs/armadillo800eva_defconfig
F: arch/arm/configs/bockw_defconfig
+F: arch/arm/configs/koelsch_defconfig
F: arch/arm/configs/kzm9g_defconfig
F: arch/arm/configs/lager_defconfig
F: arch/arm/configs/mackerel_defconfig
F: arch/arm/configs/marzen_defconfig
F: arch/arm/configs/shmobile_defconfig
-F: arch/arm/include/debug/renesas-scif.S
F: arch/arm/mach-shmobile/
F: drivers/sh/
@@ -1443,7 +1430,6 @@
F: drivers/usb/dwc3/dwc3-st.c
F: drivers/usb/host/ehci-st.c
F: drivers/usb/host/ohci-st.c
-F: drivers/ata/ahci_st.c
ARM/TECHNOLOGIC SYSTEMS TS7250 MACHINE SUPPORT
M: Lennert Buytenhek <kernel@wantstofly.org>
@@ -1517,19 +1503,6 @@
F: drivers/clk/ux500/
F: include/linux/platform_data/clk-ux500.h
-ARM/VERSATILE EXPRESS PLATFORM
-M: Liviu Dudau <liviu.dudau@arm.com>
-M: Sudeep Holla <sudeep.holla@arm.com>
-M: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Maintained
-F: arch/arm/boot/dts/vexpress*
-F: arch/arm/mach-vexpress/
-F: */*/vexpress*
-F: */*/*/vexpress*
-F: drivers/clk/versatile/clk-vexpress-osc.c
-F: drivers/clocksource/versatile.c
-
ARM/VFP SUPPORT
M: Russell King <linux@arm.linux.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1570,7 +1543,6 @@
ARM/ZYNQ ARCHITECTURE
M: Michal Simek <michal.simek@xilinx.com>
-R: Sören Brinkmann <soren.brinkmann@xilinx.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
W: http://wiki.xilinx.com
T: git git://git.xilinx.com/linux-xlnx.git
@@ -1741,13 +1713,6 @@
F: drivers/dma/at_hdmac_regs.h
F: include/linux/platform_data/dma-atmel.h
-ATMEL XDMA DRIVER
-M: Ludovic Desroches <ludovic.desroches@atmel.com>
-L: linux-arm-kernel@lists.infradead.org
-L: dmaengine@vger.kernel.org
-S: Supported
-F: drivers/dma/at_xdmac.c
-
ATMEL I2C DRIVER
M: Ludovic Desroches <ludovic.desroches@atmel.com>
L: linux-i2c@vger.kernel.org
@@ -1784,13 +1749,6 @@
S: Supported
F: drivers/spi/spi-atmel.*
-ATMEL SSC DRIVER
-M: Bo Shen <voice.shen@atmel.com>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S: Supported
-F: drivers/misc/atmel-ssc.c
-F: include/linux/atmel-ssc.h
-
ATMEL Timer Counter (TC) AND CLOCKSOURCE DRIVERS
M: Nicolas Ferre <nicolas.ferre@atmel.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -1820,11 +1778,10 @@
F: drivers/scsi/esas2r
AUDIT SUBSYSTEM
-M: Paul Moore <paul@paul-moore.com>
M: Eric Paris <eparis@redhat.com>
-L: linux-audit@redhat.com (moderated for non-subscribers)
+L: linux-audit@redhat.com (subscribers-only)
W: http://people.redhat.com/sgrubb/audit/
-T: git git://git.infradead.org/users/pcmoore/audit
+T: git git://git.infradead.org/users/eparis/audit.git
S: Maintained
F: include/linux/audit.h
F: include/uapi/linux/audit.h
@@ -1863,7 +1820,7 @@
F: net/ax25/
AZ6007 DVB DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
@@ -1897,6 +1854,7 @@
BACKLIGHT CLASS/SUBSYSTEM
M: Jingoo Han <jg1.han@samsung.com>
+M: Bryan Wu <cooloney@gmail.com>
M: Lee Jones <lee.jones@linaro.org>
S: Maintained
F: drivers/video/backlight/
@@ -1925,6 +1883,13 @@
S: Maintained:
F: drivers/md/bcache/
+BECEEM BCS200/BCS220-3/BCSM250 WIMAX SUPPORT
+M: Kevin McKinney <klmckinney1@gmail.com>
+M: Matthias Beyer <mail@beyermatthias.de>
+L: devel@driverdev.osuosl.org
+S: Maintained
+F: drivers/staging/bcm*
+
BEFS FILE SYSTEM
S: Orphan
F: Documentation/filesystems/befs.txt
@@ -2099,20 +2064,11 @@
BROADCOM BCM2835 ARM ARCHITECTURE
M: Stephen Warren <swarren@wwwdotorg.org>
-M: Lee Jones <lee@kernel.org>
L: linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/rpi/linux-rpi.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/swarren/linux-rpi.git
S: Maintained
N: bcm2835
-BROADCOM BCM33XX MIPS ARCHITECTURE
-M: Kevin Cernekee <cernekee@gmail.com>
-L: linux-mips@linux-mips.org
-S: Maintained
-F: arch/mips/bcm3384/*
-F: arch/mips/include/asm/mach-bcm3384/*
-F: arch/mips/kernel/*bmips*
-
BROADCOM BCM5301X ARM ARCHITECTURE
M: Hauke Mehrtens <hauke@hauke-m.de>
L: linux-arm-kernel@lists.infradead.org
@@ -2129,34 +2085,13 @@
F: arch/arm/mach-bcm/bcm63xx.c
F: arch/arm/include/debug/bcm63xx.S
-BROADCOM BCM63XX/BCM33XX UDC DRIVER
-M: Kevin Cernekee <cernekee@gmail.com>
-L: linux-usb@vger.kernel.org
-S: Maintained
-F: drivers/usb/gadget/udc/bcm63xx_udc.*
-
BROADCOM BCM7XXX ARM ARCHITECTURE
M: Marc Carino <marc.ceeeee@gmail.com>
M: Brian Norris <computersforpeace@gmail.com>
-M: Gregory Fong <gregory.0xf0@gmail.com>
-M: Florian Fainelli <f.fainelli@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
F: arch/arm/mach-bcm/*brcmstb*
F: arch/arm/boot/dts/bcm7*.dts*
-F: drivers/bus/brcmstb_gisb.c
-
-BROADCOM BMIPS MIPS ARCHITECTURE
-M: Kevin Cernekee <cernekee@gmail.com>
-M: Florian Fainelli <f.fainelli@gmail.com>
-L: linux-mips@linux-mips.org
-S: Maintained
-F: arch/mips/bmips/*
-F: arch/mips/include/asm/mach-bmips/*
-F: arch/mips/kernel/*bmips*
-F: arch/mips/boot/dts/bcm*.dts*
-F: drivers/irqchip/irq-bcm7*
-F: drivers/irqchip/irq-brcmstb*
BROADCOM TG3 GIGABIT ETHERNET DRIVER
M: Prashant Sreedharan <prashant@broadcom.com>
@@ -2187,20 +2122,6 @@
S: Supported
F: drivers/scsi/bnx2i/
-BROADCOM CYGNUS/IPROC ARM ARCHITECTURE
-M: Ray Jui <rjui@broadcom.com>
-M: Scott Branden <sbranden@broadcom.com>
-L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-L: bcm-kernel-feedback-list@broadcom.com
-T: git git://git.github.com/brcm/linux.git
-S: Maintained
-N: iproc
-N: cygnus
-N: bcm9113*
-N: bcm9583*
-N: bcm583*
-N: bcm113*
-
BROADCOM KONA GPIO DRIVER
M: Ray Jui <rjui@broadcom.com>
L: bcm-kernel-feedback-list@broadcom.com
@@ -2268,7 +2189,7 @@
F: fs/btrfs/
BTTV VIDEO4LINUX DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
@@ -2378,14 +2299,6 @@
F: security/commoncap.c
F: kernel/capability.c
-CC2520 IEEE-802.15.4 RADIO DRIVER
-M: Varka Bhadram <varkabhadram@gmail.com>
-L: linux-wpan@vger.kernel.org
-S: Maintained
-F: drivers/net/ieee802154/cc2520.c
-F: include/linux/spi/cc2520.h
-F: Documentation/devicetree/bindings/net/ieee802154/cc2520.txt
-
CELL BROADBAND ENGINE ARCHITECTURE
M: Arnd Bergmann <arnd@arndb.de>
L: linuxppc-dev@lists.ozlabs.org
@@ -2567,18 +2480,10 @@
F: include/linux/coda*.h
F: include/uapi/linux/coda*.h
-CODA V4L2 MEM2MEM DRIVER
-M: Philipp Zabel <p.zabel@pengutronix.de>
-L: linux-media@vger.kernel.org
-S: Maintained
-F: Documentation/devicetree/bindings/media/coda.txt
-F: drivers/media/platform/coda/
-
COMMON CLK FRAMEWORK
M: Mike Turquette <mturquette@linaro.org>
-M: Stephen Boyd <sboyd@codeaurora.org>
L: linux-kernel@vger.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/clk/linux.git
+T: git git://git.linaro.org/people/mturquette/linux.git
S: Maintained
F: drivers/clk/
X: drivers/clk/clkdev.c
@@ -2590,7 +2495,8 @@
L: linux-cifs@vger.kernel.org
L: samba-technical@lists.samba.org (moderated for non-subscribers)
W: http://linux-cifs.samba.org/
-T: git git://git.samba.org/sfrench/cifs-2.6.git
+Q: http://patchwork.ozlabs.org/project/linux-cifs-client/list/
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/sfrench/cifs-2.6.git
S: Supported
F: Documentation/filesystems/cifs/
F: fs/cifs/
@@ -2667,7 +2573,7 @@
L: linux-mm@kvack.org
S: Maintained
F: mm/memcontrol.c
-F: mm/swap_cgroup.c
+F: mm/page_cgroup.c
CORETEMP HARDWARE MONITORING DRIVER
M: Fenghua Yu <fenghua.yu@intel.com>
@@ -2717,16 +2623,6 @@
S: Maintained
F: drivers/cpuidle/cpuidle-big_little.c
-CPUIDLE DRIVER - ARM EXYNOS
-M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
-M: Daniel Lezcano <daniel.lezcano@linaro.org>
-M: Kukjin Kim <kgene@kernel.org>
-L: linux-pm@vger.kernel.org
-L: linux-samsung-soc@vger.kernel.org
-S: Supported
-F: drivers/cpuidle/cpuidle-exynos.c
-F: arch/arm/mach-exynos/pm.c
-
CPUIDLE DRIVERS
M: Rafael J. Wysocki <rjw@rjwysocki.net>
M: Daniel Lezcano <daniel.lezcano@linaro.org>
@@ -2794,7 +2690,7 @@
CX18 VIDEO4LINUX DRIVER
M: Andy Walls <awalls@md.metrocast.net>
-L: ivtv-devel@ivtvdriver.org (subscribers-only)
+L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
W: http://linuxtv.org
@@ -2814,7 +2710,7 @@
F: include/media/cx2341x*
CX88 VIDEO4LINUX DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
@@ -2839,13 +2735,6 @@
S: Supported
F: drivers/net/ethernet/chelsio/cxgb3/
-CXGB3 ISCSI DRIVER (CXGB3I)
-M: Karen Xie <kxie@chelsio.com>
-L: linux-scsi@vger.kernel.org
-W: http://www.chelsio.com
-S: Supported
-F: drivers/scsi/cxgbi/cxgb3i
-
CXGB3 IWARP RNIC DRIVER (IW_CXGB3)
M: Steve Wise <swise@chelsio.com>
L: linux-rdma@vger.kernel.org
@@ -2860,13 +2749,6 @@
S: Supported
F: drivers/net/ethernet/chelsio/cxgb4/
-CXGB4 ISCSI DRIVER (CXGB4I)
-M: Karen Xie <kxie@chelsio.com>
-L: linux-scsi@vger.kernel.org
-W: http://www.chelsio.com
-S: Supported
-F: drivers/scsi/cxgbi/cxgb4i
-
CXGB4 IWARP RNIC DRIVER (IW_CXGB4)
M: Steve Wise <swise@chelsio.com>
L: linux-rdma@vger.kernel.org
@@ -2957,10 +2839,11 @@
F: drivers/net/ethernet/dec/tulip/dmfe.c
DC390/AM53C974 SCSI driver
-M: Hannes Reinecke <hare@suse.de>
-L: linux-scsi@vger.kernel.org
+M: Kurt Garloff <garloff@suse.de>
+W: http://www.garloff.de/kurt/linux/dc390/
+M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
S: Maintained
-F: drivers/scsi/am53c974.c
+F: drivers/scsi/tmscsim.*
DC395x SCSI driver
M: Oliver Neukum <oliver@neukum.org>
@@ -3183,8 +3066,7 @@
S: Maintained
F: drivers/dma/
F: include/linux/dma*
-F: Documentation/dmaengine/
-T: git git://git.infradead.org/users/vkoul/slave-dma.git
+T: git git://git.infradead.org/users/vkoul/slave-dma.git (slave-dma)
DME1737 HARDWARE MONITOR DRIVER
M: Juerg Haefliger <juergh@gmail.com>
@@ -3301,13 +3183,6 @@
F: include/drm/exynos*
F: include/uapi/drm/exynos*
-DRM DRIVERS FOR FREESCALE IMX
-M: Philipp Zabel <p.zabel@pengutronix.de>
-L: dri-devel@lists.freedesktop.org
-S: Maintained
-F: drivers/gpu/drm/imx/
-F: Documentation/devicetree/bindings/drm/imx/
-
DRM DRIVERS FOR NVIDIA TEGRA
M: Thierry Reding <thierry.reding@gmail.com>
M: Terje Bergström <tbergstrom@nvidia.com>
@@ -3504,7 +3379,7 @@
EDAC-CORE
M: Doug Thompson <dougthompson@xmission.com>
M: Borislav Petkov <bp@alien8.de>
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Supported
@@ -3553,7 +3428,7 @@
F: drivers/edac/e7xxx_edac.c
EDAC-GHES
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
@@ -3581,21 +3456,21 @@
F: drivers/edac/i5000_edac.c
EDAC-I5400
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i5400_edac.c
EDAC-I7300
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/i7300_edac.c
EDAC-I7CORE
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
@@ -3638,7 +3513,7 @@
F: drivers/edac/r82600_edac.c
EDAC-SBRIDGE
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
@@ -3698,7 +3573,7 @@
F: drivers/net/ethernet/ibm/ehea/
EM28XX VIDEO4LINUX DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
@@ -4066,7 +3941,7 @@
FREESCALE SOC SOUND DRIVERS
M: Timur Tabi <timur@tabi.org>
M: Nicolin Chen <nicoleotsuka@gmail.com>
-M: Xiubo Li <Xiubo.Lee@gmail.com>
+M: Xiubo Li <Li.Xiubo@freescale.com>
L: alsa-devel@alsa-project.org (moderated for non-subscribers)
L: linuxppc-dev@lists.ozlabs.org
S: Maintained
@@ -4256,12 +4131,6 @@
S: Maintained
F: drivers/media/usb/go7007/
-GOODIX TOUCHSCREEN
-M: Bastien Nocera <hadess@hadess.net>
-L: linux-input@vger.kernel.org
-S: Maintained
-F: drivers/input/touchscreen/goodix.c
-
GPIO SUBSYSTEM
M: Linus Walleij <linus.walleij@linaro.org>
M: Alexandre Courbot <gnurou@gmail.com>
@@ -4436,10 +4305,8 @@
F: drivers/block/cpqarray.*
HEWLETT-PACKARD SMART ARRAY RAID DRIVER (hpsa)
-M: Don Brace <don.brace@pmcs.com>
+M: "Stephen M. Cameron" <scameron@beardog.cce.hp.com>
L: iss_storagedev@hp.com
-L: storagedev@pmcs.com
-L: linux-scsi@vger.kernel.org
S: Supported
F: Documentation/scsi/hpsa.txt
F: drivers/scsi/hpsa*.[ch]
@@ -4447,10 +4314,8 @@
F: include/uapi/linux/cciss*.h
HEWLETT-PACKARD SMART CISS RAID DRIVER (cciss)
-M: Don Brace <don.brace@pmcs.com>
+M: Mike Miller <mike.miller@hp.com>
L: iss_storagedev@hp.com
-L: storagedev@pmcs.com
-L: linux-scsi@vger.kernel.org
S: Supported
F: Documentation/blockdev/cciss.txt
F: drivers/block/cciss*
@@ -4683,7 +4548,6 @@
Q: https://patchwork.ozlabs.org/project/linux-i2c/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux.git
S: Maintained
-F: Documentation/devicetree/bindings/i2c/
F: Documentation/i2c/
F: drivers/i2c/
F: include/linux/i2c.h
@@ -4737,7 +4601,7 @@
F: drivers/crypto/nx/
IBM Power 842 compression accelerator
-M: Dan Streetman <ddstreet@us.ibm.com>
+M: Nathan Fontenot <nfont@linux.vnet.ibm.com>
S: Supported
F: drivers/crypto/nx/nx-842.c
F: include/linux/nx842.h
@@ -4822,21 +4686,8 @@
F: net/ieee802154/
F: net/mac802154/
F: drivers/net/ieee802154/
-F: include/linux/nl802154.h
-F: include/linux/ieee802154.h
-F: include/net/nl802154.h
-F: include/net/mac802154.h
-F: include/net/af_ieee802154.h
-F: include/net/cfg802154.h
-F: include/net/ieee802154_netdev.h
F: Documentation/networking/ieee802154.txt
-IGORPLUG-USB IR RECEIVER
-M: Sean Young <sean@mess.org>
-L: linux-media@vger.kernel.org
-S: Maintained
-F: drivers/media/rc/igorplugusb.c
-
IGUANAWORKS USB IR TRANSCEIVER
M: Sean Young <sean@mess.org>
L: linux-media@vger.kernel.org
@@ -4852,7 +4703,6 @@
S: Maintained
F: drivers/iio/
F: drivers/staging/iio/
-F: include/linux/iio/
IKANOS/ADI EAGLE ADSL USB DRIVER
M: Matthieu Castet <castet.matthieu@free.fr>
@@ -4894,11 +4744,6 @@
S: Supported
F: security/integrity/ima/
-IMGTEC IR DECODER DRIVER
-M: James Hogan <james.hogan@imgtec.com>
-S: Maintained
-F: drivers/media/rc/img-ir/
-
IMS TWINTURBO FRAMEBUFFER DRIVER
L: linux-fbdev@vger.kernel.org
S: Orphan
@@ -4964,12 +4809,6 @@
S: Supported
F: drivers/idle/intel_idle.c
-INTEL PSTATE DRIVER
-M: Kristen Carlson Accardi <kristen@linux.intel.com>
-L: linux-pm@vger.kernel.org
-S: Supported
-F: drivers/cpufreq/intel_pstate.c
-
INTEL FRAMEBUFFER DRIVER (excluding 810 and 815)
M: Maik Broemme <mbroemme@plusserver.de>
L: linux-fbdev@vger.kernel.org
@@ -5319,7 +5158,7 @@
IVTV VIDEO4LINUX DRIVER
M: Andy Walls <awalls@md.metrocast.net>
-L: ivtv-devel@ivtvdriver.org (subscribers-only)
+L: ivtv-devel@ivtvdriver.org (moderated for non-subscribers)
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
W: http://www.ivtvdriver.org
@@ -5502,6 +5341,15 @@
F: arch/powerpc/include/asm/kvm*
F: arch/powerpc/kvm/
+KERNEL VIRTUAL MACHINE For Itanium (KVM/IA64)
+M: Xiantao Zhang <xiantao.zhang@intel.com>
+L: kvm-ia64@vger.kernel.org
+W: http://kvm.qumranet.com
+S: Supported
+F: Documentation/ia64/kvm.txt
+F: arch/ia64/include/asm/kvm*
+F: arch/ia64/kvm/
+
KERNEL VIRTUAL MACHINE for s390 (KVM/s390)
M: Christian Borntraeger <borntraeger@de.ibm.com>
M: Cornelia Huck <cornelia.huck@de.ibm.com>
@@ -5986,14 +5834,6 @@
F: drivers/net/macvlan.c
F: include/linux/if_macvlan.h
-MAILBOX API
-M: Jassi Brar <jassisinghbrar@gmail.com>
-L: linux-kernel@vger.kernel.org
-S: Maintained
-F: drivers/mailbox/
-F: include/linux/mailbox_client.h
-F: include/linux/mailbox_controller.h
-
MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
M: Michael Kerrisk <mtk.manpages@gmail.com>
W: http://www.kernel.org/doc/man-pages
@@ -6005,11 +5845,6 @@
S: Maintained
F: drivers/gpu/drm/armada/
-MARVELL 88E6352 DSA support
-M: Guenter Roeck <linux@roeck-us.net>
-S: Maintained
-F: drivers/net/dsa/mv88e6352.c
-
MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
M: Mirko Lindner <mlindner@marvell.com>
M: Stephen Hemminger <stephen@networkplumber.org>
@@ -6091,7 +5926,7 @@
F: drivers/media/radio/radio-maxiradio*
MEDIA INPUT INFRASTRUCTURE (V4L/DVB)
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
P: LinuxTV.org Project
L: linux-media@vger.kernel.org
W: http://linuxtv.org
@@ -6120,13 +5955,10 @@
S: Odd Fixes
F: drivers/media/parport/pms*
-MEGARAID SCSI/SAS DRIVERS
-M: Kashyap Desai <kashyap.desai@avagotech.com>
-M: Sumit Saxena <sumit.saxena@avagotech.com>
-M: Uday Lingala <uday.lingala@avagotech.com>
-L: megaraidlinux.pdl@avagotech.com
+MEGARAID SCSI DRIVERS
+M: Neela Syam Kolli <megaraidlinux@lsi.com>
L: linux-scsi@vger.kernel.org
-W: http://www.lsi.com
+W: http://megaraid.lsilogic.com
S: Maintained
F: Documentation/scsi/megaraid.txt
F: drivers/scsi/megaraid.*
@@ -6249,28 +6081,6 @@
F: include/linux/mlx5/
F: drivers/infiniband/hw/mlx5/
-MN88472 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
-L: linux-media@vger.kernel.org
-W: http://linuxtv.org/
-W: http://palosaari.fi/linux/
-Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
-S: Maintained
-F: drivers/staging/media/mn88472/
-F: drivers/media/dvb-frontends/mn88472.h
-
-MN88473 MEDIA DRIVER
-M: Antti Palosaari <crope@iki.fi>
-L: linux-media@vger.kernel.org
-W: http://linuxtv.org/
-W: http://palosaari.fi/linux/
-Q: http://patchwork.linuxtv.org/project/linux-media/list/
-T: git git://linuxtv.org/anttip/media_tree.git
-S: Maintained
-F: drivers/staging/media/mn88473/
-F: drivers/media/dvb-frontends/mn88473.h
-
MODULE SUPPORT
M: Rusty Russell <rusty@rustcorp.com.au>
S: Maintained
@@ -6459,6 +6269,7 @@
F: drivers/scsi/g_NCR5380_mmio.c
F: drivers/scsi/mac_scsi.*
F: drivers/scsi/pas16.*
+F: drivers/scsi/sun3_NCR5380.c
F: drivers/scsi/sun3_scsi.*
F: drivers/scsi/sun3_scsi_vme.c
F: drivers/scsi/t128.*
@@ -6617,8 +6428,19 @@
S: Maintained
NETWORKING [WIRELESS]
+M: "John W. Linville" <linville@tuxdriver.com>
L: linux-wireless@vger.kernel.org
Q: http://patchwork.kernel.org/project/linux-wireless/list/
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git
+S: Maintained
+F: net/mac80211/
+F: net/rfkill/
+F: net/wireless/
+F: include/net/ieee80211*
+F: include/linux/wireless.h
+F: include/uapi/linux/wireless.h
+F: include/net/iw_handler.h
+F: drivers/net/wireless/
NETWORKING DRIVERS
L: netdev@vger.kernel.org
@@ -6639,14 +6461,6 @@
F: include/uapi/linux/if_*
F: include/uapi/linux/netdevice.h
-NETWORKING DRIVERS (WIRELESS)
-M: Kalle Valo <kvalo@codeaurora.org>
-L: linux-wireless@vger.kernel.org
-Q: http://patchwork.kernel.org/project/linux-wireless/list/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers.git/
-S: Maintained
-F: drivers/net/wireless/
-
NETXEN (1/10) GbE SUPPORT
M: Manish Chopra <manish.chopra@qlogic.com>
M: Sony Chacko <sony.chacko@qlogic.com>
@@ -6711,13 +6525,6 @@
F: Documentation/scsi/NinjaSCSI.txt
F: drivers/scsi/nsp32*
-NIOS2 ARCHITECTURE
-M: Ley Foon Tan <lftan@altera.com>
-L: nios2-dev@lists.rocketboards.org (moderated for non-subscribers)
-T: git git://git.rocketboards.org/linux-socfpga.git
-S: Maintained
-F: arch/nios2/
-
NTB DRIVER
M: Jon Mason <jdmason@kudzu.us>
M: Dave Jiang <dave.jiang@intel.com>
@@ -6758,12 +6565,6 @@
F: drivers/gpu/drm/i2c/tda998x_drv.c
F: include/drm/i2c/tda998x.h
-NXP TFA9879 DRIVER
-M: Peter Rosin <peda@axentia.se>
-L: alsa-devel@alsa-project.org (moderated for non-subscribers)
-S: Maintained
-F: sound/soc/codecs/tfa9879*
-
OMAP SUPPORT
M: Tony Lindgren <tony@atomide.com>
L: linux-omap@vger.kernel.org
@@ -6774,23 +6575,6 @@
S: Maintained
F: arch/arm/*omap*/
F: drivers/i2c/busses/i2c-omap.c
-F: drivers/irqchip/irq-omap-intc.c
-F: drivers/mfd/*omap*.c
-F: drivers/mfd/menelaus.c
-F: drivers/mfd/palmas.c
-F: drivers/mfd/tps65217.c
-F: drivers/mfd/tps65218.c
-F: drivers/mfd/tps65910.c
-F: drivers/mfd/twl-core.[ch]
-F: drivers/mfd/twl4030*.c
-F: drivers/mfd/twl6030*.c
-F: drivers/mfd/twl6040*.c
-F: drivers/regulator/palmas-regulator*.c
-F: drivers/regulator/pbias-regulator.c
-F: drivers/regulator/tps65217-regulator.c
-F: drivers/regulator/tps65218-regulator.c
-F: drivers/regulator/tps65910-regulator.c
-F: drivers/regulator/twl-regulator.c
F: include/linux/i2c-omap.h
OMAP DEVICE TREE SUPPORT
@@ -6801,9 +6585,6 @@
S: Maintained
F: arch/arm/boot/dts/*omap*
F: arch/arm/boot/dts/*am3*
-F: arch/arm/boot/dts/*am4*
-F: arch/arm/boot/dts/*am5*
-F: arch/arm/boot/dts/*dra7*
OMAP CLOCK FRAMEWORK SUPPORT
M: Paul Walmsley <paul@pwsan.com>
@@ -6833,14 +6614,6 @@
S: Maintained
F: sound/soc/omap/
-OMAP GENERAL PURPOSE MEMORY CONTROLLER SUPPORT
-M: Roger Quadros <rogerq@ti.com>
-M: Tony Lindgren <tony@atomide.com>
-L: linux-omap@vger.kernel.org
-S: Maintained
-F: drivers/memory/omap-gpmc.c
-F: arch/arm/mach-omap2/*gpmc*
-
OMAP FRAMEBUFFER SUPPORT
M: Tomi Valkeinen <tomi.valkeinen@ti.com>
L: linux-fbdev@vger.kernel.org
@@ -7049,7 +6822,7 @@
F: drivers/net/wireless/orinoco/
OSD LIBRARY and FILESYSTEM
-M: Boaz Harrosh <ooo@electrozaur.com>
+M: Boaz Harrosh <bharrosh@panasas.com>
M: Benny Halevy <bhalevy@primarydata.com>
L: osd-dev@open-osd.org
W: http://open-osd.org
@@ -7059,14 +6832,6 @@
F: include/scsi/osd_*
F: fs/exofs/
-OVERLAY FILESYSTEM
-M: Miklos Szeredi <miklos@szeredi.hu>
-L: linux-unionfs@vger.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs.git
-S: Supported
-F: fs/overlayfs/
-F: Documentation/filesystems/overlayfs.txt
-
P54 WIRELESS DRIVER
M: Christian Lamparter <chunkeey@googlemail.com>
L: linux-wireless@vger.kernel.org
@@ -7218,16 +6983,6 @@
F: Documentation/devicetree/bindings/pci/xgene-pci.txt
F: drivers/pci/host/pci-xgene.c
-PCI DRIVER FOR FREESCALE LAYERSCAPE
-M: Minghuan Lian <minghuan.Lian@freescale.com>
-M: Mingkai Hu <mingkai.hu@freescale.com>
-M: Roy Zang <tie-fei.zang@freescale.com>
-L: linuxppc-dev@lists.ozlabs.org
-L: linux-pci@vger.kernel.org
-L: linux-arm-kernel@lists.infradead.org
-S: Maintained
-F: drivers/pci/host/*layerscape*
-
PCI DRIVER FOR IMX6
M: Richard Zhu <r65037@freescale.com>
M: Lucas Stach <l.stach@pengutronix.de>
@@ -7398,7 +7153,6 @@
PIN CONTROL SUBSYSTEM
M: Linus Walleij <linus.walleij@linaro.org>
-L: linux-gpio@vger.kernel.org
S: Maintained
F: drivers/pinctrl/
F: include/linux/pinctrl/
@@ -7407,13 +7161,7 @@
M: Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
S: Maintained
-F: drivers/pinctrl/pinctrl-at91.*
-
-PIN CONTROLLER - INTEL
-M: Mika Westerberg <mika.westerberg@linux.intel.com>
-M: Heikki Krogerus <heikki.krogerus@linux.intel.com>
-S: Maintained
-F: drivers/pinctrl/intel/
+F: drivers/pinctrl/pinctrl-at91.c
PIN CONTROLLER - RENESAS
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -8032,13 +7780,6 @@
F: include/linux/hid-roccat*
F: Documentation/ABI/*/sysfs-driver-hid-roccat*
-ROCKER DRIVER
-M: Jiri Pirko <jiri@resnulli.us>
-M: Scott Feldman <sfeldma@gmail.com>
-L: netdev@vger.kernel.org
-S: Supported
-F: drivers/net/ethernet/rocker/
-
ROCKETPORT DRIVER
P: Comtrol Corp.
W: http://www.comtrol.com
@@ -8046,12 +7787,6 @@
F: Documentation/serial/rocket.txt
F: drivers/tty/rocket*
-ROCKETPORT EXPRESS/INFINITY DRIVER
-M: Kevin Cernekee <cernekee@gmail.com>
-L: linux-serial@vger.kernel.org
-S: Odd Fixes
-F: drivers/tty/serial/rp2.*
-
ROSE NETWORK LAYER
M: Ralf Baechle <ralf@linux-mips.org>
L: linux-hams@vger.kernel.org
@@ -8092,10 +7827,11 @@
F: drivers/media/dvb-frontends/rtl2832_sdr*
RTL8180 WIRELESS DRIVER
+M: "John W. Linville" <linville@tuxdriver.com>
L: linux-wireless@vger.kernel.org
W: http://wireless.kernel.org/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-testing.git
-S: Orphan
+S: Maintained
F: drivers/net/wireless/rtl818x/rtl8180/
RTL8187 WIRELESS DRIVER
@@ -8212,7 +7948,7 @@
F: drivers/media/i2c/saa6588*
SAA7134 VIDEO4LINUX DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
@@ -8670,7 +8406,7 @@
F: drivers/media/radio/si4713/radio-usb-si4713.c
SIANO DVB DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
@@ -8680,14 +8416,6 @@
F: drivers/media/usb/siano/
F: drivers/media/mmc/siano/
-SIMPLEFB FB DRIVER
-M: Hans de Goede <hdegoede@redhat.com>
-L: linux-fbdev@vger.kernel.org
-S: Maintained
-F: Documentation/devicetree/bindings/video/simple-framebuffer.txt
-F: drivers/video/fbdev/simplefb.c
-F: include/linux/platform_data/simplefb.h
-
SH_VEU V4L2 MEM2MEM DRIVER
L: linux-media@vger.kernel.org
S: Orphan
@@ -8729,6 +8457,7 @@
TI DAVINCI MACHINE SUPPORT
M: Sekhar Nori <nsekhar@ti.com>
M: Kevin Hilman <khilman@deeprootsystems.com>
+L: davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
T: git git://gitorious.org/linux-davinci/linux-davinci.git
Q: http://patchwork.kernel.org/project/linux-davinci/list/
S: Supported
@@ -8738,6 +8467,7 @@
TI DAVINCI SERIES MEDIA DRIVER
M: Lad, Prabhakar <prabhakar.csengg@gmail.com>
L: linux-media@vger.kernel.org
+L: davinci-linux-open-source@linux.davincidsp.com (moderated for non-subscribers)
W: http://linuxtv.org/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
T: git git://linuxtv.org/mhadli/v4l-dvb-davinci_devices.git
@@ -8889,9 +8619,7 @@
F: drivers/leds/leds-net48xx.c
SOFTLOGIC 6x10 MPEG CODEC
-M: Bluecherry Maintainers <maintainers@bluecherrydvr.com>
-M: Andrey Utkin <andrey.utkin@corp.bluecherry.net>
-M: Andrey Utkin <andrey.krieger.utkin@gmail.com>
+M: Ismael Luceno <ismael.luceno@corp.bluecherry.net>
L: linux-media@vger.kernel.org
S: Supported
F: drivers/media/pci/solo6x10/
@@ -9248,13 +8976,6 @@
F: arch/*/kernel/pci-swiotlb.c
F: include/linux/swiotlb.h
-SWITCHDEV
-M: Jiri Pirko <jiri@resnulli.us>
-L: netdev@vger.kernel.org
-S: Supported
-F: net/switchdev/
-F: include/net/switchdev.h
-
SYNOPSYS ARC ARCHITECTURE
M: Vineet Gupta <vgupta@synopsys.com>
S: Supported
@@ -9372,7 +9093,7 @@
F: drivers/media/i2c/tda9840*
TEA5761 TUNER DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
@@ -9380,7 +9101,7 @@
F: drivers/media/tuners/tea5761.*
TEA5767 TUNER DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
@@ -9511,7 +9232,6 @@
S: Supported
F: drivers/thermal/
F: include/linux/thermal.h
-F: include/uapi/linux/thermal.h
F: include/linux/cpu_cooling.h
F: Documentation/devicetree/bindings/thermal/
@@ -9616,7 +9336,7 @@
F: net/tipc/
TILE ARCHITECTURE
-M: Chris Metcalf <cmetcalf@ezchip.com>
+M: Chris Metcalf <cmetcalf@tilera.com>
W: http://www.tilera.com/scm/
S: Supported
F: arch/tile/
@@ -9693,7 +9413,7 @@
F: mm/shmem.c
TM6000 VIDEO4LINUX DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
@@ -9864,6 +9584,7 @@
UNIVERSAL FLASH STORAGE HOST CONTROLLER DRIVER
M: Vinayak Holikatti <vinholikatti@gmail.com>
+M: Santosh Y <santoshsy@gmail.com>
L: linux-scsi@vger.kernel.org
S: Supported
F: Documentation/scsi/ufs.txt
@@ -9957,6 +9678,11 @@
F: Documentation/hid/hiddev.txt
F: drivers/hid/usbhid/
+USB/IP DRIVERS
+L: linux-usb@vger.kernel.org
+S: Orphan
+F: drivers/staging/usbip/
+
USB ISP116X DRIVER
M: Olav Kongas <ok@artecdesign.ee>
L: linux-usb@vger.kernel.org
@@ -10244,13 +9970,13 @@
S: Maintained
F: drivers/net/ethernet/via/via-velocity.*
-VIVID VIRTUAL VIDEO DRIVER
+VIVI VIRTUAL VIDEO DRIVER
M: Hans Verkuil <hverkuil@xs4all.nl>
L: linux-media@vger.kernel.org
T: git git://linuxtv.org/media_tree.git
W: http://linuxtv.org
S: Maintained
-F: drivers/media/platform/vivid/*
+F: drivers/media/platform/vivi*
VLAN (802.1Q)
M: Patrick McHardy <kaber@trash.net>
@@ -10513,15 +10239,8 @@
S: Maintained
F: arch/x86/kernel/cpu/mcheck/*
-X86 VDSO
-M: Andy Lutomirski <luto@amacapital.net>
-L: linux-kernel@vger.kernel.org
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/vdso
-S: Maintained
-F: arch/x86/vdso/
-
XC2028/3028 TUNER DRIVER
-M: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
+M: Mauro Carvalho Chehab <m.chehab@samsung.com>
L: linux-media@vger.kernel.org
W: http://linuxtv.org
T: git git://linuxtv.org/media_tree.git
diff --git a/Makefile b/Makefile
index c21b813..ea3982b 100644
--- a/Makefile
+++ b/Makefile
@@ -6,7 +6,7 @@
MAKEFLAGS += --no-print-directory
SHELL := /bin/bash
-BACKPORT_DIR := $(shell pwd)
+BACKPORT_PWD := $(shell pwd)
KMODDIR ?= updates
ifneq ($(origin KLIB), undefined)
@@ -20,7 +20,7 @@
KERNEL_MAKEFILE := $(KLIB_BUILD)/Makefile
CONFIG_MD5 := $(shell md5sum $(KERNEL_CONFIG) 2>/dev/null | sed 's/\s.*//')
-export KLIB KLIB_BUILD BACKPORT_DIR KMODDIR KMODPATH_ARG
+export KLIB KLIB_BUILD BACKPORT_PWD KMODDIR KMODPATH_ARG
# disable built-in rules for this file
.SUFFIXES:
@@ -93,7 +93,7 @@
print=0 ;\
for v in $$kvers ; do \
if [ "$$print" = "1" ] ; then \
- echo config KERNEL_$$(echo $$v | tr . _) ;\
+ echo config BACKPORT_KERNEL_$$(echo $$v | tr . _) ;\
echo " def_bool y" ;\
fi ;\
if [ "$$v" = "$$kver" ] ; then print=1 ; fi ;\
@@ -159,5 +159,5 @@
@echo ""
@echo "Execute "make" or "make all" to build all targets marked with [*]"
else
-include $(BACKPORT_DIR)/Makefile.kernel
+include $(BACKPORT_PWD)/Makefile.kernel
endif
diff --git a/Makefile.build b/Makefile.build
index a848b37..d209041 100644
--- a/Makefile.build
+++ b/Makefile.build
@@ -3,8 +3,8 @@
.PHONY: modules
modules:
- @$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_DIR) modules
+ @$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_PWD) modules
.PHONY: clean
clean:
- @$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_DIR) clean
+ @$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_PWD) clean
diff --git a/Makefile.kernel b/Makefile.kernel
index 42333ad..dcb2ba7 100644
--- a/Makefile.kernel
+++ b/Makefile.kernel
@@ -1,4 +1,3 @@
-ifeq ($(CONFIG_BACKPORT_INTEGRATE),)
# Since 2.6.21, try-run is available, but cc-disable-warning
# was only added later, so we add it here ourselves:
backport-cc-disable-warning = $(call try-run,\
@@ -11,25 +10,13 @@
-I$(M)/include/uapi \
-include $(M)/backport-include/backport/backport.h \
$(call backport-cc-disable-warning, unused-but-set-variable) \
- -DCPTCFG_VERSION=\"$(BACKPORTS_VERSION)\" \
- -DCPTCFG_KERNEL_VERSION=\"$(BACKPORTED_KERNEL_VERSION)\" \
- -DCPTCFG_KERNEL_NAME=\"$(BACKPORTED_KERNEL_NAME)\" \
+ -DBACKPORTS_VERSION=\"$(BACKPORTS_VERSION)\" \
+ -DBACKPORTED_KERNEL_VERSION=\"$(BACKPORTED_KERNEL_VERSION)\" \
+ -DBACKPORTED_KERNEL_NAME=\"$(BACKPORTED_KERNEL_NAME)\" \
$(BACKPORTS_GIT_TRACKER_DEF) \
$(CFLAGS)
export backport_srctree = $(M)
-else
-export BACKPORT_DIR = backports/
-export backport_srctree = $(BACKPORT_DIR)
-NOSTDINC_FLAGS := \
- -I$(BACKPORT_DIR)/backport-include/ \
- -I$(BACKPORT_DIR)/backport-include/uapi \
- -I$(BACKPORT_DIR)/include/ \
- -I$(BACKPORT_DIR)/include/uapi \
- -include $(BACKPORT_DIR)/backport-include/backport/backport.h \
- $(CFLAGS)
-endif
-
obj-y += compat/
@@ -46,7 +33,6 @@
obj-$(CPTCFG_NFC) += drivers/nfc/
obj-$(CPTCFG_MEDIA_SUPPORT) += drivers/media/
-obj-$(CPTCFG_6LOWPAN) += net/6lowpan/
obj-$(CPTCFG_IEEE802154) += net/ieee802154/
obj-$(CPTCFG_BT) += net/ieee802154/
obj-$(CPTCFG_MAC802154) += net/mac802154/
diff --git a/Makefile.real b/Makefile.real
index a0f4916..f60d5ca 100644
--- a/Makefile.real
+++ b/Makefile.real
@@ -89,7 +89,7 @@
.PHONY: install
install: modules
- @$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_DIR) \
+ @$(MAKE) -C $(KLIB_BUILD) M=$(BACKPORT_PWD) \
INSTALL_MOD_DIR=$(KMODDIR) $(KMODPATH_ARG) \
modules_install
@./scripts/blacklist.sh $(KLIB)/ $(KLIB)/$(KMODDIR)
diff --git a/backport-include/asm-generic/barrier.h b/backport-include/asm-generic/barrier.h
deleted file mode 100644
index 9169449..0000000
--- a/backport-include/asm-generic/barrier.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __BACKPORT_ASM_GENERIC_BARRIER_H
-#define __BACKPORT_ASM_GENERIC_BARRIER_H
-#include_next <asm-generic/barrier.h>
-
-#ifndef dma_rmb
-#define dma_rmb() rmb()
-#endif
-
-#endif /* __BACKPORT_ASM_GENERIC_BARRIER_H */
diff --git a/backport-include/asm/barrier.h b/backport-include/asm/barrier.h
deleted file mode 100644
index b04bd33..0000000
--- a/backport-include/asm/barrier.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __BACKPORT_ASM_GENERIC_BARRIER_H
-#define __BACKPORT_ASM_GENERIC_BARRIER_H
-#include_next <asm/barrier.h>
-
-#ifndef dma_rmb
-#define dma_rmb() rmb()
-#endif
-
-#endif /* __BACKPORT_ASM_GENERIC_BARRIER_H */
diff --git a/backport-include/asm/dma-mapping.h b/backport-include/asm/dma-mapping.h
index b73b7da..844fe3b 100644
--- a/backport-include/asm/dma-mapping.h
+++ b/backport-include/asm/dma-mapping.h
@@ -3,12 +3,12 @@
#include_next <asm/dma-mapping.h>
#include <linux/version.h>
-#if defined(CPTCFG_BPAUTO_BUILD_DMA_SHARED_HELPERS)
+#if defined(CPTCFG_BACKPORT_BUILD_DMA_SHARED_HELPERS)
#define dma_common_get_sgtable LINUX_BACKPORT(dma_common_get_sgtable)
int
dma_common_get_sgtable(struct device *dev, struct sg_table *sgt,
void *cpu_addr, dma_addr_t dma_addr, size_t size);
-#endif /* defined(CPTCFG_BPAUTO_BUILD_DMA_SHARED_HELPERS) */
+#endif /* defined(CPTCFG_BACKPORT_BUILD_DMA_SHARED_HELPERS) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
diff --git a/backport-include/backport/backport.h b/backport-include/backport/backport.h
index d1d3b10..7cf21aa 100644
--- a/backport-include/backport/backport.h
+++ b/backport-include/backport/backport.h
@@ -1,16 +1,11 @@
#ifndef __BACKPORT_H
#define __BACKPORT_H
-#include <generated/autoconf.h>
-#ifndef CONFIG_BACKPORT_INTEGRATE
#include <backport/autoconf.h>
-#endif
#include <linux/kconfig.h>
#ifndef __ASSEMBLY__
#define LINUX_BACKPORT(__sym) backport_ ##__sym
-#ifndef CONFIG_BACKPORT_INTEGRATE
#include <backport/checks.h>
#endif
-#endif
#endif /* __BACKPORT_H */
diff --git a/backport-include/backport/leds-disabled.h b/backport-include/backport/leds-disabled.h
index 156d7fa..501f2a0 100644
--- a/backport-include/backport/leds-disabled.h
+++ b/backport-include/backport/leds-disabled.h
@@ -8,7 +8,7 @@
* allows compilation.
*/
-#ifdef CPTCFG_BPAUTO_BUILD_LEDS
+#ifdef CPTCFG_BACKPORT_BUILD_LEDS
#include <linux/list.h>
#include <linux/spinlock.h>
#include <linux/rwsem.h>
diff --git a/backport-include/linux/bitops.h b/backport-include/linux/bitops.h
deleted file mode 100644
index b0e9283..0000000
--- a/backport-include/linux/bitops.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __BACKPORT_BITOPS_H
-#define __BACKPORT_BITOPS_H
-#include_next <linux/bitops.h>
-#include <linux/version.h>
-#include <generated/utsrelease.h>
-
-#ifndef GENMASK
-
-/*
- * Create a contiguous bitmask starting at bit position @l and ending at
- * position @h. For example
- * GENMASK_ULL(39, 21) gives us the 64bit vector 0x000000ffffe00000.
- */
-#define GENMASK(h, l) (((U32_C(1) << ((h) - (l) + 1)) - 1) << (l))
-#define GENMASK_ULL(h, l) (((U64_C(1) << ((h) - (l) + 1)) - 1) << (l))
-
-#endif
-
-#endif /* __BACKPORT_BITOPS_H */
diff --git a/backport-include/linux/debugfs.h b/backport-include/linux/debugfs.h
deleted file mode 100644
index 77b2e64..0000000
--- a/backport-include/linux/debugfs.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __BACKPORT_DEBUGFS_H_
-#define __BACKPORT_DEBUGFS_H_
-#include_next <linux/debugfs.h>
-#include <linux/version.h>
-#include <generated/utsrelease.h>
-
-#if defined(CONFIG_DEBUG_FS)
-struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
- struct dentry *parent,
- int (*read_fn)(struct seq_file *s,
- void *data));
-#else
-static inline struct dentry *debugfs_create_devm_seqfile(struct device *dev,
- const char *name,
- struct dentry *parent,
- int (*read_fn)(struct seq_file *s,
- void *data))
-{
- return ERR_PTR(-ENODEV);
-}
-#endif /* CONFIG_DEBUG_FS */
-
-#endif /* __BACKPORT_DEBUGFS_H_ */
diff --git a/backport-include/linux/device.h b/backport-include/linux/device.h
index 29dc077..41f06c3 100644
--- a/backport-include/linux/device.h
+++ b/backport-include/linux/device.h
@@ -177,20 +177,4 @@
}
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)
-#define devm_kmemdup LINUX_BACKPORT(devm_kmemdup)
-static inline void *devm_kmemdup(struct device *dev, const void *src,
- size_t len, gfp_t gfp)
-{
- void *p;
-
- p = devm_kmalloc(dev, len, gfp);
- if (p)
- memcpy(p, src, len);
-
- return p;
-}
-#endif
-
-
#endif /* __BACKPORT_DEVICE_H */
diff --git a/backport-include/linux/dma-buf.h b/backport-include/linux/dma-buf.h
index 48c2ebf..13a225e 100644
--- a/backport-include/linux/dma-buf.h
+++ b/backport-include/linux/dma-buf.h
@@ -4,9 +4,6 @@
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
#include_next <linux/dma-buf.h>
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0) */
-#include <linux/dma-direction.h>
-#include <linux/dma-attrs.h>
-#include <linux/dma-mapping.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
#define dma_buf_export(priv, ops, size, flags, resv) \
diff --git a/backport-include/linux/etherdevice.h b/backport-include/linux/etherdevice.h
index 34dbf65..70decd2 100644
--- a/backport-include/linux/etherdevice.h
+++ b/backport-include/linux/etherdevice.h
@@ -178,19 +178,4 @@
int eth_get_headlen(unsigned char *data, unsigned int max_len);
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,18,0) */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#define eth_skb_pad LINUX_BACKPORT(eth_skb_pad)
-/**
- * eth_skb_pad - Pad buffer to mininum number of octets for Ethernet frame
- * @skb: Buffer to pad
- *
- * An Ethernet frame should have a minimum size of 60 bytes. This function
- * takes short frames and pads them with zeros up to the 60 byte limit.
- */
-static inline int eth_skb_pad(struct sk_buff *skb)
-{
- return skb_put_padto(skb, ETH_ZLEN);
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
#endif /* _BACKPORT_LINUX_ETHERDEVICE_H */
diff --git a/backport-include/linux/list.h b/backport-include/linux/list.h
index 3fbc10b..9042830 100644
--- a/backport-include/linux/list.h
+++ b/backport-include/linux/list.h
@@ -17,9 +17,7 @@
#undef hlist_entry_safe
#define hlist_entry_safe(ptr, type, member) \
- ({ typeof(ptr) ____ptr = (ptr); \
- ____ptr ? hlist_entry(____ptr, type, member) : NULL; \
- })
+ (ptr) ? hlist_entry(ptr, type, member) : NULL
#define hlist_for_each_entry4(tpos, pos, head, member) \
for (pos = (head)->first; \
@@ -75,17 +73,4 @@
list_entry((pos)->member.next, typeof(*(pos)), member)
#endif /* list_next_entry */
-#ifndef list_last_entry
-/**
- * list_last_entry - get the last element from a list
- * @ptr: the list head to take the element from.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- *
- * Note, that list is expected to be not empty.
- */
-#define list_last_entry(ptr, type, member) \
- list_entry((ptr)->prev, type, member)
-#endif
-
#endif /* __BACKPORT_LIST_H */
diff --git a/backport-include/linux/module.h b/backport-include/linux/module.h
index 8870abb..82c96bd 100644
--- a/backport-include/linux/module.h
+++ b/backport-include/linux/module.h
@@ -20,12 +20,11 @@
#define BACKPORT_MOD_VERSIONS MODULE_VERSION(BACKPORTS_GIT_TRACKED);
#else
#define BACKPORT_MOD_VERSIONS \
- MODULE_VERSION("backported from " CPTCFG_KERNEL_NAME \
- " (" CPTCFG_KERNEL_VERSION ")" \
- " using backports " CPTCFG_VERSION);
+ MODULE_VERSION("backported from " BACKPORTED_KERNEL_NAME \
+ " (" BACKPORTED_KERNEL_VERSION ")" \
+ " using backports " BACKPORTS_VERSION);
#endif
-#ifdef MODULE
#undef module_init
#define module_init(initfn) \
static int __init __init_backport(void) \
@@ -59,7 +58,6 @@
rcu_barrier(); \
} \
void cleanup_module(void) __attribute__((alias("__exit_compat")));
-#endif
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
#undef param_check_bool
diff --git a/backport-include/linux/netdevice.h b/backport-include/linux/netdevice.h
index 961450a..8826771 100644
--- a/backport-include/linux/netdevice.h
+++ b/backport-include/linux/netdevice.h
@@ -176,62 +176,4 @@
count)
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,17,0) */
-/*
- * This backports this commit from upstream:
- * commit 87757a917b0b3c0787e0563c679762152be81312
- * net: force a list_del() in unregister_netdevice_many()
- */
-#if (!(LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,45) && \
- LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)) && \
- !(LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,23) && \
- LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)) && \
- !(LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,9) && \
- LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0)) && \
- !(LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,2) && \
- LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)) && \
- (LINUX_VERSION_CODE < KERNEL_VERSION(3,16,0)))
-static inline void backport_unregister_netdevice_many(struct list_head *head)
-{
- unregister_netdevice_many(head);
-
- if (!(head->next == LIST_POISON1 && head->prev == LIST_POISON2))
- list_del(head);
-}
-#define unregister_netdevice_many LINUX_BACKPORT(unregister_netdevice_many)
-#endif
-
-/*
- * Complicated way of saying: We only backport netdev_rss_key stuff on kernels
- * that either already have net_get_random_once() (>= 3.13) or where we've been
- * brave enough to backport it due to static keys, refer to backports commit
- * 8cb8816d for details on difficulty to backport that further down.
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
-#define __BACKPORT_NETDEV_RSS_KEY_FILL 1
-#else
-#ifdef __BACKPORT_NET_GET_RANDOM_ONCE
-#define __BACKPORT_NETDEV_RSS_KEY_FILL 1
-#endif
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0) */
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
-#ifdef __BACKPORT_NETDEV_RSS_KEY_FILL
-/* RSS keys are 40 or 52 bytes long */
-#define NETDEV_RSS_KEY_LEN 52
-#define netdev_rss_key LINUX_BACKPORT(netdev_rss_key)
-extern u8 netdev_rss_key[NETDEV_RSS_KEY_LEN];
-#define netdev_rss_key_fill LINUX_BACKPORT(netdev_rss_key_fill)
-void netdev_rss_key_fill(void *buffer, size_t len);
-#endif /* __BACKPORT_NETDEV_RSS_KEY_FILL */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#define napi_alloc_skb LINUX_BACKPORT(napi_alloc_skb)
-static inline struct sk_buff *napi_alloc_skb(struct napi_struct *napi,
- unsigned int length)
-{
- return netdev_alloc_skb_ip_align(napi->dev, length);
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
#endif /* __BACKPORT_NETDEVICE_H */
diff --git a/backport-include/linux/of.h b/backport-include/linux/of.h
index b289bcb..f2a8ab4 100644
--- a/backport-include/linux/of.h
+++ b/backport-include/linux/of.h
@@ -29,7 +29,6 @@
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0)
-#define of_property_read_u8_array LINUX_BACKPORT(of_property_read_u8_array)
#ifdef CONFIG_OF
extern int of_property_read_u8_array(const struct device_node *np,
const char *propname, u8 *out_values, size_t sz);
@@ -40,31 +39,7 @@
return -ENOSYS;
}
#endif /* CONFIG_OF */
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,8,0) */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
-#define of_property_read_u32_array LINUX_BACKPORT(of_property_read_u32_array)
-#ifdef CONFIG_OF
-extern int of_property_read_u32_array(const struct device_node *np,
- const char *propname,
- u32 *out_values,
- size_t sz);
-#else
-static inline int of_property_read_u32_array(const struct device_node *np,
- const char *propname,
- u32 *out_values, size_t sz)
-{
- return -ENOSYS;
-}
-#endif /* CONFIG_OF */
-#define of_property_read_u32 LINUX_BACKPORT(of_property_read_u32)
-static inline int of_property_read_u32(const struct device_node *np,
- const char *propname,
- u32 *out_value)
-{
- return of_property_read_u32_array(np, propname, out_value, 1);
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) */
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
#define of_property_read_u32_index LINUX_BACKPORT(of_property_read_u32_index)
@@ -139,22 +114,4 @@
#endif /* CONFIG_OF */
#endif /* of_match_ptr */
-#ifndef for_each_compatible_node
-#define for_each_compatible_node(dn, type, compatible) \
- for (dn = of_find_compatible_node(NULL, type, compatible); dn; \
- dn = of_find_compatible_node(dn, type, compatible))
-#endif /* for_each_compatible_node */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
-#ifndef CONFIG_OF
-static inline struct device_node *of_find_compatible_node(
- struct device_node *from,
- const char *type,
- const char *compat)
-{
- return NULL;
-}
-#endif
-#endif
-
#endif /* _COMPAT_LINUX_OF_H */
diff --git a/backport-include/linux/pci.h b/backport-include/linux/pci.h
index f168bde..3dd2c7e 100644
--- a/backport-include/linux/pci.h
+++ b/backport-include/linux/pci.h
@@ -159,9 +159,4 @@
#endif
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0)
-#define pci_device_is_present LINUX_BACKPORT(pci_device_is_present)
-bool pci_device_is_present(struct pci_dev *pdev);
-#endif
-
#endif /* _BACKPORT_LINUX_PCI_H */
diff --git a/backport-include/linux/pci_regs.h b/backport-include/linux/pci_regs.h
new file mode 100644
index 0000000..b52c4a5
--- /dev/null
+++ b/backport-include/linux/pci_regs.h
@@ -0,0 +1,136 @@
+#ifndef __BACKPORT_UAPI_PCI_REGS_H
+#define __BACKPORT_UAPI_PCI_REGS_H
+#include_next <linux/pci_regs.h>
+
+#ifndef PCI_EXP_LNKCTL_ASPM_L0S
+#define PCI_EXP_LNKCTL_ASPM_L0S 0x01 /* L0s Enable */
+#endif
+
+#ifndef PCI_EXP_LNKCTL_ASPM_L1
+#define PCI_EXP_LNKCTL_ASPM_L1 0x02 /* L1 Enable */
+#endif
+
+/* This backports:
+ *
+ * commit 130f1b8f35f14d27c43da755f3c9226318c17f57
+ * Author: Bjorn Helgaas <bhelgaas@google.com>
+ * Date: Wed Dec 26 10:39:23 2012 -0700
+ *
+ * PCI: Add PCIe Link Capability link speed and width names
+ */
+#ifndef PCI_EXP_LNKCAP_SLS_2_5GB
+#define PCI_EXP_LNKCAP_SLS_2_5GB 0x1 /* LNKCAP2 SLS Vector bit 0 (2.5GT/s) */
+#endif
+
+#ifndef PCI_EXP_LNKCAP_SLS_5_0GB
+#define PCI_EXP_LNKCAP_SLS_5_0GB 0x2 /* LNKCAP2 SLS Vector bit 1 (5.0GT/s) */
+#endif
+
+#ifndef PCI_EXP_LNKSTA2
+#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
+#endif
+
+/**
+ * Backports
+ *
+ * commit cdcac9cd7741af2c2b9255cbf060f772596907bb
+ * Author: Dave Airlie <airlied@redhat.com>
+ * Date: Wed Jun 27 08:35:52 2012 +0100
+ *
+ * pci_regs: define LNKSTA2 pcie cap + bits.
+ *
+ * We need these for detecting the max link speed for drm drivers.
+ *
+ * Acked-by: Bjorn Helgaas <bhelgass@google.com>
+ * Signed-off-by: Dave Airlie <airlied@redhat.com>
+ */
+#ifndef PCI_EXP_LNKCAP2
+#define PCI_EXP_LNKCAP2 44 /* Link Capability 2 */
+#endif
+
+#ifndef PCI_EXP_LNKCAP2_SLS_2_5GB
+#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x01 /* Current Link Speed 2.5GT/s */
+#endif
+
+#ifndef PCI_EXP_LNKCAP2_SLS_5_0GB
+#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x02 /* Current Link Speed 5.0GT/s */
+#endif
+
+#ifndef PCI_EXP_LNKCAP2_SLS_8_0GB
+#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x04 /* Current Link Speed 8.0GT/s */
+#endif
+
+#ifndef PCI_EXP_LNKCAP2_CROSSLINK
+#define PCI_EXP_LNKCAP2_CROSSLINK 0x100 /* Crosslink supported */
+#endif
+
+/*
+ * PCI_EXP_TYPE_RC_EC was added via 1b6b8ce2 on v2.6.30-rc4~20 :
+ *
+ * mcgrof@frijol ~/linux-next (git::master)$ git describe --contains 1b6b8ce2
+ * v2.6.30-rc4~20^2
+ *
+ * but the fix for its definition was merged on v3.3-rc1~101^2~67
+ *
+ * mcgrof@frijol ~/linux-next (git::master)$ git describe --contains 1830ea91
+ * v3.3-rc1~101^2~67
+ *
+ * while we can assume it got merged and backported on v3.2.28 (which it did
+ * see c1c3cd9) we cannot assume every kernel has it fixed so lets just undef
+ * it here and redefine it.
+ */
+#undef PCI_EXP_TYPE_RC_EC
+#define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */
+
+#ifndef PCI_MSIX_ENTRY_CTRL_MASKBIT
+#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1
+#endif
+
+/* MSI-X entry's format */
+#ifndef PCI_MSIX_ENTRY_SIZE
+#define PCI_MSIX_ENTRY_SIZE 16
+#define PCI_MSIX_ENTRY_LOWER_ADDR 0
+#define PCI_MSIX_ENTRY_UPPER_ADDR 4
+#define PCI_MSIX_ENTRY_DATA 8
+#define PCI_MSIX_ENTRY_VECTOR_CTRL 12
+#endif
+
+#ifndef PCI_EXP_LNKCTL2
+#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
+#endif
+
+#ifndef PCI_EXP_SLTCTL2
+#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */
+#endif
+
+#ifndef PCI_EXP_LNKCTL_ES
+#define PCI_EXP_LNKCTL_ES 0x0080 /* Extended Synch */
+#endif
+
+#ifndef PCI_EXP_SLTSTA_PDS
+#define PCI_EXP_SLTSTA_PDS 0x0040 /* Presence Detect State */
+#endif
+
+#ifndef PCI_EXP_DEVCAP2
+#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
+#define PCI_EXP_DEVCAP2_ARI 0x20 /* Alternative Routing-ID */
+#endif
+
+#ifndef PCI_EXP_DEVCTL2
+#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
+#define PCI_EXP_DEVCTL2_ARI 0x20 /* Alternative Routing-ID */
+#endif
+
+#ifndef PCI_PM_CAP_PME_SHIFT
+#define PCI_PM_CAP_PME_SHIFT 11
+#endif
+
+#ifndef PCI_SRIOV_VF_DID
+#define PCI_SRIOV_VF_DID 0x1a /* VF Device ID */
+#endif
+
+#ifndef PCI_SRIOV_CTRL_VFE
+#define PCI_SRIOV_CTRL_VFE 0x01 /* VF Enable */
+#endif
+
+#endif /* __BACKPORT_UAPI_PCI_REGS_H */
diff --git a/backport-include/linux/rculist.h b/backport-include/linux/rculist.h
index 74009ab..eb3bcfe 100644
--- a/backport-include/linux/rculist.h
+++ b/backport-include/linux/rculist.h
@@ -34,24 +34,4 @@
container_of(rcu_dereference(ptr), type, member)
#endif
-#ifndef list_first_or_null_rcu
-/**
- * list_first_or_null_rcu - get the first element from a list
- * @ptr: the list head to take the element from.
- * @type: the type of the struct this is embedded in.
- * @member: the name of the list_struct within the struct.
- *
- * Note that if the list is empty, it returns NULL.
- *
- * This primitive may safely run concurrently with the _rcu list-mutation
- * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
- */
-#define list_first_or_null_rcu(ptr, type, member) \
-({ \
- struct list_head *__ptr = (ptr); \
- struct list_head *__next = ACCESS_ONCE(__ptr->next); \
- likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \
-})
-#endif /* list_first_or_null_rcu */
-
#endif /* __BACKPORT_RCULIST_H */
diff --git a/backport-include/linux/skbuff.h b/backport-include/linux/skbuff.h
index 687297c..5a1725d 100644
--- a/backport-include/linux/skbuff.h
+++ b/backport-include/linux/skbuff.h
@@ -96,6 +96,52 @@
}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0)
+/**
+ * __skb_alloc_pages - allocate pages for ps-rx on a skb and preserve pfmemalloc data
+ * @gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX
+ * @skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used
+ * @order: size of the allocation
+ *
+ * Allocate a new page.
+ *
+ * %NULL is returned if there is no free memory.
+*/
+static inline struct page *__skb_alloc_pages(gfp_t gfp_mask,
+ struct sk_buff *skb,
+ unsigned int order)
+{
+ struct page *page;
+
+ gfp_mask |= __GFP_COLD;
+#if 0
+ if (!(gfp_mask & __GFP_NOMEMALLOC))
+ gfp_mask |= __GFP_MEMALLOC;
+#endif
+ page = alloc_pages_node(NUMA_NO_NODE, gfp_mask, order);
+#if 0
+ if (skb && page && page->pfmemalloc)
+ skb->pfmemalloc = true;
+#endif
+ return page;
+}
+
+/**
+ * __skb_alloc_page - allocate a page for ps-rx for a given skb and preserve pfmemalloc data
+ * @gfp_mask: alloc_pages_node mask. Set __GFP_NOMEMALLOC if not for network packet RX
+ * @skb: skb to set pfmemalloc on if __GFP_MEMALLOC is used
+ *
+ * Allocate a new page.
+ *
+ * %NULL is returned if there is no free memory.
+ */
+static inline struct page *__skb_alloc_page(gfp_t gfp_mask,
+ struct sk_buff *skb)
+{
+ return __skb_alloc_pages(gfp_mask, skb, 0);
+}
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) */
+
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0)
#ifndef NETDEV_FRAG_PAGE_MAX_ORDER
#define NETDEV_FRAG_PAGE_MAX_ORDER get_order(32768)
@@ -118,6 +164,129 @@
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0)
+#define skb_frag_size_set LINUX_BACKPORT(skb_frag_size_set)
+static inline void skb_frag_size_set(skb_frag_t *frag, unsigned int size)
+{
+ frag->size = size;
+}
+
+#define skb_frag_size_add LINUX_BACKPORT(skb_frag_size_add)
+static inline void skb_frag_size_add(skb_frag_t *frag, int delta)
+{
+ frag->size += delta;
+}
+
+#define __skb_fill_page_desc LINUX_BACKPORT(__skb_fill_page_desc)
+/**
+ * __skb_fill_page_desc - initialise a paged fragment in an skb
+ * @skb: buffer containing fragment to be initialised
+ * @i: paged fragment index to initialise
+ * @page: the page to use for this fragment
+ * @off: the offset to the data with @page
+ * @size: the length of the data
+ *
+ * Initialises the @i'th fragment of @skb to point to &size bytes at
+ * offset @off within @page.
+ *
+ * Does not take any additional reference on the fragment.
+ */
+static inline void __skb_fill_page_desc(struct sk_buff *skb, int i,
+ struct page *page, int off, int size)
+{
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
+
+ /*
+ * Propagate page->pfmemalloc to the skb if we can. The problem is
+ * that not all callers have unique ownership of the page. If
+ * pfmemalloc is set, we check the mapping as a mapping implies
+ * page->index is set (index and pfmemalloc share space).
+ * If it's a valid mapping, we cannot use page->pfmemalloc but we
+ * do not lose pfmemalloc information as the pages would not be
+ * allocated using __GFP_MEMALLOC.
+ */
+ frag->page = page;
+ frag->page_offset = off;
+ skb_frag_size_set(frag, size);
+
+#if 0 /* we can't backport this for older kernels */
+ page = compound_head(page);
+ if (page->pfmemalloc && !page->mapping)
+ skb->pfmemalloc = true;
+#endif
+}
+
+#define skb_fill_page_desc LINUX_BACKPORT(skb_fill_page_desc)
+/**
+ * skb_fill_page_desc - initialise a paged fragment in an skb
+ * @skb: buffer containing fragment to be initialised
+ * @i: paged fragment index to initialise
+ * @page: the page to use for this fragment
+ * @off: the offset to the data with @page
+ * @size: the length of the data
+ *
+ * As per __skb_fill_page_desc() -- initialises the @i'th fragment of
+ * @skb to point to @size bytes at offset @off within @page. In
+ * addition updates @skb such that @i is the last fragment.
+ *
+ * Does not take any additional reference on the fragment.
+ */
+static inline void skb_fill_page_desc(struct sk_buff *skb, int i,
+ struct page *page, int off, int size)
+{
+ __skb_fill_page_desc(skb, i, page, off, size);
+ skb_shinfo(skb)->nr_frags = i + 1;
+}
+
+#define __skb_frag_ref LINUX_BACKPORT(__skb_frag_ref)
+/**
+ * __skb_frag_ref - take an addition reference on kb_frag_page paged fragment.
+ * @frag: the paged fragment
+ *
+ * Takes an additional reference on the paged fragment @frag.
+ */
+static inline void __skb_frag_ref(skb_frag_t *frag)
+{
+ get_page(skb_frag_page(frag));
+}
+
+#define skb_frag_ref LINUX_BACKPORT(skb_frag_ref)
+/**
+ * skb_frag_ref - take an addition reference on a paged fragment of an skb.
+ * @skb: the buffer
+ * @f: the fragment offset.
+ *
+ * Takes an additional reference on the @f'th paged fragment of @skb.
+ */
+static inline void skb_frag_ref(struct sk_buff *skb, int f)
+{
+ __skb_frag_ref(&skb_shinfo(skb)->frags[f]);
+}
+
+#define __skb_frag_unref LINUX_BACKPORT(__skb_frag_unref)
+/**
+ * __skb_frag_unref - release a reference on a paged fragment.
+ * @frag: the paged fragment
+ *
+ * Releases a reference on the paged fragment @frag.
+ */
+static inline void __skb_frag_unref(skb_frag_t *frag)
+{
+ put_page(skb_frag_page(frag));
+}
+
+#define skb_frag_unref LINUX_BACKPORT(skb_frag_unref)
+/**
+ * skb_frag_unref - release a reference on a paged fragment of an skb.
+ * @skb: the buffer
+ * @f: the fragment offset
+ *
+ * Releases a reference on the @f'th paged fragment of @skb.
+ */
+static inline void skb_frag_unref(struct sk_buff *skb, int f)
+{
+ __skb_frag_unref(&skb_shinfo(skb)->frags[f]);
+}
+
#define skb_frag_address_safe LINUX_BACKPORT(skb_frag_address_safe)
/**
* skb_frag_address_safe - gets the address of the data contained in a paged fragment
@@ -134,6 +303,34 @@
return ptr + frag->page_offset;
}
+
+#define __skb_frag_set_page LINUX_BACKPORT(__skb_frag_set_page)
+/**
+ * __skb_frag_set_page - sets the page contained in a paged fragment
+ * @frag: the paged fragment
+ * @page: the page to set
+ *
+ * Sets the fragment @frag to contain @page.
+ */
+static inline void __skb_frag_set_page(skb_frag_t *frag, struct page *page)
+{
+ frag->page = page;
+}
+
+#define skb_frag_set_page LINUX_BACKPORT(skb_frag_set_page)
+/**
+ * skb_frag_set_page - sets the page contained in a paged fragment of an skb
+ * @skb: the buffer
+ * @f: the fragment offset
+ * @page: the page to set
+ *
+ * Sets the @f'th fragment of @skb to contain @page.
+ */
+static inline void skb_frag_set_page(struct sk_buff *skb, int f,
+ struct page *page)
+{
+ __skb_frag_set_page(&skb_shinfo(skb)->frags[f], page);
+}
#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) && \
@@ -199,100 +396,4 @@
struct sk_buff *skb_clone_sk(struct sk_buff *skb);
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-/**
- * __dev_alloc_pages - allocate page for network Rx
- * @gfp_mask: allocation priority. Set __GFP_NOMEMALLOC if not for network Rx
- * @order: size of the allocation
- *
- * Allocate a new page.
- *
- * %NULL is returned if there is no free memory.
-*/
-#define __dev_alloc_pages LINUX_BACKPORT(__dev_alloc_pages)
-static inline struct page *__dev_alloc_pages(gfp_t gfp_mask,
- unsigned int order)
-{
- /* This piece of code contains several assumptions.
- * 1. This is for device Rx, therefor a cold page is preferred.
- * 2. The expectation is the user wants a compound page.
- * 3. If requesting a order 0 page it will not be compound
- * due to the check to see if order has a value in prep_new_page
- * 4. __GFP_MEMALLOC is ignored if __GFP_NOMEMALLOC is set due to
- * code in gfp_to_alloc_flags that should be enforcing this.
- */
- gfp_mask |= __GFP_COLD | __GFP_COMP;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- gfp_mask |= __GFP_MEMALLOC;
-#endif
-
- return alloc_pages_node(NUMA_NO_NODE, gfp_mask, order);
-}
-
-#define dev_alloc_pages LINUX_BACKPORT(dev_alloc_pages)
-static inline struct page *dev_alloc_pages(unsigned int order)
-{
- return __dev_alloc_pages(GFP_ATOMIC, order);
-}
-
-/**
- * __dev_alloc_page - allocate a page for network Rx
- * @gfp_mask: allocation priority. Set __GFP_NOMEMALLOC if not for network Rx
- *
- * Allocate a new page.
- *
- * %NULL is returned if there is no free memory.
- */
-#define __dev_alloc_page LINUX_BACKPORT(__dev_alloc_page)
-static inline struct page *__dev_alloc_page(gfp_t gfp_mask)
-{
- return __dev_alloc_pages(gfp_mask, 0);
-}
-
-#define dev_alloc_page LINUX_BACKPORT(dev_alloc_page)
-static inline struct page *dev_alloc_page(void)
-{
- return __dev_alloc_page(GFP_ATOMIC);
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#define skb_copy_datagram_msg LINUX_BACKPORT(skb_copy_datagram_msg)
-static inline int skb_copy_datagram_msg(const struct sk_buff *from, int offset,
- struct msghdr *msg, int size)
-{
- return skb_copy_datagram_iovec(from, offset, msg->msg_iov, size);
-}
-
-#define memcpy_from_msg LINUX_BACKPORT(memcpy_from_msg)
-static inline int memcpy_from_msg(void *data, struct msghdr *msg, int len)
-{
- return memcpy_fromiovec(data, msg->msg_iov, len);
-}
-
-/**
- * skb_put_padto - increase size and pad an skbuff up to a minimal size
- * @skb: buffer to pad
- * @len: minimal length
- *
- * Pads up a buffer to ensure the trailing bytes exist and are
- * blanked. If the buffer already contains sufficient data it
- * is untouched. Otherwise it is extended. Returns zero on
- * success. The skb is freed on error.
- */
-#define skb_put_padto LINUX_BACKPORT(skb_put_padto)
-static inline int skb_put_padto(struct sk_buff *skb, unsigned int len)
-{
- unsigned int size = skb->len;
-
- if (unlikely(size < len)) {
- len -= size;
- if (skb_pad(skb, len))
- return -ENOMEM;
- __skb_put(skb, len);
- }
- return 0;
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
#endif /* __BACKPORT_SKBUFF_H */
diff --git a/backport-include/linux/wait.h b/backport-include/linux/wait.h
index 4057ff1..dfb111d 100644
--- a/backport-include/linux/wait.h
+++ b/backport-include/linux/wait.h
@@ -23,13 +23,4 @@
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-#define WQ_FLAG_WOKEN 0x02
-
-#define wait_woken LINUX_BACKPORT(wait_woken)
-long wait_woken(wait_queue_t *wait, unsigned mode, long timeout);
-#define wait_woken LINUX_BACKPORT(wait_woken)
-int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key);
-#endif
-
#endif /* __BACKPORT_LINUX_WAIT_H */
diff --git a/backport-include/linux/workqueue.h b/backport-include/linux/workqueue.h
index 078ed59..ec5c230 100644
--- a/backport-include/linux/workqueue.h
+++ b/backport-include/linux/workqueue.h
@@ -60,8 +60,4 @@
#define system_freezable_power_efficient_wq system_freezable_wq
#endif
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0)
-#define drain_workqueue(wq) flush_workqueue(wq)
-#endif
-
#endif /* __BACKPORT_LINUX_WORKQUEUE_H */
diff --git a/backport-include/net/genetlink.h b/backport-include/net/genetlink.h
index 0535b0f..fc7eff4 100644
--- a/backport-include/net/genetlink.h
+++ b/backport-include/net/genetlink.h
@@ -1,7 +1,6 @@
#ifndef __BACKPORT_NET_GENETLINK_H
#define __BACKPORT_NET_GENETLINK_H
#include_next <net/genetlink.h>
-#include <linux/version.h>
/* this is for patches we apply */
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
@@ -86,10 +85,6 @@
#define genl_unregister_family backport_genl_unregister_family
int genl_unregister_family(struct genl_family *family);
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0)
-extern void genl_notify(struct sk_buff *skb, struct net *net, u32 pid,
- u32 group, struct nlmsghdr *nlh, gfp_t flags);
-#endif
#define genl_notify(_fam, _skb, _net, _portid, _group, _nlh, _flags) \
genl_notify(_skb, _net, _portid, (_fam)->mcgrps[_group].id, \
_nlh, _flags)
diff --git a/backport-include/net/ip6_fib.h b/backport-include/net/ip6_fib.h
deleted file mode 100644
index 8c5d8ff..0000000
--- a/backport-include/net/ip6_fib.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __BACKPORT_NET_IP6_ROUTE_H
-#define __BACKPORT_NET_IP6_ROUTE_H
-#include_next <net/ip6_fib.h>
-#include <net/ip6_route.h>
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
-#define rt6_nexthop LINUX_BACKPORT(rt6_nexthop)
-static inline struct in6_addr *rt6_nexthop(struct rt6_info *rt)
-{
- return &rt->rt6i_gateway;
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) */
-
-#endif /* __BACKPORT_NET_IP6_ROUTE_H */
diff --git a/backport-include/sound/pcm.h b/backport-include/sound/pcm.h
deleted file mode 100644
index 469e871..0000000
--- a/backport-include/sound/pcm.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __BACKPORT_SOUND_PCM_H
-#define __BACKPORT_SOUND_PCM_H
-#include_next <sound/pcm.h>
-#include <linux/version.h>
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
-/**
- * snd_pcm_stop_xrun - stop the running streams as XRUN
- * @substream: the PCM substream instance
- *
- * This stops the given running substream (and all linked substreams) as XRUN.
- * Unlike snd_pcm_stop(), this function takes the substream lock by itself.
- *
- * Return: Zero if successful, or a negative error code.
- */
-static inline int snd_pcm_stop_xrun(struct snd_pcm_substream *substream)
-{
- unsigned long flags;
- int ret = 0;
-
- snd_pcm_stream_lock_irqsave(substream, flags);
- if (snd_pcm_running(substream))
- ret = snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
- snd_pcm_stream_unlock_irqrestore(substream, flags);
- return ret;
-}
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) */
-
-#endif /* __BACKPORT_SOUND_PCM_H */
diff --git a/compat/Kconfig b/compat/Kconfig
index a5ae300..d501092 100644
--- a/compat/Kconfig
+++ b/compat/Kconfig
@@ -1,37 +1,37 @@
#
# backport Kconfig
#
-# Some options are user-selectable ("BPAUTO_USERSEL_*")
+# Some options are user-selectable ("BACKPORT_USERSEL_*")
#
# Most options, however, follow a few different schemes:
#
# A) An option that is selected by drivers ("select FOO") will be
-# changed to "select BPAUTO_FOO" (if the option BPAUTO_FOO
-# exists). The option BPAUTO_FOO then controls setting of the
-# BPAUTO_BUILD_FOO option, which is a module, like this:
+# changed to "select BACKPORT_FOO" (if the option BACKPORT_FOO
+# exists). The option BACKPORT_FOO then controls setting of the
+# BACKPORT_BUILD_FOO option, which is a module, like this:
#
-# config BPAUTO_BUILD_FOO
+# config BACKPORT_BUILD_FOO
# tristate
# # or bool
#
# # not possible on kernel < X.Y, build will fail if any
# # drivers are allowed to build on kernels < X.Y
-# depends on KERNEL_X_Y
+# depends on BACKPORT_KERNEL_X_Y
#
# # don't build the backport code if FOO is in the kernel
# # already, but only if the kernel version is also >= X.Z;
# # this is an example of backporting where the version of
# # the FOO subsystem that we need is only available from
# # kernel version X.Z
-# depends on !FOO || KERNEL_X_Z
+# depends on !FOO || BACKPORT_KERNEL_X_Z
#
-# # build if driver needs it (it selects BPAUTO_FOO)
-# default m if BPAUTO_FOO
+# # build if driver needs it (it selects BACKPORT_FOO)
+# default m if BACKPORT_FOO
#
-# # or for build-testing (BPAUTO_USERSEL_BUILD_ALL is enabled)
-# default m if BPAUTO_USERSEL_BUILD_ALL
+# # or for build-testing (BACKPORT_USERSEL_BUILD_ALL is enabled)
+# default m if BACKPORT_USERSEL_BUILD_ALL
#
-# config BPAUTO_FOO
+# config BACKPORT_FOO
# bool
#
# This only works as-is if the kernel code is usable on any version,
@@ -41,72 +41,72 @@
# B) An option for code always present on some kernels (e.g. KFIFO).
# This simply depends on/sets the default based on the version:
#
-# config BPAUTO_BUILD_KFIFO
+# config BACKPORT_BUILD_KFIFO
# def_bool y
-# depends on KERNEL_2_6_36
+# depends on BACKPORT_KERNEL_2_6_36
#
#
# C) similarly, a kconfig symbol for an option, e.g.
-# BPAUTO_OPTION_SOME_FIX (no examples provided) check git log
+# BACKPORT_OPTION_SOME_FIX (no examples provided) check git log
#
#
# Variations are obviously possible.
#
-config BPAUTO_BUILD_CORDIC
+config BACKPORT_BUILD_CORDIC
tristate
depends on m
depends on !CORDIC
- default m if BPAUTO_CORDIC
- default m if BPAUTO_USERSEL_BUILD_ALL
+ default m if BACKPORT_CORDIC
+ default m if BACKPORT_USERSEL_BUILD_ALL
#module-name cordic
#c-file lib/cordic.c
-config BPAUTO_CORDIC
+config BACKPORT_CORDIC
bool
-config BPAUTO_BUILD_AVERAGE
+config BACKPORT_BUILD_AVERAGE
bool
depends on !AVERAGE
- default y if BPAUTO_USERSEL_BUILD_ALL
- default y if BPAUTO_AVERAGE
+ default y if BACKPORT_USERSEL_BUILD_ALL
+ default y if BACKPORT_AVERAGE
#h-file linux/average.h
#c-file lib/average.c
-config BPAUTO_AVERAGE
+config BACKPORT_AVERAGE
bool
-config BPAUTO_MII
+config BACKPORT_MII
bool
-config BPAUTO_BUILD_DMA_SHARED_HELPERS
+config BACKPORT_BUILD_DMA_SHARED_HELPERS
bool
depends on HAS_DMA
# Build on other kernels kernels < 3.9 if HAVE_GENERIC_DMA_COHERENT is
# not set. Kernels >= 3.8 have this if HAS_DMA is set.
- depends on (!HAVE_GENERIC_DMA_COHERENT || KERNEL_3_9)
+ depends on (!HAVE_GENERIC_DMA_COHERENT || BACKPORT_KERNEL_3_9)
# Always build if on 3.3 - 3.5
- default y if (KERNEL_3_4 || KERNEL_3_5 || KERNEL_3_6)
+ default y if (BACKPORT_KERNEL_3_4 || BACKPORT_KERNEL_3_5 || BACKPORT_KERNEL_3_6)
# build for testing
- default y if BPAUTO_USERSEL_BUILD_ALL
+ default y if BACKPORT_USERSEL_BUILD_ALL
-config BPAUTO_BUILD_LEDS
+config BACKPORT_BUILD_LEDS
bool
depends on !NEW_LEDS || LEDS_CLASS=n || !LEDS_TRIGGERS
- default y if BPAUTO_NEW_LEDS
- default y if BPAUTO_LEDS_CLASS
- default y if BPAUTO_LEDS_TRIGGERS
+ default y if BACKPORT_NEW_LEDS
+ default y if BACKPORT_LEDS_CLASS
+ default y if BACKPORT_LEDS_TRIGGERS
-config BPAUTO_NEW_LEDS
+config BACKPORT_NEW_LEDS
bool
-config BPAUTO_LEDS_CLASS
+config BACKPORT_LEDS_CLASS
bool
-config BPAUTO_LEDS_TRIGGERS
+config BACKPORT_LEDS_TRIGGERS
bool
-config BPAUTO_USERSEL_BUILD_ALL
+config BACKPORT_USERSEL_BUILD_ALL
bool "Build all compat code"
help
This option selects all the compat code options
@@ -115,24 +115,25 @@
It's only really useful for compat testing, so
you probably shouldn't enable it.
-config BPAUTO_CRYPTO_CCM
+config BACKPORT_CRYPTO_CCM
depends on CRYPTO_AEAD
depends on CRYPTO_CTR
bool
-config BPAUTO_BUILD_CRYPTO_CCM
+config BACKPORT_BUILD_CRYPTO_CCM
bool
default n if CRYPTO_CCM
- default y if BPAUTO_CRYPTO_CCM
+ default y if BACKPORT_CRYPTO_CCM
#c-file crypto/ccm.c
-config BPAUTO_WANT_DEV_COREDUMP
+config BACKPORT_WANT_DEV_COREDUMP
bool
-config BPAUTO_BUILD_WANT_DEV_COREDUMP
+config BACKPORT_BUILD_WANT_DEV_COREDUMP
+ depends on n
bool
default n if DEV_COREDUMP
default n if DISABLE_DEV_COREDUMP
- default y if BPAUTO_WANT_DEV_COREDUMP
+ default y if BACKPORT_WANT_DEV_COREDUMP
#h-file linux/devcoredump.h
#c-file drivers/base/devcoredump.c
diff --git a/compat/Makefile b/compat/Makefile
index 36c4377..1df6225 100644
--- a/compat/Makefile
+++ b/compat/Makefile
@@ -1,35 +1,29 @@
ccflags-y += -I$(src)
-ifeq ($(CONFIG_BACKPORT_INTEGRATE),)
obj-m += compat.o
-else
-obj-y += compat.o
-endif
compat-y += main.o
# Kernel backport compatibility code
-compat-$(CPTCFG_KERNEL_3_0) += compat-3.0.o
-compat-$(CPTCFG_KERNEL_3_1) += compat-3.1.o
-compat-$(CPTCFG_KERNEL_3_2) += backport-3.2.o
-compat-$(CPTCFG_KERNEL_3_3) += compat-3.3.o
-compat-$(CPTCFG_KERNEL_3_4) += compat-3.4.o
-compat-$(CPTCFG_KERNEL_3_5) += compat-3.5.o user_namespace.o
-compat-$(CPTCFG_KERNEL_3_6) += compat-3.6.o
-compat-$(CPTCFG_KERNEL_3_7) += compat-3.7.o
-compat-$(CPTCFG_KERNEL_3_8) += compat-3.8.o
-compat-$(CPTCFG_KERNEL_3_9) += compat-3.9.o
-compat-$(CPTCFG_KERNEL_3_10) += backport-3.10.o
-compat-$(CPTCFG_KERNEL_3_12) += backport-3.12.o
-compat-$(CPTCFG_KERNEL_3_13) += backport-3.13.o
-compat-$(CPTCFG_KERNEL_3_14) += backport-3.14.o
-compat-$(CPTCFG_KERNEL_3_15) += backport-3.15.o
-compat-$(CPTCFG_KERNEL_3_17) += backport-3.17.o
-compat-$(CPTCFG_KERNEL_3_18) += backport-3.18.o
-compat-$(CPTCFG_KERNEL_3_19) += backport-3.19.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_0) += compat-3.0.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_1) += compat-3.1.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_2) += backport-3.2.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_3) += compat-3.3.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_4) += compat-3.4.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_5) += compat-3.5.o user_namespace.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_6) += compat-3.6.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_7) += compat-3.7.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_8) += compat-3.8.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_9) += compat-3.9.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_10) += backport-3.10.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_12) += backport-3.12.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_13) += backport-3.13.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_14) += backport-3.14.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_15) += backport-3.15.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_17) += backport-3.17.o
+compat-$(CPTCFG_BACKPORT_KERNEL_3_18) += backport-3.18.o
-compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o
-compat-$(CPTCFG_BPAUTO_BUILD_DMA_SHARED_HELPERS) += dma-shared-helpers.o
-compat-$(CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP) += drivers-base-devcoredump.o
-compat-$(CPTCFG_BPAUTO_BUILD_AVERAGE) += lib-average.o
+compat-$(CPTCFG_BACKPORT_BUILD_CRYPTO_CCM) += crypto-ccm.o
+compat-$(CPTCFG_BACKPORT_BUILD_DMA_SHARED_HELPERS) += dma-shared-helpers.o
cordic-objs += lib-cordic.o
-obj-$(CPTCFG_BPAUTO_BUILD_CORDIC) += cordic.o
-compat-$(CPTCFG_BPAUTO_BUILD_CRYPTO_CCM) += crypto-ccm.o
+obj-$(CPTCFG_BACKPORT_BUILD_CORDIC) += cordic.o
+compat-$(CPTCFG_BACKPORT_BUILD_AVERAGE) += lib-average.o
+compat-$(CPTCFG_BACKPORT_BUILD_CRYPTO_CCM) += crypto-ccm.o
diff --git a/compat/backport-3.13.c b/compat/backport-3.13.c
index 553ed8f..fd562bb 100644
--- a/compat/backport-3.13.c
+++ b/compat/backport-3.13.c
@@ -12,8 +12,6 @@
#include <linux/version.h>
#include <linux/kernel.h>
#include <net/genetlink.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0))
#ifdef CONFIG_REGULATOR
@@ -202,53 +200,3 @@
}
EXPORT_SYMBOL_GPL(__net_get_random_once);
#endif /* __BACKPORT_NET_GET_RANDOM_ONCE */
-
-#ifdef CONFIG_PCI
-#define pci_bus_read_dev_vendor_id LINUX_BACKPORT(pci_bus_read_dev_vendor_id)
-static bool pci_bus_read_dev_vendor_id(struct pci_bus *bus, int devfn, u32 *l,
- int crs_timeout)
-{
- int delay = 1;
-
- if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
- return false;
-
- /* some broken boards return 0 or ~0 if a slot is empty: */
- if (*l == 0xffffffff || *l == 0x00000000 ||
- *l == 0x0000ffff || *l == 0xffff0000)
- return false;
-
- /*
- * Configuration Request Retry Status. Some root ports return the
- * actual device ID instead of the synthetic ID (0xFFFF) required
- * by the PCIe spec. Ignore the device ID and only check for
- * (vendor id == 1).
- */
- while ((*l & 0xffff) == 0x0001) {
- if (!crs_timeout)
- return false;
-
- msleep(delay);
- delay *= 2;
- if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
- return false;
- /* Card hasn't responded in 60 seconds? Must be stuck. */
- if (delay > crs_timeout) {
- printk(KERN_WARNING "pci %04x:%02x:%02x.%d: not responding\n",
- pci_domain_nr(bus), bus->number, PCI_SLOT(devfn),
- PCI_FUNC(devfn));
- return false;
- }
- }
-
- return true;
-}
-
-bool pci_device_is_present(struct pci_dev *pdev)
-{
- u32 v;
-
- return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0);
-}
-EXPORT_SYMBOL_GPL(pci_device_is_present);
-#endif /* CONFIG_PCI */
diff --git a/compat/backport-3.19.c b/compat/backport-3.19.c
deleted file mode 100644
index c633f38..0000000
--- a/compat/backport-3.19.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright (c) 2014 Hauke Mehrtens <hauke@hauke-m.de>
- *
- * Backport functionality introduced in Linux 3.18.
- *
- * 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.
- */
-#include <linux/wait.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <linux/export.h>
-#include <linux/net.h>
-#include <linux/netdevice.h>
-#include <linux/debugfs.h>
-
-static inline bool is_kthread_should_stop(void)
-{
- return (current->flags & PF_KTHREAD) && kthread_should_stop();
-}
-
-/*
- * DEFINE_WAIT_FUNC(wait, woken_wake_func);
- *
- * add_wait_queue(&wq, &wait);
- * for (;;) {
- * if (condition)
- * break;
- *
- * p->state = mode; condition = true;
- * smp_mb(); // A smp_wmb(); // C
- * if (!wait->flags & WQ_FLAG_WOKEN) wait->flags |= WQ_FLAG_WOKEN;
- * schedule() try_to_wake_up();
- * p->state = TASK_RUNNING; ~~~~~~~~~~~~~~~~~~
- * wait->flags &= ~WQ_FLAG_WOKEN; condition = true;
- * smp_mb() // B smp_wmb(); // C
- * wait->flags |= WQ_FLAG_WOKEN;
- * }
- * remove_wait_queue(&wq, &wait);
- *
- */
-long wait_woken(wait_queue_t *wait, unsigned mode, long timeout)
-{
- set_current_state(mode); /* A */
- /*
- * The above implies an smp_mb(), which matches with the smp_wmb() from
- * woken_wake_function() such that if we observe WQ_FLAG_WOKEN we must
- * also observe all state before the wakeup.
- */
- if (!(wait->flags & WQ_FLAG_WOKEN) && !is_kthread_should_stop())
- timeout = schedule_timeout(timeout);
- __set_current_state(TASK_RUNNING);
-
- /*
- * The below implies an smp_mb(), it too pairs with the smp_wmb() from
- * woken_wake_function() such that we must either observe the wait
- * condition being true _OR_ WQ_FLAG_WOKEN such that we will not miss
- * an event.
- */
- set_mb(wait->flags, wait->flags & ~WQ_FLAG_WOKEN); /* B */
-
- return timeout;
-}
-EXPORT_SYMBOL(wait_woken);
-
-int woken_wake_function(wait_queue_t *wait, unsigned mode, int sync, void *key)
-{
- /*
- * Although this function is called under waitqueue lock, LOCK
- * doesn't imply write barrier and the users expects write
- * barrier semantics on wakeup functions. The following
- * smp_wmb() is equivalent to smp_wmb() in try_to_wake_up()
- * and is paired with set_mb() in wait_woken().
- */
- smp_wmb(); /* C */
- wait->flags |= WQ_FLAG_WOKEN;
-
- return default_wake_function(wait, mode, sync, key);
-}
-EXPORT_SYMBOL(woken_wake_function);
-
-#ifdef __BACKPORT_NETDEV_RSS_KEY_FILL
-u8 netdev_rss_key[NETDEV_RSS_KEY_LEN];
-
-void netdev_rss_key_fill(void *buffer, size_t len)
-{
- BUG_ON(len > sizeof(netdev_rss_key));
- net_get_random_once(netdev_rss_key, sizeof(netdev_rss_key));
- memcpy(buffer, netdev_rss_key, len);
-}
-EXPORT_SYMBOL_GPL(netdev_rss_key_fill);
-#endif /* __BACKPORT_NETDEV_RSS_KEY_FILL */
-
-#if defined(CONFIG_DEBUG_FS)
-struct debugfs_devm_entry {
- int (*read)(struct seq_file *seq, void *data);
- struct device *dev;
-};
-
-static int debugfs_devm_entry_open(struct inode *inode, struct file *f)
-{
- struct debugfs_devm_entry *entry = inode->i_private;
-
- return single_open(f, entry->read, entry->dev);
-}
-
-static const struct file_operations debugfs_devm_entry_ops = {
- .owner = THIS_MODULE,
- .open = debugfs_devm_entry_open,
- .release = single_release,
- .read = seq_read,
- .llseek = seq_lseek
-};
-
-/**
- * debugfs_create_devm_seqfile - create a debugfs file that is bound to device.
- *
- * @dev: device related to this debugfs file.
- * @name: name of the debugfs file.
- * @parent: a pointer to the parent dentry for this file. This should be a
- * directory dentry if set. If this parameter is %NULL, then the
- * file will be created in the root of the debugfs filesystem.
- * @read_fn: function pointer called to print the seq_file content.
- */
-struct dentry *debugfs_create_devm_seqfile(struct device *dev, const char *name,
- struct dentry *parent,
- int (*read_fn)(struct seq_file *s,
- void *data))
-{
- struct debugfs_devm_entry *entry;
-
- if (IS_ERR(parent))
- return ERR_PTR(-ENOENT);
-
- entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
- if (!entry)
- return ERR_PTR(-ENOMEM);
-
- entry->read = read_fn;
- entry->dev = dev;
-
- return debugfs_create_file(name, S_IRUGO, parent, entry,
- &debugfs_devm_entry_ops);
-}
-EXPORT_SYMBOL_GPL(debugfs_create_devm_seqfile);
-
-#endif /* CONFIG_DEBUG_FS */
diff --git a/compat/backports.h b/compat/backports.h
index ccc8972..c9094ac 100644
--- a/compat/backports.h
+++ b/compat/backports.h
@@ -3,7 +3,7 @@
#include <linux/version.h>
-#ifdef CPTCFG_BPAUTO_BUILD_CRYPTO_CCM
+#ifdef CPTCFG_BACKPORT_BUILD_CRYPTO_CCM
int crypto_ccm_module_init(void);
void crypto_ccm_module_exit(void);
#else
@@ -13,7 +13,7 @@
{}
#endif
-#ifdef CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP
+#ifdef CPTCFG_BACKPORT_BUILD_WANT_DEV_COREDUMP
int devcoredump_init(void);
void devcoredump_exit(void);
#else
diff --git a/compat/compat-3.1.c b/compat/compat-3.1.c
index 2618780..0d9c3a2 100644
--- a/compat/compat-3.1.c
+++ b/compat/compat-3.1.c
@@ -10,7 +10,6 @@
#include <linux/idr.h>
#include <linux/cpufreq.h>
-#include <linux/of.h>
static DEFINE_SPINLOCK(compat_simple_ida_lock);
@@ -83,36 +82,3 @@
EXPORT_SYMBOL_GPL(ida_simple_remove);
/* source lib/idr.c */
-#ifdef CONFIG_OF
-/**
- * of_property_read_u32_array - Find and read an array of 32 bit integers
- * from a property.
- *
- * @np: device node from which the property value is to be read.
- * @propname: name of the property to be searched.
- * @out_values: pointer to return value, modified only if return value is 0.
- * @sz: number of array elements to read
- *
- * Search for a property in a device node and read 32-bit value(s) from
- * it. Returns 0 on success, -EINVAL if the property does not exist,
- * -ENODATA if property does not have a value, and -EOVERFLOW if the
- * property data isn't large enough.
- *
- * The out_values is modified only if a valid u32 value can be decoded.
- */
-int of_property_read_u32_array(const struct device_node *np,
- const char *propname, u32 *out_values,
- size_t sz)
-{
- const __be32 *val = of_find_property_value_of_size(np, propname,
- (sz * sizeof(*out_values)));
-
- if (IS_ERR(val))
- return PTR_ERR(val);
-
- while (sz--)
- *out_values++ = be32_to_cpup(val++);
- return 0;
-}
-EXPORT_SYMBOL_GPL(of_property_read_u32_array);
-#endif
diff --git a/compat/compat-3.3.c b/compat/compat-3.3.c
index 490c29b..7ddc2bd 100644
--- a/compat/compat-3.3.c
+++ b/compat/compat-3.3.c
@@ -224,16 +224,3 @@
spin_unlock(&wq_name_lock);
}
EXPORT_SYMBOL_GPL(backport_destroy_workqueue);
-
-void genl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group,
- struct nlmsghdr *nlh, gfp_t flags)
-{
- struct sock *sk = net->genl_sock;
- int report = 0;
-
- if (nlh)
- report = nlmsg_report(nlh);
-
- nlmsg_notify(sk, skb, pid, group, report, flags);
-}
-EXPORT_SYMBOL_GPL(genl_notify);
diff --git a/compat/drivers-base-devcoredump.c b/compat/drivers-base-devcoredump.c
deleted file mode 100644
index f15c830..0000000
--- a/compat/drivers-base-devcoredump.c
+++ /dev/null
@@ -1,319 +0,0 @@
-/*
- * This file is provided under the GPLv2 license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2014 Intel Mobile Communications GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License 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.
- *
- * The full GNU General Public License is included in this distribution
- * in the file called COPYING.
- *
- * Contact Information:
- * Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * Author: Johannes Berg <johannes@sipsolutions.net>
- */
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/devcoredump.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/workqueue.h>
-#include "backports.h"
-
-static struct class devcd_class;
-
-/* global disable flag, for security purposes */
-static bool devcd_disabled;
-
-/* if data isn't read by userspace after 5 minutes then delete it */
-#define DEVCD_TIMEOUT (HZ * 60 * 5)
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
-static struct bin_attribute devcd_attr_data;
-#endif
-
-struct devcd_entry {
- struct device devcd_dev;
- const void *data;
- size_t datalen;
- struct module *owner;
- ssize_t (*read)(char *buffer, loff_t offset, size_t count,
- const void *data, size_t datalen);
- void (*free)(const void *data);
- struct delayed_work del_wk;
- struct device *failing_dev;
-};
-
-static struct devcd_entry *dev_to_devcd(struct device *dev)
-{
- return container_of(dev, struct devcd_entry, devcd_dev);
-}
-
-static void devcd_dev_release(struct device *dev)
-{
- struct devcd_entry *devcd = dev_to_devcd(dev);
-
- devcd->free(devcd->data);
- module_put(devcd->owner);
-
- /*
- * this seems racy, but I don't see a notifier or such on
- * a struct device to know when it goes away?
- */
- if (devcd->failing_dev->kobj.sd)
- sysfs_remove_link(&devcd->failing_dev->kobj, "devcoredump");
-
- put_device(devcd->failing_dev);
- kfree(devcd);
-}
-
-static void devcd_del(struct work_struct *wk)
-{
- struct devcd_entry *devcd;
-
- devcd = container_of(wk, struct devcd_entry, del_wk.work);
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
- device_remove_bin_file(&devcd->devcd_dev, &devcd_attr_data);
-#endif
- device_del(&devcd->devcd_dev);
- put_device(&devcd->devcd_dev);
-}
-
-static ssize_t devcd_data_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buffer, loff_t offset, size_t count)
-{
- struct device *dev = kobj_to_dev(kobj);
- struct devcd_entry *devcd = dev_to_devcd(dev);
-
- return devcd->read(buffer, offset, count, devcd->data, devcd->datalen);
-}
-
-static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
- char *buffer, loff_t offset, size_t count)
-{
- struct device *dev = kobj_to_dev(kobj);
- struct devcd_entry *devcd = dev_to_devcd(dev);
-
- mod_delayed_work(system_wq, &devcd->del_wk, 0);
-
- return count;
-}
-
-static struct bin_attribute devcd_attr_data = {
- .attr = { .name = "data", .mode = S_IRUSR | S_IWUSR, },
- .size = 0,
- .read = devcd_data_read,
- .write = devcd_data_write,
-};
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
-static struct bin_attribute *devcd_dev_bin_attrs[] = {
- &devcd_attr_data, NULL,
-};
-
-static const struct attribute_group devcd_dev_group = {
- .bin_attrs = devcd_dev_bin_attrs,
-};
-
-static const struct attribute_group *devcd_dev_groups[] = {
- &devcd_dev_group, NULL,
-};
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) */
-
-static int devcd_free(struct device *dev, void *data)
-{
- struct devcd_entry *devcd = dev_to_devcd(dev);
-
- flush_delayed_work(&devcd->del_wk);
- return 0;
-}
-
-static ssize_t disabled_show(struct class *class, struct class_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%d\n", devcd_disabled);
-}
-
-static ssize_t disabled_store(struct class *class, struct class_attribute *attr,
- const char *buf, size_t count)
-{
- long tmp = simple_strtol(buf, NULL, 10);
-
- /*
- * This essentially makes the attribute write-once, since you can't
- * go back to not having it disabled. This is intentional, it serves
- * as a system lockdown feature.
- */
- if (tmp != 1)
- return -EINVAL;
-
- devcd_disabled = true;
-
- class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
-
- return count;
-}
-
-static struct class_attribute devcd_class_attrs[] = {
- __ATTR_RW(disabled),
- __ATTR_NULL
-};
-
-static struct class devcd_class = {
- .name = "devcoredump",
- .owner = THIS_MODULE,
- .dev_release = devcd_dev_release,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
- .dev_groups = devcd_dev_groups,
-#endif
- .class_attrs = devcd_class_attrs,
-};
-
-static ssize_t devcd_readv(char *buffer, loff_t offset, size_t count,
- const void *data, size_t datalen)
-{
- if (offset > datalen)
- return -EINVAL;
-
- if (offset + count > datalen)
- count = datalen - offset;
-
- if (count)
- memcpy(buffer, ((u8 *)data) + offset, count);
-
- return count;
-}
-
-/**
- * dev_coredumpv - create device coredump with vmalloc data
- * @dev: the struct device for the crashed device
- * @data: vmalloc data containing the device coredump
- * @datalen: length of the data
- * @gfp: allocation flags
- *
- * This function takes ownership of the vmalloc'ed data and will free
- * it when it is no longer used. See dev_coredumpm() for more information.
- */
-void dev_coredumpv(struct device *dev, const void *data, size_t datalen,
- gfp_t gfp)
-{
- dev_coredumpm(dev, NULL, data, datalen, gfp, devcd_readv, vfree);
-}
-EXPORT_SYMBOL_GPL(dev_coredumpv);
-
-static int devcd_match_failing(struct device *dev, const void *failing)
-{
- struct devcd_entry *devcd = dev_to_devcd(dev);
-
- return devcd->failing_dev == failing;
-}
-
-/**
- * dev_coredumpm - create device coredump with read/free methods
- * @dev: the struct device for the crashed device
- * @owner: the module that contains the read/free functions, use %THIS_MODULE
- * @data: data cookie for the @read/@free functions
- * @datalen: length of the data
- * @gfp: allocation flags
- * @read: function to read from the given buffer
- * @free: function to free the given buffer
- *
- * Creates a new device coredump for the given device. If a previous one hasn't
- * been read yet, the new coredump is discarded. The data lifetime is determined
- * by the device coredump framework and when it is no longer needed the @free
- * function will be called to free the data.
- */
-void dev_coredumpm(struct device *dev, struct module *owner,
- const void *data, size_t datalen, gfp_t gfp,
- ssize_t (*read)(char *buffer, loff_t offset, size_t count,
- const void *data, size_t datalen),
- void (*free)(const void *data))
-{
- static atomic_t devcd_count = ATOMIC_INIT(0);
- struct devcd_entry *devcd;
- struct device *existing;
-
- if (devcd_disabled)
- goto free;
-
- existing = class_find_device(&devcd_class, NULL, dev,
- devcd_match_failing);
- if (existing) {
- put_device(existing);
- goto free;
- }
-
- if (!try_module_get(owner))
- goto free;
-
- devcd = kzalloc(sizeof(*devcd), gfp);
- if (!devcd)
- goto put_module;
-
- devcd->owner = owner;
- devcd->data = data;
- devcd->datalen = datalen;
- devcd->read = read;
- devcd->free = free;
- devcd->failing_dev = get_device(dev);
-
- device_initialize(&devcd->devcd_dev);
-
- dev_set_name(&devcd->devcd_dev, "devcd%d",
- atomic_inc_return(&devcd_count));
- devcd->devcd_dev.class = &devcd_class;
-
- if (device_add(&devcd->devcd_dev))
- goto put_device;
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)
- if (device_create_bin_file(&devcd->devcd_dev, &devcd_attr_data))
- goto put_device;
-#endif
-
- if (sysfs_create_link(&devcd->devcd_dev.kobj, &dev->kobj,
- "failing_device"))
- /* nothing - symlink will be missing */;
-
- if (sysfs_create_link(&dev->kobj, &devcd->devcd_dev.kobj,
- "devcoredump"))
- /* nothing - symlink will be missing */;
-
- INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
- schedule_delayed_work(&devcd->del_wk, DEVCD_TIMEOUT);
-
- return;
- put_device:
- put_device(&devcd->devcd_dev);
- put_module:
- module_put(owner);
- free:
- free(data);
-}
-EXPORT_SYMBOL_GPL(dev_coredumpm);
-
-int __init devcoredump_init(void)
-{
- return class_register(&devcd_class);
-}
-
-void __exit devcoredump_exit(void)
-{
- class_for_each_device(&devcd_class, NULL, NULL, devcd_free);
- class_unregister(&devcd_class);
-}
diff --git a/compat/main.c b/compat/main.c
index 5d45e3d..d3f8944 100644
--- a/compat/main.c
+++ b/compat/main.c
@@ -8,40 +8,40 @@
MODULE_DESCRIPTION("Kernel backport module");
MODULE_LICENSE("GPL");
-#ifndef CPTCFG_KERNEL_NAME
-#error "You need a CPTCFG_KERNEL_NAME"
+#ifndef BACKPORTED_KERNEL_NAME
+#error "You need a BACKPORTED_KERNEL_NAME"
#endif
-#ifndef CPTCFG_KERNEL_VERSION
-#error "You need a CPTCFG_KERNEL_VERSION"
+#ifndef BACKPORTED_KERNEL_VERSION
+#error "You need a BACKPORTED_KERNEL_VERSION"
#endif
-#ifndef CPTCFG_VERSION
-#error "You need a CPTCFG_VERSION"
+#ifndef BACKPORTS_VERSION
+#error "You need a BACKPORTS_VERSION"
#endif
-static char *backported_kernel_name = CPTCFG_KERNEL_NAME;
+static char *backported_kernel_name = BACKPORTED_KERNEL_NAME;
module_param(backported_kernel_name, charp, 0400);
MODULE_PARM_DESC(backported_kernel_name,
- "The kernel tree name that was used for this backport (" CPTCFG_KERNEL_NAME ")");
+ "The kernel tree name that was used for this backport (" BACKPORTED_KERNEL_NAME ")");
-#ifdef BACKPORTS_GIT_TRACKED
+#ifdef BACKPORTS_GIT_TRACKED
static char *backports_tracker_id = BACKPORTS_GIT_TRACKED;
module_param(backports_tracker_id, charp, 0400);
MODULE_PARM_DESC(backports_tracker_id,
"The version of the tree containing this backport (" BACKPORTS_GIT_TRACKED ")");
#else
-static char *backported_kernel_version = CPTCFG_KERNEL_VERSION;
-static char *backports_version = CPTCFG_VERSION;
+static char *backported_kernel_version = BACKPORTED_KERNEL_VERSION;
+static char *backports_version = BACKPORTS_VERSION;
module_param(backported_kernel_version, charp, 0400);
MODULE_PARM_DESC(backported_kernel_version,
- "The kernel version that was used for this backport (" CPTCFG_KERNEL_VERSION ")");
+ "The kernel version that was used for this backport (" BACKPORTED_KERNEL_VERSION ")");
module_param(backports_version, charp, 0400);
MODULE_PARM_DESC(backports_version,
- "The git version of the backports tree used to generate this backport (" CPTCFG_VERSION ")");
+ "The git version of the backports tree used to generate this backport (" BACKPORTS_VERSION ")");
#endif
@@ -63,22 +63,16 @@
return ret;
}
- printk(KERN_INFO "Loading modules backported from " CPTCFG_KERNEL_NAME
+ printk(KERN_INFO "Loading modules backported from " BACKPORTED_KERNEL_NAME
#ifndef BACKPORTS_GIT_TRACKED
- " version " CPTCFG_KERNEL_VERSION
+ " version " BACKPORTED_KERNEL_VERSION
#endif
"\n");
#ifdef BACKPORTS_GIT_TRACKED
printk(KERN_INFO BACKPORTS_GIT_TRACKED "\n");
#else
-
-#ifdef CONFIG_BACKPORT_INTEGRATE
- printk(KERN_INFO "Backport integrated by backports.git " CPTCFG_VERSION "\n");
-#else
- printk(KERN_INFO "Backport generated by backports.git " CPTCFG_VERSION "\n");
-#endif /* CONFIG_BACKPORT_INTEGRATE */
-
-#endif /* BACKPORTS_GIT_TRACKED */
+ printk(KERN_INFO "Backport generated by backports.git " BACKPORTS_VERSION "\n");
+#endif
return 0;
}
diff --git a/defconfigs/ieee802154 b/defconfigs/ieee802154
new file mode 100644
index 0000000..2c6730a
--- /dev/null
+++ b/defconfigs/ieee802154
@@ -0,0 +1,8 @@
+CPTCFG_IEEE802154_DRIVERS=m
+CPTCFG_IEEE802154_FAKEHARD=m
+CPTCFG_IEEE802154_FAKELB=m
+CPTCFG_IEEE802154_AT86RF230=m
+CPTCFG_IEEE802154_MRF24J40=m
+CPTCFG_IEEE802154=m
+CPTCFG_IEEE802154_6LOWPAN=m
+CPTCFG_MAC802154=m
diff --git a/defconfigs/media b/defconfigs/media
new file mode 100644
index 0000000..7b1bfa9
--- /dev/null
+++ b/defconfigs/media
@@ -0,0 +1,513 @@
+CPTCFG_DVB_A8293=m
+CPTCFG_DVB_AF9013=m
+CPTCFG_DVB_AF9033=m
+CPTCFG_DVB_AS102=m
+CPTCFG_DVB_AS102_FE=m
+CPTCFG_DVB_ATBM8830=m
+CPTCFG_DVB_AU8522=m
+CPTCFG_DVB_AU8522_DTV=m
+CPTCFG_DVB_AU8522_V4L=m
+CPTCFG_DVB_AV7110=m
+CPTCFG_DVB_B2C2_FLEXCOP=m
+CPTCFG_DVB_B2C2_FLEXCOP_PCI=m
+CPTCFG_DVB_B2C2_FLEXCOP_USB=m
+CPTCFG_DVB_BCM3510=m
+CPTCFG_DVB_BT8XX=m
+CPTCFG_DVB_BUDGET=m
+CPTCFG_DVB_BUDGET_AV=m
+CPTCFG_DVB_BUDGET_CI=m
+CPTCFG_DVB_BUDGET_CORE=m
+CPTCFG_DVB_BUDGET_PATCH=m
+CPTCFG_DVB_CORE=m
+CPTCFG_DVB_CX22700=m
+CPTCFG_DVB_CX22702=m
+CPTCFG_DVB_CX24110=m
+CPTCFG_DVB_CX24116=m
+CPTCFG_DVB_CX24123=m
+CPTCFG_DVB_CXD2820R=m
+CPTCFG_DVB_DDBRIDGE=m
+CPTCFG_DVB_DIB3000MB=m
+CPTCFG_DVB_DIB3000MC=m
+CPTCFG_DVB_DIB7000M=m
+CPTCFG_DVB_DIB7000P=m
+CPTCFG_DVB_DIB8000=m
+CPTCFG_DVB_DIB9000=m
+CPTCFG_DVB_DM1105=m
+CPTCFG_DVB_DRXD=m
+CPTCFG_DVB_DRXK=m
+CPTCFG_DVB_DS3000=m
+CPTCFG_DVB_DUMMY_FE=m
+CPTCFG_DVB_EC100=m
+CPTCFG_DVB_FIREDTV=m
+CPTCFG_DVB_FIREDTV_INPUT=y
+CPTCFG_DVB_HD29L2=m
+CPTCFG_DVB_HOPPER=m
+CPTCFG_DVB_ISL6405=m
+CPTCFG_DVB_ISL6421=m
+CPTCFG_DVB_ISL6423=m
+CPTCFG_DVB_IX2505V=m
+CPTCFG_DVB_L64781=m
+CPTCFG_DVB_LG2160=m
+CPTCFG_DVB_LGDT3305=m
+CPTCFG_DVB_LGDT330X=m
+CPTCFG_DVB_LGS8GL5=m
+CPTCFG_DVB_LGS8GXX=m
+CPTCFG_DVB_LNBP21=m
+CPTCFG_DVB_LNBP22=m
+CPTCFG_DVB_M88RS2000=m
+CPTCFG_DVB_MANTIS=m
+CPTCFG_DVB_MB86A16=m
+CPTCFG_DVB_MB86A20S=m
+CPTCFG_DVB_MT312=m
+CPTCFG_DVB_MT352=m
+CPTCFG_DVB_NGENE=m
+CPTCFG_DVB_NXT200X=m
+CPTCFG_DVB_NXT6000=m
+CPTCFG_DVB_OR51132=m
+CPTCFG_DVB_OR51211=m
+CPTCFG_DVB_PLL=m
+CPTCFG_DVB_PLUTO2=m
+CPTCFG_DVB_PT1=m
+CPTCFG_DVB_PT3=m
+CPTCFG_DVB_RTL2830=m
+CPTCFG_DVB_RTL2832=m
+CPTCFG_DVB_S5H1409=m
+CPTCFG_DVB_S5H1411=m
+CPTCFG_DVB_S5H1420=m
+CPTCFG_DVB_S5H1432=m
+CPTCFG_DVB_S921=m
+CPTCFG_DVB_SI21XX=m
+CPTCFG_DVB_SP8870=m
+CPTCFG_DVB_SP887X=m
+CPTCFG_DVB_STB0899=m
+CPTCFG_DVB_STB6000=m
+CPTCFG_DVB_STB6100=m
+CPTCFG_DVB_STV0288=m
+CPTCFG_DVB_STV0297=m
+CPTCFG_DVB_STV0299=m
+CPTCFG_DVB_STV0367=m
+CPTCFG_DVB_STV0900=m
+CPTCFG_DVB_STV090x=m
+CPTCFG_DVB_STV6110=m
+CPTCFG_DVB_STV6110x=m
+CPTCFG_DVB_TDA10021=m
+CPTCFG_DVB_TDA10023=m
+CPTCFG_DVB_TDA10048=m
+CPTCFG_DVB_TDA1004X=m
+CPTCFG_DVB_TDA10071=m
+CPTCFG_DVB_TDA10086=m
+CPTCFG_DVB_TDA18271C2DD=m
+CPTCFG_DVB_TDA665x=m
+CPTCFG_DVB_TDA8083=m
+CPTCFG_DVB_TDA8261=m
+CPTCFG_DVB_TDA826X=m
+CPTCFG_DVB_TS2020=m
+CPTCFG_DVB_TTUSB_BUDGET=m
+CPTCFG_DVB_TTUSB_DEC=m
+CPTCFG_DVB_TUA6100=m
+CPTCFG_DVB_TUNER_CX24113=m
+CPTCFG_DVB_TUNER_DIB0070=m
+CPTCFG_DVB_TUNER_DIB0090=m
+CPTCFG_DVB_TUNER_ITD1000=m
+CPTCFG_DVB_USB=m
+CPTCFG_DVB_USB_A800=m
+CPTCFG_DVB_USB_AF9005=m
+CPTCFG_DVB_USB_AF9005_REMOTE=m
+CPTCFG_DVB_USB_AF9015=m
+CPTCFG_DVB_USB_AF9035=m
+CPTCFG_DVB_USB_ANYSEE=m
+CPTCFG_DVB_USB_AU6610=m
+CPTCFG_DVB_USB_AZ6007=m
+CPTCFG_DVB_USB_AZ6027=m
+CPTCFG_DVB_USB_CE6230=m
+CPTCFG_DVB_USB_CINERGY_T2=m
+CPTCFG_DVB_USB_CXUSB=m
+CPTCFG_DVB_USB_CYPRESS_FIRMWARE=m
+CPTCFG_DVB_USB_DIB0700=m
+CPTCFG_DVB_USB_DIBUSB_MB=m
+CPTCFG_DVB_USB_DIBUSB_MC=m
+CPTCFG_DVB_USB_DIGITV=m
+CPTCFG_DVB_USB_DTT200U=m
+CPTCFG_DVB_USB_DTV5100=m
+CPTCFG_DVB_USB_DVBSKY=m
+CPTCFG_DVB_USB_DW2102=m
+CPTCFG_DVB_USB_EC168=m
+CPTCFG_DVB_USB_FRIIO=m
+CPTCFG_DVB_USB_GL861=m
+CPTCFG_DVB_USB_GP8PSK=m
+CPTCFG_DVB_USB_LME2510=m
+CPTCFG_DVB_USB_M920X=m
+CPTCFG_DVB_USB_MXL111SF=m
+CPTCFG_DVB_USB_NOVA_T_USB2=m
+CPTCFG_DVB_USB_OPERA1=m
+CPTCFG_DVB_USB_PCTV452E=m
+CPTCFG_DVB_USB_RTL28XXU=m
+CPTCFG_DVB_USB_TECHNISAT_USB2=m
+CPTCFG_DVB_USB_TTUSB2=m
+CPTCFG_DVB_USB_UMT_010=m
+CPTCFG_DVB_USB_V2=m
+CPTCFG_DVB_USB_VP702X=m
+CPTCFG_DVB_USB_VP7045=m
+CPTCFG_DVB_VES1820=m
+CPTCFG_DVB_VES1X93=m
+CPTCFG_DVB_ZL10036=m
+CPTCFG_DVB_ZL10039=m
+CPTCFG_DVB_ZL10353=m
+CPTCFG_I2C_SI470X=m
+CPTCFG_I2C_SI4713=m
+CPTCFG_IR_ENE=m
+CPTCFG_IR_FINTEK=m
+CPTCFG_IR_GPIO_CIR=m
+CPTCFG_IR_IGUANA=m
+CPTCFG_IR_IMG=m
+CPTCFG_IR_IMG_HW=y
+CPTCFG_IR_IMG_JVC=y
+CPTCFG_IR_IMG_NEC=y
+CPTCFG_IR_IMG_RAW=y
+CPTCFG_IR_IMG_SANYO=y
+CPTCFG_IR_IMG_SHARP=y
+CPTCFG_IR_IMG_SONY=y
+CPTCFG_IR_IMON=m
+CPTCFG_IR_ITE_CIR=m
+CPTCFG_IR_JVC_DECODER=m
+CPTCFG_IR_LIRC_CODEC=m
+CPTCFG_IR_MCEUSB=m
+CPTCFG_IR_MCE_KBD_DECODER=m
+CPTCFG_IR_NEC_DECODER=m
+CPTCFG_IR_NUVOTON=m
+CPTCFG_IR_RC5_DECODER=m
+CPTCFG_IR_RC6_DECODER=m
+CPTCFG_IR_REDRAT3=m
+CPTCFG_IR_RX51=m
+CPTCFG_IR_SANYO_DECODER=m
+CPTCFG_IR_SONY_DECODER=m
+CPTCFG_IR_STREAMZAP=m
+CPTCFG_IR_TTUSBIR=m
+CPTCFG_IR_WINBOND_CIR=m
+CPTCFG_LIRC=m
+CPTCFG_MANTIS_CORE=m
+CPTCFG_MEDIA_ALTERA_CI=m
+CPTCFG_MEDIA_ANALOG_TV_SUPPORT=y
+CPTCFG_MEDIA_CAMERA_SUPPORT=y
+CPTCFG_MEDIA_CONTROLLER=y
+CPTCFG_MEDIA_DIGITAL_TV_SUPPORT=y
+CPTCFG_MEDIA_PARPORT_SUPPORT=y
+CPTCFG_MEDIA_PCI_SUPPORT=y
+CPTCFG_MEDIA_RADIO_SUPPORT=y
+CPTCFG_MEDIA_RC_SUPPORT=y
+CPTCFG_MEDIA_SDR_SUPPORT=y
+CPTCFG_MEDIA_SUPPORT=m
+CPTCFG_MEDIA_USB_SUPPORT=y
+CPTCFG_PLATFORM_SI4713=m
+CPTCFG_RADIO_AZTECH=m
+CPTCFG_RADIO_CADET=m
+CPTCFG_RADIO_GEMTEK=m
+CPTCFG_RADIO_ISA=m
+CPTCFG_RADIO_MAXIRADIO=m
+CPTCFG_RADIO_MIROPCM20=m
+CPTCFG_RADIO_RTRACK2=m
+CPTCFG_RADIO_RTRACK=m
+CPTCFG_RADIO_SAA7706H=m
+CPTCFG_RADIO_SF16FMI=m
+CPTCFG_RADIO_SF16FMR2=m
+CPTCFG_RADIO_SHARK2=m
+CPTCFG_RADIO_SHARK=m
+CPTCFG_RADIO_SI470X=y
+CPTCFG_RADIO_SI4713=m
+CPTCFG_RADIO_SI476X=m
+CPTCFG_RADIO_TEA5764=m
+CPTCFG_RADIO_TEF6862=m
+CPTCFG_RADIO_TERRATEC=m
+CPTCFG_RADIO_TIMBERDALE=m
+CPTCFG_RADIO_TRUST=m
+CPTCFG_RADIO_TYPHOON=m
+CPTCFG_RADIO_WL1273=m
+CPTCFG_RADIO_WL128X=m
+CPTCFG_RADIO_ZOLTRIX=m
+CPTCFG_RC_ATI_REMOTE=m
+CPTCFG_RC_CORE=m
+CPTCFG_RC_DEVICES=y
+CPTCFG_RC_LOOPBACK=m
+CPTCFG_RC_MAP=m
+CPTCFG_SMS_SDIO_DRV=m
+CPTCFG_SMS_SIANO_MDTV=m
+CPTCFG_SMS_USB_DRV=m
+CPTCFG_SOC_CAMERA=m
+CPTCFG_SOC_CAMERA_IMX074=m
+CPTCFG_SOC_CAMERA_MT9M001=m
+CPTCFG_SOC_CAMERA_MT9M111=m
+CPTCFG_SOC_CAMERA_MT9T031=m
+CPTCFG_SOC_CAMERA_MT9T112=m
+CPTCFG_SOC_CAMERA_MT9V022=m
+CPTCFG_SOC_CAMERA_OV2640=m
+CPTCFG_SOC_CAMERA_OV5642=m
+CPTCFG_SOC_CAMERA_OV6650=m
+CPTCFG_SOC_CAMERA_OV772X=m
+CPTCFG_SOC_CAMERA_OV9640=m
+CPTCFG_SOC_CAMERA_OV9740=m
+CPTCFG_SOC_CAMERA_PLATFORM=m
+CPTCFG_SOC_CAMERA_RJ54N1=m
+CPTCFG_SOC_CAMERA_TW9910=m
+CPTCFG_STA2X11_VIP=m
+CPTCFG_TTPCI_EEPROM=m
+CPTCFG_USB_AIRSPY=m
+CPTCFG_USB_DSBR=m
+CPTCFG_USB_GL860=m
+CPTCFG_USB_GSPCA=m
+CPTCFG_USB_GSPCA_BENQ=m
+CPTCFG_USB_GSPCA_CONEX=m
+CPTCFG_USB_GSPCA_CPIA1=m
+CPTCFG_USB_GSPCA_DTCS033=m
+CPTCFG_USB_GSPCA_ETOMS=m
+CPTCFG_USB_GSPCA_FINEPIX=m
+CPTCFG_USB_GSPCA_JEILINJ=m
+CPTCFG_USB_GSPCA_JL2005BCD=m
+CPTCFG_USB_GSPCA_KINECT=m
+CPTCFG_USB_GSPCA_KONICA=m
+CPTCFG_USB_GSPCA_MARS=m
+CPTCFG_USB_GSPCA_MR97310A=m
+CPTCFG_USB_GSPCA_NW80X=m
+CPTCFG_USB_GSPCA_OV519=m
+CPTCFG_USB_GSPCA_OV534=m
+CPTCFG_USB_GSPCA_OV534_9=m
+CPTCFG_USB_GSPCA_PAC207=m
+CPTCFG_USB_GSPCA_PAC7302=m
+CPTCFG_USB_GSPCA_PAC7311=m
+CPTCFG_USB_GSPCA_SE401=m
+CPTCFG_USB_GSPCA_SN9C2028=m
+CPTCFG_USB_GSPCA_SN9C20X=m
+CPTCFG_USB_GSPCA_SONIXB=m
+CPTCFG_USB_GSPCA_SONIXJ=m
+CPTCFG_USB_GSPCA_SPCA1528=m
+CPTCFG_USB_GSPCA_SPCA500=m
+CPTCFG_USB_GSPCA_SPCA501=m
+CPTCFG_USB_GSPCA_SPCA505=m
+CPTCFG_USB_GSPCA_SPCA506=m
+CPTCFG_USB_GSPCA_SPCA508=m
+CPTCFG_USB_GSPCA_SPCA561=m
+CPTCFG_USB_GSPCA_SQ905=m
+CPTCFG_USB_GSPCA_SQ905C=m
+CPTCFG_USB_GSPCA_SQ930X=m
+CPTCFG_USB_GSPCA_STK014=m
+CPTCFG_USB_GSPCA_STK1135=m
+CPTCFG_USB_GSPCA_STV0680=m
+CPTCFG_USB_GSPCA_SUNPLUS=m
+CPTCFG_USB_GSPCA_T613=m
+CPTCFG_USB_GSPCA_TOPRO=m
+CPTCFG_USB_GSPCA_TV8532=m
+CPTCFG_USB_GSPCA_VC032X=m
+CPTCFG_USB_GSPCA_VICAM=m
+CPTCFG_USB_GSPCA_XIRLINK_CIT=m
+CPTCFG_USB_GSPCA_ZC3XX=m
+CPTCFG_USB_HACKRF=m
+CPTCFG_USB_KEENE=m
+CPTCFG_USB_M5602=m
+CPTCFG_USB_MA901=m
+CPTCFG_USB_MR800=m
+CPTCFG_USB_MSI2500=m
+CPTCFG_USB_PWC=m
+CPTCFG_USB_RAREMONO=m
+CPTCFG_USB_S2255=m
+CPTCFG_USB_SI470X=m
+CPTCFG_USB_SI4713=m
+CPTCFG_USB_STKWEBCAM=m
+CPTCFG_USB_STV06XX=m
+CPTCFG_USB_VIDEO_CLASS=m
+CPTCFG_USB_ZR364XX=m
+CPTCFG_V4L2_MEM2MEM_DEV=m
+CPTCFG_V4L_MEM2MEM_DRIVERS=y
+CPTCFG_V4L_PLATFORM_DRIVERS=y
+CPTCFG_VIDEOBUF2_CORE=m
+CPTCFG_VIDEOBUF2_DMA_CONTIG=m
+CPTCFG_VIDEOBUF2_DMA_SG=m
+CPTCFG_VIDEOBUF2_MEMOPS=m
+CPTCFG_VIDEOBUF2_VMALLOC=m
+CPTCFG_VIDEOBUF_DMA_CONTIG=m
+CPTCFG_VIDEOBUF_DMA_SG=m
+CPTCFG_VIDEOBUF_DVB=m
+CPTCFG_VIDEOBUF_GEN=m
+CPTCFG_VIDEOBUF_VMALLOC=m
+CPTCFG_VIDEO_AD9389B=m
+CPTCFG_VIDEO_ADP1653=m
+CPTCFG_VIDEO_ADV7170=m
+CPTCFG_VIDEO_ADV7175=m
+CPTCFG_VIDEO_ADV7180=m
+CPTCFG_VIDEO_ADV7183=m
+CPTCFG_VIDEO_ADV7343=m
+CPTCFG_VIDEO_ADV7393=m
+CPTCFG_VIDEO_ADV7604=m
+CPTCFG_VIDEO_AK881X=m
+CPTCFG_VIDEO_APTINA_PLL=m
+CPTCFG_VIDEO_AS3645A=m
+CPTCFG_VIDEO_ATMEL_ISI=m
+CPTCFG_VIDEO_AU0828=m
+CPTCFG_VIDEO_AU0828_RC=y
+CPTCFG_VIDEO_BLACKFIN_CAPTURE=m
+CPTCFG_VIDEO_BLACKFIN_PPI=m
+CPTCFG_VIDEO_BT819=m
+CPTCFG_VIDEO_BT848=m
+CPTCFG_VIDEO_BT856=m
+CPTCFG_VIDEO_BT866=m
+CPTCFG_VIDEO_BTCX=m
+CPTCFG_VIDEO_BWQCAM=m
+CPTCFG_VIDEO_CAFE_CCIC=m
+CPTCFG_VIDEO_CODA=m
+CPTCFG_VIDEO_CPIA2=m
+CPTCFG_VIDEO_CQCAM=m
+CPTCFG_VIDEO_CS5345=m
+CPTCFG_VIDEO_CS53L32A=m
+CPTCFG_VIDEO_CX18=m
+CPTCFG_VIDEO_CX18_ALSA=m
+CPTCFG_VIDEO_CX231XX=m
+CPTCFG_VIDEO_CX231XX_ALSA=m
+CPTCFG_VIDEO_CX231XX_DVB=m
+CPTCFG_VIDEO_CX231XX_RC=y
+CPTCFG_VIDEO_CX2341X=m
+CPTCFG_VIDEO_CX23885=m
+CPTCFG_VIDEO_CX25821=m
+CPTCFG_VIDEO_CX25821_ALSA=m
+CPTCFG_VIDEO_CX25840=m
+CPTCFG_VIDEO_CX88=m
+CPTCFG_VIDEO_CX88_ALSA=m
+CPTCFG_VIDEO_CX88_BLACKBIRD=m
+CPTCFG_VIDEO_CX88_DVB=m
+CPTCFG_VIDEO_CX88_MPEG=m
+CPTCFG_VIDEO_CX88_VP3054=m
+CPTCFG_VIDEO_DAVINCI_VPBE_DISPLAY=m
+CPTCFG_VIDEO_DAVINCI_VPIF_CAPTURE=m
+CPTCFG_VIDEO_DAVINCI_VPIF_DISPLAY=m
+CPTCFG_VIDEO_DEV=m
+CPTCFG_VIDEO_DM355_CCDC=m
+CPTCFG_VIDEO_DM6446_CCDC=m
+CPTCFG_VIDEO_EM28XX=m
+CPTCFG_VIDEO_EM28XX_ALSA=m
+CPTCFG_VIDEO_EM28XX_DVB=m
+CPTCFG_VIDEO_EM28XX_RC=m
+CPTCFG_VIDEO_EM28XX_V4L2=m
+CPTCFG_VIDEO_EXYNOS_FIMC_LITE=m
+CPTCFG_VIDEO_FB_IVTV=m
+CPTCFG_VIDEO_GO7007=m
+CPTCFG_VIDEO_GO7007_USB=m
+CPTCFG_VIDEO_GO7007_USB_S2250_BOARD=m
+CPTCFG_VIDEO_HDPVR=m
+CPTCFG_VIDEO_HEXIUM_GEMINI=m
+CPTCFG_VIDEO_HEXIUM_ORION=m
+CPTCFG_VIDEO_IR_I2C=m
+CPTCFG_VIDEO_IVTV=m
+CPTCFG_VIDEO_IVTV_ALSA=m
+CPTCFG_VIDEO_KS0127=m
+CPTCFG_VIDEO_M32R_AR_M64278=m
+CPTCFG_VIDEO_M52790=m
+CPTCFG_VIDEO_M5MOLS=m
+CPTCFG_VIDEO_MEM2MEM_DEINTERLACE=m
+CPTCFG_VIDEO_MEM2MEM_TESTDEV=m
+CPTCFG_VIDEO_MEYE=m
+CPTCFG_VIDEO_MMP_CAMERA=m
+CPTCFG_VIDEO_MSP3400=m
+CPTCFG_VIDEO_MT9M032=m
+CPTCFG_VIDEO_MT9P031=m
+CPTCFG_VIDEO_MT9T001=m
+CPTCFG_VIDEO_MT9V011=m
+CPTCFG_VIDEO_MT9V032=m
+CPTCFG_VIDEO_MX2=m
+CPTCFG_VIDEO_MX2_EMMAPRP=m
+CPTCFG_VIDEO_MX3=m
+CPTCFG_VIDEO_MXB=m
+CPTCFG_VIDEO_NOON010PC30=m
+CPTCFG_VIDEO_OMAP1=m
+CPTCFG_VIDEO_OMAP2_VOUT=m
+CPTCFG_VIDEO_OMAP3=m
+CPTCFG_VIDEO_OV7640=m
+CPTCFG_VIDEO_OV7670=m
+CPTCFG_VIDEO_OV9650=m
+CPTCFG_VIDEO_PMS=m
+CPTCFG_VIDEO_PVRUSB2=m
+CPTCFG_VIDEO_PXA27x=m
+CPTCFG_VIDEO_S3C_CAMIF=m
+CPTCFG_VIDEO_S5C73M3=m
+CPTCFG_VIDEO_S5K4ECGX=m
+CPTCFG_VIDEO_S5K6AA=m
+CPTCFG_VIDEO_S5P_FIMC=m
+CPTCFG_VIDEO_S5P_MIPI_CSIS=m
+CPTCFG_VIDEO_SAA6588=m
+CPTCFG_VIDEO_SAA7110=m
+CPTCFG_VIDEO_SAA711X=m
+CPTCFG_VIDEO_SAA7127=m
+CPTCFG_VIDEO_SAA7134=m
+CPTCFG_VIDEO_SAA7134_ALSA=m
+CPTCFG_VIDEO_SAA7134_DVB=m
+CPTCFG_VIDEO_SAA7134_GO7007=m
+CPTCFG_VIDEO_SAA7134_RC=y
+CPTCFG_VIDEO_SAA7146=m
+CPTCFG_VIDEO_SAA7146_VV=m
+CPTCFG_VIDEO_SAA7164=m
+CPTCFG_VIDEO_SAA717X=m
+CPTCFG_VIDEO_SAA7185=m
+CPTCFG_VIDEO_SAA7191=m
+CPTCFG_VIDEO_SAMSUNG_EXYNOS_GSC=m
+CPTCFG_VIDEO_SAMSUNG_S5P_G2D=m
+CPTCFG_VIDEO_SAMSUNG_S5P_HDMI=m
+CPTCFG_VIDEO_SAMSUNG_S5P_HDMIPHY=m
+CPTCFG_VIDEO_SAMSUNG_S5P_JPEG=m
+CPTCFG_VIDEO_SAMSUNG_S5P_MFC=m
+CPTCFG_VIDEO_SAMSUNG_S5P_MIXER=m
+CPTCFG_VIDEO_SAMSUNG_S5P_SDO=m
+CPTCFG_VIDEO_SAMSUNG_S5P_SII9234=m
+CPTCFG_VIDEO_SAMSUNG_S5P_TV=y
+CPTCFG_VIDEO_SH_MOBILE_CEU=m
+CPTCFG_VIDEO_SH_MOBILE_CSI2=m
+CPTCFG_VIDEO_SH_VEU=m
+CPTCFG_VIDEO_SH_VOU=m
+CPTCFG_VIDEO_SMIAPP=m
+CPTCFG_VIDEO_SMIAPP_PLL=m
+CPTCFG_VIDEO_SOLO6X10=m
+CPTCFG_VIDEO_SONY_BTF_MPX=m
+CPTCFG_VIDEO_SR030PC30=m
+CPTCFG_VIDEO_STK1160=m
+CPTCFG_VIDEO_STK1160_AC97=y
+CPTCFG_VIDEO_STK1160_COMMON=m
+CPTCFG_VIDEO_TDA7432=m
+CPTCFG_VIDEO_TDA9840=m
+CPTCFG_VIDEO_TEA6415C=m
+CPTCFG_VIDEO_TEA6420=m
+CPTCFG_VIDEO_THS7303=m
+CPTCFG_VIDEO_TIMBERDALE=m
+CPTCFG_VIDEO_TLG2300=m
+CPTCFG_VIDEO_TLV320AIC23B=m
+CPTCFG_VIDEO_TM6000=m
+CPTCFG_VIDEO_TM6000_ALSA=m
+CPTCFG_VIDEO_TM6000_DVB=m
+CPTCFG_VIDEO_TUNER=m
+CPTCFG_VIDEO_TVAUDIO=m
+CPTCFG_VIDEO_TVEEPROM=m
+CPTCFG_VIDEO_TVP514X=m
+CPTCFG_VIDEO_TVP5150=m
+CPTCFG_VIDEO_TVP7002=m
+CPTCFG_VIDEO_TW2804=m
+CPTCFG_VIDEO_TW68=m
+CPTCFG_VIDEO_TW9903=m
+CPTCFG_VIDEO_TW9906=m
+CPTCFG_VIDEO_UDA1342=m
+CPTCFG_VIDEO_UPD64031A=m
+CPTCFG_VIDEO_UPD64083=m
+CPTCFG_VIDEO_USBTV=m
+CPTCFG_VIDEO_USBVISION=m
+CPTCFG_VIDEO_V4L2=m
+CPTCFG_VIDEO_V4L2_SUBDEV_API=y
+CPTCFG_VIDEO_VIA_CAMERA=m
+CPTCFG_VIDEO_VINO=m
+CPTCFG_VIDEO_VIU=m
+CPTCFG_VIDEO_VP27SMPX=m
+CPTCFG_VIDEO_VPX3220=m
+CPTCFG_VIDEO_VS6624=m
+CPTCFG_VIDEO_W9966=m
+CPTCFG_VIDEO_WM8739=m
+CPTCFG_VIDEO_WM8775=m
+CPTCFG_VIDEO_ZORAN=m
+CPTCFG_VIDEO_ZORAN_AVS6EYES=m
+CPTCFG_VIDEO_ZORAN_BUZ=m
+CPTCFG_VIDEO_ZORAN_DC10=m
+CPTCFG_VIDEO_ZORAN_DC30=m
+CPTCFG_VIDEO_ZORAN_LML33=m
+CPTCFG_VIDEO_ZORAN_LML33R10=m
+CPTCFG_VIDEO_ZORAN_ZR36060=m
diff --git a/drivers/bcma/Kconfig b/drivers/bcma/Kconfig
index b9686bb..c5180b8 100644
--- a/drivers/bcma/Kconfig
+++ b/drivers/bcma/Kconfig
@@ -36,7 +36,7 @@
PCI core hostmode operation (external PCI bus).
config BCMA_HOST_SOC
- depends on !KERNEL_3_7
+ depends on !BACKPORT_KERNEL_3_7
bool "Support for BCMA in a SoC"
depends on BCMA
help
@@ -47,7 +47,7 @@
If unsure, say N
config BCMA_DRIVER_MIPS
- depends on !KERNEL_3_3
+ depends on !BACKPORT_KERNEL_3_3
bool "BCMA Broadcom MIPS core driver"
depends on BCMA && MIPS
help
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h
index cb91beb..16fc849 100644
--- a/drivers/bcma/bcma_private.h
+++ b/drivers/bcma/bcma_private.h
@@ -24,7 +24,6 @@
/* main.c */
bool bcma_wait_value(struct bcma_device *core, u16 reg, u32 mask, u32 value,
int timeout);
-void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core);
int bcma_bus_register(struct bcma_bus *bus);
void bcma_bus_unregister(struct bcma_bus *bus);
int __init bcma_bus_early_register(struct bcma_bus *bus,
diff --git a/drivers/bcma/driver_chipcommon.c b/drivers/bcma/driver_chipcommon.c
index 368c24c..9ff6cdf 100644
--- a/drivers/bcma/driver_chipcommon.c
+++ b/drivers/bcma/driver_chipcommon.c
@@ -339,7 +339,7 @@
return;
}
- irq = bcma_core_irq(cc->core, 0);
+ irq = bcma_core_irq(cc->core);
/* Determine the registers of the UARTs */
cc->nr_serial_ports = (cc->capabilities & BCMA_CC_CAP_NRUART);
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c
index 598a6cd..706b9ae 100644
--- a/drivers/bcma/driver_gpio.c
+++ b/drivers/bcma/driver_gpio.c
@@ -152,7 +152,7 @@
handle_simple_irq);
}
- hwirq = bcma_core_irq(cc->core, 0);
+ hwirq = bcma_core_irq(cc->core);
err = request_irq(hwirq, bcma_gpio_irq_handler, IRQF_SHARED, "gpio",
cc);
if (err)
@@ -183,7 +183,7 @@
return;
bcma_cc_mask32(cc, BCMA_CC_IRQMASK, ~BCMA_CC_IRQ_GPIO);
- free_irq(bcma_core_irq(cc->core, 0), cc);
+ free_irq(bcma_core_irq(cc->core), cc);
for (gpio = 0; gpio < chip->ngpio; gpio++) {
int irq = irq_find_mapping(cc->irq_domain, gpio);
diff --git a/drivers/bcma/driver_mips.c b/drivers/bcma/driver_mips.c
index 04faf6d..004d6aa 100644
--- a/drivers/bcma/driver_mips.c
+++ b/drivers/bcma/driver_mips.c
@@ -20,9 +20,6 @@
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/time.h>
-#ifdef CONFIG_BCM47XX
-#include <bcm47xx_nvram.h>
-#endif
enum bcma_boot_dev {
BCMA_BOOT_DEV_UNK = 0,
@@ -118,7 +115,7 @@
* If disabled, 5 is returned.
* If not supported, 6 is returned.
*/
-unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+static unsigned int bcma_core_mips_irq(struct bcma_device *dev)
{
struct bcma_device *mdev = dev->bus->drv_mips.core;
u32 irqflag;
@@ -136,6 +133,13 @@
return 5;
}
+unsigned int bcma_core_irq(struct bcma_device *dev)
+{
+ unsigned int mips_irq = bcma_core_mips_irq(dev);
+ return mips_irq <= 4 ? mips_irq + 2 : 0;
+}
+EXPORT_SYMBOL(bcma_core_irq);
+
static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
{
unsigned int oldirq = bcma_core_mips_irq(dev);
@@ -319,16 +323,10 @@
switch (boot_dev) {
case BCMA_BOOT_DEV_PARALLEL:
case BCMA_BOOT_DEV_SERIAL:
-#ifdef CONFIG_BCM47XX
- bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH2,
- BCMA_SOC_FLASH2_SZ);
-#endif
+ /* TODO: Init NVRAM using BCMA_SOC_FLASH2 window */
break;
case BCMA_BOOT_DEV_NAND:
-#ifdef CONFIG_BCM47XX
- bcm47xx_nvram_init_from_mem(BCMA_SOC_FLASH1,
- BCMA_SOC_FLASH1_SZ);
-#endif
+ /* TODO: Init NVRAM using BCMA_SOC_FLASH1 window */
break;
default:
break;
@@ -425,7 +423,7 @@
break;
default:
list_for_each_entry(core, &bus->cores, list) {
- core->irq = bcma_core_irq(core, 0);
+ core->irq = bcma_core_irq(core);
}
bcma_err(bus,
"Unknown device (0x%x) found, can not configure IRQs\n",
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c
index c8a6b74..c3d7b03 100644
--- a/drivers/bcma/driver_pci_host.c
+++ b/drivers/bcma/driver_pci_host.c
@@ -593,7 +593,7 @@
pr_info("PCI: Fixing up device %s\n", pci_name(dev));
/* Fix up interrupt lines */
- dev->irq = bcma_core_irq(pc_host->pdev->core, 0);
+ dev->irq = bcma_core_irq(pc_host->pdev->core);
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq);
readrq = pcie_get_readrq(dev);
@@ -617,6 +617,6 @@
pc_host = container_of(dev->bus->ops, struct bcma_drv_pci_host,
pci_ops);
- return bcma_core_irq(pc_host->pdev->core, 0);
+ return bcma_core_irq(pc_host->pdev->core);
}
EXPORT_SYMBOL(bcma_core_pci_pcibios_map_irq);
diff --git a/drivers/bcma/host_pci.c b/drivers/bcma/host_pci.c
index 34b40bb..6a76e68 100644
--- a/drivers/bcma/host_pci.c
+++ b/drivers/bcma/host_pci.c
@@ -275,7 +275,7 @@
static const struct pci_device_id bcma_pci_bridge_tbl[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x0576) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4313) },
- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) }, /* 0xa8d8 */
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43224) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4331) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4353) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4357) },
@@ -285,8 +285,7 @@
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43a9) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x43aa) },
{ PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 0x4727) },
- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, /* 0xa8db, BCM43217 (sic!) */
- { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43228) }, /* 0xa8dc */
+ { PCI_DEVICE(PCI_VENDOR_ID_BROADCOM, 43227) }, /* 0xA8DB */
{ 0, },
};
MODULE_DEVICE_TABLE(pci, bcma_pci_bridge_tbl);
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c
index 17fcf56..5379919 100644
--- a/drivers/bcma/main.c
+++ b/drivers/bcma/main.c
@@ -11,7 +11,6 @@
#include <linux/bcma/bcma.h>
#include <linux/slab.h>
#include <linux/of_address.h>
-#include <linux/of_irq.h>
MODULE_DESCRIPTION("Broadcom's specific AMBA driver");
MODULE_LICENSE("GPL");
@@ -142,7 +141,7 @@
return false;
}
-#if defined(CONFIG_OF) && defined(CONFIG_OF_ADDRESS)
+#ifdef CONFIG_OF
static struct device_node *bcma_of_find_child_device(struct platform_device *parent,
struct bcma_device *core)
{
@@ -163,46 +162,6 @@
return NULL;
}
-static int bcma_of_irq_parse(struct platform_device *parent,
- struct bcma_device *core,
- struct of_phandle_args *out_irq, int num)
-{
- __be32 laddr[1];
- int rc;
-
- if (core->dev.of_node) {
- rc = of_irq_parse_one(core->dev.of_node, num, out_irq);
- if (!rc)
- return rc;
- }
-
- out_irq->np = parent->dev.of_node;
- out_irq->args_count = 1;
- out_irq->args[0] = num;
-
- laddr[0] = cpu_to_be32(core->addr);
- return of_irq_parse_raw(laddr, out_irq);
-}
-
-static unsigned int bcma_of_get_irq(struct platform_device *parent,
- struct bcma_device *core, int num)
-{
- struct of_phandle_args out_irq;
- int ret;
-
- if (!parent || !parent->dev.of_node)
- return 0;
-
- ret = bcma_of_irq_parse(parent, core, &out_irq, num);
- if (ret) {
- bcma_debug(core->bus, "bcma_of_get_irq() failed with rc=%d\n",
- ret);
- return 0;
- }
-
- return irq_create_of_mapping(&out_irq);
-}
-
static void bcma_of_fill_device(struct platform_device *parent,
struct bcma_device *core)
{
@@ -211,47 +170,18 @@
node = bcma_of_find_child_device(parent, core);
if (node)
core->dev.of_node = node;
-
- core->irq = bcma_of_get_irq(parent, core, 0);
}
#else
static void bcma_of_fill_device(struct platform_device *parent,
struct bcma_device *core)
{
}
-static inline unsigned int bcma_of_get_irq(struct platform_device *parent,
- struct bcma_device *core, int num)
-{
- return 0;
-}
#endif /* CONFIG_OF */
-unsigned int bcma_core_irq(struct bcma_device *core, int num)
+static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
{
- struct bcma_bus *bus = core->bus;
- unsigned int mips_irq;
+ int err;
- switch (bus->hosttype) {
- case BCMA_HOSTTYPE_PCI:
- return bus->host_pci->irq;
- case BCMA_HOSTTYPE_SOC:
- if (bus->drv_mips.core && num == 0) {
- mips_irq = bcma_core_mips_irq(core);
- return mips_irq <= 4 ? mips_irq + 2 : 0;
- }
- if (bus->host_pdev)
- return bcma_of_get_irq(bus->host_pdev, core, num);
- return 0;
- case BCMA_HOSTTYPE_SDIO:
- return 0;
- }
-
- return 0;
-}
-EXPORT_SYMBOL(bcma_core_irq);
-
-void bcma_prepare_core(struct bcma_bus *bus, struct bcma_device *core)
-{
core->dev.release = bcma_release_core_dev;
core->dev.bus = &bcma_bus_type;
dev_set_name(&core->dev, "bcma%d:%d", bus->num, core->core_index);
@@ -275,11 +205,6 @@
case BCMA_HOSTTYPE_SDIO:
break;
}
-}
-
-static void bcma_register_core(struct bcma_bus *bus, struct bcma_device *core)
-{
- int err;
err = device_register(&core->dev);
if (err) {
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c
index 9175207..14b5656 100644
--- a/drivers/bcma/scan.c
+++ b/drivers/bcma/scan.c
@@ -505,7 +505,6 @@
bus->nr_cores++;
other_core = bcma_find_core_reverse(bus, core->id.id);
core->core_unit = (other_core == NULL) ? 0 : other_core->core_unit + 1;
- bcma_prepare_core(bus, core);
bcma_info(bus, "Core %d found: %s (manuf 0x%03X, id 0x%03X, rev 0x%02X, class 0x%X)\n",
core->core_index, bcma_device_name(&core->id),
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index c30744e..dcc4d71 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -223,7 +223,6 @@
depends on m
depends on BT_MRVL && MMC
depends on FW_LOADER
- select BPAUTO_WANT_DEV_COREDUMP
help
The driver for Marvell Bluetooth chipsets with SDIO interface.
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index 544feb3..1723b6e 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -79,7 +79,6 @@
{ USB_DEVICE(0x0489, 0xe057) },
{ USB_DEVICE(0x0489, 0xe056) },
{ USB_DEVICE(0x0489, 0xe05f) },
- { USB_DEVICE(0x0489, 0xe078) },
{ USB_DEVICE(0x04c5, 0x1330) },
{ USB_DEVICE(0x04CA, 0x3004) },
{ USB_DEVICE(0x04CA, 0x3005) },
@@ -87,7 +86,6 @@
{ USB_DEVICE(0x04CA, 0x3007) },
{ USB_DEVICE(0x04CA, 0x3008) },
{ USB_DEVICE(0x04CA, 0x300b) },
- { USB_DEVICE(0x04CA, 0x3010) },
{ USB_DEVICE(0x0930, 0x0219) },
{ USB_DEVICE(0x0930, 0x0220) },
{ USB_DEVICE(0x0930, 0x0227) },
@@ -107,7 +105,6 @@
{ USB_DEVICE(0x13d3, 0x3375) },
{ USB_DEVICE(0x13d3, 0x3393) },
{ USB_DEVICE(0x13d3, 0x3402) },
- { USB_DEVICE(0x13d3, 0x3408) },
{ USB_DEVICE(0x13d3, 0x3432) },
/* Atheros AR5BBU12 with sflash firmware */
@@ -133,7 +130,6 @@
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
@@ -141,7 +137,6 @@
{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
@@ -161,7 +156,6 @@
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU22 with sflash firmware */
diff --git a/drivers/bluetooth/btmrvl_debugfs.c b/drivers/bluetooth/btmrvl_debugfs.c
index 1828ed8..023d35e 100644
--- a/drivers/bluetooth/btmrvl_debugfs.c
+++ b/drivers/bluetooth/btmrvl_debugfs.c
@@ -167,35 +167,6 @@
.llseek = default_llseek,
};
-static ssize_t btmrvl_fwdump_write(struct file *file, const char __user *ubuf,
- size_t count, loff_t *ppos)
-{
- struct btmrvl_private *priv = file->private_data;
- char buf[16];
- bool result;
-
- memset(buf, 0, sizeof(buf));
-
- if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
- return -EFAULT;
-
- if (strtobool(buf, &result))
- return -EINVAL;
-
- if (!result)
- return -EINVAL;
-
- btmrvl_firmware_dump(priv);
-
- return count;
-}
-
-static const struct file_operations btmrvl_fwdump_fops = {
- .write = btmrvl_fwdump_write,
- .open = simple_open,
- .llseek = default_llseek,
-};
-
void btmrvl_debugfs_init(struct hci_dev *hdev)
{
struct btmrvl_private *priv = hci_get_drvdata(hdev);
@@ -226,8 +197,6 @@
priv, &btmrvl_hscmd_fops);
debugfs_create_file("hscfgcmd", 0644, dbg->config_dir,
priv, &btmrvl_hscfgcmd_fops);
- debugfs_create_file("fw_dump", 0200, dbg->config_dir,
- priv, &btmrvl_fwdump_fops);
dbg->status_dir = debugfs_create_dir("status", hdev->debugfs);
debugfs_create_u8("curpsmode", 0444, dbg->status_dir,
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 330f8f8..38ad662 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -32,24 +32,6 @@
/* Time to wait for command response in millisecond */
#define WAIT_UNTIL_CMD_RESP 5000
-enum rdwr_status {
- RDWR_STATUS_SUCCESS = 0,
- RDWR_STATUS_FAILURE = 1,
- RDWR_STATUS_DONE = 2
-};
-
-#define FW_DUMP_MAX_NAME_LEN 8
-#define FW_DUMP_HOST_READY 0xEE
-#define FW_DUMP_DONE 0xFF
-#define FW_DUMP_READ_DONE 0xFE
-
-struct memory_type_mapping {
- u8 mem_name[FW_DUMP_MAX_NAME_LEN];
- u8 *mem_ptr;
- u32 mem_size;
- u8 done_flag;
-};
-
struct btmrvl_thread {
struct task_struct *task;
wait_queue_head_t wait_q;
@@ -99,7 +81,6 @@
u8 *payload, u16 nb);
int (*hw_wakeup_firmware) (struct btmrvl_private *priv);
int (*hw_process_int_status) (struct btmrvl_private *priv);
- void (*firmware_dump)(struct btmrvl_private *priv);
spinlock_t driver_lock; /* spinlock used by driver */
#ifdef CONFIG_DEBUG_FS
void *debugfs_data;
@@ -170,7 +151,6 @@
int btmrvl_enable_ps(struct btmrvl_private *priv);
int btmrvl_prepare_command(struct btmrvl_private *priv);
int btmrvl_enable_hs(struct btmrvl_private *priv);
-void btmrvl_firmware_dump(struct btmrvl_private *priv);
#ifdef CONFIG_DEBUG_FS
void btmrvl_debugfs_init(struct hci_dev *hdev);
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 30939c9..1d7db20 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -22,7 +22,6 @@
#include <linux/of.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
-#include <linux/mmc/sdio_func.h>
#include "btmrvl_drv.h"
#include "btmrvl_sdio.h"
@@ -42,11 +41,6 @@
priv->adapter->int_count++;
- if (priv->adapter->hs_state == HS_ACTIVATED) {
- BT_DBG("BT: HS DEACTIVATED in ISR!");
- priv->adapter->hs_state = HS_DEACTIVATED;
- }
-
wake_up_interruptible(&priv->main_thread.wait_q);
}
EXPORT_SYMBOL_GPL(btmrvl_interrupt);
@@ -215,7 +209,7 @@
ret = btmrvl_send_sync_cmd(priv, BT_CMD_MODULE_CFG_REQ, &subcmd, 1);
if (ret)
- BT_ERR("module_cfg_cmd(%x) failed", subcmd);
+ BT_ERR("module_cfg_cmd(%x) failed\n", subcmd);
return ret;
}
@@ -251,7 +245,7 @@
ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_CONFIG, param, 2);
if (ret)
- BT_ERR("HSCFG command failed");
+ BT_ERR("HSCFG command failed\n");
return ret;
}
@@ -269,7 +263,7 @@
ret = btmrvl_send_sync_cmd(priv, BT_CMD_AUTO_SLEEP_MODE, ¶m, 1);
if (ret)
- BT_ERR("PSMODE command failed");
+ BT_ERR("PSMODE command failed\n");
return 0;
}
@@ -282,7 +276,7 @@
ret = btmrvl_send_sync_cmd(priv, BT_CMD_HOST_SLEEP_ENABLE, NULL, 0);
if (ret) {
- BT_ERR("Host sleep enable command failed");
+ BT_ERR("Host sleep enable command failed\n");
return ret;
}
@@ -329,19 +323,12 @@
} else {
ret = priv->hw_wakeup_firmware(priv);
priv->adapter->hs_state = HS_DEACTIVATED;
- BT_DBG("BT: HS DEACTIVATED due to host activity!");
}
}
return ret;
}
-void btmrvl_firmware_dump(struct btmrvl_private *priv)
-{
- if (priv->firmware_dump)
- priv->firmware_dump(priv);
-}
-
static int btmrvl_tx_pkt(struct btmrvl_private *priv, struct sk_buff *skb)
{
int ret = 0;
@@ -500,36 +487,34 @@
ret = btmrvl_send_sync_cmd(priv, BT_CMD_LOAD_CONFIG_DATA, data,
BT_CAL_HDR_LEN + len);
if (ret)
- BT_ERR("Failed to download caibration data");
+ BT_ERR("Failed to download caibration data\n");
return 0;
}
-static int btmrvl_check_device_tree(struct btmrvl_private *priv)
+static int btmrvl_cal_data_dt(struct btmrvl_private *priv)
{
struct device_node *dt_node;
u8 cal_data[BT_CAL_HDR_LEN + BT_CAL_DATA_SIZE];
+ const char name[] = "btmrvl_caldata";
+ const char property[] = "btmrvl,caldata";
int ret;
- u32 val;
- for_each_compatible_node(dt_node, NULL, "btmrvl,cfgdata") {
- ret = of_property_read_u32(dt_node, "btmrvl,gpio-gap", &val);
- if (!ret)
- priv->btmrvl_dev.gpio_gap = val;
+ dt_node = of_find_node_by_name(NULL, name);
+ if (!dt_node)
+ return -ENODEV;
- ret = of_property_read_u8_array(dt_node, "btmrvl,cal-data",
- cal_data + BT_CAL_HDR_LEN,
- BT_CAL_DATA_SIZE);
- if (ret)
- return ret;
+ ret = of_property_read_u8_array(dt_node, property,
+ cal_data + BT_CAL_HDR_LEN,
+ BT_CAL_DATA_SIZE);
+ if (ret)
+ return ret;
- BT_DBG("Use cal data from device tree");
- ret = btmrvl_download_cal_data(priv, cal_data,
- BT_CAL_DATA_SIZE);
- if (ret) {
- BT_ERR("Fail to download calibrate data");
- return ret;
- }
+ BT_DBG("Use cal data from device tree");
+ ret = btmrvl_download_cal_data(priv, cal_data, BT_CAL_DATA_SIZE);
+ if (ret) {
+ BT_ERR("Fail to download calibrate data");
+ return ret;
}
return 0;
@@ -541,15 +526,14 @@
btmrvl_send_module_cfg_cmd(priv, MODULE_BRINGUP_REQ);
- priv->btmrvl_dev.gpio_gap = 0xffff;
-
- btmrvl_check_device_tree(priv);
+ btmrvl_cal_data_dt(priv);
btmrvl_pscan_window_reporting(priv, 0x01);
priv->btmrvl_dev.psmode = 1;
btmrvl_enable_ps(priv);
+ priv->btmrvl_dev.gpio_gap = 0xffff;
btmrvl_send_hscfg_cmd(priv);
return 0;
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 0057c0b..550bce0 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -24,7 +24,6 @@
#include <linux/mmc/sdio_ids.h>
#include <linux/mmc/sdio_func.h>
#include <linux/module.h>
-#include <linux/devcoredump.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
@@ -34,24 +33,6 @@
#define VERSION "1.0"
-static struct memory_type_mapping mem_type_mapping_tbl[] = {
- {"ITCM", NULL, 0, 0xF0},
- {"DTCM", NULL, 0, 0xF1},
- {"SQRAM", NULL, 0, 0xF2},
- {"APU", NULL, 0, 0xF3},
- {"CIU", NULL, 0, 0xF4},
- {"ICU", NULL, 0, 0xF5},
- {"MAC", NULL, 0, 0xF6},
- {"EXT7", NULL, 0, 0xF7},
- {"EXT8", NULL, 0, 0xF8},
- {"EXT9", NULL, 0, 0xF9},
- {"EXT10", NULL, 0, 0xFA},
- {"EXT11", NULL, 0, 0xFB},
- {"EXT12", NULL, 0, 0xFC},
- {"EXT13", NULL, 0, 0xFD},
- {"EXTLAST", NULL, 0, 0xFE},
-};
-
/* The btmrvl_sdio_remove() callback function is called
* when user removes this module from kernel space or ejects
* the card from the slot. The driver handles these 2 cases
@@ -141,9 +122,6 @@
.int_read_to_clear = true,
.host_int_rsr = 0x01,
.card_misc_cfg = 0xcc,
- .fw_dump_ctrl = 0xe2,
- .fw_dump_start = 0xe3,
- .fw_dump_end = 0xea,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
@@ -152,7 +130,6 @@
.reg = &btmrvl_reg_8688,
.support_pscan_win_report = false,
.sd_blksz_fw_dl = 64,
- .supports_fw_dump = false,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
@@ -161,7 +138,6 @@
.reg = &btmrvl_reg_87xx,
.support_pscan_win_report = false,
.sd_blksz_fw_dl = 256,
- .supports_fw_dump = false,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
@@ -170,7 +146,6 @@
.reg = &btmrvl_reg_87xx,
.support_pscan_win_report = false,
.sd_blksz_fw_dl = 256,
- .supports_fw_dump = false,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8887 = {
@@ -179,7 +154,6 @@
.reg = &btmrvl_reg_8887,
.support_pscan_win_report = true,
.sd_blksz_fw_dl = 256,
- .supports_fw_dump = false,
};
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
@@ -188,7 +162,6 @@
.reg = &btmrvl_reg_8897,
.support_pscan_win_report = true,
.sd_blksz_fw_dl = 256,
- .supports_fw_dump = true,
};
static const struct sdio_device_id btmrvl_sdio_ids[] = {
@@ -791,8 +764,8 @@
card = sdio_get_drvdata(func);
if (!card || !card->priv) {
- BT_ERR("sbi_interrupt(%p) card or priv is NULL, card=%p",
- func, card);
+ BT_ERR("sbi_interrupt(%p) card or priv is "
+ "NULL, card=%p\n", func, card);
return;
}
@@ -1107,277 +1080,6 @@
return ret;
}
-static void btmrvl_sdio_dump_regs(struct btmrvl_private *priv)
-{
- struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
- int ret = 0;
- unsigned int reg, reg_start, reg_end;
- char buf[256], *ptr;
- u8 loop, func, data;
- int MAX_LOOP = 2;
-
- btmrvl_sdio_wakeup_fw(priv);
- sdio_claim_host(card->func);
-
- for (loop = 0; loop < MAX_LOOP; loop++) {
- memset(buf, 0, sizeof(buf));
- ptr = buf;
-
- if (loop == 0) {
- /* Read the registers of SDIO function0 */
- func = loop;
- reg_start = 0;
- reg_end = 9;
- } else {
- func = 2;
- reg_start = 0;
- reg_end = 0x09;
- }
-
- ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ",
- func, reg_start, reg_end);
- for (reg = reg_start; reg <= reg_end; reg++) {
- if (func == 0)
- data = sdio_f0_readb(card->func, reg, &ret);
- else
- data = sdio_readb(card->func, reg, &ret);
-
- if (!ret) {
- ptr += sprintf(ptr, "%02x ", data);
- } else {
- ptr += sprintf(ptr, "ERR");
- break;
- }
- }
-
- BT_INFO("%s", buf);
- }
-
- sdio_release_host(card->func);
-}
-
-/* This function read/write firmware */
-static enum
-rdwr_status btmrvl_sdio_rdwr_firmware(struct btmrvl_private *priv,
- u8 doneflag)
-{
- struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
- int ret, tries;
- u8 ctrl_data = 0;
-
- sdio_writeb(card->func, FW_DUMP_HOST_READY, card->reg->fw_dump_ctrl,
- &ret);
-
- if (ret) {
- BT_ERR("SDIO write err");
- return RDWR_STATUS_FAILURE;
- }
-
- for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
- ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl,
- &ret);
-
- if (ret) {
- BT_ERR("SDIO read err");
- return RDWR_STATUS_FAILURE;
- }
-
- if (ctrl_data == FW_DUMP_DONE)
- break;
- if (doneflag && ctrl_data == doneflag)
- return RDWR_STATUS_DONE;
- if (ctrl_data != FW_DUMP_HOST_READY) {
- BT_INFO("The ctrl reg was changed, re-try again!");
- sdio_writeb(card->func, FW_DUMP_HOST_READY,
- card->reg->fw_dump_ctrl, &ret);
- if (ret) {
- BT_ERR("SDIO write err");
- return RDWR_STATUS_FAILURE;
- }
- }
- usleep_range(100, 200);
- }
-
- if (ctrl_data == FW_DUMP_HOST_READY) {
- BT_ERR("Fail to pull ctrl_data");
- return RDWR_STATUS_FAILURE;
- }
-
- return RDWR_STATUS_SUCCESS;
-}
-
-/* This function dump sdio register and memory data */
-static void btmrvl_sdio_dump_firmware(struct btmrvl_private *priv)
-{
- struct btmrvl_sdio_card *card = priv->btmrvl_dev.card;
- int ret = 0;
- unsigned int reg, reg_start, reg_end;
- enum rdwr_status stat;
- u8 *dbg_ptr, *end_ptr, *fw_dump_data, *fw_dump_ptr;
- u8 dump_num, idx, i, read_reg, doneflag = 0;
- u32 memory_size, fw_dump_len = 0;
-
- /* dump sdio register first */
- btmrvl_sdio_dump_regs(priv);
-
- if (!card->supports_fw_dump) {
- BT_ERR("Firmware dump not supported for this card!");
- return;
- }
-
- for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) {
- struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
- if (entry->mem_ptr) {
- vfree(entry->mem_ptr);
- entry->mem_ptr = NULL;
- }
- entry->mem_size = 0;
- }
-
- btmrvl_sdio_wakeup_fw(priv);
- sdio_claim_host(card->func);
-
- BT_INFO("== btmrvl firmware dump start ==");
-
- stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
- if (stat == RDWR_STATUS_FAILURE)
- goto done;
-
- reg = card->reg->fw_dump_start;
- /* Read the number of the memories which will dump */
- dump_num = sdio_readb(card->func, reg, &ret);
-
- if (ret) {
- BT_ERR("SDIO read memory length err");
- goto done;
- }
-
- /* Read the length of every memory which will dump */
- for (idx = 0; idx < dump_num; idx++) {
- struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
- stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
- if (stat == RDWR_STATUS_FAILURE)
- goto done;
-
- memory_size = 0;
- reg = card->reg->fw_dump_start;
- for (i = 0; i < 4; i++) {
- read_reg = sdio_readb(card->func, reg, &ret);
- if (ret) {
- BT_ERR("SDIO read err");
- goto done;
- }
- memory_size |= (read_reg << i*8);
- reg++;
- }
-
- if (memory_size == 0) {
- BT_INFO("Firmware dump finished!");
- break;
- }
-
- BT_INFO("%s_SIZE=0x%x", entry->mem_name, memory_size);
- entry->mem_ptr = vzalloc(memory_size + 1);
- entry->mem_size = memory_size;
- if (!entry->mem_ptr) {
- BT_ERR("Vzalloc %s failed", entry->mem_name);
- goto done;
- }
-
- fw_dump_len += (strlen("========Start dump ") +
- strlen(entry->mem_name) +
- strlen("========\n") +
- (memory_size + 1) +
- strlen("\n========End dump========\n"));
-
- dbg_ptr = entry->mem_ptr;
- end_ptr = dbg_ptr + memory_size;
-
- doneflag = entry->done_flag;
- BT_INFO("Start %s output, please wait...",
- entry->mem_name);
-
- do {
- stat = btmrvl_sdio_rdwr_firmware(priv, doneflag);
- if (stat == RDWR_STATUS_FAILURE)
- goto done;
-
- reg_start = card->reg->fw_dump_start;
- reg_end = card->reg->fw_dump_end;
- for (reg = reg_start; reg <= reg_end; reg++) {
- *dbg_ptr = sdio_readb(card->func, reg, &ret);
- if (ret) {
- BT_ERR("SDIO read err");
- goto done;
- }
- if (dbg_ptr < end_ptr)
- dbg_ptr++;
- else
- BT_ERR("Allocated buffer not enough");
- }
-
- if (stat != RDWR_STATUS_DONE) {
- continue;
- } else {
- BT_INFO("%s done: size=0x%tx",
- entry->mem_name,
- dbg_ptr - entry->mem_ptr);
- break;
- }
- } while (1);
- }
-
- BT_INFO("== btmrvl firmware dump end ==");
-
-done:
- sdio_release_host(card->func);
-
- if (fw_dump_len == 0)
- return;
-
- fw_dump_data = vzalloc(fw_dump_len+1);
- if (!fw_dump_data) {
- BT_ERR("Vzalloc fw_dump_data fail!");
- return;
- }
- fw_dump_ptr = fw_dump_data;
-
- /* Dump all the memory data into single file, a userspace script will
- be used to split all the memory data to multiple files*/
- BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump start");
- for (idx = 0; idx < dump_num; idx++) {
- struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx];
-
- if (entry->mem_ptr) {
- strcpy(fw_dump_ptr, "========Start dump ");
- fw_dump_ptr += strlen("========Start dump ");
-
- strcpy(fw_dump_ptr, entry->mem_name);
- fw_dump_ptr += strlen(entry->mem_name);
-
- strcpy(fw_dump_ptr, "========\n");
- fw_dump_ptr += strlen("========\n");
-
- memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size);
- fw_dump_ptr += entry->mem_size;
-
- strcpy(fw_dump_ptr, "\n========End dump========\n");
- fw_dump_ptr += strlen("\n========End dump========\n");
-
- vfree(mem_type_mapping_tbl[idx].mem_ptr);
- mem_type_mapping_tbl[idx].mem_ptr = NULL;
- }
- }
-
- /* fw_dump_data will be free in device coredump release function
- after 5 min*/
- dev_coredumpv(&priv->btmrvl_dev.hcidev->dev, fw_dump_data,
- fw_dump_len, GFP_KERNEL);
- BT_INFO("== btmrvl firmware dump to /sys/class/devcoredump end");
-}
-
static int btmrvl_sdio_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
@@ -1401,7 +1103,6 @@
card->reg = data->reg;
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
card->support_pscan_win_report = data->support_pscan_win_report;
- card->supports_fw_dump = data->supports_fw_dump;
}
if (btmrvl_sdio_register_dev(card) < 0) {
@@ -1433,7 +1134,6 @@
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
priv->hw_wakeup_firmware = btmrvl_sdio_wakeup_fw;
priv->hw_process_int_status = btmrvl_sdio_process_int_status;
- priv->firmware_dump = btmrvl_sdio_dump_firmware;
if (btmrvl_register_hdev(priv)) {
BT_ERR("Register hdev failed!");
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
index 1a3bd06..453559f 100644
--- a/drivers/bluetooth/btmrvl_sdio.h
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -81,9 +81,6 @@
bool int_read_to_clear;
u8 host_int_rsr;
u8 card_misc_cfg;
- u8 fw_dump_ctrl;
- u8 fw_dump_start;
- u8 fw_dump_end;
};
struct btmrvl_sdio_card {
@@ -93,7 +90,6 @@
const char *firmware;
const struct btmrvl_sdio_card_reg *reg;
bool support_pscan_win_report;
- bool supports_fw_dump;
u16 sd_blksz_fw_dl;
u8 rx_unit;
struct btmrvl_private *priv;
@@ -105,7 +101,6 @@
const struct btmrvl_sdio_card_reg *reg;
const bool support_pscan_win_report;
u16 sd_blksz_fw_dl;
- bool supports_fw_dump;
};
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 61d9c77..f9db709 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -106,12 +106,9 @@
{ USB_DEVICE(0x0b05, 0x17b5) },
{ USB_DEVICE(0x0b05, 0x17cb) },
{ USB_DEVICE(0x413c, 0x8197) },
- { USB_DEVICE(0x13d3, 0x3404),
- .driver_info = BTUSB_BCM_PATCHRAM },
/* Foxconn - Hon Hai */
- { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
- .driver_info = BTUSB_BCM_PATCHRAM },
+ { USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01) },
/* Broadcom devices with vendor specific id */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01),
@@ -159,7 +156,6 @@
{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0489, 0xe05f), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x0489, 0xe078), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04c5, 0x1330), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
@@ -167,7 +163,6 @@
{ USB_DEVICE(0x04ca, 0x3007), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x04ca, 0x300b), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x04ca, 0x3010), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0220), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x0930, 0x0227), .driver_info = BTUSB_ATH3012 },
@@ -187,7 +182,6 @@
{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3402), .driver_info = BTUSB_ATH3012 },
- { USB_DEVICE(0x13d3, 0x3408), .driver_info = BTUSB_ATH3012 },
{ USB_DEVICE(0x13d3, 0x3432), .driver_info = BTUSB_ATH3012 },
/* Atheros AR5BBU12 with sflash firmware */
@@ -304,8 +298,6 @@
unsigned int sco_num;
int isoc_altsetting;
int suspend_count;
-
- int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
};
static inline void btusb_free_frags(struct btusb_data *data)
@@ -597,7 +589,7 @@
if (urb->status == 0) {
hdev->stat.byte_rx += urb->actual_length;
- if (data->recv_bulk(data, urb->transfer_buffer,
+ if (btusb_recv_bulk(data, urb->transfer_buffer,
urb->actual_length) < 0) {
BT_ERR("%s corrupted ACL packet", hdev->name);
hdev->stat.err_rx++;
@@ -2019,8 +2011,6 @@
init_usb_anchor(&data->isoc_anchor);
spin_lock_init(&data->rxlock);
- data->recv_bulk = btusb_recv_bulk;
-
hdev = hci_alloc_dev();
if (!hdev)
return -ENOMEM;
@@ -2044,7 +2034,6 @@
if (id->driver_info & BTUSB_BCM_PATCHRAM) {
hdev->setup = btusb_setup_bcm_patchram;
hdev->set_bdaddr = btusb_set_bdaddr_bcm;
- set_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks);
}
if (id->driver_info & BTUSB_INTEL) {
diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c
index 55c135b..f038dba 100644
--- a/drivers/bluetooth/btwilink.c
+++ b/drivers/bluetooth/btwilink.c
@@ -349,6 +349,7 @@
.remove = bt_ti_remove,
.driver = {
.name = "btwilink",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index 326eb27..b6d639e 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -78,7 +78,7 @@
status = tty->driver->ops->tiocmget(tty);
- /* Enable Automatic RTSCTS */
+ /* Disable Automatic RTSCTS */
ktermios.c_cflag |= CRTSCTS;
status = tty_set_termios(tty, &ktermios);
diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c
index ec0fa77..a228386 100644
--- a/drivers/bluetooth/hci_h5.c
+++ b/drivers/bluetooth/hci_h5.c
@@ -168,27 +168,6 @@
hci_uart_tx_wakeup(hu);
}
-static void h5_peer_reset(struct hci_uart *hu)
-{
- struct h5 *h5 = hu->priv;
-
- BT_ERR("Peer device has reset");
-
- h5->state = H5_UNINITIALIZED;
-
- del_timer(&h5->timer);
-
- skb_queue_purge(&h5->rel);
- skb_queue_purge(&h5->unrel);
- skb_queue_purge(&h5->unack);
-
- h5->tx_seq = 0;
- h5->tx_ack = 0;
-
- /* Send reset request to upper stack */
- hci_reset_dev(hu->hdev);
-}
-
static int h5_open(struct hci_uart *hu)
{
struct h5 *h5;
@@ -304,12 +283,8 @@
conf_req[2] = h5_cfg_field(h5);
if (memcmp(data, sync_req, 2) == 0) {
- if (h5->state == H5_ACTIVE)
- h5_peer_reset(hu);
h5_link_control(hu, sync_rsp, 2);
} else if (memcmp(data, sync_rsp, 2) == 0) {
- if (h5->state == H5_ACTIVE)
- h5_peer_reset(hu);
h5->state = H5_INITIALIZED;
h5_link_control(hu, conf_req, 3);
} else if (memcmp(data, conf_req, 2) == 0) {
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index ac7a704..fda0983 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -3,7 +3,7 @@
#
menuconfig MEDIA_SUPPORT
- depends on !KERNEL_3_2
+ depends on !BACKPORT_KERNEL_3_2
tristate "Multimedia support"
depends on m
depends on HAS_IOMEM
@@ -165,6 +165,7 @@
source "drivers/media/pci/Kconfig"
source "drivers/media/platform/Kconfig"
source "drivers/media/mmc/Kconfig"
+source "drivers/media/parport/Kconfig"
source "drivers/media/radio/Kconfig"
comment "Supported FireWire (IEEE 1394) Adapters"
diff --git a/drivers/media/Makefile b/drivers/media/Makefile
index 9f5d0bc..6219093 100644
--- a/drivers/media/Makefile
+++ b/drivers/media/Makefile
@@ -28,6 +28,6 @@
# Finally, merge the drivers that require the core
#
-obj-y += common/ platform/ pci/ usb/ mmc/ firewire/
+obj-y += common/ platform/ pci/ usb/ mmc/ firewire/ parport/
obj-$(CPTCFG_VIDEO_DEV) += radio/
diff --git a/drivers/media/common/cx2341x.c b/drivers/media/common/cx2341x.c
index c07b9db..be76315 100644
--- a/drivers/media/common/cx2341x.c
+++ b/drivers/media/common/cx2341x.c
@@ -931,35 +931,6 @@
}
}
-/* Check for correctness of the ctrl's value based on the data from
- struct v4l2_queryctrl and the available menu items. Note that
- menu_items may be NULL, in that case it is ignored. */
-static int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
- const char * const *menu_items)
-{
- if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
- return -EINVAL;
- if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
- return -EBUSY;
- if (qctrl->type == V4L2_CTRL_TYPE_STRING)
- return 0;
- if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
- qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
- qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
- return 0;
- if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)
- return -ERANGE;
- if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {
- if (menu_items[ctrl->value] == NULL ||
- menu_items[ctrl->value][0] == '\0')
- return -EINVAL;
- }
- if (qctrl->type == V4L2_CTRL_TYPE_BITMASK &&
- (ctrl->value & ~qctrl->maximum))
- return -ERANGE;
- return 0;
-}
-
int cx2341x_ext_ctrls(struct cx2341x_mpeg_params *params, int busy,
struct v4l2_ext_controls *ctrls, unsigned int cmd)
{
diff --git a/drivers/media/common/saa7146/saa7146_core.c b/drivers/media/common/saa7146/saa7146_core.c
index 1ff9f53..97afee6 100644
--- a/drivers/media/common/saa7146/saa7146_core.c
+++ b/drivers/media/common/saa7146/saa7146_core.c
@@ -71,7 +71,7 @@
if (saa7146_read(dev, MC2) & 2)
break;
if (err) {
- pr_debug("%s: %s timed out while waiting for registers getting programmed\n",
+ pr_err("%s: %s timed out while waiting for registers getting programmed\n",
dev->name, __func__);
return -ETIMEDOUT;
}
@@ -364,9 +364,6 @@
goto out;
}
- /* create a nice device name */
- sprintf(dev->name, "saa7146 (%d)", saa7146_num);
-
DEB_EE("pci:%p\n", pci);
err = pci_enable_device(pci);
@@ -441,6 +438,9 @@
/* the rest + print status message */
+ /* create a nice device name */
+ sprintf(dev->name, "saa7146 (%d)", saa7146_num);
+
pr_info("found saa7146 @ mem %p (revision %d, irq %d) (0x%04x,0x%04x)\n",
dev->mem, dev->revision, pci->irq,
pci->subsystem_vendor, pci->subsystem_device);
diff --git a/drivers/media/common/siano/smsir.c b/drivers/media/common/siano/smsir.c
index 35d0e88..273043e 100644
--- a/drivers/media/common/siano/smsir.c
+++ b/drivers/media/common/siano/smsir.c
@@ -107,7 +107,8 @@
void sms_ir_exit(struct smscore_device_t *coredev)
{
- rc_unregister_device(coredev->ir.dev);
+ if (coredev->ir.dev)
+ rc_unregister_device(coredev->ir.dev);
sms_log("");
}
diff --git a/drivers/media/common/tveeprom.c b/drivers/media/common/tveeprom.c
index 47da037..c7dace6 100644
--- a/drivers/media/common/tveeprom.c
+++ b/drivers/media/common/tveeprom.c
@@ -286,17 +286,9 @@
{ TUNER_ABSENT, "Xceive XC5200C"},
{ TUNER_ABSENT, "NXP 18273"},
{ TUNER_ABSENT, "Montage M88TS2022"},
- /* 180-188 */
+ /* 180-189 */
{ TUNER_ABSENT, "NXP 18272M"},
{ TUNER_ABSENT, "NXP 18272S"},
-
- { TUNER_ABSENT, "Mirics MSi003"},
- { TUNER_ABSENT, "MaxLinear MxL256"},
- { TUNER_ABSENT, "SiLabs Si2158"},
- { TUNER_ABSENT, "SiLabs Si2178"},
- { TUNER_ABSENT, "SiLabs Si2157"},
- { TUNER_ABSENT, "SiLabs Si2177"},
- { TUNER_ABSENT, "ITE IT9137FN"},
};
/* Use TVEEPROM_AUDPROC_INTERNAL for those audio 'chips' that are
@@ -359,16 +351,6 @@
{ TVEEPROM_AUDPROC_INTERNAL, "CX23887" },
{ TVEEPROM_AUDPROC_INTERNAL, "SAA7164" },
{ TVEEPROM_AUDPROC_INTERNAL, "AU8522" },
- /* 45-49 */
- { TVEEPROM_AUDPROC_INTERNAL, "AVF4910B" },
- { TVEEPROM_AUDPROC_INTERNAL, "SAA7231" },
- { TVEEPROM_AUDPROC_INTERNAL, "CX23102" },
- { TVEEPROM_AUDPROC_INTERNAL, "SAA7163" },
- { TVEEPROM_AUDPROC_OTHER, "AK4113" },
- /* 50-52 */
- { TVEEPROM_AUDPROC_OTHER, "CS5340" },
- { TVEEPROM_AUDPROC_OTHER, "CS8416" },
- { TVEEPROM_AUDPROC_OTHER, "CX20810" },
};
/* This list is supplied by Hauppauge. Thanks! */
@@ -389,12 +371,8 @@
"CX25843", "CX23418", "NEC61153", "CX23885", "CX23888",
/* 35-39 */
"SAA7131", "CX25837", "CX23887", "CX23885A", "CX23887A",
- /* 40-44 */
- "SAA7164", "CX23885B", "AU8522", "ADV7401", "AVF4910B",
- /* 45-49 */
- "SAA7231", "CX23102", "SAA7163", "ADV7441A", "ADV7181C",
- /* 50-53 */
- "CX25836", "TDA9955", "TDA19977", "ADV7842"
+ /* 40-42 */
+ "SAA7164", "CX23885B", "AU8522"
};
static int hasRadioTuner(int tunerType)
@@ -570,10 +548,10 @@
tvee->serial_number =
eeprom_data[i+5] +
(eeprom_data[i+6] << 8) +
- (eeprom_data[i+7] << 16)+
- (eeprom_data[i+8] << 24);
+ (eeprom_data[i+7] << 16);
- if (eeprom_data[i + 8] == 0xf0) {
+ if ((eeprom_data[i + 8] & 0xf0) &&
+ (tvee->serial_number < 0xffffff)) {
tvee->MAC_address[0] = 0x00;
tvee->MAC_address[1] = 0x0D;
tvee->MAC_address[2] = 0xFE;
@@ -718,7 +696,7 @@
}
}
- tveeprom_info("Hauppauge model %d, rev %s, serial# %u\n",
+ tveeprom_info("Hauppauge model %d, rev %s, serial# %d\n",
tvee->model, tvee->rev_str, tvee->serial_number);
if (tvee->has_MAC_address == 1)
tveeprom_info("MAC address is %pM\n", tvee->MAC_address);
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
index 80ab8d0..e07a84e 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -356,7 +356,6 @@
#define USB_PID_MSI_DIGI_VOX_MINI_III 0x8807
#define USB_PID_SONY_PLAYTV 0x0003
#define USB_PID_MYGICA_D689 0xd811
-#define USB_PID_MYGICA_T230 0xc688
#define USB_PID_ELGATO_EYETV_DIVERSITY 0x0011
#define USB_PID_ELGATO_EYETV_DTT 0x0021
#define USB_PID_ELGATO_EYETV_DTT_2 0x003f
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index c29531e..7e9b079 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -962,11 +962,6 @@
case SYS_ATSC:
c->modulation = VSB_8;
break;
- case SYS_ISDBS:
- c->symbol_rate = 28860000;
- c->rolloff = ROLLOFF_35;
- c->bandwidth_hz = c->symbol_rate / 100 * 135;
- break;
default:
c->modulation = QAM_AUTO;
break;
@@ -2077,7 +2072,6 @@
break;
case SYS_DVBS:
case SYS_TURBO:
- case SYS_ISDBS:
rolloff = 135;
break;
case SYS_DVBS2:
diff --git a/drivers/media/dvb-core/dvb_net.c b/drivers/media/dvb-core/dvb_net.c
index e4041f0..059e611 100644
--- a/drivers/media/dvb-core/dvb_net.c
+++ b/drivers/media/dvb-core/dvb_net.c
@@ -379,9 +379,7 @@
/* Check TS error conditions: sync_byte, transport_error_indicator, scrambling_control . */
if ((ts[0] != TS_SYNC) || (ts[1] & TS_TEI) || ((ts[3] & TS_SC) != 0)) {
printk(KERN_WARNING "%lu: Invalid TS cell: SYNC %#x, TEI %u, SC %#x.\n",
- priv->ts_count, ts[0],
- (ts[1] & TS_TEI) >> 7,
- (ts[3] & TS_SC) >> 6);
+ priv->ts_count, ts[0], ts[1] & TS_TEI >> 7, ts[3] & 0xC0 >> 6);
/* Drop partly decoded SNDU, reset state, resync on PUSI. */
if (priv->ule_skb) {
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index bafccf7..8971120 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -728,16 +728,13 @@
A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator.
Say Y when you want to support this frontend.
-comment "ISDB-S (satellite) & ISDB-T (terrestrial) frontends"
- depends on DVB_CORE
-
config DVB_TC90522
tristate "Toshiba TC90522"
depends on m
depends on DVB_CORE && I2C
default m if !MEDIA_SUBDRV_AUTOSELECT
help
- Toshiba TC90522 2xISDB-S 8PSK + 2xISDB-T OFDM demodulator.
+ A Toshiba TC90522 2xISDB-T + 2xISDB-S demodulator.
Say Y when you want to support this frontend.
comment "Digital terrestrial only tuners/PLL"
diff --git a/drivers/media/dvb-frontends/af9033.c b/drivers/media/dvb-frontends/af9033.c
index 82ce47b..63a89c1 100644
--- a/drivers/media/dvb-frontends/af9033.c
+++ b/drivers/media/dvb-frontends/af9033.c
@@ -291,12 +291,6 @@
if (clock_adc_lut[i].clock == dev->cfg.clock)
break;
}
- if (i == ARRAY_SIZE(clock_adc_lut)) {
- dev_err(&dev->client->dev,
- "Couldn't find ADC config for clock=%d\n",
- dev->cfg.clock);
- goto err;
- }
adc_cw = af9033_div(dev, clock_adc_lut[i].adc, 1000000ul, 19ul);
buf[0] = (adc_cw >> 0) & 0xff;
@@ -586,15 +580,7 @@
break;
}
}
- if (i == ARRAY_SIZE(coeff_lut)) {
- dev_err(&dev->client->dev,
- "Couldn't find LUT config for clock=%d\n",
- dev->cfg.clock);
- ret = -EINVAL;
- goto err;
- }
-
- ret = af9033_wr_regs(dev, 0x800001,
+ ret = af9033_wr_regs(dev, 0x800001,
coeff_lut[i].val, sizeof(coeff_lut[i].val));
}
@@ -606,13 +592,6 @@
if (clock_adc_lut[i].clock == dev->cfg.clock)
break;
}
- if (i == ARRAY_SIZE(clock_adc_lut)) {
- dev_err(&dev->client->dev,
- "Couldn't find ADC clock for clock=%d\n",
- dev->cfg.clock);
- ret = -EINVAL;
- goto err;
- }
adc_freq = clock_adc_lut[i].adc;
/* get used IF frequency */
@@ -870,97 +849,29 @@
{
struct af9033_dev *dev = fe->demodulator_priv;
struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
- int ret;
- u8 u8tmp;
/* use DVBv5 CNR */
- if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL) {
- /* Return 0.1 dB for AF9030 and 0-0xffff for IT9130. */
- if (dev->is_af9035) {
- /* 1000x => 10x (0.1 dB) */
- *snr = div_s64(c->cnr.stat[0].svalue, 100);
- } else {
- /* 1000x => 1x (1 dB) */
- *snr = div_s64(c->cnr.stat[0].svalue, 1000);
-
- /* read current modulation */
- ret = af9033_rd_reg(dev, 0x80f903, &u8tmp);
- if (ret)
- goto err;
-
- /* scale value to 0x0000-0xffff */
- switch ((u8tmp >> 0) & 3) {
- case 0:
- *snr = *snr * 0xffff / 23;
- break;
- case 1:
- *snr = *snr * 0xffff / 26;
- break;
- case 2:
- *snr = *snr * 0xffff / 32;
- break;
- default:
- goto err;
- }
- }
- } else {
+ if (c->cnr.stat[0].scale == FE_SCALE_DECIBEL)
+ *snr = div_s64(c->cnr.stat[0].svalue, 100); /* 1000x => 10x */
+ else
*snr = 0;
- }
return 0;
-
-err:
- dev_dbg(&dev->client->dev, "failed=%d\n", ret);
-
- return ret;
}
static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
{
struct af9033_dev *dev = fe->demodulator_priv;
- struct dtv_frontend_properties *c = &dev->fe.dtv_property_cache;
- int ret, tmp, power_real;
- u8 u8tmp, gain_offset, buf[7];
+ int ret;
+ u8 strength2;
- if (dev->is_af9035) {
- /* read signal strength of 0-100 scale */
- ret = af9033_rd_reg(dev, 0x800048, &u8tmp);
- if (ret < 0)
- goto err;
+ /* read signal strength of 0-100 scale */
+ ret = af9033_rd_reg(dev, 0x800048, &strength2);
+ if (ret < 0)
+ goto err;
- /* scale value to 0x0000-0xffff */
- *strength = u8tmp * 0xffff / 100;
- } else {
- ret = af9033_rd_reg(dev, 0x8000f7, &u8tmp);
- if (ret < 0)
- goto err;
-
- ret = af9033_rd_regs(dev, 0x80f900, buf, 7);
- if (ret < 0)
- goto err;
-
- if (c->frequency <= 300000000)
- gain_offset = 7; /* VHF */
- else
- gain_offset = 4; /* UHF */
-
- power_real = (u8tmp - 100 - gain_offset) -
- power_reference[((buf[3] >> 0) & 3)][((buf[6] >> 0) & 7)];
-
- if (power_real < -15)
- tmp = 0;
- else if ((power_real >= -15) && (power_real < 0))
- tmp = (2 * (power_real + 15)) / 3;
- else if ((power_real >= 0) && (power_real < 20))
- tmp = 4 * power_real + 10;
- else if ((power_real >= 20) && (power_real < 35))
- tmp = (2 * (power_real - 20)) / 3 + 90;
- else
- tmp = 100;
-
- /* scale value to 0x0000-0xffff */
- *strength = tmp * 0xffff / 100;
- }
+ /* scale value to 0x0000-0xffff */
+ *strength = strength2 * 0xffff / 100;
return 0;
@@ -1100,33 +1011,6 @@
snr_val = (buf[2] << 16) | (buf[1] << 8) | (buf[0] << 0);
- /* read superframe number */
- ret = af9033_rd_reg(dev, 0x80f78b, &u8tmp);
- if (ret)
- goto err;
-
- if (u8tmp)
- snr_val /= u8tmp;
-
- /* read current transmission mode */
- ret = af9033_rd_reg(dev, 0x80f900, &u8tmp);
- if (ret)
- goto err;
-
- switch ((u8tmp >> 0) & 3) {
- case 0:
- snr_val *= 4;
- break;
- case 1:
- snr_val *= 1;
- break;
- case 2:
- snr_val *= 2;
- break;
- default:
- goto err_schedule_delayed_work;
- }
-
/* read current modulation */
ret = af9033_rd_reg(dev, 0x80f903, &u8tmp);
if (ret)
diff --git a/drivers/media/dvb-frontends/af9033_priv.h b/drivers/media/dvb-frontends/af9033_priv.h
index 8e23275..c12c92c 100644
--- a/drivers/media/dvb-frontends/af9033_priv.h
+++ b/drivers/media/dvb-frontends/af9033_priv.h
@@ -181,10 +181,7 @@
{ 0x05570d, 26 },
{ 0x059feb, 27 },
{ 0x05bf38, 28 },
- { 0x05f78f, 29 },
- { 0x0612c3, 30 },
- { 0x0626be, 31 },
- { 0xffffff, 32 },
+ { 0xffffff, 29 },
};
static const struct reg_val ofsm_init[] = {
@@ -2054,10 +2051,4 @@
{ 0x80fd8b, 0x00 },
};
-/* NorDig power reference table */
-static const int power_reference[][5] = {
- {-93, -91, -90, -89, -88}, /* QPSK 1/2 ~ 7/8 */
- {-87, -85, -84, -83, -82}, /* 16QAM 1/2 ~ 7/8 */
- {-82, -80, -78, -77, -76}, /* 64QAM 1/2 ~ 7/8 */
-};
#endif /* AF9033_PRIV_H */
diff --git a/drivers/media/dvb-frontends/au8522_dig.c b/drivers/media/dvb-frontends/au8522_dig.c
index 5d06c99..a68974f 100644
--- a/drivers/media/dvb-frontends/au8522_dig.c
+++ b/drivers/media/dvb-frontends/au8522_dig.c
@@ -29,7 +29,6 @@
#include "au8522_priv.h"
static int debug;
-static int zv_mode = 1; /* default to on */
#define dprintk(arg...)\
do { if (debug)\
@@ -470,87 +469,6 @@
{ 0x8526, 0x01 },
};
-static struct {
- u16 reg;
- u16 data;
-} QAM256_mod_tab_zv_mode[] = {
- { 0x80a3, 0x09 },
- { 0x80a4, 0x00 },
- { 0x8081, 0xc4 },
- { 0x80a5, 0x40 },
- { 0x80b5, 0xfb },
- { 0x80b6, 0x8e },
- { 0x80b7, 0x39 },
- { 0x80aa, 0x77 },
- { 0x80ad, 0x77 },
- { 0x80a6, 0x67 },
- { 0x8262, 0x20 },
- { 0x821c, 0x30 },
- { 0x80b8, 0x3e },
- { 0x80b9, 0xf0 },
- { 0x80ba, 0x01 },
- { 0x80bb, 0x18 },
- { 0x80bc, 0x50 },
- { 0x80bd, 0x00 },
- { 0x80be, 0xea },
- { 0x80bf, 0xef },
- { 0x80c0, 0xfc },
- { 0x80c1, 0xbd },
- { 0x80c2, 0x1f },
- { 0x80c3, 0xfc },
- { 0x80c4, 0xdd },
- { 0x80c5, 0xaf },
- { 0x80c6, 0x00 },
- { 0x80c7, 0x38 },
- { 0x80c8, 0x30 },
- { 0x80c9, 0x05 },
- { 0x80ca, 0x4a },
- { 0x80cb, 0xd0 },
- { 0x80cc, 0x01 },
- { 0x80cd, 0xd9 },
- { 0x80ce, 0x6f },
- { 0x80cf, 0xf9 },
- { 0x80d0, 0x70 },
- { 0x80d1, 0xdf },
- { 0x80d2, 0xf7 },
- { 0x80d3, 0xc2 },
- { 0x80d4, 0xdf },
- { 0x80d5, 0x02 },
- { 0x80d6, 0x9a },
- { 0x80d7, 0xd0 },
- { 0x8250, 0x0d },
- { 0x8251, 0xcd },
- { 0x8252, 0xe0 },
- { 0x8253, 0x05 },
- { 0x8254, 0xa7 },
- { 0x8255, 0xff },
- { 0x8256, 0xed },
- { 0x8257, 0x5b },
- { 0x8258, 0xae },
- { 0x8259, 0xe6 },
- { 0x825a, 0x3d },
- { 0x825b, 0x0f },
- { 0x825c, 0x0d },
- { 0x825d, 0xea },
- { 0x825e, 0xf2 },
- { 0x825f, 0x51 },
- { 0x8260, 0xf5 },
- { 0x8261, 0x06 },
- { 0x821a, 0x01 },
- { 0x8546, 0x40 },
- { 0x8210, 0x26 },
- { 0x8211, 0xf6 },
- { 0x8212, 0x84 },
- { 0x8213, 0x02 },
- { 0x8502, 0x01 },
- { 0x8121, 0x04 },
- { 0x8122, 0x04 },
- { 0x852e, 0x10 },
- { 0x80a4, 0xca },
- { 0x80a7, 0x40 },
- { 0x8526, 0x01 },
-};
-
static int au8522_enable_modulation(struct dvb_frontend *fe,
fe_modulation_t m)
{
@@ -577,23 +495,12 @@
au8522_set_if(fe, state->config->qam_if);
break;
case QAM_256:
- if (zv_mode) {
- dprintk("%s() QAM 256 (zv_mode)\n", __func__);
- for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab_zv_mode); i++)
- au8522_writereg(state,
- QAM256_mod_tab_zv_mode[i].reg,
- QAM256_mod_tab_zv_mode[i].data);
- au8522_set_if(fe, state->config->qam_if);
- msleep(100);
- au8522_writereg(state, 0x821a, 0x00);
- } else {
- dprintk("%s() QAM 256\n", __func__);
- for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
- au8522_writereg(state,
- QAM256_mod_tab[i].reg,
- QAM256_mod_tab[i].data);
- au8522_set_if(fe, state->config->qam_if);
- }
+ dprintk("%s() QAM 256\n", __func__);
+ for (i = 0; i < ARRAY_SIZE(QAM256_mod_tab); i++)
+ au8522_writereg(state,
+ QAM256_mod_tab[i].reg,
+ QAM256_mod_tab[i].data);
+ au8522_set_if(fe, state->config->qam_if);
break;
default:
dprintk("%s() Invalid modulation\n", __func__);
@@ -630,12 +537,7 @@
return ret;
/* Allow the tuner to settle */
- if (zv_mode) {
- dprintk("%s() increase tuner settling time for zv_mode\n",
- __func__);
- msleep(250);
- } else
- msleep(100);
+ msleep(100);
au8522_enable_modulation(fe, c->modulation);
@@ -921,11 +823,6 @@
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Enable verbose debug messages");
-module_param(zv_mode, int, 0644);
-MODULE_PARM_DESC(zv_mode, "Turn on/off ZeeVee modulator compatability mode (default:on).\n"
- "\t\ton - modified AU8522 QAM256 initialization.\n"
- "\t\tProvides faster lock when using ZeeVee modulator based sources");
-
MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
MODULE_AUTHOR("Steven Toth");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb-frontends/cx22700.c b/drivers/media/dvb-frontends/cx22700.c
index 8656326..3d399d9 100644
--- a/drivers/media/dvb-frontends/cx22700.c
+++ b/drivers/media/dvb-frontends/cx22700.c
@@ -169,9 +169,6 @@
cx22700_writereg (state, 0x04, val);
- if (p->code_rate_HP - FEC_1_2 >= sizeof(fec_tab) ||
- p->code_rate_LP - FEC_1_2 >= sizeof(fec_tab))
- return -EINVAL;
val = fec_tab[p->code_rate_HP - FEC_1_2] << 3;
val |= fec_tab[p->code_rate_LP - FEC_1_2];
diff --git a/drivers/media/dvb-frontends/cx24110.c b/drivers/media/dvb-frontends/cx24110.c
index 7b510f2..95b981c 100644
--- a/drivers/media/dvb-frontends/cx24110.c
+++ b/drivers/media/dvb-frontends/cx24110.c
@@ -177,45 +177,47 @@
return 0;
}
-static int cx24110_set_fec(struct cx24110_state* state, fe_code_rate_t fec)
+static int cx24110_set_fec (struct cx24110_state* state, fe_code_rate_t fec)
{
- static const int rate[FEC_AUTO] = {-1, 1, 2, 3, 5, 7, -1};
- static const int g1[FEC_AUTO] = {-1, 0x01, 0x02, 0x05, 0x15, 0x45, -1};
- static const int g2[FEC_AUTO] = {-1, 0x01, 0x03, 0x06, 0x1a, 0x7a, -1};
+/* fixme (low): error handling */
+
+ static const int rate[]={-1,1,2,3,5,7,-1};
+ static const int g1[]={-1,0x01,0x02,0x05,0x15,0x45,-1};
+ static const int g2[]={-1,0x01,0x03,0x06,0x1a,0x7a,-1};
/* Well, the AutoAcq engine of the cx24106 and 24110 automatically
searches all enabled viterbi rates, and can handle non-standard
rates as well. */
- if (fec > FEC_AUTO)
- fec = FEC_AUTO;
+ if (fec>FEC_AUTO)
+ fec=FEC_AUTO;
- if (fec == FEC_AUTO) { /* (re-)establish AutoAcq behaviour */
- cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) & 0xdf);
+ if (fec==FEC_AUTO) { /* (re-)establish AutoAcq behaviour */
+ cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)&0xdf);
/* clear AcqVitDis bit */
- cx24110_writereg(state, 0x18, 0xae);
+ cx24110_writereg(state,0x18,0xae);
/* allow all DVB standard code rates */
- cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | 0x3);
+ cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|0x3);
/* set nominal Viterbi rate 3/4 */
- cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | 0x3);
+ cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|0x3);
/* set current Viterbi rate 3/4 */
- cx24110_writereg(state, 0x1a, 0x05);
- cx24110_writereg(state, 0x1b, 0x06);
+ cx24110_writereg(state,0x1a,0x05); cx24110_writereg(state,0x1b,0x06);
/* set the puncture registers for code rate 3/4 */
return 0;
} else {
- cx24110_writereg(state, 0x37, cx24110_readreg(state, 0x37) | 0x20);
+ cx24110_writereg(state,0x37,cx24110_readreg(state,0x37)|0x20);
/* set AcqVitDis bit */
- if (rate[fec] < 0)
- return -EINVAL;
-
- cx24110_writereg(state, 0x05, (cx24110_readreg(state, 0x05) & 0xf0) | rate[fec]);
- /* set nominal Viterbi rate */
- cx24110_writereg(state, 0x22, (cx24110_readreg(state, 0x22) & 0xf0) | rate[fec]);
- /* set current Viterbi rate */
- cx24110_writereg(state, 0x1a, g1[fec]);
- cx24110_writereg(state, 0x1b, g2[fec]);
- /* not sure if this is the right way: I always used AutoAcq mode */
+ if(rate[fec]>0) {
+ cx24110_writereg(state,0x05,(cx24110_readreg(state,0x05)&0xf0)|rate[fec]);
+ /* set nominal Viterbi rate */
+ cx24110_writereg(state,0x22,(cx24110_readreg(state,0x22)&0xf0)|rate[fec]);
+ /* set current Viterbi rate */
+ cx24110_writereg(state,0x1a,g1[fec]);
+ cx24110_writereg(state,0x1b,g2[fec]);
+ /* not sure if this is the right way: I always used AutoAcq mode */
+ } else
+ return -EOPNOTSUPP;
+/* fixme (low): which is the correct return code? */
}
return 0;
}
diff --git a/drivers/media/dvb-frontends/cx24117.c b/drivers/media/dvb-frontends/cx24117.c
index acb965c..a6c3c9e 100644
--- a/drivers/media/dvb-frontends/cx24117.c
+++ b/drivers/media/dvb-frontends/cx24117.c
@@ -459,7 +459,7 @@
if (state->priv->skip_fw_load)
return 0;
- /* check if firmware is already running */
+ /* check if firmware if already running */
if (cx24117_readreg(state, 0xeb) != 0xa) {
/* Load firmware */
/* request the firmware, this will block until loaded */
diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c
index c505d69..589134e 100644
--- a/drivers/media/dvb-frontends/dib7000p.c
+++ b/drivers/media/dvb-frontends/dib7000p.c
@@ -1780,7 +1780,7 @@
}
/* FIXME: may require changes - this one was borrowed from dib8000 */
-static u32 dib7000p_get_time_us(struct dvb_frontend *demod)
+static u32 dib7000p_get_time_us(struct dvb_frontend *demod, int layer)
{
struct dtv_frontend_properties *c = &demod->dtv_property_cache;
u64 time_us, tmp64;
@@ -1881,6 +1881,7 @@
{
struct dib7000p_state *state = demod->demodulator_priv;
struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+ int i;
int show_per_stats = 0;
u32 time_us = 0, val, snr;
u64 blocks, ucb;
@@ -1934,7 +1935,7 @@
/* Estimate the number of packets based on bitrate */
if (!time_us)
- time_us = dib7000p_get_time_us(demod);
+ time_us = dib7000p_get_time_us(demod, -1);
if (time_us) {
blocks = 1250000ULL * 1000000ULL;
@@ -1948,7 +1949,7 @@
/* Get post-BER measures */
if (time_after(jiffies, state->ber_jiffies_stats)) {
- time_us = dib7000p_get_time_us(demod);
+ time_us = dib7000p_get_time_us(demod, -1);
state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
dprintk("Next all layers stats available in %u us.", time_us);
@@ -1968,7 +1969,7 @@
c->block_error.stat[0].scale = FE_SCALE_COUNTER;
c->block_error.stat[0].uvalue += val;
- time_us = dib7000p_get_time_us(demod);
+ time_us = dib7000p_get_time_us(demod, i);
if (time_us) {
blocks = 1250000ULL * 1000000ULL;
do_div(blocks, time_us * 8 * 204);
diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c
index 2bfa7a4..5ec221f 100644
--- a/drivers/media/dvb-frontends/drx39xyj/drxj.c
+++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c
@@ -12255,7 +12255,8 @@
kfree(demod->my_ext_attr);
kfree(demod->my_common_attr);
kfree(demod->my_i2c_dev_addr);
- release_firmware(demod->firmware);
+ if (demod->firmware)
+ release_firmware(demod->firmware);
kfree(demod);
kfree(state);
}
diff --git a/drivers/media/dvb-frontends/drxk_hard.c b/drivers/media/dvb-frontends/drxk_hard.c
index d46cf5f..6721951 100644
--- a/drivers/media/dvb-frontends/drxk_hard.c
+++ b/drivers/media/dvb-frontends/drxk_hard.c
@@ -166,9 +166,9 @@
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages");
-#define dprintk(level, fmt, arg...) do { \
-if (debug >= level) \
- printk(KERN_DEBUG KBUILD_MODNAME ": %s " fmt, __func__, ##arg); \
+#define dprintk(level, fmt, arg...) do { \
+if (debug >= level) \
+ pr_debug(fmt, ##arg); \
} while (0)
@@ -6310,7 +6310,8 @@
struct drxk_state *state = fe->demodulator_priv;
dprintk(1, "\n");
- release_firmware(state->fw);
+ if (state->fw)
+ release_firmware(state->fw);
kfree(state);
}
diff --git a/drivers/media/dvb-frontends/ds3000.c b/drivers/media/dvb-frontends/ds3000.c
index 9d0d034..335daef 100644
--- a/drivers/media/dvb-frontends/ds3000.c
+++ b/drivers/media/dvb-frontends/ds3000.c
@@ -864,13 +864,6 @@
memcpy(&state->frontend.ops, &ds3000_ops,
sizeof(struct dvb_frontend_ops));
state->frontend.demodulator_priv = state;
-
- /*
- * Some devices like T480 starts with voltage on. Be sure
- * to turn voltage off during init, as this can otherwise
- * interfere with Unicable SCR systems.
- */
- ds3000_set_voltage(&state->frontend, SEC_VOLTAGE_OFF);
return &state->frontend;
error3:
diff --git a/drivers/media/dvb-frontends/m88ds3103.c b/drivers/media/dvb-frontends/m88ds3103.c
index ba4ee0b..81657e9 100644
--- a/drivers/media/dvb-frontends/m88ds3103.c
+++ b/drivers/media/dvb-frontends/m88ds3103.c
@@ -1,5 +1,5 @@
/*
- * Montage M88DS3103/M88RS6000 demodulator driver
+ * Montage M88DS3103 demodulator driver
*
* Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
*
@@ -162,7 +162,7 @@
dev_dbg(&priv->i2c->dev, "%s: tab_len=%d\n", __func__, tab_len);
- if (tab_len > 86) {
+ if (tab_len > 83) {
ret = -EINVAL;
goto err;
}
@@ -245,9 +245,9 @@
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret, len;
const struct m88ds3103_reg_val *init;
- u8 u8tmp, u8tmp1 = 0, u8tmp2 = 0; /* silence compiler warning */
- u8 buf[3];
- u16 u16tmp, divide_ratio = 0;
+ u8 u8tmp, u8tmp1, u8tmp2;
+ u8 buf[2];
+ u16 u16tmp, divide_ratio;
u32 tuner_frequency, target_mclk;
s32 s32tmp;
@@ -262,22 +262,6 @@
goto err;
}
- /* reset */
- ret = m88ds3103_wr_reg(priv, 0x07, 0x80);
- if (ret)
- goto err;
-
- ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
- if (ret)
- goto err;
-
- /* Disable demod clock path */
- if (priv->chip_id == M88RS6000_CHIP_ID) {
- ret = m88ds3103_wr_reg(priv, 0x06, 0xe0);
- if (ret)
- goto err;
- }
-
/* program tuner */
if (fe->ops.tuner_ops.set_params) {
ret = fe->ops.tuner_ops.set_params(fe);
@@ -298,73 +282,14 @@
tuner_frequency = c->frequency;
}
- /* select M88RS6000 demod main mclk and ts mclk from tuner die. */
- if (priv->chip_id == M88RS6000_CHIP_ID) {
- if (c->symbol_rate > 45010000)
- priv->mclk_khz = 110250;
- else
- priv->mclk_khz = 96000;
+ /* reset */
+ ret = m88ds3103_wr_reg(priv, 0x07, 0x80);
+ if (ret)
+ goto err;
- if (c->delivery_system == SYS_DVBS)
- target_mclk = 96000;
- else
- target_mclk = 144000;
-
- /* Enable demod clock path */
- ret = m88ds3103_wr_reg(priv, 0x06, 0x00);
- if (ret)
- goto err;
- usleep_range(10000, 20000);
- } else {
- /* set M88DS3103 mclk and ts mclk. */
- priv->mclk_khz = 96000;
-
- switch (priv->cfg->ts_mode) {
- case M88DS3103_TS_SERIAL:
- case M88DS3103_TS_SERIAL_D7:
- target_mclk = priv->cfg->ts_clk;
- break;
- case M88DS3103_TS_PARALLEL:
- case M88DS3103_TS_CI:
- if (c->delivery_system == SYS_DVBS)
- target_mclk = 96000;
- else {
- if (c->symbol_rate < 18000000)
- target_mclk = 96000;
- else if (c->symbol_rate < 28000000)
- target_mclk = 144000;
- else
- target_mclk = 192000;
- }
- break;
- default:
- dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n",
- __func__);
- ret = -EINVAL;
- goto err;
- }
-
- switch (target_mclk) {
- case 96000:
- u8tmp1 = 0x02; /* 0b10 */
- u8tmp2 = 0x01; /* 0b01 */
- break;
- case 144000:
- u8tmp1 = 0x00; /* 0b00 */
- u8tmp2 = 0x01; /* 0b01 */
- break;
- case 192000:
- u8tmp1 = 0x03; /* 0b11 */
- u8tmp2 = 0x00; /* 0b00 */
- break;
- }
- ret = m88ds3103_wr_reg_mask(priv, 0x22, u8tmp1 << 6, 0xc0);
- if (ret)
- goto err;
- ret = m88ds3103_wr_reg_mask(priv, 0x24, u8tmp2 << 6, 0xc0);
- if (ret)
- goto err;
- }
+ ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
+ if (ret)
+ goto err;
ret = m88ds3103_wr_reg(priv, 0xb2, 0x01);
if (ret)
@@ -376,21 +301,36 @@
switch (c->delivery_system) {
case SYS_DVBS:
- if (priv->chip_id == M88RS6000_CHIP_ID) {
- len = ARRAY_SIZE(m88rs6000_dvbs_init_reg_vals);
- init = m88rs6000_dvbs_init_reg_vals;
- } else {
- len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals);
- init = m88ds3103_dvbs_init_reg_vals;
- }
+ len = ARRAY_SIZE(m88ds3103_dvbs_init_reg_vals);
+ init = m88ds3103_dvbs_init_reg_vals;
+ target_mclk = 96000;
break;
case SYS_DVBS2:
- if (priv->chip_id == M88RS6000_CHIP_ID) {
- len = ARRAY_SIZE(m88rs6000_dvbs2_init_reg_vals);
- init = m88rs6000_dvbs2_init_reg_vals;
- } else {
- len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals);
- init = m88ds3103_dvbs2_init_reg_vals;
+ len = ARRAY_SIZE(m88ds3103_dvbs2_init_reg_vals);
+ init = m88ds3103_dvbs2_init_reg_vals;
+
+ switch (priv->cfg->ts_mode) {
+ case M88DS3103_TS_SERIAL:
+ case M88DS3103_TS_SERIAL_D7:
+ if (c->symbol_rate < 18000000)
+ target_mclk = 96000;
+ else
+ target_mclk = 144000;
+ break;
+ case M88DS3103_TS_PARALLEL:
+ case M88DS3103_TS_CI:
+ if (c->symbol_rate < 18000000)
+ target_mclk = 96000;
+ else if (c->symbol_rate < 28000000)
+ target_mclk = 144000;
+ else
+ target_mclk = 192000;
+ break;
+ default:
+ dev_dbg(&priv->i2c->dev, "%s: invalid ts_mode\n",
+ __func__);
+ ret = -EINVAL;
+ goto err;
}
break;
default:
@@ -407,30 +347,7 @@
goto err;
}
- if (priv->chip_id == M88RS6000_CHIP_ID) {
- if ((c->delivery_system == SYS_DVBS2)
- && ((c->symbol_rate / 1000) <= 5000)) {
- ret = m88ds3103_wr_reg(priv, 0xc0, 0x04);
- if (ret)
- goto err;
- buf[0] = 0x09;
- buf[1] = 0x22;
- buf[2] = 0x88;
- ret = m88ds3103_wr_regs(priv, 0x8a, buf, 3);
- if (ret)
- goto err;
- }
- ret = m88ds3103_wr_reg_mask(priv, 0x9d, 0x08, 0x08);
- if (ret)
- goto err;
- ret = m88ds3103_wr_reg(priv, 0xf1, 0x01);
- if (ret)
- goto err;
- ret = m88ds3103_wr_reg_mask(priv, 0x30, 0x80, 0x80);
- if (ret)
- goto err;
- }
-
+ u8tmp1 = 0; /* silence compiler warning */
switch (priv->cfg->ts_mode) {
case M88DS3103_TS_SERIAL:
u8tmp1 = 0x00;
@@ -466,15 +383,16 @@
ret = m88ds3103_wr_reg_mask(priv, 0x29, u8tmp1, 0x20);
if (ret)
goto err;
+ }
+
+ if (priv->cfg->ts_clk) {
+ divide_ratio = DIV_ROUND_UP(target_mclk, priv->cfg->ts_clk);
+ u8tmp1 = divide_ratio / 2;
+ u8tmp2 = DIV_ROUND_UP(divide_ratio, 2);
+ } else {
+ divide_ratio = 0;
u8tmp1 = 0;
u8tmp2 = 0;
- break;
- default:
- if (priv->cfg->ts_clk) {
- divide_ratio = DIV_ROUND_UP(target_mclk, priv->cfg->ts_clk);
- u8tmp1 = divide_ratio / 2;
- u8tmp2 = DIV_ROUND_UP(divide_ratio, 2);
- }
}
dev_dbg(&priv->i2c->dev,
@@ -502,6 +420,29 @@
if (ret)
goto err;
+ switch (target_mclk) {
+ case 96000:
+ u8tmp1 = 0x02; /* 0b10 */
+ u8tmp2 = 0x01; /* 0b01 */
+ break;
+ case 144000:
+ u8tmp1 = 0x00; /* 0b00 */
+ u8tmp2 = 0x01; /* 0b01 */
+ break;
+ case 192000:
+ u8tmp1 = 0x03; /* 0b11 */
+ u8tmp2 = 0x00; /* 0b00 */
+ break;
+ }
+
+ ret = m88ds3103_wr_reg_mask(priv, 0x22, u8tmp1 << 6, 0xc0);
+ if (ret)
+ goto err;
+
+ ret = m88ds3103_wr_reg_mask(priv, 0x24, u8tmp2 << 6, 0xc0);
+ if (ret)
+ goto err;
+
if (c->symbol_rate <= 3000000)
u8tmp = 0x20;
else if (c->symbol_rate <= 10000000)
@@ -525,7 +466,7 @@
if (ret)
goto err;
- u16tmp = DIV_ROUND_CLOSEST((c->symbol_rate / 1000) << 15, priv->mclk_khz / 2);
+ u16tmp = DIV_ROUND_CLOSEST((c->symbol_rate / 1000) << 15, M88DS3103_MCLK_KHZ / 2);
buf[0] = (u16tmp >> 0) & 0xff;
buf[1] = (u16tmp >> 8) & 0xff;
ret = m88ds3103_wr_regs(priv, 0x61, buf, 2);
@@ -548,7 +489,7 @@
(tuner_frequency - c->frequency));
s32tmp = 0x10000 * (tuner_frequency - c->frequency);
- s32tmp = DIV_ROUND_CLOSEST(s32tmp, priv->mclk_khz);
+ s32tmp = DIV_ROUND_CLOSEST(s32tmp, M88DS3103_MCLK_KHZ);
if (s32tmp < 0)
s32tmp += 0x10000;
@@ -579,7 +520,7 @@
struct m88ds3103_priv *priv = fe->demodulator_priv;
int ret, len, remaining;
const struct firmware *fw = NULL;
- u8 *fw_file;
+ u8 *fw_file = M88DS3103_FIRMWARE;
u8 u8tmp;
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
@@ -600,6 +541,15 @@
if (ret)
goto err;
+ /* reset */
+ ret = m88ds3103_wr_reg(priv, 0x07, 0x60);
+ if (ret)
+ goto err;
+
+ ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
+ if (ret)
+ goto err;
+
/* firmware status */
ret = m88ds3103_rd_reg(priv, 0xb9, &u8tmp);
if (ret)
@@ -610,23 +560,10 @@
if (u8tmp)
goto skip_fw_download;
- /* global reset, global diseqc reset, golbal fec reset */
- ret = m88ds3103_wr_reg(priv, 0x07, 0xe0);
- if (ret)
- goto err;
-
- ret = m88ds3103_wr_reg(priv, 0x07, 0x00);
- if (ret)
- goto err;
-
/* cold state - try to download firmware */
dev_info(&priv->i2c->dev, "%s: found a '%s' in cold state\n",
KBUILD_MODNAME, m88ds3103_ops.info.name);
- if (priv->chip_id == M88RS6000_CHIP_ID)
- fw_file = M88RS6000_FIRMWARE;
- else
- fw_file = M88DS3103_FIRMWARE;
/* request the firmware, this will block and timeout */
ret = request_firmware(&fw, fw_file, priv->i2c->dev.parent);
if (ret) {
@@ -640,7 +577,7 @@
ret = m88ds3103_wr_reg(priv, 0xb2, 0x01);
if (ret)
- goto error_fw_release;
+ goto err;
for (remaining = fw->size; remaining > 0;
remaining -= (priv->cfg->i2c_wr_max - 1)) {
@@ -654,13 +591,13 @@
dev_err(&priv->i2c->dev,
"%s: firmware download failed=%d\n",
KBUILD_MODNAME, ret);
- goto error_fw_release;
+ goto err;
}
}
ret = m88ds3103_wr_reg(priv, 0xb2, 0x00);
if (ret)
- goto error_fw_release;
+ goto err;
release_firmware(fw);
fw = NULL;
@@ -686,10 +623,10 @@
priv->warm = true;
return 0;
-
-error_fw_release:
- release_firmware(fw);
err:
+ if (fw)
+ release_firmware(fw);
+
dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
return ret;
}
@@ -698,18 +635,13 @@
{
struct m88ds3103_priv *priv = fe->demodulator_priv;
int ret;
- u8 u8tmp;
dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
priv->delivery_system = SYS_UNDEFINED;
/* TS Hi-Z */
- if (priv->chip_id == M88RS6000_CHIP_ID)
- u8tmp = 0x29;
- else
- u8tmp = 0x27;
- ret = m88ds3103_wr_reg_mask(priv, u8tmp, 0x00, 0x01);
+ ret = m88ds3103_wr_reg_mask(priv, 0x27, 0x00, 0x01);
if (ret)
goto err;
@@ -898,7 +830,7 @@
goto err;
c->symbol_rate = 1ull * ((buf[1] << 8) | (buf[0] << 0)) *
- priv->mclk_khz * 1000 / 0x10000;
+ M88DS3103_MCLK_KHZ * 1000 / 0x10000;
return 0;
err:
@@ -1378,22 +1310,18 @@
priv->i2c = i2c;
mutex_init(&priv->i2c_mutex);
- /* 0x00: chip id[6:0], 0x01: chip ver[7:0], 0x02: chip ver[15:8] */
- ret = m88ds3103_rd_reg(priv, 0x00, &chip_id);
+ ret = m88ds3103_rd_reg(priv, 0x01, &chip_id);
if (ret)
goto err;
- chip_id >>= 1;
- dev_info(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
+ dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
switch (chip_id) {
- case M88RS6000_CHIP_ID:
- case M88DS3103_CHIP_ID:
+ case 0xd0:
break;
default:
goto err;
}
- priv->chip_id = chip_id;
switch (priv->cfg->clock_out) {
case M88DS3103_CLOCK_OUT_DISABLED:
@@ -1409,11 +1337,6 @@
goto err;
}
- /* 0x29 register is defined differently for m88rs6000. */
- /* set internal tuner address to 0x21 */
- if (chip_id == M88RS6000_CHIP_ID)
- u8tmp = 0x00;
-
ret = m88ds3103_wr_reg(priv, 0x29, u8tmp);
if (ret)
goto err;
@@ -1441,9 +1364,6 @@
/* create dvb_frontend */
memcpy(&priv->fe.ops, &m88ds3103_ops, sizeof(struct dvb_frontend_ops));
- if (priv->chip_id == M88RS6000_CHIP_ID)
- strncpy(priv->fe.ops.info.name,
- "Montage M88RS6000", sizeof(priv->fe.ops.info.name));
priv->fe.demodulator_priv = priv;
return &priv->fe;
@@ -1503,4 +1423,3 @@
MODULE_DESCRIPTION("Montage M88DS3103 DVB-S/S2 demodulator driver");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(M88DS3103_FIRMWARE);
-MODULE_FIRMWARE(M88RS6000_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/m88ds3103_priv.h b/drivers/media/dvb-frontends/m88ds3103_priv.h
index a2c0958..9169fdd 100644
--- a/drivers/media/dvb-frontends/m88ds3103_priv.h
+++ b/drivers/media/dvb-frontends/m88ds3103_priv.h
@@ -25,10 +25,7 @@
#include <linux/math64.h>
#define M88DS3103_FIRMWARE "dvb-demod-m88ds3103.fw"
-#define M88RS6000_FIRMWARE "dvb-demod-m88rs6000.fw"
#define M88DS3103_MCLK_KHZ 96000
-#define M88RS6000_CHIP_ID 0x74
-#define M88DS3103_CHIP_ID 0x70
struct m88ds3103_priv {
struct i2c_adapter *i2c;
@@ -41,10 +38,6 @@
u32 ber;
bool warm; /* FW running */
struct i2c_adapter *i2c_adapter;
- /* auto detect chip id to do different config */
- u8 chip_id;
- /* main mclk is calculated for M88RS6000 dynamically */
- u32 mclk_khz;
};
struct m88ds3103_reg_val {
@@ -221,178 +214,4 @@
{0xb8, 0x00},
};
-static const struct m88ds3103_reg_val m88rs6000_dvbs_init_reg_vals[] = {
- {0x23, 0x07},
- {0x08, 0x03},
- {0x0c, 0x02},
- {0x20, 0x00},
- {0x21, 0x54},
- {0x25, 0x82},
- {0x27, 0x31},
- {0x30, 0x08},
- {0x31, 0x40},
- {0x32, 0x32},
- {0x33, 0x35},
- {0x35, 0xff},
- {0x3a, 0x00},
- {0x37, 0x10},
- {0x38, 0x10},
- {0x39, 0x02},
- {0x42, 0x60},
- {0x4a, 0x80},
- {0x4b, 0x04},
- {0x4d, 0x91},
- {0x5d, 0xc8},
- {0x50, 0x36},
- {0x51, 0x36},
- {0x52, 0x36},
- {0x53, 0x36},
- {0x63, 0x0f},
- {0x64, 0x30},
- {0x65, 0x40},
- {0x68, 0x26},
- {0x69, 0x4c},
- {0x70, 0x20},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0x40},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0x60},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0x80},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0xa0},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0x1f},
- {0x76, 0x38},
- {0x77, 0xa6},
- {0x78, 0x0c},
- {0x79, 0x80},
- {0x7f, 0x14},
- {0x7c, 0x00},
- {0xae, 0x82},
- {0x80, 0x64},
- {0x81, 0x66},
- {0x82, 0x44},
- {0x85, 0x04},
- {0xcd, 0xf4},
- {0x90, 0x33},
- {0xa0, 0x44},
- {0xbe, 0x00},
- {0xc0, 0x08},
- {0xc3, 0x10},
- {0xc4, 0x08},
- {0xc5, 0xf0},
- {0xc6, 0xff},
- {0xc7, 0x00},
- {0xc8, 0x1a},
- {0xc9, 0x80},
- {0xe0, 0xf8},
- {0xe6, 0x8b},
- {0xd0, 0x40},
- {0xf8, 0x20},
- {0xfa, 0x0f},
- {0x00, 0x00},
- {0xbd, 0x01},
- {0xb8, 0x00},
- {0x29, 0x11},
-};
-
-static const struct m88ds3103_reg_val m88rs6000_dvbs2_init_reg_vals[] = {
- {0x23, 0x07},
- {0x08, 0x07},
- {0x0c, 0x02},
- {0x20, 0x00},
- {0x21, 0x54},
- {0x25, 0x82},
- {0x27, 0x31},
- {0x30, 0x08},
- {0x32, 0x32},
- {0x33, 0x35},
- {0x35, 0xff},
- {0x3a, 0x00},
- {0x37, 0x10},
- {0x38, 0x10},
- {0x39, 0x02},
- {0x42, 0x60},
- {0x4a, 0x80},
- {0x4b, 0x04},
- {0x4d, 0x91},
- {0x5d, 0xc8},
- {0x50, 0x36},
- {0x51, 0x36},
- {0x52, 0x36},
- {0x53, 0x36},
- {0x63, 0x0f},
- {0x64, 0x10},
- {0x65, 0x20},
- {0x68, 0x46},
- {0x69, 0xcd},
- {0x70, 0x20},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0x40},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0x60},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0x80},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0xa0},
- {0x71, 0x70},
- {0x72, 0x04},
- {0x73, 0x00},
- {0x70, 0x1f},
- {0x76, 0x38},
- {0x77, 0xa6},
- {0x78, 0x0c},
- {0x79, 0x80},
- {0x7f, 0x14},
- {0x85, 0x08},
- {0xcd, 0xf4},
- {0x90, 0x33},
- {0x86, 0x00},
- {0x87, 0x0f},
- {0x89, 0x00},
- {0x8b, 0x44},
- {0x8c, 0x66},
- {0x9d, 0xc1},
- {0x8a, 0x10},
- {0xad, 0x40},
- {0xa0, 0x44},
- {0xbe, 0x00},
- {0xc0, 0x08},
- {0xc1, 0x10},
- {0xc2, 0x08},
- {0xc3, 0x10},
- {0xc4, 0x08},
- {0xc5, 0xf0},
- {0xc6, 0xff},
- {0xc7, 0x00},
- {0xc8, 0x1a},
- {0xc9, 0x80},
- {0xca, 0x23},
- {0xcb, 0x24},
- {0xcc, 0xf4},
- {0xce, 0x74},
- {0x00, 0x00},
- {0xbd, 0x01},
- {0xb8, 0x00},
- {0x29, 0x01},
-};
#endif
diff --git a/drivers/media/dvb-frontends/mn88472.h b/drivers/media/dvb-frontends/mn88472.h
deleted file mode 100644
index da4558b..0000000
--- a/drivers/media/dvb-frontends/mn88472.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Panasonic MN88472 DVB-T/T2/C demodulator driver
- *
- * Copyright (C) 2013 Antti Palosaari <crope@iki.fi>
- *
- * 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.
- */
-
-#ifndef MN88472_H
-#define MN88472_H
-
-#include <linux/dvb/frontend.h>
-
-struct mn88472_config {
- /*
- * Max num of bytes given I2C adapter could write at once.
- * Default: none
- */
- u16 i2c_wr_max;
-
-
- /* Everything after that is returned by the driver. */
-
- /*
- * DVB frontend.
- */
- struct dvb_frontend **fe;
-};
-
-#endif
diff --git a/drivers/media/dvb-frontends/mn88473.h b/drivers/media/dvb-frontends/mn88473.h
deleted file mode 100644
index a373ec9..0000000
--- a/drivers/media/dvb-frontends/mn88473.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Panasonic MN88473 DVB-T/T2/C demodulator driver
- *
- * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
- *
- * 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.
- */
-
-#ifndef MN88473_H
-#define MN88473_H
-
-#include <linux/dvb/frontend.h>
-
-struct mn88473_config {
- /*
- * Max num of bytes given I2C adapter could write at once.
- * Default: none
- */
- u16 i2c_wr_max;
-
-
- /* Everything after that is returned by the driver. */
-
- /*
- * DVB frontend.
- */
- struct dvb_frontend **fe;
-};
-
-#endif
diff --git a/drivers/media/dvb-frontends/rtl2832.c b/drivers/media/dvb-frontends/rtl2832.c
index 9026e1a..eb737cf 100644
--- a/drivers/media/dvb-frontends/rtl2832.c
+++ b/drivers/media/dvb-frontends/rtl2832.c
@@ -258,11 +258,13 @@
return rtl2832_rd(priv, reg, val, len);
}
+#if 0 /* currently not used */
/* write single register */
static int rtl2832_wr_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 val)
{
return rtl2832_wr_regs(priv, reg, page, &val, 1);
}
+#endif
/* read single register */
static int rtl2832_rd_reg(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val)
@@ -597,11 +599,6 @@
if (fe->ops.tuner_ops.set_params)
fe->ops.tuner_ops.set_params(fe);
- /* PIP mode related */
- ret = rtl2832_wr_regs(priv, 0x92, 1, "\x00\x0f\xff", 3);
- if (ret)
- goto err;
-
/* If the frontend has get_if_frequency(), use it */
if (fe->ops.tuner_ops.get_if_frequency) {
u32 if_freq;
@@ -664,6 +661,7 @@
if (ret)
goto err;
+
/* soft reset */
ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
if (ret)
@@ -1022,58 +1020,6 @@
return 0;
}
-int rtl2832_enable_external_ts_if(struct dvb_frontend *fe)
-{
- struct rtl2832_priv *priv = fe->demodulator_priv;
- int ret;
-
- dev_dbg(&priv->i2c->dev, "%s: setting PIP mode\n", __func__);
-
- ret = rtl2832_wr_regs(priv, 0x0c, 1, "\x5f\xff", 2);
- if (ret)
- goto err;
-
- ret = rtl2832_wr_demod_reg(priv, DVBT_PIP_ON, 0x1);
- if (ret)
- goto err;
-
- ret = rtl2832_wr_reg(priv, 0xbc, 0, 0x18);
- if (ret)
- goto err;
-
- ret = rtl2832_wr_reg(priv, 0x22, 0, 0x01);
- if (ret)
- goto err;
-
- ret = rtl2832_wr_reg(priv, 0x26, 0, 0x1f);
- if (ret)
- goto err;
-
- ret = rtl2832_wr_reg(priv, 0x27, 0, 0xff);
- if (ret)
- goto err;
-
- ret = rtl2832_wr_regs(priv, 0x92, 1, "\x7f\xf7\xff", 3);
- if (ret)
- goto err;
-
- /* soft reset */
- ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x1);
- if (ret)
- goto err;
-
- ret = rtl2832_wr_demod_reg(priv, DVBT_SOFT_RST, 0x0);
- if (ret)
- goto err;
-
- return 0;
-err:
- dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
- return ret;
-
-}
-EXPORT_SYMBOL(rtl2832_enable_external_ts_if);
-
struct i2c_adapter *rtl2832_get_i2c_adapter(struct dvb_frontend *fe)
{
struct rtl2832_priv *priv = fe->demodulator_priv;
diff --git a/drivers/media/dvb-frontends/rtl2832.h b/drivers/media/dvb-frontends/rtl2832.h
index 5e72630..f32b09c 100644
--- a/drivers/media/dvb-frontends/rtl2832.h
+++ b/drivers/media/dvb-frontends/rtl2832.h
@@ -64,10 +64,6 @@
struct dvb_frontend *fe
);
-extern int rtl2832_enable_external_ts_if(
- struct dvb_frontend *fe
-);
-
#else
static inline struct dvb_frontend *rtl2832_attach(
@@ -93,13 +89,6 @@
return NULL;
}
-static inline int rtl2832_enable_external_ts_if(
- struct dvb_frontend *fe
-)
-{
- return -ENODEV;
-}
-
#endif
diff --git a/drivers/media/dvb-frontends/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 2896b47..7bf98cf 100644
--- a/drivers/media/dvb-frontends/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -1013,10 +1013,6 @@
if (s->d->props->power_ctrl)
s->d->props->power_ctrl(s->d, 1);
- /* enable ADC */
- if (s->d->props->frontend_ctrl)
- s->d->props->frontend_ctrl(s->fe, 1);
-
set_bit(POWER_ON, &s->flags);
ret = rtl2832_sdr_set_tuner(s);
@@ -1068,10 +1064,6 @@
clear_bit(POWER_ON, &s->flags);
- /* disable ADC */
- if (s->d->props->frontend_ctrl)
- s->d->props->frontend_ctrl(s->fe, 0);
-
if (s->d->props->power_ctrl)
s->d->props->power_ctrl(s->d, 0);
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index ce9ab44..1cd93be 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -308,16 +308,14 @@
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x08", 6);
- cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10;
+ memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6);
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x05", 6);
- cmd.args[5] |= s->ts_clock_inv ? 0x00 : 0x10;
+ memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
@@ -455,45 +453,27 @@
dev_err(&s->client->dev,
"firmware file '%s' not found\n",
fw_file);
- goto error_fw_release;
+ goto err;
}
}
dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
fw_file);
- if ((fw->size % 17 == 0) && (fw->data[0] > 5)) {
- /* firmware is in the new format */
- for (remaining = fw->size; remaining > 0; remaining -= 17) {
- len = fw->data[fw->size - remaining];
- memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
- cmd.wlen = len;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret) {
- dev_err(&s->client->dev,
- "firmware download failed=%d\n",
- ret);
- goto error_fw_release;
- }
- }
- } else {
- /* firmware is in the old format */
- for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
- len = remaining;
- if (len > i2c_wr_max)
- len = i2c_wr_max;
+ for (remaining = fw->size; remaining > 0; remaining -= i2c_wr_max) {
+ len = remaining;
+ if (len > i2c_wr_max)
+ len = i2c_wr_max;
- memcpy(cmd.args, &fw->data[fw->size - remaining], len);
- cmd.wlen = len;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret) {
- dev_err(&s->client->dev,
- "firmware download failed=%d\n",
- ret);
- goto error_fw_release;
- }
+ memcpy(cmd.args, &fw->data[fw->size - remaining], len);
+ cmd.wlen = len;
+ cmd.rlen = 1;
+ ret = si2168_cmd_execute(s, &cmd);
+ if (ret) {
+ dev_err(&s->client->dev,
+ "firmware download failed=%d\n",
+ ret);
+ goto err;
}
}
@@ -507,17 +487,6 @@
if (ret)
goto err;
- /* query firmware version */
- memcpy(cmd.args, "\x11", 1);
- cmd.wlen = 1;
- cmd.rlen = 10;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- dev_dbg(&s->client->dev, "firmware version: %c.%c.%d\n",
- cmd.args[6], cmd.args[7], cmd.args[8]);
-
/* set ts mode */
memcpy(cmd.args, "\x14\x00\x01\x10\x10\x00", 6);
cmd.args[4] |= s->ts_mode;
@@ -529,16 +498,17 @@
s->fw_loaded = true;
+warm:
dev_info(&s->client->dev, "found a '%s' in warm state\n",
si2168_ops.info.name);
-warm:
+
s->active = true;
return 0;
-
-error_fw_release:
- release_firmware(fw);
err:
+ if (fw)
+ release_firmware(fw);
+
dev_dbg(&s->client->dev, "failed=%d\n", ret);
return ret;
}
@@ -700,7 +670,6 @@
*config->i2c_adapter = s->adapter;
*config->fe = &s->fe;
s->ts_mode = config->ts_mode;
- s->ts_clock_inv = config->ts_clock_inv;
s->fw_loaded = false;
i2c_set_clientdata(client, s);
diff --git a/drivers/media/dvb-frontends/si2168.h b/drivers/media/dvb-frontends/si2168.h
index 87bc121..e086d67 100644
--- a/drivers/media/dvb-frontends/si2168.h
+++ b/drivers/media/dvb-frontends/si2168.h
@@ -37,10 +37,6 @@
/* TS mode */
u8 ts_mode;
-
- /* TS clock inverted */
- bool ts_clock_inv;
-
};
#define SI2168_TS_PARALLEL 0x06
diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h
index 60bc334..e13983e 100644
--- a/drivers/media/dvb-frontends/si2168_priv.h
+++ b/drivers/media/dvb-frontends/si2168_priv.h
@@ -38,7 +38,6 @@
bool active;
bool fw_loaded;
u8 ts_mode;
- bool ts_clock_inv;
};
/* firmare command struct */
diff --git a/drivers/media/dvb-frontends/sp2.c b/drivers/media/dvb-frontends/sp2.c
index cc1ef96..9b684d5 100644
--- a/drivers/media/dvb-frontends/sp2.c
+++ b/drivers/media/dvb-frontends/sp2.c
@@ -92,9 +92,6 @@
return -EIO;
}
- dev_dbg(&s->client->dev, "addr=0x%04x, reg = 0x%02x, data = %*ph\n",
- client->addr, reg, len, buf);
-
return 0;
}
@@ -106,6 +103,9 @@
int mem, ret;
int (*ci_op_cam)(void*, u8, int, u8, int*) = s->ci_control;
+ dev_dbg(&s->client->dev, "slot=%d, acs=0x%02x, addr=0x%04x, data = 0x%02x",
+ slot, acs, addr, data);
+
if (slot != 0)
return -EINVAL;
@@ -140,16 +140,13 @@
if (ret)
return ret;
- dev_dbg(&s->client->dev, "%s: slot=%d, addr=0x%04x, %s, data=%x",
- (read) ? "read" : "write", slot, addr,
- (acs == SP2_CI_ATTR_ACS) ? "attr" : "io",
- (read) ? mem : data);
-
- if (read)
+ if (read) {
+ dev_dbg(&s->client->dev, "cam read, addr=0x%04x, data = 0x%04x",
+ addr, mem);
return mem;
- else
+ } else {
return 0;
-
+ }
}
int sp2_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
@@ -269,7 +266,7 @@
return s->status;
}
-static int sp2_init(struct sp2 *s)
+int sp2_init(struct sp2 *s)
{
int ret = 0;
u8 buf;
@@ -351,7 +348,7 @@
return ret;
}
-static int sp2_exit(struct i2c_client *client)
+int sp2_exit(struct i2c_client *client)
{
struct sp2 *s;
@@ -410,7 +407,7 @@
static int sp2_remove(struct i2c_client *client)
{
- struct sp2 *s = i2c_get_clientdata(client);
+ struct si2157 *s = i2c_get_clientdata(client);
dev_dbg(&client->dev, "\n");
diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
index 19646fb..07cd5ea 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -705,7 +705,7 @@
struct stb0899_state *state = fe->demodulator_priv;
u8 reg, i;
- if (cmd->msg_len > sizeof(cmd->msg))
+ if (cmd->msg_len > 8)
return -EINVAL;
/* enable FIFO precharge */
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
index 0b2a934..23e872f 100644
--- a/drivers/media/dvb-frontends/stv090x.c
+++ b/drivers/media/dvb-frontends/stv090x.c
@@ -2146,7 +2146,7 @@
u32 reg;
s32 car_step, steps, cur_step, dir, freq, timeout_lock;
- int lock;
+ int lock = 0;
if (state->srate >= 10000000)
timeout_lock = timeout_dmd / 3;
@@ -2154,96 +2154,98 @@
timeout_lock = timeout_dmd / 2;
lock = stv090x_get_dmdlock(state, timeout_lock); /* cold start wait */
- if (lock)
- return lock;
+ if (!lock) {
+ if (state->srate >= 10000000) {
+ if (stv090x_chk_tmg(state)) {
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+ goto err;
+ lock = stv090x_get_dmdlock(state, timeout_dmd);
+ } else {
+ lock = 0;
+ }
+ } else {
+ if (state->srate <= 4000000)
+ car_step = 1000;
+ else if (state->srate <= 7000000)
+ car_step = 2000;
+ else if (state->srate <= 10000000)
+ car_step = 3000;
+ else
+ car_step = 5000;
- if (state->srate >= 10000000) {
- if (stv090x_chk_tmg(state)) {
- if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
- goto err;
- if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
- goto err;
- return stv090x_get_dmdlock(state, timeout_dmd);
+ steps = (state->search_range / 1000) / car_step;
+ steps /= 2;
+ steps = 2 * (steps + 1);
+ if (steps < 0)
+ steps = 2;
+ else if (steps > 12)
+ steps = 12;
+
+ cur_step = 1;
+ dir = 1;
+
+ if (!lock) {
+ freq = state->frequency;
+ state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
+ while ((cur_step <= steps) && (!lock)) {
+ if (dir > 0)
+ freq += cur_step * car_step;
+ else
+ freq -= cur_step * car_step;
+
+ /* Setup tuner */
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_set_frequency) {
+ if (state->config->tuner_set_frequency(fe, freq) < 0)
+ goto err_gateoff;
+ }
+
+ if (state->config->tuner_set_bandwidth) {
+ if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
+ goto err_gateoff;
+ }
+
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+ goto err;
+
+ msleep(50);
+
+ if (stv090x_i2c_gate_ctrl(state, 1) < 0)
+ goto err;
+
+ if (state->config->tuner_get_status) {
+ if (state->config->tuner_get_status(fe, ®) < 0)
+ goto err_gateoff;
+ }
+
+ if (reg)
+ dprintk(FE_DEBUG, 1, "Tuner phase locked");
+ else
+ dprintk(FE_DEBUG, 1, "Tuner unlocked");
+
+ if (stv090x_i2c_gate_ctrl(state, 0) < 0)
+ goto err;
+
+ STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
+ if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
+ goto err;
+ if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
+ goto err;
+ lock = stv090x_get_dmdlock(state, (timeout_dmd / 3));
+
+ dir *= -1;
+ cur_step++;
+ }
+ }
}
- return 0;
- }
-
- if (state->srate <= 4000000)
- car_step = 1000;
- else if (state->srate <= 7000000)
- car_step = 2000;
- else if (state->srate <= 10000000)
- car_step = 3000;
- else
- car_step = 5000;
-
- steps = (state->search_range / 1000) / car_step;
- steps /= 2;
- steps = 2 * (steps + 1);
- if (steps < 0)
- steps = 2;
- else if (steps > 12)
- steps = 12;
-
- cur_step = 1;
- dir = 1;
-
- freq = state->frequency;
- state->tuner_bw = stv090x_car_width(state->srate, state->rolloff) + state->srate;
- while ((cur_step <= steps) && (!lock)) {
- if (dir > 0)
- freq += cur_step * car_step;
- else
- freq -= cur_step * car_step;
-
- /* Setup tuner */
- if (stv090x_i2c_gate_ctrl(state, 1) < 0)
- goto err;
-
- if (state->config->tuner_set_frequency) {
- if (state->config->tuner_set_frequency(fe, freq) < 0)
- goto err_gateoff;
- }
-
- if (state->config->tuner_set_bandwidth) {
- if (state->config->tuner_set_bandwidth(fe, state->tuner_bw) < 0)
- goto err_gateoff;
- }
-
- if (stv090x_i2c_gate_ctrl(state, 0) < 0)
- goto err;
-
- msleep(50);
-
- if (stv090x_i2c_gate_ctrl(state, 1) < 0)
- goto err;
-
- if (state->config->tuner_get_status) {
- if (state->config->tuner_get_status(fe, ®) < 0)
- goto err_gateoff;
- }
-
- if (reg)
- dprintk(FE_DEBUG, 1, "Tuner phase locked");
- else
- dprintk(FE_DEBUG, 1, "Tuner unlocked");
-
- if (stv090x_i2c_gate_ctrl(state, 0) < 0)
- goto err;
-
- STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1c);
- if (STV090x_WRITE_DEMOD(state, CFRINIT1, 0x00) < 0)
- goto err;
- if (STV090x_WRITE_DEMOD(state, CFRINIT0, 0x00) < 0)
- goto err;
- if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x1f) < 0)
- goto err;
- if (STV090x_WRITE_DEMOD(state, DMDISTATE, 0x15) < 0)
- goto err;
- lock = stv090x_get_dmdlock(state, (timeout_dmd / 3));
-
- dir *= -1;
- cur_step++;
}
return lock;
@@ -2661,9 +2663,13 @@
return STV090x_RANGEOK;
else if (abs(offst_freq) <= (stv090x_car_width(state->srate, state->rolloff) / 2000))
return STV090x_RANGEOK;
+ else
+ return STV090x_OUTOFRANGE; /* Out of Range */
} else {
if (abs(offst_freq) <= ((state->search_range / 2000) + 500))
return STV090x_RANGEOK;
+ else
+ return STV090x_OUTOFRANGE;
}
return STV090x_OUTOFRANGE;
@@ -2783,12 +2789,6 @@
aclc = car_loop[i].crl_pilots_off_30;
}
} else { /* 16APSK and 32APSK */
- /*
- * This should never happen in practice, except if
- * something is really wrong at the car_loop table.
- */
- if (i >= 11)
- i = 10;
if (state->srate <= 3000000)
aclc = car_loop_apsk_low[i].crl_pilots_on_2;
else if (state->srate <= 7000000)
@@ -3470,20 +3470,7 @@
if (props->frequency == 0)
return DVBFE_ALGO_SEARCH_INVALID;
- switch (props->delivery_system) {
- case SYS_DSS:
- state->delsys = STV090x_DSS;
- break;
- case SYS_DVBS:
- state->delsys = STV090x_DVBS1;
- break;
- case SYS_DVBS2:
- state->delsys = STV090x_DVBS2;
- break;
- default:
- return DVBFE_ALGO_SEARCH_INVALID;
- }
-
+ state->delsys = props->delivery_system;
state->frequency = props->frequency;
state->srate = props->symbol_rate;
state->search_mode = STV090x_SEARCH_AUTO;
@@ -4872,8 +4859,8 @@
return -1;
}
-static int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir,
- u8 value, u8 xor_value)
+int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
+ u8 xor_value)
{
struct stv090x_state *state = fe->demodulator_priv;
u8 reg = 0;
@@ -4884,6 +4871,7 @@
return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
}
+EXPORT_SYMBOL(stv090x_set_gpio);
static struct dvb_frontend_ops stv090x_ops = {
.delsys = { SYS_DVBS, SYS_DVBS2, SYS_DSS },
@@ -4920,7 +4908,7 @@
};
-struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
+struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
struct i2c_adapter *i2c,
enum stv090x_demodulator demod)
{
@@ -4981,8 +4969,6 @@
if (config->diseqc_envelope_mode)
stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
- config->set_gpio = stv090x_set_gpio;
-
dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
state->device == STV0900 ? "STV0900" : "STV0903",
demod,
diff --git a/drivers/media/dvb-frontends/stv090x.h b/drivers/media/dvb-frontends/stv090x.h
index 9a3ca6f..86ef794 100644
--- a/drivers/media/dvb-frontends/stv090x.h
+++ b/drivers/media/dvb-frontends/stv090x.h
@@ -89,29 +89,29 @@
bool diseqc_envelope_mode;
- int (*tuner_init)(struct dvb_frontend *fe);
- int (*tuner_sleep)(struct dvb_frontend *fe);
- int (*tuner_set_mode)(struct dvb_frontend *fe, enum tuner_mode mode);
- int (*tuner_set_frequency)(struct dvb_frontend *fe, u32 frequency);
- int (*tuner_get_frequency)(struct dvb_frontend *fe, u32 *frequency);
- int (*tuner_set_bandwidth)(struct dvb_frontend *fe, u32 bandwidth);
- int (*tuner_get_bandwidth)(struct dvb_frontend *fe, u32 *bandwidth);
- int (*tuner_set_bbgain)(struct dvb_frontend *fe, u32 gain);
- int (*tuner_get_bbgain)(struct dvb_frontend *fe, u32 *gain);
- int (*tuner_set_refclk)(struct dvb_frontend *fe, u32 refclk);
- int (*tuner_get_status)(struct dvb_frontend *fe, u32 *status);
- void (*tuner_i2c_lock)(struct dvb_frontend *fe, int lock);
-
- /* dir = 0 -> output, dir = 1 -> input/open-drain */
- int (*set_gpio)(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
- u8 xor_value);
+ int (*tuner_init) (struct dvb_frontend *fe);
+ int (*tuner_sleep) (struct dvb_frontend *fe);
+ int (*tuner_set_mode) (struct dvb_frontend *fe, enum tuner_mode mode);
+ int (*tuner_set_frequency) (struct dvb_frontend *fe, u32 frequency);
+ int (*tuner_get_frequency) (struct dvb_frontend *fe, u32 *frequency);
+ int (*tuner_set_bandwidth) (struct dvb_frontend *fe, u32 bandwidth);
+ int (*tuner_get_bandwidth) (struct dvb_frontend *fe, u32 *bandwidth);
+ int (*tuner_set_bbgain) (struct dvb_frontend *fe, u32 gain);
+ int (*tuner_get_bbgain) (struct dvb_frontend *fe, u32 *gain);
+ int (*tuner_set_refclk) (struct dvb_frontend *fe, u32 refclk);
+ int (*tuner_get_status) (struct dvb_frontend *fe, u32 *status);
+ void (*tuner_i2c_lock) (struct dvb_frontend *fe, int lock);
};
#if IS_ENABLED(CPTCFG_DVB_STV090x)
-struct dvb_frontend *stv090x_attach(struct stv090x_config *config,
- struct i2c_adapter *i2c,
- enum stv090x_demodulator demod);
+extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
+ struct i2c_adapter *i2c,
+ enum stv090x_demodulator demod);
+
+/* dir = 0 -> output, dir = 1 -> input/open-drain */
+extern int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
+ u8 dir, u8 value, u8 xor_value);
#else
@@ -123,6 +123,12 @@
return NULL;
}
+static inline int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
+ u8 opd, u8 value, u8 xor_value)
+{
+ printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+ return -ENODEV;
+}
#endif /* CPTCFG_DVB_STV090x */
#endif /* __STV090x_H */
diff --git a/drivers/media/dvb-frontends/tc90522.c b/drivers/media/dvb-frontends/tc90522.c
index b35d65c..d9905fb 100644
--- a/drivers/media/dvb-frontends/tc90522.c
+++ b/drivers/media/dvb-frontends/tc90522.c
@@ -216,30 +216,32 @@
c->delivery_system = SYS_ISDBS;
layers = 0;
- ret = reg_read(state, 0xe6, val, 5);
+ ret = reg_read(state, 0xe8, val, 3);
if (ret == 0) {
+ int slots;
u8 v;
- c->stream_id = val[0] << 8 | val[1];
-
/* high/single layer */
- v = (val[2] & 0x70) >> 4;
+ v = (val[0] & 0x70) >> 4;
c->modulation = (v == 7) ? PSK_8 : QPSK;
c->fec_inner = fec_conv_sat[v];
c->layer[0].fec = c->fec_inner;
c->layer[0].modulation = c->modulation;
- c->layer[0].segment_count = val[3] & 0x3f; /* slots */
+ c->layer[0].segment_count = val[1] & 0x3f; /* slots */
/* low layer */
- v = (val[2] & 0x07);
+ v = (val[0] & 0x07);
c->layer[1].fec = fec_conv_sat[v];
if (v == 0) /* no low layer */
c->layer[1].segment_count = 0;
else
- c->layer[1].segment_count = val[4] & 0x3f; /* slots */
+ c->layer[1].segment_count = val[2] & 0x3f; /* slots */
/* actually, BPSK if v==1, but not defined in fe_modulation_t */
c->layer[1].modulation = QPSK;
layers = (v > 0) ? 2 : 1;
+
+ slots = c->layer[0].segment_count + c->layer[1].segment_count;
+ c->symbol_rate = 28860000 * slots / 48;
}
/* statistics */
@@ -361,7 +363,7 @@
u8 v;
c->isdbt_partial_reception = val[0] & 0x01;
- c->isdbt_sb_mode = (val[0] & 0xc0) == 0x40;
+ c->isdbt_sb_mode = (val[0] & 0xc0) == 0x01;
/* layer A */
v = (val[2] & 0x78) >> 3;
diff --git a/drivers/media/firewire/Kconfig b/drivers/media/firewire/Kconfig
index 0a173ac..eea1e1d 100644
--- a/drivers/media/firewire/Kconfig
+++ b/drivers/media/firewire/Kconfig
@@ -1,5 +1,5 @@
config DVB_FIREDTV
- depends on !KERNEL_3_11
+ depends on !BACKPORT_KERNEL_3_11
tristate "FireDTV and FloppyDTV"
depends on m
depends on DVB_CORE && FIREWIRE
diff --git a/drivers/media/firewire/firedtv-ci.c b/drivers/media/firewire/firedtv-ci.c
index e63f582..e5ebdbf 100644
--- a/drivers/media/firewire/firedtv-ci.c
+++ b/drivers/media/firewire/firedtv-ci.c
@@ -253,5 +253,6 @@
void fdtv_ca_release(struct firedtv *fdtv)
{
- dvb_unregister_device(fdtv->cadev);
+ if (fdtv->cadev)
+ dvb_unregister_device(fdtv->cadev);
}
diff --git a/drivers/media/firewire/firedtv.h b/drivers/media/firewire/firedtv.h
index 23972d2..0d79513 100644
--- a/drivers/media/firewire/firedtv.h
+++ b/drivers/media/firewire/firedtv.h
@@ -96,7 +96,7 @@
enum model_type type;
char subunit;
- s8 isochannel;
+ char isochannel;
struct fdtv_ir_context *ir_context;
fe_sec_voltage_t voltage;
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index bd78e2f..1482285 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -213,7 +213,7 @@
module will be called adv7183.
config VIDEO_ADV7604
- depends on !KERNEL_3_13
+ depends on !BACKPORT_KERNEL_3_13
tristate "Analog Devices ADV7604 decoder"
depends on m
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && MEDIA_CONTROLLER
@@ -312,6 +312,16 @@
To compile this driver as a module, choose M here: the
module will be called saa7115.
+config VIDEO_SAA7191
+ tristate "Philips SAA7191 video decoder"
+ depends on m
+ depends on VIDEO_V4L2 && I2C
+ ---help---
+ Support for the Philips SAA7191 video decoder.
+
+ To compile this driver as a module, choose M here: the
+ module will be called saa7191.
+
config VIDEO_TVP514X
tristate "Texas Instruments TVP514x video decoder"
depends on m
@@ -443,7 +453,6 @@
module will be called adv7175.
config VIDEO_ADV7343
- depends on !KERNEL_3_4
tristate "ADV7343 video encoder"
depends on m
depends on I2C
@@ -567,7 +576,7 @@
models only.
config VIDEO_MT9P031
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_3
tristate "Aptina MT9P031 support"
depends on m
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -578,7 +587,7 @@
(Micron) mt9p031 5 Mpixel camera.
config VIDEO_MT9T001
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_3
tristate "Aptina MT9T001 support"
depends on m
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -598,7 +607,7 @@
em28xx driver.
config VIDEO_MT9V032
- depends on !KERNEL_3_3
+ depends on !BACKPORT_KERNEL_3_3
tristate "Micron MT9V032 sensor support"
depends on m
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -617,7 +626,7 @@
This driver supports SR030PC30 VGA camera from Siliconfile
config VIDEO_NOON010PC30
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_3
tristate "Siliconfile NOON010PC30 sensor support"
depends on m
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -628,8 +637,7 @@
source "drivers/media/i2c/m5mols/Kconfig"
config VIDEO_S5K6AA
- depends on !KERNEL_3_3
- depends on !KERNEL_3_13
+ depends on !BACKPORT_KERNEL_3_3
tristate "Samsung S5K6AAFX sensor support"
depends on m
depends on MEDIA_CAMERA_SUPPORT
@@ -639,7 +647,7 @@
camera sensor with an embedded SoC image signal processor.
config VIDEO_S5K6A3
- depends on !KERNEL_3_13
+ depends on !BACKPORT_KERNEL_3_3
tristate "Samsung S5K6A3 sensor support"
depends on m
depends on MEDIA_CAMERA_SUPPORT
@@ -649,7 +657,7 @@
camera sensor.
config VIDEO_S5K4ECGX
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_3
tristate "Samsung S5K4ECGX sensor support"
depends on m
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -658,7 +666,7 @@
camera sensor with an embedded SoC image signal processor.
config VIDEO_S5K5BAF
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_3
tristate "Samsung S5K5BAF sensor support"
depends on m
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -669,7 +677,7 @@
source "drivers/media/i2c/smiapp/Kconfig"
config VIDEO_S5C73M3
- depends on !KERNEL_3_6
+ depends on !BACKPORT_KERNEL_3_3
tristate "Samsung S5C73M3 sensor support"
depends on m
depends on I2C && SPI && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
@@ -698,7 +706,7 @@
build in control for flash, torch and indicator LEDs.
config VIDEO_LM3560
- depends on !KERNEL_3_3
+ depends on !BACKPORT_KERNEL_3_3
tristate "LM3560 dual flash driver support"
depends on m
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
@@ -709,7 +717,7 @@
flash, torch LEDs.
config VIDEO_LM3646
- depends on !KERNEL_3_3
+ depends on !BACKPORT_KERNEL_3_3
tristate "LM3646 dual flash driver support"
depends on m
depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
index 61f289c..6345c00 100644
--- a/drivers/media/i2c/Makefile
+++ b/drivers/media/i2c/Makefile
@@ -18,6 +18,7 @@
obj-$(CPTCFG_VIDEO_SAA717X) += saa717x.o
obj-$(CPTCFG_VIDEO_SAA7127) += saa7127.o
obj-$(CPTCFG_VIDEO_SAA7185) += saa7185.o
+obj-$(CPTCFG_VIDEO_SAA7191) += saa7191.o
obj-$(CPTCFG_VIDEO_SAA6752HS) += saa6752hs.o
obj-$(CPTCFG_VIDEO_ADV7170) += adv7170.o
obj-$(CPTCFG_VIDEO_ADV7175) += adv7175.o
diff --git a/drivers/media/i2c/adv7170.c b/drivers/media/i2c/adv7170.c
index 40a1a95..04bb297 100644
--- a/drivers/media/i2c/adv7170.c
+++ b/drivers/media/i2c/adv7170.c
@@ -63,9 +63,9 @@
static char *inputs[] = { "pass_through", "play_back" };
-static u32 adv7170_codes[] = {
- MEDIA_BUS_FMT_UYVY8_2X8,
- MEDIA_BUS_FMT_UYVY8_1X16,
+static enum v4l2_mbus_pixelcode adv7170_codes[] = {
+ V4L2_MBUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_UYVY8_1X16,
};
/* ----------------------------------------------------------------------- */
@@ -263,7 +263,7 @@
}
static int adv7170_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(adv7170_codes))
return -EINVAL;
@@ -278,9 +278,9 @@
u8 val = adv7170_read(sd, 0x7);
if ((val & 0x40) == (1 << 6))
- mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
+ mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
else
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
mf->width = 0;
@@ -297,11 +297,11 @@
int ret;
switch (mf->code) {
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
val &= ~0x40;
break;
- case MEDIA_BUS_FMT_UYVY8_1X16:
+ case V4L2_MBUS_FMT_UYVY8_1X16:
val |= 0x40;
break;
diff --git a/drivers/media/i2c/adv7175.c b/drivers/media/i2c/adv7175.c
index d220af5..b88f3b3 100644
--- a/drivers/media/i2c/adv7175.c
+++ b/drivers/media/i2c/adv7175.c
@@ -60,9 +60,9 @@
static char *inputs[] = { "pass_through", "play_back", "color_bar" };
-static u32 adv7175_codes[] = {
- MEDIA_BUS_FMT_UYVY8_2X8,
- MEDIA_BUS_FMT_UYVY8_1X16,
+static enum v4l2_mbus_pixelcode adv7175_codes[] = {
+ V4L2_MBUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_UYVY8_1X16,
};
/* ----------------------------------------------------------------------- */
@@ -301,7 +301,7 @@
}
static int adv7175_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(adv7175_codes))
return -EINVAL;
@@ -316,9 +316,9 @@
u8 val = adv7175_read(sd, 0x7);
if ((val & 0x40) == (1 << 6))
- mf->code = MEDIA_BUS_FMT_UYVY8_1X16;
+ mf->code = V4L2_MBUS_FMT_UYVY8_1X16;
else
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
mf->width = 0;
@@ -335,11 +335,11 @@
int ret;
switch (mf->code) {
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
val &= ~0x40;
break;
- case MEDIA_BUS_FMT_UYVY8_1X16:
+ case V4L2_MBUS_FMT_UYVY8_1X16:
val |= 0x40;
break;
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index bffe6eb..821178d 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -422,12 +422,12 @@
}
static int adv7180_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_YUYV8_2X8;
+ *code = V4L2_MBUS_FMT_YUYV8_2X8;
return 0;
}
@@ -437,7 +437,7 @@
{
struct adv7180_state *state = to_state(sd);
- fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ fmt->code = V4L2_MBUS_FMT_YUYV8_2X8;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
fmt->field = V4L2_FIELD_INTERLACED;
fmt->width = 720;
diff --git a/drivers/media/i2c/adv7183.c b/drivers/media/i2c/adv7183.c
index 905890a..3222c79 100644
--- a/drivers/media/i2c/adv7183.c
+++ b/drivers/media/i2c/adv7183.c
@@ -421,12 +421,12 @@
}
static int adv7183_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_UYVY8_2X8;
+ *code = V4L2_MBUS_FMT_UYVY8_2X8;
return 0;
}
@@ -435,7 +435,7 @@
{
struct adv7183 *decoder = to_adv7183(sd);
- fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ 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;
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index 3a943c6..7b2d7ce 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -26,7 +26,6 @@
#include <linux/videodev2.h>
#include <linux/gpio.h>
#include <linux/workqueue.h>
-#include <linux/hdmi.h>
#include <linux/v4l2-dv-timings.h>
#include <media/v4l2-device.h>
#include <media/v4l2-common.h>
@@ -97,10 +96,6 @@
bool have_monitor;
/* timings from s_dv_timings */
struct v4l2_dv_timings dv_timings;
- u32 fmt_code;
- u32 colorspace;
- u32 ycbcr_enc;
- u32 quantization;
/* controls */
struct v4l2_ctrl *hdmi_mode_ctrl;
struct v4l2_ctrl *hotplug_ctrl;
@@ -784,234 +779,26 @@
{
struct adv7511_state *state = get_adv7511_state(sd);
- memset(edid->reserved, 0, sizeof(edid->reserved));
-
if (edid->pad != 0)
return -EINVAL;
-
- if (edid->start_block == 0 && edid->blocks == 0) {
- edid->blocks = state->edid.segments * 2;
- return 0;
- }
-
- if (state->edid.segments == 0)
- return -ENODATA;
-
- if (edid->start_block >= state->edid.segments * 2)
+ if ((edid->blocks == 0) || (edid->blocks > 256))
return -EINVAL;
-
- if (edid->start_block + edid->blocks > state->edid.segments * 2)
+ if (!state->edid.segments) {
+ v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
+ return -ENODATA;
+ }
+ if (edid->start_block >= state->edid.segments * 2)
+ return -E2BIG;
+ if ((edid->blocks + edid->start_block) >= state->edid.segments * 2)
edid->blocks = state->edid.segments * 2 - edid->start_block;
memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
128 * edid->blocks);
-
- return 0;
-}
-
-static int adv7511_enum_mbus_code(struct v4l2_subdev *sd,
- struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_mbus_code_enum *code)
-{
- if (code->pad != 0)
- return -EINVAL;
-
- switch (code->index) {
- case 0:
- code->code = MEDIA_BUS_FMT_RGB888_1X24;
- break;
- case 1:
- code->code = MEDIA_BUS_FMT_YUYV8_1X16;
- break;
- case 2:
- code->code = MEDIA_BUS_FMT_UYVY8_1X16;
- break;
- default:
- return -EINVAL;
- }
- return 0;
-}
-
-static void adv7511_fill_format(struct adv7511_state *state,
- struct v4l2_mbus_framefmt *format)
-{
- memset(format, 0, sizeof(*format));
-
- format->width = state->dv_timings.bt.width;
- format->height = state->dv_timings.bt.height;
- format->field = V4L2_FIELD_NONE;
-}
-
-static int adv7511_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_format *format)
-{
- struct adv7511_state *state = get_adv7511_state(sd);
-
- if (format->pad != 0)
- return -EINVAL;
-
- adv7511_fill_format(state, &format->format);
-
- if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- struct v4l2_mbus_framefmt *fmt;
-
- fmt = v4l2_subdev_get_try_format(fh, format->pad);
- format->format.code = fmt->code;
- format->format.colorspace = fmt->colorspace;
- format->format.ycbcr_enc = fmt->ycbcr_enc;
- format->format.quantization = fmt->quantization;
- } else {
- format->format.code = state->fmt_code;
- format->format.colorspace = state->colorspace;
- format->format.ycbcr_enc = state->ycbcr_enc;
- format->format.quantization = state->quantization;
- }
-
- return 0;
-}
-
-static int adv7511_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_format *format)
-{
- struct adv7511_state *state = get_adv7511_state(sd);
- /*
- * Bitfield namings come the CEA-861-F standard, table 8 "Auxiliary
- * Video Information (AVI) InfoFrame Format"
- *
- * c = Colorimetry
- * ec = Extended Colorimetry
- * y = RGB or YCbCr
- * q = RGB Quantization Range
- * yq = YCC Quantization Range
- */
- u8 c = HDMI_COLORIMETRY_NONE;
- u8 ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
- u8 y = HDMI_COLORSPACE_RGB;
- u8 q = HDMI_QUANTIZATION_RANGE_DEFAULT;
- u8 yq = HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
-
- if (format->pad != 0)
- return -EINVAL;
- switch (format->format.code) {
- case MEDIA_BUS_FMT_UYVY8_1X16:
- case MEDIA_BUS_FMT_YUYV8_1X16:
- case MEDIA_BUS_FMT_RGB888_1X24:
- break;
- default:
- return -EINVAL;
- }
-
- adv7511_fill_format(state, &format->format);
- if (format->which == V4L2_SUBDEV_FORMAT_TRY) {
- struct v4l2_mbus_framefmt *fmt;
-
- fmt = v4l2_subdev_get_try_format(fh, format->pad);
- fmt->code = format->format.code;
- fmt->colorspace = format->format.colorspace;
- fmt->ycbcr_enc = format->format.ycbcr_enc;
- fmt->quantization = format->format.quantization;
- return 0;
- }
-
- switch (format->format.code) {
- case MEDIA_BUS_FMT_UYVY8_1X16:
- adv7511_wr_and_or(sd, 0x15, 0xf0, 0x01);
- adv7511_wr_and_or(sd, 0x16, 0x03, 0xb8);
- y = HDMI_COLORSPACE_YUV422;
- break;
- case MEDIA_BUS_FMT_YUYV8_1X16:
- adv7511_wr_and_or(sd, 0x15, 0xf0, 0x01);
- adv7511_wr_and_or(sd, 0x16, 0x03, 0xbc);
- y = HDMI_COLORSPACE_YUV422;
- break;
- case MEDIA_BUS_FMT_RGB888_1X24:
- default:
- adv7511_wr_and_or(sd, 0x15, 0xf0, 0x00);
- adv7511_wr_and_or(sd, 0x16, 0x03, 0x00);
- break;
- }
- state->fmt_code = format->format.code;
- state->colorspace = format->format.colorspace;
- state->ycbcr_enc = format->format.ycbcr_enc;
- state->quantization = format->format.quantization;
-
- switch (format->format.colorspace) {
- case V4L2_COLORSPACE_ADOBERGB:
- c = HDMI_COLORIMETRY_EXTENDED;
- ec = y ? HDMI_EXTENDED_COLORIMETRY_ADOBE_YCC_601 :
- HDMI_EXTENDED_COLORIMETRY_ADOBE_RGB;
- break;
- case V4L2_COLORSPACE_SMPTE170M:
- c = y ? HDMI_COLORIMETRY_ITU_601 : HDMI_COLORIMETRY_NONE;
- if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_XV601) {
- c = HDMI_COLORIMETRY_EXTENDED;
- ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
- }
- break;
- case V4L2_COLORSPACE_REC709:
- c = y ? HDMI_COLORIMETRY_ITU_709 : HDMI_COLORIMETRY_NONE;
- if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_XV709) {
- c = HDMI_COLORIMETRY_EXTENDED;
- ec = HDMI_EXTENDED_COLORIMETRY_XV_YCC_709;
- }
- break;
- case V4L2_COLORSPACE_SRGB:
- c = y ? HDMI_COLORIMETRY_EXTENDED : HDMI_COLORIMETRY_NONE;
- ec = y ? HDMI_EXTENDED_COLORIMETRY_S_YCC_601 :
- HDMI_EXTENDED_COLORIMETRY_XV_YCC_601;
- break;
- case V4L2_COLORSPACE_BT2020:
- c = HDMI_COLORIMETRY_EXTENDED;
- if (y && format->format.ycbcr_enc == V4L2_YCBCR_ENC_BT2020_CONST_LUM)
- ec = 5; /* Not yet available in hdmi.h */
- else
- ec = 6; /* Not yet available in hdmi.h */
- break;
- default:
- break;
- }
-
- /*
- * CEA-861-F says that for RGB formats the YCC range must match the
- * RGB range, although sources should ignore the YCC range.
- *
- * The RGB quantization range shouldn't be non-zero if the EDID doesn't
- * have the Q bit set in the Video Capabilities Data Block, however this
- * isn't checked at the moment. The assumption is that the application
- * knows the EDID and can detect this.
- *
- * The same is true for the YCC quantization range: non-standard YCC
- * quantization ranges should only be sent if the EDID has the YQ bit
- * set in the Video Capabilities Data Block.
- */
- switch (format->format.quantization) {
- case V4L2_QUANTIZATION_FULL_RANGE:
- q = y ? HDMI_QUANTIZATION_RANGE_DEFAULT :
- HDMI_QUANTIZATION_RANGE_FULL;
- yq = q ? q - 1 : HDMI_YCC_QUANTIZATION_RANGE_FULL;
- break;
- case V4L2_QUANTIZATION_LIM_RANGE:
- q = y ? HDMI_QUANTIZATION_RANGE_DEFAULT :
- HDMI_QUANTIZATION_RANGE_LIMITED;
- yq = q ? q - 1 : HDMI_YCC_QUANTIZATION_RANGE_LIMITED;
- break;
- }
-
- adv7511_wr_and_or(sd, 0x4a, 0xbf, 0);
- adv7511_wr_and_or(sd, 0x55, 0x9f, y << 5);
- adv7511_wr_and_or(sd, 0x56, 0x3f, c << 6);
- adv7511_wr_and_or(sd, 0x57, 0x83, (ec << 4) | (q << 2));
- adv7511_wr_and_or(sd, 0x59, 0x0f, yq << 4);
- adv7511_wr_and_or(sd, 0x4a, 0xff, 1);
-
return 0;
}
static const struct v4l2_subdev_pad_ops adv7511_pad_ops = {
.get_edid = adv7511_get_edid,
- .enum_mbus_code = adv7511_enum_mbus_code,
- .get_fmt = adv7511_get_fmt,
- .set_fmt = adv7511_set_fmt,
.enum_dv_timings = adv7511_enum_dv_timings,
.dv_timings_cap = adv7511_dv_timings_cap,
};
@@ -1329,8 +1116,6 @@
return -ENODEV;
}
memcpy(&state->pdata, pdata, sizeof(state->pdata));
- state->fmt_code = MEDIA_BUS_FMT_RGB888_1X24;
- state->colorspace = V4L2_COLORSPACE_SRGB;
sd = &state->sd;
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 764b2b7..bb6c3a4 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -88,7 +88,7 @@
};
struct adv7604_format_info {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
u8 op_ch_sel;
bool rgb_out;
bool swap_cb_cr;
@@ -749,77 +749,77 @@
*/
static const struct adv7604_format_info adv7604_formats[] = {
- { MEDIA_BUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+ { V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV10_2X10, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
- { MEDIA_BUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU10_2X10, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_10BIT },
- { MEDIA_BUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+ { V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+ { V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
+ { V4L2_MBUS_FMT_UYVY10_1X20, ADV7604_OP_CH_SEL_RBG, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
- { MEDIA_BUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
+ { V4L2_MBUS_FMT_VYUY10_1X20, ADV7604_OP_CH_SEL_RBG, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
- { MEDIA_BUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV10_1X20, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
- { MEDIA_BUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU10_1X20, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_10BIT },
- { MEDIA_BUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+ { V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+ { V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
};
static const struct adv7604_format_info adv7611_formats[] = {
- { MEDIA_BUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
+ { V4L2_MBUS_FMT_RGB888_1X24, ADV7604_OP_CH_SEL_RGB, true, false,
ADV7604_OP_MODE_SEL_SDR_444 | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV8_2X8, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU8_2X8, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV12_2X12, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU12_2X12, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422 | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
+ { V4L2_MBUS_FMT_UYVY8_1X16, ADV7604_OP_CH_SEL_RBG, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
+ { V4L2_MBUS_FMT_VYUY8_1X16, ADV7604_OP_CH_SEL_RBG, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV8_1X16, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU8_1X16, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_8BIT },
- { MEDIA_BUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
+ { V4L2_MBUS_FMT_UYVY12_1X24, ADV7604_OP_CH_SEL_RBG, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
+ { V4L2_MBUS_FMT_VYUY12_1X24, ADV7604_OP_CH_SEL_RBG, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
+ { V4L2_MBUS_FMT_YUYV12_1X24, ADV7604_OP_CH_SEL_RGB, false, false,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
- { MEDIA_BUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
+ { V4L2_MBUS_FMT_YVYU12_1X24, ADV7604_OP_CH_SEL_RGB, false, true,
ADV7604_OP_MODE_SEL_SDR_422_2X | ADV7604_OP_FORMAT_SEL_12BIT },
};
static const struct adv7604_format_info *
-adv7604_format_info(struct adv7604_state *state, u32 code)
+adv7604_format_info(struct adv7604_state *state, enum v4l2_mbus_pixelcode code)
{
unsigned int i;
@@ -1917,7 +1917,7 @@
info = adv7604_format_info(state, format->format.code);
if (info == NULL)
- info = adv7604_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
+ info = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
adv7604_fill_format(state, &format->format);
format->format.code = info->code;
@@ -1997,7 +1997,19 @@
struct adv7604_state *state = to_state(sd);
u8 *data = NULL;
- memset(edid->reserved, 0, sizeof(edid->reserved));
+ if (edid->pad > ADV7604_PAD_HDMI_PORT_D)
+ return -EINVAL;
+ if (edid->blocks == 0)
+ return -EINVAL;
+ if (edid->blocks > 2)
+ return -EINVAL;
+ if (edid->start_block > 1)
+ return -EINVAL;
+ if (edid->start_block == 1)
+ edid->blocks = 1;
+
+ if (edid->blocks > state->edid.blocks)
+ edid->blocks = state->edid.blocks;
switch (edid->pad) {
case ADV7604_PAD_HDMI_PORT_A:
@@ -2009,24 +2021,14 @@
break;
default:
return -EINVAL;
+ break;
}
-
- if (edid->start_block == 0 && edid->blocks == 0) {
- edid->blocks = data ? state->edid.blocks : 0;
- return 0;
- }
-
- if (data == NULL)
+ if (!data)
return -ENODATA;
- if (edid->start_block >= state->edid.blocks)
- return -EINVAL;
-
- if (edid->start_block + edid->blocks > state->edid.blocks)
- edid->blocks = state->edid.blocks - edid->start_block;
-
- memcpy(edid->edid, data + edid->start_block * 128, edid->blocks * 128);
-
+ memcpy(edid->edid,
+ data + edid->start_block * 128,
+ edid->blocks * 128);
return 0;
}
@@ -2066,8 +2068,6 @@
int err;
int i;
- memset(edid->reserved, 0, sizeof(edid->reserved));
-
if (edid->pad > ADV7604_PAD_HDMI_PORT_D)
return -EINVAL;
if (edid->start_block != 0)
@@ -2164,6 +2164,7 @@
return -EIO;
}
+
/* enable hotplug after 100 ms */
queue_delayed_work(state->work_queues,
&state->delayed_work_enable_hotplug, HZ / 10);
@@ -2806,7 +2807,7 @@
}
state->timings = cea640x480;
- state->format = adv7604_format_info(state, MEDIA_BUS_FMT_YUYV8_2X8);
+ state->format = adv7604_format_info(state, V4L2_MBUS_FMT_YUYV8_2X8);
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
diff --git a/drivers/media/i2c/adv7842.c b/drivers/media/i2c/adv7842.c
index 9af02d3..ba8e833 100644
--- a/drivers/media/i2c/adv7842.c
+++ b/drivers/media/i2c/adv7842.c
@@ -1877,12 +1877,12 @@
}
static int adv7842_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index)
return -EINVAL;
/* Good enough for now */
- *code = MEDIA_BUS_FMT_FIXED;
+ *code = V4L2_MBUS_FMT_FIXED;
return 0;
}
@@ -1893,7 +1893,7 @@
fmt->width = state->timings.bt.width;
fmt->height = state->timings.bt.height;
- fmt->code = MEDIA_BUS_FMT_FIXED;
+ fmt->code = V4L2_MBUS_FMT_FIXED;
fmt->field = V4L2_FIELD_NONE;
if (state->mode == ADV7842_MODE_SDP) {
@@ -2028,7 +2028,16 @@
struct adv7842_state *state = to_state(sd);
u8 *data = NULL;
- memset(edid->reserved, 0, sizeof(edid->reserved));
+ if (edid->pad > ADV7842_EDID_PORT_VGA)
+ return -EINVAL;
+ if (edid->blocks == 0)
+ return -EINVAL;
+ if (edid->blocks > 2)
+ return -EINVAL;
+ if (edid->start_block > 1)
+ return -EINVAL;
+ if (edid->start_block == 1)
+ edid->blocks = 1;
switch (edid->pad) {
case ADV7842_EDID_PORT_A:
@@ -2043,23 +2052,12 @@
default:
return -EINVAL;
}
-
- if (edid->start_block == 0 && edid->blocks == 0) {
- edid->blocks = data ? 2 : 0;
- return 0;
- }
-
if (!data)
return -ENODATA;
- if (edid->start_block >= 2)
- return -EINVAL;
-
- if (edid->start_block + edid->blocks > 2)
- edid->blocks = 2 - edid->start_block;
-
- memcpy(edid->edid, data + edid->start_block * 128, edid->blocks * 128);
-
+ memcpy(edid->edid,
+ data + edid->start_block * 128,
+ edid->blocks * 128);
return 0;
}
@@ -2068,16 +2066,12 @@
struct adv7842_state *state = to_state(sd);
int err = 0;
- memset(e->reserved, 0, sizeof(e->reserved));
-
if (e->pad > ADV7842_EDID_PORT_VGA)
return -EINVAL;
if (e->start_block != 0)
return -EINVAL;
- if (e->blocks > 2) {
- e->blocks = 2;
+ if (e->blocks > 2)
return -E2BIG;
- }
/* todo, per edid */
state->aspect_ratio = v4l2_calc_aspect_ratio(e->edid[0x15],
diff --git a/drivers/media/i2c/ak881x.c b/drivers/media/i2c/ak881x.c
index c8076f2..b480759 100644
--- a/drivers/media/i2c/ak881x.c
+++ b/drivers/media/i2c/ak881x.c
@@ -102,7 +102,7 @@
v4l_bound_align_image(&mf->width, 0, 720, 2,
&mf->height, 0, ak881x->lines, 1, 0);
mf->field = V4L2_FIELD_INTERLACED;
- mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
mf->colorspace = V4L2_COLORSPACE_SMPTE170M;
return 0;
@@ -112,19 +112,19 @@
struct v4l2_mbus_framefmt *mf)
{
if (mf->field != V4L2_FIELD_INTERLACED ||
- mf->code != MEDIA_BUS_FMT_YUYV8_2X8)
+ mf->code != V4L2_MBUS_FMT_YUYV8_2X8)
return -EINVAL;
return ak881x_try_g_mbus_fmt(sd, mf);
}
static int ak881x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_YUYV8_2X8;
+ *code = V4L2_MBUS_FMT_YUYV8_2X8;
return 0;
}
diff --git a/drivers/media/i2c/cx25840/cx25840-core.c b/drivers/media/i2c/cx25840/cx25840-core.c
index 05b7cd6..f460ce0 100644
--- a/drivers/media/i2c/cx25840/cx25840-core.c
+++ b/drivers/media/i2c/cx25840/cx25840-core.c
@@ -879,7 +879,7 @@
/* Sets horizontal blanking delay and active lines */
cx25840_write(client, 0x470, hblank);
cx25840_write(client, 0x471,
- (((hblank >> 8) & 0x3) | (hactive << 4)) & 0xff);
+ 0xff & (((hblank >> 8) & 0x3) | (hactive << 4)));
cx25840_write(client, 0x472, hactive >> 4);
/* Sets burst gate delay */
@@ -888,13 +888,13 @@
/* Sets vertical blanking delay and active duration */
cx25840_write(client, 0x474, vblank);
cx25840_write(client, 0x475,
- (((vblank >> 8) & 0x3) | (vactive << 4)) & 0xff);
+ 0xff & (((vblank >> 8) & 0x3) | (vactive << 4)));
cx25840_write(client, 0x476, vactive >> 4);
cx25840_write(client, 0x477, vblank656);
/* Sets src decimation rate */
- cx25840_write(client, 0x478, src_decimation & 0xff);
- cx25840_write(client, 0x479, (src_decimation >> 8) & 0xff);
+ cx25840_write(client, 0x478, 0xff & src_decimation);
+ cx25840_write(client, 0x479, 0xff & (src_decimation >> 8));
/* Sets Luma and UV Low pass filters */
cx25840_write(client, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
@@ -904,8 +904,8 @@
/* Sets SC Step*/
cx25840_write(client, 0x47c, sc);
- cx25840_write(client, 0x47d, (sc >> 8) & 0xff);
- cx25840_write(client, 0x47e, (sc >> 16) & 0xff);
+ cx25840_write(client, 0x47d, 0xff & sc >> 8);
+ cx25840_write(client, 0x47e, 0xff & sc >> 16);
/* Sets VBI parameters */
if (std & V4L2_STD_625_50) {
@@ -1373,7 +1373,7 @@
int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60);
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (fmt->code != V4L2_MBUS_FMT_FIXED)
return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
diff --git a/drivers/media/i2c/cx25840/cx25840-firmware.c b/drivers/media/i2c/cx25840/cx25840-firmware.c
index 9bbb31a..b3169f9 100644
--- a/drivers/media/i2c/cx25840/cx25840-firmware.c
+++ b/drivers/media/i2c/cx25840/cx25840-firmware.c
@@ -113,7 +113,7 @@
const u8 *ptr;
const char *fwname = get_fw_name(client);
int size, retval;
- int max_buf_size = FWSEND;
+ int MAX_BUF_SIZE = FWSEND;
u32 gpio_oe = 0, gpio_da = 0;
if (is_cx2388x(state)) {
@@ -122,9 +122,10 @@
gpio_da = cx25840_read(client, 0x164);
}
- /* cx231xx cannot accept more than 16 bytes at a time */
- if (is_cx231xx(state) && max_buf_size > 16)
- max_buf_size = 16;
+ if (is_cx231xx(state) && MAX_BUF_SIZE > 16) {
+ v4l_err(client, " Firmware download size changed to 16 bytes max length\n");
+ MAX_BUF_SIZE = 16; /* cx231xx cannot accept more than 16 bytes at a time */
+ }
if (request_firmware(&fw, fwname, FWDEV(client)) != 0) {
v4l_err(client, "unable to open firmware %s\n", fwname);
@@ -139,7 +140,7 @@
size = fw->size;
ptr = fw->data;
while (size > 0) {
- int len = min(max_buf_size - 2, size);
+ int len = min(MAX_BUF_SIZE - 2, size);
memcpy(buffer + 2, ptr, len);
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 175a761..8311f1a 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -464,7 +464,8 @@
cancel_delayed_work_sync(&ir->work);
/* unregister device */
- rc_unregister_device(ir->rc);
+ if (ir->rc)
+ rc_unregister_device(ir->rc);
/* free memory */
return 0;
diff --git a/drivers/media/i2c/m5mols/Kconfig b/drivers/media/i2c/m5mols/Kconfig
index 4ed0509..c858c2f 100644
--- a/drivers/media/i2c/m5mols/Kconfig
+++ b/drivers/media/i2c/m5mols/Kconfig
@@ -1,5 +1,5 @@
config VIDEO_M5MOLS
- depends on !KERNEL_3_6
+ depends on !BACKPORT_KERNEL_3_3
tristate "Fujitsu M-5MOLS 8MP sensor support"
depends on m
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c
index 2820f7c..8d870b7 100644
--- a/drivers/media/i2c/m5mols/m5mols_core.c
+++ b/drivers/media/i2c/m5mols/m5mols_core.c
@@ -57,14 +57,14 @@
[M5MOLS_RESTYPE_MONITOR] = {
.width = 1920,
.height = 1080,
- .code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .code = V4L2_MBUS_FMT_VYUY8_2X8,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_JPEG,
},
[M5MOLS_RESTYPE_CAPTURE] = {
.width = 1920,
.height = 1080,
- .code = MEDIA_BUS_FMT_JPEG_1X8,
+ .code = V4L2_MBUS_FMT_JPEG_1X8,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_JPEG,
},
@@ -479,7 +479,7 @@
* __find_restype - Lookup M-5MOLS resolution type according to pixel code
* @code: pixel code
*/
-static enum m5mols_restype __find_restype(u32 code)
+static enum m5mols_restype __find_restype(enum v4l2_mbus_pixelcode code)
{
enum m5mols_restype type = M5MOLS_RESTYPE_MONITOR;
diff --git a/drivers/media/i2c/ml86v7667.c b/drivers/media/i2c/ml86v7667.c
index f6ed2a4..c629b33 100644
--- a/drivers/media/i2c/ml86v7667.c
+++ b/drivers/media/i2c/ml86v7667.c
@@ -192,12 +192,12 @@
}
static int ml86v7667_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_YUYV8_2X8;
+ *code = V4L2_MBUS_FMT_YUYV8_2X8;
return 0;
}
@@ -207,7 +207,7 @@
{
struct ml86v7667_priv *priv = to_ml86v7667(sd);
- fmt->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ fmt->code = V4L2_MBUS_FMT_YUYV8_2X8;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
/* The top field is always transferred first by the chip */
fmt->field = V4L2_FIELD_INTERLACED_TB;
diff --git a/drivers/media/i2c/mt9m032.c b/drivers/media/i2c/mt9m032.c
index 7a2b628..fe9d820 100644
--- a/drivers/media/i2c/mt9m032.c
+++ b/drivers/media/i2c/mt9m032.c
@@ -323,7 +323,7 @@
if (code->index != 0)
return -EINVAL;
- code->code = MEDIA_BUS_FMT_Y8_1X8;
+ code->code = V4L2_MBUS_FMT_Y8_1X8;
return 0;
}
@@ -331,7 +331,7 @@
struct v4l2_subdev_fh *fh,
struct v4l2_subdev_frame_size_enum *fse)
{
- if (fse->index != 0 || fse->code != MEDIA_BUS_FMT_Y8_1X8)
+ if (fse->index != 0 || fse->code != V4L2_MBUS_FMT_Y8_1X8)
return -EINVAL;
fse->min_width = MT9M032_COLUMN_SIZE_DEF;
@@ -759,7 +759,7 @@
sensor->format.width = sensor->crop.width;
sensor->format.height = sensor->crop.height;
- sensor->format.code = MEDIA_BUS_FMT_Y8_1X8;
+ sensor->format.code = V4L2_MBUS_FMT_Y8_1X8;
sensor->format.field = V4L2_FIELD_NONE;
sensor->format.colorspace = V4L2_COLORSPACE_SRGB;
diff --git a/drivers/media/i2c/mt9p031.c b/drivers/media/i2c/mt9p031.c
index edb76bd..e18797f 100644
--- a/drivers/media/i2c/mt9p031.c
+++ b/drivers/media/i2c/mt9p031.c
@@ -950,9 +950,9 @@
format = v4l2_subdev_get_try_format(fh, 0);
if (mt9p031->model == MT9P031_MODEL_MONOCHROME)
- format->code = MEDIA_BUS_FMT_Y12_1X12;
+ format->code = V4L2_MBUS_FMT_Y12_1X12;
else
- format->code = MEDIA_BUS_FMT_SGRBG12_1X12;
+ format->code = V4L2_MBUS_FMT_SGRBG12_1X12;
format->width = MT9P031_WINDOW_WIDTH_DEF;
format->height = MT9P031_WINDOW_HEIGHT_DEF;
@@ -1120,9 +1120,9 @@
mt9p031->crop.top = MT9P031_ROW_START_DEF;
if (mt9p031->model == MT9P031_MODEL_MONOCHROME)
- mt9p031->format.code = MEDIA_BUS_FMT_Y12_1X12;
+ mt9p031->format.code = V4L2_MBUS_FMT_Y12_1X12;
else
- mt9p031->format.code = MEDIA_BUS_FMT_SGRBG12_1X12;
+ mt9p031->format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF;
mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF;
diff --git a/drivers/media/i2c/mt9t001.c b/drivers/media/i2c/mt9t001.c
index d9e9889..422e068 100644
--- a/drivers/media/i2c/mt9t001.c
+++ b/drivers/media/i2c/mt9t001.c
@@ -333,7 +333,7 @@
if (code->index > 0)
return -EINVAL;
- code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
return 0;
}
@@ -341,7 +341,7 @@
struct v4l2_subdev_fh *fh,
struct v4l2_subdev_frame_size_enum *fse)
{
- if (fse->index >= 8 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
+ if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
return -EINVAL;
fse->min_width = (MT9T001_WINDOW_WIDTH_DEF + 1) / fse->index;
@@ -792,7 +792,7 @@
crop->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
format = v4l2_subdev_get_try_format(fh, 0);
- format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
format->width = MT9T001_WINDOW_WIDTH_DEF + 1;
format->height = MT9T001_WINDOW_HEIGHT_DEF + 1;
format->field = V4L2_FIELD_NONE;
@@ -917,7 +917,7 @@
mt9t001->crop.width = MT9T001_WINDOW_WIDTH_DEF + 1;
mt9t001->crop.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
- mt9t001->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ mt9t001->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
mt9t001->format.width = MT9T001_WINDOW_WIDTH_DEF + 1;
mt9t001->format.height = MT9T001_WINDOW_HEIGHT_DEF + 1;
mt9t001->format.field = V4L2_FIELD_NONE;
diff --git a/drivers/media/i2c/mt9v011.c b/drivers/media/i2c/mt9v011.c
index d56bd47..355646c 100644
--- a/drivers/media/i2c/mt9v011.c
+++ b/drivers/media/i2c/mt9v011.c
@@ -325,18 +325,18 @@
}
static int mt9v011_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index > 0)
return -EINVAL;
- *code = MEDIA_BUS_FMT_SGRBG8_1X8;
+ *code = V4L2_MBUS_FMT_SGRBG8_1X8;
return 0;
}
static int mt9v011_try_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
- if (fmt->code != MEDIA_BUS_FMT_SGRBG8_1X8)
+ if (fmt->code != V4L2_MBUS_FMT_SGRBG8_1X8)
return -EINVAL;
v4l_bound_align_image(&fmt->width, 48, 639, 1,
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 93687c1..d044bce 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -454,7 +454,7 @@
if (code->index > 0)
return -EINVAL;
- code->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
return 0;
}
@@ -462,7 +462,7 @@
struct v4l2_subdev_fh *fh,
struct v4l2_subdev_frame_size_enum *fse)
{
- if (fse->index >= 3 || fse->code != MEDIA_BUS_FMT_SGRBG10_1X10)
+ if (fse->index >= 3 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
return -EINVAL;
fse->min_width = MT9V032_WINDOW_WIDTH_DEF / (1 << fse->index);
@@ -814,9 +814,9 @@
format = v4l2_subdev_get_try_format(fh, 0);
if (mt9v032->model->color)
- format->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
else
- format->code = MEDIA_BUS_FMT_Y10_1X10;
+ format->code = V4L2_MBUS_FMT_Y10_1X10;
format->width = MT9V032_WINDOW_WIDTH_DEF;
format->height = MT9V032_WINDOW_HEIGHT_DEF;
@@ -966,9 +966,9 @@
mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF;
if (mt9v032->model->color)
- mt9v032->format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
else
- mt9v032->format.code = MEDIA_BUS_FMT_Y10_1X10;
+ mt9v032->format.code = V4L2_MBUS_FMT_Y10_1X10;
mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF;
mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF;
diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c
index 00c7b26..7eae487 100644
--- a/drivers/media/i2c/noon010pc30.c
+++ b/drivers/media/i2c/noon010pc30.c
@@ -112,7 +112,7 @@
#define REG_TERM 0xFFFF
struct noon010_format {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
u16 ispctl1_reg;
};
@@ -175,23 +175,23 @@
/* Supported pixel formats. */
static const struct noon010_format noon010_formats[] = {
{
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0x03,
}, {
- .code = MEDIA_BUS_FMT_YVYU8_2X8,
+ .code = V4L2_MBUS_FMT_YVYU8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0x02,
}, {
- .code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .code = V4L2_MBUS_FMT_VYUY8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0,
}, {
- .code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .code = V4L2_MBUS_FMT_UYVY8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0x01,
}, {
- .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+ .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0x40,
},
diff --git a/drivers/media/i2c/ov7670.c b/drivers/media/i2c/ov7670.c
index 48eeb6a..ad8795f 100644
--- a/drivers/media/i2c/ov7670.c
+++ b/drivers/media/i2c/ov7670.c
@@ -632,31 +632,31 @@
* The magic matrix numbers come from OmniVision.
*/
static struct ov7670_format_struct {
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
enum v4l2_colorspace colorspace;
struct regval_list *regs;
int cmatrix[CMATRIX_LEN];
} ov7670_formats[] = {
{
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.regs = ov7670_fmt_yuv422,
.cmatrix = { 128, -128, 0, -34, -94, 128 },
},
{
- .mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE,
+ .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
.colorspace = V4L2_COLORSPACE_SRGB,
.regs = ov7670_fmt_rgb444,
.cmatrix = { 179, -179, 0, -61, -176, 228 },
},
{
- .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
.colorspace = V4L2_COLORSPACE_SRGB,
.regs = ov7670_fmt_rgb565,
.cmatrix = { 179, -179, 0, -61, -176, 228 },
},
{
- .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8,
.colorspace = V4L2_COLORSPACE_SRGB,
.regs = ov7670_fmt_raw,
.cmatrix = { 0, 0, 0, 0, 0, 0 },
@@ -772,7 +772,7 @@
pll_factor = PLL_FACTOR;
clkrc++;
- if (info->fmt->mbus_code == MEDIA_BUS_FMT_SBGGR8_1X8)
+ if (info->fmt->mbus_code == V4L2_MBUS_FMT_SBGGR8_1X8)
clkrc = (clkrc >> 1);
tpf->numerator = 1;
@@ -810,7 +810,7 @@
} else {
clkrc = (5 * pll_factor * info->clock_speed * tpf->numerator) /
(4 * tpf->denominator);
- if (info->fmt->mbus_code == MEDIA_BUS_FMT_SBGGR8_1X8)
+ if (info->fmt->mbus_code == V4L2_MBUS_FMT_SBGGR8_1X8)
clkrc = (clkrc << 1);
clkrc--;
}
@@ -900,7 +900,7 @@
static int ov7670_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= N_OV7670_FMTS)
return -EINVAL;
diff --git a/drivers/media/i2c/ov9650.c b/drivers/media/i2c/ov9650.c
index 2246bd5..4da90c6 100644
--- a/drivers/media/i2c/ov9650.c
+++ b/drivers/media/i2c/ov9650.c
@@ -384,17 +384,17 @@
};
struct ov965x_pixfmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
u32 colorspace;
/* REG_TSLB value, only bits [3:2] may be set. */
u8 tslb_reg;
};
static const struct ov965x_pixfmt ov965x_formats[] = {
- { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 0x00},
- { MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG, 0x04},
- { MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG, 0x0c},
- { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG, 0x08},
+ { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 0x00},
+ { V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG, 0x04},
+ { V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG, 0x0c},
+ { V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG, 0x08},
};
/*
diff --git a/drivers/media/i2c/s5c73m3/s5c73m3.h b/drivers/media/i2c/s5c73m3/s5c73m3.h
index 13aed59..9656b67 100644
--- a/drivers/media/i2c/s5c73m3/s5c73m3.h
+++ b/drivers/media/i2c/s5c73m3/s5c73m3.h
@@ -27,8 +27,8 @@
#define DRIVER_NAME "S5C73M3"
-#define S5C73M3_ISP_FMT MEDIA_BUS_FMT_VYUY8_2X8
-#define S5C73M3_JPEG_FMT MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8
+#define S5C73M3_ISP_FMT V4L2_MBUS_FMT_VYUY8_2X8
+#define S5C73M3_JPEG_FMT V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8
/* Subdevs pad index definitions */
enum s5c73m3_pads {
@@ -402,7 +402,7 @@
const struct s5c73m3_frame_size *sensor_pix_size[2];
const struct s5c73m3_frame_size *oif_pix_size[2];
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
const struct s5c73m3_interval *fiv;
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
index d1c50c9..1fcc76f 100644
--- a/drivers/media/i2c/s5k4ecgx.c
+++ b/drivers/media/i2c/s5k4ecgx.c
@@ -151,7 +151,7 @@
#define S5K4ECGX_NUM_PREV ARRAY_SIZE(s5k4ecgx_prev_sizes)
struct s5k4ecgx_pixfmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
u32 colorspace;
/* REG_TC_PCFG_Format register value */
u16 reg_p_format;
@@ -159,7 +159,7 @@
/* By default value, output from sensor will be YUV422 0-255 */
static const struct s5k4ecgx_pixfmt s5k4ecgx_formats[] = {
- { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 },
+ { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 },
};
static const char * const s5k4ecgx_supply_names[] = {
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 60a74d8..0e461a6 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -248,7 +248,7 @@
#define NUM_ISP_PADS 2
struct s5k5baf_pixfmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
u32 colorspace;
/* REG_P_FMT(x) register value */
u16 reg_p_fmt;
@@ -331,10 +331,10 @@
};
static const struct s5k5baf_pixfmt s5k5baf_formats[] = {
- { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG, 5 },
+ { V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG, 5 },
/* range 16-240 */
- { MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_REC709, 6 },
- { MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_JPEG, 0 },
+ { V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_REC709, 6 },
+ { V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_JPEG, 0 },
};
static struct v4l2_rect s5k5baf_cis_rect = {
@@ -1206,7 +1206,7 @@
if (code->pad == PAD_CIS) {
if (code->index > 0)
return -EINVAL;
- code->code = MEDIA_BUS_FMT_FIXED;
+ code->code = V4L2_MBUS_FMT_FIXED;
return 0;
}
@@ -1227,7 +1227,7 @@
return -EINVAL;
if (fse->pad == PAD_CIS) {
- fse->code = MEDIA_BUS_FMT_FIXED;
+ fse->code = V4L2_MBUS_FMT_FIXED;
fse->min_width = S5K5BAF_CIS_WIDTH;
fse->max_width = S5K5BAF_CIS_WIDTH;
fse->min_height = S5K5BAF_CIS_HEIGHT;
@@ -1252,7 +1252,7 @@
{
mf->width = S5K5BAF_CIS_WIDTH;
mf->height = S5K5BAF_CIS_HEIGHT;
- mf->code = MEDIA_BUS_FMT_FIXED;
+ mf->code = V4L2_MBUS_FMT_FIXED;
mf->colorspace = V4L2_COLORSPACE_JPEG;
mf->field = V4L2_FIELD_NONE;
}
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
index 91b841a..c11a408 100644
--- a/drivers/media/i2c/s5k6a3.c
+++ b/drivers/media/i2c/s5k6a3.c
@@ -80,7 +80,7 @@
static const struct v4l2_mbus_framefmt s5k6a3_formats[] = {
{
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .code = V4L2_MBUS_FMT_SGRBG10_1X10,
.colorspace = V4L2_COLORSPACE_SRGB,
.field = V4L2_FIELD_NONE,
}
diff --git a/drivers/media/i2c/s5k6aa.c b/drivers/media/i2c/s5k6aa.c
index 2851581..629a5cd 100644
--- a/drivers/media/i2c/s5k6aa.c
+++ b/drivers/media/i2c/s5k6aa.c
@@ -191,7 +191,7 @@
};
struct s5k6aa_pixfmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
u32 colorspace;
/* REG_P_FMT(x) register value */
u16 reg_p_fmt;
@@ -285,10 +285,10 @@
/* TODO: Add RGB888 and Bayer format */
static const struct s5k6aa_pixfmt s5k6aa_formats[] = {
- { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 },
+ { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 },
/* range 16-240 */
- { MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_REC709, 6 },
- { MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_JPEG, 0 },
+ { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_REC709, 6 },
+ { V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_JPEG, 0 },
};
static const struct s5k6aa_interval s5k6aa_intervals[] = {
diff --git a/drivers/media/i2c/saa6752hs.c b/drivers/media/i2c/saa6752hs.c
index f14c0e6..4024ea6 100644
--- a/drivers/media/i2c/saa6752hs.c
+++ b/drivers/media/i2c/saa6752hs.c
@@ -562,7 +562,7 @@
h->video_format = SAA6752HS_VF_D1;
f->width = v4l2_format_table[h->video_format].fmt.pix.width;
f->height = v4l2_format_table[h->video_format].fmt.pix.height;
- f->code = MEDIA_BUS_FMT_FIXED;
+ f->code = V4L2_MBUS_FMT_FIXED;
f->field = V4L2_FIELD_INTERLACED;
f->colorspace = V4L2_COLORSPACE_SMPTE170M;
return 0;
@@ -572,7 +572,7 @@
{
int dist_352, dist_480, dist_720;
- f->code = MEDIA_BUS_FMT_FIXED;
+ f->code = V4L2_MBUS_FMT_FIXED;
dist_352 = abs(f->width - 352);
dist_480 = abs(f->width - 480);
@@ -599,7 +599,7 @@
{
struct saa6752hs_state *h = to_state(sd);
- if (f->code != MEDIA_BUS_FMT_FIXED)
+ if (f->code != V4L2_MBUS_FMT_FIXED)
return -EINVAL;
/*
diff --git a/drivers/media/i2c/saa7115.c b/drivers/media/i2c/saa7115.c
index 80a106b..bdbac44 100644
--- a/drivers/media/i2c/saa7115.c
+++ b/drivers/media/i2c/saa7115.c
@@ -1172,7 +1172,7 @@
static int saa711x_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
{
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (fmt->code != V4L2_MBUS_FMT_FIXED)
return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
diff --git a/drivers/media/i2c/saa717x.c b/drivers/media/i2c/saa717x.c
index 5ef14b2..4aef84a 100644
--- a/drivers/media/i2c/saa717x.c
+++ b/drivers/media/i2c/saa717x.c
@@ -998,7 +998,7 @@
v4l2_dbg(1, debug, sd, "decoder set size\n");
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (fmt->code != V4L2_MBUS_FMT_FIXED)
return -EINVAL;
/* FIXME need better bounds checking here */
diff --git a/drivers/media/i2c/saa7191.c b/drivers/media/i2c/saa7191.c
new file mode 100644
index 0000000..8e96992
--- /dev/null
+++ b/drivers/media/i2c/saa7191.c
@@ -0,0 +1,649 @@
+/*
+ * saa7191.c - Philips SAA7191 video decoder driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+
+#include "saa7191.h"
+
+#define SAA7191_MODULE_VERSION "0.0.5"
+
+MODULE_DESCRIPTION("Philips SAA7191 video decoder driver");
+MODULE_VERSION(SAA7191_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+
+// #define SAA7191_DEBUG
+
+#ifdef SAA7191_DEBUG
+#define dprintk(x...) printk("SAA7191: " x);
+#else
+#define dprintk(x...)
+#endif
+
+#define SAA7191_SYNC_COUNT 30
+#define SAA7191_SYNC_DELAY 100 /* milliseconds */
+
+struct saa7191 {
+ struct v4l2_subdev sd;
+
+ /* the register values are stored here as the actual
+ * I2C-registers are write-only */
+ u8 reg[25];
+
+ int input;
+ v4l2_std_id norm;
+};
+
+static inline struct saa7191 *to_saa7191(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct saa7191, sd);
+}
+
+static const u8 initseq[] = {
+ 0, /* Subaddress */
+
+ 0x50, /* (0x50) SAA7191_REG_IDEL */
+
+ /* 50 Hz signal timing */
+ 0x30, /* (0x30) SAA7191_REG_HSYB */
+ 0x00, /* (0x00) SAA7191_REG_HSYS */
+ 0xe8, /* (0xe8) SAA7191_REG_HCLB */
+ 0xb6, /* (0xb6) SAA7191_REG_HCLS */
+ 0xf4, /* (0xf4) SAA7191_REG_HPHI */
+
+ /* control */
+ SAA7191_LUMA_APER_1, /* (0x01) SAA7191_REG_LUMA - CVBS mode */
+ 0x00, /* (0x00) SAA7191_REG_HUEC */
+ 0xf8, /* (0xf8) SAA7191_REG_CKTQ */
+ 0xf8, /* (0xf8) SAA7191_REG_CKTS */
+ 0x90, /* (0x90) SAA7191_REG_PLSE */
+ 0x90, /* (0x90) SAA7191_REG_SESE */
+ 0x00, /* (0x00) SAA7191_REG_GAIN */
+ SAA7191_STDC_NFEN | SAA7191_STDC_HRMV, /* (0x0c) SAA7191_REG_STDC
+ * - not SECAM,
+ * slow time constant */
+ SAA7191_IOCK_OEDC | SAA7191_IOCK_OEHS | SAA7191_IOCK_OEVS
+ | SAA7191_IOCK_OEDY, /* (0x78) SAA7191_REG_IOCK
+ * - chroma from CVBS, GPSW1 & 2 off */
+ SAA7191_CTL3_AUFD | SAA7191_CTL3_SCEN | SAA7191_CTL3_OFTS
+ | SAA7191_CTL3_YDEL0, /* (0x99) SAA7191_REG_CTL3
+ * - automatic field detection */
+ 0x00, /* (0x00) SAA7191_REG_CTL4 */
+ 0x2c, /* (0x2c) SAA7191_REG_CHCV - PAL nominal value */
+ 0x00, /* unused */
+ 0x00, /* unused */
+
+ /* 60 Hz signal timing */
+ 0x34, /* (0x34) SAA7191_REG_HS6B */
+ 0x0a, /* (0x0a) SAA7191_REG_HS6S */
+ 0xf4, /* (0xf4) SAA7191_REG_HC6B */
+ 0xce, /* (0xce) SAA7191_REG_HC6S */
+ 0xf4, /* (0xf4) SAA7191_REG_HP6I */
+};
+
+/* SAA7191 register handling */
+
+static u8 saa7191_read_reg(struct v4l2_subdev *sd, u8 reg)
+{
+ return to_saa7191(sd)->reg[reg];
+}
+
+static int saa7191_read_status(struct v4l2_subdev *sd, u8 *value)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int ret;
+
+ ret = i2c_master_recv(client, value, 1);
+ if (ret < 0) {
+ printk(KERN_ERR "SAA7191: saa7191_read_status(): read failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+
+static int saa7191_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+ to_saa7191(sd)->reg[reg] = value;
+ return i2c_smbus_write_byte_data(client, reg, value);
+}
+
+/* the first byte of data must be the first subaddress number (register) */
+static int saa7191_write_block(struct v4l2_subdev *sd,
+ u8 length, const u8 *data)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ struct saa7191 *decoder = to_saa7191(sd);
+ int i;
+ int ret;
+
+ for (i = 0; i < (length - 1); i++) {
+ decoder->reg[data[0] + i] = data[i + 1];
+ }
+
+ ret = i2c_master_send(client, data, length);
+ if (ret < 0) {
+ printk(KERN_ERR "SAA7191: saa7191_write_block(): "
+ "write failed\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Helper functions */
+
+static int saa7191_s_routing(struct v4l2_subdev *sd,
+ u32 input, u32 output, u32 config)
+{
+ struct saa7191 *decoder = to_saa7191(sd);
+ u8 luma = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+ u8 iock = saa7191_read_reg(sd, SAA7191_REG_IOCK);
+ int err;
+
+ switch (input) {
+ case SAA7191_INPUT_COMPOSITE: /* Set Composite input */
+ iock &= ~(SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW1
+ | SAA7191_IOCK_GPSW2);
+ /* Chrominance trap active */
+ luma &= ~SAA7191_LUMA_BYPS;
+ break;
+ case SAA7191_INPUT_SVIDEO: /* Set S-Video input */
+ iock |= SAA7191_IOCK_CHRS | SAA7191_IOCK_GPSW2;
+ /* Chrominance trap bypassed */
+ luma |= SAA7191_LUMA_BYPS;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ err = saa7191_write_reg(sd, SAA7191_REG_LUMA, luma);
+ if (err)
+ return -EIO;
+ err = saa7191_write_reg(sd, SAA7191_REG_IOCK, iock);
+ if (err)
+ return -EIO;
+
+ decoder->input = input;
+
+ return 0;
+}
+
+static int saa7191_s_std(struct v4l2_subdev *sd, v4l2_std_id norm)
+{
+ struct saa7191 *decoder = to_saa7191(sd);
+ u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
+ u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+ u8 chcv = saa7191_read_reg(sd, SAA7191_REG_CHCV);
+ int err;
+
+ if (norm & V4L2_STD_PAL) {
+ stdc &= ~SAA7191_STDC_SECS;
+ ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+ chcv = SAA7191_CHCV_PAL;
+ } else if (norm & V4L2_STD_NTSC) {
+ stdc &= ~SAA7191_STDC_SECS;
+ ctl3 &= ~SAA7191_CTL3_AUFD;
+ ctl3 |= SAA7191_CTL3_FSEL;
+ chcv = SAA7191_CHCV_NTSC;
+ } else if (norm & V4L2_STD_SECAM) {
+ stdc |= SAA7191_STDC_SECS;
+ ctl3 &= ~(SAA7191_CTL3_AUFD | SAA7191_CTL3_FSEL);
+ chcv = SAA7191_CHCV_PAL;
+ } else {
+ return -EINVAL;
+ }
+
+ err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
+ if (err)
+ return -EIO;
+ err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
+ if (err)
+ return -EIO;
+ err = saa7191_write_reg(sd, SAA7191_REG_CHCV, chcv);
+ if (err)
+ return -EIO;
+
+ decoder->norm = norm;
+
+ dprintk("ctl3: %02x stdc: %02x chcv: %02x\n", ctl3,
+ stdc, chcv);
+ dprintk("norm: %llx\n", norm);
+
+ return 0;
+}
+
+static int saa7191_wait_for_signal(struct v4l2_subdev *sd, u8 *status)
+{
+ int i = 0;
+
+ dprintk("Checking for signal...\n");
+
+ for (i = 0; i < SAA7191_SYNC_COUNT; i++) {
+ if (saa7191_read_status(sd, status))
+ return -EIO;
+
+ if (((*status) & SAA7191_STATUS_HLCK) == 0) {
+ dprintk("Signal found\n");
+ return 0;
+ }
+
+ msleep(SAA7191_SYNC_DELAY);
+ }
+
+ dprintk("No signal\n");
+
+ return -EBUSY;
+}
+
+static int saa7191_querystd(struct v4l2_subdev *sd, v4l2_std_id *norm)
+{
+ struct saa7191 *decoder = to_saa7191(sd);
+ u8 stdc = saa7191_read_reg(sd, SAA7191_REG_STDC);
+ u8 ctl3 = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+ u8 status;
+ v4l2_std_id old_norm = decoder->norm;
+ int err = 0;
+
+ dprintk("SAA7191 extended signal auto-detection...\n");
+
+ *norm &= V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
+ stdc &= ~SAA7191_STDC_SECS;
+ ctl3 &= ~(SAA7191_CTL3_FSEL);
+
+ err = saa7191_write_reg(sd, SAA7191_REG_STDC, stdc);
+ if (err) {
+ err = -EIO;
+ goto out;
+ }
+ err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
+ if (err) {
+ err = -EIO;
+ goto out;
+ }
+
+ ctl3 |= SAA7191_CTL3_AUFD;
+ err = saa7191_write_reg(sd, SAA7191_REG_CTL3, ctl3);
+ if (err) {
+ err = -EIO;
+ goto out;
+ }
+
+ msleep(SAA7191_SYNC_DELAY);
+
+ err = saa7191_wait_for_signal(sd, &status);
+ if (err)
+ goto out;
+
+ if (status & SAA7191_STATUS_FIDT) {
+ /* 60Hz signal -> NTSC */
+ dprintk("60Hz signal: NTSC\n");
+ *norm &= V4L2_STD_NTSC;
+ return 0;
+ }
+
+ /* 50Hz signal */
+ dprintk("50Hz signal: Trying PAL...\n");
+
+ /* try PAL first */
+ err = saa7191_s_std(sd, V4L2_STD_PAL);
+ if (err)
+ goto out;
+
+ msleep(SAA7191_SYNC_DELAY);
+
+ err = saa7191_wait_for_signal(sd, &status);
+ if (err)
+ goto out;
+
+ /* not 50Hz ? */
+ if (status & SAA7191_STATUS_FIDT) {
+ dprintk("No 50Hz signal\n");
+ saa7191_s_std(sd, old_norm);
+ *norm = V4L2_STD_UNKNOWN;
+ return 0;
+ }
+
+ if (status & SAA7191_STATUS_CODE) {
+ dprintk("PAL\n");
+ *norm &= V4L2_STD_PAL;
+ return saa7191_s_std(sd, old_norm);
+ }
+
+ dprintk("No color detected with PAL - Trying SECAM...\n");
+
+ /* no color detected ? -> try SECAM */
+ err = saa7191_s_std(sd, V4L2_STD_SECAM);
+ if (err)
+ goto out;
+
+ msleep(SAA7191_SYNC_DELAY);
+
+ err = saa7191_wait_for_signal(sd, &status);
+ if (err)
+ goto out;
+
+ /* not 50Hz ? */
+ if (status & SAA7191_STATUS_FIDT) {
+ dprintk("No 50Hz signal\n");
+ *norm = V4L2_STD_UNKNOWN;
+ goto out;
+ }
+
+ if (status & SAA7191_STATUS_CODE) {
+ /* Color detected -> SECAM */
+ dprintk("SECAM\n");
+ *norm &= V4L2_STD_SECAM;
+ return saa7191_s_std(sd, old_norm);
+ }
+
+ dprintk("No color detected with SECAM - Going back to PAL.\n");
+ *norm = V4L2_STD_UNKNOWN;
+
+out:
+ return saa7191_s_std(sd, old_norm);
+}
+
+static int saa7191_autodetect_norm(struct v4l2_subdev *sd)
+{
+ u8 status;
+
+ dprintk("SAA7191 signal auto-detection...\n");
+
+ dprintk("Reading status...\n");
+
+ if (saa7191_read_status(sd, &status))
+ return -EIO;
+
+ dprintk("Checking for signal...\n");
+
+ /* no signal ? */
+ if (status & SAA7191_STATUS_HLCK) {
+ dprintk("No signal\n");
+ return -EBUSY;
+ }
+
+ dprintk("Signal found\n");
+
+ if (status & SAA7191_STATUS_FIDT) {
+ /* 60hz signal -> NTSC */
+ dprintk("NTSC\n");
+ return saa7191_s_std(sd, V4L2_STD_NTSC);
+ } else {
+ /* 50hz signal -> PAL */
+ dprintk("PAL\n");
+ return saa7191_s_std(sd, V4L2_STD_PAL);
+ }
+}
+
+static int saa7191_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ u8 reg;
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case SAA7191_CONTROL_BANDPASS:
+ case SAA7191_CONTROL_BANDPASS_WEIGHT:
+ case SAA7191_CONTROL_CORING:
+ reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+ switch (ctrl->id) {
+ case SAA7191_CONTROL_BANDPASS:
+ ctrl->value = ((s32)reg & SAA7191_LUMA_BPSS_MASK)
+ >> SAA7191_LUMA_BPSS_SHIFT;
+ break;
+ case SAA7191_CONTROL_BANDPASS_WEIGHT:
+ ctrl->value = ((s32)reg & SAA7191_LUMA_APER_MASK)
+ >> SAA7191_LUMA_APER_SHIFT;
+ break;
+ case SAA7191_CONTROL_CORING:
+ ctrl->value = ((s32)reg & SAA7191_LUMA_CORI_MASK)
+ >> SAA7191_LUMA_CORI_SHIFT;
+ break;
+ }
+ break;
+ case SAA7191_CONTROL_FORCE_COLOUR:
+ case SAA7191_CONTROL_CHROMA_GAIN:
+ reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
+ if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR)
+ ctrl->value = ((s32)reg & SAA7191_GAIN_COLO) ? 1 : 0;
+ else
+ ctrl->value = ((s32)reg & SAA7191_GAIN_LFIS_MASK)
+ >> SAA7191_GAIN_LFIS_SHIFT;
+ break;
+ case V4L2_CID_HUE:
+ reg = saa7191_read_reg(sd, SAA7191_REG_HUEC);
+ if (reg < 0x80)
+ reg += 0x80;
+ else
+ reg -= 0x80;
+ ctrl->value = (s32)reg;
+ break;
+ case SAA7191_CONTROL_VTRC:
+ reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
+ ctrl->value = ((s32)reg & SAA7191_STDC_VTRC) ? 1 : 0;
+ break;
+ case SAA7191_CONTROL_LUMA_DELAY:
+ reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+ ctrl->value = ((s32)reg & SAA7191_CTL3_YDEL_MASK)
+ >> SAA7191_CTL3_YDEL_SHIFT;
+ if (ctrl->value >= 4)
+ ctrl->value -= 8;
+ break;
+ case SAA7191_CONTROL_VNR:
+ reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
+ ctrl->value = ((s32)reg & SAA7191_CTL4_VNOI_MASK)
+ >> SAA7191_CTL4_VNOI_SHIFT;
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int saa7191_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ u8 reg;
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case SAA7191_CONTROL_BANDPASS:
+ case SAA7191_CONTROL_BANDPASS_WEIGHT:
+ case SAA7191_CONTROL_CORING:
+ reg = saa7191_read_reg(sd, SAA7191_REG_LUMA);
+ switch (ctrl->id) {
+ case SAA7191_CONTROL_BANDPASS:
+ reg &= ~SAA7191_LUMA_BPSS_MASK;
+ reg |= (ctrl->value << SAA7191_LUMA_BPSS_SHIFT)
+ & SAA7191_LUMA_BPSS_MASK;
+ break;
+ case SAA7191_CONTROL_BANDPASS_WEIGHT:
+ reg &= ~SAA7191_LUMA_APER_MASK;
+ reg |= (ctrl->value << SAA7191_LUMA_APER_SHIFT)
+ & SAA7191_LUMA_APER_MASK;
+ break;
+ case SAA7191_CONTROL_CORING:
+ reg &= ~SAA7191_LUMA_CORI_MASK;
+ reg |= (ctrl->value << SAA7191_LUMA_CORI_SHIFT)
+ & SAA7191_LUMA_CORI_MASK;
+ break;
+ }
+ ret = saa7191_write_reg(sd, SAA7191_REG_LUMA, reg);
+ break;
+ case SAA7191_CONTROL_FORCE_COLOUR:
+ case SAA7191_CONTROL_CHROMA_GAIN:
+ reg = saa7191_read_reg(sd, SAA7191_REG_GAIN);
+ if (ctrl->id == SAA7191_CONTROL_FORCE_COLOUR) {
+ if (ctrl->value)
+ reg |= SAA7191_GAIN_COLO;
+ else
+ reg &= ~SAA7191_GAIN_COLO;
+ } else {
+ reg &= ~SAA7191_GAIN_LFIS_MASK;
+ reg |= (ctrl->value << SAA7191_GAIN_LFIS_SHIFT)
+ & SAA7191_GAIN_LFIS_MASK;
+ }
+ ret = saa7191_write_reg(sd, SAA7191_REG_GAIN, reg);
+ break;
+ case V4L2_CID_HUE:
+ reg = ctrl->value & 0xff;
+ if (reg < 0x80)
+ reg += 0x80;
+ else
+ reg -= 0x80;
+ ret = saa7191_write_reg(sd, SAA7191_REG_HUEC, reg);
+ break;
+ case SAA7191_CONTROL_VTRC:
+ reg = saa7191_read_reg(sd, SAA7191_REG_STDC);
+ if (ctrl->value)
+ reg |= SAA7191_STDC_VTRC;
+ else
+ reg &= ~SAA7191_STDC_VTRC;
+ ret = saa7191_write_reg(sd, SAA7191_REG_STDC, reg);
+ break;
+ case SAA7191_CONTROL_LUMA_DELAY: {
+ s32 value = ctrl->value;
+ if (value < 0)
+ value += 8;
+ reg = saa7191_read_reg(sd, SAA7191_REG_CTL3);
+ reg &= ~SAA7191_CTL3_YDEL_MASK;
+ reg |= (value << SAA7191_CTL3_YDEL_SHIFT)
+ & SAA7191_CTL3_YDEL_MASK;
+ ret = saa7191_write_reg(sd, SAA7191_REG_CTL3, reg);
+ break;
+ }
+ case SAA7191_CONTROL_VNR:
+ reg = saa7191_read_reg(sd, SAA7191_REG_CTL4);
+ reg &= ~SAA7191_CTL4_VNOI_MASK;
+ reg |= (ctrl->value << SAA7191_CTL4_VNOI_SHIFT)
+ & SAA7191_CTL4_VNOI_MASK;
+ ret = saa7191_write_reg(sd, SAA7191_REG_CTL4, reg);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/* I2C-interface */
+
+static int saa7191_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+ u8 status_reg;
+ int res = V4L2_IN_ST_NO_SIGNAL;
+
+ if (saa7191_read_status(sd, &status_reg))
+ return -EIO;
+ if ((status_reg & SAA7191_STATUS_HLCK) == 0)
+ res = 0;
+ if (!(status_reg & SAA7191_STATUS_CODE))
+ res |= V4L2_IN_ST_NO_COLOR;
+ *status = res;
+ return 0;
+}
+
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops saa7191_core_ops = {
+ .g_ctrl = saa7191_g_ctrl,
+ .s_ctrl = saa7191_s_ctrl,
+};
+
+static const struct v4l2_subdev_video_ops saa7191_video_ops = {
+ .s_std = saa7191_s_std,
+ .s_routing = saa7191_s_routing,
+ .querystd = saa7191_querystd,
+ .g_input_status = saa7191_g_input_status,
+};
+
+static const struct v4l2_subdev_ops saa7191_ops = {
+ .core = &saa7191_core_ops,
+ .video = &saa7191_video_ops,
+};
+
+static int saa7191_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct saa7191 *decoder;
+ struct v4l2_subdev *sd;
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
+
+ decoder = devm_kzalloc(&client->dev, sizeof(*decoder), GFP_KERNEL);
+ if (!decoder)
+ return -ENOMEM;
+
+ sd = &decoder->sd;
+ v4l2_i2c_subdev_init(sd, client, &saa7191_ops);
+
+ err = saa7191_write_block(sd, sizeof(initseq), initseq);
+ if (err) {
+ printk(KERN_ERR "SAA7191 initialization failed\n");
+ return err;
+ }
+
+ printk(KERN_INFO "SAA7191 initialized\n");
+
+ decoder->input = SAA7191_INPUT_COMPOSITE;
+ decoder->norm = V4L2_STD_PAL;
+
+ err = saa7191_autodetect_norm(sd);
+ if (err && (err != -EBUSY))
+ printk(KERN_ERR "SAA7191: Signal auto-detection failed\n");
+
+ return 0;
+}
+
+static int saa7191_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+ v4l2_device_unregister_subdev(sd);
+ return 0;
+}
+
+static const struct i2c_device_id saa7191_id[] = {
+ { "saa7191", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, saa7191_id);
+
+static struct i2c_driver saa7191_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "saa7191",
+ },
+ .probe = saa7191_probe,
+ .remove = saa7191_remove,
+ .id_table = saa7191_id,
+};
+
+module_i2c_driver(saa7191_driver);
diff --git a/drivers/media/i2c/saa7191.h b/drivers/media/i2c/saa7191.h
new file mode 100644
index 0000000..803c74d
--- /dev/null
+++ b/drivers/media/i2c/saa7191.h
@@ -0,0 +1,245 @@
+/*
+ * saa7191.h - Philips SAA7191 video decoder driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * 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 _SAA7191_H_
+#define _SAA7191_H_
+
+/* Philips SAA7191 DMSD I2C bus address */
+#define SAA7191_ADDR 0x8a
+
+/* Register subaddresses. */
+#define SAA7191_REG_IDEL 0x00
+#define SAA7191_REG_HSYB 0x01
+#define SAA7191_REG_HSYS 0x02
+#define SAA7191_REG_HCLB 0x03
+#define SAA7191_REG_HCLS 0x04
+#define SAA7191_REG_HPHI 0x05
+#define SAA7191_REG_LUMA 0x06
+#define SAA7191_REG_HUEC 0x07
+#define SAA7191_REG_CKTQ 0x08 /* bits 3-7 */
+#define SAA7191_REG_CKTS 0x09 /* bits 3-7 */
+#define SAA7191_REG_PLSE 0x0a
+#define SAA7191_REG_SESE 0x0b
+#define SAA7191_REG_GAIN 0x0c
+#define SAA7191_REG_STDC 0x0d
+#define SAA7191_REG_IOCK 0x0e
+#define SAA7191_REG_CTL3 0x0f
+#define SAA7191_REG_CTL4 0x10
+#define SAA7191_REG_CHCV 0x11
+#define SAA7191_REG_HS6B 0x14
+#define SAA7191_REG_HS6S 0x15
+#define SAA7191_REG_HC6B 0x16
+#define SAA7191_REG_HC6S 0x17
+#define SAA7191_REG_HP6I 0x18
+#define SAA7191_REG_STATUS 0xff /* not really a subaddress */
+
+/* Status Register definitions */
+#define SAA7191_STATUS_CODE 0x01 /* color detected flag */
+#define SAA7191_STATUS_FIDT 0x20 /* signal type 50/60 Hz */
+#define SAA7191_STATUS_HLCK 0x40 /* PLL unlocked(1)/locked(0) */
+#define SAA7191_STATUS_STTC 0x80 /* tv/vtr time constant */
+
+/* Luminance Control Register definitions */
+/* input mode select bit:
+ * 0=CVBS (chrominance trap active), 1=S-Video (trap bypassed) */
+#define SAA7191_LUMA_BYPS 0x80
+/* pre-filter (only when chrominance trap is active) */
+#define SAA7191_LUMA_PREF 0x40
+/* aperture bandpass to select different characteristics with maximums
+ * (bits 4-5) */
+#define SAA7191_LUMA_BPSS_MASK 0x30
+#define SAA7191_LUMA_BPSS_SHIFT 4
+#define SAA7191_LUMA_BPSS_3 0x30
+#define SAA7191_LUMA_BPSS_2 0x20
+#define SAA7191_LUMA_BPSS_1 0x10
+#define SAA7191_LUMA_BPSS_0 0x00
+/* coring range for high frequency components according to 8-bit luminance
+ * (bits 2-3)
+ * 0=coring off, n= (+-)n LSB */
+#define SAA7191_LUMA_CORI_MASK 0x0c
+#define SAA7191_LUMA_CORI_SHIFT 2
+#define SAA7191_LUMA_CORI_3 0x0c
+#define SAA7191_LUMA_CORI_2 0x08
+#define SAA7191_LUMA_CORI_1 0x04
+#define SAA7191_LUMA_CORI_0 0x00
+/* aperture bandpass filter weights high frequency components of luminance
+ * signal (bits 0-1)
+ * 0=factor 0, 1=0.25, 2=0.5, 3=1 */
+#define SAA7191_LUMA_APER_MASK 0x03
+#define SAA7191_LUMA_APER_SHIFT 0
+#define SAA7191_LUMA_APER_3 0x03
+#define SAA7191_LUMA_APER_2 0x02
+#define SAA7191_LUMA_APER_1 0x01
+#define SAA7191_LUMA_APER_0 0x00
+
+/* Chrominance Gain Control Settings Register definitions */
+/* colour on: 0=automatic colour-killer enabled, 1=forced colour on */
+#define SAA7191_GAIN_COLO 0x80
+/* chrominance gain control (AGC filter)
+ * 0=loop filter time constant slow, 1=medium, 2=fast, 3=actual gain */
+#define SAA7191_GAIN_LFIS_MASK 0x60
+#define SAA7191_GAIN_LFIS_SHIFT 5
+#define SAA7191_GAIN_LFIS_3 0x60
+#define SAA7191_GAIN_LFIS_2 0x40
+#define SAA7191_GAIN_LFIS_1 0x20
+#define SAA7191_GAIN_LFIS_0 0x00
+
+/* Standard/Mode Control Register definitions */
+/* tv/vtr mode bit: 0=TV mode (slow time constant),
+ * 1=VTR mode (fast time constant) */
+#define SAA7191_STDC_VTRC 0x80
+/* SAA7191B-specific functions enable (RTCO, ODD and GPSW0 outputs)
+ * 0=outputs set to high-impedance (circuit equals SAA7191), 1=enabled */
+#define SAA7191_STDC_NFEN 0x08
+/* HREF generation: 0=like SAA7191, 1=HREF is 8xLLC2 clocks earlier */
+#define SAA7191_STDC_HRMV 0x04
+/* general purpose switch 0
+ * (not used with VINO afaik) */
+#define SAA7191_STDC_GPSW0 0x02
+/* SECAM mode bit: 0=other standards, 1=SECAM */
+#define SAA7191_STDC_SECS 0x01
+
+/* I/O and Clock Control Register definitions */
+/* horizontal clock PLL: 0=PLL closed,
+ * 1=PLL circuit open and horizontal freq fixed */
+#define SAA7191_IOCK_HPLL 0x80
+/* colour-difference output enable (outputs UV0-UV7) */
+#define SAA7191_IOCK_OEDC 0x40
+/* H-sync output enable */
+#define SAA7191_IOCK_OEHS 0x20
+/* V-sync output enable */
+#define SAA7191_IOCK_OEVS 0x10
+/* luminance output enable (outputs Y0-Y7) */
+#define SAA7191_IOCK_OEDY 0x08
+/* S-VHS bit (chrominance from CVBS or from chrominance input):
+ * 0=controlled by BYPS-bit, 1=from chrominance input */
+#define SAA7191_IOCK_CHRS 0x04
+/* general purpose switch 2
+ * VINO-specific: 0=used with CVBS, 1=used with S-Video */
+#define SAA7191_IOCK_GPSW2 0x02
+/* general purpose switch 1 */
+/* VINO-specific: 0=always, 1=not used!*/
+#define SAA7191_IOCK_GPSW1 0x01
+
+/* Miscellaneous Control #1 Register definitions */
+/* automatic field detection (50/60Hz standard) */
+#define SAA7191_CTL3_AUFD 0x80
+/* field select: (if AUFD=0)
+ * 0=50Hz (625 lines), 1=60Hz (525 lines) */
+#define SAA7191_CTL3_FSEL 0x40
+/* SECAM cross-colour reduction enable */
+#define SAA7191_CTL3_SXCR 0x20
+/* sync and clamping pulse enable (HCL and HSY outputs) */
+#define SAA7191_CTL3_SCEN 0x10
+/* output format: 0=4:1:1, 1=4:2:2 (4:2:2 for VINO) */
+#define SAA7191_CTL3_OFTS 0x08
+/* luminance delay compensation
+ * 0=0*2/LLC, 1=+1*2/LLC, 2=+2*2/LLC, 3=+3*2/LLC,
+ * 4=-4*2/LLC, 5=-3*2/LLC, 6=-2*2/LLC, 7=-1*2/LLC
+ * step size = 2/LLC = 67.8ns for 50Hz, 81.5ns for 60Hz */
+#define SAA7191_CTL3_YDEL_MASK 0x07
+#define SAA7191_CTL3_YDEL_SHIFT 0
+#define SAA7191_CTL3_YDEL2 0x04
+#define SAA7191_CTL3_YDEL1 0x02
+#define SAA7191_CTL3_YDEL0 0x01
+
+/* Miscellaneous Control #2 Register definitions */
+/* select HREF position
+ * 0=normal, HREF is matched to YUV output port,
+ * 1=HREF is matched to CVBS input port */
+#define SAA7191_CTL4_HRFS 0x04
+/* vertical noise reduction
+ * 0=normal, 1=searching window, 2=auto-deflection, 3=reduction bypassed */
+#define SAA7191_CTL4_VNOI_MASK 0x03
+#define SAA7191_CTL4_VNOI_SHIFT 0
+#define SAA7191_CTL4_VNOI_3 0x03
+#define SAA7191_CTL4_VNOI_2 0x02
+#define SAA7191_CTL4_VNOI_1 0x01
+#define SAA7191_CTL4_VNOI_0 0x00
+
+/* Chrominance Gain Control Register definitions
+ * - for QAM-modulated input signals, effects output amplitude
+ * (SECAM gain fixed)
+ * (nominal values for UV CCIR level) */
+#define SAA7191_CHCV_NTSC 0x2c
+#define SAA7191_CHCV_PAL 0x59
+
+/* Driver interface definitions */
+#define SAA7191_INPUT_COMPOSITE 0
+#define SAA7191_INPUT_SVIDEO 1
+
+#define SAA7191_NORM_PAL 1
+#define SAA7191_NORM_NTSC 2
+#define SAA7191_NORM_SECAM 3
+
+struct saa7191_status {
+ /* 0=no signal, 1=signal detected */
+ int signal;
+ /* 0=50hz (pal) signal, 1=60hz (ntsc) signal */
+ int signal_60hz;
+ /* 0=no color detected, 1=color detected */
+ int color;
+
+ /* current SAA7191_INPUT_ */
+ int input;
+ /* current SAA7191_NORM_ */
+ int norm;
+};
+
+#define SAA7191_BANDPASS_MIN 0x00
+#define SAA7191_BANDPASS_MAX 0x03
+#define SAA7191_BANDPASS_DEFAULT 0x00
+
+#define SAA7191_BANDPASS_WEIGHT_MIN 0x00
+#define SAA7191_BANDPASS_WEIGHT_MAX 0x03
+#define SAA7191_BANDPASS_WEIGHT_DEFAULT 0x01
+
+#define SAA7191_CORING_MIN 0x00
+#define SAA7191_CORING_MAX 0x03
+#define SAA7191_CORING_DEFAULT 0x00
+
+#define SAA7191_HUE_MIN 0x00
+#define SAA7191_HUE_MAX 0xff
+#define SAA7191_HUE_DEFAULT 0x80
+
+#define SAA7191_VTRC_MIN 0x00
+#define SAA7191_VTRC_MAX 0x01
+#define SAA7191_VTRC_DEFAULT 0x00
+
+#define SAA7191_FORCE_COLOUR_MIN 0x00
+#define SAA7191_FORCE_COLOUR_MAX 0x01
+#define SAA7191_FORCE_COLOUR_DEFAULT 0x00
+
+#define SAA7191_CHROMA_GAIN_MIN 0x00
+#define SAA7191_CHROMA_GAIN_MAX 0x03
+#define SAA7191_CHROMA_GAIN_DEFAULT 0x00
+
+#define SAA7191_LUMA_DELAY_MIN -0x04
+#define SAA7191_LUMA_DELAY_MAX 0x03
+#define SAA7191_LUMA_DELAY_DEFAULT 0x01
+
+#define SAA7191_VNR_MIN 0x00
+#define SAA7191_VNR_MAX 0x03
+#define SAA7191_VNR_DEFAULT 0x00
+
+#define SAA7191_CONTROL_BANDPASS (V4L2_CID_PRIVATE_BASE + 0)
+#define SAA7191_CONTROL_BANDPASS_WEIGHT (V4L2_CID_PRIVATE_BASE + 1)
+#define SAA7191_CONTROL_CORING (V4L2_CID_PRIVATE_BASE + 2)
+#define SAA7191_CONTROL_FORCE_COLOUR (V4L2_CID_PRIVATE_BASE + 3)
+#define SAA7191_CONTROL_CHROMA_GAIN (V4L2_CID_PRIVATE_BASE + 4)
+#define SAA7191_CONTROL_VTRC (V4L2_CID_PRIVATE_BASE + 5)
+#define SAA7191_CONTROL_LUMA_DELAY (V4L2_CID_PRIVATE_BASE + 6)
+#define SAA7191_CONTROL_VNR (V4L2_CID_PRIVATE_BASE + 7)
+
+#define DECODER_SAA7191_GET_STATUS _IOR('d', 195, struct saa7191_status)
+#define DECODER_SAA7191_SET_NORM _IOW('d', 196, int)
+
+#endif
diff --git a/drivers/media/i2c/smiapp-pll.c b/drivers/media/i2c/smiapp-pll.c
index e40d902..2335529 100644
--- a/drivers/media/i2c/smiapp-pll.c
+++ b/drivers/media/i2c/smiapp-pll.c
@@ -65,36 +65,264 @@
static void print_pll(struct device *dev, struct smiapp_pll *pll)
{
- dev_dbg(dev, "pre_pll_clk_div\t%u\n", pll->pre_pll_clk_div);
- dev_dbg(dev, "pll_multiplier \t%u\n", pll->pll_multiplier);
- if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
- dev_dbg(dev, "op_sys_clk_div \t%u\n", pll->op.sys_clk_div);
- dev_dbg(dev, "op_pix_clk_div \t%u\n", pll->op.pix_clk_div);
+ dev_dbg(dev, "pre_pll_clk_div\t%d\n", pll->pre_pll_clk_div);
+ dev_dbg(dev, "pll_multiplier \t%d\n", pll->pll_multiplier);
+ if (pll->flags != SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+ dev_dbg(dev, "op_sys_clk_div \t%d\n", pll->op_sys_clk_div);
+ dev_dbg(dev, "op_pix_clk_div \t%d\n", pll->op_pix_clk_div);
}
- dev_dbg(dev, "vt_sys_clk_div \t%u\n", pll->vt.sys_clk_div);
- dev_dbg(dev, "vt_pix_clk_div \t%u\n", pll->vt.pix_clk_div);
+ dev_dbg(dev, "vt_sys_clk_div \t%d\n", pll->vt_sys_clk_div);
+ dev_dbg(dev, "vt_pix_clk_div \t%d\n", pll->vt_pix_clk_div);
- dev_dbg(dev, "ext_clk_freq_hz \t%u\n", pll->ext_clk_freq_hz);
- dev_dbg(dev, "pll_ip_clk_freq_hz \t%u\n", pll->pll_ip_clk_freq_hz);
- dev_dbg(dev, "pll_op_clk_freq_hz \t%u\n", pll->pll_op_clk_freq_hz);
- if (!(pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)) {
- dev_dbg(dev, "op_sys_clk_freq_hz \t%u\n",
- pll->op.sys_clk_freq_hz);
- dev_dbg(dev, "op_pix_clk_freq_hz \t%u\n",
- pll->op.pix_clk_freq_hz);
+ dev_dbg(dev, "ext_clk_freq_hz \t%d\n", pll->ext_clk_freq_hz);
+ dev_dbg(dev, "pll_ip_clk_freq_hz \t%d\n", pll->pll_ip_clk_freq_hz);
+ dev_dbg(dev, "pll_op_clk_freq_hz \t%d\n", pll->pll_op_clk_freq_hz);
+ if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
+ dev_dbg(dev, "op_sys_clk_freq_hz \t%d\n",
+ pll->op_sys_clk_freq_hz);
+ dev_dbg(dev, "op_pix_clk_freq_hz \t%d\n",
+ pll->op_pix_clk_freq_hz);
}
- dev_dbg(dev, "vt_sys_clk_freq_hz \t%u\n", pll->vt.sys_clk_freq_hz);
- dev_dbg(dev, "vt_pix_clk_freq_hz \t%u\n", pll->vt.pix_clk_freq_hz);
+ dev_dbg(dev, "vt_sys_clk_freq_hz \t%d\n", pll->vt_sys_clk_freq_hz);
+ dev_dbg(dev, "vt_pix_clk_freq_hz \t%d\n", pll->vt_pix_clk_freq_hz);
}
-static int check_all_bounds(struct device *dev,
- const struct smiapp_pll_limits *limits,
- const struct smiapp_pll_branch_limits *op_limits,
- struct smiapp_pll *pll,
- struct smiapp_pll_branch *op_pll)
+/*
+ * Heuristically guess the PLL tree for a given common multiplier and
+ * divisor. Begin with the operational timing and continue to video
+ * timing once operational timing has been verified.
+ *
+ * @mul is the PLL multiplier and @div is the common divisor
+ * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL
+ * multiplier will be a multiple of @mul.
+ *
+ * @return Zero on success, error code on error.
+ */
+static int __smiapp_pll_calculate(struct device *dev,
+ const struct smiapp_pll_limits *limits,
+ struct smiapp_pll *pll, uint32_t mul,
+ uint32_t div, uint32_t lane_op_clock_ratio)
{
+ uint32_t sys_div;
+ uint32_t best_pix_div = INT_MAX >> 1;
+ uint32_t vt_op_binning_div;
+ /*
+ * Higher multipliers (and divisors) are often required than
+ * necessitated by the external clock and the output clocks.
+ * There are limits for all values in the clock tree. These
+ * are the minimum and maximum multiplier for mul.
+ */
+ uint32_t more_mul_min, more_mul_max;
+ uint32_t more_mul_factor;
+ uint32_t min_vt_div, max_vt_div, vt_div;
+ uint32_t min_sys_div, max_sys_div;
+ unsigned int i;
int rval;
+ /*
+ * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
+ * too high.
+ */
+ dev_dbg(dev, "pre_pll_clk_div %d\n", pll->pre_pll_clk_div);
+
+ /* Don't go above max pll multiplier. */
+ more_mul_max = limits->max_pll_multiplier / mul;
+ dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %d\n",
+ more_mul_max);
+ /* Don't go above max pll op frequency. */
+ more_mul_max =
+ min_t(uint32_t,
+ more_mul_max,
+ limits->max_pll_op_freq_hz
+ / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
+ dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %d\n",
+ more_mul_max);
+ /* Don't go above the division capability of op sys clock divider. */
+ more_mul_max = min(more_mul_max,
+ limits->op.max_sys_clk_div * pll->pre_pll_clk_div
+ / div);
+ dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %d\n",
+ more_mul_max);
+ /* Ensure we won't go above min_pll_multiplier. */
+ more_mul_max = min(more_mul_max,
+ DIV_ROUND_UP(limits->max_pll_multiplier, mul));
+ dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %d\n",
+ more_mul_max);
+
+ /* Ensure we won't go below min_pll_op_freq_hz. */
+ more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz,
+ pll->ext_clk_freq_hz / pll->pre_pll_clk_div
+ * mul);
+ dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %d\n",
+ more_mul_min);
+ /* Ensure we won't go below min_pll_multiplier. */
+ more_mul_min = max(more_mul_min,
+ DIV_ROUND_UP(limits->min_pll_multiplier, mul));
+ dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %d\n",
+ more_mul_min);
+
+ if (more_mul_min > more_mul_max) {
+ dev_dbg(dev,
+ "unable to compute more_mul_min and more_mul_max\n");
+ return -EINVAL;
+ }
+
+ more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
+ dev_dbg(dev, "more_mul_factor: %d\n", more_mul_factor);
+ more_mul_factor = lcm(more_mul_factor, limits->op.min_sys_clk_div);
+ dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
+ more_mul_factor);
+ i = roundup(more_mul_min, more_mul_factor);
+ if (!is_one_or_even(i))
+ i <<= 1;
+
+ dev_dbg(dev, "final more_mul: %d\n", i);
+ if (i > more_mul_max) {
+ dev_dbg(dev, "final more_mul is bad, max %d\n", more_mul_max);
+ return -EINVAL;
+ }
+
+ pll->pll_multiplier = mul * i;
+ pll->op_sys_clk_div = div * i / pll->pre_pll_clk_div;
+ dev_dbg(dev, "op_sys_clk_div: %d\n", pll->op_sys_clk_div);
+
+ pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz
+ / pll->pre_pll_clk_div;
+
+ pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz
+ * pll->pll_multiplier;
+
+ /* Derive pll_op_clk_freq_hz. */
+ pll->op_sys_clk_freq_hz =
+ pll->pll_op_clk_freq_hz / pll->op_sys_clk_div;
+
+ pll->op_pix_clk_div = pll->bits_per_pixel;
+ dev_dbg(dev, "op_pix_clk_div: %d\n", pll->op_pix_clk_div);
+
+ pll->op_pix_clk_freq_hz =
+ pll->op_sys_clk_freq_hz / pll->op_pix_clk_div;
+
+ /*
+ * Some sensors perform analogue binning and some do this
+ * digitally. The ones doing this digitally can be roughly be
+ * found out using this formula. The ones doing this digitally
+ * should run at higher clock rate, so smaller divisor is used
+ * on video timing side.
+ */
+ if (limits->min_line_length_pck_bin > limits->min_line_length_pck
+ / pll->binning_horizontal)
+ vt_op_binning_div = pll->binning_horizontal;
+ else
+ vt_op_binning_div = 1;
+ dev_dbg(dev, "vt_op_binning_div: %d\n", vt_op_binning_div);
+
+ /*
+ * Profile 2 supports vt_pix_clk_div E [4, 10]
+ *
+ * Horizontal binning can be used as a base for difference in
+ * divisors. One must make sure that horizontal blanking is
+ * enough to accommodate the CSI-2 sync codes.
+ *
+ * Take scaling factor into account as well.
+ *
+ * Find absolute limits for the factor of vt divider.
+ */
+ dev_dbg(dev, "scale_m: %d\n", pll->scale_m);
+ min_vt_div = DIV_ROUND_UP(pll->op_pix_clk_div * pll->op_sys_clk_div
+ * pll->scale_n,
+ lane_op_clock_ratio * vt_op_binning_div
+ * pll->scale_m);
+
+ /* Find smallest and biggest allowed vt divisor. */
+ dev_dbg(dev, "min_vt_div: %d\n", min_vt_div);
+ min_vt_div = max(min_vt_div,
+ DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
+ limits->vt.max_pix_clk_freq_hz));
+ dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %d\n",
+ min_vt_div);
+ min_vt_div = max_t(uint32_t, min_vt_div,
+ limits->vt.min_pix_clk_div
+ * limits->vt.min_sys_clk_div);
+ dev_dbg(dev, "min_vt_div: min_vt_clk_div: %d\n", min_vt_div);
+
+ max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
+ dev_dbg(dev, "max_vt_div: %d\n", max_vt_div);
+ max_vt_div = min(max_vt_div,
+ DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
+ limits->vt.min_pix_clk_freq_hz));
+ dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %d\n",
+ max_vt_div);
+
+ /*
+ * Find limitsits for sys_clk_div. Not all values are possible
+ * with all values of pix_clk_div.
+ */
+ min_sys_div = limits->vt.min_sys_clk_div;
+ dev_dbg(dev, "min_sys_div: %d\n", min_sys_div);
+ min_sys_div = max(min_sys_div,
+ DIV_ROUND_UP(min_vt_div,
+ limits->vt.max_pix_clk_div));
+ dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %d\n", min_sys_div);
+ min_sys_div = max(min_sys_div,
+ pll->pll_op_clk_freq_hz
+ / limits->vt.max_sys_clk_freq_hz);
+ dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %d\n", min_sys_div);
+ min_sys_div = clk_div_even_up(min_sys_div);
+ dev_dbg(dev, "min_sys_div: one or even: %d\n", min_sys_div);
+
+ max_sys_div = limits->vt.max_sys_clk_div;
+ dev_dbg(dev, "max_sys_div: %d\n", max_sys_div);
+ max_sys_div = min(max_sys_div,
+ DIV_ROUND_UP(max_vt_div,
+ limits->vt.min_pix_clk_div));
+ dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %d\n", max_sys_div);
+ max_sys_div = min(max_sys_div,
+ DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
+ limits->vt.min_pix_clk_freq_hz));
+ dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %d\n", max_sys_div);
+
+ /*
+ * Find pix_div such that a legal pix_div * sys_div results
+ * into a value which is not smaller than div, the desired
+ * divisor.
+ */
+ for (vt_div = min_vt_div; vt_div <= max_vt_div;
+ vt_div += 2 - (vt_div & 1)) {
+ for (sys_div = min_sys_div;
+ sys_div <= max_sys_div;
+ sys_div += 2 - (sys_div & 1)) {
+ uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div);
+
+ if (pix_div < limits->vt.min_pix_clk_div
+ || pix_div > limits->vt.max_pix_clk_div) {
+ dev_dbg(dev,
+ "pix_div %d too small or too big (%d--%d)\n",
+ pix_div,
+ limits->vt.min_pix_clk_div,
+ limits->vt.max_pix_clk_div);
+ continue;
+ }
+
+ /* Check if this one is better. */
+ if (pix_div * sys_div
+ <= roundup(min_vt_div, best_pix_div))
+ best_pix_div = pix_div;
+ }
+ if (best_pix_div < INT_MAX >> 1)
+ break;
+ }
+
+ pll->vt_sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div);
+ pll->vt_pix_clk_div = best_pix_div;
+
+ pll->vt_sys_clk_freq_hz =
+ pll->pll_op_clk_freq_hz / pll->vt_sys_clk_div;
+ pll->vt_pix_clk_freq_hz =
+ pll->vt_sys_clk_freq_hz / pll->vt_pix_clk_div;
+
+ pll->pixel_rate_csi =
+ pll->op_pix_clk_freq_hz * lane_op_clock_ratio;
+
rval = bounds_check(dev, pll->pll_ip_clk_freq_hz,
limits->min_pll_ip_freq_hz,
limits->max_pll_ip_freq_hz,
@@ -111,38 +339,35 @@
"pll_op_clk_freq_hz");
if (!rval)
rval = bounds_check(
- dev, op_pll->sys_clk_div,
- op_limits->min_sys_clk_div, op_limits->max_sys_clk_div,
+ dev, pll->op_sys_clk_div,
+ limits->op.min_sys_clk_div, limits->op.max_sys_clk_div,
"op_sys_clk_div");
if (!rval)
rval = bounds_check(
- dev, op_pll->sys_clk_freq_hz,
- op_limits->min_sys_clk_freq_hz,
- op_limits->max_sys_clk_freq_hz,
+ dev, pll->op_pix_clk_div,
+ limits->op.min_pix_clk_div, limits->op.max_pix_clk_div,
+ "op_pix_clk_div");
+ if (!rval)
+ rval = bounds_check(
+ dev, pll->op_sys_clk_freq_hz,
+ limits->op.min_sys_clk_freq_hz,
+ limits->op.max_sys_clk_freq_hz,
"op_sys_clk_freq_hz");
if (!rval)
rval = bounds_check(
- dev, op_pll->pix_clk_freq_hz,
- op_limits->min_pix_clk_freq_hz,
- op_limits->max_pix_clk_freq_hz,
+ dev, pll->op_pix_clk_freq_hz,
+ limits->op.min_pix_clk_freq_hz,
+ limits->op.max_pix_clk_freq_hz,
"op_pix_clk_freq_hz");
-
- /*
- * If there are no OP clocks, the VT clocks are contained in
- * the OP clock struct.
- */
- if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS)
- return rval;
-
if (!rval)
rval = bounds_check(
- dev, pll->vt.sys_clk_freq_hz,
+ dev, pll->vt_sys_clk_freq_hz,
limits->vt.min_sys_clk_freq_hz,
limits->vt.max_sys_clk_freq_hz,
"vt_sys_clk_freq_hz");
if (!rval)
rval = bounds_check(
- dev, pll->vt.pix_clk_freq_hz,
+ dev, pll->vt_pix_clk_freq_hz,
limits->vt.min_pix_clk_freq_hz,
limits->vt.max_pix_clk_freq_hz,
"vt_pix_clk_freq_hz");
@@ -150,258 +375,10 @@
return rval;
}
-/*
- * Heuristically guess the PLL tree for a given common multiplier and
- * divisor. Begin with the operational timing and continue to video
- * timing once operational timing has been verified.
- *
- * @mul is the PLL multiplier and @div is the common divisor
- * (pre_pll_clk_div and op_sys_clk_div combined). The final PLL
- * multiplier will be a multiple of @mul.
- *
- * @return Zero on success, error code on error.
- */
-static int __smiapp_pll_calculate(
- struct device *dev, const struct smiapp_pll_limits *limits,
- const struct smiapp_pll_branch_limits *op_limits,
- struct smiapp_pll *pll, struct smiapp_pll_branch *op_pll, uint32_t mul,
- uint32_t div, uint32_t lane_op_clock_ratio)
-{
- uint32_t sys_div;
- uint32_t best_pix_div = INT_MAX >> 1;
- uint32_t vt_op_binning_div;
- /*
- * Higher multipliers (and divisors) are often required than
- * necessitated by the external clock and the output clocks.
- * There are limits for all values in the clock tree. These
- * are the minimum and maximum multiplier for mul.
- */
- uint32_t more_mul_min, more_mul_max;
- uint32_t more_mul_factor;
- uint32_t min_vt_div, max_vt_div, vt_div;
- uint32_t min_sys_div, max_sys_div;
- unsigned int i;
-
- /*
- * Get pre_pll_clk_div so that our pll_op_clk_freq_hz won't be
- * too high.
- */
- dev_dbg(dev, "pre_pll_clk_div %u\n", pll->pre_pll_clk_div);
-
- /* Don't go above max pll multiplier. */
- more_mul_max = limits->max_pll_multiplier / mul;
- dev_dbg(dev, "more_mul_max: max_pll_multiplier check: %u\n",
- more_mul_max);
- /* Don't go above max pll op frequency. */
- more_mul_max =
- min_t(uint32_t,
- more_mul_max,
- limits->max_pll_op_freq_hz
- / (pll->ext_clk_freq_hz / pll->pre_pll_clk_div * mul));
- dev_dbg(dev, "more_mul_max: max_pll_op_freq_hz check: %u\n",
- more_mul_max);
- /* Don't go above the division capability of op sys clock divider. */
- more_mul_max = min(more_mul_max,
- op_limits->max_sys_clk_div * pll->pre_pll_clk_div
- / div);
- dev_dbg(dev, "more_mul_max: max_op_sys_clk_div check: %u\n",
- more_mul_max);
- /* Ensure we won't go above min_pll_multiplier. */
- more_mul_max = min(more_mul_max,
- DIV_ROUND_UP(limits->max_pll_multiplier, mul));
- dev_dbg(dev, "more_mul_max: min_pll_multiplier check: %u\n",
- more_mul_max);
-
- /* Ensure we won't go below min_pll_op_freq_hz. */
- more_mul_min = DIV_ROUND_UP(limits->min_pll_op_freq_hz,
- pll->ext_clk_freq_hz / pll->pre_pll_clk_div
- * mul);
- dev_dbg(dev, "more_mul_min: min_pll_op_freq_hz check: %u\n",
- more_mul_min);
- /* Ensure we won't go below min_pll_multiplier. */
- more_mul_min = max(more_mul_min,
- DIV_ROUND_UP(limits->min_pll_multiplier, mul));
- dev_dbg(dev, "more_mul_min: min_pll_multiplier check: %u\n",
- more_mul_min);
-
- if (more_mul_min > more_mul_max) {
- dev_dbg(dev,
- "unable to compute more_mul_min and more_mul_max\n");
- return -EINVAL;
- }
-
- more_mul_factor = lcm(div, pll->pre_pll_clk_div) / div;
- dev_dbg(dev, "more_mul_factor: %u\n", more_mul_factor);
- more_mul_factor = lcm(more_mul_factor, op_limits->min_sys_clk_div);
- dev_dbg(dev, "more_mul_factor: min_op_sys_clk_div: %d\n",
- more_mul_factor);
- i = roundup(more_mul_min, more_mul_factor);
- if (!is_one_or_even(i))
- i <<= 1;
-
- dev_dbg(dev, "final more_mul: %u\n", i);
- if (i > more_mul_max) {
- dev_dbg(dev, "final more_mul is bad, max %u\n", more_mul_max);
- return -EINVAL;
- }
-
- pll->pll_multiplier = mul * i;
- op_pll->sys_clk_div = div * i / pll->pre_pll_clk_div;
- dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll->sys_clk_div);
-
- pll->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz
- / pll->pre_pll_clk_div;
-
- pll->pll_op_clk_freq_hz = pll->pll_ip_clk_freq_hz
- * pll->pll_multiplier;
-
- /* Derive pll_op_clk_freq_hz. */
- op_pll->sys_clk_freq_hz =
- pll->pll_op_clk_freq_hz / op_pll->sys_clk_div;
-
- op_pll->pix_clk_div = pll->bits_per_pixel;
- dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll->pix_clk_div);
-
- op_pll->pix_clk_freq_hz =
- op_pll->sys_clk_freq_hz / op_pll->pix_clk_div;
-
- if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
- /* No OP clocks --- VT clocks are used instead. */
- goto out_skip_vt_calc;
- }
-
- /*
- * Some sensors perform analogue binning and some do this
- * digitally. The ones doing this digitally can be roughly be
- * found out using this formula. The ones doing this digitally
- * should run at higher clock rate, so smaller divisor is used
- * on video timing side.
- */
- if (limits->min_line_length_pck_bin > limits->min_line_length_pck
- / pll->binning_horizontal)
- vt_op_binning_div = pll->binning_horizontal;
- else
- vt_op_binning_div = 1;
- dev_dbg(dev, "vt_op_binning_div: %u\n", vt_op_binning_div);
-
- /*
- * Profile 2 supports vt_pix_clk_div E [4, 10]
- *
- * Horizontal binning can be used as a base for difference in
- * divisors. One must make sure that horizontal blanking is
- * enough to accommodate the CSI-2 sync codes.
- *
- * Take scaling factor into account as well.
- *
- * Find absolute limits for the factor of vt divider.
- */
- dev_dbg(dev, "scale_m: %u\n", pll->scale_m);
- min_vt_div = DIV_ROUND_UP(op_pll->pix_clk_div * op_pll->sys_clk_div
- * pll->scale_n,
- lane_op_clock_ratio * vt_op_binning_div
- * pll->scale_m);
-
- /* Find smallest and biggest allowed vt divisor. */
- dev_dbg(dev, "min_vt_div: %u\n", min_vt_div);
- min_vt_div = max(min_vt_div,
- DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
- limits->vt.max_pix_clk_freq_hz));
- dev_dbg(dev, "min_vt_div: max_vt_pix_clk_freq_hz: %u\n",
- min_vt_div);
- min_vt_div = max_t(uint32_t, min_vt_div,
- limits->vt.min_pix_clk_div
- * limits->vt.min_sys_clk_div);
- dev_dbg(dev, "min_vt_div: min_vt_clk_div: %u\n", min_vt_div);
-
- max_vt_div = limits->vt.max_sys_clk_div * limits->vt.max_pix_clk_div;
- dev_dbg(dev, "max_vt_div: %u\n", max_vt_div);
- max_vt_div = min(max_vt_div,
- DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
- limits->vt.min_pix_clk_freq_hz));
- dev_dbg(dev, "max_vt_div: min_vt_pix_clk_freq_hz: %u\n",
- max_vt_div);
-
- /*
- * Find limitsits for sys_clk_div. Not all values are possible
- * with all values of pix_clk_div.
- */
- min_sys_div = limits->vt.min_sys_clk_div;
- dev_dbg(dev, "min_sys_div: %u\n", min_sys_div);
- min_sys_div = max(min_sys_div,
- DIV_ROUND_UP(min_vt_div,
- limits->vt.max_pix_clk_div));
- dev_dbg(dev, "min_sys_div: max_vt_pix_clk_div: %u\n", min_sys_div);
- min_sys_div = max(min_sys_div,
- pll->pll_op_clk_freq_hz
- / limits->vt.max_sys_clk_freq_hz);
- dev_dbg(dev, "min_sys_div: max_pll_op_clk_freq_hz: %u\n", min_sys_div);
- min_sys_div = clk_div_even_up(min_sys_div);
- dev_dbg(dev, "min_sys_div: one or even: %u\n", min_sys_div);
-
- max_sys_div = limits->vt.max_sys_clk_div;
- dev_dbg(dev, "max_sys_div: %u\n", max_sys_div);
- max_sys_div = min(max_sys_div,
- DIV_ROUND_UP(max_vt_div,
- limits->vt.min_pix_clk_div));
- dev_dbg(dev, "max_sys_div: min_vt_pix_clk_div: %u\n", max_sys_div);
- max_sys_div = min(max_sys_div,
- DIV_ROUND_UP(pll->pll_op_clk_freq_hz,
- limits->vt.min_pix_clk_freq_hz));
- dev_dbg(dev, "max_sys_div: min_vt_pix_clk_freq_hz: %u\n", max_sys_div);
-
- /*
- * Find pix_div such that a legal pix_div * sys_div results
- * into a value which is not smaller than div, the desired
- * divisor.
- */
- for (vt_div = min_vt_div; vt_div <= max_vt_div;
- vt_div += 2 - (vt_div & 1)) {
- for (sys_div = min_sys_div;
- sys_div <= max_sys_div;
- sys_div += 2 - (sys_div & 1)) {
- uint16_t pix_div = DIV_ROUND_UP(vt_div, sys_div);
-
- if (pix_div < limits->vt.min_pix_clk_div
- || pix_div > limits->vt.max_pix_clk_div) {
- dev_dbg(dev,
- "pix_div %u too small or too big (%u--%u)\n",
- pix_div,
- limits->vt.min_pix_clk_div,
- limits->vt.max_pix_clk_div);
- continue;
- }
-
- /* Check if this one is better. */
- if (pix_div * sys_div
- <= roundup(min_vt_div, best_pix_div))
- best_pix_div = pix_div;
- }
- if (best_pix_div < INT_MAX >> 1)
- break;
- }
-
- pll->vt.sys_clk_div = DIV_ROUND_UP(min_vt_div, best_pix_div);
- pll->vt.pix_clk_div = best_pix_div;
-
- pll->vt.sys_clk_freq_hz =
- pll->pll_op_clk_freq_hz / pll->vt.sys_clk_div;
- pll->vt.pix_clk_freq_hz =
- pll->vt.sys_clk_freq_hz / pll->vt.pix_clk_div;
-
-out_skip_vt_calc:
- pll->pixel_rate_csi =
- op_pll->pix_clk_freq_hz * lane_op_clock_ratio;
- pll->pixel_rate_pixel_array = pll->vt.pix_clk_freq_hz;
-
- return check_all_bounds(dev, limits, op_limits, pll, op_pll);
-}
-
int smiapp_pll_calculate(struct device *dev,
const struct smiapp_pll_limits *limits,
struct smiapp_pll *pll)
{
- const struct smiapp_pll_branch_limits *op_limits = &limits->op;
- struct smiapp_pll_branch *op_pll = &pll->op;
uint16_t min_pre_pll_clk_div;
uint16_t max_pre_pll_clk_div;
uint32_t lane_op_clock_ratio;
@@ -409,23 +386,13 @@
unsigned int i;
int rval = -EINVAL;
- if (pll->flags & SMIAPP_PLL_FLAG_NO_OP_CLOCKS) {
- /*
- * If there's no OP PLL at all, use the VT values
- * instead. The OP values are ignored for the rest of
- * the PLL calculation.
- */
- op_limits = &limits->vt;
- op_pll = &pll->vt;
- }
-
if (pll->flags & SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE)
lane_op_clock_ratio = pll->csi2.lanes;
else
lane_op_clock_ratio = 1;
- dev_dbg(dev, "lane_op_clock_ratio: %u\n", lane_op_clock_ratio);
+ dev_dbg(dev, "lane_op_clock_ratio: %d\n", lane_op_clock_ratio);
- dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal,
+ dev_dbg(dev, "binning: %dx%d\n", pll->binning_horizontal,
pll->binning_vertical);
switch (pll->bus_type) {
@@ -444,7 +411,7 @@
}
/* Figure out limits for pre-pll divider based on extclk */
- dev_dbg(dev, "min / max pre_pll_clk_div: %u / %u\n",
+ dev_dbg(dev, "min / max pre_pll_clk_div: %d / %d\n",
limits->min_pre_pll_clk_div, limits->max_pre_pll_clk_div);
max_pre_pll_clk_div =
min_t(uint16_t, limits->max_pre_pll_clk_div,
@@ -455,27 +422,26 @@
clk_div_even_up(
DIV_ROUND_UP(pll->ext_clk_freq_hz,
limits->max_pll_ip_freq_hz)));
- dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %u / %u\n",
+ dev_dbg(dev, "pre-pll check: min / max pre_pll_clk_div: %d / %d\n",
min_pre_pll_clk_div, max_pre_pll_clk_div);
i = gcd(pll->pll_op_clk_freq_hz, pll->ext_clk_freq_hz);
mul = div_u64(pll->pll_op_clk_freq_hz, i);
div = pll->ext_clk_freq_hz / i;
- dev_dbg(dev, "mul %u / div %u\n", mul, div);
+ dev_dbg(dev, "mul %d / div %d\n", mul, div);
min_pre_pll_clk_div =
max_t(uint16_t, min_pre_pll_clk_div,
clk_div_even_up(
DIV_ROUND_UP(mul * pll->ext_clk_freq_hz,
limits->max_pll_op_freq_hz)));
- dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %u / %u\n",
+ dev_dbg(dev, "pll_op check: min / max pre_pll_clk_div: %d / %d\n",
min_pre_pll_clk_div, max_pre_pll_clk_div);
for (pll->pre_pll_clk_div = min_pre_pll_clk_div;
pll->pre_pll_clk_div <= max_pre_pll_clk_div;
pll->pre_pll_clk_div += 2 - (pll->pre_pll_clk_div & 1)) {
- rval = __smiapp_pll_calculate(dev, limits, op_limits, pll,
- op_pll, mul, div,
+ rval = __smiapp_pll_calculate(dev, limits, pll, mul, div,
lane_op_clock_ratio);
if (rval)
continue;
diff --git a/drivers/media/i2c/smiapp-pll.h b/drivers/media/i2c/smiapp-pll.h
index e8f035a..5ce2b61 100644
--- a/drivers/media/i2c/smiapp-pll.h
+++ b/drivers/media/i2c/smiapp-pll.h
@@ -35,13 +35,6 @@
#define SMIAPP_PLL_FLAG_OP_PIX_CLOCK_PER_LANE (1 << 0)
#define SMIAPP_PLL_FLAG_NO_OP_CLOCKS (1 << 1)
-struct smiapp_pll_branch {
- uint16_t sys_clk_div;
- uint16_t pix_clk_div;
- uint32_t sys_clk_freq_hz;
- uint32_t pix_clk_freq_hz;
-};
-
struct smiapp_pll {
/* input values */
uint8_t bus_type;
@@ -60,18 +53,24 @@
uint8_t scale_n;
uint8_t bits_per_pixel;
uint32_t link_freq;
- uint32_t ext_clk_freq_hz;
/* output values */
uint16_t pre_pll_clk_div;
uint16_t pll_multiplier;
+ uint16_t op_sys_clk_div;
+ uint16_t op_pix_clk_div;
+ uint16_t vt_sys_clk_div;
+ uint16_t vt_pix_clk_div;
+
+ uint32_t ext_clk_freq_hz;
uint32_t pll_ip_clk_freq_hz;
uint32_t pll_op_clk_freq_hz;
- struct smiapp_pll_branch vt;
- struct smiapp_pll_branch op;
+ uint32_t op_sys_clk_freq_hz;
+ uint32_t op_pix_clk_freq_hz;
+ uint32_t vt_sys_clk_freq_hz;
+ uint32_t vt_pix_clk_freq_hz;
uint32_t pixel_rate_csi;
- uint32_t pixel_rate_pixel_array;
};
struct smiapp_pll_branch_limits {
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 0df5070..932ed9b 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -205,12 +205,12 @@
int rval;
rval = smiapp_write(
- sensor, SMIAPP_REG_U16_VT_PIX_CLK_DIV, pll->vt.pix_clk_div);
+ sensor, SMIAPP_REG_U16_VT_PIX_CLK_DIV, pll->vt_pix_clk_div);
if (rval < 0)
return rval;
rval = smiapp_write(
- sensor, SMIAPP_REG_U16_VT_SYS_CLK_DIV, pll->vt.sys_clk_div);
+ sensor, SMIAPP_REG_U16_VT_SYS_CLK_DIV, pll->vt_sys_clk_div);
if (rval < 0)
return rval;
@@ -227,21 +227,20 @@
/* Lane op clock ratio does not apply here. */
rval = smiapp_write(
sensor, SMIAPP_REG_U32_REQUESTED_LINK_BIT_RATE_MBPS,
- DIV_ROUND_UP(pll->op.sys_clk_freq_hz, 1000000 / 256 / 256));
+ DIV_ROUND_UP(pll->op_sys_clk_freq_hz, 1000000 / 256 / 256));
if (rval < 0 || sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
return rval;
rval = smiapp_write(
- sensor, SMIAPP_REG_U16_OP_PIX_CLK_DIV, pll->op.pix_clk_div);
+ sensor, SMIAPP_REG_U16_OP_PIX_CLK_DIV, pll->op_pix_clk_div);
if (rval < 0)
return rval;
return smiapp_write(
- sensor, SMIAPP_REG_U16_OP_SYS_CLK_DIV, pll->op.sys_clk_div);
+ sensor, SMIAPP_REG_U16_OP_SYS_CLK_DIV, pll->op_sys_clk_div);
}
-static int smiapp_pll_try(struct smiapp_sensor *sensor,
- struct smiapp_pll *pll)
+static int smiapp_pll_update(struct smiapp_sensor *sensor)
{
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
struct smiapp_pll_limits lim = {
@@ -275,15 +274,19 @@
.min_line_length_pck_bin = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK_BIN],
.min_line_length_pck = sensor->limits[SMIAPP_LIMIT_MIN_LINE_LENGTH_PCK],
};
-
- return smiapp_pll_calculate(&client->dev, &lim, pll);
-}
-
-static int smiapp_pll_update(struct smiapp_sensor *sensor)
-{
struct smiapp_pll *pll = &sensor->pll;
int rval;
+ if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0) {
+ /*
+ * Fill in operational clock divisors limits from the
+ * video timing ones. On profile 0 sensors the
+ * requirements regarding them are essentially the
+ * same as on VT ones.
+ */
+ lim.op = lim.vt;
+ }
+
pll->binning_horizontal = sensor->binning_horizontal;
pll->binning_vertical = sensor->binning_vertical;
pll->link_freq =
@@ -291,12 +294,12 @@
pll->scale_m = sensor->scale_m;
pll->bits_per_pixel = sensor->csi_format->compressed;
- rval = smiapp_pll_try(sensor, pll);
+ rval = smiapp_pll_calculate(&client->dev, &lim, pll);
if (rval < 0)
return rval;
__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_parray,
- pll->pixel_rate_pixel_array);
+ pll->vt_pix_clk_freq_hz);
__v4l2_ctrl_s_ctrl_int64(sensor->pixel_rate_csi, pll->pixel_rate_csi);
return 0;
@@ -330,22 +333,22 @@
* orders must be defined.
*/
static const struct smiapp_csi_data_format smiapp_csi_data_formats[] = {
- { MEDIA_BUS_FMT_SGRBG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GRBG, },
- { MEDIA_BUS_FMT_SRGGB12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_RGGB, },
- { MEDIA_BUS_FMT_SBGGR12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_BGGR, },
- { MEDIA_BUS_FMT_SGBRG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GBRG, },
- { MEDIA_BUS_FMT_SGRBG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GRBG, },
- { MEDIA_BUS_FMT_SRGGB10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_RGGB, },
- { MEDIA_BUS_FMT_SBGGR10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_BGGR, },
- { MEDIA_BUS_FMT_SGBRG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GBRG, },
- { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GRBG, },
- { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_RGGB, },
- { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_BGGR, },
- { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GBRG, },
- { MEDIA_BUS_FMT_SGRBG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GRBG, },
- { MEDIA_BUS_FMT_SRGGB8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_RGGB, },
- { MEDIA_BUS_FMT_SBGGR8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_BGGR, },
- { MEDIA_BUS_FMT_SGBRG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GBRG, },
+ { V4L2_MBUS_FMT_SGRBG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GRBG, },
+ { V4L2_MBUS_FMT_SRGGB12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_RGGB, },
+ { V4L2_MBUS_FMT_SBGGR12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_BGGR, },
+ { V4L2_MBUS_FMT_SGBRG12_1X12, 12, 12, SMIAPP_PIXEL_ORDER_GBRG, },
+ { V4L2_MBUS_FMT_SGRBG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GRBG, },
+ { V4L2_MBUS_FMT_SRGGB10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_RGGB, },
+ { V4L2_MBUS_FMT_SBGGR10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_BGGR, },
+ { V4L2_MBUS_FMT_SGBRG10_1X10, 10, 10, SMIAPP_PIXEL_ORDER_GBRG, },
+ { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GRBG, },
+ { V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_RGGB, },
+ { V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_BGGR, },
+ { V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, 10, 8, SMIAPP_PIXEL_ORDER_GBRG, },
+ { V4L2_MBUS_FMT_SGRBG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GRBG, },
+ { V4L2_MBUS_FMT_SRGGB8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_RGGB, },
+ { V4L2_MBUS_FMT_SBGGR8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_BGGR, },
+ { V4L2_MBUS_FMT_SGBRG8_1X8, 8, 8, SMIAPP_PIXEL_ORDER_GBRG, },
};
const char *pixel_order_str[] = { "GRBG", "RGGB", "BGGR", "GBRG" };
@@ -523,8 +526,6 @@
static int smiapp_init_controls(struct smiapp_sensor *sensor)
{
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
- unsigned long *valid_link_freqs = &sensor->valid_link_freqs[
- sensor->csi_format->compressed - SMIAPP_COMPRESSED_BASE];
unsigned int max, i;
int rval;
@@ -607,8 +608,8 @@
sensor->link_freq = v4l2_ctrl_new_int_menu(
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
- V4L2_CID_LINK_FREQ, __fls(*valid_link_freqs),
- __ffs(*valid_link_freqs), sensor->platform_data->op_sys_clock);
+ V4L2_CID_LINK_FREQ, max, 0,
+ sensor->platform_data->op_sys_clock);
sensor->pixel_rate_csi = v4l2_ctrl_new_std(
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
@@ -744,7 +745,6 @@
static int smiapp_get_mbus_formats(struct smiapp_sensor *sensor)
{
struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
- struct smiapp_pll *pll = &sensor->pll;
unsigned int type, n;
unsigned int i, pixel_order;
int rval;
@@ -808,57 +808,14 @@
dev_dbg(&client->dev, "jolly good! %d\n", j);
sensor->default_mbus_frame_fmts |= 1 << j;
- }
- }
-
- /* Figure out which BPP values can be used with which formats. */
- pll->binning_horizontal = 1;
- pll->binning_vertical = 1;
- pll->scale_m = sensor->scale_m;
-
- for (i = 0; i < ARRAY_SIZE(smiapp_csi_data_formats); i++) {
- const struct smiapp_csi_data_format *f =
- &smiapp_csi_data_formats[i];
- unsigned long *valid_link_freqs =
- &sensor->valid_link_freqs[
- f->compressed - SMIAPP_COMPRESSED_BASE];
- unsigned int j;
-
- BUG_ON(f->compressed < SMIAPP_COMPRESSED_BASE);
- BUG_ON(f->compressed > SMIAPP_COMPRESSED_MAX);
-
- if (!(sensor->default_mbus_frame_fmts & 1 << i))
- continue;
-
- pll->bits_per_pixel = f->compressed;
-
- for (j = 0; sensor->platform_data->op_sys_clock[j]; j++) {
- pll->link_freq = sensor->platform_data->op_sys_clock[j];
-
- rval = smiapp_pll_try(sensor, pll);
- dev_dbg(&client->dev, "link freq %u Hz, bpp %u %s\n",
- pll->link_freq, pll->bits_per_pixel,
- rval ? "not ok" : "ok");
- if (rval)
- continue;
-
- set_bit(j, valid_link_freqs);
- }
-
- if (!*valid_link_freqs) {
- dev_info(&client->dev,
- "no valid link frequencies for %u bpp\n",
- f->compressed);
- sensor->default_mbus_frame_fmts &= ~BIT(i);
- continue;
- }
-
- if (!sensor->csi_format
- || f->width > sensor->csi_format->width
- || (f->width == sensor->csi_format->width
- && f->compressed > sensor->csi_format->compressed)) {
- sensor->csi_format = f;
- sensor->internal_csi_format = f;
+ if (!sensor->csi_format
+ || f->width > sensor->csi_format->width
+ || (f->width == sensor->csi_format->width
+ && f->compressed
+ > sensor->csi_format->compressed)) {
+ sensor->csi_format = f;
+ sensor->internal_csi_format = f;
+ }
}
}
@@ -947,7 +904,7 @@
dev_dbg(&client->dev, "hblank\t\t%d\n", sensor->hblank->val);
dev_dbg(&client->dev, "real timeperframe\t100/%d\n",
- sensor->pll.pixel_rate_pixel_array /
+ sensor->pll.vt_pix_clk_freq_hz /
((sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].width
+ sensor->hblank->val) *
(sensor->pixel_array->crop[SMIAPP_PA_PAD_SRC].height
@@ -1730,59 +1687,6 @@
return csi_format;
}
-static int smiapp_set_format_source(struct v4l2_subdev *subdev,
- struct v4l2_subdev_fh *fh,
- struct v4l2_subdev_format *fmt)
-{
- struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
- const struct smiapp_csi_data_format *csi_format,
- *old_csi_format = sensor->csi_format;
- unsigned long *valid_link_freqs;
- u32 code = fmt->format.code;
- unsigned int i;
- int rval;
-
- rval = __smiapp_get_format(subdev, fh, fmt);
- if (rval)
- return rval;
-
- /*
- * Media bus code is changeable on src subdev's source pad. On
- * other source pads we just get format here.
- */
- if (subdev != &sensor->src->sd)
- return 0;
-
- csi_format = smiapp_validate_csi_data_format(sensor, code);
-
- fmt->format.code = csi_format->code;
-
- if (fmt->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return 0;
-
- sensor->csi_format = csi_format;
-
- if (csi_format->width != old_csi_format->width)
- for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++)
- __v4l2_ctrl_modify_range(
- sensor->test_data[i], 0,
- (1 << csi_format->width) - 1, 1, 0);
-
- if (csi_format->compressed == old_csi_format->compressed)
- return 0;
-
- valid_link_freqs =
- &sensor->valid_link_freqs[sensor->csi_format->compressed
- - SMIAPP_COMPRESSED_BASE];
-
- __v4l2_ctrl_modify_range(
- sensor->link_freq, 0,
- __fls(*valid_link_freqs), ~*valid_link_freqs,
- __ffs(*valid_link_freqs));
-
- return smiapp_pll_update(sensor);
-}
-
static int smiapp_set_format(struct v4l2_subdev *subdev,
struct v4l2_subdev_fh *fh,
struct v4l2_subdev_format *fmt)
@@ -1793,14 +1697,41 @@
mutex_lock(&sensor->mutex);
+ /*
+ * Media bus code is changeable on src subdev's source pad. On
+ * other source pads we just get format here.
+ */
if (fmt->pad == ssd->source_pad) {
- int rval;
+ u32 code = fmt->format.code;
+ int rval = __smiapp_get_format(subdev, fh, fmt);
+ bool range_changed = false;
+ unsigned int i;
- rval = smiapp_set_format_source(subdev, fh, fmt);
+ if (!rval && subdev == &sensor->src->sd) {
+ const struct smiapp_csi_data_format *csi_format =
+ smiapp_validate_csi_data_format(sensor, code);
+
+ if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+ if (csi_format->width !=
+ sensor->csi_format->width)
+ range_changed = true;
+
+ sensor->csi_format = csi_format;
+ }
+
+ fmt->format.code = csi_format->code;
+ }
mutex_unlock(&sensor->mutex);
+ if (rval || !range_changed)
+ return rval;
- return rval;
+ for (i = 0; i < ARRAY_SIZE(sensor->test_data); i++)
+ v4l2_ctrl_modify_range(
+ sensor->test_data[i],
+ 0, (1 << sensor->csi_format->width) - 1, 1, 0);
+
+ return 0;
}
/* Sink pad. Width and height are changeable here. */
@@ -2092,11 +2023,6 @@
== SMIAPP_DIGITAL_CROP_CAPABILITY_INPUT_CROP)
return 0;
return -EINVAL;
- case V4L2_SEL_TGT_NATIVE_SIZE:
- if (ssd == sensor->pixel_array
- && sel->pad == SMIAPP_PA_PAD_SRC)
- return 0;
- return -EINVAL;
case V4L2_SEL_TGT_COMPOSE:
case V4L2_SEL_TGT_COMPOSE_BOUNDS:
if (sel->pad == ssd->source_pad)
@@ -2195,9 +2121,7 @@
switch (sel->target) {
case V4L2_SEL_TGT_CROP_BOUNDS:
- case V4L2_SEL_TGT_NATIVE_SIZE:
if (ssd == sensor->pixel_array) {
- sel->r.left = sel->r.top = 0;
sel->r.width =
sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
sel->r.height =
@@ -2266,7 +2190,7 @@
ret = smiapp_set_compose(subdev, fh, sel);
break;
default:
- ret = -EINVAL;
+ BUG();
}
mutex_unlock(&sensor->mutex);
@@ -2558,6 +2482,12 @@
goto out_power_off;
}
+ rval = smiapp_get_mbus_formats(sensor);
+ if (rval) {
+ rval = -ENODEV;
+ goto out_power_off;
+ }
+
if (sensor->limits[SMIAPP_LIMIT_BINNING_CAPABILITY]) {
u32 val;
@@ -2639,22 +2569,6 @@
sensor->scale_m = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
- /* prepare PLL configuration input values */
- pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
- pll->csi2.lanes = sensor->platform_data->lanes;
- pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
- pll->flags = smiapp_call_quirk(sensor, pll_flags);
- pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
- /* Profile 0 sensors have no separate OP clock branch. */
- if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
- pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
-
- rval = smiapp_get_mbus_formats(sensor);
- if (rval) {
- rval = -ENODEV;
- goto out_nvm_release;
- }
-
for (i = 0; i < SMIAPP_SUBDEVS; i++) {
struct {
struct smiapp_subdev *ssd;
@@ -2752,9 +2666,18 @@
if (rval < 0)
goto out_nvm_release;
- mutex_lock(&sensor->mutex);
+ /* prepare PLL configuration input values */
+ pll->bus_type = SMIAPP_PLL_BUS_TYPE_CSI2;
+ pll->csi2.lanes = sensor->platform_data->lanes;
+ pll->ext_clk_freq_hz = sensor->platform_data->ext_clk;
+ pll->flags = smiapp_call_quirk(sensor, pll_flags);
+
+ /* Profile 0 sensors have no separate OP clock branch. */
+ if (sensor->minfo.smiapp_profile == SMIAPP_PROFILE_0)
+ pll->flags |= SMIAPP_PLL_FLAG_NO_OP_CLOCKS;
+ pll->scale_n = sensor->limits[SMIAPP_LIMIT_SCALER_N_MIN];
+
rval = smiapp_update_mode(sensor);
- mutex_unlock(&sensor->mutex);
if (rval) {
dev_err(&client->dev, "update mode failed\n");
goto out_nvm_release;
diff --git a/drivers/media/i2c/smiapp/smiapp.h b/drivers/media/i2c/smiapp/smiapp.h
index f88f8ec..874b49f 100644
--- a/drivers/media/i2c/smiapp/smiapp.h
+++ b/drivers/media/i2c/smiapp/smiapp.h
@@ -156,11 +156,6 @@
#define SMIAPP_PAD_SRC 1
#define SMIAPP_PADS 2
-#define SMIAPP_COMPRESSED_BASE 8
-#define SMIAPP_COMPRESSED_MAX 12
-#define SMIAPP_NR_OF_COMPRESSED (SMIAPP_COMPRESSED_MAX - \
- SMIAPP_COMPRESSED_BASE + 1)
-
struct smiapp_binning_subtype {
u8 horizontal:4;
u8 vertical:4;
@@ -237,9 +232,6 @@
struct smiapp_pll pll;
- /* Is a default format supported for a given BPP? */
- unsigned long valid_link_freqs[SMIAPP_NR_OF_COMPRESSED];
-
/* Pixel array controls */
struct v4l2_ctrl *analog_gain;
struct v4l2_ctrl *exposure;
diff --git a/drivers/media/i2c/soc_camera/imx074.c b/drivers/media/i2c/soc_camera/imx074.c
index ec89cfa..5b91593 100644
--- a/drivers/media/i2c/soc_camera/imx074.c
+++ b/drivers/media/i2c/soc_camera/imx074.c
@@ -71,7 +71,7 @@
/* IMX074 has only one fixed colorspace per pixelcode */
struct imx074_datafmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
};
@@ -82,7 +82,7 @@
};
static const struct imx074_datafmt imx074_colour_fmts[] = {
- {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
};
static struct imx074 *to_imx074(const struct i2c_client *client)
@@ -91,7 +91,7 @@
}
/* Find a data format by a pixel code in an array */
-static const struct imx074_datafmt *imx074_find_datafmt(u32 code)
+static const struct imx074_datafmt *imx074_find_datafmt(enum v4l2_mbus_pixelcode code)
{
int i;
@@ -236,7 +236,7 @@
}
static int imx074_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if ((unsigned int)index >= ARRAY_SIZE(imx074_colour_fmts))
return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c
index 0cc1901..8150d0d 100644
--- a/drivers/media/i2c/soc_camera/mt9m001.c
+++ b/drivers/media/i2c/soc_camera/mt9m001.c
@@ -53,13 +53,13 @@
/* MT9M001 has only one fixed colorspace per pixelcode */
struct mt9m001_datafmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
};
/* Find a data format by a pixel code in an array */
static const struct mt9m001_datafmt *mt9m001_find_datafmt(
- u32 code, const struct mt9m001_datafmt *fmt,
+ enum v4l2_mbus_pixelcode code, const struct mt9m001_datafmt *fmt,
int n)
{
int i;
@@ -75,14 +75,14 @@
* Order important: first natively supported,
* second supported with a GPIO extender
*/
- {MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
};
static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = {
/* Order important - see above */
- {MEDIA_BUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
- {MEDIA_BUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
};
struct mt9m001 {
@@ -563,7 +563,7 @@
};
static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9m001 *mt9m001 = to_mt9m001(client);
diff --git a/drivers/media/i2c/soc_camera/mt9m111.c b/drivers/media/i2c/soc_camera/mt9m111.c
index a35a2f9..e5c5d9a 100644
--- a/drivers/media/i2c/soc_camera/mt9m111.c
+++ b/drivers/media/i2c/soc_camera/mt9m111.c
@@ -182,23 +182,23 @@
/* MT9M111 has only one fixed colorspace per pixelcode */
struct mt9m111_datafmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
};
static const struct mt9m111_datafmt mt9m111_colour_fmts[] = {
- {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
- {MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
- {MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
- {MEDIA_BUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG},
- {MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_BGR565_2X8_LE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_BGR565_2X8_BE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_VYUY8_2X8, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_BGR565_2X8_LE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_BGR565_2X8_BE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
};
struct mt9m111 {
@@ -218,7 +218,7 @@
/* Find a data format by a pixel code */
static const struct mt9m111_datafmt *mt9m111_find_datafmt(struct mt9m111 *mt9m111,
- u32 code)
+ enum v4l2_mbus_pixelcode code)
{
int i;
for (i = 0; i < ARRAY_SIZE(mt9m111_colour_fmts); i++)
@@ -331,7 +331,7 @@
}
static int mt9m111_setup_geometry(struct mt9m111 *mt9m111, struct v4l2_rect *rect,
- int width, int height, u32 code)
+ int width, int height, enum v4l2_mbus_pixelcode code)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
int ret;
@@ -345,7 +345,7 @@
if (!ret)
ret = reg_write(WINDOW_HEIGHT, rect->height);
- if (code != MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {
+ if (code != V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
/* IFP in use, down-scaling possible */
if (!ret)
ret = mt9m111_setup_rect_ctx(mt9m111, &context_b,
@@ -393,8 +393,8 @@
if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL;
- if (mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
- mt9m111->fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {
+ if (mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+ mt9m111->fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
/* Bayer format - even size lengths */
rect.width = ALIGN(rect.width, 2);
rect.height = ALIGN(rect.height, 2);
@@ -462,7 +462,7 @@
}
static int mt9m111_set_pixfmt(struct mt9m111 *mt9m111,
- u32 code)
+ enum v4l2_mbus_pixelcode code)
{
struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
u16 data_outfmt2, mask_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
@@ -474,46 +474,46 @@
int ret;
switch (code) {
- case MEDIA_BUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
data_outfmt2 = MT9M111_OUTFMT_PROCESSED_BAYER |
MT9M111_OUTFMT_RGB;
break;
- case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
+ case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
data_outfmt2 = MT9M111_OUTFMT_BYPASS_IFP | MT9M111_OUTFMT_RGB;
break;
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
+ case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555 |
MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
break;
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
+ case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB555;
break;
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
break;
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
+ case V4L2_MBUS_FMT_RGB565_2X8_BE:
data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565;
break;
- case MEDIA_BUS_FMT_BGR565_2X8_BE:
+ case V4L2_MBUS_FMT_BGR565_2X8_BE:
data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
break;
- case MEDIA_BUS_FMT_BGR565_2X8_LE:
+ case V4L2_MBUS_FMT_BGR565_2X8_LE:
data_outfmt2 = MT9M111_OUTFMT_RGB | MT9M111_OUTFMT_RGB565 |
MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
break;
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
data_outfmt2 = 0;
break;
- case MEDIA_BUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
break;
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN;
break;
- case MEDIA_BUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
data_outfmt2 = MT9M111_OUTFMT_SWAP_YCbCr_C_Y_RGB_EVEN |
MT9M111_OUTFMT_SWAP_YCbCr_Cb_Cr_RGB_R_B;
break;
@@ -542,8 +542,8 @@
fmt = mt9m111_find_datafmt(mt9m111, mf->code);
- bayer = fmt->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
- fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE;
+ bayer = fmt->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+ fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE;
/*
* With Bayer format enforce even side lengths, but let the user play
@@ -554,7 +554,7 @@
rect->height = ALIGN(rect->height, 2);
}
- if (fmt->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE) {
+ if (fmt->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE) {
/* IFP bypass mode, no scaling */
mf->width = rect->width;
mf->height = rect->height;
@@ -840,7 +840,7 @@
};
static int mt9m111_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(mt9m111_colour_fmts))
return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c
index e803676..b8d9f2c 100644
--- a/drivers/media/i2c/soc_camera/mt9t031.c
+++ b/drivers/media/i2c/soc_camera/mt9t031.c
@@ -345,7 +345,7 @@
mf->width = mt9t031->rect.width / mt9t031->xskip;
mf->height = mt9t031->rect.height / mt9t031->yskip;
- mf->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ mf->code = V4L2_MBUS_FMT_SBGGR10_1X10;
mf->colorspace = V4L2_COLORSPACE_SRGB;
mf->field = V4L2_FIELD_NONE;
@@ -367,7 +367,7 @@
xskip = mt9t031_skip(&rect.width, mf->width, MT9T031_MAX_WIDTH);
yskip = mt9t031_skip(&rect.height, mf->height, MT9T031_MAX_HEIGHT);
- mf->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ mf->code = V4L2_MBUS_FMT_SBGGR10_1X10;
mf->colorspace = V4L2_COLORSPACE_SRGB;
/* mt9t031_set_params() doesn't change width and height */
@@ -385,7 +385,7 @@
&mf->width, MT9T031_MIN_WIDTH, MT9T031_MAX_WIDTH, 1,
&mf->height, MT9T031_MIN_HEIGHT, MT9T031_MAX_HEIGHT, 1, 0);
- mf->code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ mf->code = V4L2_MBUS_FMT_SBGGR10_1X10;
mf->colorspace = V4L2_COLORSPACE_SRGB;
return 0;
@@ -673,12 +673,12 @@
};
static int mt9t031_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_SBGGR10_1X10;
+ *code = V4L2_MBUS_FMT_SBGGR10_1X10;
return 0;
}
diff --git a/drivers/media/i2c/soc_camera/mt9t112.c b/drivers/media/i2c/soc_camera/mt9t112.c
index 113f0eb..7520e11 100644
--- a/drivers/media/i2c/soc_camera/mt9t112.c
+++ b/drivers/media/i2c/soc_camera/mt9t112.c
@@ -77,7 +77,7 @@
struct
************************************************************************/
struct mt9t112_format {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
u16 fmt;
u16 order;
@@ -103,32 +103,32 @@
static const struct mt9t112_format mt9t112_cfmts[] = {
{
- .code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .code = V4L2_MBUS_FMT_UYVY8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.fmt = 1,
.order = 0,
}, {
- .code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .code = V4L2_MBUS_FMT_VYUY8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.fmt = 1,
.order = 1,
}, {
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.fmt = 1,
.order = 2,
}, {
- .code = MEDIA_BUS_FMT_YVYU8_2X8,
+ .code = V4L2_MBUS_FMT_YVYU8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.fmt = 1,
.order = 3,
}, {
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+ .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
.colorspace = V4L2_COLORSPACE_SRGB,
.fmt = 8,
.order = 2,
}, {
- .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+ .code = V4L2_MBUS_FMT_RGB565_2X8_LE,
.colorspace = V4L2_COLORSPACE_SRGB,
.fmt = 4,
.order = 2,
@@ -840,7 +840,7 @@
static int mt9t112_set_params(struct mt9t112_priv *priv,
const struct v4l2_rect *rect,
- u32 code)
+ enum v4l2_mbus_pixelcode code)
{
int i;
@@ -953,7 +953,7 @@
break;
if (i == priv->num_formats) {
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
mf->colorspace = V4L2_COLORSPACE_JPEG;
} else {
mf->colorspace = mt9t112_cfmts[i].colorspace;
@@ -967,7 +967,7 @@
}
static int mt9t112_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9t112_priv *priv = to_mt9t112(client);
@@ -1101,7 +1101,7 @@
/* Cannot fail: using the default supported pixel code */
if (!ret)
- mt9t112_set_params(priv, &rect, MEDIA_BUS_FMT_UYVY8_2X8);
+ mt9t112_set_params(priv, &rect, V4L2_MBUS_FMT_UYVY8_2X8);
else
v4l2_clk_put(priv->clk);
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index a82cf3d..8250357 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -85,13 +85,13 @@
/* MT9V022 has only one fixed colorspace per pixelcode */
struct mt9v022_datafmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
};
/* Find a data format by a pixel code in an array */
static const struct mt9v022_datafmt *mt9v022_find_datafmt(
- u32 code, const struct mt9v022_datafmt *fmt,
+ enum v4l2_mbus_pixelcode code, const struct mt9v022_datafmt *fmt,
int n)
{
int i;
@@ -107,14 +107,14 @@
* Order important: first natively supported,
* second supported with a GPIO extender
*/
- {MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_COLORSPACE_SRGB},
};
static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
/* Order important - see above */
- {MEDIA_BUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
- {MEDIA_BUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
};
/* only registers with different addresses on different mt9v02x sensors */
@@ -410,13 +410,13 @@
* .try_mbus_fmt(), datawidth is from our supported format list
*/
switch (mf->code) {
- case MEDIA_BUS_FMT_Y8_1X8:
- case MEDIA_BUS_FMT_Y10_1X10:
+ case V4L2_MBUS_FMT_Y8_1X8:
+ case V4L2_MBUS_FMT_Y10_1X10:
if (mt9v022->model != MT9V022IX7ATM)
return -EINVAL;
break;
- case MEDIA_BUS_FMT_SBGGR8_1X8:
- case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SBGGR10_1X10:
if (mt9v022->model != MT9V022IX7ATC)
return -EINVAL;
break;
@@ -443,8 +443,8 @@
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9v022 *mt9v022 = to_mt9v022(client);
const struct mt9v022_datafmt *fmt;
- int align = mf->code == MEDIA_BUS_FMT_SBGGR8_1X8 ||
- mf->code == MEDIA_BUS_FMT_SBGGR10_1X10;
+ int align = mf->code == V4L2_MBUS_FMT_SBGGR8_1X8 ||
+ mf->code == V4L2_MBUS_FMT_SBGGR10_1X10;
v4l_bound_align_image(&mf->width, MT9V022_MIN_WIDTH,
MT9V022_MAX_WIDTH, align,
@@ -759,7 +759,7 @@
};
static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct mt9v022 *mt9v022 = to_mt9v022(client);
diff --git a/drivers/media/i2c/soc_camera/ov2640.c b/drivers/media/i2c/soc_camera/ov2640.c
index 0c05283..ce0517d 100644
--- a/drivers/media/i2c/soc_camera/ov2640.c
+++ b/drivers/media/i2c/soc_camera/ov2640.c
@@ -302,7 +302,7 @@
struct ov2640_priv {
struct v4l2_subdev subdev;
struct v4l2_ctrl_handler hdl;
- u32 cfmt_code;
+ enum v4l2_mbus_pixelcode cfmt_code;
struct v4l2_clk *clk;
const struct ov2640_win_size *win;
};
@@ -623,11 +623,11 @@
ENDMARKER,
};
-static u32 ov2640_codes[] = {
- MEDIA_BUS_FMT_YUYV8_2X8,
- MEDIA_BUS_FMT_UYVY8_2X8,
- MEDIA_BUS_FMT_RGB565_2X8_BE,
- MEDIA_BUS_FMT_RGB565_2X8_LE,
+static enum v4l2_mbus_pixelcode ov2640_codes[] = {
+ V4L2_MBUS_FMT_YUYV8_2X8,
+ V4L2_MBUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_RGB565_2X8_BE,
+ V4L2_MBUS_FMT_RGB565_2X8_LE,
};
/*
@@ -785,7 +785,7 @@
}
static int ov2640_set_params(struct i2c_client *client, u32 *width, u32 *height,
- u32 code)
+ enum v4l2_mbus_pixelcode code)
{
struct ov2640_priv *priv = to_ov2640(client);
const struct regval_list *selected_cfmt_regs;
@@ -797,20 +797,20 @@
/* select format */
priv->cfmt_code = 0;
switch (code) {
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
+ case V4L2_MBUS_FMT_RGB565_2X8_BE:
dev_dbg(&client->dev, "%s: Selected cfmt RGB565 BE", __func__);
selected_cfmt_regs = ov2640_rgb565_be_regs;
break;
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
dev_dbg(&client->dev, "%s: Selected cfmt RGB565 LE", __func__);
selected_cfmt_regs = ov2640_rgb565_le_regs;
break;
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
dev_dbg(&client->dev, "%s: Selected cfmt YUYV (YUV422)", __func__);
selected_cfmt_regs = ov2640_yuyv_regs;
break;
default:
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
dev_dbg(&client->dev, "%s: Selected cfmt UYVY", __func__);
selected_cfmt_regs = ov2640_uyvy_regs;
}
@@ -869,7 +869,7 @@
if (!priv->win) {
u32 width = W_SVGA, height = H_SVGA;
priv->win = ov2640_select_win(&width, &height);
- priv->cfmt_code = MEDIA_BUS_FMT_UYVY8_2X8;
+ priv->cfmt_code = V4L2_MBUS_FMT_UYVY8_2X8;
}
mf->width = priv->win->width;
@@ -877,13 +877,13 @@
mf->code = priv->cfmt_code;
switch (mf->code) {
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_BE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
mf->colorspace = V4L2_COLORSPACE_SRGB;
break;
default:
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
mf->colorspace = V4L2_COLORSPACE_JPEG;
}
mf->field = V4L2_FIELD_NONE;
@@ -899,14 +899,14 @@
switch (mf->code) {
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_BE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
mf->colorspace = V4L2_COLORSPACE_SRGB;
break;
default:
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
mf->colorspace = V4L2_COLORSPACE_JPEG;
}
@@ -926,14 +926,14 @@
mf->field = V4L2_FIELD_NONE;
switch (mf->code) {
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_BE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
mf->colorspace = V4L2_COLORSPACE_SRGB;
break;
default:
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
mf->colorspace = V4L2_COLORSPACE_JPEG;
}
@@ -941,7 +941,7 @@
}
static int ov2640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(ov2640_codes))
return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov5642.c b/drivers/media/i2c/soc_camera/ov5642.c
index e9a2931..c8a3921 100644
--- a/drivers/media/i2c/soc_camera/ov5642.c
+++ b/drivers/media/i2c/soc_camera/ov5642.c
@@ -602,7 +602,7 @@
};
struct ov5642_datafmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
};
@@ -618,7 +618,7 @@
};
static const struct ov5642_datafmt ov5642_colour_fmts[] = {
- {MEDIA_BUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_UYVY8_2X8, V4L2_COLORSPACE_JPEG},
};
static struct ov5642 *to_ov5642(const struct i2c_client *client)
@@ -628,7 +628,7 @@
/* Find a data format by a pixel code in an array */
static const struct ov5642_datafmt
- *ov5642_find_datafmt(u32 code)
+ *ov5642_find_datafmt(enum v4l2_mbus_pixelcode code)
{
int i;
@@ -840,7 +840,7 @@
}
static int ov5642_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(ov5642_colour_fmts))
return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov6650.c b/drivers/media/i2c/soc_camera/ov6650.c
index 3d3dfeb..adbc185 100644
--- a/drivers/media/i2c/soc_camera/ov6650.c
+++ b/drivers/media/i2c/soc_camera/ov6650.c
@@ -202,18 +202,18 @@
unsigned long pclk_limit; /* from host */
unsigned long pclk_max; /* from resolution and format */
struct v4l2_fract tpf; /* as requested with s_parm */
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
};
-static u32 ov6650_codes[] = {
- MEDIA_BUS_FMT_YUYV8_2X8,
- MEDIA_BUS_FMT_UYVY8_2X8,
- MEDIA_BUS_FMT_YVYU8_2X8,
- MEDIA_BUS_FMT_VYUY8_2X8,
- MEDIA_BUS_FMT_SBGGR8_1X8,
- MEDIA_BUS_FMT_Y8_1X8,
+static enum v4l2_mbus_pixelcode ov6650_codes[] = {
+ V4L2_MBUS_FMT_YUYV8_2X8,
+ V4L2_MBUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_YVYU8_2X8,
+ V4L2_MBUS_FMT_VYUY8_2X8,
+ V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_MBUS_FMT_Y8_1X8,
};
/* read a register */
@@ -555,29 +555,29 @@
.height = mf->height << half_scale,
},
};
- u32 code = mf->code;
+ enum v4l2_mbus_pixelcode code = mf->code;
unsigned long mclk, pclk;
u8 coma_set = 0, coma_mask = 0, coml_set, coml_mask, clkrc;
int ret;
/* select color matrix configuration for given color encoding */
switch (code) {
- case MEDIA_BUS_FMT_Y8_1X8:
+ case V4L2_MBUS_FMT_Y8_1X8:
dev_dbg(&client->dev, "pixel format GREY8_1X8\n");
coma_mask |= COMA_RGB | COMA_WORD_SWAP | COMA_BYTE_SWAP;
coma_set |= COMA_BW;
break;
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
dev_dbg(&client->dev, "pixel format YUYV8_2X8_LE\n");
coma_mask |= COMA_RGB | COMA_BW | COMA_BYTE_SWAP;
coma_set |= COMA_WORD_SWAP;
break;
- case MEDIA_BUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
dev_dbg(&client->dev, "pixel format YVYU8_2X8_LE (untested)\n");
coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP |
COMA_BYTE_SWAP;
break;
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
dev_dbg(&client->dev, "pixel format YUYV8_2X8_BE\n");
if (half_scale) {
coma_mask |= COMA_RGB | COMA_BW | COMA_WORD_SWAP;
@@ -587,7 +587,7 @@
coma_set |= COMA_BYTE_SWAP | COMA_WORD_SWAP;
}
break;
- case MEDIA_BUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
dev_dbg(&client->dev, "pixel format YVYU8_2X8_BE (untested)\n");
if (half_scale) {
coma_mask |= COMA_RGB | COMA_BW;
@@ -597,7 +597,7 @@
coma_set |= COMA_BYTE_SWAP;
}
break;
- case MEDIA_BUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
dev_dbg(&client->dev, "pixel format SBGGR8_1X8 (untested)\n");
coma_mask |= COMA_BW | COMA_BYTE_SWAP | COMA_WORD_SWAP;
coma_set |= COMA_RAW_RGB | COMA_RGB;
@@ -608,8 +608,8 @@
}
priv->code = code;
- if (code == MEDIA_BUS_FMT_Y8_1X8 ||
- code == MEDIA_BUS_FMT_SBGGR8_1X8) {
+ if (code == V4L2_MBUS_FMT_Y8_1X8 ||
+ code == V4L2_MBUS_FMT_SBGGR8_1X8) {
coml_mask = COML_ONE_CHANNEL;
coml_set = 0;
priv->pclk_max = 4000000;
@@ -619,7 +619,7 @@
priv->pclk_max = 8000000;
}
- if (code == MEDIA_BUS_FMT_SBGGR8_1X8)
+ if (code == V4L2_MBUS_FMT_SBGGR8_1X8)
priv->colorspace = V4L2_COLORSPACE_SRGB;
else if (code != 0)
priv->colorspace = V4L2_COLORSPACE_JPEG;
@@ -697,18 +697,18 @@
mf->field = V4L2_FIELD_NONE;
switch (mf->code) {
- case MEDIA_BUS_FMT_Y10_1X10:
- mf->code = MEDIA_BUS_FMT_Y8_1X8;
- case MEDIA_BUS_FMT_Y8_1X8:
- case MEDIA_BUS_FMT_YVYU8_2X8:
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_VYUY8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_Y10_1X10:
+ mf->code = V4L2_MBUS_FMT_Y8_1X8;
+ case V4L2_MBUS_FMT_Y8_1X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
mf->colorspace = V4L2_COLORSPACE_JPEG;
break;
default:
- mf->code = MEDIA_BUS_FMT_SBGGR8_1X8;
- case MEDIA_BUS_FMT_SBGGR8_1X8:
+ mf->code = V4L2_MBUS_FMT_SBGGR8_1X8;
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
mf->colorspace = V4L2_COLORSPACE_SRGB;
break;
}
@@ -717,7 +717,7 @@
}
static int ov6650_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(ov6650_codes))
return -EINVAL;
@@ -1013,7 +1013,7 @@
priv->rect.width = W_CIF;
priv->rect.height = H_CIF;
priv->half_scale = false;
- priv->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ priv->code = V4L2_MBUS_FMT_YUYV8_2X8;
priv->colorspace = V4L2_COLORSPACE_JPEG;
priv->clk = v4l2_clk_get(&client->dev, "mclk");
diff --git a/drivers/media/i2c/soc_camera/ov772x.c b/drivers/media/i2c/soc_camera/ov772x.c
index 4eef535..8650c78 100644
--- a/drivers/media/i2c/soc_camera/ov772x.c
+++ b/drivers/media/i2c/soc_camera/ov772x.c
@@ -376,7 +376,7 @@
*/
struct ov772x_color_format {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
u8 dsp3;
u8 dsp4;
@@ -408,7 +408,7 @@
*/
static const struct ov772x_color_format ov772x_cfmts[] = {
{
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.dsp3 = 0x0,
.dsp4 = DSP_OFMT_YUV,
@@ -416,7 +416,7 @@
.com7 = OFMT_YUV,
},
{
- .code = MEDIA_BUS_FMT_YVYU8_2X8,
+ .code = V4L2_MBUS_FMT_YVYU8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.dsp3 = UV_ON,
.dsp4 = DSP_OFMT_YUV,
@@ -424,7 +424,7 @@
.com7 = OFMT_YUV,
},
{
- .code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .code = V4L2_MBUS_FMT_UYVY8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.dsp3 = 0x0,
.dsp4 = DSP_OFMT_YUV,
@@ -432,7 +432,7 @@
.com7 = OFMT_YUV,
},
{
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+ .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
.colorspace = V4L2_COLORSPACE_SRGB,
.dsp3 = 0x0,
.dsp4 = DSP_OFMT_YUV,
@@ -440,7 +440,7 @@
.com7 = FMT_RGB555 | OFMT_RGB,
},
{
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+ .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
.colorspace = V4L2_COLORSPACE_SRGB,
.dsp3 = 0x0,
.dsp4 = DSP_OFMT_YUV,
@@ -448,7 +448,7 @@
.com7 = FMT_RGB555 | OFMT_RGB,
},
{
- .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+ .code = V4L2_MBUS_FMT_RGB565_2X8_LE,
.colorspace = V4L2_COLORSPACE_SRGB,
.dsp3 = 0x0,
.dsp4 = DSP_OFMT_YUV,
@@ -456,7 +456,7 @@
.com7 = FMT_RGB565 | OFMT_RGB,
},
{
- .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+ .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
.colorspace = V4L2_COLORSPACE_SRGB,
.dsp3 = 0x0,
.dsp4 = DSP_OFMT_YUV,
@@ -468,7 +468,7 @@
* regardless of the COM7 value. We can thus only support 10-bit
* Bayer until someone figures it out.
*/
- .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
.colorspace = V4L2_COLORSPACE_SRGB,
.dsp3 = 0x0,
.dsp4 = DSP_OFMT_RAW10,
@@ -990,7 +990,7 @@
};
static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(ov772x_cfmts))
return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov9640.c b/drivers/media/i2c/soc_camera/ov9640.c
index 299308d..1a3a4a3 100644
--- a/drivers/media/i2c/soc_camera/ov9640.c
+++ b/drivers/media/i2c/soc_camera/ov9640.c
@@ -159,10 +159,10 @@
{ OV9640_MTXS, 0x65 },
};
-static u32 ov9640_codes[] = {
- MEDIA_BUS_FMT_UYVY8_2X8,
- MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
- MEDIA_BUS_FMT_RGB565_2X8_LE,
+static enum v4l2_mbus_pixelcode ov9640_codes[] = {
+ V4L2_MBUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
+ V4L2_MBUS_FMT_RGB565_2X8_LE,
};
/* read a register */
@@ -351,22 +351,22 @@
}
/* Prepare necessary register changes depending on color encoding */
-static void ov9640_alter_regs(u32 code,
+static void ov9640_alter_regs(enum v4l2_mbus_pixelcode code,
struct ov9640_reg_alt *alt)
{
switch (code) {
default:
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
alt->com12 = OV9640_COM12_YUV_AVG;
alt->com13 = OV9640_COM13_Y_DELAY_EN |
OV9640_COM13_YUV_DLY(0x01);
break;
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
+ case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
alt->com7 = OV9640_COM7_RGB;
alt->com13 = OV9640_COM13_RGB_AVG;
alt->com15 = OV9640_COM15_RGB_555;
break;
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
alt->com7 = OV9640_COM7_RGB;
alt->com13 = OV9640_COM13_RGB_AVG;
alt->com15 = OV9640_COM15_RGB_565;
@@ -376,7 +376,7 @@
/* Setup registers according to resolution and color encoding */
static int ov9640_write_regs(struct i2c_client *client, u32 width,
- u32 code, struct ov9640_reg_alt *alts)
+ enum v4l2_mbus_pixelcode code, struct ov9640_reg_alt *alts)
{
const struct ov9640_reg *ov9640_regs, *matrix_regs;
int ov9640_regs_len, matrix_regs_len;
@@ -419,7 +419,7 @@
}
/* select color matrix configuration for given color encoding */
- if (code == MEDIA_BUS_FMT_UYVY8_2X8) {
+ if (code == V4L2_MBUS_FMT_UYVY8_2X8) {
matrix_regs = ov9640_regs_yuv;
matrix_regs_len = ARRAY_SIZE(ov9640_regs_yuv);
} else {
@@ -487,7 +487,7 @@
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov9640_reg_alt alts = {0};
enum v4l2_colorspace cspace;
- u32 code = mf->code;
+ enum v4l2_mbus_pixelcode code = mf->code;
int ret;
ov9640_res_roundup(&mf->width, &mf->height);
@@ -500,13 +500,13 @@
return ret;
switch (code) {
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
cspace = V4L2_COLORSPACE_SRGB;
break;
default:
- code = MEDIA_BUS_FMT_UYVY8_2X8;
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ code = V4L2_MBUS_FMT_UYVY8_2X8;
+ case V4L2_MBUS_FMT_UYVY8_2X8:
cspace = V4L2_COLORSPACE_JPEG;
}
@@ -527,13 +527,13 @@
mf->field = V4L2_FIELD_NONE;
switch (mf->code) {
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
mf->colorspace = V4L2_COLORSPACE_SRGB;
break;
default:
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
+ case V4L2_MBUS_FMT_UYVY8_2X8:
mf->colorspace = V4L2_COLORSPACE_JPEG;
}
@@ -541,7 +541,7 @@
}
static int ov9640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(ov9640_codes))
return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/ov9740.c b/drivers/media/i2c/soc_camera/ov9740.c
index 8cf6b21..7e2656a 100644
--- a/drivers/media/i2c/soc_camera/ov9740.c
+++ b/drivers/media/i2c/soc_camera/ov9740.c
@@ -392,8 +392,8 @@
{ OV9740_ISP_CTRL19, 0x02 },
};
-static u32 ov9740_codes[] = {
- MEDIA_BUS_FMT_YUYV8_2X8,
+static enum v4l2_mbus_pixelcode ov9740_codes[] = {
+ V4L2_MBUS_FMT_YUYV8_2X8,
};
/* read a register */
@@ -674,13 +674,13 @@
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct ov9740_priv *priv = to_ov9740(sd);
enum v4l2_colorspace cspace;
- u32 code = mf->code;
+ enum v4l2_mbus_pixelcode code = mf->code;
int ret;
ov9740_res_roundup(&mf->width, &mf->height);
switch (code) {
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
cspace = V4L2_COLORSPACE_SRGB;
break;
default:
@@ -710,14 +710,14 @@
ov9740_res_roundup(&mf->width, &mf->height);
mf->field = V4L2_FIELD_NONE;
- mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
mf->colorspace = V4L2_COLORSPACE_SRGB;
return 0;
}
static int ov9740_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(ov9740_codes))
return -EINVAL;
diff --git a/drivers/media/i2c/soc_camera/rj54n1cb0c.c b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
index 2b26200..d523249 100644
--- a/drivers/media/i2c/soc_camera/rj54n1cb0c.c
+++ b/drivers/media/i2c/soc_camera/rj54n1cb0c.c
@@ -111,13 +111,13 @@
/* RJ54N1CB0C has only one fixed colorspace per pixelcode */
struct rj54n1_datafmt {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
};
/* Find a data format by a pixel code in an array */
static const struct rj54n1_datafmt *rj54n1_find_datafmt(
- u32 code, const struct rj54n1_datafmt *fmt,
+ enum v4l2_mbus_pixelcode code, const struct rj54n1_datafmt *fmt,
int n)
{
int i;
@@ -129,15 +129,15 @@
}
static const struct rj54n1_datafmt rj54n1_colour_fmts[] = {
- {MEDIA_BUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
- {MEDIA_BUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
- {MEDIA_BUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB},
- {MEDIA_BUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_YVYU8_2X8, V4L2_COLORSPACE_JPEG},
+ {V4L2_MBUS_FMT_RGB565_2X8_LE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_RGB565_2X8_BE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE, V4L2_COLORSPACE_SRGB},
+ {V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_COLORSPACE_SRGB},
};
struct rj54n1_clock_div {
@@ -486,7 +486,7 @@
}
static int rj54n1_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(rj54n1_colour_fmts))
return -EINVAL;
@@ -965,11 +965,11 @@
struct i2c_client *client = v4l2_get_subdevdata(sd);
struct rj54n1 *rj54n1 = to_rj54n1(client);
const struct rj54n1_datafmt *fmt;
- int align = mf->code == MEDIA_BUS_FMT_SBGGR10_1X10 ||
- mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE ||
- mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE ||
- mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE ||
- mf->code == MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE;
+ int align = mf->code == V4L2_MBUS_FMT_SBGGR10_1X10 ||
+ mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE ||
+ mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE ||
+ mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE ||
+ mf->code == V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE;
dev_dbg(&client->dev, "%s: code = %d, width = %u, height = %u\n",
__func__, mf->code, mf->width, mf->height);
@@ -1025,55 +1025,55 @@
/* RA_SEL_UL is only relevant for raw modes, ignored otherwise. */
switch (mf->code) {
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
ret = reg_write(client, RJ54N1_OUT_SEL, 0);
if (!ret)
ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
break;
- case MEDIA_BUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
ret = reg_write(client, RJ54N1_OUT_SEL, 0);
if (!ret)
ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
break;
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
if (!ret)
ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
break;
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
+ case V4L2_MBUS_FMT_RGB565_2X8_BE:
ret = reg_write(client, RJ54N1_OUT_SEL, 0x11);
if (!ret)
ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
break;
- case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
+ case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE:
ret = reg_write(client, RJ54N1_OUT_SEL, 4);
if (!ret)
ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
if (!ret)
ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
break;
- case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
+ case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE:
ret = reg_write(client, RJ54N1_OUT_SEL, 4);
if (!ret)
ret = reg_set(client, RJ54N1_BYTE_SWAP, 8, 8);
if (!ret)
ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
break;
- case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
+ case V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE:
ret = reg_write(client, RJ54N1_OUT_SEL, 4);
if (!ret)
ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
if (!ret)
ret = reg_write(client, RJ54N1_RA_SEL_UL, 0);
break;
- case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
+ case V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE:
ret = reg_write(client, RJ54N1_OUT_SEL, 4);
if (!ret)
ret = reg_set(client, RJ54N1_BYTE_SWAP, 0, 8);
if (!ret)
ret = reg_write(client, RJ54N1_RA_SEL_UL, 8);
break;
- case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case V4L2_MBUS_FMT_SBGGR10_1X10:
ret = reg_write(client, RJ54N1_OUT_SEL, 5);
break;
default:
@@ -1083,7 +1083,7 @@
/* Special case: a raw mode with 10 bits of data per clock tick */
if (!ret)
ret = reg_set(client, RJ54N1_OCLK_SEL_EN,
- (mf->code == MEDIA_BUS_FMT_SBGGR10_1X10) << 1, 2);
+ (mf->code == V4L2_MBUS_FMT_SBGGR10_1X10) << 1, 2);
if (ret < 0)
return ret;
diff --git a/drivers/media/i2c/soc_camera/tw9910.c b/drivers/media/i2c/soc_camera/tw9910.c
index b5237c6..3a84291 100644
--- a/drivers/media/i2c/soc_camera/tw9910.c
+++ b/drivers/media/i2c/soc_camera/tw9910.c
@@ -705,7 +705,7 @@
mf->width = priv->scale->width;
mf->height = priv->scale->height;
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
mf->colorspace = V4L2_COLORSPACE_JPEG;
mf->field = V4L2_FIELD_INTERLACED_BT;
@@ -724,7 +724,7 @@
/*
* check color format
*/
- if (mf->code != MEDIA_BUS_FMT_UYVY8_2X8)
+ if (mf->code != V4L2_MBUS_FMT_UYVY8_2X8)
return -EINVAL;
mf->colorspace = V4L2_COLORSPACE_JPEG;
@@ -751,7 +751,7 @@
return -EINVAL;
}
- mf->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ mf->code = V4L2_MBUS_FMT_UYVY8_2X8;
mf->colorspace = V4L2_COLORSPACE_JPEG;
/*
@@ -822,12 +822,12 @@
};
static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_UYVY8_2X8;
+ *code = V4L2_MBUS_FMT_UYVY8_2X8;
return 0;
}
diff --git a/drivers/media/i2c/sr030pc30.c b/drivers/media/i2c/sr030pc30.c
index 10c735c..118f8ee 100644
--- a/drivers/media/i2c/sr030pc30.c
+++ b/drivers/media/i2c/sr030pc30.c
@@ -165,7 +165,7 @@
};
struct sr030pc30_format {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
enum v4l2_colorspace colorspace;
u16 ispctl1_reg;
};
@@ -201,23 +201,23 @@
/* supported pixel formats */
static const struct sr030pc30_format sr030pc30_formats[] = {
{
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0x03,
}, {
- .code = MEDIA_BUS_FMT_YVYU8_2X8,
+ .code = V4L2_MBUS_FMT_YVYU8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0x02,
}, {
- .code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .code = V4L2_MBUS_FMT_VYUY8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0,
}, {
- .code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .code = V4L2_MBUS_FMT_UYVY8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0x01,
}, {
- .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+ .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
.colorspace = V4L2_COLORSPACE_JPEG,
.ispctl1_reg = 0x40,
},
@@ -472,7 +472,7 @@
}
static int sr030pc30_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (!code || index >= ARRAY_SIZE(sr030pc30_formats))
return -EINVAL;
diff --git a/drivers/media/i2c/tvp514x.c b/drivers/media/i2c/tvp514x.c
index c692fdf..5a28d99 100644
--- a/drivers/media/i2c/tvp514x.c
+++ b/drivers/media/i2c/tvp514x.c
@@ -756,12 +756,12 @@
*/
static int
tvp514x_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_YUYV10_2X10;
+ *code = V4L2_MBUS_FMT_YUYV10_2X10;
return 0;
}
@@ -784,7 +784,7 @@
/* Calculate height and width based on current standard */
current_std = decoder->current_std;
- f->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ f->code = V4L2_MBUS_FMT_YUYV8_2X8;
f->width = decoder->std_list[current_std].width;
f->height = decoder->std_list[current_std].height;
f->field = V4L2_FIELD_INTERLACED;
@@ -942,7 +942,7 @@
if (index != 0)
return -EINVAL;
- code->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ code->code = V4L2_MBUS_FMT_YUYV8_2X8;
return 0;
}
@@ -967,7 +967,7 @@
return 0;
}
- format->format.code = MEDIA_BUS_FMT_YUYV8_2X8;
+ format->format.code = V4L2_MBUS_FMT_YUYV8_2X8;
format->format.width = tvp514x_std_list[decoder->current_std].width;
format->format.height = tvp514x_std_list[decoder->current_std].height;
format->format.colorspace = V4L2_COLORSPACE_SMPTE170M;
@@ -991,7 +991,7 @@
struct tvp514x_decoder *decoder = to_decoder(sd);
if (fmt->format.field != V4L2_FIELD_INTERLACED ||
- fmt->format.code != MEDIA_BUS_FMT_YUYV8_2X8 ||
+ fmt->format.code != V4L2_MBUS_FMT_YUYV8_2X8 ||
fmt->format.colorspace != V4L2_COLORSPACE_SMPTE170M ||
fmt->format.width != tvp514x_std_list[decoder->current_std].width ||
fmt->format.height != tvp514x_std_list[decoder->current_std].height)
diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c
index f23110c..f32495f 100644
--- a/drivers/media/i2c/tvp5150.c
+++ b/drivers/media/i2c/tvp5150.c
@@ -818,12 +818,12 @@
}
static int tvp5150_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_UYVY8_2X8;
+ *code = V4L2_MBUS_FMT_UYVY8_2X8;
return 0;
}
@@ -840,7 +840,7 @@
f->width = decoder->rect.width;
f->height = decoder->rect.height;
- f->code = MEDIA_BUS_FMT_UYVY8_2X8;
+ f->code = V4L2_MBUS_FMT_UYVY8_2X8;
f->field = V4L2_FIELD_SEQ_TB;
f->colorspace = V4L2_COLORSPACE_SMPTE170M;
diff --git a/drivers/media/i2c/tvp7002.c b/drivers/media/i2c/tvp7002.c
index 8d8e714..28f978e 100644
--- a/drivers/media/i2c/tvp7002.c
+++ b/drivers/media/i2c/tvp7002.c
@@ -626,7 +626,7 @@
f->width = bt->width;
f->height = bt->height;
- f->code = MEDIA_BUS_FMT_YUYV10_1X20;
+ f->code = V4L2_MBUS_FMT_YUYV10_1X20;
f->field = device->current_timings->scanmode;
f->colorspace = device->current_timings->color_space;
@@ -756,12 +756,12 @@
*/
static int tvp7002_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
/* Check requested format index is within range */
if (index)
return -EINVAL;
- *code = MEDIA_BUS_FMT_YUYV10_1X20;
+ *code = V4L2_MBUS_FMT_YUYV10_1X20;
return 0;
}
@@ -859,7 +859,7 @@
if (code->index != 0)
return -EINVAL;
- code->code = MEDIA_BUS_FMT_YUYV10_1X20;
+ code->code = V4L2_MBUS_FMT_YUYV10_1X20;
return 0;
}
@@ -878,7 +878,7 @@
{
struct tvp7002 *tvp7002 = to_tvp7002(sd);
- fmt->format.code = MEDIA_BUS_FMT_YUYV10_1X20;
+ fmt->format.code = V4L2_MBUS_FMT_YUYV10_1X20;
fmt->format.width = tvp7002->current_timings->timings.bt.width;
fmt->format.height = tvp7002->current_timings->timings.bt.height;
fmt->format.field = tvp7002->current_timings->scanmode;
diff --git a/drivers/media/i2c/vs6624.c b/drivers/media/i2c/vs6624.c
index 0127932..e315d8b 100644
--- a/drivers/media/i2c/vs6624.c
+++ b/drivers/media/i2c/vs6624.c
@@ -45,19 +45,19 @@
};
static const struct vs6624_format {
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
enum v4l2_colorspace colorspace;
} vs6624_formats[] = {
{
- .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
},
{
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.colorspace = V4L2_COLORSPACE_JPEG,
},
{
- .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
.colorspace = V4L2_COLORSPACE_SRGB,
},
};
@@ -65,7 +65,7 @@
static struct v4l2_mbus_framefmt vs6624_default_fmt = {
.width = VGA_WIDTH,
.height = VGA_HEIGHT,
- .code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .code = V4L2_MBUS_FMT_UYVY8_2X8,
.field = V4L2_FIELD_NONE,
.colorspace = V4L2_COLORSPACE_JPEG,
};
@@ -558,7 +558,7 @@
}
static int vs6624_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
if (index >= ARRAY_SIZE(vs6624_formats))
return -EINVAL;
@@ -605,15 +605,15 @@
/* set image format */
switch (fmt->code) {
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
vs6624_write(sd, VS6624_YUV_SETUP, 0x1);
break;
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
vs6624_write(sd, VS6624_IMG_FMT0, 0x0);
vs6624_write(sd, VS6624_YUV_SETUP, 0x3);
break;
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
vs6624_write(sd, VS6624_IMG_FMT0, 0x4);
vs6624_write(sd, VS6624_RGB_SETUP, 0x0);
break;
diff --git a/drivers/media/media-entity.c b/drivers/media/media-entity.c
index 4d8e01c..37c334e 100644
--- a/drivers/media/media-entity.c
+++ b/drivers/media/media-entity.c
@@ -279,14 +279,8 @@
continue;
ret = entity->ops->link_validate(link);
- if (ret < 0 && ret != -ENOIOCTLCMD) {
- dev_dbg(entity->parent->dev,
- "link validation failed for \"%s\":%u -> \"%s\":%u, error %d\n",
- entity->name, link->source->index,
- link->sink->entity->name,
- link->sink->index, ret);
+ if (ret < 0 && ret != -ENOIOCTLCMD)
goto error;
- }
}
/* Either no links or validated links are fine. */
@@ -294,11 +288,6 @@
if (!bitmap_full(active, entity->num_pads)) {
ret = -EPIPE;
- dev_dbg(entity->parent->dev,
- "\"%s\":%u must be connected by an enabled link\n",
- entity->name,
- (unsigned)find_first_zero_bit(
- active, entity->num_pads));
goto error;
}
}
diff --git a/drivers/media/parport/Kconfig b/drivers/media/parport/Kconfig
new file mode 100644
index 0000000..ef209f5
--- /dev/null
+++ b/drivers/media/parport/Kconfig
@@ -0,0 +1,57 @@
+menuconfig MEDIA_PARPORT_SUPPORT
+ bool "ISA and parallel port devices"
+ depends on (ISA || PARPORT) && MEDIA_CAMERA_SUPPORT
+ help
+ Enables drivers for ISA and parallel port bus. If you
+ need media drivers using those legacy buses, say Y.
+
+if MEDIA_PARPORT_SUPPORT
+config VIDEO_BWQCAM
+ tristate "Quickcam BW Video For Linux"
+ depends on m
+ depends on PARPORT && VIDEO_V4L2
+ select VIDEOBUF2_VMALLOC
+ help
+ Say Y have if you the black and white version of the QuickCam
+ camera. See the next option for the color version.
+
+ To compile this driver as a module, choose M here: the
+ module will be called bw-qcam.
+
+config VIDEO_CQCAM
+ tristate "QuickCam Colour Video For Linux"
+ depends on m
+ depends on PARPORT && VIDEO_V4L2
+ help
+ This is the video4linux driver for the colour version of the
+ Connectix QuickCam. If you have one of these cameras, say Y here,
+ otherwise say N. This driver does not work with the original
+ monochrome QuickCam, QuickCam VC or QuickClip. It is also available
+ as a module (c-qcam).
+ Read <file:Documentation/video4linux/CQcam.txt> for more information.
+
+config VIDEO_PMS
+ tristate "Mediavision Pro Movie Studio Video For Linux"
+ depends on m
+ depends on ISA && VIDEO_V4L2
+ help
+ Say Y if you have the ISA Mediavision Pro Movie Studio
+ capture card.
+
+ To compile this driver as a module, choose M here: the
+ module will be called pms.
+
+config VIDEO_W9966
+ tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux"
+ depends on m
+ depends on PARPORT_1284 && PARPORT && VIDEO_V4L2
+ help
+ Video4linux driver for Winbond's w9966 based Webcams.
+ Currently tested with the LifeView FlyCam Supra.
+ If you have one of these cameras, say Y here
+ otherwise say N.
+ This driver is also available as a module (w9966).
+
+ Check out <file:Documentation/video4linux/w9966.txt> for more
+ information.
+endif
diff --git a/drivers/media/parport/Makefile b/drivers/media/parport/Makefile
new file mode 100644
index 0000000..f0b2dbe
--- /dev/null
+++ b/drivers/media/parport/Makefile
@@ -0,0 +1,4 @@
+obj-$(CPTCFG_VIDEO_CQCAM) += c-qcam.o
+obj-$(CPTCFG_VIDEO_BWQCAM) += bw-qcam.o
+obj-$(CPTCFG_VIDEO_W9966) += w9966.o
+obj-$(CPTCFG_VIDEO_PMS) += pms.o
diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c
new file mode 100644
index 0000000..67b9da1
--- /dev/null
+++ b/drivers/media/parport/bw-qcam.c
@@ -0,0 +1,1177 @@
+/*
+ * QuickCam Driver For Video4Linux.
+ *
+ * Video4Linux conversion work by Alan Cox.
+ * Parport compatibility by Phil Blundell.
+ * Busy loop avoidance by Mark Cooke.
+ *
+ * Module parameters:
+ *
+ * maxpoll=<1 - 5000>
+ *
+ * When polling the QuickCam for a response, busy-wait for a
+ * maximum of this many loops. The default of 250 gives little
+ * impact on interactive response.
+ *
+ * NOTE: If this parameter is set too high, the processor
+ * will busy wait until this loop times out, and then
+ * slowly poll for a further 5 seconds before failing
+ * the transaction. You have been warned.
+ *
+ * yieldlines=<1 - 250>
+ *
+ * When acquiring a frame from the camera, the data gathering
+ * loop will yield back to the scheduler after completing
+ * this many lines. The default of 4 provides a trade-off
+ * between increased frame acquisition time and impact on
+ * interactive response.
+ */
+
+/* qcam-lib.c -- Library for programming with the Connectix QuickCam.
+ * See the included documentation for usage instructions and details
+ * of the protocol involved. */
+
+
+/* Version 0.5, August 4, 1996 */
+/* Version 0.7, August 27, 1996 */
+/* Version 0.9, November 17, 1996 */
+
+
+/******************************************************************
+
+Copyright (C) 1996 by Scott Laird
+
+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 SCOTT LAIRD 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.
+
+******************************************************************/
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/parport.h>
+#include <linux/sched.h>
+#include <linux/videodev2.h>
+#include <linux/mutex.h>
+#include <asm/uaccess.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+
+/* One from column A... */
+#define QC_NOTSET 0
+#define QC_UNIDIR 1
+#define QC_BIDIR 2
+#define QC_SERIAL 3
+
+/* ... and one from column B */
+#define QC_ANY 0x00
+#define QC_FORCE_UNIDIR 0x10
+#define QC_FORCE_BIDIR 0x20
+#define QC_FORCE_SERIAL 0x30
+/* in the port_mode member */
+
+#define QC_MODE_MASK 0x07
+#define QC_FORCE_MASK 0x70
+
+#define MAX_HEIGHT 243
+#define MAX_WIDTH 336
+
+/* Bit fields for status flags */
+#define QC_PARAM_CHANGE 0x01 /* Camera status change has occurred */
+
+struct qcam {
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ struct v4l2_ctrl_handler hdl;
+ struct vb2_queue vb_vidq;
+ struct pardevice *pdev;
+ struct parport *pport;
+ struct mutex lock;
+ struct mutex queue_lock;
+ int width, height;
+ int bpp;
+ int mode;
+ int contrast, brightness, whitebal;
+ int port_mode;
+ int transfer_scale;
+ int top, left;
+ int status;
+ unsigned int saved_bits;
+ unsigned long in_use;
+};
+
+static unsigned int maxpoll = 250; /* Maximum busy-loop count for qcam I/O */
+static unsigned int yieldlines = 4; /* Yield after this many during capture */
+static int video_nr = -1;
+static unsigned int force_init; /* Whether to probe aggressively */
+
+module_param(maxpoll, int, 0);
+module_param(yieldlines, int, 0);
+module_param(video_nr, int, 0);
+
+/* Set force_init=1 to avoid detection by polling status register and
+ * immediately attempt to initialize qcam */
+module_param(force_init, int, 0);
+
+#define MAX_CAMS 4
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline int read_lpstatus(struct qcam *q)
+{
+ return parport_read_status(q->pport);
+}
+
+static inline int read_lpdata(struct qcam *q)
+{
+ return parport_read_data(q->pport);
+}
+
+static inline void write_lpdata(struct qcam *q, int d)
+{
+ parport_write_data(q->pport, d);
+}
+
+static void write_lpcontrol(struct qcam *q, int d)
+{
+ if (d & 0x20) {
+ /* Set bidirectional mode to reverse (data in) */
+ parport_data_reverse(q->pport);
+ } else {
+ /* Set bidirectional mode to forward (data out) */
+ parport_data_forward(q->pport);
+ }
+
+ /* Now issue the regular port command, but strip out the
+ * direction flag */
+ d &= ~0x20;
+ parport_write_control(q->pport, d);
+}
+
+
+/* qc_waithand busy-waits for a handshake signal from the QuickCam.
+ * Almost all communication with the camera requires handshaking. */
+
+static int qc_waithand(struct qcam *q, int val)
+{
+ int status;
+ int runs = 0;
+
+ if (val) {
+ while (!((status = read_lpstatus(q)) & 8)) {
+ /* 1000 is enough spins on the I/O for all normal
+ cases, at that point we start to poll slowly
+ until the camera wakes up. However, we are
+ busy blocked until the camera responds, so
+ setting it lower is much better for interactive
+ response. */
+
+ if (runs++ > maxpoll)
+ msleep_interruptible(5);
+ if (runs > (maxpoll + 1000)) /* 5 seconds */
+ return -1;
+ }
+ } else {
+ while (((status = read_lpstatus(q)) & 8)) {
+ /* 1000 is enough spins on the I/O for all normal
+ cases, at that point we start to poll slowly
+ until the camera wakes up. However, we are
+ busy blocked until the camera responds, so
+ setting it lower is much better for interactive
+ response. */
+
+ if (runs++ > maxpoll)
+ msleep_interruptible(5);
+ if (runs++ > (maxpoll + 1000)) /* 5 seconds */
+ return -1;
+ }
+ }
+
+ return status;
+}
+
+/* Waithand2 is used when the qcam is in bidirectional mode, and the
+ * handshaking signal is CamRdy2 (bit 0 of data reg) instead of CamRdy1
+ * (bit 3 of status register). It also returns the last value read,
+ * since this data is useful. */
+
+static unsigned int qc_waithand2(struct qcam *q, int val)
+{
+ unsigned int status;
+ int runs = 0;
+
+ do {
+ status = read_lpdata(q);
+ /* 1000 is enough spins on the I/O for all normal
+ cases, at that point we start to poll slowly
+ until the camera wakes up. However, we are
+ busy blocked until the camera responds, so
+ setting it lower is much better for interactive
+ response. */
+
+ if (runs++ > maxpoll)
+ msleep_interruptible(5);
+ if (runs++ > (maxpoll + 1000)) /* 5 seconds */
+ return 0;
+ } while ((status & 1) != val);
+
+ return status;
+}
+
+/* qc_command is probably a bit of a misnomer -- it's used to send
+ * bytes *to* the camera. Generally, these bytes are either commands
+ * or arguments to commands, so the name fits, but it still bugs me a
+ * bit. See the documentation for a list of commands. */
+
+static int qc_command(struct qcam *q, int command)
+{
+ int n1, n2;
+ int cmd;
+
+ write_lpdata(q, command);
+ write_lpcontrol(q, 6);
+
+ n1 = qc_waithand(q, 1);
+
+ write_lpcontrol(q, 0xe);
+ n2 = qc_waithand(q, 0);
+
+ cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+ return cmd;
+}
+
+static int qc_readparam(struct qcam *q)
+{
+ int n1, n2;
+ int cmd;
+
+ write_lpcontrol(q, 6);
+ n1 = qc_waithand(q, 1);
+
+ write_lpcontrol(q, 0xe);
+ n2 = qc_waithand(q, 0);
+
+ cmd = (n1 & 0xf0) | ((n2 & 0xf0) >> 4);
+ return cmd;
+}
+
+
+/* Try to detect a QuickCam. It appears to flash the upper 4 bits of
+ the status register at 5-10 Hz. This is only used in the autoprobe
+ code. Be aware that this isn't the way Connectix detects the
+ camera (they send a reset and try to handshake), but this should be
+ almost completely safe, while their method screws up my printer if
+ I plug it in before the camera. */
+
+static int qc_detect(struct qcam *q)
+{
+ int reg, lastreg;
+ int count = 0;
+ int i;
+
+ if (force_init)
+ return 1;
+
+ lastreg = reg = read_lpstatus(q) & 0xf0;
+
+ for (i = 0; i < 500; i++) {
+ reg = read_lpstatus(q) & 0xf0;
+ if (reg != lastreg)
+ count++;
+ lastreg = reg;
+ mdelay(2);
+ }
+
+
+#if 0
+ /* Force camera detection during testing. Sometimes the camera
+ won't be flashing these bits. Possibly unloading the module
+ in the middle of a grab? Or some timeout condition?
+ I've seen this parameter as low as 19 on my 450Mhz box - mpc */
+ printk(KERN_DEBUG "Debugging: QCam detection counter <30-200 counts as detected>: %d\n", count);
+ return 1;
+#endif
+
+ /* Be (even more) liberal in what you accept... */
+
+ if (count > 20 && count < 400) {
+ return 1; /* found */
+ } else {
+ printk(KERN_ERR "No Quickcam found on port %s\n",
+ q->pport->name);
+ printk(KERN_DEBUG "Quickcam detection counter: %u\n", count);
+ return 0; /* not found */
+ }
+}
+
+/* Decide which scan mode to use. There's no real requirement that
+ * the scanmode match the resolution in q->height and q-> width -- the
+ * camera takes the picture at the resolution specified in the
+ * "scanmode" and then returns the image at the resolution specified
+ * with the resolution commands. If the scan is bigger than the
+ * requested resolution, the upper-left hand corner of the scan is
+ * returned. If the scan is smaller, then the rest of the image
+ * returned contains garbage. */
+
+static int qc_setscanmode(struct qcam *q)
+{
+ int old_mode = q->mode;
+
+ switch (q->transfer_scale) {
+ case 1:
+ q->mode = 0;
+ break;
+ case 2:
+ q->mode = 4;
+ break;
+ case 4:
+ q->mode = 8;
+ break;
+ }
+
+ switch (q->bpp) {
+ case 4:
+ break;
+ case 6:
+ q->mode += 2;
+ break;
+ }
+
+ switch (q->port_mode & QC_MODE_MASK) {
+ case QC_BIDIR:
+ q->mode += 1;
+ break;
+ case QC_NOTSET:
+ case QC_UNIDIR:
+ break;
+ }
+
+ if (q->mode != old_mode)
+ q->status |= QC_PARAM_CHANGE;
+
+ return 0;
+}
+
+
+/* Reset the QuickCam. This uses the same sequence the Windows
+ * QuickPic program uses. Someone with a bi-directional port should
+ * check that bi-directional mode is detected right, and then
+ * implement bi-directional mode in qc_readbyte(). */
+
+static void qc_reset(struct qcam *q)
+{
+ switch (q->port_mode & QC_FORCE_MASK) {
+ case QC_FORCE_UNIDIR:
+ q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+ break;
+
+ case QC_FORCE_BIDIR:
+ q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+ break;
+
+ case QC_ANY:
+ write_lpcontrol(q, 0x20);
+ write_lpdata(q, 0x75);
+
+ if (read_lpdata(q) != 0x75)
+ q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_BIDIR;
+ else
+ q->port_mode = (q->port_mode & ~QC_MODE_MASK) | QC_UNIDIR;
+ break;
+ }
+
+ write_lpcontrol(q, 0xb);
+ udelay(250);
+ write_lpcontrol(q, 0xe);
+ qc_setscanmode(q); /* in case port_mode changed */
+}
+
+
+
+/* Reset the QuickCam and program for brightness, contrast,
+ * white-balance, and resolution. */
+
+static void qc_set(struct qcam *q)
+{
+ int val;
+ int val2;
+
+ /* Set the brightness. Yes, this is repetitive, but it works.
+ * Shorter versions seem to fail subtly. Feel free to try :-). */
+ /* I think the problem was in qc_command, not here -- bls */
+
+ qc_command(q, 0xb);
+ qc_command(q, q->brightness);
+
+ val = q->height / q->transfer_scale;
+ qc_command(q, 0x11);
+ qc_command(q, val);
+ if ((q->port_mode & QC_MODE_MASK) == QC_UNIDIR && q->bpp == 6) {
+ /* The normal "transfers per line" calculation doesn't seem to work
+ as expected here (and yet it works fine in qc_scan). No idea
+ why this case is the odd man out. Fortunately, Laird's original
+ working version gives me a good way to guess at working values.
+ -- bls */
+ val = q->width;
+ val2 = q->transfer_scale * 4;
+ } else {
+ val = q->width * q->bpp;
+ val2 = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
+ q->transfer_scale;
+ }
+ val = DIV_ROUND_UP(val, val2);
+ qc_command(q, 0x13);
+ qc_command(q, val);
+
+ /* Setting top and left -- bls */
+ qc_command(q, 0xd);
+ qc_command(q, q->top);
+ qc_command(q, 0xf);
+ qc_command(q, q->left / 2);
+
+ qc_command(q, 0x19);
+ qc_command(q, q->contrast);
+ qc_command(q, 0x1f);
+ qc_command(q, q->whitebal);
+
+ /* Clear flag that we must update the grabbing parameters on the camera
+ before we grab the next frame */
+ q->status &= (~QC_PARAM_CHANGE);
+}
+
+/* Qc_readbytes reads some bytes from the QC and puts them in
+ the supplied buffer. It returns the number of bytes read,
+ or -1 on error. */
+
+static inline int qc_readbytes(struct qcam *q, char buffer[])
+{
+ int ret = 1;
+ unsigned int hi, lo;
+ unsigned int hi2, lo2;
+ static int state;
+
+ if (buffer == NULL) {
+ state = 0;
+ return 0;
+ }
+
+ switch (q->port_mode & QC_MODE_MASK) {
+ case QC_BIDIR: /* Bi-directional Port */
+ write_lpcontrol(q, 0x26);
+ lo = (qc_waithand2(q, 1) >> 1);
+ hi = (read_lpstatus(q) >> 3) & 0x1f;
+ write_lpcontrol(q, 0x2e);
+ lo2 = (qc_waithand2(q, 0) >> 1);
+ hi2 = (read_lpstatus(q) >> 3) & 0x1f;
+ switch (q->bpp) {
+ case 4:
+ buffer[0] = lo & 0xf;
+ buffer[1] = ((lo & 0x70) >> 4) | ((hi & 1) << 3);
+ buffer[2] = (hi & 0x1e) >> 1;
+ buffer[3] = lo2 & 0xf;
+ buffer[4] = ((lo2 & 0x70) >> 4) | ((hi2 & 1) << 3);
+ buffer[5] = (hi2 & 0x1e) >> 1;
+ ret = 6;
+ break;
+ case 6:
+ buffer[0] = lo & 0x3f;
+ buffer[1] = ((lo & 0x40) >> 6) | (hi << 1);
+ buffer[2] = lo2 & 0x3f;
+ buffer[3] = ((lo2 & 0x40) >> 6) | (hi2 << 1);
+ ret = 4;
+ break;
+ }
+ break;
+
+ case QC_UNIDIR: /* Unidirectional Port */
+ write_lpcontrol(q, 6);
+ lo = (qc_waithand(q, 1) & 0xf0) >> 4;
+ write_lpcontrol(q, 0xe);
+ hi = (qc_waithand(q, 0) & 0xf0) >> 4;
+
+ switch (q->bpp) {
+ case 4:
+ buffer[0] = lo;
+ buffer[1] = hi;
+ ret = 2;
+ break;
+ case 6:
+ switch (state) {
+ case 0:
+ buffer[0] = (lo << 2) | ((hi & 0xc) >> 2);
+ q->saved_bits = (hi & 3) << 4;
+ state = 1;
+ ret = 1;
+ break;
+ case 1:
+ buffer[0] = lo | q->saved_bits;
+ q->saved_bits = hi << 2;
+ state = 2;
+ ret = 1;
+ break;
+ case 2:
+ buffer[0] = ((lo & 0xc) >> 2) | q->saved_bits;
+ buffer[1] = ((lo & 3) << 4) | hi;
+ state = 0;
+ ret = 2;
+ break;
+ }
+ break;
+ }
+ break;
+ }
+ return ret;
+}
+
+/* requests a scan from the camera. It sends the correct instructions
+ * to the camera and then reads back the correct number of bytes. In
+ * previous versions of this routine the return structure contained
+ * the raw output from the camera, and there was a 'qc_convertscan'
+ * function that converted that to a useful format. In version 0.3 I
+ * rolled qc_convertscan into qc_scan and now I only return the
+ * converted scan. The format is just an one-dimensional array of
+ * characters, one for each pixel, with 0=black up to n=white, where
+ * n=2^(bit depth)-1. Ask me for more details if you don't understand
+ * this. */
+
+static long qc_capture(struct qcam *q, u8 *buf, unsigned long len)
+{
+ int i, j, k, yield;
+ int bytes;
+ int linestotrans, transperline;
+ int divisor;
+ int pixels_per_line;
+ int pixels_read = 0;
+ int got = 0;
+ char buffer[6];
+ int shift = 8 - q->bpp;
+ char invert;
+
+ if (q->mode == -1)
+ return -ENXIO;
+
+ qc_command(q, 0x7);
+ qc_command(q, q->mode);
+
+ if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) {
+ write_lpcontrol(q, 0x2e); /* turn port around */
+ write_lpcontrol(q, 0x26);
+ qc_waithand(q, 1);
+ write_lpcontrol(q, 0x2e);
+ qc_waithand(q, 0);
+ }
+
+ /* strange -- should be 15:63 below, but 4bpp is odd */
+ invert = (q->bpp == 4) ? 16 : 63;
+
+ linestotrans = q->height / q->transfer_scale;
+ pixels_per_line = q->width / q->transfer_scale;
+ transperline = q->width * q->bpp;
+ divisor = (((q->port_mode & QC_MODE_MASK) == QC_BIDIR) ? 24 : 8) *
+ q->transfer_scale;
+ transperline = DIV_ROUND_UP(transperline, divisor);
+
+ for (i = 0, yield = yieldlines; i < linestotrans; i++) {
+ for (pixels_read = j = 0; j < transperline; j++) {
+ bytes = qc_readbytes(q, buffer);
+ for (k = 0; k < bytes && (pixels_read + k) < pixels_per_line; k++) {
+ int o;
+ if (buffer[k] == 0 && invert == 16) {
+ /* 4bpp is odd (again) -- inverter is 16, not 15, but output
+ must be 0-15 -- bls */
+ buffer[k] = 16;
+ }
+ o = i * pixels_per_line + pixels_read + k;
+ if (o < len) {
+ u8 ch = invert - buffer[k];
+ got++;
+ buf[o] = ch << shift;
+ }
+ }
+ pixels_read += bytes;
+ }
+ qc_readbytes(q, NULL); /* reset state machine */
+
+ /* Grabbing an entire frame from the quickcam is a lengthy
+ process. We don't (usually) want to busy-block the
+ processor for the entire frame. yieldlines is a module
+ parameter. If we yield every line, the minimum frame
+ time will be 240 / 200 = 1.2 seconds. The compile-time
+ default is to yield every 4 lines. */
+ if (i >= yield) {
+ msleep_interruptible(5);
+ yield = i + yieldlines;
+ }
+ }
+
+ if ((q->port_mode & QC_MODE_MASK) == QC_BIDIR) {
+ write_lpcontrol(q, 2);
+ write_lpcontrol(q, 6);
+ udelay(3);
+ write_lpcontrol(q, 0xe);
+ }
+ if (got < len)
+ return got;
+ return len;
+}
+
+/* ------------------------------------------------------------------
+ Videobuf operations
+ ------------------------------------------------------------------*/
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
+ unsigned int *nbuffers, unsigned int *nplanes,
+ unsigned int sizes[], void *alloc_ctxs[])
+{
+ struct qcam *dev = vb2_get_drv_priv(vq);
+
+ if (0 == *nbuffers)
+ *nbuffers = 3;
+ *nplanes = 1;
+ mutex_lock(&dev->lock);
+ if (fmt)
+ sizes[0] = fmt->fmt.pix.width * fmt->fmt.pix.height;
+ else
+ sizes[0] = (dev->width / dev->transfer_scale) *
+ (dev->height / dev->transfer_scale);
+ mutex_unlock(&dev->lock);
+ return 0;
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+ vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
+}
+
+static void buffer_finish(struct vb2_buffer *vb)
+{
+ struct qcam *qcam = vb2_get_drv_priv(vb->vb2_queue);
+ void *vbuf = vb2_plane_vaddr(vb, 0);
+ int size = vb->vb2_queue->plane_sizes[0];
+ int len;
+
+ if (!vb2_is_streaming(vb->vb2_queue))
+ return;
+
+ mutex_lock(&qcam->lock);
+ parport_claim_or_block(qcam->pdev);
+
+ qc_reset(qcam);
+
+ /* Update the camera parameters if we need to */
+ if (qcam->status & QC_PARAM_CHANGE)
+ qc_set(qcam);
+
+ len = qc_capture(qcam, vbuf, size);
+
+ parport_release(qcam->pdev);
+ mutex_unlock(&qcam->lock);
+ v4l2_get_timestamp(&vb->v4l2_buf.timestamp);
+ if (len != size)
+ vb->state = VB2_BUF_STATE_ERROR;
+ vb2_set_plane_payload(vb, 0, len);
+}
+
+static struct vb2_ops qcam_video_qops = {
+ .queue_setup = queue_setup,
+ .buf_queue = buffer_queue,
+ .buf_finish = buffer_finish,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+};
+
+/*
+ * Video4linux interfacing
+ */
+
+static int qcam_querycap(struct file *file, void *priv,
+ struct v4l2_capability *vcap)
+{
+ struct qcam *qcam = video_drvdata(file);
+
+ strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+ strlcpy(vcap->card, "Connectix B&W Quickcam", sizeof(vcap->card));
+ strlcpy(vcap->bus_info, qcam->pport->name, sizeof(vcap->bus_info));
+ vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
+ V4L2_CAP_STREAMING;
+ vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+ if (vin->index > 0)
+ return -EINVAL;
+ strlcpy(vin->name, "Camera", sizeof(vin->name));
+ vin->type = V4L2_INPUT_TYPE_CAMERA;
+ vin->audioset = 0;
+ vin->tuner = 0;
+ vin->std = 0;
+ vin->status = 0;
+ return 0;
+}
+
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+ *inp = 0;
+ return 0;
+}
+
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+ return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct qcam *qcam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ pix->width = qcam->width / qcam->transfer_scale;
+ pix->height = qcam->height / qcam->transfer_scale;
+ pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = pix->width;
+ pix->sizeimage = pix->width * pix->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ if (pix->height <= 60 || pix->width <= 80) {
+ pix->height = 60;
+ pix->width = 80;
+ } else if (pix->height <= 120 || pix->width <= 160) {
+ pix->height = 120;
+ pix->width = 160;
+ } else {
+ pix->height = 240;
+ pix->width = 320;
+ }
+ if (pix->pixelformat != V4L2_PIX_FMT_Y4 &&
+ pix->pixelformat != V4L2_PIX_FMT_Y6)
+ pix->pixelformat = V4L2_PIX_FMT_Y4;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = pix->width;
+ pix->sizeimage = pix->width * pix->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct qcam *qcam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+ int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+ if (ret)
+ return ret;
+ if (vb2_is_busy(&qcam->vb_vidq))
+ return -EBUSY;
+ qcam->width = 320;
+ qcam->height = 240;
+ if (pix->height == 60)
+ qcam->transfer_scale = 4;
+ else if (pix->height == 120)
+ qcam->transfer_scale = 2;
+ else
+ qcam->transfer_scale = 1;
+ if (pix->pixelformat == V4L2_PIX_FMT_Y6)
+ qcam->bpp = 6;
+ else
+ qcam->bpp = 4;
+
+ qc_setscanmode(qcam);
+ /* We must update the camera before we grab. We could
+ just have changed the grab size */
+ qcam->status |= QC_PARAM_CHANGE;
+ return 0;
+}
+
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+ static struct v4l2_fmtdesc formats[] = {
+ { 0, 0, 0,
+ "4-Bit Monochrome", V4L2_PIX_FMT_Y4,
+ { 0, 0, 0, 0 }
+ },
+ { 1, 0, 0,
+ "6-Bit Monochrome", V4L2_PIX_FMT_Y6,
+ { 0, 0, 0, 0 }
+ },
+ };
+ enum v4l2_buf_type type = fmt->type;
+
+ if (fmt->index > 1)
+ return -EINVAL;
+
+ *fmt = formats[fmt->index];
+ fmt->type = type;
+ return 0;
+}
+
+static int qcam_enum_framesizes(struct file *file, void *fh,
+ struct v4l2_frmsizeenum *fsize)
+{
+ static const struct v4l2_frmsize_discrete sizes[] = {
+ { 80, 60 },
+ { 160, 120 },
+ { 320, 240 },
+ };
+
+ if (fsize->index > 2)
+ return -EINVAL;
+ if (fsize->pixel_format != V4L2_PIX_FMT_Y4 &&
+ fsize->pixel_format != V4L2_PIX_FMT_Y6)
+ return -EINVAL;
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete = sizes[fsize->index];
+ return 0;
+}
+
+static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct qcam *qcam =
+ container_of(ctrl->handler, struct qcam, hdl);
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ qcam->brightness = ctrl->val;
+ break;
+ case V4L2_CID_CONTRAST:
+ qcam->contrast = ctrl->val;
+ break;
+ case V4L2_CID_GAMMA:
+ qcam->whitebal = ctrl->val;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret == 0)
+ qcam->status |= QC_PARAM_CHANGE;
+ return ret;
+}
+
+static const struct v4l2_file_operations qcam_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .poll = vb2_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .read = vb2_fop_read,
+ .mmap = vb2_fop_mmap,
+};
+
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+ .vidioc_querycap = qcam_querycap,
+ .vidioc_g_input = qcam_g_input,
+ .vidioc_s_input = qcam_s_input,
+ .vidioc_enum_input = qcam_enum_input,
+ .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
+ .vidioc_enum_framesizes = qcam_enum_framesizes,
+ .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ctrl_ops qcam_ctrl_ops = {
+ .s_ctrl = qcam_s_ctrl,
+};
+
+/* Initialize the QuickCam driver control structure. This is where
+ * defaults are set for people who don't have a config file.*/
+
+static struct qcam *qcam_init(struct parport *port)
+{
+ struct qcam *qcam;
+ struct v4l2_device *v4l2_dev;
+ struct vb2_queue *q;
+ int err;
+
+ qcam = kzalloc(sizeof(struct qcam), GFP_KERNEL);
+ if (qcam == NULL)
+ return NULL;
+
+ v4l2_dev = &qcam->v4l2_dev;
+ snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "bw-qcam%u", num_cams);
+
+ if (v4l2_device_register(port->dev, v4l2_dev) < 0) {
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+ kfree(qcam);
+ return NULL;
+ }
+
+ v4l2_ctrl_handler_init(&qcam->hdl, 3);
+ v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 255, 1, 180);
+ v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 255, 1, 192);
+ v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+ V4L2_CID_GAMMA, 0, 255, 1, 105);
+ if (qcam->hdl.error) {
+ v4l2_err(v4l2_dev, "couldn't register controls\n");
+ goto exit;
+ }
+
+ mutex_init(&qcam->lock);
+ mutex_init(&qcam->queue_lock);
+
+ /* initialize queue */
+ q = &qcam->vb_vidq;
+ q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+ q->drv_priv = qcam;
+ q->ops = &qcam_video_qops;
+ q->mem_ops = &vb2_vmalloc_memops;
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ err = vb2_queue_init(q);
+ if (err < 0) {
+ v4l2_err(v4l2_dev, "couldn't init vb2_queue for %s.\n", port->name);
+ goto exit;
+ }
+ qcam->vdev.queue = q;
+ qcam->vdev.queue->lock = &qcam->queue_lock;
+
+ qcam->pport = port;
+ qcam->pdev = parport_register_device(port, v4l2_dev->name, NULL, NULL,
+ NULL, 0, NULL);
+ if (qcam->pdev == NULL) {
+ v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+ goto exit;
+ }
+
+ strlcpy(qcam->vdev.name, "Connectix QuickCam", sizeof(qcam->vdev.name));
+ qcam->vdev.v4l2_dev = v4l2_dev;
+ qcam->vdev.ctrl_handler = &qcam->hdl;
+ qcam->vdev.fops = &qcam_fops;
+ qcam->vdev.lock = &qcam->lock;
+ qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+ qcam->vdev.release = video_device_release_empty;
+ video_set_drvdata(&qcam->vdev, qcam);
+
+ qcam->port_mode = (QC_ANY | QC_NOTSET);
+ qcam->width = 320;
+ qcam->height = 240;
+ qcam->bpp = 4;
+ qcam->transfer_scale = 2;
+ qcam->contrast = 192;
+ qcam->brightness = 180;
+ qcam->whitebal = 105;
+ qcam->top = 1;
+ qcam->left = 14;
+ qcam->mode = -1;
+ qcam->status = QC_PARAM_CHANGE;
+ return qcam;
+
+exit:
+ v4l2_ctrl_handler_free(&qcam->hdl);
+ kfree(qcam);
+ return NULL;
+}
+
+static int qc_calibrate(struct qcam *q)
+{
+ /*
+ * Bugfix by Hanno Mueller hmueller@kabel.de, Mai 21 96
+ * The white balance is an individual value for each
+ * quickcam.
+ */
+
+ int value;
+ int count = 0;
+
+ qc_command(q, 27); /* AutoAdjustOffset */
+ qc_command(q, 0); /* Dummy Parameter, ignored by the camera */
+
+ /* GetOffset (33) will read 255 until autocalibration */
+ /* is finished. After that, a value of 1-254 will be */
+ /* returned. */
+
+ do {
+ qc_command(q, 33);
+ value = qc_readparam(q);
+ mdelay(1);
+ schedule();
+ count++;
+ } while (value == 0xff && count < 2048);
+
+ q->whitebal = value;
+ return value;
+}
+
+static int init_bwqcam(struct parport *port)
+{
+ struct qcam *qcam;
+
+ if (num_cams == MAX_CAMS) {
+ printk(KERN_ERR "Too many Quickcams (max %d)\n", MAX_CAMS);
+ return -ENOSPC;
+ }
+
+ qcam = qcam_init(port);
+ if (qcam == NULL)
+ return -ENODEV;
+
+ parport_claim_or_block(qcam->pdev);
+
+ qc_reset(qcam);
+
+ if (qc_detect(qcam) == 0) {
+ parport_release(qcam->pdev);
+ parport_unregister_device(qcam->pdev);
+ kfree(qcam);
+ return -ENODEV;
+ }
+ qc_calibrate(qcam);
+ v4l2_ctrl_handler_setup(&qcam->hdl);
+
+ parport_release(qcam->pdev);
+
+ v4l2_info(&qcam->v4l2_dev, "Connectix Quickcam on %s\n", qcam->pport->name);
+
+ if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+ parport_unregister_device(qcam->pdev);
+ kfree(qcam);
+ return -ENODEV;
+ }
+
+ qcams[num_cams++] = qcam;
+
+ return 0;
+}
+
+static void close_bwqcam(struct qcam *qcam)
+{
+ video_unregister_device(&qcam->vdev);
+ v4l2_ctrl_handler_free(&qcam->hdl);
+ parport_unregister_device(qcam->pdev);
+ kfree(qcam);
+}
+
+/* The parport parameter controls which parports will be scanned.
+ * Scanning all parports causes some printers to print a garbage page.
+ * -- March 14, 1999 Billy Donahue <billy@escape.com> */
+#ifdef MODULE
+static char *parport[MAX_CAMS] = { NULL, };
+module_param_array(parport, charp, NULL, 0);
+#endif
+
+static int accept_bwqcam(struct parport *port)
+{
+#ifdef MODULE
+ int n;
+
+ if (parport[0] && strncmp(parport[0], "auto", 4) != 0) {
+ /* user gave parport parameters */
+ for (n = 0; n < MAX_CAMS && parport[n]; n++) {
+ char *ep;
+ unsigned long r;
+ r = simple_strtoul(parport[n], &ep, 0);
+ if (ep == parport[n]) {
+ printk(KERN_ERR
+ "bw-qcam: bad port specifier \"%s\"\n",
+ parport[n]);
+ continue;
+ }
+ if (r == port->number)
+ return 1;
+ }
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+static void bwqcam_attach(struct parport *port)
+{
+ if (accept_bwqcam(port))
+ init_bwqcam(port);
+}
+
+static void bwqcam_detach(struct parport *port)
+{
+ int i;
+ for (i = 0; i < num_cams; i++) {
+ struct qcam *qcam = qcams[i];
+ if (qcam && qcam->pdev->port == port) {
+ qcams[i] = NULL;
+ close_bwqcam(qcam);
+ }
+ }
+}
+
+static struct parport_driver bwqcam_driver = {
+ .name = "bw-qcam",
+ .attach = bwqcam_attach,
+ .detach = bwqcam_detach,
+};
+
+static void __exit exit_bw_qcams(void)
+{
+ parport_unregister_driver(&bwqcam_driver);
+}
+
+static int __init init_bw_qcams(void)
+{
+#ifdef MODULE
+ /* Do some sanity checks on the module parameters. */
+ if (maxpoll > 5000) {
+ printk(KERN_INFO "Connectix Quickcam max-poll was above 5000. Using 5000.\n");
+ maxpoll = 5000;
+ }
+
+ if (yieldlines < 1) {
+ printk(KERN_INFO "Connectix Quickcam yieldlines was less than 1. Using 1.\n");
+ yieldlines = 1;
+ }
+#endif
+ return parport_register_driver(&bwqcam_driver);
+}
+
+module_init(init_bw_qcams);
+module_exit(exit_bw_qcams);
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.3");
diff --git a/drivers/media/parport/c-qcam.c b/drivers/media/parport/c-qcam.c
new file mode 100644
index 0000000..b9010bd
--- /dev/null
+++ b/drivers/media/parport/c-qcam.c
@@ -0,0 +1,882 @@
+/*
+ * Video4Linux Colour QuickCam driver
+ * Copyright 1997-2000 Philip Blundell <philb@gnu.org>
+ *
+ * Module parameters:
+ *
+ * parport=auto -- probe all parports (default)
+ * parport=0 -- parport0 becomes qcam1
+ * parport=2,0,1 -- parports 2,0,1 are tried in that order
+ *
+ * probe=0 -- do no probing, assume camera is present
+ * probe=1 -- use IEEE-1284 autoprobe data only (default)
+ * probe=2 -- probe aggressively for cameras
+ *
+ * force_rgb=1 -- force data format to RGB (default is BGR)
+ *
+ * The parport parameter controls which parports will be scanned.
+ * Scanning all parports causes some printers to print a garbage page.
+ * -- March 14, 1999 Billy Donahue <billy@escape.com>
+ *
+ * Fixed data format to BGR, added force_rgb parameter. Added missing
+ * parport_unregister_driver() on module removal.
+ * -- May 28, 2000 Claudio Matsuoka <claudio@conectiva.com>
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/parport.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/jiffies.h>
+#include <linux/videodev2.h>
+#include <asm/uaccess.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+
+struct qcam {
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ struct v4l2_ctrl_handler hdl;
+ struct pardevice *pdev;
+ struct parport *pport;
+ int width, height;
+ int ccd_width, ccd_height;
+ int mode;
+ int contrast, brightness, whitebal;
+ int top, left;
+ unsigned int bidirectional;
+ struct mutex lock;
+};
+
+/* cameras maximum */
+#define MAX_CAMS 4
+
+/* The three possible QuickCam modes */
+#define QC_MILLIONS 0x18
+#define QC_BILLIONS 0x10
+#define QC_THOUSANDS 0x08 /* with VIDEC compression (not supported) */
+
+/* The three possible decimations */
+#define QC_DECIMATION_1 0
+#define QC_DECIMATION_2 2
+#define QC_DECIMATION_4 4
+
+#define BANNER "Colour QuickCam for Video4Linux v0.06"
+
+static int parport[MAX_CAMS] = { [1 ... MAX_CAMS-1] = -1 };
+static int probe = 2;
+static bool force_rgb;
+static int video_nr = -1;
+
+/* FIXME: parport=auto would never have worked, surely? --RR */
+MODULE_PARM_DESC(parport, "parport=<auto|n[,n]...> for port detection method\n"
+ "probe=<0|1|2> for camera detection method\n"
+ "force_rgb=<0|1> for RGB data format (default BGR)");
+module_param_array(parport, int, NULL, 0);
+module_param(probe, int, 0);
+module_param(force_rgb, bool, 0);
+module_param(video_nr, int, 0);
+
+static struct qcam *qcams[MAX_CAMS];
+static unsigned int num_cams;
+
+static inline void qcam_set_ack(struct qcam *qcam, unsigned int i)
+{
+ /* note: the QC specs refer to the PCAck pin by voltage, not
+ software level. PC ports have builtin inverters. */
+ parport_frob_control(qcam->pport, 8, i ? 8 : 0);
+}
+
+static inline unsigned int qcam_ready1(struct qcam *qcam)
+{
+ return (parport_read_status(qcam->pport) & 0x8) ? 1 : 0;
+}
+
+static inline unsigned int qcam_ready2(struct qcam *qcam)
+{
+ return (parport_read_data(qcam->pport) & 0x1) ? 1 : 0;
+}
+
+static unsigned int qcam_await_ready1(struct qcam *qcam, int value)
+{
+ struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+ unsigned long oldjiffies = jiffies;
+ unsigned int i;
+
+ for (oldjiffies = jiffies;
+ time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
+ if (qcam_ready1(qcam) == value)
+ return 0;
+
+ /* If the camera didn't respond within 1/25 second, poll slowly
+ for a while. */
+ for (i = 0; i < 50; i++) {
+ if (qcam_ready1(qcam) == value)
+ return 0;
+ msleep_interruptible(100);
+ }
+
+ /* Probably somebody pulled the plug out. Not much we can do. */
+ v4l2_err(v4l2_dev, "ready1 timeout (%d) %x %x\n", value,
+ parport_read_status(qcam->pport),
+ parport_read_control(qcam->pport));
+ return 1;
+}
+
+static unsigned int qcam_await_ready2(struct qcam *qcam, int value)
+{
+ struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+ unsigned long oldjiffies = jiffies;
+ unsigned int i;
+
+ for (oldjiffies = jiffies;
+ time_before(jiffies, oldjiffies + msecs_to_jiffies(40));)
+ if (qcam_ready2(qcam) == value)
+ return 0;
+
+ /* If the camera didn't respond within 1/25 second, poll slowly
+ for a while. */
+ for (i = 0; i < 50; i++) {
+ if (qcam_ready2(qcam) == value)
+ return 0;
+ msleep_interruptible(100);
+ }
+
+ /* Probably somebody pulled the plug out. Not much we can do. */
+ v4l2_err(v4l2_dev, "ready2 timeout (%d) %x %x %x\n", value,
+ parport_read_status(qcam->pport),
+ parport_read_control(qcam->pport),
+ parport_read_data(qcam->pport));
+ return 1;
+}
+
+static int qcam_read_data(struct qcam *qcam)
+{
+ unsigned int idata;
+
+ qcam_set_ack(qcam, 0);
+ if (qcam_await_ready1(qcam, 1))
+ return -1;
+ idata = parport_read_status(qcam->pport) & 0xf0;
+ qcam_set_ack(qcam, 1);
+ if (qcam_await_ready1(qcam, 0))
+ return -1;
+ idata |= parport_read_status(qcam->pport) >> 4;
+ return idata;
+}
+
+static int qcam_write_data(struct qcam *qcam, unsigned int data)
+{
+ struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+ unsigned int idata;
+
+ parport_write_data(qcam->pport, data);
+ idata = qcam_read_data(qcam);
+ if (data != idata) {
+ v4l2_warn(v4l2_dev, "sent %x but received %x\n", data,
+ idata);
+ return 1;
+ }
+ return 0;
+}
+
+static inline int qcam_set(struct qcam *qcam, unsigned int cmd, unsigned int data)
+{
+ if (qcam_write_data(qcam, cmd))
+ return -1;
+ if (qcam_write_data(qcam, data))
+ return -1;
+ return 0;
+}
+
+static inline int qcam_get(struct qcam *qcam, unsigned int cmd)
+{
+ if (qcam_write_data(qcam, cmd))
+ return -1;
+ return qcam_read_data(qcam);
+}
+
+static int qc_detect(struct qcam *qcam)
+{
+ unsigned int stat, ostat, i, count = 0;
+
+ /* The probe routine below is not very reliable. The IEEE-1284
+ probe takes precedence. */
+ /* XXX Currently parport provides no way to distinguish between
+ "the IEEE probe was not done" and "the probe was done, but
+ no device was found". Fix this one day. */
+ if (qcam->pport->probe_info[0].class == PARPORT_CLASS_MEDIA
+ && qcam->pport->probe_info[0].model
+ && !strcmp(qcam->pdev->port->probe_info[0].model,
+ "Color QuickCam 2.0")) {
+ printk(KERN_DEBUG "QuickCam: Found by IEEE1284 probe.\n");
+ return 1;
+ }
+
+ if (probe < 2)
+ return 0;
+
+ parport_write_control(qcam->pport, 0xc);
+
+ /* look for a heartbeat */
+ ostat = stat = parport_read_status(qcam->pport);
+ for (i = 0; i < 250; i++) {
+ mdelay(1);
+ stat = parport_read_status(qcam->pport);
+ if (ostat != stat) {
+ if (++count >= 3)
+ return 1;
+ ostat = stat;
+ }
+ }
+
+ /* Reset the camera and try again */
+ parport_write_control(qcam->pport, 0xc);
+ parport_write_control(qcam->pport, 0x8);
+ mdelay(1);
+ parport_write_control(qcam->pport, 0xc);
+ mdelay(1);
+ count = 0;
+
+ ostat = stat = parport_read_status(qcam->pport);
+ for (i = 0; i < 250; i++) {
+ mdelay(1);
+ stat = parport_read_status(qcam->pport);
+ if (ostat != stat) {
+ if (++count >= 3)
+ return 1;
+ ostat = stat;
+ }
+ }
+
+ /* no (or flatline) camera, give up */
+ return 0;
+}
+
+static void qc_reset(struct qcam *qcam)
+{
+ parport_write_control(qcam->pport, 0xc);
+ parport_write_control(qcam->pport, 0x8);
+ mdelay(1);
+ parport_write_control(qcam->pport, 0xc);
+ mdelay(1);
+}
+
+/* Reset the QuickCam and program for brightness, contrast,
+ * white-balance, and resolution. */
+
+static void qc_setup(struct qcam *qcam)
+{
+ qc_reset(qcam);
+
+ /* Set the brightness. */
+ qcam_set(qcam, 11, qcam->brightness);
+
+ /* Set the height and width. These refer to the actual
+ CCD area *before* applying the selected decimation. */
+ qcam_set(qcam, 17, qcam->ccd_height);
+ qcam_set(qcam, 19, qcam->ccd_width / 2);
+
+ /* Set top and left. */
+ qcam_set(qcam, 0xd, qcam->top);
+ qcam_set(qcam, 0xf, qcam->left);
+
+ /* Set contrast and white balance. */
+ qcam_set(qcam, 0x19, qcam->contrast);
+ qcam_set(qcam, 0x1f, qcam->whitebal);
+
+ /* Set the speed. */
+ qcam_set(qcam, 45, 2);
+}
+
+/* Read some bytes from the camera and put them in the buffer.
+ nbytes should be a multiple of 3, because bidirectional mode gives
+ us three bytes at a time. */
+
+static unsigned int qcam_read_bytes(struct qcam *qcam, unsigned char *buf, unsigned int nbytes)
+{
+ unsigned int bytes = 0;
+
+ qcam_set_ack(qcam, 0);
+ if (qcam->bidirectional) {
+ /* It's a bidirectional port */
+ while (bytes < nbytes) {
+ unsigned int lo1, hi1, lo2, hi2;
+ unsigned char r, g, b;
+
+ if (qcam_await_ready2(qcam, 1))
+ return bytes;
+ lo1 = parport_read_data(qcam->pport) >> 1;
+ hi1 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+ qcam_set_ack(qcam, 1);
+ if (qcam_await_ready2(qcam, 0))
+ return bytes;
+ lo2 = parport_read_data(qcam->pport) >> 1;
+ hi2 = ((parport_read_status(qcam->pport) >> 3) & 0x1f) ^ 0x10;
+ qcam_set_ack(qcam, 0);
+ r = lo1 | ((hi1 & 1) << 7);
+ g = ((hi1 & 0x1e) << 3) | ((hi2 & 0x1e) >> 1);
+ b = lo2 | ((hi2 & 1) << 7);
+ if (force_rgb) {
+ buf[bytes++] = r;
+ buf[bytes++] = g;
+ buf[bytes++] = b;
+ } else {
+ buf[bytes++] = b;
+ buf[bytes++] = g;
+ buf[bytes++] = r;
+ }
+ }
+ } else {
+ /* It's a unidirectional port */
+ int i = 0, n = bytes;
+ unsigned char rgb[3];
+
+ while (bytes < nbytes) {
+ unsigned int hi, lo;
+
+ if (qcam_await_ready1(qcam, 1))
+ return bytes;
+ hi = (parport_read_status(qcam->pport) & 0xf0);
+ qcam_set_ack(qcam, 1);
+ if (qcam_await_ready1(qcam, 0))
+ return bytes;
+ lo = (parport_read_status(qcam->pport) & 0xf0);
+ qcam_set_ack(qcam, 0);
+ /* flip some bits */
+ rgb[(i = bytes++ % 3)] = (hi | (lo >> 4)) ^ 0x88;
+ if (i >= 2) {
+get_fragment:
+ if (force_rgb) {
+ buf[n++] = rgb[0];
+ buf[n++] = rgb[1];
+ buf[n++] = rgb[2];
+ } else {
+ buf[n++] = rgb[2];
+ buf[n++] = rgb[1];
+ buf[n++] = rgb[0];
+ }
+ }
+ }
+ if (i) {
+ i = 0;
+ goto get_fragment;
+ }
+ }
+ return bytes;
+}
+
+#define BUFSZ 150
+
+static long qc_capture(struct qcam *qcam, char __user *buf, unsigned long len)
+{
+ struct v4l2_device *v4l2_dev = &qcam->v4l2_dev;
+ unsigned lines, pixelsperline;
+ unsigned int is_bi_dir = qcam->bidirectional;
+ size_t wantlen, outptr = 0;
+ char tmpbuf[BUFSZ];
+
+ if (!access_ok(VERIFY_WRITE, buf, len))
+ return -EFAULT;
+
+ /* Wait for camera to become ready */
+ for (;;) {
+ int i = qcam_get(qcam, 41);
+
+ if (i == -1) {
+ qc_setup(qcam);
+ return -EIO;
+ }
+ if ((i & 0x80) == 0)
+ break;
+ schedule();
+ }
+
+ if (qcam_set(qcam, 7, (qcam->mode | (is_bi_dir ? 1 : 0)) + 1))
+ return -EIO;
+
+ lines = qcam->height;
+ pixelsperline = qcam->width;
+
+ if (is_bi_dir) {
+ /* Turn the port around */
+ parport_data_reverse(qcam->pport);
+ mdelay(3);
+ qcam_set_ack(qcam, 0);
+ if (qcam_await_ready1(qcam, 1)) {
+ qc_setup(qcam);
+ return -EIO;
+ }
+ qcam_set_ack(qcam, 1);
+ if (qcam_await_ready1(qcam, 0)) {
+ qc_setup(qcam);
+ return -EIO;
+ }
+ }
+
+ wantlen = lines * pixelsperline * 24 / 8;
+
+ while (wantlen) {
+ size_t t, s;
+
+ s = (wantlen > BUFSZ) ? BUFSZ : wantlen;
+ t = qcam_read_bytes(qcam, tmpbuf, s);
+ if (outptr < len) {
+ size_t sz = len - outptr;
+
+ if (sz > t)
+ sz = t;
+ if (__copy_to_user(buf + outptr, tmpbuf, sz))
+ break;
+ outptr += sz;
+ }
+ wantlen -= t;
+ if (t < s)
+ break;
+ cond_resched();
+ }
+
+ len = outptr;
+
+ if (wantlen) {
+ v4l2_err(v4l2_dev, "short read.\n");
+ if (is_bi_dir)
+ parport_data_forward(qcam->pport);
+ qc_setup(qcam);
+ return len;
+ }
+
+ if (is_bi_dir) {
+ int l;
+
+ do {
+ l = qcam_read_bytes(qcam, tmpbuf, 3);
+ cond_resched();
+ } while (l && (tmpbuf[0] == 0x7e || tmpbuf[1] == 0x7e || tmpbuf[2] == 0x7e));
+ if (force_rgb) {
+ if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
+ v4l2_err(v4l2_dev, "bad EOF\n");
+ } else {
+ if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
+ v4l2_err(v4l2_dev, "bad EOF\n");
+ }
+ qcam_set_ack(qcam, 0);
+ if (qcam_await_ready1(qcam, 1)) {
+ v4l2_err(v4l2_dev, "no ack after EOF\n");
+ parport_data_forward(qcam->pport);
+ qc_setup(qcam);
+ return len;
+ }
+ parport_data_forward(qcam->pport);
+ mdelay(3);
+ qcam_set_ack(qcam, 1);
+ if (qcam_await_ready1(qcam, 0)) {
+ v4l2_err(v4l2_dev, "no ack to port turnaround\n");
+ qc_setup(qcam);
+ return len;
+ }
+ } else {
+ int l;
+
+ do {
+ l = qcam_read_bytes(qcam, tmpbuf, 1);
+ cond_resched();
+ } while (l && tmpbuf[0] == 0x7e);
+ l = qcam_read_bytes(qcam, tmpbuf + 1, 2);
+ if (force_rgb) {
+ if (tmpbuf[0] != 0xe || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xf)
+ v4l2_err(v4l2_dev, "bad EOF\n");
+ } else {
+ if (tmpbuf[0] != 0xf || tmpbuf[1] != 0x0 || tmpbuf[2] != 0xe)
+ v4l2_err(v4l2_dev, "bad EOF\n");
+ }
+ }
+
+ qcam_write_data(qcam, 0);
+ return len;
+}
+
+/*
+ * Video4linux interfacing
+ */
+
+static int qcam_querycap(struct file *file, void *priv,
+ struct v4l2_capability *vcap)
+{
+ struct qcam *qcam = video_drvdata(file);
+
+ strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
+ strlcpy(vcap->card, "Color Quickcam", sizeof(vcap->card));
+ strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+ vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+ vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+static int qcam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+ if (vin->index > 0)
+ return -EINVAL;
+ strlcpy(vin->name, "Camera", sizeof(vin->name));
+ vin->type = V4L2_INPUT_TYPE_CAMERA;
+ vin->audioset = 0;
+ vin->tuner = 0;
+ vin->std = 0;
+ vin->status = 0;
+ return 0;
+}
+
+static int qcam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+ *inp = 0;
+ return 0;
+}
+
+static int qcam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+ return (inp > 0) ? -EINVAL : 0;
+}
+
+static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct qcam *qcam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ pix->width = qcam->width;
+ pix->height = qcam->height;
+ pix->pixelformat = V4L2_PIX_FMT_RGB24;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = 3 * qcam->width;
+ pix->sizeimage = 3 * qcam->width * qcam->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ if (pix->height < 60 || pix->width < 80) {
+ pix->height = 60;
+ pix->width = 80;
+ } else if (pix->height < 120 || pix->width < 160) {
+ pix->height = 120;
+ pix->width = 160;
+ } else {
+ pix->height = 240;
+ pix->width = 320;
+ }
+ pix->pixelformat = V4L2_PIX_FMT_RGB24;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = 3 * pix->width;
+ pix->sizeimage = 3 * pix->width * pix->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int qcam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct qcam *qcam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+ int ret = qcam_try_fmt_vid_cap(file, fh, fmt);
+
+ if (ret)
+ return ret;
+ switch (pix->height) {
+ case 60:
+ qcam->mode = QC_DECIMATION_4;
+ break;
+ case 120:
+ qcam->mode = QC_DECIMATION_2;
+ break;
+ default:
+ qcam->mode = QC_DECIMATION_1;
+ break;
+ }
+
+ mutex_lock(&qcam->lock);
+ qcam->mode |= QC_MILLIONS;
+ qcam->height = pix->height;
+ qcam->width = pix->width;
+ parport_claim_or_block(qcam->pdev);
+ qc_setup(qcam);
+ parport_release(qcam->pdev);
+ mutex_unlock(&qcam->lock);
+ return 0;
+}
+
+static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+ static struct v4l2_fmtdesc formats[] = {
+ { 0, 0, 0,
+ "RGB 8:8:8", V4L2_PIX_FMT_RGB24,
+ { 0, 0, 0, 0 }
+ },
+ };
+ enum v4l2_buf_type type = fmt->type;
+
+ if (fmt->index > 0)
+ return -EINVAL;
+
+ *fmt = formats[fmt->index];
+ fmt->type = type;
+ return 0;
+}
+
+static ssize_t qcam_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct qcam *qcam = video_drvdata(file);
+ int len;
+
+ mutex_lock(&qcam->lock);
+ parport_claim_or_block(qcam->pdev);
+ /* Probably should have a semaphore against multiple users */
+ len = qc_capture(qcam, buf, count);
+ parport_release(qcam->pdev);
+ mutex_unlock(&qcam->lock);
+ return len;
+}
+
+static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct qcam *qcam =
+ container_of(ctrl->handler, struct qcam, hdl);
+ int ret = 0;
+
+ mutex_lock(&qcam->lock);
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ qcam->brightness = ctrl->val;
+ break;
+ case V4L2_CID_CONTRAST:
+ qcam->contrast = ctrl->val;
+ break;
+ case V4L2_CID_GAMMA:
+ qcam->whitebal = ctrl->val;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ if (ret == 0) {
+ parport_claim_or_block(qcam->pdev);
+ qc_setup(qcam);
+ parport_release(qcam->pdev);
+ }
+ mutex_unlock(&qcam->lock);
+ return ret;
+}
+
+static const struct v4l2_file_operations qcam_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = v4l2_fh_release,
+ .poll = v4l2_ctrl_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .read = qcam_read,
+};
+
+static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
+ .vidioc_querycap = qcam_querycap,
+ .vidioc_g_input = qcam_g_input,
+ .vidioc_s_input = qcam_s_input,
+ .vidioc_enum_input = qcam_enum_input,
+ .vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = qcam_try_fmt_vid_cap,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ctrl_ops qcam_ctrl_ops = {
+ .s_ctrl = qcam_s_ctrl,
+};
+
+/* Initialize the QuickCam driver control structure. */
+
+static struct qcam *qcam_init(struct parport *port)
+{
+ struct qcam *qcam;
+ struct v4l2_device *v4l2_dev;
+
+ qcam = kzalloc(sizeof(*qcam), GFP_KERNEL);
+ if (qcam == NULL)
+ return NULL;
+
+ v4l2_dev = &qcam->v4l2_dev;
+ strlcpy(v4l2_dev->name, "c-qcam", sizeof(v4l2_dev->name));
+
+ if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+ kfree(qcam);
+ return NULL;
+ }
+
+ v4l2_ctrl_handler_init(&qcam->hdl, 3);
+ v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 255, 1, 240);
+ v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 255, 1, 192);
+ v4l2_ctrl_new_std(&qcam->hdl, &qcam_ctrl_ops,
+ V4L2_CID_GAMMA, 0, 255, 1, 128);
+ if (qcam->hdl.error) {
+ v4l2_err(v4l2_dev, "couldn't register controls\n");
+ v4l2_ctrl_handler_free(&qcam->hdl);
+ kfree(qcam);
+ return NULL;
+ }
+
+ qcam->pport = port;
+ qcam->pdev = parport_register_device(port, "c-qcam", NULL, NULL,
+ NULL, 0, NULL);
+
+ qcam->bidirectional = (qcam->pport->modes & PARPORT_MODE_TRISTATE) ? 1 : 0;
+
+ if (qcam->pdev == NULL) {
+ v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
+ v4l2_ctrl_handler_free(&qcam->hdl);
+ kfree(qcam);
+ return NULL;
+ }
+
+ strlcpy(qcam->vdev.name, "Colour QuickCam", sizeof(qcam->vdev.name));
+ qcam->vdev.v4l2_dev = v4l2_dev;
+ qcam->vdev.fops = &qcam_fops;
+ qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
+ qcam->vdev.release = video_device_release_empty;
+ qcam->vdev.ctrl_handler = &qcam->hdl;
+ video_set_drvdata(&qcam->vdev, qcam);
+
+ mutex_init(&qcam->lock);
+ qcam->width = qcam->ccd_width = 320;
+ qcam->height = qcam->ccd_height = 240;
+ qcam->mode = QC_MILLIONS | QC_DECIMATION_1;
+ qcam->contrast = 192;
+ qcam->brightness = 240;
+ qcam->whitebal = 128;
+ qcam->top = 1;
+ qcam->left = 14;
+ return qcam;
+}
+
+static int init_cqcam(struct parport *port)
+{
+ struct qcam *qcam;
+ struct v4l2_device *v4l2_dev;
+
+ if (parport[0] != -1) {
+ /* The user gave specific instructions */
+ int i, found = 0;
+
+ for (i = 0; i < MAX_CAMS && parport[i] != -1; i++) {
+ if (parport[0] == port->number)
+ found = 1;
+ }
+ if (!found)
+ return -ENODEV;
+ }
+
+ if (num_cams == MAX_CAMS)
+ return -ENOSPC;
+
+ qcam = qcam_init(port);
+ if (qcam == NULL)
+ return -ENODEV;
+
+ v4l2_dev = &qcam->v4l2_dev;
+
+ parport_claim_or_block(qcam->pdev);
+
+ qc_reset(qcam);
+
+ if (probe && qc_detect(qcam) == 0) {
+ parport_release(qcam->pdev);
+ parport_unregister_device(qcam->pdev);
+ kfree(qcam);
+ return -ENODEV;
+ }
+
+ qc_setup(qcam);
+
+ parport_release(qcam->pdev);
+
+ if (video_register_device(&qcam->vdev, VFL_TYPE_GRABBER, video_nr) < 0) {
+ v4l2_err(v4l2_dev, "Unable to register Colour QuickCam on %s\n",
+ qcam->pport->name);
+ parport_unregister_device(qcam->pdev);
+ kfree(qcam);
+ return -ENODEV;
+ }
+
+ v4l2_info(v4l2_dev, "%s: Colour QuickCam found on %s\n",
+ video_device_node_name(&qcam->vdev), qcam->pport->name);
+
+ qcams[num_cams++] = qcam;
+
+ return 0;
+}
+
+static void close_cqcam(struct qcam *qcam)
+{
+ video_unregister_device(&qcam->vdev);
+ v4l2_ctrl_handler_free(&qcam->hdl);
+ parport_unregister_device(qcam->pdev);
+ kfree(qcam);
+}
+
+static void cq_attach(struct parport *port)
+{
+ init_cqcam(port);
+}
+
+static void cq_detach(struct parport *port)
+{
+ /* Write this some day. */
+}
+
+static struct parport_driver cqcam_driver = {
+ .name = "cqcam",
+ .attach = cq_attach,
+ .detach = cq_detach,
+};
+
+static int __init cqcam_init(void)
+{
+ printk(KERN_INFO BANNER "\n");
+
+ return parport_register_driver(&cqcam_driver);
+}
+
+static void __exit cqcam_cleanup(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_cams; i++)
+ close_cqcam(qcams[i]);
+
+ parport_unregister_driver(&cqcam_driver);
+}
+
+MODULE_AUTHOR("Philip Blundell <philb@gnu.org>");
+MODULE_DESCRIPTION(BANNER);
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.4");
+
+module_init(cqcam_init);
+module_exit(cqcam_cleanup);
diff --git a/drivers/media/parport/pms.c b/drivers/media/parport/pms.c
new file mode 100644
index 0000000..e6b4975
--- /dev/null
+++ b/drivers/media/parport/pms.c
@@ -0,0 +1,1156 @@
+/*
+ * Media Vision Pro Movie Studio
+ * or
+ * "all you need is an I2C bus some RAM and a prayer"
+ *
+ * This draws heavily on code
+ *
+ * (c) Wolfgang Koehler, wolf@first.gmd.de, Dec. 1994
+ * Kiefernring 15
+ * 14478 Potsdam, Germany
+ *
+ * Most of this code is directly derived from his userspace driver.
+ * His driver works so send any reports to alan@lxorguk.ukuu.org.uk
+ * unless the userspace driver also doesn't work for you...
+ *
+ * Changes:
+ * 25-11-2009 Hans Verkuil <hverkuil@xs4all.nl>
+ * - converted to version 2 of the V4L API.
+ * 08/07/2003 Daniele Bellucci <bellucda@tiscali.it>
+ * - pms_capture: report back -EFAULT
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+#include <linux/isa.h>
+#include <asm/io.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-device.h>
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.5");
+
+#define MOTOROLA 1
+#define PHILIPS2 2 /* SAA7191 */
+#define PHILIPS1 3
+#define MVVMEMORYWIDTH 0x40 /* 512 bytes */
+
+struct i2c_info {
+ u8 slave;
+ u8 sub;
+ u8 data;
+ u8 hits;
+};
+
+struct pms {
+ struct v4l2_device v4l2_dev;
+ struct video_device vdev;
+ struct v4l2_ctrl_handler hdl;
+ int height;
+ int width;
+ int depth;
+ int input;
+ struct mutex lock;
+ int i2c_count;
+ struct i2c_info i2cinfo[64];
+
+ int decoder;
+ int standard; /* 0 - auto 1 - ntsc 2 - pal 3 - secam */
+ v4l2_std_id std;
+ int io;
+ int data;
+ void __iomem *mem;
+};
+
+/*
+ * I/O ports and Shared Memory
+ */
+
+static int io_port = 0x250;
+module_param(io_port, int, 0);
+
+static int mem_base = 0xc8000;
+module_param(mem_base, int, 0);
+
+static int video_nr = -1;
+module_param(video_nr, int, 0);
+
+
+static inline void mvv_write(struct pms *dev, u8 index, u8 value)
+{
+ outw(index | (value << 8), dev->io);
+}
+
+static inline u8 mvv_read(struct pms *dev, u8 index)
+{
+ outb(index, dev->io);
+ return inb(dev->data);
+}
+
+static int pms_i2c_stat(struct pms *dev, u8 slave)
+{
+ int counter = 0;
+ int i;
+
+ outb(0x28, dev->io);
+
+ while ((inb(dev->data) & 0x01) == 0)
+ if (counter++ == 256)
+ break;
+
+ while ((inb(dev->data) & 0x01) != 0)
+ if (counter++ == 256)
+ break;
+
+ outb(slave, dev->io);
+
+ counter = 0;
+ while ((inb(dev->data) & 0x01) == 0)
+ if (counter++ == 256)
+ break;
+
+ while ((inb(dev->data) & 0x01) != 0)
+ if (counter++ == 256)
+ break;
+
+ for (i = 0; i < 12; i++) {
+ char st = inb(dev->data);
+
+ if ((st & 2) != 0)
+ return -1;
+ if ((st & 1) == 0)
+ break;
+ }
+ outb(0x29, dev->io);
+ return inb(dev->data);
+}
+
+static int pms_i2c_write(struct pms *dev, u16 slave, u16 sub, u16 data)
+{
+ int skip = 0;
+ int count;
+ int i;
+
+ for (i = 0; i < dev->i2c_count; i++) {
+ if ((dev->i2cinfo[i].slave == slave) &&
+ (dev->i2cinfo[i].sub == sub)) {
+ if (dev->i2cinfo[i].data == data)
+ skip = 1;
+ dev->i2cinfo[i].data = data;
+ i = dev->i2c_count + 1;
+ }
+ }
+
+ if (i == dev->i2c_count && dev->i2c_count < 64) {
+ dev->i2cinfo[dev->i2c_count].slave = slave;
+ dev->i2cinfo[dev->i2c_count].sub = sub;
+ dev->i2cinfo[dev->i2c_count].data = data;
+ dev->i2c_count++;
+ }
+
+ if (skip)
+ return 0;
+
+ mvv_write(dev, 0x29, sub);
+ mvv_write(dev, 0x2A, data);
+ mvv_write(dev, 0x28, slave);
+
+ outb(0x28, dev->io);
+
+ count = 0;
+ while ((inb(dev->data) & 1) == 0)
+ if (count > 255)
+ break;
+ while ((inb(dev->data) & 1) != 0)
+ if (count > 255)
+ break;
+
+ count = inb(dev->data);
+
+ if (count & 2)
+ return -1;
+ return count;
+}
+
+static int pms_i2c_read(struct pms *dev, int slave, int sub)
+{
+ int i;
+
+ for (i = 0; i < dev->i2c_count; i++) {
+ if (dev->i2cinfo[i].slave == slave && dev->i2cinfo[i].sub == sub)
+ return dev->i2cinfo[i].data;
+ }
+ return 0;
+}
+
+
+static void pms_i2c_andor(struct pms *dev, int slave, int sub, int and, int or)
+{
+ u8 tmp;
+
+ tmp = pms_i2c_read(dev, slave, sub);
+ tmp = (tmp & and) | or;
+ pms_i2c_write(dev, slave, sub, tmp);
+}
+
+/*
+ * Control functions
+ */
+
+
+static void pms_videosource(struct pms *dev, short source)
+{
+ switch (dev->decoder) {
+ case MOTOROLA:
+ break;
+ case PHILIPS2:
+ pms_i2c_andor(dev, 0x8a, 0x06, 0x7f, source ? 0x80 : 0);
+ break;
+ case PHILIPS1:
+ break;
+ }
+ mvv_write(dev, 0x2E, 0x31);
+ /* Was: mvv_write(dev, 0x2E, source ? 0x31 : 0x30);
+ But could not make this work correctly. Only Composite input
+ worked for me. */
+}
+
+static void pms_hue(struct pms *dev, short hue)
+{
+ switch (dev->decoder) {
+ case MOTOROLA:
+ pms_i2c_write(dev, 0x8a, 0x00, hue);
+ break;
+ case PHILIPS2:
+ pms_i2c_write(dev, 0x8a, 0x07, hue);
+ break;
+ case PHILIPS1:
+ pms_i2c_write(dev, 0x42, 0x07, hue);
+ break;
+ }
+}
+
+static void pms_saturation(struct pms *dev, short sat)
+{
+ switch (dev->decoder) {
+ case MOTOROLA:
+ pms_i2c_write(dev, 0x8a, 0x00, sat);
+ break;
+ case PHILIPS1:
+ pms_i2c_write(dev, 0x42, 0x12, sat);
+ break;
+ }
+}
+
+
+static void pms_contrast(struct pms *dev, short contrast)
+{
+ switch (dev->decoder) {
+ case MOTOROLA:
+ pms_i2c_write(dev, 0x8a, 0x00, contrast);
+ break;
+ case PHILIPS1:
+ pms_i2c_write(dev, 0x42, 0x13, contrast);
+ break;
+ }
+}
+
+static void pms_brightness(struct pms *dev, short brightness)
+{
+ switch (dev->decoder) {
+ case MOTOROLA:
+ pms_i2c_write(dev, 0x8a, 0x00, brightness);
+ pms_i2c_write(dev, 0x8a, 0x00, brightness);
+ pms_i2c_write(dev, 0x8a, 0x00, brightness);
+ break;
+ case PHILIPS1:
+ pms_i2c_write(dev, 0x42, 0x19, brightness);
+ break;
+ }
+}
+
+
+static void pms_format(struct pms *dev, short format)
+{
+ int target;
+
+ dev->standard = format;
+
+ if (dev->decoder == PHILIPS1)
+ target = 0x42;
+ else if (dev->decoder == PHILIPS2)
+ target = 0x8a;
+ else
+ return;
+
+ switch (format) {
+ case 0: /* Auto */
+ pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
+ pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x80);
+ break;
+ case 1: /* NTSC */
+ pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
+ pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x40);
+ break;
+ case 2: /* PAL */
+ pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x00);
+ pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
+ break;
+ case 3: /* SECAM */
+ pms_i2c_andor(dev, target, 0x0d, 0xfe, 0x01);
+ pms_i2c_andor(dev, target, 0x0f, 0x3f, 0x00);
+ break;
+ }
+}
+
+#ifdef FOR_FUTURE_EXPANSION
+
+/*
+ * These features of the PMS card are not currently exposes. They
+ * could become a private v4l ioctl for PMSCONFIG or somesuch if
+ * people need it. We also don't yet use the PMS interrupt.
+ */
+
+static void pms_hstart(struct pms *dev, short start)
+{
+ switch (dev->decoder) {
+ case PHILIPS1:
+ pms_i2c_write(dev, 0x8a, 0x05, start);
+ pms_i2c_write(dev, 0x8a, 0x18, start);
+ break;
+ case PHILIPS2:
+ pms_i2c_write(dev, 0x42, 0x05, start);
+ pms_i2c_write(dev, 0x42, 0x18, start);
+ break;
+ }
+}
+
+/*
+ * Bandpass filters
+ */
+
+static void pms_bandpass(struct pms *dev, short pass)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0x8a, 0x06, 0xcf, (pass & 0x03) << 4);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x06, 0xcf, (pass & 0x03) << 4);
+}
+
+static void pms_antisnow(struct pms *dev, short snow)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0x8a, 0x06, 0xf3, (snow & 0x03) << 2);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x06, 0xf3, (snow & 0x03) << 2);
+}
+
+static void pms_sharpness(struct pms *dev, short sharp)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0x8a, 0x06, 0xfc, sharp & 0x03);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x06, 0xfc, sharp & 0x03);
+}
+
+static void pms_chromaagc(struct pms *dev, short agc)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0x8a, 0x0c, 0x9f, (agc & 0x03) << 5);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x0c, 0x9f, (agc & 0x03) << 5);
+}
+
+static void pms_vertnoise(struct pms *dev, short noise)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0x8a, 0x10, 0xfc, noise & 3);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x10, 0xfc, noise & 3);
+}
+
+static void pms_forcecolour(struct pms *dev, short colour)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0x8a, 0x0c, 0x7f, (colour & 1) << 7);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x0c, 0x7, (colour & 1) << 7);
+}
+
+static void pms_antigamma(struct pms *dev, short gamma)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0xb8, 0x00, 0x7f, (gamma & 1) << 7);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x20, 0x7, (gamma & 1) << 7);
+}
+
+static void pms_prefilter(struct pms *dev, short filter)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0x8a, 0x06, 0xbf, (filter & 1) << 6);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x06, 0xbf, (filter & 1) << 6);
+}
+
+static void pms_hfilter(struct pms *dev, short filter)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0xb8, 0x04, 0x1f, (filter & 7) << 5);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x24, 0x1f, (filter & 7) << 5);
+}
+
+static void pms_vfilter(struct pms *dev, short filter)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0xb8, 0x08, 0x9f, (filter & 3) << 5);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x28, 0x9f, (filter & 3) << 5);
+}
+
+static void pms_killcolour(struct pms *dev, short colour)
+{
+ if (dev->decoder == PHILIPS2) {
+ pms_i2c_andor(dev, 0x8a, 0x08, 0x07, (colour & 0x1f) << 3);
+ pms_i2c_andor(dev, 0x8a, 0x09, 0x07, (colour & 0x1f) << 3);
+ } else if (dev->decoder == PHILIPS1) {
+ pms_i2c_andor(dev, 0x42, 0x08, 0x07, (colour & 0x1f) << 3);
+ pms_i2c_andor(dev, 0x42, 0x09, 0x07, (colour & 0x1f) << 3);
+ }
+}
+
+static void pms_chromagain(struct pms *dev, short chroma)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_write(dev, 0x8a, 0x11, chroma);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_write(dev, 0x42, 0x11, chroma);
+}
+
+
+static void pms_spacialcompl(struct pms *dev, short data)
+{
+ mvv_write(dev, 0x3b, data);
+}
+
+static void pms_spacialcomph(struct pms *dev, short data)
+{
+ mvv_write(dev, 0x3a, data);
+}
+
+static void pms_vstart(struct pms *dev, short start)
+{
+ mvv_write(dev, 0x16, start);
+ mvv_write(dev, 0x17, (start >> 8) & 0x01);
+}
+
+#endif
+
+static void pms_secamcross(struct pms *dev, short cross)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0x8a, 0x0f, 0xdf, (cross & 1) << 5);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x0f, 0xdf, (cross & 1) << 5);
+}
+
+
+static void pms_swsense(struct pms *dev, short sense)
+{
+ if (dev->decoder == PHILIPS2) {
+ pms_i2c_write(dev, 0x8a, 0x0a, sense);
+ pms_i2c_write(dev, 0x8a, 0x0b, sense);
+ } else if (dev->decoder == PHILIPS1) {
+ pms_i2c_write(dev, 0x42, 0x0a, sense);
+ pms_i2c_write(dev, 0x42, 0x0b, sense);
+ }
+}
+
+
+static void pms_framerate(struct pms *dev, short frr)
+{
+ int fps = (dev->std & V4L2_STD_525_60) ? 30 : 25;
+
+ if (frr == 0)
+ return;
+ fps = fps/frr;
+ mvv_write(dev, 0x14, 0x80 | fps);
+ mvv_write(dev, 0x15, 1);
+}
+
+static void pms_vert(struct pms *dev, u8 deciden, u8 decinum)
+{
+ mvv_write(dev, 0x1c, deciden); /* Denominator */
+ mvv_write(dev, 0x1d, decinum); /* Numerator */
+}
+
+/*
+ * Turn 16bit ratios into best small ratio the chipset can grok
+ */
+
+static void pms_vertdeci(struct pms *dev, unsigned short decinum, unsigned short deciden)
+{
+ /* Knock it down by / 5 once */
+ if (decinum % 5 == 0) {
+ deciden /= 5;
+ decinum /= 5;
+ }
+ /*
+ * 3's
+ */
+ while (decinum % 3 == 0 && deciden % 3 == 0) {
+ deciden /= 3;
+ decinum /= 3;
+ }
+ /*
+ * 2's
+ */
+ while (decinum % 2 == 0 && deciden % 2 == 0) {
+ decinum /= 2;
+ deciden /= 2;
+ }
+ /*
+ * Fudgyify
+ */
+ while (deciden > 32) {
+ deciden /= 2;
+ decinum = (decinum + 1) / 2;
+ }
+ if (deciden == 32)
+ deciden--;
+ pms_vert(dev, deciden, decinum);
+}
+
+static void pms_horzdeci(struct pms *dev, short decinum, short deciden)
+{
+ if (decinum <= 512) {
+ if (decinum % 5 == 0) {
+ decinum /= 5;
+ deciden /= 5;
+ }
+ } else {
+ decinum = 512;
+ deciden = 640; /* 768 would be ideal */
+ }
+
+ while (((decinum | deciden) & 1) == 0) {
+ decinum >>= 1;
+ deciden >>= 1;
+ }
+ while (deciden > 32) {
+ deciden >>= 1;
+ decinum = (decinum + 1) >> 1;
+ }
+ if (deciden == 32)
+ deciden--;
+
+ mvv_write(dev, 0x24, 0x80 | deciden);
+ mvv_write(dev, 0x25, decinum);
+}
+
+static void pms_resolution(struct pms *dev, short width, short height)
+{
+ int fg_height;
+
+ fg_height = height;
+ if (fg_height > 280)
+ fg_height = 280;
+
+ mvv_write(dev, 0x18, fg_height);
+ mvv_write(dev, 0x19, fg_height >> 8);
+
+ if (dev->std & V4L2_STD_525_60) {
+ mvv_write(dev, 0x1a, 0xfc);
+ mvv_write(dev, 0x1b, 0x00);
+ if (height > fg_height)
+ pms_vertdeci(dev, 240, 240);
+ else
+ pms_vertdeci(dev, fg_height, 240);
+ } else {
+ mvv_write(dev, 0x1a, 0x1a);
+ mvv_write(dev, 0x1b, 0x01);
+ if (fg_height > 256)
+ pms_vertdeci(dev, 270, 270);
+ else
+ pms_vertdeci(dev, fg_height, 270);
+ }
+ mvv_write(dev, 0x12, 0);
+ mvv_write(dev, 0x13, MVVMEMORYWIDTH);
+ mvv_write(dev, 0x42, 0x00);
+ mvv_write(dev, 0x43, 0x00);
+ mvv_write(dev, 0x44, MVVMEMORYWIDTH);
+
+ mvv_write(dev, 0x22, width + 8);
+ mvv_write(dev, 0x23, (width + 8) >> 8);
+
+ if (dev->std & V4L2_STD_525_60)
+ pms_horzdeci(dev, width, 640);
+ else
+ pms_horzdeci(dev, width + 8, 768);
+
+ mvv_write(dev, 0x30, mvv_read(dev, 0x30) & 0xfe);
+ mvv_write(dev, 0x08, mvv_read(dev, 0x08) | 0x01);
+ mvv_write(dev, 0x01, mvv_read(dev, 0x01) & 0xfd);
+ mvv_write(dev, 0x32, 0x00);
+ mvv_write(dev, 0x33, MVVMEMORYWIDTH);
+}
+
+
+/*
+ * Set Input
+ */
+
+static void pms_vcrinput(struct pms *dev, short input)
+{
+ if (dev->decoder == PHILIPS2)
+ pms_i2c_andor(dev, 0x8a, 0x0d, 0x7f, (input & 1) << 7);
+ else if (dev->decoder == PHILIPS1)
+ pms_i2c_andor(dev, 0x42, 0x0d, 0x7f, (input & 1) << 7);
+}
+
+
+static int pms_capture(struct pms *dev, char __user *buf, int rgb555, int count)
+{
+ int y;
+ int dw = 2 * dev->width;
+ char *tmp; /* using a temp buffer is faster than direct */
+ int cnt = 0;
+ int len = 0;
+ unsigned char r8 = 0x5; /* value for reg8 */
+
+ tmp = kmalloc(dw + 32, GFP_KERNEL);
+ if (!tmp)
+ return 0;
+
+ if (rgb555)
+ r8 |= 0x20; /* else use untranslated rgb = 565 */
+ mvv_write(dev, 0x08, r8); /* capture rgb555/565, init DRAM, PC enable */
+
+/* printf("%d %d %d %d %d %x %x\n",width,height,voff,nom,den,mvv_buf); */
+
+ for (y = 0; y < dev->height; y++) {
+ writeb(0, dev->mem); /* synchronisiert neue Zeile */
+
+ /*
+ * This is in truth a fifo, be very careful as if you
+ * forgot this odd things will occur 8)
+ */
+
+ memcpy_fromio(tmp, dev->mem, dw + 32); /* discard 16 word */
+ cnt -= dev->height;
+ while (cnt <= 0) {
+ /*
+ * Don't copy too far
+ */
+ int dt = dw;
+ if (dt + len > count)
+ dt = count - len;
+ cnt += dev->height;
+ if (copy_to_user(buf, tmp + 32, dt))
+ return len ? len : -EFAULT;
+ buf += dt;
+ len += dt;
+ }
+ }
+ kfree(tmp);
+ return len;
+}
+
+
+/*
+ * Video4linux interfacing
+ */
+
+static int pms_querycap(struct file *file, void *priv,
+ struct v4l2_capability *vcap)
+{
+ struct pms *dev = video_drvdata(file);
+
+ strlcpy(vcap->driver, dev->v4l2_dev.name, sizeof(vcap->driver));
+ strlcpy(vcap->card, "Mediavision PMS", sizeof(vcap->card));
+ snprintf(vcap->bus_info, sizeof(vcap->bus_info),
+ "ISA:%s", dev->v4l2_dev.name);
+ vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+ vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+static int pms_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+ static const char *inputs[4] = {
+ "Composite",
+ "S-Video",
+ "Composite (VCR)",
+ "S-Video (VCR)"
+ };
+
+ if (vin->index > 3)
+ return -EINVAL;
+ strlcpy(vin->name, inputs[vin->index], sizeof(vin->name));
+ vin->type = V4L2_INPUT_TYPE_CAMERA;
+ vin->audioset = 0;
+ vin->tuner = 0;
+ vin->std = V4L2_STD_ALL;
+ vin->status = 0;
+ return 0;
+}
+
+static int pms_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+ struct pms *dev = video_drvdata(file);
+
+ *inp = dev->input;
+ return 0;
+}
+
+static int pms_s_input(struct file *file, void *fh, unsigned int inp)
+{
+ struct pms *dev = video_drvdata(file);
+
+ if (inp > 3)
+ return -EINVAL;
+
+ dev->input = inp;
+ pms_videosource(dev, inp & 1);
+ pms_vcrinput(dev, inp >> 1);
+ return 0;
+}
+
+static int pms_g_std(struct file *file, void *fh, v4l2_std_id *std)
+{
+ struct pms *dev = video_drvdata(file);
+
+ *std = dev->std;
+ return 0;
+}
+
+static int pms_s_std(struct file *file, void *fh, v4l2_std_id std)
+{
+ struct pms *dev = video_drvdata(file);
+ int ret = 0;
+
+ dev->std = std;
+ if (dev->std & V4L2_STD_NTSC) {
+ pms_framerate(dev, 30);
+ pms_secamcross(dev, 0);
+ pms_format(dev, 1);
+ } else if (dev->std & V4L2_STD_PAL) {
+ pms_framerate(dev, 25);
+ pms_secamcross(dev, 0);
+ pms_format(dev, 2);
+ } else if (dev->std & V4L2_STD_SECAM) {
+ pms_framerate(dev, 25);
+ pms_secamcross(dev, 1);
+ pms_format(dev, 2);
+ } else {
+ ret = -EINVAL;
+ }
+ /*
+ switch (v->mode) {
+ case VIDEO_MODE_AUTO:
+ pms_framerate(dev, 25);
+ pms_secamcross(dev, 0);
+ pms_format(dev, 0);
+ break;
+ }*/
+ return ret;
+}
+
+static int pms_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct pms *dev = container_of(ctrl->handler, struct pms, hdl);
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ pms_brightness(dev, ctrl->val);
+ break;
+ case V4L2_CID_CONTRAST:
+ pms_contrast(dev, ctrl->val);
+ break;
+ case V4L2_CID_SATURATION:
+ pms_saturation(dev, ctrl->val);
+ break;
+ case V4L2_CID_HUE:
+ pms_hue(dev, ctrl->val);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int pms_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct pms *dev = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ pix->width = dev->width;
+ pix->height = dev->height;
+ pix->pixelformat = dev->width == 15 ?
+ V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB565;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = 2 * dev->width;
+ pix->sizeimage = 2 * dev->width * dev->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int pms_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ if (pix->height < 16 || pix->height > 480)
+ return -EINVAL;
+ if (pix->width < 16 || pix->width > 640)
+ return -EINVAL;
+ if (pix->pixelformat != V4L2_PIX_FMT_RGB555 &&
+ pix->pixelformat != V4L2_PIX_FMT_RGB565)
+ return -EINVAL;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = 2 * pix->width;
+ pix->sizeimage = 2 * pix->width * pix->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ return 0;
+}
+
+static int pms_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct pms *dev = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+ int ret = pms_try_fmt_vid_cap(file, fh, fmt);
+
+ if (ret)
+ return ret;
+ dev->width = pix->width;
+ dev->height = pix->height;
+ dev->depth = (pix->pixelformat == V4L2_PIX_FMT_RGB555) ? 15 : 16;
+ pms_resolution(dev, dev->width, dev->height);
+ /* Ok we figured out what to use from our wide choice */
+ return 0;
+}
+
+static int pms_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+ static struct v4l2_fmtdesc formats[] = {
+ { 0, 0, 0,
+ "RGB 5:5:5", V4L2_PIX_FMT_RGB555,
+ { 0, 0, 0, 0 }
+ },
+ { 1, 0, 0,
+ "RGB 5:6:5", V4L2_PIX_FMT_RGB565,
+ { 0, 0, 0, 0 }
+ },
+ };
+ enum v4l2_buf_type type = fmt->type;
+
+ if (fmt->index > 1)
+ return -EINVAL;
+
+ *fmt = formats[fmt->index];
+ fmt->type = type;
+ return 0;
+}
+
+static ssize_t pms_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct pms *dev = video_drvdata(file);
+ int len;
+
+ len = pms_capture(dev, buf, (dev->depth == 15), count);
+ return len;
+}
+
+static unsigned int pms_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct v4l2_fh *fh = file->private_data;
+ unsigned int res = POLLIN | POLLRDNORM;
+
+ if (v4l2_event_pending(fh))
+ res |= POLLPRI;
+ poll_wait(file, &fh->wait, wait);
+ return res;
+}
+
+static const struct v4l2_file_operations pms_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = v4l2_fh_release,
+ .poll = pms_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .read = pms_read,
+};
+
+static const struct v4l2_ioctl_ops pms_ioctl_ops = {
+ .vidioc_querycap = pms_querycap,
+ .vidioc_g_input = pms_g_input,
+ .vidioc_s_input = pms_s_input,
+ .vidioc_enum_input = pms_enum_input,
+ .vidioc_g_std = pms_g_std,
+ .vidioc_s_std = pms_s_std,
+ .vidioc_enum_fmt_vid_cap = pms_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = pms_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = pms_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = pms_try_fmt_vid_cap,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+/*
+ * Probe for and initialise the Mediavision PMS
+ */
+
+static int init_mediavision(struct pms *dev)
+{
+ int idec, decst;
+ int i;
+ static const unsigned char i2c_defs[] = {
+ 0x4c, 0x30, 0x00, 0xe8,
+ 0xb6, 0xe2, 0x00, 0x00,
+ 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x78, 0x98,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x34, 0x0a, 0xf4, 0xce,
+ 0xe4
+ };
+
+ dev->mem = ioremap(mem_base, 0x800);
+ if (!dev->mem)
+ return -ENOMEM;
+
+ if (!request_region(0x9a01, 1, "Mediavision PMS config")) {
+ printk(KERN_WARNING "mediavision: unable to detect: 0x9a01 in use.\n");
+ iounmap(dev->mem);
+ return -EBUSY;
+ }
+ if (!request_region(dev->io, 3, "Mediavision PMS")) {
+ printk(KERN_WARNING "mediavision: I/O port %d in use.\n", dev->io);
+ release_region(0x9a01, 1);
+ iounmap(dev->mem);
+ return -EBUSY;
+ }
+ outb(0xb8, 0x9a01); /* Unlock */
+ outb(dev->io >> 4, 0x9a01); /* Set IO port */
+
+
+ decst = pms_i2c_stat(dev, 0x43);
+
+ if (decst != -1)
+ idec = 2;
+ else if (pms_i2c_stat(dev, 0xb9) != -1)
+ idec = 3;
+ else if (pms_i2c_stat(dev, 0x8b) != -1)
+ idec = 1;
+ else
+ idec = 0;
+
+ printk(KERN_INFO "PMS type is %d\n", idec);
+ if (idec == 0) {
+ release_region(dev->io, 3);
+ release_region(0x9a01, 1);
+ iounmap(dev->mem);
+ return -ENODEV;
+ }
+
+ /*
+ * Ok we have a PMS of some sort
+ */
+
+ mvv_write(dev, 0x04, mem_base >> 12); /* Set the memory area */
+
+ /* Ok now load the defaults */
+
+ for (i = 0; i < 0x19; i++) {
+ if (i2c_defs[i] == 0xff)
+ pms_i2c_andor(dev, 0x8a, i, 0x07, 0x00);
+ else
+ pms_i2c_write(dev, 0x8a, i, i2c_defs[i]);
+ }
+
+ pms_i2c_write(dev, 0xb8, 0x00, 0x12);
+ pms_i2c_write(dev, 0xb8, 0x04, 0x00);
+ pms_i2c_write(dev, 0xb8, 0x07, 0x00);
+ pms_i2c_write(dev, 0xb8, 0x08, 0x00);
+ pms_i2c_write(dev, 0xb8, 0x09, 0xff);
+ pms_i2c_write(dev, 0xb8, 0x0a, 0x00);
+ pms_i2c_write(dev, 0xb8, 0x0b, 0x10);
+ pms_i2c_write(dev, 0xb8, 0x10, 0x03);
+
+ mvv_write(dev, 0x01, 0x00);
+ mvv_write(dev, 0x05, 0xa0);
+ mvv_write(dev, 0x08, 0x25);
+ mvv_write(dev, 0x09, 0x00);
+ mvv_write(dev, 0x0a, 0x20 | MVVMEMORYWIDTH);
+
+ mvv_write(dev, 0x10, 0x02);
+ mvv_write(dev, 0x1e, 0x0c);
+ mvv_write(dev, 0x1f, 0x03);
+ mvv_write(dev, 0x26, 0x06);
+
+ mvv_write(dev, 0x2b, 0x00);
+ mvv_write(dev, 0x2c, 0x20);
+ mvv_write(dev, 0x2d, 0x00);
+ mvv_write(dev, 0x2f, 0x70);
+ mvv_write(dev, 0x32, 0x00);
+ mvv_write(dev, 0x33, MVVMEMORYWIDTH);
+ mvv_write(dev, 0x34, 0x00);
+ mvv_write(dev, 0x35, 0x00);
+ mvv_write(dev, 0x3a, 0x80);
+ mvv_write(dev, 0x3b, 0x10);
+ mvv_write(dev, 0x20, 0x00);
+ mvv_write(dev, 0x21, 0x00);
+ mvv_write(dev, 0x30, 0x22);
+ return 0;
+}
+
+/*
+ * Initialization and module stuff
+ */
+
+#ifndef MODULE
+static int enable;
+module_param(enable, int, 0);
+#endif
+
+static const struct v4l2_ctrl_ops pms_ctrl_ops = {
+ .s_ctrl = pms_s_ctrl,
+};
+
+static int pms_probe(struct device *pdev, unsigned int card)
+{
+ struct pms *dev;
+ struct v4l2_device *v4l2_dev;
+ struct v4l2_ctrl_handler *hdl;
+ int res;
+
+#ifndef MODULE
+ if (!enable) {
+ pr_err("PMS: not enabled, use pms.enable=1 to probe\n");
+ return -ENODEV;
+ }
+#endif
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (dev == NULL)
+ return -ENOMEM;
+
+ dev->decoder = PHILIPS2;
+ dev->io = io_port;
+ dev->data = io_port + 1;
+ v4l2_dev = &dev->v4l2_dev;
+ hdl = &dev->hdl;
+
+ res = v4l2_device_register(pdev, v4l2_dev);
+ if (res < 0) {
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+ goto free_dev;
+ }
+ v4l2_info(v4l2_dev, "Mediavision Pro Movie Studio driver 0.05\n");
+
+ res = init_mediavision(dev);
+ if (res) {
+ v4l2_err(v4l2_dev, "Board not found.\n");
+ goto free_io;
+ }
+
+ v4l2_ctrl_handler_init(hdl, 4);
+ v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 255, 1, 139);
+ v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+ V4L2_CID_CONTRAST, 0, 255, 1, 70);
+ v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+ V4L2_CID_SATURATION, 0, 255, 1, 64);
+ v4l2_ctrl_new_std(hdl, &pms_ctrl_ops,
+ V4L2_CID_HUE, 0, 255, 1, 0);
+ if (hdl->error) {
+ res = hdl->error;
+ goto free_hdl;
+ }
+
+ mutex_init(&dev->lock);
+ strlcpy(dev->vdev.name, v4l2_dev->name, sizeof(dev->vdev.name));
+ dev->vdev.v4l2_dev = v4l2_dev;
+ dev->vdev.ctrl_handler = hdl;
+ dev->vdev.fops = &pms_fops;
+ dev->vdev.ioctl_ops = &pms_ioctl_ops;
+ dev->vdev.release = video_device_release_empty;
+ dev->vdev.lock = &dev->lock;
+ dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
+ video_set_drvdata(&dev->vdev, dev);
+ dev->std = V4L2_STD_NTSC_M;
+ dev->height = 240;
+ dev->width = 320;
+ dev->depth = 16;
+ pms_swsense(dev, 75);
+ pms_resolution(dev, 320, 240);
+ pms_videosource(dev, 0);
+ pms_vcrinput(dev, 0);
+ v4l2_ctrl_handler_setup(hdl);
+ res = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, video_nr);
+ if (res >= 0)
+ return 0;
+
+free_hdl:
+ v4l2_ctrl_handler_free(hdl);
+ v4l2_device_unregister(&dev->v4l2_dev);
+free_io:
+ release_region(dev->io, 3);
+ release_region(0x9a01, 1);
+ iounmap(dev->mem);
+free_dev:
+ kfree(dev);
+ return res;
+}
+
+static int pms_remove(struct device *pdev, unsigned int card)
+{
+ struct pms *dev = dev_get_drvdata(pdev);
+
+ video_unregister_device(&dev->vdev);
+ v4l2_ctrl_handler_free(&dev->hdl);
+ release_region(dev->io, 3);
+ release_region(0x9a01, 1);
+ iounmap(dev->mem);
+ return 0;
+}
+
+static struct isa_driver pms_driver = {
+ .probe = pms_probe,
+ .remove = pms_remove,
+ .driver = {
+ .name = "pms",
+ },
+};
+
+static int __init pms_init(void)
+{
+ return isa_register_driver(&pms_driver, 1);
+}
+
+static void __exit pms_exit(void)
+{
+ isa_unregister_driver(&pms_driver);
+}
+
+module_init(pms_init);
+module_exit(pms_exit);
diff --git a/drivers/media/parport/w9966.c b/drivers/media/parport/w9966.c
new file mode 100644
index 0000000..f7502f3
--- /dev/null
+++ b/drivers/media/parport/w9966.c
@@ -0,0 +1,980 @@
+/*
+ Winbond w9966cf Webcam parport driver.
+
+ Version 0.33
+
+ Copyright (C) 2001 Jakob Kemi <jakob.kemi@post.utfors.se>
+
+ 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.
+*/
+/*
+ Supported devices:
+ *Lifeview FlyCam Supra (using the Philips saa7111a chip)
+
+ Does any other model using the w9966 interface chip exist ?
+
+ Todo:
+
+ *Add a working EPP mode, since DMA ECP read isn't implemented
+ in the parport drivers. (That's why it's so sloow)
+
+ *Add support for other ccd-control chips than the saa7111
+ please send me feedback on what kind of chips you have.
+
+ *Add proper probing. I don't know what's wrong with the IEEE1284
+ parport drivers but (IEEE1284_MODE_NIBBLE|IEEE1284_DEVICE_ID)
+ and nibble read seems to be broken for some peripherals.
+
+ *Add probing for onboard SRAM, port directions etc. (if possible)
+
+ *Add support for the hardware compressed modes (maybe using v4l2)
+
+ *Fix better support for the capture window (no skewed images, v4l
+ interface to capt. window)
+
+ *Probably some bugs that I don't know of
+
+ Please support me by sending feedback!
+
+ Changes:
+
+ Alan Cox: Removed RGB mode for kernel merge, added THIS_MODULE
+ and owner support for newer module locks
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/slab.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <linux/parport.h>
+
+/*#define DEBUG*/ /* Undef me for production */
+
+#ifdef DEBUG
+#define DPRINTF(x, a...) printk(KERN_DEBUG "W9966: %s(): "x, __func__ , ##a)
+#else
+#define DPRINTF(x...)
+#endif
+
+/*
+ * Defines, simple typedefs etc.
+ */
+
+#define W9966_DRIVERNAME "W9966CF Webcam"
+#define W9966_MAXCAMS 4 /* Maximum number of cameras */
+#define W9966_RBUFFER 2048 /* Read buffer (must be an even number) */
+#define W9966_SRAMSIZE 131072 /* 128kb */
+#define W9966_SRAMID 0x02 /* check w9966cf.pdf */
+
+/* Empirically determined window limits */
+#define W9966_WND_MIN_X 16
+#define W9966_WND_MIN_Y 14
+#define W9966_WND_MAX_X 705
+#define W9966_WND_MAX_Y 253
+#define W9966_WND_MAX_W (W9966_WND_MAX_X - W9966_WND_MIN_X)
+#define W9966_WND_MAX_H (W9966_WND_MAX_Y - W9966_WND_MIN_Y)
+
+/* Keep track of our current state */
+#define W9966_STATE_PDEV 0x01
+#define W9966_STATE_CLAIMED 0x02
+#define W9966_STATE_VDEV 0x04
+
+#define W9966_I2C_W_ID 0x48
+#define W9966_I2C_R_ID 0x49
+#define W9966_I2C_R_DATA 0x08
+#define W9966_I2C_R_CLOCK 0x04
+#define W9966_I2C_W_DATA 0x02
+#define W9966_I2C_W_CLOCK 0x01
+
+struct w9966 {
+ struct v4l2_device v4l2_dev;
+ struct v4l2_ctrl_handler hdl;
+ unsigned char dev_state;
+ unsigned char i2c_state;
+ unsigned short ppmode;
+ struct parport *pport;
+ struct pardevice *pdev;
+ struct video_device vdev;
+ unsigned short width;
+ unsigned short height;
+ unsigned char brightness;
+ signed char contrast;
+ signed char color;
+ signed char hue;
+ struct mutex lock;
+};
+
+/*
+ * Module specific properties
+ */
+
+MODULE_AUTHOR("Jakob Kemi <jakob.kemi@post.utfors.se>");
+MODULE_DESCRIPTION("Winbond w9966cf WebCam driver (0.32)");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.33.1");
+
+#ifdef MODULE
+static char *pardev[] = {[0 ... W9966_MAXCAMS] = ""};
+#else
+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"
+ "\teach camera. 'aggressive' means brute-force search.\n"
+ "\tEg: >pardev=parport3,aggressive,parport2,parport1< would assign\n"
+ "\tcam 1 to parport3 and search every parport for cam 2 etc...");
+
+static int parmode;
+module_param(parmode, int, 0);
+MODULE_PARM_DESC(parmode, "parmode: transfer mode (0=auto, 1=ecp, 2=epp");
+
+static int video_nr = -1;
+module_param(video_nr, int, 0);
+
+static struct w9966 w9966_cams[W9966_MAXCAMS];
+
+/*
+ * Private function defines
+ */
+
+
+/* Set camera phase flags, so we know what to uninit when terminating */
+static inline void w9966_set_state(struct w9966 *cam, int mask, int val)
+{
+ cam->dev_state = (cam->dev_state & ~mask) ^ val;
+}
+
+/* Get camera phase flags */
+static inline int w9966_get_state(struct w9966 *cam, int mask, int val)
+{
+ return ((cam->dev_state & mask) == val);
+}
+
+/* Claim parport for ourself */
+static void w9966_pdev_claim(struct w9966 *cam)
+{
+ if (w9966_get_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED))
+ return;
+ parport_claim_or_block(cam->pdev);
+ w9966_set_state(cam, W9966_STATE_CLAIMED, W9966_STATE_CLAIMED);
+}
+
+/* Release parport for others to use */
+static void w9966_pdev_release(struct w9966 *cam)
+{
+ if (w9966_get_state(cam, W9966_STATE_CLAIMED, 0))
+ return;
+ parport_release(cam->pdev);
+ w9966_set_state(cam, W9966_STATE_CLAIMED, 0);
+}
+
+/* Read register from W9966 interface-chip
+ Expects a claimed pdev
+ -1 on error, else register data (byte) */
+static int w9966_read_reg(struct w9966 *cam, int reg)
+{
+ /* ECP, read, regtransfer, REG, REG, REG, REG, REG */
+ const unsigned char addr = 0x80 | (reg & 0x1f);
+ unsigned char val;
+
+ if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
+ return -1;
+ if (parport_write(cam->pport, &addr, 1) != 1)
+ return -1;
+ if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
+ return -1;
+ if (parport_read(cam->pport, &val, 1) != 1)
+ return -1;
+
+ return val;
+}
+
+/* Write register to W9966 interface-chip
+ Expects a claimed pdev
+ -1 on error */
+static int w9966_write_reg(struct w9966 *cam, int reg, int data)
+{
+ /* ECP, write, regtransfer, REG, REG, REG, REG, REG */
+ const unsigned char addr = 0xc0 | (reg & 0x1f);
+ const unsigned char val = data;
+
+ if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_ADDR) != 0)
+ return -1;
+ if (parport_write(cam->pport, &addr, 1) != 1)
+ return -1;
+ if (parport_negotiate(cam->pport, cam->ppmode | IEEE1284_DATA) != 0)
+ return -1;
+ if (parport_write(cam->pport, &val, 1) != 1)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Ugly and primitive i2c protocol functions
+ */
+
+/* Sets the data line on the i2c bus.
+ Expects a claimed pdev. */
+static void w9966_i2c_setsda(struct w9966 *cam, int state)
+{
+ if (state)
+ cam->i2c_state |= W9966_I2C_W_DATA;
+ else
+ cam->i2c_state &= ~W9966_I2C_W_DATA;
+
+ w9966_write_reg(cam, 0x18, cam->i2c_state);
+ udelay(5);
+}
+
+/* Get peripheral clock line
+ Expects a claimed pdev. */
+static int w9966_i2c_getscl(struct w9966 *cam)
+{
+ const unsigned char state = w9966_read_reg(cam, 0x18);
+ return ((state & W9966_I2C_R_CLOCK) > 0);
+}
+
+/* Sets the clock line on the i2c bus.
+ Expects a claimed pdev. -1 on error */
+static int w9966_i2c_setscl(struct w9966 *cam, int state)
+{
+ unsigned long timeout;
+
+ if (state)
+ cam->i2c_state |= W9966_I2C_W_CLOCK;
+ else
+ cam->i2c_state &= ~W9966_I2C_W_CLOCK;
+
+ w9966_write_reg(cam, 0x18, cam->i2c_state);
+ udelay(5);
+
+ /* we go to high, we also expect the peripheral to ack. */
+ if (state) {
+ timeout = jiffies + 100;
+ while (!w9966_i2c_getscl(cam)) {
+ if (time_after(jiffies, timeout))
+ return -1;
+ }
+ }
+ return 0;
+}
+
+#if 0
+/* Get peripheral data line
+ Expects a claimed pdev. */
+static int w9966_i2c_getsda(struct w9966 *cam)
+{
+ const unsigned char state = w9966_read_reg(cam, 0x18);
+ return ((state & W9966_I2C_R_DATA) > 0);
+}
+#endif
+
+/* Write a byte with ack to the i2c bus.
+ Expects a claimed pdev. -1 on error */
+static int w9966_i2c_wbyte(struct w9966 *cam, int data)
+{
+ int i;
+
+ for (i = 7; i >= 0; i--) {
+ w9966_i2c_setsda(cam, (data >> i) & 0x01);
+
+ if (w9966_i2c_setscl(cam, 1) == -1)
+ return -1;
+ w9966_i2c_setscl(cam, 0);
+ }
+
+ w9966_i2c_setsda(cam, 1);
+
+ if (w9966_i2c_setscl(cam, 1) == -1)
+ return -1;
+ w9966_i2c_setscl(cam, 0);
+
+ return 0;
+}
+
+/* Read a data byte with ack from the i2c-bus
+ Expects a claimed pdev. -1 on error */
+#if 0
+static int w9966_i2c_rbyte(struct w9966 *cam)
+{
+ unsigned char data = 0x00;
+ int i;
+
+ w9966_i2c_setsda(cam, 1);
+
+ for (i = 0; i < 8; i++) {
+ if (w9966_i2c_setscl(cam, 1) == -1)
+ return -1;
+ data = data << 1;
+ if (w9966_i2c_getsda(cam))
+ data |= 0x01;
+
+ w9966_i2c_setscl(cam, 0);
+ }
+ return data;
+}
+#endif
+
+/* Read a register from the i2c device.
+ Expects claimed pdev. -1 on error */
+#if 0
+static int w9966_read_reg_i2c(struct w9966 *cam, int reg)
+{
+ int data;
+
+ w9966_i2c_setsda(cam, 0);
+ w9966_i2c_setscl(cam, 0);
+
+ if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
+ w9966_i2c_wbyte(cam, reg) == -1)
+ return -1;
+
+ w9966_i2c_setsda(cam, 1);
+ if (w9966_i2c_setscl(cam, 1) == -1)
+ return -1;
+ w9966_i2c_setsda(cam, 0);
+ w9966_i2c_setscl(cam, 0);
+
+ if (w9966_i2c_wbyte(cam, W9966_I2C_R_ID) == -1)
+ return -1;
+ data = w9966_i2c_rbyte(cam);
+ if (data == -1)
+ return -1;
+
+ w9966_i2c_setsda(cam, 0);
+
+ if (w9966_i2c_setscl(cam, 1) == -1)
+ return -1;
+ w9966_i2c_setsda(cam, 1);
+
+ return data;
+}
+#endif
+
+/* Write a register to the i2c device.
+ Expects claimed pdev. -1 on error */
+static int w9966_write_reg_i2c(struct w9966 *cam, int reg, int data)
+{
+ w9966_i2c_setsda(cam, 0);
+ w9966_i2c_setscl(cam, 0);
+
+ if (w9966_i2c_wbyte(cam, W9966_I2C_W_ID) == -1 ||
+ w9966_i2c_wbyte(cam, reg) == -1 ||
+ w9966_i2c_wbyte(cam, data) == -1)
+ return -1;
+
+ w9966_i2c_setsda(cam, 0);
+ if (w9966_i2c_setscl(cam, 1) == -1)
+ return -1;
+
+ w9966_i2c_setsda(cam, 1);
+
+ return 0;
+}
+
+/* Find a good length for capture window (used both for W and H)
+ A bit ugly but pretty functional. The capture length
+ have to match the downscale */
+static int w9966_findlen(int near, int size, int maxlen)
+{
+ int bestlen = size;
+ int besterr = abs(near - bestlen);
+ int len;
+
+ for (len = size + 1; len < maxlen; len++) {
+ int err;
+ if (((64 * size) % len) != 0)
+ continue;
+
+ err = abs(near - len);
+
+ /* Only continue as long as we keep getting better values */
+ if (err > besterr)
+ break;
+
+ besterr = err;
+ bestlen = len;
+ }
+
+ return bestlen;
+}
+
+/* Modify capture window (if necessary)
+ and calculate downscaling
+ Return -1 on error */
+static int w9966_calcscale(int size, int min, int max, int *beg, int *end, unsigned char *factor)
+{
+ int maxlen = max - min;
+ int len = *end - *beg + 1;
+ int newlen = w9966_findlen(len, size, maxlen);
+ int err = newlen - len;
+
+ /* Check for bad format */
+ if (newlen > maxlen || newlen < size)
+ return -1;
+
+ /* Set factor (6 bit fixed) */
+ *factor = (64 * size) / newlen;
+ if (*factor == 64)
+ *factor = 0x00; /* downscale is disabled */
+ else
+ *factor |= 0x80; /* set downscale-enable bit */
+
+ /* Modify old beginning and end */
+ *beg -= err / 2;
+ *end += err - (err / 2);
+
+ /* Move window if outside borders */
+ if (*beg < min) {
+ *end += min - *beg;
+ *beg += min - *beg;
+ }
+ if (*end > max) {
+ *beg -= *end - max;
+ *end -= *end - max;
+ }
+
+ return 0;
+}
+
+/* Setup the cameras capture window etc.
+ Expects a claimed pdev
+ return -1 on error */
+static int w9966_setup(struct w9966 *cam, int x1, int y1, int x2, int y2, int w, int h)
+{
+ unsigned int i;
+ unsigned int enh_s, enh_e;
+ unsigned char scale_x, scale_y;
+ unsigned char regs[0x1c];
+ unsigned char saa7111_regs[] = {
+ 0x21, 0x00, 0xd8, 0x23, 0x00, 0x80, 0x80, 0x00,
+ 0x88, 0x10, 0x80, 0x40, 0x40, 0x00, 0x01, 0x00,
+ 0x48, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x71, 0xe7, 0x00, 0x00, 0xc0
+ };
+
+
+ if (w * h * 2 > W9966_SRAMSIZE) {
+ DPRINTF("capture window exceeds SRAM size!.\n");
+ w = 200; h = 160; /* Pick default values */
+ }
+
+ w &= ~0x1;
+ if (w < 2)
+ w = 2;
+ if (h < 1)
+ h = 1;
+ if (w > W9966_WND_MAX_W)
+ w = W9966_WND_MAX_W;
+ if (h > W9966_WND_MAX_H)
+ h = W9966_WND_MAX_H;
+
+ cam->width = w;
+ cam->height = h;
+
+ enh_s = 0;
+ enh_e = w * h * 2;
+
+ /* Modify capture window if necessary and calculate downscaling */
+ if (w9966_calcscale(w, W9966_WND_MIN_X, W9966_WND_MAX_X, &x1, &x2, &scale_x) != 0 ||
+ w9966_calcscale(h, W9966_WND_MIN_Y, W9966_WND_MAX_Y, &y1, &y2, &scale_y) != 0)
+ return -1;
+
+ DPRINTF("%dx%d, x: %d<->%d, y: %d<->%d, sx: %d/64, sy: %d/64.\n",
+ w, h, x1, x2, y1, y2, scale_x & ~0x80, scale_y & ~0x80);
+
+ /* Setup registers */
+ regs[0x00] = 0x00; /* Set normal operation */
+ regs[0x01] = 0x18; /* Capture mode */
+ regs[0x02] = scale_y; /* V-scaling */
+ regs[0x03] = scale_x; /* H-scaling */
+
+ /* Capture window */
+ regs[0x04] = (x1 & 0x0ff); /* X-start (8 low bits) */
+ regs[0x05] = (x1 & 0x300)>>8; /* X-start (2 high bits) */
+ regs[0x06] = (y1 & 0x0ff); /* Y-start (8 low bits) */
+ regs[0x07] = (y1 & 0x300)>>8; /* Y-start (2 high bits) */
+ regs[0x08] = (x2 & 0x0ff); /* X-end (8 low bits) */
+ regs[0x09] = (x2 & 0x300)>>8; /* X-end (2 high bits) */
+ regs[0x0a] = (y2 & 0x0ff); /* Y-end (8 low bits) */
+
+ regs[0x0c] = W9966_SRAMID; /* SRAM-banks (1x 128kb) */
+
+ /* Enhancement layer */
+ regs[0x0d] = (enh_s & 0x000ff); /* Enh. start (0-7) */
+ regs[0x0e] = (enh_s & 0x0ff00) >> 8; /* Enh. start (8-15) */
+ regs[0x0f] = (enh_s & 0x70000) >> 16; /* Enh. start (16-17/18??) */
+ regs[0x10] = (enh_e & 0x000ff); /* Enh. end (0-7) */
+ regs[0x11] = (enh_e & 0x0ff00) >> 8; /* Enh. end (8-15) */
+ regs[0x12] = (enh_e & 0x70000) >> 16; /* Enh. end (16-17/18??) */
+
+ /* Misc */
+ regs[0x13] = 0x40; /* VEE control (raw 4:2:2) */
+ regs[0x17] = 0x00; /* ??? */
+ regs[0x18] = cam->i2c_state = 0x00; /* Serial bus */
+ regs[0x19] = 0xff; /* I/O port direction control */
+ regs[0x1a] = 0xff; /* I/O port data register */
+ regs[0x1b] = 0x10; /* ??? */
+
+ /* SAA7111 chip settings */
+ saa7111_regs[0x0a] = cam->brightness;
+ saa7111_regs[0x0b] = cam->contrast;
+ saa7111_regs[0x0c] = cam->color;
+ saa7111_regs[0x0d] = cam->hue;
+
+ /* Reset (ECP-fifo & serial-bus) */
+ if (w9966_write_reg(cam, 0x00, 0x03) == -1)
+ return -1;
+
+ /* Write regs to w9966cf chip */
+ for (i = 0; i < 0x1c; i++)
+ if (w9966_write_reg(cam, i, regs[i]) == -1)
+ return -1;
+
+ /* Write regs to saa7111 chip */
+ for (i = 0; i < 0x20; i++)
+ if (w9966_write_reg_i2c(cam, i, saa7111_regs[i]) == -1)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * Video4linux interfacing
+ */
+
+static int cam_querycap(struct file *file, void *priv,
+ struct v4l2_capability *vcap)
+{
+ struct w9966 *cam = video_drvdata(file);
+
+ strlcpy(vcap->driver, cam->v4l2_dev.name, sizeof(vcap->driver));
+ strlcpy(vcap->card, W9966_DRIVERNAME, sizeof(vcap->card));
+ strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
+ vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
+ vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+static int cam_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
+{
+ if (vin->index > 0)
+ return -EINVAL;
+ strlcpy(vin->name, "Camera", sizeof(vin->name));
+ vin->type = V4L2_INPUT_TYPE_CAMERA;
+ vin->audioset = 0;
+ vin->tuner = 0;
+ vin->std = 0;
+ vin->status = 0;
+ return 0;
+}
+
+static int cam_g_input(struct file *file, void *fh, unsigned int *inp)
+{
+ *inp = 0;
+ return 0;
+}
+
+static int cam_s_input(struct file *file, void *fh, unsigned int inp)
+{
+ return (inp > 0) ? -EINVAL : 0;
+}
+
+static int cam_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct w9966 *cam =
+ container_of(ctrl->handler, struct w9966, hdl);
+ int ret = 0;
+
+ mutex_lock(&cam->lock);
+ switch (ctrl->id) {
+ case V4L2_CID_BRIGHTNESS:
+ cam->brightness = ctrl->val;
+ break;
+ case V4L2_CID_CONTRAST:
+ cam->contrast = ctrl->val;
+ break;
+ case V4L2_CID_SATURATION:
+ cam->color = ctrl->val;
+ break;
+ case V4L2_CID_HUE:
+ cam->hue = ctrl->val;
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+
+ if (ret == 0) {
+ w9966_pdev_claim(cam);
+
+ if (w9966_write_reg_i2c(cam, 0x0a, cam->brightness) == -1 ||
+ w9966_write_reg_i2c(cam, 0x0b, cam->contrast) == -1 ||
+ w9966_write_reg_i2c(cam, 0x0c, cam->color) == -1 ||
+ w9966_write_reg_i2c(cam, 0x0d, cam->hue) == -1) {
+ ret = -EIO;
+ }
+
+ w9966_pdev_release(cam);
+ }
+ mutex_unlock(&cam->lock);
+ return ret;
+}
+
+static int cam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct w9966 *cam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ pix->width = cam->width;
+ pix->height = cam->height;
+ pix->pixelformat = V4L2_PIX_FMT_YUYV;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = 2 * cam->width;
+ pix->sizeimage = 2 * cam->width * cam->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ return 0;
+}
+
+static int cam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+
+ if (pix->width < 2)
+ pix->width = 2;
+ if (pix->height < 1)
+ pix->height = 1;
+ if (pix->width > W9966_WND_MAX_W)
+ pix->width = W9966_WND_MAX_W;
+ if (pix->height > W9966_WND_MAX_H)
+ pix->height = W9966_WND_MAX_H;
+ pix->pixelformat = V4L2_PIX_FMT_YUYV;
+ pix->field = V4L2_FIELD_NONE;
+ pix->bytesperline = 2 * pix->width;
+ pix->sizeimage = 2 * pix->width * pix->height;
+ /* Just a guess */
+ pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
+ return 0;
+}
+
+static int cam_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
+{
+ struct w9966 *cam = video_drvdata(file);
+ struct v4l2_pix_format *pix = &fmt->fmt.pix;
+ int ret = cam_try_fmt_vid_cap(file, fh, fmt);
+
+ if (ret)
+ return ret;
+
+ mutex_lock(&cam->lock);
+ /* Update camera regs */
+ w9966_pdev_claim(cam);
+ ret = w9966_setup(cam, 0, 0, 1023, 1023, pix->width, pix->height);
+ w9966_pdev_release(cam);
+ mutex_unlock(&cam->lock);
+ return ret;
+}
+
+static int cam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
+{
+ static struct v4l2_fmtdesc formats[] = {
+ { 0, 0, 0,
+ "YUV 4:2:2", V4L2_PIX_FMT_YUYV,
+ { 0, 0, 0, 0 }
+ },
+ };
+ enum v4l2_buf_type type = fmt->type;
+
+ if (fmt->index > 0)
+ return -EINVAL;
+
+ *fmt = formats[fmt->index];
+ fmt->type = type;
+ return 0;
+}
+
+/* Capture data */
+static ssize_t w9966_v4l_read(struct file *file, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ struct w9966 *cam = video_drvdata(file);
+ unsigned char addr = 0xa0; /* ECP, read, CCD-transfer, 00000 */
+ unsigned char __user *dest = (unsigned char __user *)buf;
+ unsigned long dleft = count;
+ unsigned char *tbuf;
+
+ /* Why would anyone want more than this?? */
+ if (count > cam->width * cam->height * 2)
+ return -EINVAL;
+
+ mutex_lock(&cam->lock);
+ w9966_pdev_claim(cam);
+ w9966_write_reg(cam, 0x00, 0x02); /* Reset ECP-FIFO buffer */
+ w9966_write_reg(cam, 0x00, 0x00); /* Return to normal operation */
+ w9966_write_reg(cam, 0x01, 0x98); /* Enable capture */
+
+ /* write special capture-addr and negotiate into data transfer */
+ if ((parport_negotiate(cam->pport, cam->ppmode|IEEE1284_ADDR) != 0) ||
+ (parport_write(cam->pport, &addr, 1) != 1) ||
+ (parport_negotiate(cam->pport, cam->ppmode|IEEE1284_DATA) != 0)) {
+ w9966_pdev_release(cam);
+ mutex_unlock(&cam->lock);
+ return -EFAULT;
+ }
+
+ tbuf = kmalloc(W9966_RBUFFER, GFP_KERNEL);
+ if (tbuf == NULL) {
+ count = -ENOMEM;
+ goto out;
+ }
+
+ while (dleft > 0) {
+ unsigned long tsize = (dleft > W9966_RBUFFER) ? W9966_RBUFFER : dleft;
+
+ if (parport_read(cam->pport, tbuf, tsize) < tsize) {
+ count = -EFAULT;
+ goto out;
+ }
+ if (copy_to_user(dest, tbuf, tsize) != 0) {
+ count = -EFAULT;
+ goto out;
+ }
+ dest += tsize;
+ dleft -= tsize;
+ }
+
+ w9966_write_reg(cam, 0x01, 0x18); /* Disable capture */
+
+out:
+ kfree(tbuf);
+ w9966_pdev_release(cam);
+ mutex_unlock(&cam->lock);
+
+ return count;
+}
+
+static const struct v4l2_file_operations w9966_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = v4l2_fh_release,
+ .poll = v4l2_ctrl_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .read = w9966_v4l_read,
+};
+
+static const struct v4l2_ioctl_ops w9966_ioctl_ops = {
+ .vidioc_querycap = cam_querycap,
+ .vidioc_g_input = cam_g_input,
+ .vidioc_s_input = cam_s_input,
+ .vidioc_enum_input = cam_enum_input,
+ .vidioc_enum_fmt_vid_cap = cam_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = cam_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = cam_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = cam_try_fmt_vid_cap,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static const struct v4l2_ctrl_ops cam_ctrl_ops = {
+ .s_ctrl = cam_s_ctrl,
+};
+
+
+/* Initialize camera device. Setup all internal flags, set a
+ default video mode, setup ccd-chip, register v4l device etc..
+ Also used for 'probing' of hardware.
+ -1 on error */
+static int w9966_init(struct w9966 *cam, struct parport *port)
+{
+ struct v4l2_device *v4l2_dev = &cam->v4l2_dev;
+
+ if (cam->dev_state != 0)
+ return -1;
+
+ strlcpy(v4l2_dev->name, "w9966", sizeof(v4l2_dev->name));
+
+ if (v4l2_device_register(NULL, v4l2_dev) < 0) {
+ v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
+ return -1;
+ }
+
+ v4l2_ctrl_handler_init(&cam->hdl, 4);
+ v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+ V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+ v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+ V4L2_CID_CONTRAST, -64, 64, 1, 64);
+ v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+ V4L2_CID_SATURATION, -64, 64, 1, 64);
+ v4l2_ctrl_new_std(&cam->hdl, &cam_ctrl_ops,
+ V4L2_CID_HUE, -128, 127, 1, 0);
+ if (cam->hdl.error) {
+ v4l2_err(v4l2_dev, "couldn't register controls\n");
+ return -1;
+ }
+ cam->pport = port;
+ cam->brightness = 128;
+ cam->contrast = 64;
+ cam->color = 64;
+ cam->hue = 0;
+
+ /* Select requested transfer mode */
+ switch (parmode) {
+ default: /* Auto-detect (priority: hw-ecp, hw-epp, sw-ecp) */
+ case 0:
+ if (port->modes & PARPORT_MODE_ECP)
+ cam->ppmode = IEEE1284_MODE_ECP;
+ else if (port->modes & PARPORT_MODE_EPP)
+ cam->ppmode = IEEE1284_MODE_EPP;
+ else
+ cam->ppmode = IEEE1284_MODE_ECP;
+ break;
+ case 1: /* hw- or sw-ecp */
+ cam->ppmode = IEEE1284_MODE_ECP;
+ break;
+ case 2: /* hw- or sw-epp */
+ cam->ppmode = IEEE1284_MODE_EPP;
+ break;
+ }
+
+ /* Tell the parport driver that we exists */
+ cam->pdev = parport_register_device(port, "w9966", NULL, NULL, NULL, 0, NULL);
+ if (cam->pdev == NULL) {
+ DPRINTF("parport_register_device() failed\n");
+ return -1;
+ }
+ w9966_set_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV);
+
+ w9966_pdev_claim(cam);
+
+ /* Setup a default capture mode */
+ if (w9966_setup(cam, 0, 0, 1023, 1023, 200, 160) != 0) {
+ DPRINTF("w9966_setup() failed.\n");
+ return -1;
+ }
+
+ w9966_pdev_release(cam);
+
+ /* Fill in the video_device struct and register us to v4l */
+ strlcpy(cam->vdev.name, W9966_DRIVERNAME, sizeof(cam->vdev.name));
+ cam->vdev.v4l2_dev = v4l2_dev;
+ cam->vdev.fops = &w9966_fops;
+ cam->vdev.ioctl_ops = &w9966_ioctl_ops;
+ cam->vdev.release = video_device_release_empty;
+ cam->vdev.ctrl_handler = &cam->hdl;
+ video_set_drvdata(&cam->vdev, cam);
+
+ mutex_init(&cam->lock);
+
+ if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, video_nr) < 0)
+ return -1;
+
+ w9966_set_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV);
+
+ /* All ok */
+ v4l2_info(v4l2_dev, "Found and initialized a webcam on %s.\n",
+ cam->pport->name);
+ return 0;
+}
+
+
+/* Terminate everything gracefully */
+static void w9966_term(struct w9966 *cam)
+{
+ /* Unregister from v4l */
+ if (w9966_get_state(cam, W9966_STATE_VDEV, W9966_STATE_VDEV)) {
+ video_unregister_device(&cam->vdev);
+ w9966_set_state(cam, W9966_STATE_VDEV, 0);
+ }
+
+ v4l2_ctrl_handler_free(&cam->hdl);
+
+ /* Terminate from IEEE1284 mode and release pdev block */
+ if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
+ w9966_pdev_claim(cam);
+ parport_negotiate(cam->pport, IEEE1284_MODE_COMPAT);
+ w9966_pdev_release(cam);
+ }
+
+ /* Unregister from parport */
+ if (w9966_get_state(cam, W9966_STATE_PDEV, W9966_STATE_PDEV)) {
+ parport_unregister_device(cam->pdev);
+ w9966_set_state(cam, W9966_STATE_PDEV, 0);
+ }
+ memset(cam, 0, sizeof(*cam));
+}
+
+
+/* Called once for every parport on init */
+static void w9966_attach(struct parport *port)
+{
+ int i;
+
+ for (i = 0; i < W9966_MAXCAMS; i++) {
+ if (w9966_cams[i].dev_state != 0) /* Cam is already assigned */
+ continue;
+ if (strcmp(pardev[i], "aggressive") == 0 || strcmp(pardev[i], port->name) == 0) {
+ if (w9966_init(&w9966_cams[i], port) != 0)
+ w9966_term(&w9966_cams[i]);
+ break; /* return */
+ }
+ }
+}
+
+/* Called once for every parport on termination */
+static void w9966_detach(struct parport *port)
+{
+ int i;
+
+ for (i = 0; i < W9966_MAXCAMS; i++)
+ if (w9966_cams[i].dev_state != 0 && w9966_cams[i].pport == port)
+ w9966_term(&w9966_cams[i]);
+}
+
+
+static struct parport_driver w9966_ppd = {
+ .name = W9966_DRIVERNAME,
+ .attach = w9966_attach,
+ .detach = w9966_detach,
+};
+
+/* Module entry point */
+static int __init w9966_mod_init(void)
+{
+ int i;
+
+ for (i = 0; i < W9966_MAXCAMS; i++)
+ w9966_cams[i].dev_state = 0;
+
+ return parport_register_driver(&w9966_ppd);
+}
+
+/* Module cleanup */
+static void __exit w9966_mod_term(void)
+{
+ parport_unregister_driver(&w9966_ppd);
+}
+
+module_init(w9966_mod_init);
+module_exit(w9966_mod_term);
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
index 218144a..f8cec8e 100644
--- a/drivers/media/pci/Kconfig
+++ b/drivers/media/pci/Kconfig
@@ -46,7 +46,6 @@
source "drivers/media/pci/mantis/Kconfig"
source "drivers/media/pci/ngene/Kconfig"
source "drivers/media/pci/ddbridge/Kconfig"
-source "drivers/media/pci/smipcie/Kconfig"
endif
endif #MEDIA_PCI_SUPPORT
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
index 7f15888..abdb56a 100644
--- a/drivers/media/pci/Makefile
+++ b/drivers/media/pci/Makefile
@@ -11,8 +11,7 @@
mantis/ \
ngene/ \
ddbridge/ \
- saa7146/ \
- smipcie/
+ saa7146/
obj-$(CPTCFG_VIDEO_IVTV) += ivtv/
obj-$(CPTCFG_VIDEO_ZORAN) += zoran/
diff --git a/drivers/media/pci/bt8xx/bttv-cards.c b/drivers/media/pci/bt8xx/bttv-cards.c
index 4105560..d8ec583 100644
--- a/drivers/media/pci/bt8xx/bttv-cards.c
+++ b/drivers/media/pci/bt8xx/bttv-cards.c
@@ -3870,10 +3870,10 @@
} else {
unsigned short type;
- for (i = 4 * 16; i < 8 * 16; i += 16) {
- u16 checksum = (__force u16)ip_compute_csum(ee + i, 16);
+ for (i = 4*16; i < 8*16; i += 16) {
+ u16 checksum = ip_compute_csum(ee + i, 16);
- if ((checksum & 0xff) + (checksum >> 8) == 0xff)
+ if ((checksum&0xff) + (checksum>>8) == 0xff)
break;
}
if (i >= 8*16)
diff --git a/drivers/media/pci/bt8xx/bttv-risc.c b/drivers/media/pci/bt8xx/bttv-risc.c
index 4d3f05a..82cc47d 100644
--- a/drivers/media/pci/bt8xx/bttv-risc.c
+++ b/drivers/media/pci/bt8xx/bttv-risc.c
@@ -84,7 +84,7 @@
continue;
while (offset && offset >= sg_dma_len(sg)) {
offset -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
if (bpl <= sg_dma_len(sg)-offset) {
/* fits into current chunk */
@@ -100,13 +100,13 @@
*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
todo -= (sg_dma_len(sg)-offset);
offset = 0;
- sg = sg_next(sg);
+ sg++;
while (todo > sg_dma_len(sg)) {
*(rp++)=cpu_to_le32(BT848_RISC_WRITE|
sg_dma_len(sg));
*(rp++)=cpu_to_le32(sg_dma_address(sg));
todo -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
*(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL|
todo);
@@ -187,15 +187,15 @@
/* go to next sg entry if needed */
while (yoffset && yoffset >= sg_dma_len(ysg)) {
yoffset -= sg_dma_len(ysg);
- ysg = sg_next(ysg);
+ ysg++;
}
while (uoffset && uoffset >= sg_dma_len(usg)) {
uoffset -= sg_dma_len(usg);
- usg = sg_next(usg);
+ usg++;
}
while (voffset && voffset >= sg_dma_len(vsg)) {
voffset -= sg_dma_len(vsg);
- vsg = sg_next(vsg);
+ vsg++;
}
/* calculate max number of bytes we can write */
diff --git a/drivers/media/pci/cx18/cx18-av-core.c b/drivers/media/pci/cx18/cx18-av-core.c
index 7f2cec2..d2402aa 100644
--- a/drivers/media/pci/cx18/cx18-av-core.c
+++ b/drivers/media/pci/cx18/cx18-av-core.c
@@ -490,8 +490,8 @@
/* Sets horizontal blanking delay and active lines */
cx18_av_write(cx, 0x470, hblank);
- cx18_av_write(cx, 0x471,
- (((hblank >> 8) & 0x3) | (hactive << 4)) & 0xff);
+ cx18_av_write(cx, 0x471, 0xff & (((hblank >> 8) & 0x3) |
+ (hactive << 4)));
cx18_av_write(cx, 0x472, hactive >> 4);
/* Sets burst gate delay */
@@ -499,14 +499,14 @@
/* Sets vertical blanking delay and active duration */
cx18_av_write(cx, 0x474, vblank);
- cx18_av_write(cx, 0x475,
- (((vblank >> 8) & 0x3) | (vactive << 4)) & 0xff);
+ cx18_av_write(cx, 0x475, 0xff & (((vblank >> 8) & 0x3) |
+ (vactive << 4)));
cx18_av_write(cx, 0x476, vactive >> 4);
cx18_av_write(cx, 0x477, vblank656);
/* Sets src decimation rate */
- cx18_av_write(cx, 0x478, src_decimation & 0xff);
- cx18_av_write(cx, 0x479, (src_decimation >> 8) & 0xff);
+ cx18_av_write(cx, 0x478, 0xff & src_decimation);
+ cx18_av_write(cx, 0x479, 0xff & (src_decimation >> 8));
/* Sets Luma and UV Low pass filters */
cx18_av_write(cx, 0x47a, luma_lpf << 6 | ((uv_lpf << 4) & 0x30));
@@ -516,8 +516,8 @@
/* Sets SC Step*/
cx18_av_write(cx, 0x47c, sc);
- cx18_av_write(cx, 0x47d, (sc >> 8) & 0xff);
- cx18_av_write(cx, 0x47e, (sc >> 16) & 0xff);
+ cx18_av_write(cx, 0x47d, 0xff & sc >> 8);
+ cx18_av_write(cx, 0x47e, 0xff & sc >> 16);
if (std & V4L2_STD_625_50) {
state->slicer_line_delay = 1;
@@ -952,7 +952,7 @@
int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(state->std & V4L2_STD_525_60);
- if (fmt->code != MEDIA_BUS_FMT_FIXED)
+ if (fmt->code != V4L2_MBUS_FMT_FIXED)
return -EINVAL;
fmt->field = V4L2_FIELD_INTERLACED;
diff --git a/drivers/media/pci/cx18/cx18-cards.h b/drivers/media/pci/cx18/cx18-cards.h
index f6b921f..add7391 100644
--- a/drivers/media/pci/cx18/cx18-cards.h
+++ b/drivers/media/pci/cx18/cx18-cards.h
@@ -57,8 +57,7 @@
/* V4L2 capability aliases */
#define CX18_CAP_ENCODER (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER | \
V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | \
- V4L2_CAP_STREAMING | V4L2_CAP_VBI_CAPTURE | \
- V4L2_CAP_SLICED_VBI_CAPTURE)
+ V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE)
struct cx18_card_video_input {
u8 video_type; /* video input type */
diff --git a/drivers/media/pci/cx18/cx18-controls.c b/drivers/media/pci/cx18/cx18-controls.c
index 4aeb7c6..282a3d2 100644
--- a/drivers/media/pci/cx18/cx18-controls.c
+++ b/drivers/media/pci/cx18/cx18-controls.c
@@ -98,7 +98,7 @@
/* fix videodecoder resolution */
fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
fmt.height = cxhdl->height;
- fmt.code = MEDIA_BUS_FMT_FIXED;
+ fmt.code = V4L2_MBUS_FMT_FIXED;
v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
return 0;
}
diff --git a/drivers/media/pci/cx18/cx18-driver.h b/drivers/media/pci/cx18/cx18-driver.h
index 207d6e8..57f4688 100644
--- a/drivers/media/pci/cx18/cx18-driver.h
+++ b/drivers/media/pci/cx18/cx18-driver.h
@@ -290,7 +290,7 @@
* list_entry_is_past_end - check if a previous loop cursor is off list end
* @pos: the type * previously used as a loop cursor.
* @head: the head for your list.
- * @member: the name of the list_head within the struct.
+ * @member: the name of the list_struct within the struct.
*
* Check if the entry's list_head is the head of the list, thus it's not a
* real entry but was the loop cursor that walked past the end
@@ -379,7 +379,6 @@
const char *name; /* name of the stream */
int type; /* stream type */
u32 handle; /* task handle */
- u32 v4l2_dev_caps; /* device capabilities */
unsigned int mdl_base_idx;
u32 id;
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
index 27fdad8..0d6616b 100644
--- a/drivers/media/pci/cx18/cx18-ioctl.c
+++ b/drivers/media/pci/cx18/cx18-ioctl.c
@@ -294,7 +294,7 @@
mbus_fmt.width = cx->cxhdl.width = w;
mbus_fmt.height = cx->cxhdl.height = h;
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
+ mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
return cx18_g_fmt_vid_cap(file, fh, fmt);
}
@@ -393,16 +393,15 @@
struct v4l2_capability *vcap)
{
struct cx18_open_id *id = fh2id(fh);
- struct cx18_stream *s = video_drvdata(file);
struct cx18 *cx = id->cx;
strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
snprintf(vcap->bus_info, sizeof(vcap->bus_info),
"PCI:%s", pci_name(cx->pci_dev));
- vcap->capabilities = cx->v4l2_cap; /* capabilities */
- vcap->device_caps = s->v4l2_dev_caps; /* device capabilities */
- vcap->capabilities |= V4L2_CAP_DEVICE_CAPS;
+ vcap->capabilities = cx->v4l2_cap; /* capabilities */
+ if (id->type == CX18_ENC_STREAM_TYPE_YUV)
+ vcap->capabilities |= V4L2_CAP_STREAMING;
return 0;
}
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
index 369445f..f3541b5 100644
--- a/drivers/media/pci/cx18/cx18-streams.c
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -58,14 +58,11 @@
int vfl_type;
int num_offset;
int dma;
- u32 caps;
} cx18_stream_info[] = {
{ /* CX18_ENC_STREAM_TYPE_MPG */
"encoder MPEG",
VFL_TYPE_GRABBER, 0,
PCI_DMA_FROMDEVICE,
- V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
- V4L2_CAP_AUDIO | V4L2_CAP_TUNER
},
{ /* CX18_ENC_STREAM_TYPE_TS */
"TS",
@@ -76,15 +73,11 @@
"encoder YUV",
VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
PCI_DMA_FROMDEVICE,
- V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING | V4L2_CAP_AUDIO | V4L2_CAP_TUNER
},
{ /* CX18_ENC_STREAM_TYPE_VBI */
"encoder VBI",
VFL_TYPE_VBI, 0,
PCI_DMA_FROMDEVICE,
- V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE |
- V4L2_CAP_READWRITE | V4L2_CAP_TUNER
},
{ /* CX18_ENC_STREAM_TYPE_PCM */
"encoder PCM audio",
@@ -100,7 +93,6 @@
"encoder radio",
VFL_TYPE_RADIO, 0,
PCI_DMA_NONE,
- V4L2_CAP_RADIO | V4L2_CAP_TUNER
},
};
@@ -268,7 +260,6 @@
s->handle = CX18_INVALID_TASK_HANDLE;
s->dma = cx18_stream_info[type].dma;
- s->v4l2_dev_caps = cx18_stream_info[type].caps;
s->buffers = cx->stream_buffers[type];
s->buf_size = cx->stream_buf_size[type];
INIT_LIST_HEAD(&s->buf_pool);
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig
index fcbcf43..911c260 100644
--- a/drivers/media/pci/cx23885/Kconfig
+++ b/drivers/media/pci/cx23885/Kconfig
@@ -1,5 +1,5 @@
config VIDEO_CX23885
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Conexant cx23885 (2388x successor) support"
depends on m
depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND
diff --git a/drivers/media/pci/cx23885/cx23885-417.c b/drivers/media/pci/cx23885/cx23885-417.c
index 5a0f130..4a4f949 100644
--- a/drivers/media/pci/cx23885/cx23885-417.c
+++ b/drivers/media/pci/cx23885/cx23885-417.c
@@ -1148,7 +1148,6 @@
dev->ts1.ts_packet_count = mpeglines;
*num_planes = 1;
sizes[0] = mpeglinesize * mpeglines;
- alloc_ctxs[0] = dev->alloc_ctx;
*num_buffers = mpegbufs;
return 0;
}
@@ -1167,8 +1166,11 @@
struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf = container_of(vb,
struct cx23885_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
cx23885_free_buffer(dev, buf);
+
+ dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
static void buffer_queue(struct vb2_buffer *vb)
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
index db99ca2..88c257d 100644
--- a/drivers/media/pci/cx23885/cx23885-cards.c
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -680,32 +680,6 @@
.portb = CX23885_MPEG_DVB,
.portc = CX23885_MPEG_DVB,
},
- [CX23885_BOARD_DVBSKY_T980C] = {
- .name = "DVBSky T980C",
- .portb = CX23885_MPEG_DVB,
- },
- [CX23885_BOARD_DVBSKY_S950C] = {
- .name = "DVBSky S950C",
- .portb = CX23885_MPEG_DVB,
- },
- [CX23885_BOARD_TT_CT2_4500_CI] = {
- .name = "Technotrend TT-budget CT2-4500 CI",
- .portb = CX23885_MPEG_DVB,
- },
- [CX23885_BOARD_DVBSKY_S950] = {
- .name = "DVBSky S950",
- .portb = CX23885_MPEG_DVB,
- },
- [CX23885_BOARD_DVBSKY_S952] = {
- .name = "DVBSky S952",
- .portb = CX23885_MPEG_DVB,
- .portc = CX23885_MPEG_DVB,
- },
- [CX23885_BOARD_DVBSKY_T982] = {
- .name = "DVBSky T982",
- .portb = CX23885_MPEG_DVB,
- .portc = CX23885_MPEG_DVB,
- },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -965,30 +939,6 @@
.subvendor = 0x4254,
.subdevice = 0x9580,
.card = CX23885_BOARD_DVBSKY_T9580,
- }, {
- .subvendor = 0x4254,
- .subdevice = 0x980c,
- .card = CX23885_BOARD_DVBSKY_T980C,
- }, {
- .subvendor = 0x4254,
- .subdevice = 0x950c,
- .card = CX23885_BOARD_DVBSKY_S950C,
- }, {
- .subvendor = 0x13c2,
- .subdevice = 0x3013,
- .card = CX23885_BOARD_TT_CT2_4500_CI,
- }, {
- .subvendor = 0x4254,
- .subdevice = 0x0950,
- .card = CX23885_BOARD_DVBSKY_S950,
- }, {
- .subvendor = 0x4254,
- .subdevice = 0x0952,
- .card = CX23885_BOARD_DVBSKY_S952,
- }, {
- .subvendor = 0x4254,
- .subdevice = 0x0982,
- .card = CX23885_BOARD_DVBSKY_T982,
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -1584,8 +1534,6 @@
mdelay(60);
break;
case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_S952:
- case CX23885_BOARD_DVBSKY_T982:
/* enable GPIO3-18 pins */
cx_write(MC417_CTL, 0x00000037);
cx23885_gpio_enable(dev, GPIO_2 | GPIO_11, 1);
@@ -1593,45 +1541,6 @@
mdelay(100);
cx23885_gpio_set(dev, GPIO_2 | GPIO_11);
break;
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_TT_CT2_4500_CI:
- /*
- * GPIO-0 INTA from CiMax, input
- * GPIO-1 reset CiMax, output, high active
- * GPIO-2 reset demod, output, low active
- * GPIO-3 to GPIO-10 data/addr for CAM
- * GPIO-11 ~CS0 to CiMax1
- * GPIO-12 ~CS1 to CiMax2
- * GPIO-13 ADL0 load LSB addr
- * GPIO-14 ADL1 load MSB addr
- * GPIO-15 ~RDY from CiMax
- * GPIO-17 ~RD to CiMax
- * GPIO-18 ~WR to CiMax
- */
-
- cx_set(GP0_IO, 0x00060002); /* GPIO 1/2 as output */
- cx_clear(GP0_IO, 0x00010004); /* GPIO 0 as input */
- mdelay(100); /* reset delay */
- cx_set(GP0_IO, 0x00060004); /* GPIO as out, reset high */
- cx_clear(GP0_IO, 0x00010002);
- cx_write(MC417_CTL, 0x00000037); /* enable GPIO3-18 pins */
-
- /* GPIO-15 IN as ~ACK, rest as OUT */
- cx_write(MC417_OEN, 0x00001000);
-
- /* ~RD, ~WR high; ADL0, ADL1 low; ~CS0, ~CS1 high */
- cx_write(MC417_RWD, 0x0000c300);
-
- /* enable irq */
- cx_write(GPIO_ISM, 0x00000000); /* INTERRUPTS active low */
- break;
- case CX23885_BOARD_DVBSKY_S950:
- cx23885_gpio_enable(dev, GPIO_2, 1);
- cx23885_gpio_clear(dev, GPIO_2);
- msleep(100);
- cx23885_gpio_set(dev, GPIO_2);
- break;
}
}
@@ -1712,13 +1621,6 @@
case CX23885_BOARD_MYGICA_X8507:
case CX23885_BOARD_TBS_6980:
case CX23885_BOARD_TBS_6981:
- case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_TT_CT2_4500_CI:
- case CX23885_BOARD_DVBSKY_S950:
- case CX23885_BOARD_DVBSKY_S952:
- case CX23885_BOARD_DVBSKY_T982:
if (!enable_885_ir)
break;
dev->sd_ir = cx23885_find_hw(dev, CX23885_HW_AV_CORE);
@@ -1765,13 +1667,6 @@
case CX23885_BOARD_MYGICA_X8507:
case CX23885_BOARD_TBS_6980:
case CX23885_BOARD_TBS_6981:
- case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_TT_CT2_4500_CI:
- case CX23885_BOARD_DVBSKY_S950:
- case CX23885_BOARD_DVBSKY_S952:
- case CX23885_BOARD_DVBSKY_T982:
cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
/* sd_ir is a duplicate pointer to the AV Core, just clear it */
dev->sd_ir = NULL;
@@ -1819,13 +1714,6 @@
case CX23885_BOARD_MYGICA_X8507:
case CX23885_BOARD_TBS_6980:
case CX23885_BOARD_TBS_6981:
- case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_TT_CT2_4500_CI:
- case CX23885_BOARD_DVBSKY_S950:
- case CX23885_BOARD_DVBSKY_S952:
- case CX23885_BOARD_DVBSKY_T982:
if (dev->sd_ir)
cx23885_irq_add_enable(dev, PCI_MSK_AV_CORE);
break;
@@ -1929,10 +1817,6 @@
case CX23885_BOARD_TEVII_S471:
case CX23885_BOARD_DVBWORLD_2005:
case CX23885_BOARD_PROF_8000:
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_TT_CT2_4500_CI:
- case CX23885_BOARD_DVBSKY_S950:
ts1->gen_ctrl_val = 0x5; /* Parallel */
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -1981,7 +1865,6 @@
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break;
case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_T982:
ts1->gen_ctrl_val = 0x5; /* Parallel */
ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -1989,14 +1872,6 @@
ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
break;
- case CX23885_BOARD_DVBSKY_S952:
- ts1->gen_ctrl_val = 0x5; /* Parallel */
- ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
- ts1->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
- ts2->gen_ctrl_val = 0xe; /* Serial bus */
- ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */
- ts2->src_sel_val = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
- break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1500:
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
@@ -2060,12 +1935,6 @@
case CX23885_BOARD_TBS_6980:
case CX23885_BOARD_TBS_6981:
case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_TT_CT2_4500_CI:
- case CX23885_BOARD_DVBSKY_S950:
- case CX23885_BOARD_DVBSKY_S952:
- case CX23885_BOARD_DVBSKY_T982:
dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
&dev->i2c_bus[2].i2c_adap,
"cx25840", 0x88 >> 1, NULL);
diff --git a/drivers/media/pci/cx23885/cx23885-core.c b/drivers/media/pci/cx23885/cx23885-core.c
index 1d9d0f8..331edda 100644
--- a/drivers/media/pci/cx23885/cx23885-core.c
+++ b/drivers/media/pci/cx23885/cx23885-core.c
@@ -1078,7 +1078,7 @@
for (line = 0; line < lines; line++) {
while (offset && offset >= sg_dma_len(sg)) {
offset -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
if (lpi && line > 0 && !(line % lpi))
@@ -1101,14 +1101,14 @@
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= (sg_dma_len(sg)-offset);
offset = 0;
- sg = sg_next(sg);
+ sg++;
while (todo > sg_dma_len(sg)) {
*(rp++) = cpu_to_le32(RISC_WRITE|
sg_dma_len(sg));
*(rp++) = cpu_to_le32(sg_dma_address(sg));
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
*(rp++) = cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
*(rp++) = cpu_to_le32(sg_dma_address(sg));
@@ -1453,12 +1453,17 @@
struct cx23885_dev *dev = port->dev;
int size = port->ts_packet_size * port->ts_packet_count;
struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
+ int rc;
dprintk(1, "%s: %p\n", __func__, buf);
if (vb2_plane_size(&buf->vb, 0) < size)
return -EINVAL;
vb2_set_plane_payload(&buf->vb, 0, size);
+ rc = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+ if (!rc)
+ return -EIO;
+
cx23885_risc_databuffer(dev->pci, &buf->risc,
sgt->sgl,
port->ts_packet_size, port->ts_packet_count, 0);
@@ -1992,14 +1997,9 @@
if (!pci_dma_supported(pci_dev, 0xffffffff)) {
printk("%s/0: Oops: no 32bit PCI DMA ???\n", dev->name);
err = -EIO;
- goto fail_context;
+ goto fail_irq;
}
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail_context;
- }
err = request_irq(pci_dev->irq, cx23885_irq,
IRQF_SHARED, dev->name, dev);
if (err < 0) {
@@ -2028,8 +2028,6 @@
return 0;
fail_irq:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
-fail_context:
cx23885_dev_unregister(dev);
fail_ctrl:
v4l2_ctrl_handler_free(hdl);
@@ -2055,7 +2053,6 @@
free_irq(pci_dev->irq, dev);
cx23885_dev_unregister(dev);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
v4l2_ctrl_handler_free(&dev->ctrl_handler);
v4l2_device_unregister(v4l2_dev);
kfree(dev);
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index c47d182..13734b8 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -71,7 +71,6 @@
#include "si2165.h"
#include "si2168.h"
#include "si2157.h"
-#include "sp2.h"
#include "m88ds3103.h"
#include "m88ts2022.h"
@@ -102,7 +101,6 @@
port->ts_packet_count = 32;
*num_planes = 1;
sizes[0] = port->ts_packet_size * port->ts_packet_count;
- alloc_ctxs[0] = port->dev->alloc_ctx;
*num_buffers = 32;
return 0;
}
@@ -123,8 +121,11 @@
struct cx23885_dev *dev = port->dev;
struct cx23885_buffer *buf = container_of(vb,
struct cx23885_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
cx23885_free_buffer(dev, buf);
+
+ dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
static void buffer_queue(struct vb2_buffer *vb)
@@ -615,103 +616,6 @@
return 0;
}
-static int dvbsky_s952_portc_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
-{
- struct cx23885_tsport *port = fe->dvb->priv;
- struct cx23885_dev *dev = port->dev;
-
- cx23885_gpio_enable(dev, GPIO_12 | GPIO_13, 1);
-
- switch (voltage) {
- case SEC_VOLTAGE_13:
- cx23885_gpio_set(dev, GPIO_13);
- cx23885_gpio_clear(dev, GPIO_12);
- break;
- case SEC_VOLTAGE_18:
- cx23885_gpio_set(dev, GPIO_13);
- cx23885_gpio_set(dev, GPIO_12);
- break;
- case SEC_VOLTAGE_OFF:
- cx23885_gpio_clear(dev, GPIO_13);
- cx23885_gpio_clear(dev, GPIO_12);
- break;
- }
- /* call the frontend set_voltage function */
- return port->fe_set_voltage(fe, voltage);
-}
-
-static int cx23885_sp2_ci_ctrl(void *priv, u8 read, int addr,
- u8 data, int *mem)
-{
- /* MC417 */
- #define SP2_DATA 0x000000ff
- #define SP2_WR 0x00008000
- #define SP2_RD 0x00004000
- #define SP2_ACK 0x00001000
- #define SP2_ADHI 0x00000800
- #define SP2_ADLO 0x00000400
- #define SP2_CS1 0x00000200
- #define SP2_CS0 0x00000100
- #define SP2_EN_ALL 0x00001000
- #define SP2_CTRL_OFF (SP2_CS1 | SP2_CS0 | SP2_WR | SP2_RD)
-
- struct cx23885_tsport *port = priv;
- struct cx23885_dev *dev = port->dev;
- int ret;
- int tmp = 0;
- unsigned long timeout;
-
- mutex_lock(&dev->gpio_lock);
-
- /* write addr */
- cx_write(MC417_OEN, SP2_EN_ALL);
- cx_write(MC417_RWD, SP2_CTRL_OFF |
- SP2_ADLO | (0xff & addr));
- cx_clear(MC417_RWD, SP2_ADLO);
- cx_write(MC417_RWD, SP2_CTRL_OFF |
- SP2_ADHI | (0xff & (addr >> 8)));
- cx_clear(MC417_RWD, SP2_ADHI);
-
- if (read)
- /* data in */
- cx_write(MC417_OEN, SP2_EN_ALL | SP2_DATA);
- else
- /* data out */
- cx_write(MC417_RWD, SP2_CTRL_OFF | data);
-
- /* chip select 0 */
- cx_clear(MC417_RWD, SP2_CS0);
-
- /* read/write */
- cx_clear(MC417_RWD, (read) ? SP2_RD : SP2_WR);
-
- /* wait for a maximum of 1 msec */
- timeout = jiffies + msecs_to_jiffies(1);
- while (!time_after(jiffies, timeout)) {
- tmp = cx_read(MC417_RWD);
- if ((tmp & SP2_ACK) == 0)
- break;
- usleep_range(50, 100);
- }
-
- cx_set(MC417_RWD, SP2_CTRL_OFF);
- *mem = tmp & 0xff;
-
- mutex_unlock(&dev->gpio_lock);
-
- if (!read) {
- if (*mem < 0) {
- ret = -EREMOTEIO;
- goto err;
- }
- }
-
- return 0;
-err:
- return ret;
-}
-
static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
@@ -889,32 +793,6 @@
.agc = 0x99,
};
-static const struct m88ds3103_config dvbsky_s950c_m88ds3103_config = {
- .i2c_addr = 0x68,
- .clock = 27000000,
- .i2c_wr_max = 33,
- .clock_out = 0,
- .ts_mode = M88DS3103_TS_CI,
- .ts_clk = 10000,
- .ts_clk_pol = 1,
- .lnb_en_pol = 1,
- .lnb_hv_pol = 0,
- .agc = 0x99,
-};
-
-static const struct m88ds3103_config dvbsky_s952_portc_m88ds3103_config = {
- .i2c_addr = 0x68,
- .clock = 27000000,
- .i2c_wr_max = 33,
- .clock_out = 0,
- .ts_mode = M88DS3103_TS_SERIAL,
- .ts_clk = 96000,
- .ts_clk_pol = 0,
- .lnb_en_pol = 1,
- .lnb_hv_pol = 0,
- .agc = 0x99,
-};
-
static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
{
struct cx23885_dev *dev = (struct cx23885_dev *)device;
@@ -1066,13 +944,11 @@
struct vb2_dvb_frontend *fe0, *fe1 = NULL;
struct si2168_config si2168_config;
struct si2157_config si2157_config;
- struct sp2_config sp2_config;
struct m88ts2022_config m88ts2022_config;
struct i2c_board_info info;
struct i2c_adapter *adapter;
- struct i2c_client *client_demod = NULL, *client_tuner = NULL, *client_ci = NULL;
- const struct m88ds3103_config *p_m88ds3103_config = NULL;
- int (*p_set_voltage)(struct dvb_frontend *fe, fe_sec_voltage_t voltage) = NULL;
+ struct i2c_client *client_demod;
+ struct i2c_client *client_tuner;
int mfe_shared = 0; /* bus not shared by default */
int ret;
@@ -1097,11 +973,11 @@
fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&hauppauge_generic_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(mt2131_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_generic_tunerconfig, 0);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(mt2131_attach, fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &hauppauge_generic_tunerconfig, 0);
+ }
break;
case CX23885_BOARD_HAUPPAUGE_HVR1270:
case CX23885_BOARD_HAUPPAUGE_HVR1275:
@@ -1109,11 +985,11 @@
fe0->dvb.frontend = dvb_attach(lgdt3305_attach,
&hauppauge_lgdt3305_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(tda18271_attach, fe0->dvb.frontend,
- 0x60, &dev->i2c_bus[1].i2c_adap,
- &hauppauge_hvr127x_config);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(tda18271_attach, fe0->dvb.frontend,
+ 0x60, &dev->i2c_bus[1].i2c_adap,
+ &hauppauge_hvr127x_config);
+ }
if (dev->board == CX23885_BOARD_HAUPPAUGE_HVR1275)
cx23885_set_frontend_hook(port, fe0->dvb.frontend);
break;
@@ -1123,12 +999,11 @@
fe0->dvb.frontend = dvb_attach(s5h1411_attach,
&hcw_s5h1411_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
-
- dvb_attach(tda18271_attach, fe0->dvb.frontend,
- 0x60, &dev->i2c_bus[1].i2c_adap,
- &hauppauge_tda18271_config);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(tda18271_attach, fe0->dvb.frontend,
+ 0x60, &dev->i2c_bus[1].i2c_adap,
+ &hauppauge_tda18271_config);
+ }
tda18271_attach(&dev->ts1.analog_fe,
0x60, &dev->i2c_bus[1].i2c_adap,
@@ -1143,15 +1018,14 @@
dvb_attach(s5h1409_attach,
&hauppauge_ezqam_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
-
- dvb_attach(tda829x_attach, fe0->dvb.frontend,
- &dev->i2c_bus[1].i2c_adap, 0x42,
- &tda829x_no_probe);
- dvb_attach(tda18271_attach, fe0->dvb.frontend,
- 0x60, &dev->i2c_bus[1].i2c_adap,
- &hauppauge_tda18271_config);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(tda829x_attach, fe0->dvb.frontend,
+ &dev->i2c_bus[1].i2c_adap, 0x42,
+ &tda829x_no_probe);
+ dvb_attach(tda18271_attach, fe0->dvb.frontend,
+ 0x60, &dev->i2c_bus[1].i2c_adap,
+ &hauppauge_tda18271_config);
+ }
break;
case 0:
default:
@@ -1159,11 +1033,11 @@
dvb_attach(s5h1409_attach,
&hauppauge_generic_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(mt2131_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_generic_tunerconfig, 0);
+ if (fe0->dvb.frontend != NULL)
+ dvb_attach(mt2131_attach, fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &hauppauge_generic_tunerconfig, 0);
+ break;
}
break;
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
@@ -1171,33 +1045,32 @@
fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&hauppauge_hvr1800lp_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(mt2131_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_generic_tunerconfig, 0);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(mt2131_attach, fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &hauppauge_generic_tunerconfig, 0);
+ }
break;
case CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP:
i2c_bus = &dev->i2c_bus[0];
fe0->dvb.frontend = dvb_attach(lgdt330x_attach,
&fusionhdtv_5_express,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap, 0x61,
- TUNER_LG_TDVS_H06XF);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(simple_tuner_attach, fe0->dvb.frontend,
+ &i2c_bus->i2c_adap, 0x61,
+ TUNER_LG_TDVS_H06XF);
+ }
break;
case CX23885_BOARD_HAUPPAUGE_HVR1500Q:
i2c_bus = &dev->i2c_bus[1];
fe0->dvb.frontend = dvb_attach(s5h1409_attach,
&hauppauge_hvr1500q_config,
&dev->i2c_bus[0].i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(xc5000_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_hvr1500q_tunerconfig);
+ if (fe0->dvb.frontend != NULL)
+ dvb_attach(xc5000_attach, fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &hauppauge_hvr1500q_tunerconfig);
break;
case CX23885_BOARD_HAUPPAUGE_HVR1500:
i2c_bus = &dev->i2c_bus[1];
@@ -1228,14 +1101,14 @@
fe0->dvb.frontend = dvb_attach(tda10048_attach,
&hauppauge_hvr1200_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(tda829x_attach, fe0->dvb.frontend,
- &dev->i2c_bus[1].i2c_adap, 0x42,
- &tda829x_no_probe);
- dvb_attach(tda18271_attach, fe0->dvb.frontend,
- 0x60, &dev->i2c_bus[1].i2c_adap,
- &hauppauge_hvr1200_tuner_config);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(tda829x_attach, fe0->dvb.frontend,
+ &dev->i2c_bus[1].i2c_adap, 0x42,
+ &tda829x_no_probe);
+ dvb_attach(tda18271_attach, fe0->dvb.frontend,
+ 0x60, &dev->i2c_bus[1].i2c_adap,
+ &hauppauge_hvr1200_tuner_config);
+ }
break;
case CX23885_BOARD_HAUPPAUGE_HVR1210:
i2c_bus = &dev->i2c_bus[0];
@@ -1494,10 +1367,12 @@
fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
&mygica_x8506_lgs8gl5_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(xc5000_attach, fe0->dvb.frontend,
- &i2c_bus2->i2c_adap, &mygica_x8506_xc5000_config);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(xc5000_attach,
+ fe0->dvb.frontend,
+ &i2c_bus2->i2c_adap,
+ &mygica_x8506_xc5000_config);
+ }
cx23885_set_frontend_hook(port, fe0->dvb.frontend);
break;
case CX23885_BOARD_MYGICA_X8507:
@@ -1506,12 +1381,12 @@
fe0->dvb.frontend = dvb_attach(mb86a20s_attach,
&mygica_x8507_mb86a20s_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
-
- dvb_attach(xc5000_attach, fe0->dvb.frontend,
- &i2c_bus2->i2c_adap,
- &mygica_x8507_xc5000_config);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(xc5000_attach,
+ fe0->dvb.frontend,
+ &i2c_bus2->i2c_adap,
+ &mygica_x8507_xc5000_config);
+ }
cx23885_set_frontend_hook(port, fe0->dvb.frontend);
break;
case CX23885_BOARD_MAGICPRO_PROHDTVE2:
@@ -1520,11 +1395,12 @@
fe0->dvb.frontend = dvb_attach(lgs8gxx_attach,
&magicpro_prohdtve2_lgs8g75_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(xc5000_attach, fe0->dvb.frontend,
- &i2c_bus2->i2c_adap,
- &magicpro_prohdtve2_xc5000_config);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(xc5000_attach,
+ fe0->dvb.frontend,
+ &i2c_bus2->i2c_adap,
+ &magicpro_prohdtve2_xc5000_config);
+ }
cx23885_set_frontend_hook(port, fe0->dvb.frontend);
break;
case CX23885_BOARD_HAUPPAUGE_HVR1850:
@@ -1532,11 +1408,10 @@
fe0->dvb.frontend = dvb_attach(s5h1411_attach,
&hcw_s5h1411_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(tda18271_attach, fe0->dvb.frontend,
- 0x60, &dev->i2c_bus[0].i2c_adap,
- &hauppauge_tda18271_config);
+ if (fe0->dvb.frontend != NULL)
+ dvb_attach(tda18271_attach, fe0->dvb.frontend,
+ 0x60, &dev->i2c_bus[0].i2c_adap,
+ &hauppauge_tda18271_config);
tda18271_attach(&dev->ts1.analog_fe,
0x60, &dev->i2c_bus[1].i2c_adap,
@@ -1548,11 +1423,10 @@
fe0->dvb.frontend = dvb_attach(s5h1411_attach,
&hcw_s5h1411_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(tda18271_attach, fe0->dvb.frontend,
- 0x60, &dev->i2c_bus[0].i2c_adap,
- &hauppauge_tda18271_config);
+ if (fe0->dvb.frontend != NULL)
+ dvb_attach(tda18271_attach, fe0->dvb.frontend,
+ 0x60, &dev->i2c_bus[0].i2c_adap,
+ &hauppauge_tda18271_config);
break;
case CX23885_BOARD_MYGICA_X8558PRO:
switch (port->nr) {
@@ -1562,11 +1436,12 @@
fe0->dvb.frontend = dvb_attach(atbm8830_attach,
&mygica_x8558pro_atbm8830_cfg1,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(max2165_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &mygic_x8558pro_max2165_cfg1);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(max2165_attach,
+ fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &mygic_x8558pro_max2165_cfg1);
+ }
break;
/* port C */
case 2:
@@ -1574,11 +1449,13 @@
fe0->dvb.frontend = dvb_attach(atbm8830_attach,
&mygica_x8558pro_atbm8830_cfg2,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(max2165_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &mygic_x8558pro_max2165_cfg2);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(max2165_attach,
+ fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &mygic_x8558pro_max2165_cfg2);
+ }
+ break;
}
break;
case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
@@ -1590,15 +1467,15 @@
fe0->dvb.frontend = dvb_attach(stv0367ter_attach,
&netup_stv0367_config[port->nr - 1],
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- if (NULL == dvb_attach(xc5000_attach, fe0->dvb.frontend,
+ if (fe0->dvb.frontend != NULL) {
+ if (NULL == dvb_attach(xc5000_attach,
+ fe0->dvb.frontend,
&i2c_bus->i2c_adap,
&netup_xc5000_config[port->nr - 1]))
- goto frontend_detach;
- /* load xc5000 firmware */
- fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend);
-
+ goto frontend_detach;
+ /* load xc5000 firmware */
+ fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend);
+ }
/* MFE frontend 2 */
fe1 = vb2_dvb_get_frontend(&port->frontends, 2);
if (fe1 == NULL)
@@ -1607,15 +1484,14 @@
fe1->dvb.frontend = dvb_attach(stv0367cab_attach,
&netup_stv0367_config[port->nr - 1],
&i2c_bus->i2c_adap);
- if (fe1->dvb.frontend == NULL)
- break;
-
- fe1->dvb.frontend->id = 1;
- if (NULL == dvb_attach(xc5000_attach,
- fe1->dvb.frontend,
- &i2c_bus->i2c_adap,
- &netup_xc5000_config[port->nr - 1]))
- goto frontend_detach;
+ if (fe1->dvb.frontend != NULL) {
+ fe1->dvb.frontend->id = 1;
+ if (NULL == dvb_attach(xc5000_attach,
+ fe1->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &netup_xc5000_config[port->nr - 1]))
+ goto frontend_detach;
+ }
break;
case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
i2c_bus = &dev->i2c_bus[0];
@@ -1627,26 +1503,26 @@
fe0->dvb.frontend = dvb_attach(drxk_attach,
&terratec_drxk_config[0],
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- if (!dvb_attach(mt2063_attach,
- fe0->dvb.frontend,
- &terratec_mt2063_config[0],
- &i2c_bus2->i2c_adap))
- goto frontend_detach;
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(mt2063_attach,
+ fe0->dvb.frontend,
+ &terratec_mt2063_config[0],
+ &i2c_bus2->i2c_adap))
+ goto frontend_detach;
+ }
break;
/* port c */
case 2:
fe0->dvb.frontend = dvb_attach(drxk_attach,
&terratec_drxk_config[1],
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- if (!dvb_attach(mt2063_attach,
- fe0->dvb.frontend,
- &terratec_mt2063_config[1],
- &i2c_bus2->i2c_adap))
- goto frontend_detach;
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(mt2063_attach,
+ fe0->dvb.frontend,
+ &terratec_mt2063_config[1],
+ &i2c_bus2->i2c_adap))
+ goto frontend_detach;
+ }
break;
}
break;
@@ -1656,10 +1532,10 @@
fe0->dvb.frontend = dvb_attach(ds3000_attach,
&tevii_ds3000_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- dvb_attach(ts2020_attach, fe0->dvb.frontend,
- &tevii_ts2020_config, &i2c_bus->i2c_adap);
+ if (fe0->dvb.frontend != NULL) {
+ dvb_attach(ts2020_attach, fe0->dvb.frontend,
+ &tevii_ts2020_config, &i2c_bus->i2c_adap);
+ }
break;
case CX23885_BOARD_PROF_8000:
i2c_bus = &dev->i2c_bus[0];
@@ -1668,15 +1544,15 @@
&prof_8000_stv090x_config,
&i2c_bus->i2c_adap,
STV090x_DEMODULATOR_0);
- if (fe0->dvb.frontend == NULL)
- break;
- if (!dvb_attach(stb6100_attach,
- fe0->dvb.frontend,
- &prof_8000_stb6100_config,
- &i2c_bus->i2c_adap))
- goto frontend_detach;
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(stb6100_attach,
+ fe0->dvb.frontend,
+ &prof_8000_stb6100_config,
+ &i2c_bus->i2c_adap))
+ goto frontend_detach;
- fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage;
+ fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage;
+ }
break;
case CX23885_BOARD_HAUPPAUGE_HVR4400:
i2c_bus = &dev->i2c_bus[0];
@@ -1687,31 +1563,30 @@
fe0->dvb.frontend = dvb_attach(tda10071_attach,
&hauppauge_tda10071_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
- &i2c_bus->i2c_adap,
- &hauppauge_a8293_config))
- goto frontend_detach;
+ if (fe0->dvb.frontend != NULL) {
+ if (!dvb_attach(a8293_attach, fe0->dvb.frontend,
+ &i2c_bus->i2c_adap,
+ &hauppauge_a8293_config))
+ goto frontend_detach;
+ }
break;
/* port c */
case 2:
fe0->dvb.frontend = dvb_attach(si2165_attach,
&hauppauge_hvr4400_si2165_config,
&i2c_bus->i2c_adap);
- if (fe0->dvb.frontend == NULL)
- break;
- fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
- if (!dvb_attach(tda18271_attach,
- fe0->dvb.frontend,
- 0x60, &i2c_bus2->i2c_adap,
- &hauppauge_hvr4400_tuner_config))
- goto frontend_detach;
+ if (fe0->dvb.frontend != NULL) {
+ fe0->dvb.frontend->ops.i2c_gate_ctrl = NULL;
+ if (!dvb_attach(tda18271_attach,
+ fe0->dvb.frontend,
+ 0x60, &i2c_bus2->i2c_adap,
+ &hauppauge_hvr4400_tuner_config))
+ goto frontend_detach;
+ }
break;
}
break;
case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_S950:
i2c_bus = &dev->i2c_bus[0];
i2c_bus2 = &dev->i2c_bus[1];
switch (port->nr) {
@@ -1725,7 +1600,6 @@
break;
/* attach tuner */
- memset(&m88ts2022_config, 0, sizeof(m88ts2022_config));
m88ts2022_config.fe = fe0->dvb.frontend;
m88ts2022_config.clock = 27000000;
memset(&info, 0, sizeof(struct i2c_board_info));
@@ -1761,7 +1635,6 @@
/* port c - terrestrial/cable */
case 2:
/* attach frontend */
- memset(&si2168_config, 0, sizeof(si2168_config));
si2168_config.i2c_adapter = &adapter;
si2168_config.fe = &fe0->dvb.frontend;
si2168_config.ts_mode = SI2168_TS_SERIAL;
@@ -1781,7 +1654,6 @@
port->i2c_client_demod = client_demod;
/* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = fe0->dvb.frontend;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
@@ -1805,201 +1677,6 @@
break;
}
break;
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_TT_CT2_4500_CI:
- i2c_bus = &dev->i2c_bus[1];
- i2c_bus2 = &dev->i2c_bus[0];
-
- /* attach frontend */
- memset(&si2168_config, 0, sizeof(si2168_config));
- si2168_config.i2c_adapter = &adapter;
- si2168_config.fe = &fe0->dvb.frontend;
- si2168_config.ts_mode = SI2168_TS_PARALLEL;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
- info.addr = 0x64;
- info.platform_data = &si2168_config;
- request_module(info.type);
- client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
- if (client_demod == NULL ||
- client_demod->dev.driver == NULL)
- goto frontend_detach;
- if (!try_module_get(client_demod->dev.driver->owner)) {
- i2c_unregister_device(client_demod);
- goto frontend_detach;
- }
- port->i2c_client_demod = client_demod;
-
- /* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
- si2157_config.fe = fe0->dvb.frontend;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2157", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &si2157_config;
- request_module(info.type);
- client_tuner = i2c_new_device(adapter, &info);
- if (client_tuner == NULL ||
- client_tuner->dev.driver == NULL) {
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- goto frontend_detach;
- }
- if (!try_module_get(client_tuner->dev.driver->owner)) {
- i2c_unregister_device(client_tuner);
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- goto frontend_detach;
- }
- port->i2c_client_tuner = client_tuner;
- break;
- case CX23885_BOARD_DVBSKY_S950C:
- i2c_bus = &dev->i2c_bus[1];
- i2c_bus2 = &dev->i2c_bus[0];
-
- /* attach frontend */
- fe0->dvb.frontend = dvb_attach(m88ds3103_attach,
- &dvbsky_s950c_m88ds3103_config,
- &i2c_bus->i2c_adap, &adapter);
- if (fe0->dvb.frontend == NULL)
- break;
-
- /* attach tuner */
- memset(&m88ts2022_config, 0, sizeof(m88ts2022_config));
- m88ts2022_config.fe = fe0->dvb.frontend;
- m88ts2022_config.clock = 27000000;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &m88ts2022_config;
- request_module(info.type);
- client_tuner = i2c_new_device(adapter, &info);
- if (client_tuner == NULL ||
- client_tuner->dev.driver == NULL)
- goto frontend_detach;
- if (!try_module_get(client_tuner->dev.driver->owner)) {
- i2c_unregister_device(client_tuner);
- goto frontend_detach;
- }
-
- /* delegate signal strength measurement to tuner */
- fe0->dvb.frontend->ops.read_signal_strength =
- fe0->dvb.frontend->ops.tuner_ops.get_rf_strength;
-
- port->i2c_client_tuner = client_tuner;
- break;
- case CX23885_BOARD_DVBSKY_S952:
- switch (port->nr) {
- /* port b */
- case 1:
- i2c_bus = &dev->i2c_bus[1];
- p_m88ds3103_config = &dvbsky_t9580_m88ds3103_config;
- p_set_voltage = dvbsky_t9580_set_voltage;
- break;
- /* port c */
- case 2:
- i2c_bus = &dev->i2c_bus[0];
- p_m88ds3103_config = &dvbsky_s952_portc_m88ds3103_config;
- p_set_voltage = dvbsky_s952_portc_set_voltage;
- break;
- }
-
- /* attach frontend */
- fe0->dvb.frontend = dvb_attach(m88ds3103_attach,
- p_m88ds3103_config,
- &i2c_bus->i2c_adap, &adapter);
- if (fe0->dvb.frontend == NULL)
- break;
-
- /* attach tuner */
- memset(&m88ts2022_config, 0, sizeof(m88ts2022_config));
- m88ts2022_config.fe = fe0->dvb.frontend;
- m88ts2022_config.clock = 27000000;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &m88ts2022_config;
- request_module(info.type);
- client_tuner = i2c_new_device(adapter, &info);
- if (client_tuner == NULL ||
- client_tuner->dev.driver == NULL)
- goto frontend_detach;
- if (!try_module_get(client_tuner->dev.driver->owner)) {
- i2c_unregister_device(client_tuner);
- goto frontend_detach;
- }
-
- /* delegate signal strength measurement to tuner */
- fe0->dvb.frontend->ops.read_signal_strength =
- fe0->dvb.frontend->ops.tuner_ops.get_rf_strength;
-
- /*
- * for setting the voltage we need to set GPIOs on
- * the card.
- */
- port->fe_set_voltage =
- fe0->dvb.frontend->ops.set_voltage;
- fe0->dvb.frontend->ops.set_voltage = p_set_voltage;
-
- port->i2c_client_tuner = client_tuner;
- break;
- case CX23885_BOARD_DVBSKY_T982:
- memset(&si2168_config, 0, sizeof(si2168_config));
- switch (port->nr) {
- /* port b */
- case 1:
- i2c_bus = &dev->i2c_bus[1];
- si2168_config.ts_mode = SI2168_TS_PARALLEL;
- break;
- /* port c */
- case 2:
- i2c_bus = &dev->i2c_bus[0];
- si2168_config.ts_mode = SI2168_TS_SERIAL;
- break;
- }
-
- /* attach frontend */
- si2168_config.i2c_adapter = &adapter;
- si2168_config.fe = &fe0->dvb.frontend;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
- info.addr = 0x64;
- info.platform_data = &si2168_config;
- request_module(info.type);
- client_demod = i2c_new_device(&i2c_bus->i2c_adap, &info);
- if (client_demod == NULL ||
- client_demod->dev.driver == NULL)
- goto frontend_detach;
- if (!try_module_get(client_demod->dev.driver->owner)) {
- i2c_unregister_device(client_demod);
- goto frontend_detach;
- }
- port->i2c_client_demod = client_demod;
-
- /* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
- si2157_config.fe = fe0->dvb.frontend;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2157", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &si2157_config;
- request_module(info.type);
- client_tuner = i2c_new_device(adapter, &info);
- if (client_tuner == NULL ||
- client_tuner->dev.driver == NULL) {
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- goto frontend_detach;
- }
- if (!try_module_get(client_tuner->dev.driver->owner)) {
- i2c_unregister_device(client_tuner);
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- port->i2c_client_demod = NULL;
- goto frontend_detach;
- }
- port->i2c_client_tuner = client_tuner;
- break;
default:
printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
" isn't supported yet\n",
@@ -2074,10 +1751,7 @@
memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xa0, 6);
break;
}
- case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_S950:
- case CX23885_BOARD_DVBSKY_S952:
- case CX23885_BOARD_DVBSKY_T982: {
+ case CX23885_BOARD_DVBSKY_T9580: {
u8 eeprom[256]; /* 24C02 i2c eeprom */
if (port->nr > 2)
@@ -2087,67 +1761,12 @@
dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
sizeof(eeprom));
- printk(KERN_INFO "%s port %d MAC address: %pM\n",
- cx23885_boards[dev->board].name, port->nr,
- eeprom + 0xc0 + (port->nr-1) * 8);
+ printk(KERN_INFO "DVBSky T9580 port %d MAC address: %pM\n",
+ port->nr, eeprom + 0xc0 + (port->nr-1) * 8);
memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0 +
(port->nr-1) * 8, 6);
break;
}
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_TT_CT2_4500_CI: {
- u8 eeprom[256]; /* 24C02 i2c eeprom */
-
- /* attach CI */
- memset(&sp2_config, 0, sizeof(sp2_config));
- sp2_config.dvb_adap = &port->frontends.adapter;
- sp2_config.priv = port;
- sp2_config.ci_control = cx23885_sp2_ci_ctrl;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "sp2", I2C_NAME_SIZE);
- info.addr = 0x40;
- info.platform_data = &sp2_config;
- request_module(info.type);
- client_ci = i2c_new_device(&i2c_bus2->i2c_adap, &info);
- if (client_ci == NULL ||
- client_ci->dev.driver == NULL) {
- if (client_tuner) {
- module_put(client_tuner->dev.driver->owner);
- i2c_unregister_device(client_tuner);
- }
- if (client_demod) {
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- }
- goto frontend_detach;
- }
- if (!try_module_get(client_ci->dev.driver->owner)) {
- i2c_unregister_device(client_ci);
- if (client_tuner) {
- module_put(client_tuner->dev.driver->owner);
- i2c_unregister_device(client_tuner);
- }
- if (client_demod) {
- module_put(client_demod->dev.driver->owner);
- i2c_unregister_device(client_demod);
- }
- goto frontend_detach;
- }
- port->i2c_client_ci = client_ci;
-
- if (port->nr != 1)
- break;
-
- /* Read entire EEPROM */
- dev->i2c_bus[0].i2c_client.addr = 0xa0 >> 1;
- tveeprom_read(&dev->i2c_bus[0].i2c_client, eeprom,
- sizeof(eeprom));
- printk(KERN_INFO "%s MAC address: %pM\n",
- cx23885_boards[dev->board].name, eeprom + 0xc0);
- memcpy(port->frontends.adapter.proposed_mac, eeprom + 0xc0, 6);
- break;
- }
}
return ret;
@@ -2188,7 +1807,7 @@
fe0 = vb2_dvb_get_frontend(&port->frontends, i);
if (!fe0)
- return -EINVAL;
+ err = -EINVAL;
dprintk(1, "%s\n", __func__);
dprintk(1, " ->probed by Card=%d Name=%s, PCI %02x:%02x\n",
@@ -2231,13 +1850,6 @@
struct vb2_dvb_frontend *fe0;
struct i2c_client *client;
- /* remove I2C client for CI */
- client = port->i2c_client_ci;
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
-
/* remove I2C client for tuner */
client = port->i2c_client_tuner;
if (client) {
diff --git a/drivers/media/pci/cx23885/cx23885-input.c b/drivers/media/pci/cx23885/cx23885-input.c
index 088799c..9d37fe6 100644
--- a/drivers/media/pci/cx23885/cx23885-input.c
+++ b/drivers/media/pci/cx23885/cx23885-input.c
@@ -87,13 +87,6 @@
case CX23885_BOARD_MYGICA_X8507:
case CX23885_BOARD_TBS_6980:
case CX23885_BOARD_TBS_6981:
- case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_TT_CT2_4500_CI:
- case CX23885_BOARD_DVBSKY_S950:
- case CX23885_BOARD_DVBSKY_S952:
- case CX23885_BOARD_DVBSKY_T982:
/*
* The only boards we handle right now. However other boards
* using the CX2388x integrated IR controller should be similar
@@ -146,13 +139,6 @@
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_MYGICA_X8507:
- case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_TT_CT2_4500_CI:
- case CX23885_BOARD_DVBSKY_S950:
- case CX23885_BOARD_DVBSKY_S952:
- case CX23885_BOARD_DVBSKY_T982:
/*
* The IR controller on this board only returns pulse widths.
* Any other mode setting will fail to set up the device.
@@ -319,23 +305,6 @@
/* A guess at the remote */
rc_map = RC_MAP_TBS_NEC;
break;
- case CX23885_BOARD_DVBSKY_T9580:
- case CX23885_BOARD_DVBSKY_T980C:
- case CX23885_BOARD_DVBSKY_S950C:
- case CX23885_BOARD_DVBSKY_S950:
- case CX23885_BOARD_DVBSKY_S952:
- case CX23885_BOARD_DVBSKY_T982:
- /* Integrated CX23885 IR controller */
- driver_type = RC_DRIVER_IR_RAW;
- allowed_protos = RC_BIT_ALL;
- rc_map = RC_MAP_DVBSKY;
- break;
- case CX23885_BOARD_TT_CT2_4500_CI:
- /* Integrated CX23885 IR controller */
- driver_type = RC_DRIVER_IR_RAW;
- allowed_protos = RC_BIT_ALL;
- rc_map = RC_MAP_TT_1500;
- break;
default:
return -ENODEV;
}
diff --git a/drivers/media/pci/cx23885/cx23885-vbi.c b/drivers/media/pci/cx23885/cx23885-vbi.c
index d362d38..a7c6ef8 100644
--- a/drivers/media/pci/cx23885/cx23885-vbi.c
+++ b/drivers/media/pci/cx23885/cx23885-vbi.c
@@ -132,7 +132,6 @@
lines = VBI_NTSC_LINE_COUNT;
*num_planes = 1;
sizes[0] = lines * VBI_LINE_LENGTH * 2;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
@@ -143,6 +142,7 @@
struct cx23885_buffer, vb);
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
unsigned lines = VBI_PAL_LINE_COUNT;
+ int ret;
if (dev->tvnorm & V4L2_STD_525_60)
lines = VBI_NTSC_LINE_COUNT;
@@ -151,6 +151,10 @@
return -EINVAL;
vb2_set_plane_payload(vb, 0, lines * VBI_LINE_LENGTH * 2);
+ ret = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+ if (!ret)
+ return -EIO;
+
cx23885_risc_vbibuffer(dev->pci, &buf->risc,
sgt->sgl,
0, VBI_LINE_LENGTH * lines,
@@ -161,10 +165,14 @@
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf = container_of(vb,
struct cx23885_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
+
+ dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
/*
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index 2cd103d..f10469a 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -323,7 +323,6 @@
*num_planes = 1;
sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
@@ -335,6 +334,7 @@
u32 line0_offset, line1_offset;
struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
int field_tff;
+ int ret;
buf->bpl = (dev->width * dev->fmt->depth) >> 3;
@@ -342,6 +342,10 @@
return -EINVAL;
vb2_set_plane_payload(vb, 0, dev->height * buf->bpl);
+ ret = dma_map_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
+ if (!ret)
+ return -EIO;
+
switch (dev->field) {
case V4L2_FIELD_TOP:
cx23885_risc_buffer(dev->pci, &buf->risc,
@@ -409,10 +413,14 @@
static void buffer_finish(struct vb2_buffer *vb)
{
+ struct cx23885_dev *dev = vb->vb2_queue->drv_priv;
struct cx23885_buffer *buf = container_of(vb,
struct cx23885_buffer, vb);
+ struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
cx23885_free_buffer(vb->vb2_queue->drv_priv, buf);
+
+ dma_unmap_sg(&dev->pci->dev, sgt->sgl, sgt->nents, DMA_FROM_DEVICE);
}
/*
@@ -600,7 +608,7 @@
dev->field = f->fmt.pix.field;
dprintk(2, "%s() width=%d height=%d field=%d\n", __func__,
dev->width, dev->height, dev->field);
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
call_all(dev, video, s_mbus_fmt, &mbus_fmt);
v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
/* s_mbus_fmt overwrites f->fmt.pix.field, restore it */
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index f55cd12..6c35e61 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -93,12 +93,6 @@
#define CX23885_BOARD_HAUPPAUGE_IMPACTVCBE 43
#define CX23885_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL_EXP2 44
#define CX23885_BOARD_DVBSKY_T9580 45
-#define CX23885_BOARD_DVBSKY_T980C 46
-#define CX23885_BOARD_DVBSKY_S950C 47
-#define CX23885_BOARD_TT_CT2_4500_CI 48
-#define CX23885_BOARD_DVBSKY_S950 49
-#define CX23885_BOARD_DVBSKY_S952 50
-#define CX23885_BOARD_DVBSKY_T982 51
#define GPIO_0 0x00000001
#define GPIO_1 0x00000002
@@ -302,7 +296,6 @@
struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
- struct i2c_client *i2c_client_ci;
int (*set_frontend)(struct dvb_frontend *fe);
int (*fe_set_voltage)(struct dvb_frontend *fe,
@@ -425,7 +418,6 @@
struct vb2_queue vb2_vidq;
struct cx23885_dmaqueue vbiq;
struct vb2_queue vb2_vbiq;
- void *alloc_ctx;
spinlock_t slock;
diff --git a/drivers/media/pci/cx25821/cx25821-core.c b/drivers/media/pci/cx25821/cx25821-core.c
index 389fffd..e81173c 100644
--- a/drivers/media/pci/cx25821/cx25821-core.c
+++ b/drivers/media/pci/cx25821/cx25821-core.c
@@ -996,7 +996,7 @@
for (line = 0; line < lines; line++) {
while (offset && offset >= sg_dma_len(sg)) {
offset -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
if (bpl <= sg_dma_len(sg) - offset) {
/* fits into current chunk */
@@ -1014,14 +1014,14 @@
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= (sg_dma_len(sg) - offset);
offset = 0;
- sg = sg_next(sg);
+ sg++;
while (todo > sg_dma_len(sg)) {
*(rp++) = cpu_to_le32(RISC_WRITE |
sg_dma_len(sg));
*(rp++) = cpu_to_le32(sg_dma_address(sg));
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
*(rp++) = cpu_to_le32(sg_dma_address(sg));
@@ -1101,7 +1101,7 @@
for (line = 0; line < lines; line++) {
while (offset && offset >= sg_dma_len(sg)) {
offset -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
if (lpi && line > 0 && !(line % lpi))
@@ -1125,14 +1125,14 @@
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= (sg_dma_len(sg) - offset);
offset = 0;
- sg = sg_next(sg);
+ sg++;
while (todo > sg_dma_len(sg)) {
*(rp++) = cpu_to_le32(RISC_WRITE |
sg_dma_len(sg));
*(rp++) = cpu_to_le32(sg_dma_address(sg));
*(rp++) = cpu_to_le32(0); /* bits 63-32 */
todo -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
*(rp++) = cpu_to_le32(RISC_WRITE | RISC_EOL | todo);
*(rp++) = cpu_to_le32(sg_dma_address(sg));
diff --git a/drivers/media/pci/cx88/Kconfig b/drivers/media/pci/cx88/Kconfig
index 4a7d489..3d30f90 100644
--- a/drivers/media/pci/cx88/Kconfig
+++ b/drivers/media/pci/cx88/Kconfig
@@ -3,7 +3,8 @@
depends on m
depends on VIDEO_DEV && PCI && I2C && RC_CORE
depends on I2C_ALGOBIT
- select VIDEOBUF2_DMA_SG
+ select VIDEO_BTCX
+ select VIDEOBUF_DMA_SG
select VIDEO_TUNER
select VIDEO_TVEEPROM
select VIDEO_WM8775 if MEDIA_SUBDRV_AUTOSELECT
@@ -48,7 +49,7 @@
tristate "DVB/ATSC Support for cx2388x based TV cards"
depends on m
depends on VIDEO_CX88 && DVB_CORE
- select VIDEOBUF2_DVB
+ select VIDEOBUF_DVB
select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/pci/cx88/Makefile b/drivers/media/pci/cx88/Makefile
index 97b6f50..a1e2796 100644
--- a/drivers/media/pci/cx88/Makefile
+++ b/drivers/media/pci/cx88/Makefile
@@ -11,6 +11,7 @@
obj-$(CPTCFG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
ccflags-y += -I$(backport_srctree)/drivers/media/i2c
+ccflags-y += -I$(backport_srctree)/drivers/media/common
ccflags-y += -I$(backport_srctree)/drivers/media/tuners
ccflags-y += -I$(backport_srctree)/drivers/media/dvb-core
ccflags-y += -I$(backport_srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/pci/cx88/cx88-alsa.c b/drivers/media/pci/cx88/cx88-alsa.c
index 7f8dc60..a72579a 100644
--- a/drivers/media/pci/cx88/cx88-alsa.c
+++ b/drivers/media/pci/cx88/cx88-alsa.c
@@ -61,11 +61,8 @@
struct cx88_audio_buffer {
unsigned int bpl;
- struct cx88_riscmem risc;
- void *vaddr;
- struct scatterlist *sglist;
- int sglen;
- int nr_pages;
+ struct btcx_riscmem risc;
+ struct videobuf_dmabuf dma;
};
struct cx88_audio_dev {
@@ -87,6 +84,8 @@
unsigned int period_size;
unsigned int num_periods;
+ struct videobuf_dmabuf *dma_risc;
+
struct cx88_audio_buffer *buf;
struct snd_pcm_substream *substream;
@@ -291,97 +290,19 @@
return IRQ_RETVAL(handled);
}
-static int cx88_alsa_dma_init(struct cx88_audio_dev *chip, int nr_pages)
-{
- struct cx88_audio_buffer *buf = chip->buf;
- struct page *pg;
- int i;
-
- buf->vaddr = vmalloc_32(nr_pages << PAGE_SHIFT);
- if (NULL == buf->vaddr) {
- dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
- return -ENOMEM;
- }
-
- dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
- (unsigned long)buf->vaddr,
- nr_pages << PAGE_SHIFT);
-
- memset(buf->vaddr, 0, nr_pages << PAGE_SHIFT);
- buf->nr_pages = nr_pages;
-
- buf->sglist = vzalloc(buf->nr_pages * sizeof(*buf->sglist));
- if (NULL == buf->sglist)
- goto vzalloc_err;
-
- sg_init_table(buf->sglist, buf->nr_pages);
- for (i = 0; i < buf->nr_pages; i++) {
- pg = vmalloc_to_page(buf->vaddr + i * PAGE_SIZE);
- if (NULL == pg)
- goto vmalloc_to_page_err;
- sg_set_page(&buf->sglist[i], pg, PAGE_SIZE, 0);
- }
- return 0;
-
-vmalloc_to_page_err:
- vfree(buf->sglist);
- buf->sglist = NULL;
-vzalloc_err:
- vfree(buf->vaddr);
- buf->vaddr = NULL;
- return -ENOMEM;
-}
-
-static int cx88_alsa_dma_map(struct cx88_audio_dev *dev)
-{
- struct cx88_audio_buffer *buf = dev->buf;
-
- buf->sglen = dma_map_sg(&dev->pci->dev, buf->sglist,
- buf->nr_pages, PCI_DMA_FROMDEVICE);
-
- if (0 == buf->sglen) {
- pr_warn("%s: cx88_alsa_map_sg failed\n", __func__);
- return -ENOMEM;
- }
- return 0;
-}
-
-static int cx88_alsa_dma_unmap(struct cx88_audio_dev *dev)
-{
- struct cx88_audio_buffer *buf = dev->buf;
-
- if (!buf->sglen)
- return 0;
-
- dma_unmap_sg(&dev->pci->dev, buf->sglist, buf->sglen, PCI_DMA_FROMDEVICE);
- buf->sglen = 0;
- return 0;
-}
-
-static int cx88_alsa_dma_free(struct cx88_audio_buffer *buf)
-{
- vfree(buf->sglist);
- buf->sglist = NULL;
- vfree(buf->vaddr);
- buf->vaddr = NULL;
- return 0;
-}
-
static int dsp_buffer_free(snd_cx88_card_t *chip)
{
- struct cx88_riscmem *risc = &chip->buf->risc;
-
BUG_ON(!chip->dma_size);
dprintk(2,"Freeing buffer\n");
- cx88_alsa_dma_unmap(chip);
- cx88_alsa_dma_free(chip->buf);
- if (risc->cpu)
- pci_free_consistent(chip->pci, risc->size, risc->cpu, risc->dma);
+ videobuf_dma_unmap(&chip->pci->dev, chip->dma_risc);
+ videobuf_dma_free(chip->dma_risc);
+ btcx_riscmem_free(chip->pci,&chip->buf->risc);
kfree(chip->buf);
- chip->buf = NULL;
+ chip->dma_risc = NULL;
+ chip->dma_size = 0;
return 0;
}
@@ -466,6 +387,7 @@
struct snd_pcm_hw_params * hw_params)
{
snd_cx88_card_t *chip = snd_pcm_substream_chip(substream);
+ struct videobuf_dmabuf *dma;
struct cx88_audio_buffer *buf;
int ret;
@@ -486,19 +408,20 @@
if (NULL == buf)
return -ENOMEM;
- chip->buf = buf;
buf->bpl = chip->period_size;
- ret = cx88_alsa_dma_init(chip,
+ dma = &buf->dma;
+ videobuf_dma_init(dma);
+ ret = videobuf_dma_init_kernel(dma, PCI_DMA_FROMDEVICE,
(PAGE_ALIGN(chip->dma_size) >> PAGE_SHIFT));
if (ret < 0)
goto error;
- ret = cx88_alsa_dma_map(chip);
+ ret = videobuf_dma_map(&chip->pci->dev, dma);
if (ret < 0)
goto error;
- ret = cx88_risc_databuffer(chip->pci, &buf->risc, buf->sglist,
+ ret = cx88_risc_databuffer(chip->pci, &buf->risc, dma->sglist,
chip->period_size, chip->num_periods, 1);
if (ret < 0)
goto error;
@@ -507,7 +430,10 @@
buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP|RISC_IRQ1|RISC_CNT_INC);
buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- substream->runtime->dma_area = chip->buf->vaddr;
+ chip->buf = buf;
+ chip->dma_risc = dma;
+
+ substream->runtime->dma_area = chip->dma_risc->vaddr;
substream->runtime->dma_bytes = chip->dma_size;
substream->runtime->dma_addr = 0;
return 0;
diff --git a/drivers/media/pci/cx88/cx88-blackbird.c b/drivers/media/pci/cx88/cx88-blackbird.c
index d3c79d9..150bb76 100644
--- a/drivers/media/pci/cx88/cx88-blackbird.c
+++ b/drivers/media/pci/cx88/cx88-blackbird.c
@@ -45,6 +45,10 @@
MODULE_LICENSE("GPL");
MODULE_VERSION(CX88_VERSION);
+static unsigned int mpegbufs = 32;
+module_param(mpegbufs,int,0644);
+MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
+
static unsigned int debug;
module_param(debug,int,0644);
MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
@@ -322,13 +326,13 @@
memory_read(dev->core, dev->mailbox - 4, &value);
if (value != 0x12345678) {
dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
- return -EIO;
+ return -1;
}
memory_read(dev->core, dev->mailbox, &flag);
if (flag) {
dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
- return -EIO;
+ return -1;
}
flag |= 1; /* tell 'em we're working on it */
@@ -348,14 +352,14 @@
memory_write(dev->core, dev->mailbox, flag);
/* wait for firmware to handle the API command */
- timeout = jiffies + msecs_to_jiffies(1000);
+ timeout = jiffies + msecs_to_jiffies(10);
for (;;) {
memory_read(dev->core, dev->mailbox, &flag);
if (0 != (flag & 4))
break;
if (time_after(jiffies,timeout)) {
- dprintk(0, "ERROR: API Mailbox timeout %x\n", command);
- return -EIO;
+ dprintk(0, "ERROR: API Mailbox timeout\n");
+ return -1;
}
udelay(10);
}
@@ -416,7 +420,7 @@
}
}
dprintk(0, "Mailbox signature values not found!\n");
- return -EIO;
+ return -1;
}
static int blackbird_load_firmware(struct cx8802_dev *dev)
@@ -428,7 +432,7 @@
int i, retval = 0;
u32 value = 0;
u32 checksum = 0;
- __le32 *dataptr;
+ u32 *dataptr;
retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
@@ -445,28 +449,29 @@
if (retval != 0) {
- pr_err("Hotplug firmware request failed (%s).\n",
+ dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
CX2341X_FIRM_ENC_FILENAME);
- pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
- return -EIO;
+ dprintk(0, "Please fix your hotplug setup, the board will "
+ "not work without firmware loaded!\n");
+ return -1;
}
if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
- pr_err("Firmware size mismatch (have %zd, expected %d)\n",
+ dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
release_firmware(firmware);
- return -EINVAL;
+ return -1;
}
if (0 != memcmp(firmware->data, magic, 8)) {
- pr_err("Firmware magic mismatch, wrong file?\n");
+ dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
release_firmware(firmware);
- return -EINVAL;
+ return -1;
}
/* transfer to the chip */
dprintk(1,"Loading firmware ...\n");
- dataptr = (__le32 *)firmware->data;
+ dataptr = (u32*)firmware->data;
for (i = 0; i < (firmware->size >> 2); i++) {
value = le32_to_cpu(*dataptr);
checksum += ~value;
@@ -479,11 +484,12 @@
memory_read(dev->core, i, &value);
checksum -= ~value;
}
- release_firmware(firmware);
if (checksum) {
- pr_err("Firmware load might have failed (checksum mismatch).\n");
- return -EIO;
+ dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
+ release_firmware(firmware);
+ return -1;
}
+ release_firmware(firmware);
dprintk(0, "Firmware upload successful.\n");
retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
@@ -515,14 +521,12 @@
static void blackbird_codec_settings(struct cx8802_dev *dev)
{
- struct cx88_core *core = dev->core;
-
/* assign frame size */
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
- core->height, core->width);
+ dev->height, dev->width);
- dev->cxhdl.width = core->width;
- dev->cxhdl.height = core->height;
+ dev->cxhdl.width = dev->width;
+ dev->cxhdl.height = dev->height;
cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
cx2341x_handler_setup(&dev->cxhdl);
}
@@ -536,6 +540,9 @@
dprintk(1,"Initialize codec\n");
retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
if (retval < 0) {
+
+ dev->mpeg_active = 0;
+
/* ping was not successful, reset and upload firmware */
cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
@@ -582,8 +589,9 @@
return 0;
}
-static int blackbird_start_codec(struct cx8802_dev *dev)
+static int blackbird_start_codec(struct file *file, void *priv)
{
+ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
struct cx88_core *core = dev->core;
/* start capturing to the host interface */
u32 reg;
@@ -619,6 +627,7 @@
BLACKBIRD_RAW_BITS_NONE
);
+ dev->mpeg_active = 1;
return 0;
}
@@ -632,137 +641,51 @@
cx2341x_handler_set_busy(&dev->cxhdl, 0);
+ dev->mpeg_active = 0;
return 0;
}
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
- unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+static int bb_buf_setup(struct videobuf_queue *q,
+ unsigned int *count, unsigned int *size)
{
- struct cx8802_dev *dev = q->drv_priv;
+ struct cx8802_fh *fh = q->priv_data;
- *num_planes = 1;
- dev->ts_packet_size = 188 * 4;
- dev->ts_packet_count = 32;
- sizes[0] = dev->ts_packet_size * dev->ts_packet_count;
- alloc_ctxs[0] = dev->alloc_ctx;
+ fh->dev->ts_packet_size = 188 * 4; /* was: 512 */
+ fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
+
+ *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
+ *count = fh->dev->ts_packet_count;
return 0;
}
-static int buffer_prepare(struct vb2_buffer *vb)
+static int
+bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ enum v4l2_field field)
{
- struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-
- return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
+ struct cx8802_fh *fh = q->priv_data;
+ return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
}
-static void buffer_finish(struct vb2_buffer *vb)
+static void
+bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
- struct cx88_riscmem *risc = &buf->risc;
-
- if (risc->cpu)
- pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
- memset(risc, 0, sizeof(*risc));
+ struct cx8802_fh *fh = q->priv_data;
+ cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
}
-static void buffer_queue(struct vb2_buffer *vb)
+static void
+bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-
- cx8802_buf_queue(dev, buf);
+ cx88_free_buffer(q, (struct cx88_buffer*)vb);
}
-static int start_streaming(struct vb2_queue *q, unsigned int count)
-{
- struct cx8802_dev *dev = q->drv_priv;
- struct cx88_dmaqueue *dmaq = &dev->mpegq;
- struct cx8802_driver *drv;
- struct cx88_buffer *buf;
- unsigned long flags;
- int err;
-
- /* Make sure we can acquire the hardware */
- drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
- if (!drv) {
- dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
- err = -ENODEV;
- goto fail;
- }
-
- err = drv->request_acquire(drv);
- if (err != 0) {
- dprintk(1, "%s: Unable to acquire hardware, %d\n", __func__, err);
- goto fail;
- }
-
- if (blackbird_initialize_codec(dev) < 0) {
- drv->request_release(drv);
- err = -EINVAL;
- goto fail;
- }
-
- err = blackbird_start_codec(dev);
- if (err == 0) {
- buf = list_entry(dmaq->active.next, struct cx88_buffer, list);
- cx8802_start_dma(dev, dmaq, buf);
- return 0;
- }
-
-fail:
- spin_lock_irqsave(&dev->slock, flags);
- while (!list_empty(&dmaq->active)) {
- struct cx88_buffer *buf = list_entry(dmaq->active.next,
- struct cx88_buffer, list);
-
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_QUEUED);
- }
- spin_unlock_irqrestore(&dev->slock, flags);
- return err;
-}
-
-static void stop_streaming(struct vb2_queue *q)
-{
- struct cx8802_dev *dev = q->drv_priv;
- struct cx88_dmaqueue *dmaq = &dev->mpegq;
- struct cx8802_driver *drv = NULL;
- unsigned long flags;
-
- cx8802_cancel_buffers(dev);
- blackbird_stop_codec(dev);
-
- /* Make sure we release the hardware */
- drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
- WARN_ON(!drv);
- if (drv)
- drv->request_release(drv);
-
- spin_lock_irqsave(&dev->slock, flags);
- while (!list_empty(&dmaq->active)) {
- struct cx88_buffer *buf = list_entry(dmaq->active.next,
- struct cx88_buffer, list);
-
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
- }
- spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-static struct vb2_ops blackbird_qops = {
- .queue_setup = queue_setup,
- .buf_prepare = buffer_prepare,
- .buf_finish = buffer_finish,
- .buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
- .start_streaming = start_streaming,
- .stop_streaming = stop_streaming,
+static struct videobuf_queue_ops blackbird_qops = {
+ .buf_setup = bb_buf_setup,
+ .buf_prepare = bb_buf_prepare,
+ .buf_queue = bb_buf_queue,
+ .buf_release = bb_buf_release,
};
/* ------------------------------------------------------------------ */
@@ -770,8 +693,8 @@
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
+ struct cx88_core *core = dev->core;
strcpy(cap->driver, "cx88_blackbird");
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
@@ -791,111 +714,131 @@
return 0;
}
-static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx8802_fh *fh = priv;
+ struct cx8802_dev *dev = fh->dev;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count;
+ f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.width = core->width;
- f->fmt.pix.height = core->height;
- f->fmt.pix.field = core->field;
+ f->fmt.pix.width = dev->width;
+ f->fmt.pix.height = dev->height;
+ f->fmt.pix.field = fh->mpegq.field;
+ dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
+ dev->width, dev->height, fh->mpegq.field );
return 0;
}
-static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
- unsigned maxw, maxh;
- enum v4l2_field field;
+ struct cx8802_fh *fh = priv;
+ struct cx8802_dev *dev = fh->dev;
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.sizeimage = dev->ts_packet_size * dev->ts_packet_count;
+ f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
-
- maxw = norm_maxw(core->tvnorm);
- maxh = norm_maxh(core->tvnorm);
-
- field = f->fmt.pix.field;
-
- switch (field) {
- case V4L2_FIELD_TOP:
- case V4L2_FIELD_BOTTOM:
- case V4L2_FIELD_INTERLACED:
- case V4L2_FIELD_SEQ_BT:
- case V4L2_FIELD_SEQ_TB:
- break;
- default:
- field = (f->fmt.pix.height > maxh / 2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_BOTTOM;
- break;
- }
- if (V4L2_FIELD_HAS_T_OR_B(field))
- maxh /= 2;
-
- v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
- &f->fmt.pix.height, 32, maxh, 0, 0);
- f->fmt.pix.field = field;
+ dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
+ dev->width, dev->height, fh->mpegq.field );
return 0;
}
-static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8802_dev *dev = video_drvdata(file);
+ struct cx8802_fh *fh = priv;
+ struct cx8802_dev *dev = fh->dev;
struct cx88_core *core = dev->core;
- if (vb2_is_busy(&dev->vb2_mpegq))
- return -EBUSY;
- if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) ||
- vb2_is_busy(&core->v4ldev->vb2_vbiq)))
- return -EBUSY;
- vidioc_try_fmt_vid_cap(file, priv, f);
- core->width = f->fmt.pix.width;
- core->height = f->fmt.pix.height;
- core->field = f->fmt.pix.field;
+ f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
+ f->fmt.pix.bytesperline = 0;
+ f->fmt.pix.sizeimage = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ dev->width = f->fmt.pix.width;
+ dev->height = f->fmt.pix.height;
+ fh->mpegq.field = f->fmt.pix.field;
cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
f->fmt.pix.height, f->fmt.pix.width);
+ dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
+ f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
return 0;
}
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+ struct cx8802_fh *fh = priv;
+ return (videobuf_reqbufs(&fh->mpegq, p));
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cx8802_fh *fh = priv;
+ return (videobuf_querybuf(&fh->mpegq, p));
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cx8802_fh *fh = priv;
+ return (videobuf_qbuf(&fh->mpegq, p));
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cx8802_fh *fh = priv;
+ return (videobuf_dqbuf(&fh->mpegq, p,
+ file->f_flags & O_NONBLOCK));
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx8802_fh *fh = priv;
+ struct cx8802_dev *dev = fh->dev;
+
+ if (!dev->mpeg_active)
+ blackbird_start_codec(file, fh);
+ return videobuf_streamon(&fh->mpegq);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cx8802_fh *fh = priv;
+ struct cx8802_dev *dev = fh->dev;
+
+ if (dev->mpeg_active)
+ blackbird_stop_codec(dev);
+ return videobuf_streamoff(&fh->mpegq);
+}
+
static int vidioc_s_frequency (struct file *file, void *priv,
const struct v4l2_frequency *f)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
- bool streaming;
+ struct cx8802_fh *fh = priv;
+ struct cx8802_dev *dev = fh->dev;
+ struct cx88_core *core = dev->core;
if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
if (unlikely(f->tuner != 0))
return -EINVAL;
- streaming = vb2_start_streaming_called(&dev->vb2_mpegq);
- if (streaming)
+ if (dev->mpeg_active)
blackbird_stop_codec(dev);
cx88_set_freq (core,f);
blackbird_initialize_codec(dev);
- cx88_set_scale(core, core->width, core->height,
- core->field);
- if (streaming)
- blackbird_start_codec(dev);
+ cx88_set_scale(dev->core, dev->width, dev->height,
+ fh->mpegq.field);
return 0;
}
static int vidioc_log_status (struct file *file, void *priv)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx8802_dev *dev = ((struct cx8802_fh *)priv)->dev;
+ struct cx88_core *core = dev->core;
char name[32 + 2];
snprintf(name, sizeof(name), "%s/2", core->name);
@@ -907,16 +850,15 @@
static int vidioc_enum_input (struct file *file, void *priv,
struct v4l2_input *i)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
return cx88_enum_input (core,i);
}
static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx8802_fh *fh = priv;
+ struct cx88_core *core = fh->dev->core;
if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
@@ -931,8 +873,7 @@
static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
*i = core->input;
return 0;
@@ -940,24 +881,24 @@
static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
if (i >= 4)
return -EINVAL;
if (0 == INPUT(i).type)
return -EINVAL;
+ mutex_lock(&core->lock);
cx88_newstation(core);
cx88_video_mux(core,i);
+ mutex_unlock(&core->lock);
return 0;
}
static int vidioc_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
u32 reg;
if (unlikely(UNSET == core->board.tuner_type))
@@ -979,8 +920,7 @@
static int vidioc_s_tuner (struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
if (UNSET == core->board.tuner_type)
return -EINVAL;
@@ -993,8 +933,7 @@
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
*tvnorm = core->tvnorm;
return 0;
@@ -1002,20 +941,155 @@
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
{
- struct cx8802_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
- return cx88_set_tvnorm(core, id);
+ mutex_lock(&core->lock);
+ cx88_set_tvnorm(core, id);
+ mutex_unlock(&core->lock);
+ return 0;
+}
+
+/* FIXME: cx88_ioctl_hook not implemented */
+
+static int mpeg_open(struct file *file)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct cx8802_dev *dev = video_drvdata(file);
+ struct cx8802_fh *fh;
+ struct cx8802_driver *drv = NULL;
+ int err;
+
+ dprintk( 1, "%s\n", __func__);
+
+ mutex_lock(&dev->core->lock);
+
+ /* Make sure we can acquire the hardware */
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+ if (!drv) {
+ dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
+ mutex_unlock(&dev->core->lock);
+ return -ENODEV;
+ }
+
+ err = drv->request_acquire(drv);
+ if (err != 0) {
+ dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
+ mutex_unlock(&dev->core->lock);
+ return err;
+ }
+
+ if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) {
+ drv->request_release(drv);
+ mutex_unlock(&dev->core->lock);
+ return -EINVAL;
+ }
+ dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+ if (NULL == fh) {
+ drv->request_release(drv);
+ mutex_unlock(&dev->core->lock);
+ return -ENOMEM;
+ }
+ v4l2_fh_init(&fh->fh, vdev);
+ file->private_data = fh;
+ fh->dev = dev;
+
+ videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx88_buffer),
+ fh, NULL);
+
+ /* FIXME: locking against other video device */
+ cx88_set_scale(dev->core, dev->width, dev->height,
+ fh->mpegq.field);
+
+ dev->core->mpeg_users++;
+ mutex_unlock(&dev->core->lock);
+ v4l2_fh_add(&fh->fh);
+ return 0;
+}
+
+static int mpeg_release(struct file *file)
+{
+ struct cx8802_fh *fh = file->private_data;
+ struct cx8802_dev *dev = fh->dev;
+ struct cx8802_driver *drv = NULL;
+
+ mutex_lock(&dev->core->lock);
+
+ if (dev->mpeg_active && dev->core->mpeg_users == 1)
+ blackbird_stop_codec(dev);
+
+ cx8802_cancel_buffers(fh->dev);
+ /* stop mpeg capture */
+ videobuf_stop(&fh->mpegq);
+
+ videobuf_mmap_free(&fh->mpegq);
+
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
+ file->private_data = NULL;
+ kfree(fh);
+
+ /* Make sure we release the hardware */
+ drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
+ WARN_ON(!drv);
+ if (drv)
+ drv->request_release(drv);
+
+ dev->core->mpeg_users--;
+
+ mutex_unlock(&dev->core->lock);
+
+ return 0;
+}
+
+static ssize_t
+mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+ struct cx8802_fh *fh = file->private_data;
+ struct cx8802_dev *dev = fh->dev;
+
+ if (!dev->mpeg_active)
+ blackbird_start_codec(file, fh);
+
+ return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
+ file->f_flags & O_NONBLOCK);
+}
+
+static unsigned int
+mpeg_poll(struct file *file, struct poll_table_struct *wait)
+{
+ unsigned long req_events = poll_requested_events(wait);
+ struct cx8802_fh *fh = file->private_data;
+ struct cx8802_dev *dev = fh->dev;
+
+ if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
+ blackbird_start_codec(file, fh);
+
+ return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
+}
+
+static int
+mpeg_mmap(struct file *file, struct vm_area_struct * vma)
+{
+ struct cx8802_fh *fh = file->private_data;
+
+ return videobuf_mmap_mapper(&fh->mpegq, vma);
}
static const struct v4l2_file_operations mpeg_fops =
{
.owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = vb2_fop_release,
- .read = vb2_fop_read,
- .poll = vb2_fop_poll,
- .mmap = vb2_fop_mmap,
+ .open = mpeg_open,
+ .release = mpeg_release,
+ .read = mpeg_read,
+ .poll = mpeg_poll,
+ .mmap = mpeg_mmap,
.unlocked_ioctl = video_ioctl2,
};
@@ -1025,12 +1099,12 @@
.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_reqbufs = vb2_ioctl_reqbufs,
- .vidioc_querybuf = vb2_ioctl_querybuf,
- .vidioc_qbuf = vb2_ioctl_qbuf,
- .vidioc_dqbuf = vb2_ioctl_dqbuf,
- .vidioc_streamon = vb2_ioctl_streamon,
- .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
.vidioc_s_frequency = vidioc_s_frequency,
.vidioc_log_status = vidioc_log_status,
.vidioc_enum_input = vidioc_enum_input,
@@ -1115,12 +1189,11 @@
{
int err;
- dev->mpeg_dev = cx88_vdev_init(dev->core, dev->pci,
- &cx8802_mpeg_template, "mpeg");
+ dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
+ &cx8802_mpeg_template,"mpeg");
dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
video_set_drvdata(dev->mpeg_dev, dev);
- dev->mpeg_dev->queue = &dev->vb2_mpegq;
- err = video_register_device(dev->mpeg_dev, VFL_TYPE_GRABBER, -1);
+ err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
if (err < 0) {
printk(KERN_INFO "%s/2: can't register mpeg device\n",
dev->core->name);
@@ -1137,7 +1210,6 @@
{
struct cx88_core *core = drv->core;
struct cx8802_dev *dev = core->dvbdev;
- struct vb2_queue *q;
int err;
dprintk( 1, "%s\n", __func__);
@@ -1151,9 +1223,15 @@
if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
goto fail_core;
+ dev->width = 720;
+ if (core->tvnorm & V4L2_STD_525_60) {
+ dev->height = 480;
+ } else {
+ dev->height = 576;
+ }
dev->cxhdl.port = CX2341X_PORT_STREAMING;
- dev->cxhdl.width = core->width;
- dev->cxhdl.height = core->height;
+ dev->cxhdl.width = dev->width;
+ dev->cxhdl.height = dev->height;
dev->cxhdl.func = blackbird_mbox_func;
dev->cxhdl.priv = dev;
err = cx2341x_handler_init(&dev->cxhdl, 36);
@@ -1172,30 +1250,13 @@
// init_controls(core);
cx88_set_tvnorm(core,core->tvnorm);
cx88_video_mux(core,0);
- cx2341x_handler_set_50hz(&dev->cxhdl, core->height == 576);
+ cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
cx2341x_handler_setup(&dev->cxhdl);
-
- q = &dev->vb2_mpegq;
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
- q->gfp_flags = GFP_DMA32;
- q->min_buffers_needed = 2;
- q->drv_priv = dev;
- q->buf_struct_size = sizeof(struct cx88_buffer);
- q->ops = &blackbird_qops;
- q->mem_ops = &vb2_dma_sg_memops;
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->lock = &core->lock;
-
- err = vb2_queue_init(q);
- if (err < 0)
- goto fail_core;
-
blackbird_register_video(dev);
return 0;
-fail_core:
+ fail_core:
return err;
}
diff --git a/drivers/media/pci/cx88/cx88-cards.c b/drivers/media/pci/cx88/cx88-cards.c
index 8f2556e..851754b 100644
--- a/drivers/media/pci/cx88/cx88-cards.c
+++ b/drivers/media/pci/cx88/cx88-cards.c
@@ -347,7 +347,7 @@
},
[CX88_BOARD_IODATA_GVVCP3PCI] = {
.name = "IODATA GV-VCP3/PCI",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -436,7 +436,7 @@
},
[CX88_BOARD_KWORLD_DVB_T] = {
.name = "KWorld/VStream XPert DVB-T",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -455,7 +455,7 @@
},
[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = {
.name = "DViCO FusionHDTV DVB-T1",
- .tuner_type = UNSET, /* No analog tuner */
+ .tuner_type = TUNER_ABSENT, /* No analog tuner */
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -542,7 +542,7 @@
},
[CX88_BOARD_HAUPPAUGE_DVB_T1] = {
.name = "Hauppauge Nova-T DVB-T",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -554,7 +554,7 @@
},
[CX88_BOARD_CONEXANT_DVB_T1] = {
.name = "Conexant DVB-T reference design",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -579,7 +579,7 @@
},
[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS] = {
.name = "DViCO FusionHDTV DVB-T Plus",
- .tuner_type = UNSET, /* No analog tuner */
+ .tuner_type = TUNER_ABSENT, /* No analog tuner */
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -596,7 +596,7 @@
},
[CX88_BOARD_DNTV_LIVE_DVB_T] = {
.name = "digitalnow DNTV Live! DVB-T",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -787,7 +787,7 @@
},
[CX88_BOARD_ADSTECH_DVB_T_PCI] = {
.name = "ADS Tech Instant TV DVB-T PCI",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -806,7 +806,7 @@
},
[CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = {
.name = "TerraTec Cinergy 1400 DVB-T",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.input = { {
.type = CX88_VMUX_DVB,
.vmux = 0,
@@ -924,7 +924,7 @@
},
[CX88_BOARD_WINFAST_DTV1000] = {
.name = "WinFast DTV1000-T",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -972,7 +972,7 @@
},
[CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1] = {
.name = "Hauppauge Nova-S-Plus DVB-S",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -998,7 +998,7 @@
},
[CX88_BOARD_HAUPPAUGE_NOVASE2_S1] = {
.name = "Hauppauge Nova-SE2 DVB-S",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1010,7 +1010,7 @@
},
[CX88_BOARD_KWORLD_DVBS_100] = {
.name = "KWorld DVB-S 100",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1102,7 +1102,7 @@
/* DTT 7579 Conexant CX22702-19 Conexant CX2388x */
/* Manenti Marco <marco_manenti@colman.it> */
.name = "KWorld/VStream XPert DVB-T with cx22702",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1121,7 +1121,7 @@
},
[CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL] = {
.name = "DViCO FusionHDTV DVB-T Dual Digital",
- .tuner_type = UNSET, /* No analog tuner */
+ .tuner_type = TUNER_ABSENT, /* No analog tuner */
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1356,7 +1356,7 @@
},
[CX88_BOARD_GENIATECH_DVBS] = {
.name = "Geniatech DVB-S",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1494,7 +1494,7 @@
},
[CX88_BOARD_SAMSUNG_SMT_7020] = {
.name = "Samsung SMT 7020 DVB-S",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1506,7 +1506,7 @@
},
[CX88_BOARD_ADSTECH_PTV_390] = {
.name = "ADS Tech Instant Video PCI",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -1553,7 +1553,7 @@
[CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = {
.name = "DViCO FusionHDTV 5 PCI nano",
/* xc3008 tuner, digital only for now */
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2069,7 +2069,7 @@
},
[CX88_BOARD_TBS_8920] = {
.name = "TBS 8920 DVB-S/S2",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2304,7 +2304,7 @@
},
[CX88_BOARD_TWINHAN_VP1027_DVBS] = {
.name = "Twinhan VP-1027 DVB-S",
- .tuner_type = UNSET,
+ .tuner_type = TUNER_ABSENT,
.radio_type = UNSET,
.tuner_addr = ADDR_UNSET,
.radio_addr = ADDR_UNSET,
@@ -2921,33 +2921,33 @@
int fm;
const char *name;
} gdi_tuner[] = {
- [ 0x01 ] = { .id = UNSET,
+ [ 0x01 ] = { .id = TUNER_ABSENT,
.name = "NTSC_M" },
- [ 0x02 ] = { .id = UNSET,
+ [ 0x02 ] = { .id = TUNER_ABSENT,
.name = "PAL_B" },
- [ 0x03 ] = { .id = UNSET,
+ [ 0x03 ] = { .id = TUNER_ABSENT,
.name = "PAL_I" },
- [ 0x04 ] = { .id = UNSET,
+ [ 0x04 ] = { .id = TUNER_ABSENT,
.name = "PAL_D" },
- [ 0x05 ] = { .id = UNSET,
+ [ 0x05 ] = { .id = TUNER_ABSENT,
.name = "SECAM" },
- [ 0x10 ] = { .id = UNSET,
+ [ 0x10 ] = { .id = TUNER_ABSENT,
.fm = 1,
.name = "TEMIC_4049" },
[ 0x11 ] = { .id = TUNER_TEMIC_4136FY5,
.name = "TEMIC_4136" },
- [ 0x12 ] = { .id = UNSET,
+ [ 0x12 ] = { .id = TUNER_ABSENT,
.name = "TEMIC_4146" },
[ 0x20 ] = { .id = TUNER_PHILIPS_FQ1216ME,
.fm = 1,
.name = "PHILIPS_FQ1216_MK3" },
- [ 0x21 ] = { .id = UNSET, .fm = 1,
+ [ 0x21 ] = { .id = TUNER_ABSENT, .fm = 1,
.name = "PHILIPS_FQ1236_MK3" },
- [ 0x22 ] = { .id = UNSET,
+ [ 0x22 ] = { .id = TUNER_ABSENT,
.name = "PHILIPS_FI1236_MK3" },
- [ 0x23 ] = { .id = UNSET,
+ [ 0x23 ] = { .id = TUNER_ABSENT,
.name = "PHILIPS_FI1216_MK3" },
};
@@ -3564,7 +3564,7 @@
mode_mask &= ~T_RADIO;
}
- if (core->board.tuner_type != UNSET) {
+ if (core->board.tuner_type != TUNER_ABSENT) {
tun_setup.mode_mask = mode_mask;
tun_setup.type = core->board.tuner_type;
tun_setup.addr = core->board.tuner_addr;
@@ -3691,11 +3691,6 @@
core->nr = nr;
sprintf(core->name, "cx88[%d]", core->nr);
- core->tvnorm = V4L2_STD_NTSC_M;
- core->width = 320;
- core->height = 240;
- core->field = V4L2_FIELD_INTERLACED;
-
strcpy(core->v4l2_dev.name, core->name);
if (v4l2_device_register(NULL, &core->v4l2_dev)) {
kfree(core);
@@ -3777,7 +3772,7 @@
cx88_i2c_init(core, pci);
/* load tuner module, if needed */
- if (UNSET != core->board.tuner_type) {
+ if (TUNER_ABSENT != core->board.tuner_type) {
/* Ignore 0x6b and 0x6f on cx88 boards.
* FusionHDTV5 RT Gold has an ir receiver at 0x6b
* and an RTC at 0x6f which can get corrupted if probed. */
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index dee177e..7163023 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -76,16 +76,11 @@
static __le32* cx88_risc_field(__le32 *rp, struct scatterlist *sglist,
unsigned int offset, u32 sync_line,
unsigned int bpl, unsigned int padding,
- unsigned int lines, unsigned int lpi, bool jump)
+ unsigned int lines, unsigned int lpi)
{
struct scatterlist *sg;
unsigned int line,todo,sol;
- if (jump) {
- (*rp++) = cpu_to_le32(RISC_JUMP);
- (*rp++) = 0;
- }
-
/* sync instruction */
if (sync_line != NO_SYNC_LINE)
*(rp++) = cpu_to_le32(RISC_RESYNC | sync_line);
@@ -95,7 +90,7 @@
for (line = 0; line < lines; line++) {
while (offset && offset >= sg_dma_len(sg)) {
offset -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
if (lpi && line>0 && !(line % lpi))
sol = RISC_SOL | RISC_IRQ1 | RISC_CNT_INC;
@@ -114,13 +109,13 @@
*(rp++)=cpu_to_le32(sg_dma_address(sg)+offset);
todo -= (sg_dma_len(sg)-offset);
offset = 0;
- sg = sg_next(sg);
+ sg++;
while (todo > sg_dma_len(sg)) {
*(rp++)=cpu_to_le32(RISC_WRITE|
sg_dma_len(sg));
*(rp++)=cpu_to_le32(sg_dma_address(sg));
todo -= sg_dma_len(sg);
- sg = sg_next(sg);
+ sg++;
}
*(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo);
*(rp++)=cpu_to_le32(sg_dma_address(sg));
@@ -132,13 +127,14 @@
return rp;
}
-int cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc,
+int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
struct scatterlist *sglist,
unsigned int top_offset, unsigned int bottom_offset,
unsigned int bpl, unsigned int padding, unsigned int lines)
{
u32 instructions,fields;
__le32 *rp;
+ int rc;
fields = 0;
if (UNSET != top_offset)
@@ -151,21 +147,18 @@
can cause next bpl to start close to a page border. First DMA
region may be smaller than PAGE_SIZE */
instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines);
- instructions += 4;
- risc->size = instructions * 8;
- risc->dma = 0;
- risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
- if (NULL == risc->cpu)
- return -ENOMEM;
+ instructions += 2;
+ if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
+ return rc;
/* write risc instructions */
rp = risc->cpu;
if (UNSET != top_offset)
rp = cx88_risc_field(rp, sglist, top_offset, 0,
- bpl, padding, lines, 0, true);
+ bpl, padding, lines, 0);
if (UNSET != bottom_offset)
rp = cx88_risc_field(rp, sglist, bottom_offset, 0x200,
- bpl, padding, lines, 0, top_offset == UNSET);
+ bpl, padding, lines, 0);
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -173,28 +166,26 @@
return 0;
}
-int cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc,
+int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
struct scatterlist *sglist, unsigned int bpl,
unsigned int lines, unsigned int lpi)
{
u32 instructions;
__le32 *rp;
+ int rc;
/* estimate risc mem: worst case is one write per page border +
one write per scan line + syncs + jump (all 2 dwords). Here
there is no padding and no sync. First DMA region may be smaller
than PAGE_SIZE */
instructions = 1 + (bpl * lines) / PAGE_SIZE + lines;
- instructions += 3;
- risc->size = instructions * 8;
- risc->dma = 0;
- risc->cpu = pci_zalloc_consistent(pci, risc->size, &risc->dma);
- if (NULL == risc->cpu)
- return -ENOMEM;
+ instructions += 1;
+ if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0)
+ return rc;
/* write risc instructions */
rp = risc->cpu;
- rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi, !lpi);
+ rp = cx88_risc_field(rp, sglist, 0, NO_SYNC_LINE, bpl, 0, lines, lpi);
/* save pointer to jmp instruction address */
risc->jmp = rp;
@@ -202,6 +193,39 @@
return 0;
}
+int cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+ u32 reg, u32 mask, u32 value)
+{
+ __le32 *rp;
+ int rc;
+
+ if ((rc = btcx_riscmem_alloc(pci, risc, 4*16)) < 0)
+ return rc;
+
+ /* write risc instructions */
+ rp = risc->cpu;
+ *(rp++) = cpu_to_le32(RISC_WRITECR | RISC_IRQ2 | RISC_IMM);
+ *(rp++) = cpu_to_le32(reg);
+ *(rp++) = cpu_to_le32(value);
+ *(rp++) = cpu_to_le32(mask);
+ *(rp++) = cpu_to_le32(RISC_JUMP);
+ *(rp++) = cpu_to_le32(risc->dma);
+ return 0;
+}
+
+void
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
+{
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+
+ BUG_ON(in_interrupt());
+ videobuf_waiton(q, &buf->vb, 0, 0);
+ videobuf_dma_unmap(q->dev, dma);
+ videobuf_dma_free(dma);
+ btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
+ buf->vb.state = VIDEOBUF_NEEDS_INIT;
+}
+
/* ------------------------------------------------------------------ */
/* our SRAM memory layout */
@@ -515,12 +539,33 @@
struct cx88_dmaqueue *q, u32 count)
{
struct cx88_buffer *buf;
+ int bc;
- buf = list_entry(q->active.next,
- struct cx88_buffer, list);
- v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+ for (bc = 0;; bc++) {
+ if (list_empty(&q->active))
+ break;
+ buf = list_entry(q->active.next,
+ struct cx88_buffer, vb.queue);
+ /* count comes from the hw and is is 16bit wide --
+ * this trick handles wrap-arounds correctly for
+ * up to 32767 buffers in flight... */
+ if ((s16) (count - buf->count) < 0)
+ break;
+ v4l2_get_timestamp(&buf->vb.ts);
+ dprintk(2,"[%p/%d] wakeup reg=%d buf=%d\n",buf,buf->vb.i,
+ count, buf->count);
+ buf->vb.state = VIDEOBUF_DONE;
+ list_del(&buf->vb.queue);
+ wake_up(&buf->vb.done);
+ }
+ if (list_empty(&q->active)) {
+ del_timer(&q->timeout);
+ } else {
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ }
+ if (bc != 1)
+ dprintk(2, "%s: %d buffers handled (should be 1)\n",
+ __func__, bc);
}
void cx88_shutdown(struct cx88_core *core)
@@ -864,13 +909,6 @@
u32 bdelay,agcdelay,htotal;
u32 cxiformat, cxoformat;
- if (norm == core->tvnorm)
- return 0;
- if (core->v4ldev && (vb2_is_busy(&core->v4ldev->vb2_vidq) ||
- vb2_is_busy(&core->v4ldev->vb2_vbiq)))
- return -EBUSY;
- if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq))
- return -EBUSY;
core->tvnorm = norm;
fsc8 = norm_fsc8(norm);
adc_clock = xtal;
@@ -1005,7 +1043,6 @@
vfd->v4l2_dev = &core->v4l2_dev;
vfd->dev_parent = &pci->dev;
vfd->release = video_device_release;
- vfd->lock = &core->lock;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
core->name, type, core->board.name);
return vfd;
@@ -1077,6 +1114,8 @@
EXPORT_SYMBOL(cx88_risc_buffer);
EXPORT_SYMBOL(cx88_risc_databuffer);
+EXPORT_SYMBOL(cx88_risc_stopper);
+EXPORT_SYMBOL(cx88_free_buffer);
EXPORT_SYMBOL(cx88_sram_channels);
EXPORT_SYMBOL(cx88_sram_channel_setup);
diff --git a/drivers/media/pci/cx88/cx88-dvb.c b/drivers/media/pci/cx88/cx88-dvb.c
index 8b19efa..4f3c001 100644
--- a/drivers/media/pci/cx88/cx88-dvb.c
+++ b/drivers/media/pci/cx88/cx88-dvb.c
@@ -82,87 +82,43 @@
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
- unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+static int dvb_buf_setup(struct videobuf_queue *q,
+ unsigned int *count, unsigned int *size)
{
- struct cx8802_dev *dev = q->drv_priv;
+ struct cx8802_dev *dev = q->priv_data;
- *num_planes = 1;
dev->ts_packet_size = 188 * 4;
dev->ts_packet_count = dvb_buf_tscnt;
- sizes[0] = dev->ts_packet_size * dev->ts_packet_count;
- alloc_ctxs[0] = dev->alloc_ctx;
- *num_buffers = dvb_buf_tscnt;
+
+ *size = dev->ts_packet_size * dev->ts_packet_count;
+ *count = dvb_buf_tscnt;
return 0;
}
-static int buffer_prepare(struct vb2_buffer *vb)
+static int dvb_buf_prepare(struct videobuf_queue *q,
+ struct videobuf_buffer *vb, enum v4l2_field field)
{
- struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-
- return cx8802_buf_prepare(vb->vb2_queue, dev, buf);
+ struct cx8802_dev *dev = q->priv_data;
+ return cx8802_buf_prepare(q, dev, (struct cx88_buffer*)vb,field);
}
-static void buffer_finish(struct vb2_buffer *vb)
+static void dvb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
- struct cx88_riscmem *risc = &buf->risc;
-
- if (risc->cpu)
- pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
- memset(risc, 0, sizeof(*risc));
+ struct cx8802_dev *dev = q->priv_data;
+ cx8802_buf_queue(dev, (struct cx88_buffer*)vb);
}
-static void buffer_queue(struct vb2_buffer *vb)
+static void dvb_buf_release(struct videobuf_queue *q,
+ struct videobuf_buffer *vb)
{
- struct cx8802_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
-
- cx8802_buf_queue(dev, buf);
+ cx88_free_buffer(q, (struct cx88_buffer*)vb);
}
-static int start_streaming(struct vb2_queue *q, unsigned int count)
-{
- struct cx8802_dev *dev = q->drv_priv;
- struct cx88_dmaqueue *dmaq = &dev->mpegq;
- struct cx88_buffer *buf;
-
- buf = list_entry(dmaq->active.next, struct cx88_buffer, list);
- cx8802_start_dma(dev, dmaq, buf);
- return 0;
-}
-
-static void stop_streaming(struct vb2_queue *q)
-{
- struct cx8802_dev *dev = q->drv_priv;
- struct cx88_dmaqueue *dmaq = &dev->mpegq;
- unsigned long flags;
-
- cx8802_cancel_buffers(dev);
-
- spin_lock_irqsave(&dev->slock, flags);
- while (!list_empty(&dmaq->active)) {
- struct cx88_buffer *buf = list_entry(dmaq->active.next,
- struct cx88_buffer, list);
-
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
- }
- spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-static struct vb2_ops dvb_qops = {
- .queue_setup = queue_setup,
- .buf_prepare = buffer_prepare,
- .buf_finish = buffer_finish,
- .buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
- .start_streaming = start_streaming,
- .stop_streaming = stop_streaming,
+static const struct videobuf_queue_ops dvb_qops = {
+ .buf_setup = dvb_buf_setup,
+ .buf_prepare = dvb_buf_prepare,
+ .buf_queue = dvb_buf_queue,
+ .buf_release = dvb_buf_release,
};
/* ------------------------------------------------------------------ */
@@ -174,7 +130,7 @@
int ret = 0;
int fe_id;
- fe_id = vb2_dvb_find_frontend(&dev->frontends, fe);
+ fe_id = videobuf_dvb_find_frontend(&dev->frontends, fe);
if (!fe_id) {
printk(KERN_ERR "%s() No frontend found\n", __func__);
return -EINVAL;
@@ -198,8 +154,8 @@
static void cx88_dvb_gate_ctrl(struct cx88_core *core, int open)
{
- struct vb2_dvb_frontends *f;
- struct vb2_dvb_frontend *fe;
+ struct videobuf_dvb_frontends *f;
+ struct videobuf_dvb_frontend *fe;
if (!core->dvbdev)
return;
@@ -210,9 +166,9 @@
return;
if (f->gate <= 1) /* undefined or fe0 */
- fe = vb2_dvb_get_frontend(f, 1);
+ fe = videobuf_dvb_get_frontend(f, 1);
else
- fe = vb2_dvb_get_frontend(f, f->gate);
+ fe = videobuf_dvb_get_frontend(f, f->gate);
if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
@@ -609,7 +565,7 @@
static int attach_xc3028(u8 addr, struct cx8802_dev *dev)
{
struct dvb_frontend *fe;
- struct vb2_dvb_frontend *fe0 = NULL;
+ struct videobuf_dvb_frontend *fe0 = NULL;
struct xc2028_ctrl ctl;
struct xc2028_config cfg = {
.i2c_adap = &dev->core->i2c_adap,
@@ -618,7 +574,7 @@
};
/* Get the first frontend */
- fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
return -EINVAL;
@@ -655,10 +611,10 @@
static int attach_xc4000(struct cx8802_dev *dev, struct xc4000_config *cfg)
{
struct dvb_frontend *fe;
- struct vb2_dvb_frontend *fe0 = NULL;
+ struct videobuf_dvb_frontend *fe0 = NULL;
/* Get the first frontend */
- fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
return -EINVAL;
@@ -789,7 +745,7 @@
static int cx8802_alloc_frontends(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
- struct vb2_dvb_frontend *fe = NULL;
+ struct videobuf_dvb_frontend *fe = NULL;
int i;
mutex_init(&dev->frontends.lock);
@@ -801,10 +757,10 @@
printk(KERN_INFO "%s() allocating %d frontend(s)\n", __func__,
core->board.num_frontends);
for (i = 1; i <= core->board.num_frontends; i++) {
- fe = vb2_dvb_alloc_frontend(&dev->frontends, i);
+ fe = videobuf_dvb_alloc_frontend(&dev->frontends, i);
if (!fe) {
printk(KERN_ERR "%s() failed to alloc\n", __func__);
- vb2_dvb_dealloc_frontends(&dev->frontends);
+ videobuf_dvb_dealloc_frontends(&dev->frontends);
return -ENOMEM;
}
}
@@ -1002,7 +958,7 @@
static int dvb_register(struct cx8802_dev *dev)
{
struct cx88_core *core = dev->core;
- struct vb2_dvb_frontend *fe0, *fe1 = NULL;
+ struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
int mfe_shared = 0; /* bus not shared by default */
int res = -EINVAL;
@@ -1012,7 +968,7 @@
}
/* Get the first frontend */
- fe0 = vb2_dvb_get_frontend(&dev->frontends, 1);
+ fe0 = videobuf_dvb_get_frontend(&dev->frontends, 1);
if (!fe0)
goto frontend_detach;
@@ -1090,7 +1046,7 @@
goto frontend_detach;
}
/* MFE frontend 2 */
- fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
+ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
if (!fe1)
goto frontend_detach;
/* DVB-T init */
@@ -1459,7 +1415,7 @@
goto frontend_detach;
}
/* MFE frontend 2 */
- fe1 = vb2_dvb_get_frontend(&dev->frontends, 2);
+ fe1 = videobuf_dvb_get_frontend(&dev->frontends, 2);
if (!fe1)
goto frontend_detach;
/* DVB-T Init */
@@ -1638,7 +1594,7 @@
call_all(core, core, s_power, 0);
/* register everything */
- res = vb2_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
+ res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
&dev->pci->dev, adapter_nr, mfe_shared);
if (res)
goto frontend_detach;
@@ -1646,7 +1602,7 @@
frontend_detach:
core->gate_ctrl = NULL;
- vb2_dvb_dealloc_frontends(&dev->frontends);
+ videobuf_dvb_dealloc_frontends(&dev->frontends);
return res;
}
@@ -1741,7 +1697,7 @@
struct cx88_core *core = drv->core;
struct cx8802_dev *dev = drv->core->dvbdev;
int err;
- struct vb2_dvb_frontend *fe;
+ struct videobuf_dvb_frontend *fe;
int i;
dprintk( 1, "%s\n", __func__);
@@ -1770,31 +1726,19 @@
err = -ENODEV;
for (i = 1; i <= core->board.num_frontends; i++) {
- struct vb2_queue *q;
-
- fe = vb2_dvb_get_frontend(&core->dvbdev->frontends, i);
+ fe = videobuf_dvb_get_frontend(&core->dvbdev->frontends, i);
if (fe == NULL) {
printk(KERN_ERR "%s() failed to get frontend(%d)\n",
__func__, i);
goto fail_probe;
}
- q = &fe->dvb.dvbq;
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
- q->gfp_flags = GFP_DMA32;
- q->min_buffers_needed = 2;
- q->drv_priv = dev;
- q->buf_struct_size = sizeof(struct cx88_buffer);
- q->ops = &dvb_qops;
- q->mem_ops = &vb2_dma_sg_memops;
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->lock = &core->lock;
-
- err = vb2_queue_init(q);
- if (err < 0)
- goto fail_probe;
-
- /* init struct vb2_dvb */
+ videobuf_queue_sg_init(&fe->dvb.dvbq, &dvb_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_TOP,
+ sizeof(struct cx88_buffer),
+ dev, NULL);
+ /* init struct videobuf_dvb */
fe->dvb.name = dev->core->name;
}
@@ -1805,7 +1749,7 @@
core->name, err);
return err;
fail_probe:
- vb2_dvb_dealloc_frontends(&core->dvbdev->frontends);
+ videobuf_dvb_dealloc_frontends(&core->dvbdev->frontends);
fail_core:
return err;
}
@@ -1817,7 +1761,7 @@
dprintk( 1, "%s\n", __func__);
- vb2_dvb_unregister_bus(&dev->frontends);
+ videobuf_dvb_unregister_bus(&dev->frontends);
vp3054_i2c_remove(dev);
diff --git a/drivers/media/pci/cx88/cx88-mpeg.c b/drivers/media/pci/cx88/cx88-mpeg.c
index 1c1f69e..74b7b86 100644
--- a/drivers/media/pci/cx88/cx88-mpeg.c
+++ b/drivers/media/pci/cx88/cx88-mpeg.c
@@ -86,21 +86,21 @@
static DEFINE_MUTEX(cx8802_mutex);
/* ------------------------------------------------------------------ */
-int cx8802_start_dma(struct cx8802_dev *dev,
+static int cx8802_start_dma(struct cx8802_dev *dev,
struct cx88_dmaqueue *q,
struct cx88_buffer *buf)
{
struct cx88_core *core = dev->core;
dprintk(1, "cx8802_start_dma w: %d, h: %d, f: %d\n",
- core->width, core->height, core->field);
+ buf->vb.width, buf->vb.height, buf->vb.field);
/* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH28],
dev->ts_packet_size, buf->risc.dma);
/* write TS length to chip */
- cx_write(MO_TS_LNGTH, dev->ts_packet_size);
+ cx_write(MO_TS_LNGTH, buf->vb.width);
/* FIXME: this needs a review.
* also: move to cx88-blackbird + cx88-dvb source files? */
@@ -210,40 +210,83 @@
dprintk( 1, "cx8802_restart_queue\n" );
if (list_empty(&q->active))
- return 0;
+ {
+ struct cx88_buffer *prev;
+ prev = NULL;
- buf = list_entry(q->active.next, struct cx88_buffer, list);
+ dprintk(1, "cx8802_restart_queue: queue is empty\n" );
+
+ for (;;) {
+ if (list_empty(&q->queued))
+ return 0;
+ buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+ if (NULL == prev) {
+ list_move_tail(&buf->vb.queue, &q->active);
+ cx8802_start_dma(dev, q, buf);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ dprintk(1,"[%p/%d] restart_queue - first active\n",
+ buf,buf->vb.i);
+
+ } else if (prev->vb.width == buf->vb.width &&
+ prev->vb.height == buf->vb.height &&
+ prev->fmt == buf->fmt) {
+ list_move_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ dprintk(1,"[%p/%d] restart_queue - move to active\n",
+ buf,buf->vb.i);
+ } else {
+ return 0;
+ }
+ prev = buf;
+ }
+ return 0;
+ }
+
+ buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.i);
cx8802_start_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
+ list_for_each_entry(buf, &q->active, vb.queue)
buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
/* ------------------------------------------------------------------ */
-int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
- struct cx88_buffer *buf)
+int cx8802_buf_prepare(struct videobuf_queue *q, struct cx8802_dev *dev,
+ struct cx88_buffer *buf, enum v4l2_field field)
{
int size = dev->ts_packet_size * dev->ts_packet_count;
- struct sg_table *sgt = vb2_dma_sg_plane_desc(&buf->vb, 0);
- struct cx88_riscmem *risc = &buf->risc;
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
int rc;
- if (vb2_plane_size(&buf->vb, 0) < size)
+ dprintk(1, "%s: %p\n", __func__, buf);
+ if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
- vb2_set_plane_payload(&buf->vb, 0, size);
- rc = cx88_risc_databuffer(dev->pci, risc, sgt->sgl,
- dev->ts_packet_size, dev->ts_packet_count, 0);
- if (rc) {
- if (risc->cpu)
- pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
- memset(risc, 0, sizeof(*risc));
- return rc;
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ buf->vb.width = dev->ts_packet_size;
+ buf->vb.height = dev->ts_packet_count;
+ buf->vb.size = size;
+ buf->vb.field = field /*V4L2_FIELD_TOP*/;
+
+ if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+ goto fail;
+ cx88_risc_databuffer(dev->pci, &buf->risc,
+ dma->sglist,
+ buf->vb.width, buf->vb.height, 0);
}
+ buf->vb.state = VIDEOBUF_PREPARED;
return 0;
+
+ fail:
+ cx88_free_buffer(q,buf);
+ return rc;
}
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf)
@@ -252,33 +295,35 @@
struct cx88_dmaqueue *cx88q = &dev->mpegq;
dprintk( 1, "cx8802_buf_queue\n" );
- /* add jump to start */
- buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
- buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
- buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(cx88q->stopper.dma);
if (list_empty(&cx88q->active)) {
dprintk( 1, "queue is empty - first active\n" );
- list_add_tail(&buf->list, &cx88q->active);
+ list_add_tail(&buf->vb.queue,&cx88q->active);
+ cx8802_start_dma(dev, cx88q, buf);
+ buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = cx88q->count++;
+ mod_timer(&cx88q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(1,"[%p/%d] %s - first active\n",
- buf, buf->vb.v4l2_buf.index, __func__);
+ buf, buf->vb.i, __func__);
} else {
- buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
dprintk( 1, "queue is not empty - append to active\n" );
- prev = list_entry(cx88q->active.prev, struct cx88_buffer, list);
- list_add_tail(&buf->list, &cx88q->active);
+ prev = list_entry(cx88q->active.prev, struct cx88_buffer, vb.queue);
+ list_add_tail(&buf->vb.queue,&cx88q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = cx88q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk( 1, "[%p/%d] %s - append to active\n",
- buf, buf->vb.v4l2_buf.index, __func__);
+ buf, buf->vb.i, __func__);
}
}
/* ----------------------------------------------------------- */
-static void do_cancel_buffers(struct cx8802_dev *dev)
+static void do_cancel_buffers(struct cx8802_dev *dev, const char *reason, int restart)
{
struct cx88_dmaqueue *q = &dev->mpegq;
struct cx88_buffer *buf;
@@ -286,18 +331,41 @@
spin_lock_irqsave(&dev->slock,flags);
while (!list_empty(&q->active)) {
- buf = list_entry(q->active.next, struct cx88_buffer, list);
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+ list_del(&buf->vb.queue);
+ buf->vb.state = VIDEOBUF_ERROR;
+ wake_up(&buf->vb.done);
+ dprintk(1,"[%p/%d] %s - dma=0x%08lx\n",
+ buf, buf->vb.i, reason, (unsigned long)buf->risc.dma);
+ }
+ if (restart)
+ {
+ dprintk(1, "restarting queue\n" );
+ cx8802_restart_queue(dev,q);
}
spin_unlock_irqrestore(&dev->slock,flags);
}
void cx8802_cancel_buffers(struct cx8802_dev *dev)
{
+ struct cx88_dmaqueue *q = &dev->mpegq;
+
dprintk( 1, "cx8802_cancel_buffers" );
+ del_timer_sync(&q->timeout);
cx8802_stop_dma(dev);
- do_cancel_buffers(dev);
+ do_cancel_buffers(dev,"cancel",0);
+}
+
+static void cx8802_timeout(unsigned long data)
+{
+ struct cx8802_dev *dev = (struct cx8802_dev*)data;
+
+ dprintk(1, "%s\n",__func__);
+
+ if (debug)
+ cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH28]);
+ cx8802_stop_dma(dev);
+ do_cancel_buffers(dev,"timeout",1);
}
static const char * cx88_mpeg_irqs[32] = {
@@ -343,11 +411,19 @@
spin_unlock(&dev->slock);
}
+ /* risc2 y */
+ if (status & 0x10) {
+ spin_lock(&dev->slock);
+ cx8802_restart_queue(dev,&dev->mpegq);
+ spin_unlock(&dev->slock);
+ }
+
/* other general errors */
if (status & 0x1f0100) {
dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 );
spin_lock(&dev->slock);
cx8802_stop_dma(dev);
+ cx8802_restart_queue(dev,&dev->mpegq);
spin_unlock(&dev->slock);
}
}
@@ -414,6 +490,12 @@
/* init dma queue */
INIT_LIST_HEAD(&dev->mpegq.active);
+ INIT_LIST_HEAD(&dev->mpegq.queued);
+ dev->mpegq.timeout.function = cx8802_timeout;
+ dev->mpegq.timeout.data = (unsigned long)dev;
+ init_timer(&dev->mpegq.timeout);
+ cx88_risc_stopper(dev->pci,&dev->mpegq.stopper,
+ MO_TS_DMACNTRL,0x11,0x00);
/* get irq */
err = request_irq(dev->pci->irq, cx8802_irq,
@@ -438,6 +520,9 @@
/* unregister stuff */
free_irq(dev->pci->irq, dev);
+
+ /* free memory */
+ btcx_riscmem_free(dev->pci,&dev->mpegq.stopper);
}
/* ----------------------------------------------------------- */
@@ -454,6 +539,7 @@
dprintk( 2, "suspend\n" );
printk("%s: suspend mpeg\n", core->name);
cx8802_stop_dma(dev);
+ del_timer(&dev->mpegq.timeout);
}
spin_unlock_irqrestore(&dev->slock, flags);
@@ -729,11 +815,6 @@
if (NULL == dev)
goto fail_core;
dev->pci = pci_dev;
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail_core;
- }
dev->core = core;
/* Maintain a reference so cx88-video can query the 8802 device. */
@@ -753,7 +834,6 @@
return 0;
fail_free:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
kfree(dev);
fail_core:
core->dvbdev = NULL;
@@ -800,7 +880,6 @@
/* common */
cx8802_fini_common(dev);
cx88_core_put(dev->core,dev->pci);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
kfree(dev);
}
@@ -828,7 +907,6 @@
EXPORT_SYMBOL(cx8802_buf_prepare);
EXPORT_SYMBOL(cx8802_buf_queue);
EXPORT_SYMBOL(cx8802_cancel_buffers);
-EXPORT_SYMBOL(cx8802_start_dma);
EXPORT_SYMBOL(cx8802_register_driver);
EXPORT_SYMBOL(cx8802_unregister_driver);
diff --git a/drivers/media/pci/cx88/cx88-vbi.c b/drivers/media/pci/cx88/cx88-vbi.c
index 32eb7fd..f8f8389 100644
--- a/drivers/media/pci/cx88/cx88-vbi.c
+++ b/drivers/media/pci/cx88/cx88-vbi.c
@@ -6,6 +6,10 @@
#include "cx88.h"
+static unsigned int vbibufs = 4;
+module_param(vbibufs,int,0644);
+MODULE_PARM_DESC(vbibufs,"number of vbi buffers, range 2-32");
+
static unsigned int vbi_debug;
module_param(vbi_debug,int,0644);
MODULE_PARM_DESC(vbi_debug,"enable debug messages [vbi]");
@@ -18,27 +22,26 @@
int cx8800_vbi_fmt (struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8800_dev *dev = video_drvdata(file);
+ struct cx8800_fh *fh = priv;
+ struct cx8800_dev *dev = fh->dev;
f->fmt.vbi.samples_per_line = VBI_LINE_LENGTH;
f->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
f->fmt.vbi.offset = 244;
+ f->fmt.vbi.count[0] = VBI_LINE_COUNT;
+ f->fmt.vbi.count[1] = VBI_LINE_COUNT;
if (dev->core->tvnorm & V4L2_STD_525_60) {
/* ntsc */
f->fmt.vbi.sampling_rate = 28636363;
f->fmt.vbi.start[0] = 10;
f->fmt.vbi.start[1] = 273;
- f->fmt.vbi.count[0] = VBI_LINE_NTSC_COUNT;
- f->fmt.vbi.count[1] = VBI_LINE_NTSC_COUNT;
} else if (dev->core->tvnorm & V4L2_STD_625_50) {
/* pal */
f->fmt.vbi.sampling_rate = 35468950;
- f->fmt.vbi.start[0] = V4L2_VBI_ITU_625_F1_START + 5;
- f->fmt.vbi.start[1] = V4L2_VBI_ITU_625_F2_START + 5;
- f->fmt.vbi.count[0] = VBI_LINE_PAL_COUNT;
- f->fmt.vbi.count[1] = VBI_LINE_PAL_COUNT;
+ f->fmt.vbi.start[0] = 7 -1;
+ f->fmt.vbi.start[1] = 319 -1;
}
return 0;
}
@@ -51,7 +54,7 @@
/* setup fifo + format */
cx88_sram_channel_setup(dev->core, &cx88_sram_channels[SRAM_CH24],
- VBI_LINE_LENGTH, buf->risc.dma);
+ buf->vb.width, buf->risc.dma);
cx_write(MO_VBOS_CONTROL, ( (1 << 18) | // comb filter delay fixup
(1 << 15) | // enable vbi capture
@@ -75,7 +78,7 @@
return 0;
}
-void cx8800_stop_vbi_dma(struct cx8800_dev *dev)
+int cx8800_stop_vbi_dma(struct cx8800_dev *dev)
{
struct cx88_core *core = dev->core;
@@ -88,6 +91,7 @@
/* disable irqs */
cx_clear(MO_PCI_INTMSK, PCI_INT_VIDINT);
cx_clear(MO_VID_INTMSK, 0x0f0088);
+ return 0;
}
int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
@@ -98,137 +102,144 @@
if (list_empty(&q->active))
return 0;
- buf = list_entry(q->active.next, struct cx88_buffer, list);
+ buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.i);
cx8800_start_vbi_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
+ list_for_each_entry(buf, &q->active, vb.queue)
buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
return 0;
}
+void cx8800_vbi_timeout(unsigned long data)
+{
+ struct cx8800_dev *dev = (struct cx8800_dev*)data;
+ struct cx88_core *core = dev->core;
+ struct cx88_dmaqueue *q = &dev->vbiq;
+ struct cx88_buffer *buf;
+ unsigned long flags;
+
+ cx88_sram_channel_dump(dev->core, &cx88_sram_channels[SRAM_CH24]);
+
+ cx_clear(MO_VID_DMACNTRL, 0x88);
+ cx_clear(VID_CAPTURE_CONTROL, 0x18);
+
+ spin_lock_irqsave(&dev->slock,flags);
+ while (!list_empty(&q->active)) {
+ buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+ list_del(&buf->vb.queue);
+ buf->vb.state = VIDEOBUF_ERROR;
+ wake_up(&buf->vb.done);
+ printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", dev->core->name,
+ buf, buf->vb.i, (unsigned long)buf->risc.dma);
+ }
+ cx8800_restart_vbi_queue(dev,q);
+ spin_unlock_irqrestore(&dev->slock,flags);
+}
+
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
- unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+static int
+vbi_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
{
- struct cx8800_dev *dev = q->drv_priv;
-
- *num_planes = 1;
- if (dev->core->tvnorm & V4L2_STD_525_60)
- sizes[0] = VBI_LINE_NTSC_COUNT * VBI_LINE_LENGTH * 2;
- else
- sizes[0] = VBI_LINE_PAL_COUNT * VBI_LINE_LENGTH * 2;
- alloc_ctxs[0] = dev->alloc_ctx;
+ *size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+ if (0 == *count)
+ *count = vbibufs;
+ if (*count < 2)
+ *count = 2;
+ if (*count > 32)
+ *count = 32;
return 0;
}
-
-static int buffer_prepare(struct vb2_buffer *vb)
+static int
+vbi_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ enum v4l2_field field)
{
- struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
- struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
- unsigned int lines;
+ struct cx8800_fh *fh = q->priv_data;
+ struct cx8800_dev *dev = fh->dev;
+ struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
unsigned int size;
+ int rc;
- if (dev->core->tvnorm & V4L2_STD_525_60)
- lines = VBI_LINE_NTSC_COUNT;
- else
- lines = VBI_LINE_PAL_COUNT;
- size = lines * VBI_LINE_LENGTH * 2;
- if (vb2_plane_size(vb, 0) < size)
+ size = VBI_LINE_COUNT * VBI_LINE_LENGTH * 2;
+ if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
- vb2_set_plane_payload(vb, 0, size);
- cx88_risc_buffer(dev->pci, &buf->risc, sgt->sgl,
- 0, VBI_LINE_LENGTH * lines,
- VBI_LINE_LENGTH, 0,
- lines);
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ buf->vb.width = VBI_LINE_LENGTH;
+ buf->vb.height = VBI_LINE_COUNT;
+ buf->vb.size = size;
+ buf->vb.field = V4L2_FIELD_SEQ_TB;
+
+ if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+ goto fail;
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist,
+ 0, buf->vb.width * buf->vb.height,
+ buf->vb.width, 0,
+ buf->vb.height);
+ }
+ buf->vb.state = VIDEOBUF_PREPARED;
return 0;
+
+ fail:
+ cx88_free_buffer(q,buf);
+ return rc;
}
-static void buffer_finish(struct vb2_buffer *vb)
+static void
+vbi_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
{
- struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
- struct cx88_riscmem *risc = &buf->risc;
-
- if (risc->cpu)
- pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
- memset(risc, 0, sizeof(*risc));
-}
-
-static void buffer_queue(struct vb2_buffer *vb)
-{
- struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
struct cx88_buffer *prev;
+ struct cx8800_fh *fh = vq->priv_data;
+ struct cx8800_dev *dev = fh->dev;
struct cx88_dmaqueue *q = &dev->vbiq;
- /* add jump to start */
- buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
- buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
- buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
if (list_empty(&q->active)) {
- list_add_tail(&buf->list, &q->active);
+ list_add_tail(&buf->vb.queue,&q->active);
cx8800_start_vbi_dma(dev, q, buf);
+ buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(2,"[%p/%d] vbi_queue - first active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.i);
} else {
- buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
- prev = list_entry(q->active.prev, struct cx88_buffer, list);
- list_add_tail(&buf->list, &q->active);
+ prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
+ list_add_tail(&buf->vb.queue,&q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
dprintk(2,"[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.i);
}
}
-static int start_streaming(struct vb2_queue *q, unsigned int count)
+static void vbi_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct cx8800_dev *dev = q->drv_priv;
- struct cx88_dmaqueue *dmaq = &dev->vbiq;
- struct cx88_buffer *buf = list_entry(dmaq->active.next,
- struct cx88_buffer, list);
+ struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
- cx8800_start_vbi_dma(dev, dmaq, buf);
- return 0;
+ cx88_free_buffer(q,buf);
}
-static void stop_streaming(struct vb2_queue *q)
-{
- struct cx8800_dev *dev = q->drv_priv;
- struct cx88_core *core = dev->core;
- struct cx88_dmaqueue *dmaq = &dev->vbiq;
- unsigned long flags;
-
- cx_clear(MO_VID_DMACNTRL, 0x11);
- cx_clear(VID_CAPTURE_CONTROL, 0x06);
- cx8800_stop_vbi_dma(dev);
- spin_lock_irqsave(&dev->slock, flags);
- while (!list_empty(&dmaq->active)) {
- struct cx88_buffer *buf = list_entry(dmaq->active.next,
- struct cx88_buffer, list);
-
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
- }
- spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-const struct vb2_ops cx8800_vbi_qops = {
- .queue_setup = queue_setup,
- .buf_prepare = buffer_prepare,
- .buf_finish = buffer_finish,
- .buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
- .start_streaming = start_streaming,
- .stop_streaming = stop_streaming,
+const struct videobuf_queue_ops cx8800_vbi_qops = {
+ .buf_setup = vbi_setup,
+ .buf_prepare = vbi_prepare,
+ .buf_queue = vbi_queue,
+ .buf_release = vbi_release,
};
+
+/* ------------------------------------------------------------------ */
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
diff --git a/drivers/media/pci/cx88/cx88-video.c b/drivers/media/pci/cx88/cx88-video.c
index 05d5844..e46b732 100644
--- a/drivers/media/pci/cx88/cx88-video.c
+++ b/drivers/media/pci/cx88/cx88-video.c
@@ -70,6 +70,10 @@
module_param(irq_debug,int,0644);
MODULE_PARM_DESC(irq_debug,"enable debug messages [IRQ handler]");
+static unsigned int vid_limit = 16;
+module_param(vid_limit,int,0644);
+MODULE_PARM_DESC(vid_limit,"capture memory limit in megabytes");
+
#define dprintk(level,fmt, arg...) if (video_debug >= level) \
printk(KERN_DEBUG "%s/0: " fmt, core->name , ## arg)
@@ -293,6 +297,56 @@
CX8800_AUD_CTLS = ARRAY_SIZE(cx8800_aud_ctls),
};
+/* ------------------------------------------------------------------- */
+/* resource management */
+
+static int res_get(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bit)
+{
+ struct cx88_core *core = dev->core;
+ if (fh->resources & bit)
+ /* have it already allocated */
+ return 1;
+
+ /* is it free? */
+ mutex_lock(&core->lock);
+ if (dev->resources & bit) {
+ /* no, someone else uses it */
+ mutex_unlock(&core->lock);
+ return 0;
+ }
+ /* it's free, grab it */
+ fh->resources |= bit;
+ dev->resources |= bit;
+ dprintk(1,"res: get %d\n",bit);
+ mutex_unlock(&core->lock);
+ return 1;
+}
+
+static
+int res_check(struct cx8800_fh *fh, unsigned int bit)
+{
+ return (fh->resources & bit);
+}
+
+static
+int res_locked(struct cx8800_dev *dev, unsigned int bit)
+{
+ return (dev->resources & bit);
+}
+
+static
+void res_free(struct cx8800_dev *dev, struct cx8800_fh *fh, unsigned int bits)
+{
+ struct cx88_core *core = dev->core;
+ BUG_ON((fh->resources & bits) != bits);
+
+ mutex_lock(&core->lock);
+ fh->resources &= ~bits;
+ dev->resources &= ~bits;
+ dprintk(1,"res: put %d\n",bits);
+ mutex_unlock(&core->lock);
+}
+
/* ------------------------------------------------------------------ */
int cx88_video_mux(struct cx88_core *core, unsigned int input)
@@ -365,8 +419,8 @@
/* setup fifo + format */
cx88_sram_channel_setup(core, &cx88_sram_channels[SRAM_CH21],
buf->bpl, buf->risc.dma);
- cx88_set_scale(core, core->width, core->height, core->field);
- cx_write(MO_COLOR_CTRL, dev->fmt->cxformat | ColorFormatGamma);
+ cx88_set_scale(core, buf->vb.width, buf->vb.height, buf->vb.field);
+ cx_write(MO_COLOR_CTRL, buf->fmt->cxformat | ColorFormatGamma);
/* reset counter */
cx_write(MO_VIDY_GPCNTRL,GP_COUNT_CONTROL_RESET);
@@ -416,203 +470,433 @@
struct cx88_dmaqueue *q)
{
struct cx88_core *core = dev->core;
- struct cx88_buffer *buf;
+ struct cx88_buffer *buf, *prev;
if (!list_empty(&q->active)) {
- buf = list_entry(q->active.next, struct cx88_buffer, list);
+ buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
dprintk(2,"restart_queue [%p/%d]: restart dma\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.i);
start_video_dma(dev, q, buf);
- list_for_each_entry(buf, &q->active, list)
+ list_for_each_entry(buf, &q->active, vb.queue)
buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ return 0;
}
- return 0;
+
+ prev = NULL;
+ for (;;) {
+ if (list_empty(&q->queued))
+ return 0;
+ buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue);
+ if (NULL == prev) {
+ list_move_tail(&buf->vb.queue, &q->active);
+ start_video_dma(dev, q, buf);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
+ dprintk(2,"[%p/%d] restart_queue - first active\n",
+ buf,buf->vb.i);
+
+ } else if (prev->vb.width == buf->vb.width &&
+ prev->vb.height == buf->vb.height &&
+ prev->fmt == buf->fmt) {
+ list_move_tail(&buf->vb.queue, &q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ dprintk(2,"[%p/%d] restart_queue - move to active\n",
+ buf,buf->vb.i);
+ } else {
+ return 0;
+ }
+ prev = buf;
+ }
}
/* ------------------------------------------------------------------ */
-static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
- unsigned int *num_buffers, unsigned int *num_planes,
- unsigned int sizes[], void *alloc_ctxs[])
+static int
+buffer_setup(struct videobuf_queue *q, unsigned int *count, unsigned int *size)
{
- struct cx8800_dev *dev = q->drv_priv;
- struct cx88_core *core = dev->core;
+ struct cx8800_fh *fh = q->priv_data;
+ struct cx8800_dev *dev = fh->dev;
- *num_planes = 1;
- sizes[0] = (dev->fmt->depth * core->width * core->height) >> 3;
- alloc_ctxs[0] = dev->alloc_ctx;
+ *size = dev->fmt->depth * dev->width * dev->height >> 3;
+ if (0 == *count)
+ *count = 32;
+ if (*size * *count > vid_limit * 1024 * 1024)
+ *count = (vid_limit * 1024 * 1024) / *size;
return 0;
}
-static int buffer_prepare(struct vb2_buffer *vb)
+static int
+buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ enum v4l2_field field)
{
- struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
+ struct cx8800_fh *fh = q->priv_data;
+ struct cx8800_dev *dev = fh->dev;
struct cx88_core *core = dev->core;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
- struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, 0);
+ struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
+ struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
+ int rc, init_buffer = 0;
- buf->bpl = core->width * dev->fmt->depth >> 3;
-
- if (vb2_plane_size(vb, 0) < core->height * buf->bpl)
+ BUG_ON(NULL == dev->fmt);
+ if (dev->width < 48 || dev->width > norm_maxw(core->tvnorm) ||
+ dev->height < 32 || dev->height > norm_maxh(core->tvnorm))
return -EINVAL;
- vb2_set_plane_payload(vb, 0, core->height * buf->bpl);
+ buf->vb.size = (dev->width * dev->height * dev->fmt->depth) >> 3;
+ if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+ return -EINVAL;
- switch (core->field) {
- case V4L2_FIELD_TOP:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl, 0, UNSET,
- buf->bpl, 0, core->height);
- break;
- case V4L2_FIELD_BOTTOM:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl, UNSET, 0,
- buf->bpl, 0, core->height);
- break;
- case V4L2_FIELD_SEQ_TB:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl,
- 0, buf->bpl * (core->height >> 1),
- buf->bpl, 0,
- core->height >> 1);
- break;
- case V4L2_FIELD_SEQ_BT:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl,
- buf->bpl * (core->height >> 1), 0,
- buf->bpl, 0,
- core->height >> 1);
- break;
- case V4L2_FIELD_INTERLACED:
- default:
- cx88_risc_buffer(dev->pci, &buf->risc,
- sgt->sgl, 0, buf->bpl,
- buf->bpl, buf->bpl,
- core->height >> 1);
- break;
+ if (buf->fmt != dev->fmt ||
+ buf->vb.width != dev->width ||
+ buf->vb.height != dev->height ||
+ buf->vb.field != field) {
+ buf->fmt = dev->fmt;
+ buf->vb.width = dev->width;
+ buf->vb.height = dev->height;
+ buf->vb.field = field;
+ init_buffer = 1;
+ }
+
+ if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
+ init_buffer = 1;
+ if (0 != (rc = videobuf_iolock(q,&buf->vb,NULL)))
+ goto fail;
+ }
+
+ if (init_buffer) {
+ buf->bpl = buf->vb.width * buf->fmt->depth >> 3;
+ switch (buf->vb.field) {
+ case V4L2_FIELD_TOP:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist, 0, UNSET,
+ buf->bpl, 0, buf->vb.height);
+ break;
+ case V4L2_FIELD_BOTTOM:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist, UNSET, 0,
+ buf->bpl, 0, buf->vb.height);
+ break;
+ case V4L2_FIELD_INTERLACED:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist, 0, buf->bpl,
+ buf->bpl, buf->bpl,
+ buf->vb.height >> 1);
+ break;
+ case V4L2_FIELD_SEQ_TB:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist,
+ 0, buf->bpl * (buf->vb.height >> 1),
+ buf->bpl, 0,
+ buf->vb.height >> 1);
+ break;
+ case V4L2_FIELD_SEQ_BT:
+ cx88_risc_buffer(dev->pci, &buf->risc,
+ dma->sglist,
+ buf->bpl * (buf->vb.height >> 1), 0,
+ buf->bpl, 0,
+ buf->vb.height >> 1);
+ break;
+ default:
+ BUG();
+ }
}
dprintk(2,"[%p/%d] buffer_prepare - %dx%d %dbpp \"%s\" - dma=0x%08lx\n",
- buf, buf->vb.v4l2_buf.index,
- core->width, core->height, dev->fmt->depth, dev->fmt->name,
+ buf, buf->vb.i,
+ dev->width, dev->height, dev->fmt->depth, dev->fmt->name,
(unsigned long)buf->risc.dma);
+
+ buf->vb.state = VIDEOBUF_PREPARED;
return 0;
+
+ fail:
+ cx88_free_buffer(q,buf);
+ return rc;
}
-static void buffer_finish(struct vb2_buffer *vb)
+static void
+buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
{
- struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
- struct cx88_riscmem *risc = &buf->risc;
-
- if (risc->cpu)
- pci_free_consistent(dev->pci, risc->size, risc->cpu, risc->dma);
- memset(risc, 0, sizeof(*risc));
-}
-
-static void buffer_queue(struct vb2_buffer *vb)
-{
- struct cx8800_dev *dev = vb->vb2_queue->drv_priv;
- struct cx88_buffer *buf = container_of(vb, struct cx88_buffer, vb);
+ struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
struct cx88_buffer *prev;
+ struct cx8800_fh *fh = vq->priv_data;
+ struct cx8800_dev *dev = fh->dev;
struct cx88_core *core = dev->core;
struct cx88_dmaqueue *q = &dev->vidq;
- /* add jump to start */
- buf->risc.cpu[1] = cpu_to_le32(buf->risc.dma + 8);
- buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_CNT_INC);
- buf->risc.jmp[1] = cpu_to_le32(buf->risc.dma + 8);
+ /* add jump to stopper */
+ buf->risc.jmp[0] = cpu_to_le32(RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC);
+ buf->risc.jmp[1] = cpu_to_le32(q->stopper.dma);
- if (list_empty(&q->active)) {
- list_add_tail(&buf->list, &q->active);
+ if (!list_empty(&q->queued)) {
+ list_add_tail(&buf->vb.queue,&q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2,"[%p/%d] buffer_queue - append to queued\n",
+ buf, buf->vb.i);
+
+ } else if (list_empty(&q->active)) {
+ list_add_tail(&buf->vb.queue,&q->active);
+ start_video_dma(dev, q, buf);
+ buf->vb.state = VIDEOBUF_ACTIVE;
buf->count = q->count++;
+ mod_timer(&q->timeout, jiffies+BUFFER_TIMEOUT);
dprintk(2,"[%p/%d] buffer_queue - first active\n",
- buf, buf->vb.v4l2_buf.index);
+ buf, buf->vb.i);
} else {
- buf->risc.cpu[0] |= cpu_to_le32(RISC_IRQ1);
- prev = list_entry(q->active.prev, struct cx88_buffer, list);
- list_add_tail(&buf->list, &q->active);
- buf->count = q->count++;
- prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
- dprintk(2, "[%p/%d] buffer_queue - append to active\n",
- buf, buf->vb.v4l2_buf.index);
+ prev = list_entry(q->active.prev, struct cx88_buffer, vb.queue);
+ if (prev->vb.width == buf->vb.width &&
+ prev->vb.height == buf->vb.height &&
+ prev->fmt == buf->fmt) {
+ list_add_tail(&buf->vb.queue,&q->active);
+ buf->vb.state = VIDEOBUF_ACTIVE;
+ buf->count = q->count++;
+ prev->risc.jmp[1] = cpu_to_le32(buf->risc.dma);
+ dprintk(2,"[%p/%d] buffer_queue - append to active\n",
+ buf, buf->vb.i);
+
+ } else {
+ list_add_tail(&buf->vb.queue,&q->queued);
+ buf->vb.state = VIDEOBUF_QUEUED;
+ dprintk(2,"[%p/%d] buffer_queue - first queued\n",
+ buf, buf->vb.i);
+ }
}
}
-static int start_streaming(struct vb2_queue *q, unsigned int count)
+static void buffer_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{
- struct cx8800_dev *dev = q->drv_priv;
- struct cx88_dmaqueue *dmaq = &dev->vidq;
- struct cx88_buffer *buf = list_entry(dmaq->active.next,
- struct cx88_buffer, list);
+ struct cx88_buffer *buf = container_of(vb,struct cx88_buffer,vb);
- start_video_dma(dev, dmaq, buf);
- return 0;
+ cx88_free_buffer(q,buf);
}
-static void stop_streaming(struct vb2_queue *q)
-{
- struct cx8800_dev *dev = q->drv_priv;
- struct cx88_core *core = dev->core;
- struct cx88_dmaqueue *dmaq = &dev->vidq;
- unsigned long flags;
-
- cx_clear(MO_VID_DMACNTRL, 0x11);
- cx_clear(VID_CAPTURE_CONTROL, 0x06);
- spin_lock_irqsave(&dev->slock, flags);
- while (!list_empty(&dmaq->active)) {
- struct cx88_buffer *buf = list_entry(dmaq->active.next,
- struct cx88_buffer, list);
-
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
- }
- spin_unlock_irqrestore(&dev->slock, flags);
-}
-
-static struct vb2_ops cx8800_video_qops = {
- .queue_setup = queue_setup,
+static const struct videobuf_queue_ops cx8800_video_qops = {
+ .buf_setup = buffer_setup,
.buf_prepare = buffer_prepare,
- .buf_finish = buffer_finish,
.buf_queue = buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
- .start_streaming = start_streaming,
- .stop_streaming = stop_streaming,
+ .buf_release = buffer_release,
};
/* ------------------------------------------------------------------ */
-static int radio_open(struct file *file)
+
+/* ------------------------------------------------------------------ */
+
+static struct videobuf_queue *get_queue(struct file *file)
{
+ struct video_device *vdev = video_devdata(file);
+ struct cx8800_fh *fh = file->private_data;
+
+ switch (vdev->vfl_type) {
+ case VFL_TYPE_GRABBER:
+ return &fh->vidq;
+ case VFL_TYPE_VBI:
+ return &fh->vbiq;
+ default:
+ BUG();
+ }
+}
+
+static int get_resource(struct file *file)
+{
+ struct video_device *vdev = video_devdata(file);
+
+ switch (vdev->vfl_type) {
+ case VFL_TYPE_GRABBER:
+ return RESOURCE_VIDEO;
+ case VFL_TYPE_VBI:
+ return RESOURCE_VBI;
+ default:
+ BUG();
+ }
+}
+
+static int video_open(struct file *file)
+{
+ struct video_device *vdev = video_devdata(file);
struct cx8800_dev *dev = video_drvdata(file);
struct cx88_core *core = dev->core;
- int ret = v4l2_fh_open(file);
+ struct cx8800_fh *fh;
+ enum v4l2_buf_type type = 0;
+ int radio = 0;
- if (ret)
- return ret;
-
- cx_write(MO_GP3_IO, core->board.radio.gpio3);
- cx_write(MO_GP0_IO, core->board.radio.gpio0);
- cx_write(MO_GP1_IO, core->board.radio.gpio1);
- cx_write(MO_GP2_IO, core->board.radio.gpio2);
- if (core->board.radio.audioroute) {
- if (core->sd_wm8775) {
- call_all(core, audio, s_routing,
- core->board.radio.audioroute, 0, 0);
- }
- /* "I2S ADC mode" */
- core->tvaudio = WW_I2SADC;
- cx88_set_tvaudio(core);
- } else {
- /* FM Mode */
- core->tvaudio = WW_FM;
- cx88_set_tvaudio(core);
- cx88_set_stereo(core, V4L2_TUNER_MODE_STEREO, 1);
+ switch (vdev->vfl_type) {
+ case VFL_TYPE_GRABBER:
+ type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ break;
+ case VFL_TYPE_VBI:
+ type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ break;
+ case VFL_TYPE_RADIO:
+ radio = 1;
+ break;
}
- call_all(core, tuner, s_radio);
+
+ dprintk(1, "open dev=%s radio=%d type=%s\n",
+ video_device_node_name(vdev), radio, v4l2_type_names[type]);
+
+ /* allocate + initialize per filehandle data */
+ fh = kzalloc(sizeof(*fh),GFP_KERNEL);
+ if (unlikely(!fh))
+ return -ENOMEM;
+
+ v4l2_fh_init(&fh->fh, vdev);
+ file->private_data = fh;
+ fh->dev = dev;
+
+ mutex_lock(&core->lock);
+
+ videobuf_queue_sg_init(&fh->vidq, &cx8800_video_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,
+ sizeof(struct cx88_buffer),
+ fh, NULL);
+ videobuf_queue_sg_init(&fh->vbiq, &cx8800_vbi_qops,
+ &dev->pci->dev, &dev->slock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_SEQ_TB,
+ sizeof(struct cx88_buffer),
+ fh, NULL);
+
+ if (vdev->vfl_type == VFL_TYPE_RADIO) {
+ dprintk(1,"video_open: setting radio device\n");
+ cx_write(MO_GP3_IO, core->board.radio.gpio3);
+ cx_write(MO_GP0_IO, core->board.radio.gpio0);
+ cx_write(MO_GP1_IO, core->board.radio.gpio1);
+ cx_write(MO_GP2_IO, core->board.radio.gpio2);
+ if (core->board.radio.audioroute) {
+ if (core->sd_wm8775) {
+ call_all(core, audio, s_routing,
+ core->board.radio.audioroute, 0, 0);
+ }
+ /* "I2S ADC mode" */
+ core->tvaudio = WW_I2SADC;
+ cx88_set_tvaudio(core);
+ } else {
+ /* FM Mode */
+ core->tvaudio = WW_FM;
+ cx88_set_tvaudio(core);
+ cx88_set_stereo(core,V4L2_TUNER_MODE_STEREO,1);
+ }
+ call_all(core, tuner, s_radio);
+ }
+
+ core->users++;
+ mutex_unlock(&core->lock);
+ v4l2_fh_add(&fh->fh);
+
return 0;
}
+static ssize_t
+video_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct cx8800_fh *fh = file->private_data;
+
+ switch (vdev->vfl_type) {
+ case VFL_TYPE_GRABBER:
+ if (res_locked(fh->dev,RESOURCE_VIDEO))
+ return -EBUSY;
+ return videobuf_read_one(&fh->vidq, data, count, ppos,
+ file->f_flags & O_NONBLOCK);
+ case VFL_TYPE_VBI:
+ if (!res_get(fh->dev,fh,RESOURCE_VBI))
+ return -EBUSY;
+ return videobuf_read_stream(&fh->vbiq, data, count, ppos, 1,
+ file->f_flags & O_NONBLOCK);
+ default:
+ BUG();
+ }
+}
+
+static unsigned int
+video_poll(struct file *file, struct poll_table_struct *wait)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct cx8800_fh *fh = file->private_data;
+ struct cx88_buffer *buf;
+ unsigned int rc = v4l2_ctrl_poll(file, wait);
+
+ if (vdev->vfl_type == VFL_TYPE_VBI) {
+ if (!res_get(fh->dev,fh,RESOURCE_VBI))
+ return rc | POLLERR;
+ return rc | videobuf_poll_stream(file, &fh->vbiq, wait);
+ }
+ mutex_lock(&fh->vidq.vb_lock);
+ if (res_check(fh,RESOURCE_VIDEO)) {
+ /* streaming capture */
+ if (list_empty(&fh->vidq.stream))
+ goto done;
+ buf = list_entry(fh->vidq.stream.next,struct cx88_buffer,vb.stream);
+ } else {
+ /* read() capture */
+ buf = (struct cx88_buffer*)fh->vidq.read_buf;
+ if (NULL == buf)
+ goto done;
+ }
+ poll_wait(file, &buf->vb.done, wait);
+ if (buf->vb.state == VIDEOBUF_DONE ||
+ buf->vb.state == VIDEOBUF_ERROR)
+ rc |= POLLIN|POLLRDNORM;
+done:
+ mutex_unlock(&fh->vidq.vb_lock);
+ return rc;
+}
+
+static int video_release(struct file *file)
+{
+ struct cx8800_fh *fh = file->private_data;
+ struct cx8800_dev *dev = fh->dev;
+
+ /* turn off overlay */
+ if (res_check(fh, RESOURCE_OVERLAY)) {
+ /* FIXME */
+ res_free(dev,fh,RESOURCE_OVERLAY);
+ }
+
+ /* stop video capture */
+ if (res_check(fh, RESOURCE_VIDEO)) {
+ videobuf_queue_cancel(&fh->vidq);
+ res_free(dev,fh,RESOURCE_VIDEO);
+ }
+ if (fh->vidq.read_buf) {
+ buffer_release(&fh->vidq,fh->vidq.read_buf);
+ kfree(fh->vidq.read_buf);
+ }
+
+ /* stop vbi capture */
+ if (res_check(fh, RESOURCE_VBI)) {
+ videobuf_stop(&fh->vbiq);
+ res_free(dev,fh,RESOURCE_VBI);
+ }
+
+ videobuf_mmap_free(&fh->vidq);
+ videobuf_mmap_free(&fh->vbiq);
+
+ mutex_lock(&dev->core->lock);
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
+ file->private_data = NULL;
+ kfree(fh);
+
+ dev->core->users--;
+ if (!dev->core->users)
+ call_all(dev->core, core, s_power, 0);
+ mutex_unlock(&dev->core->lock);
+
+ return 0;
+}
+
+static int
+video_mmap(struct file *file, struct vm_area_struct * vma)
+{
+ return videobuf_mmap_mapper(get_queue(file), vma);
+}
+
/* ------------------------------------------------------------------ */
/* VIDEO CTRL IOCTLS */
@@ -715,12 +999,12 @@
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx8800_fh *fh = priv;
+ struct cx8800_dev *dev = fh->dev;
- f->fmt.pix.width = core->width;
- f->fmt.pix.height = core->height;
- f->fmt.pix.field = core->field;
+ f->fmt.pix.width = dev->width;
+ f->fmt.pix.height = dev->height;
+ f->fmt.pix.field = fh->vidq.field;
f->fmt.pix.pixelformat = dev->fmt->fourcc;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * dev->fmt->depth) >> 3;
@@ -733,8 +1017,7 @@
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
const struct cx8800_fmt *fmt;
enum v4l2_field field;
unsigned int maxw, maxh;
@@ -743,30 +1026,30 @@
if (NULL == fmt)
return -EINVAL;
- maxw = norm_maxw(core->tvnorm);
- maxh = norm_maxh(core->tvnorm);
-
field = f->fmt.pix.field;
+ maxw = norm_maxw(core->tvnorm);
+ maxh = norm_maxh(core->tvnorm);
+
+ if (V4L2_FIELD_ANY == field) {
+ field = (f->fmt.pix.height > maxh/2)
+ ? V4L2_FIELD_INTERLACED
+ : V4L2_FIELD_BOTTOM;
+ }
switch (field) {
case V4L2_FIELD_TOP:
case V4L2_FIELD_BOTTOM:
+ maxh = maxh / 2;
+ break;
case V4L2_FIELD_INTERLACED:
- case V4L2_FIELD_SEQ_BT:
- case V4L2_FIELD_SEQ_TB:
break;
default:
- field = (f->fmt.pix.height > maxh / 2)
- ? V4L2_FIELD_INTERLACED
- : V4L2_FIELD_BOTTOM;
- break;
+ return -EINVAL;
}
- if (V4L2_FIELD_HAS_T_OR_B(field))
- maxh /= 2;
+ f->fmt.pix.field = field;
v4l_bound_align_image(&f->fmt.pix.width, 48, maxw, 2,
&f->fmt.pix.height, 32, maxh, 0, 0);
- f->fmt.pix.field = field;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage =
@@ -778,20 +1061,16 @@
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx8800_fh *fh = priv;
+ struct cx8800_dev *dev = fh->dev;
int err = vidioc_try_fmt_vid_cap (file,priv,f);
if (0 != err)
return err;
- if (vb2_is_busy(&dev->vb2_vidq) || vb2_is_busy(&dev->vb2_vbiq))
- return -EBUSY;
- if (core->dvbdev && vb2_is_busy(&core->dvbdev->vb2_mpegq))
- return -EBUSY;
- dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
- core->width = f->fmt.pix.width;
- core->height = f->fmt.pix.height;
- core->field = f->fmt.pix.field;
+ dev->fmt = format_by_fourcc(f->fmt.pix.pixelformat);
+ dev->width = f->fmt.pix.width;
+ dev->height = f->fmt.pix.height;
+ fh->vidq.field = f->fmt.pix.field;
return 0;
}
@@ -825,8 +1104,8 @@
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx8800_dev *dev = ((struct cx8800_fh *)priv)->dev;
+ struct cx88_core *core = dev->core;
strcpy(cap->driver, "cx8800");
sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
@@ -846,10 +1125,64 @@
return 0;
}
+static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
+{
+ return videobuf_reqbufs(get_queue(file), p);
+}
+
+static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ return videobuf_querybuf(get_queue(file), p);
+}
+
+static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ return videobuf_qbuf(get_queue(file), p);
+}
+
+static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ return videobuf_dqbuf(get_queue(file), p,
+ file->f_flags & O_NONBLOCK);
+}
+
+static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct cx8800_fh *fh = priv;
+ struct cx8800_dev *dev = fh->dev;
+
+ if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+ (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
+ return -EINVAL;
+
+ if (unlikely(!res_get(dev, fh, get_resource(file))))
+ return -EBUSY;
+ return videobuf_streamon(get_queue(file));
+}
+
+static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct cx8800_fh *fh = priv;
+ struct cx8800_dev *dev = fh->dev;
+ int err, res;
+
+ if ((vdev->vfl_type == VFL_TYPE_GRABBER && i != V4L2_BUF_TYPE_VIDEO_CAPTURE) ||
+ (vdev->vfl_type == VFL_TYPE_VBI && i != V4L2_BUF_TYPE_VBI_CAPTURE))
+ return -EINVAL;
+
+ res = get_resource(file);
+ err = videobuf_streamoff(get_queue(file));
+ if (err < 0)
+ return err;
+ res_free(dev,fh,res);
+ return 0;
+}
+
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
*tvnorm = core->tvnorm;
return 0;
@@ -857,10 +1190,13 @@
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id tvnorms)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
- return cx88_set_tvnorm(core, tvnorms);
+ mutex_lock(&core->lock);
+ cx88_set_tvnorm(core, tvnorms);
+ mutex_unlock(&core->lock);
+
+ return 0;
}
/* only one input in this sample driver */
@@ -897,15 +1233,13 @@
static int vidioc_enum_input (struct file *file, void *priv,
struct v4l2_input *i)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
return cx88_enum_input (core,i);
}
static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
*i = core->input;
return 0;
@@ -913,24 +1247,24 @@
static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
if (i >= 4)
return -EINVAL;
if (0 == INPUT(i).type)
return -EINVAL;
+ mutex_lock(&core->lock);
cx88_newstation(core);
cx88_video_mux(core,i);
+ mutex_unlock(&core->lock);
return 0;
}
static int vidioc_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
u32 reg;
if (unlikely(UNSET == core->board.tuner_type))
@@ -952,8 +1286,7 @@
static int vidioc_s_tuner (struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
if (UNSET == core->board.tuner_type)
return -EINVAL;
@@ -967,8 +1300,8 @@
static int vidioc_g_frequency (struct file *file, void *priv,
struct v4l2_frequency *f)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx8800_fh *fh = priv;
+ struct cx88_core *core = fh->dev->core;
if (unlikely(UNSET == core->board.tuner_type))
return -EINVAL;
@@ -992,6 +1325,7 @@
if (unlikely(f->tuner != 0))
return -EINVAL;
+ mutex_lock(&core->lock);
cx88_newstation(core);
call_all(core, tuner, s_frequency, f);
call_all(core, tuner, g_frequency, &new_freq);
@@ -1001,6 +1335,8 @@
msleep (10);
cx88_set_tvaudio(core);
+ mutex_unlock(&core->lock);
+
return 0;
}
EXPORT_SYMBOL(cx88_set_freq);
@@ -1008,8 +1344,8 @@
static int vidioc_s_frequency (struct file *file, void *priv,
const struct v4l2_frequency *f)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx8800_fh *fh = priv;
+ struct cx88_core *core = fh->dev->core;
return cx88_set_freq(core, f);
}
@@ -1018,8 +1354,7 @@
static int vidioc_g_register (struct file *file, void *fh,
struct v4l2_dbg_register *reg)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
/* cx2388x has a 24-bit register space */
reg->val = cx_read(reg->reg & 0xfffffc);
@@ -1030,8 +1365,7 @@
static int vidioc_s_register (struct file *file, void *fh,
const struct v4l2_dbg_register *reg)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh*)fh)->dev->core;
cx_write(reg->reg & 0xfffffc, reg->val);
return 0;
@@ -1045,8 +1379,7 @@
static int radio_g_tuner (struct file *file, void *priv,
struct v4l2_tuner *t)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
if (unlikely(t->index > 0))
return -EINVAL;
@@ -1060,8 +1393,7 @@
static int radio_s_tuner (struct file *file, void *priv,
const struct v4l2_tuner *t)
{
- struct cx8800_dev *dev = video_drvdata(file);
- struct cx88_core *core = dev->core;
+ struct cx88_core *core = ((struct cx8800_fh *)priv)->dev->core;
if (0 != t->index)
return -EINVAL;
@@ -1072,6 +1404,32 @@
/* ----------------------------------------------------------- */
+static void cx8800_vid_timeout(unsigned long data)
+{
+ struct cx8800_dev *dev = (struct cx8800_dev*)data;
+ struct cx88_core *core = dev->core;
+ struct cx88_dmaqueue *q = &dev->vidq;
+ struct cx88_buffer *buf;
+ unsigned long flags;
+
+ cx88_sram_channel_dump(core, &cx88_sram_channels[SRAM_CH21]);
+
+ cx_clear(MO_VID_DMACNTRL, 0x11);
+ cx_clear(VID_CAPTURE_CONTROL, 0x06);
+
+ spin_lock_irqsave(&dev->slock,flags);
+ while (!list_empty(&q->active)) {
+ buf = list_entry(q->active.next, struct cx88_buffer, vb.queue);
+ list_del(&buf->vb.queue);
+ buf->vb.state = VIDEOBUF_ERROR;
+ wake_up(&buf->vb.done);
+ printk("%s/0: [%p/%d] timeout - dma=0x%08lx\n", core->name,
+ buf, buf->vb.i, (unsigned long)buf->risc.dma);
+ }
+ restart_video_queue(dev,q);
+ spin_unlock_irqrestore(&dev->slock,flags);
+}
+
static const char *cx88_vid_irqs[32] = {
"y_risci1", "u_risci1", "v_risci1", "vbi_risc1",
"y_risci2", "u_risci2", "v_risci2", "vbi_risc2",
@@ -1118,6 +1476,22 @@
cx88_wakeup(core, &dev->vbiq, count);
spin_unlock(&dev->slock);
}
+
+ /* risc2 y */
+ if (status & 0x10) {
+ dprintk(2,"stopper video\n");
+ spin_lock(&dev->slock);
+ restart_video_queue(dev,&dev->vidq);
+ spin_unlock(&dev->slock);
+ }
+
+ /* risc2 vbi */
+ if (status & 0x80) {
+ dprintk(2,"stopper vbi\n");
+ spin_lock(&dev->slock);
+ cx8800_restart_vbi_queue(dev,&dev->vbiq);
+ spin_unlock(&dev->slock);
+ }
}
static irqreturn_t cx8800_irq(int irq, void *dev_id)
@@ -1156,11 +1530,11 @@
static const struct v4l2_file_operations video_fops =
{
.owner = THIS_MODULE,
- .open = v4l2_fh_open,
- .release = vb2_fop_release,
- .read = vb2_fop_read,
- .poll = vb2_fop_poll,
- .mmap = vb2_fop_mmap,
+ .open = video_open,
+ .release = video_release,
+ .read = video_read,
+ .poll = video_poll,
+ .mmap = video_mmap,
.unlocked_ioctl = video_ioctl2,
};
@@ -1170,17 +1544,17 @@
.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_reqbufs = vb2_ioctl_reqbufs,
- .vidioc_querybuf = vb2_ioctl_querybuf,
- .vidioc_qbuf = vb2_ioctl_qbuf,
- .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
.vidioc_g_std = vidioc_g_std,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
- .vidioc_streamon = vb2_ioctl_streamon,
- .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
@@ -1205,17 +1579,17 @@
.vidioc_g_fmt_vbi_cap = cx8800_vbi_fmt,
.vidioc_try_fmt_vbi_cap = cx8800_vbi_fmt,
.vidioc_s_fmt_vbi_cap = cx8800_vbi_fmt,
- .vidioc_reqbufs = vb2_ioctl_reqbufs,
- .vidioc_querybuf = vb2_ioctl_querybuf,
- .vidioc_qbuf = vb2_ioctl_qbuf,
- .vidioc_dqbuf = vb2_ioctl_dqbuf,
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
.vidioc_g_std = vidioc_g_std,
.vidioc_s_std = vidioc_s_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
- .vidioc_streamon = vb2_ioctl_streamon,
- .vidioc_streamoff = vb2_ioctl_streamoff,
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
@@ -1236,9 +1610,9 @@
static const struct v4l2_file_operations radio_fops =
{
.owner = THIS_MODULE,
- .open = radio_open,
+ .open = video_open,
.poll = v4l2_ctrl_poll,
- .release = v4l2_fh_release,
+ .release = video_release,
.unlocked_ioctl = video_ioctl2,
};
@@ -1302,7 +1676,6 @@
{
struct cx8800_dev *dev;
struct cx88_core *core;
- struct vb2_queue *q;
int err;
int i;
@@ -1337,21 +1710,28 @@
err = -EIO;
goto fail_core;
}
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail_core;
- }
-
/* initialize driver struct */
spin_lock_init(&dev->slock);
+ core->tvnorm = V4L2_STD_NTSC_M;
/* init video dma queues */
INIT_LIST_HEAD(&dev->vidq.active);
+ INIT_LIST_HEAD(&dev->vidq.queued);
+ dev->vidq.timeout.function = cx8800_vid_timeout;
+ dev->vidq.timeout.data = (unsigned long)dev;
+ init_timer(&dev->vidq.timeout);
+ cx88_risc_stopper(dev->pci,&dev->vidq.stopper,
+ MO_VID_DMACNTRL,0x11,0x00);
/* init vbi dma queues */
INIT_LIST_HEAD(&dev->vbiq.active);
+ INIT_LIST_HEAD(&dev->vbiq.queued);
+ dev->vbiq.timeout.function = cx8800_vbi_timeout;
+ dev->vbiq.timeout.data = (unsigned long)dev;
+ init_timer(&dev->vbiq.timeout);
+ cx88_risc_stopper(dev->pci,&dev->vbiq.stopper,
+ MO_VID_DMACNTRL,0x88,0x00);
/* get irq */
err = request_irq(pci_dev->irq, cx8800_irq,
@@ -1440,10 +1820,9 @@
/* Sets device info at pci_dev */
pci_set_drvdata(pci_dev, dev);
- dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
-
- /* Maintain a reference so cx88-blackbird can query the 8800 device. */
- core->v4ldev = dev;
+ dev->width = 320;
+ dev->height = 240;
+ dev->fmt = format_by_fourcc(V4L2_PIX_FMT_BGR24);
/* initial device configuration */
mutex_lock(&core->lock);
@@ -1452,44 +1831,11 @@
v4l2_ctrl_handler_setup(&core->audio_hdl);
cx88_video_mux(core, 0);
- q = &dev->vb2_vidq;
- q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
- q->gfp_flags = GFP_DMA32;
- q->min_buffers_needed = 2;
- q->drv_priv = dev;
- q->buf_struct_size = sizeof(struct cx88_buffer);
- q->ops = &cx8800_video_qops;
- q->mem_ops = &vb2_dma_sg_memops;
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->lock = &core->lock;
-
- err = vb2_queue_init(q);
- if (err < 0)
- goto fail_unreg;
-
- q = &dev->vb2_vbiq;
- q->type = V4L2_BUF_TYPE_VBI_CAPTURE;
- q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF | VB2_READ;
- q->gfp_flags = GFP_DMA32;
- q->min_buffers_needed = 2;
- q->drv_priv = dev;
- q->buf_struct_size = sizeof(struct cx88_buffer);
- q->ops = &cx8800_vbi_qops;
- q->mem_ops = &vb2_dma_sg_memops;
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->lock = &core->lock;
-
- err = vb2_queue_init(q);
- if (err < 0)
- goto fail_unreg;
-
/* register v4l devices */
dev->video_dev = cx88_vdev_init(core,dev->pci,
&cx8800_video_template,"video");
video_set_drvdata(dev->video_dev, dev);
dev->video_dev->ctrl_handler = &core->video_hdl;
- dev->video_dev->queue = &dev->vb2_vidq;
err = video_register_device(dev->video_dev,VFL_TYPE_GRABBER,
video_nr[core->nr]);
if (err < 0) {
@@ -1502,7 +1848,6 @@
dev->vbi_dev = cx88_vdev_init(core,dev->pci,&cx8800_vbi_template,"vbi");
video_set_drvdata(dev->vbi_dev, dev);
- dev->vbi_dev->queue = &dev->vb2_vbiq;
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
vbi_nr[core->nr]);
if (err < 0) {
@@ -1530,7 +1875,7 @@
}
/* start tvaudio thread */
- if (core->board.tuner_type != UNSET) {
+ if (core->board.tuner_type != TUNER_ABSENT) {
core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
if (IS_ERR(core->kthread)) {
err = PTR_ERR(core->kthread);
@@ -1547,8 +1892,6 @@
free_irq(pci_dev->irq, dev);
mutex_unlock(&core->lock);
fail_core:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
- core->v4ldev = NULL;
cx88_core_put(core,dev->pci);
fail_free:
kfree(dev);
@@ -1570,18 +1913,16 @@
cx88_ir_stop(core);
cx88_shutdown(core); /* FIXME */
+ pci_disable_device(pci_dev);
/* unregister stuff */
free_irq(pci_dev->irq, dev);
cx8800_unregister_video(dev);
- pci_disable_device(pci_dev);
-
- core->v4ldev = NULL;
/* free memory */
+ btcx_riscmem_free(dev->pci,&dev->vidq.stopper);
cx88_core_put(core,dev->pci);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
kfree(dev);
}
@@ -1597,10 +1938,12 @@
if (!list_empty(&dev->vidq.active)) {
printk("%s/0: suspend video\n", core->name);
stop_video_dma(dev);
+ del_timer(&dev->vidq.timeout);
}
if (!list_empty(&dev->vbiq.active)) {
printk("%s/0: suspend vbi\n", core->name);
cx8800_stop_vbi_dma(dev);
+ del_timer(&dev->vbiq.timeout);
}
spin_unlock_irqrestore(&dev->slock, flags);
diff --git a/drivers/media/pci/cx88/cx88.h b/drivers/media/pci/cx88/cx88.h
index f3eccd7..d744348 100644
--- a/drivers/media/pci/cx88/cx88.h
+++ b/drivers/media/pci/cx88/cx88.h
@@ -29,18 +29,19 @@
#include <media/v4l2-fh.h>
#include <media/tuner.h>
#include <media/tveeprom.h>
-#include <media/videobuf2-dma-sg.h>
+#include <media/videobuf-dma-sg.h>
#include <media/cx2341x.h>
-#include <media/videobuf2-dvb.h>
+#include <media/videobuf-dvb.h>
#include <media/ir-kbd-i2c.h>
#include <media/wm8775.h>
+#include "btcx-risc.h"
#include "cx88-reg.h"
#include "tuner-xc2028.h"
#include <linux/mutex.h>
-#define CX88_VERSION "1.0.0"
+#define CX88_VERSION "0.0.9"
#define UNSET (-1U)
@@ -61,8 +62,7 @@
#define FORMAT_FLAGS_PACKED 0x01
#define FORMAT_FLAGS_PLANAR 0x02
-#define VBI_LINE_PAL_COUNT 18
-#define VBI_LINE_NTSC_COUNT 12
+#define VBI_LINE_COUNT 17
#define VBI_LINE_LENGTH 2048
#define AUD_RDS_LINES 4
@@ -95,13 +95,13 @@
static inline unsigned int norm_maxw(v4l2_std_id norm)
{
- return 720;
+ return (norm & (V4L2_STD_MN & ~V4L2_STD_PAL_Nc)) ? 720 : 768;
}
static inline unsigned int norm_maxh(v4l2_std_id norm)
{
- return (norm & V4L2_STD_525_60) ? 480 : 576;
+ return (norm & V4L2_STD_625_50) ? 576 : 480;
}
/* ----------------------------------------------------------- */
@@ -311,33 +311,26 @@
#define BUFFER_TIMEOUT msecs_to_jiffies(2000)
-struct cx88_riscmem {
- unsigned int size;
- __le32 *cpu;
- __le32 *jmp;
- dma_addr_t dma;
-};
-
/* buffer for one video frame */
struct cx88_buffer {
/* common v4l buffer stuff -- must be first */
- struct vb2_buffer vb;
- struct list_head list;
+ struct videobuf_buffer vb;
/* cx88 specific */
unsigned int bpl;
- struct cx88_riscmem risc;
+ struct btcx_riscmem risc;
+ const struct cx8800_fmt *fmt;
u32 count;
};
struct cx88_dmaqueue {
struct list_head active;
+ struct list_head queued;
+ struct timer_list timeout;
+ struct btcx_riscmem stopper;
u32 count;
};
-struct cx8800_dev;
-struct cx8802_dev;
-
struct cx88_core {
struct list_head devlist;
atomic_t refcount;
@@ -383,8 +376,6 @@
/* state info */
struct task_struct *kthread;
v4l2_std_id tvnorm;
- unsigned width, height;
- unsigned field;
enum cx88_tvaudio tvaudio;
u32 audiomode_manual;
u32 audiomode_current;
@@ -404,14 +395,11 @@
struct mutex lock;
/* various v4l controls */
u32 freq;
+ int users;
+ int mpeg_users;
- /*
- * cx88-video needs to access cx8802 for hybrid tuner pll access and
- * for vb2_is_busy() checks.
- */
+ /* cx88-video needs to access cx8802 for hybrid tuner pll access. */
struct cx8802_dev *dvbdev;
- /* cx88-blackbird needs to access cx8800 for vb2_is_busy() checks */
- struct cx8800_dev *v4ldev;
enum cx88_board_type active_type_id;
int active_ref;
int active_fe_id;
@@ -465,9 +453,24 @@
val; \
})
+struct cx8800_dev;
+struct cx8802_dev;
+
/* ----------------------------------------------------------- */
/* function 0: video stuff */
+struct cx8800_fh {
+ struct v4l2_fh fh;
+ struct cx8800_dev *dev;
+ unsigned int resources;
+
+ /* video capture */
+ struct videobuf_queue vidq;
+
+ /* vbi capture */
+ struct videobuf_queue vbiq;
+};
+
struct cx8800_suspend_state {
int disabled;
};
@@ -485,15 +488,13 @@
/* pci i/o */
struct pci_dev *pci;
unsigned char pci_rev,pci_lat;
- void *alloc_ctx;
const struct cx8800_fmt *fmt;
+ unsigned int width, height;
/* capture queues */
struct cx88_dmaqueue vidq;
- struct vb2_queue vb2_vidq;
struct cx88_dmaqueue vbiq;
- struct vb2_queue vb2_vbiq;
/* various v4l controls */
@@ -509,6 +510,12 @@
/* ----------------------------------------------------------- */
/* function 2: mpeg stuff */
+struct cx8802_fh {
+ struct v4l2_fh fh;
+ struct cx8802_dev *dev;
+ struct videobuf_queue mpegq;
+};
+
struct cx8802_suspend_state {
int disabled;
};
@@ -549,11 +556,9 @@
/* pci i/o */
struct pci_dev *pci;
unsigned char pci_rev,pci_lat;
- void *alloc_ctx;
/* dma queues */
struct cx88_dmaqueue mpegq;
- struct vb2_queue vb2_mpegq;
u32 ts_packet_size;
u32 ts_packet_count;
@@ -565,6 +570,9 @@
#if IS_ENABLED(CPTCFG_VIDEO_CX88_BLACKBIRD)
struct video_device *mpeg_dev;
u32 mailbox;
+ int width;
+ int height;
+ unsigned char mpeg_active; /* nonzero if mpeg encoder is active */
/* mpeg params */
struct cx2341x_handler cxhdl;
@@ -572,7 +580,7 @@
#if IS_ENABLED(CPTCFG_VIDEO_CX88_DVB)
/* for dvb only */
- struct vb2_dvb_frontends frontends;
+ struct videobuf_dvb_frontends frontends;
#endif
#if IS_ENABLED(CPTCFG_VIDEO_CX88_VP3054)
@@ -626,17 +634,22 @@
extern int cx88_reset(struct cx88_core *core);
extern int
-cx88_risc_buffer(struct pci_dev *pci, struct cx88_riscmem *risc,
+cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc,
struct scatterlist *sglist,
unsigned int top_offset, unsigned int bottom_offset,
unsigned int bpl, unsigned int padding, unsigned int lines);
extern int
-cx88_risc_databuffer(struct pci_dev *pci, struct cx88_riscmem *risc,
+cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc,
struct scatterlist *sglist, unsigned int bpl,
unsigned int lines, unsigned int lpi);
+extern int
+cx88_risc_stopper(struct pci_dev *pci, struct btcx_riscmem *risc,
+ u32 reg, u32 mask, u32 value);
+extern void
+cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf);
extern void cx88_risc_disasm(struct cx88_core *core,
- struct cx88_riscmem *risc);
+ struct btcx_riscmem *risc);
extern int cx88_sram_channel_setup(struct cx88_core *core,
const struct sram_channel *ch,
unsigned int bpl, u32 risc);
@@ -651,7 +664,7 @@
struct pci_dev *pci,
const struct video_device *template_,
const char *type);
-extern struct cx88_core *cx88_core_get(struct pci_dev *pci);
+extern struct cx88_core* cx88_core_get(struct pci_dev *pci);
extern void cx88_core_put(struct cx88_core *core,
struct pci_dev *pci);
@@ -671,10 +684,12 @@
struct cx88_dmaqueue *q,
struct cx88_buffer *buf);
*/
-void cx8800_stop_vbi_dma(struct cx8800_dev *dev);
-int cx8800_restart_vbi_queue(struct cx8800_dev *dev, struct cx88_dmaqueue *q);
+int cx8800_stop_vbi_dma(struct cx8800_dev *dev);
+int cx8800_restart_vbi_queue(struct cx8800_dev *dev,
+ struct cx88_dmaqueue *q);
+void cx8800_vbi_timeout(unsigned long data);
-extern const struct vb2_ops cx8800_vbi_qops;
+extern const struct videobuf_queue_ops cx8800_vbi_qops;
/* ----------------------------------------------------------- */
/* cx88-i2c.c */
@@ -724,17 +739,14 @@
/* ----------------------------------------------------------- */
/* cx88-mpeg.c */
-int cx8802_buf_prepare(struct vb2_queue *q, struct cx8802_dev *dev,
- struct cx88_buffer *buf);
+int cx8802_buf_prepare(struct videobuf_queue *q,struct cx8802_dev *dev,
+ struct cx88_buffer *buf, enum v4l2_field field);
void cx8802_buf_queue(struct cx8802_dev *dev, struct cx88_buffer *buf);
void cx8802_cancel_buffers(struct cx8802_dev *dev);
-int cx8802_start_dma(struct cx8802_dev *dev,
- struct cx88_dmaqueue *q,
- struct cx88_buffer *buf);
/* ----------------------------------------------------------- */
/* cx88-video.c*/
-int cx88_enum_input(struct cx88_core *core, struct v4l2_input *i);
+int cx88_enum_input (struct cx88_core *core,struct v4l2_input *i);
int cx88_set_freq(struct cx88_core *core, const struct v4l2_frequency *f);
int cx88_video_mux(struct cx88_core *core, unsigned int input);
void cx88_querycap(struct file *file, struct cx88_core *core,
diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c
index 9c00ff1..ad8dfdd 100644
--- a/drivers/media/pci/ddbridge/ddbridge-core.c
+++ b/drivers/media/pci/ddbridge/ddbridge-core.c
@@ -1118,7 +1118,8 @@
dvb_input_detach(port->input[1]);
break;
case DDB_PORT_CI:
- dvb_unregister_device(port->output->dev);
+ if (port->output->dev)
+ dvb_unregister_device(port->output->dev);
if (port->en) {
ddb_input_stop(port->input[0]);
ddb_output_stop(port->output);
diff --git a/drivers/media/pci/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c
index ccf548c..2b0ab26 100644
--- a/drivers/media/pci/ivtv/ivtv-controls.c
+++ b/drivers/media/pci/ivtv/ivtv-controls.c
@@ -69,7 +69,7 @@
/* fix videodecoder resolution */
fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
fmt.height = cxhdl->height;
- fmt.code = MEDIA_BUS_FMT_FIXED;
+ fmt.code = V4L2_MBUS_FMT_FIXED;
v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &fmt);
return 0;
}
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
index 9c5f710..b9744b5 100644
--- a/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -595,7 +595,7 @@
fmt->fmt.pix.width /= 2;
mbus_fmt.width = fmt->fmt.pix.width;
mbus_fmt.height = h;
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
+ mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
v4l2_subdev_call(itv->sd_video, video, s_mbus_fmt, &mbus_fmt);
return ivtv_g_fmt_vid_cap(file, fh, fmt);
}
diff --git a/drivers/media/pci/ivtv/ivtv-udma.c b/drivers/media/pci/ivtv/ivtv-udma.c
index bee2329..7338cb2 100644
--- a/drivers/media/pci/ivtv/ivtv-udma.c
+++ b/drivers/media/pci/ivtv/ivtv-udma.c
@@ -76,7 +76,7 @@
int i;
struct scatterlist *sg;
- for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg = sg_next(sg)) {
+ for (i = 0, sg = dma->SGlist; i < dma->SG_length; i++, sg++) {
dma->SGarray[i].size = cpu_to_le32(sg_dma_len(sg));
dma->SGarray[i].src = cpu_to_le32(sg_dma_address(sg));
dma->SGarray[i].dst = cpu_to_le32(buffer_offset);
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
index 9d9f90c..aeae547 100644
--- a/drivers/media/pci/meye/meye.c
+++ b/drivers/media/pci/meye/meye.c
@@ -1031,6 +1031,9 @@
strcpy(cap->card, "meye");
sprintf(cap->bus_info, "PCI:%s", pci_name(meye.mchip_dev));
+ cap->version = (MEYE_DRIVER_MAJORVERSION << 8) +
+ MEYE_DRIVER_MINORVERSION;
+
cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
diff --git a/drivers/media/pci/pt1/pt1.c b/drivers/media/pci/pt1/pt1.c
index acc35b4..db887b0 100644
--- a/drivers/media/pci/pt1/pt1.c
+++ b/drivers/media/pci/pt1/pt1.c
@@ -109,6 +109,9 @@
int sleep;
};
+#define pt1_printk(level, pt1, format, arg...) \
+ dev_printk(level, &(pt1)->pdev->dev, format, ##arg)
+
static void pt1_write_reg(struct pt1 *pt1, int reg, u32 data)
{
writel(data, pt1->regs + reg * 4);
@@ -151,7 +154,7 @@
return 0;
pt1_write_reg(pt1, 0, 0x00000008);
}
- dev_err(&pt1->pdev->dev, "could not sync\n");
+ pt1_printk(KERN_ERR, pt1, "could not sync\n");
return -EIO;
}
@@ -176,7 +179,7 @@
return 0;
schedule_timeout_uninterruptible((HZ + 999) / 1000);
}
- dev_err(&pt1->pdev->dev, "could not unlock\n");
+ pt1_printk(KERN_ERR, pt1, "could not unlock\n");
return -EIO;
}
@@ -190,7 +193,7 @@
return 0;
schedule_timeout_uninterruptible((HZ + 999) / 1000);
}
- dev_err(&pt1->pdev->dev, "could not reset PCI\n");
+ pt1_printk(KERN_ERR, pt1, "could not reset PCI\n");
return -EIO;
}
@@ -204,7 +207,7 @@
return 0;
schedule_timeout_uninterruptible((HZ + 999) / 1000);
}
- dev_err(&pt1->pdev->dev, "could not reset RAM\n");
+ pt1_printk(KERN_ERR, pt1, "could not reset RAM\n");
return -EIO;
}
@@ -221,7 +224,7 @@
}
schedule_timeout_uninterruptible((HZ + 999) / 1000);
}
- dev_err(&pt1->pdev->dev, "could not enable RAM\n");
+ pt1_printk(KERN_ERR, pt1, "could not enable RAM\n");
return -EIO;
}
diff --git a/drivers/media/pci/pt3/Kconfig b/drivers/media/pci/pt3/Kconfig
index 6a1671a..f62f306 100644
--- a/drivers/media/pci/pt3/Kconfig
+++ b/drivers/media/pci/pt3/Kconfig
@@ -1,5 +1,5 @@
config DVB_PT3
- depends on !KERNEL_3_3
+ depends on !BACKPORT_KERNEL_3_3
tristate "Earthsoft PT3 cards"
depends on m
depends on DVB_CORE && PCI && I2C
diff --git a/drivers/media/pci/pt3/pt3.c b/drivers/media/pci/pt3/pt3.c
index 7a37e8f..1fdeac1 100644
--- a/drivers/media/pci/pt3/pt3.c
+++ b/drivers/media/pci/pt3/pt3.c
@@ -255,7 +255,7 @@
pt3_i2c_reset(pt3);
ret = pt3_init_all_demods(pt3);
if (ret < 0) {
- dev_warn(&pt3->pdev->dev, "Failed to init demod chips\n");
+ dev_warn(&pt3->pdev->dev, "Failed to init demod chips.");
return ret;
}
@@ -271,7 +271,7 @@
init0_ter, ARRAY_SIZE(init0_ter));
if (ret < 0) {
dev_warn(&pt3->pdev->dev,
- "demod[%d] failed in init sequence0\n", i);
+ "demod[%d] faild in init sequence0.", i);
return ret;
}
ret = fe->ops.init(fe);
@@ -282,7 +282,7 @@
usleep_range(2000, 4000);
ret = pt3_set_tuner_power(pt3, true, false);
if (ret < 0) {
- dev_warn(&pt3->pdev->dev, "Failed to control tuner module\n");
+ dev_warn(&pt3->pdev->dev, "Failed to control tuner module.");
return ret;
}
@@ -297,7 +297,7 @@
cfg_ter, ARRAY_SIZE(cfg_ter));
if (ret < 0) {
dev_warn(&pt3->pdev->dev,
- "demod[%d] failed in init sequence1\n", i);
+ "demod[%d] faild in init sequence1.", i);
return ret;
}
}
@@ -311,19 +311,19 @@
ret = fe->ops.tuner_ops.init(fe);
if (ret < 0) {
dev_warn(&pt3->pdev->dev,
- "Failed to init SAT-tuner[%d]\n", i);
+ "Failed to init SAT-tuner[%d].", i);
return ret;
}
}
ret = pt3_init_all_mxl301rf(pt3);
if (ret < 0) {
- dev_warn(&pt3->pdev->dev, "Failed to init TERR-tuners\n");
+ dev_warn(&pt3->pdev->dev, "Failed to init TERR-tuners.");
return ret;
}
ret = pt3_set_tuner_power(pt3, true, true);
if (ret < 0) {
- dev_warn(&pt3->pdev->dev, "Failed to control tuner module\n");
+ dev_warn(&pt3->pdev->dev, "Failed to control tuner module.");
return ret;
}
@@ -344,7 +344,7 @@
}
if (ret < 0) {
dev_warn(&pt3->pdev->dev,
- "Failed in initial tuning of tuner[%d]\n", i);
+ "Failed in initial tuning of tuner[%d].", i);
return ret;
}
}
@@ -366,7 +366,7 @@
fe->ops.set_lna = &pt3_set_lna;
}
if (i < PT3_NUM_FE) {
- dev_warn(&pt3->pdev->dev, "FE[%d] failed to standby\n", i);
+ dev_warn(&pt3->pdev->dev, "FE[%d] failed to standby.", i);
return ret;
}
return 0;
@@ -453,8 +453,8 @@
pt3_init_dmabuf(adap);
adap->num_discard = PT3_INITIAL_BUF_DROPS;
- dev_dbg(adap->dvb_adap.device, "PT3: [%s] started\n",
- adap->thread->comm);
+ dev_dbg(adap->dvb_adap.device,
+ "PT3: [%s] started.\n", adap->thread->comm);
set_freezable();
while (!kthread_freezable_should_stop(&was_frozen)) {
if (was_frozen)
@@ -468,8 +468,8 @@
PT3_FETCH_DELAY_DELTA * NSEC_PER_MSEC,
HRTIMER_MODE_REL);
}
- dev_dbg(adap->dvb_adap.device, "PT3: [%s] exited\n",
- adap->thread->comm);
+ dev_dbg(adap->dvb_adap.device,
+ "PT3: [%s] exited.\n", adap->thread->comm);
adap->thread = NULL;
return 0;
}
@@ -485,8 +485,8 @@
int ret = PTR_ERR(thread);
dev_warn(adap->dvb_adap.device,
- "PT3 (adap:%d, dmx:%d): failed to start kthread\n",
- adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
+ "PT3 (adap:%d, dmx:%d): failed to start kthread.\n",
+ adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
return ret;
}
adap->thread = thread;
@@ -501,8 +501,8 @@
ret = pt3_stop_dma(adap);
if (ret)
dev_warn(adap->dvb_adap.device,
- "PT3: failed to stop streaming of adap:%d/FE:%d\n",
- adap->dvb_adap.num, adap->fe->id);
+ "PT3: failed to stop streaming of adap:%d/FE:%d\n",
+ adap->dvb_adap.num, adap->fe->id);
/* kill the fetching thread */
ret = kthread_stop(adap->thread);
@@ -522,8 +522,8 @@
return 0;
if (adap->num_feeds != 1) {
dev_warn(adap->dvb_adap.device,
- "%s: unmatched start/stop_feed in adap:%i/dmx:%i\n",
- __func__, adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
+ "%s: unmatched start/stop_feed in adap:%i/dmx:%i.\n",
+ __func__, adap->dvb_adap.num, adap->dmxdev.dvbdev->id);
adap->num_feeds = 1;
}
@@ -553,9 +553,10 @@
struct dvb_adapter *da;
adap = kzalloc(sizeof(*adap), GFP_KERNEL);
- if (!adap)
+ if (!adap) {
+ dev_err(&pt3->pdev->dev, "failed to alloc mem for adapter.\n");
return -ENOMEM;
-
+ }
pt3->adaps[index] = adap;
adap->adap_idx = index;
@@ -564,7 +565,7 @@
THIS_MODULE, &pt3->pdev->dev, adapter_nr);
if (ret < 0) {
dev_err(&pt3->pdev->dev,
- "failed to register adapter dev\n");
+ "failed to register adapter dev.\n");
goto err_mem;
}
da = &adap->dvb_adap;
@@ -580,7 +581,7 @@
adap->demux.stop_feed = pt3_stop_feed;
ret = dvb_dmx_init(&adap->demux);
if (ret < 0) {
- dev_err(&pt3->pdev->dev, "failed to init dmx dev\n");
+ dev_err(&pt3->pdev->dev, "failed to init dmx dev.\n");
goto err_adap;
}
@@ -588,13 +589,13 @@
adap->dmxdev.demux = &adap->demux.dmx;
ret = dvb_dmxdev_init(&adap->dmxdev, da);
if (ret < 0) {
- dev_err(&pt3->pdev->dev, "failed to init dmxdev\n");
+ dev_err(&pt3->pdev->dev, "failed to init dmxdev.\n");
goto err_demux;
}
ret = pt3_alloc_dmabuf(adap);
if (ret) {
- dev_err(&pt3->pdev->dev, "failed to alloc DMA buffers\n");
+ dev_err(&pt3->pdev->dev, "failed to alloc DMA buffers.\n");
goto err_dmabuf;
}
@@ -694,7 +695,7 @@
dvb_frontend_resume(adap->fe);
ret = pt3_alloc_dmabuf(adap);
if (ret) {
- dev_err(&pt3->pdev->dev, "failed to alloc DMA bufs\n");
+ dev_err(&pt3->pdev->dev, "failed to alloc DMA bufs.\n");
continue;
}
if (adap->num_feeds > 0)
@@ -752,14 +753,15 @@
if (ret == 0)
dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
else {
- dev_err(&pdev->dev, "Failed to set DMA mask\n");
+ dev_err(&pdev->dev, "Failed to set DMA mask.\n");
goto err_release_regions;
}
- dev_info(&pdev->dev, "Use 32bit DMA\n");
+ dev_info(&pdev->dev, "Use 32bit DMA.\n");
}
pt3 = kzalloc(sizeof(*pt3), GFP_KERNEL);
if (!pt3) {
+ dev_err(&pdev->dev, "Failed to alloc mem for this dev.\n");
ret = -ENOMEM;
goto err_release_regions;
}
@@ -769,15 +771,15 @@
pt3->regs[0] = pci_ioremap_bar(pdev, 0);
pt3->regs[1] = pci_ioremap_bar(pdev, 2);
if (pt3->regs[0] == NULL || pt3->regs[1] == NULL) {
- dev_err(&pdev->dev, "Failed to ioremap\n");
+ dev_err(&pdev->dev, "Failed to ioremap.\n");
ret = -ENOMEM;
goto err_kfree;
}
ver = ioread32(pt3->regs[0] + REG_VERSION);
if ((ver >> 16) != 0x0301) {
- dev_warn(&pdev->dev, "PT%d, I/F-ver.:%d not supported\n",
- ver >> 24, (ver & 0x00ff0000) >> 16);
+ dev_warn(&pdev->dev, "PT%d, I/F-ver.:%d not supported",
+ ver >> 24, (ver & 0x00ff0000) >> 16);
ret = -ENODEV;
goto err_iounmap;
}
@@ -786,6 +788,7 @@
pt3->i2c_buf = kmalloc(sizeof(*pt3->i2c_buf), GFP_KERNEL);
if (pt3->i2c_buf == NULL) {
+ dev_err(&pdev->dev, "Failed to alloc mem for i2c.\n");
ret = -ENOMEM;
goto err_iounmap;
}
@@ -798,7 +801,7 @@
i2c_set_adapdata(i2c, pt3);
ret = i2c_add_adapter(i2c);
if (ret < 0) {
- dev_err(&pdev->dev, "Failed to add i2c adapter\n");
+ dev_err(&pdev->dev, "Failed to add i2c adapter.\n");
goto err_i2cbuf;
}
@@ -812,20 +815,20 @@
break;
}
if (i < PT3_NUM_FE) {
- dev_err(&pdev->dev, "Failed to create FE%d\n", i);
+ dev_err(&pdev->dev, "Failed to create FE%d.\n", i);
goto err_cleanup_adapters;
}
ret = pt3_fe_init(pt3);
if (ret < 0) {
- dev_err(&pdev->dev, "Failed to init frontends\n");
+ dev_err(&pdev->dev, "Failed to init frontends.\n");
i = PT3_NUM_FE - 1;
goto err_cleanup_adapters;
}
dev_info(&pdev->dev,
- "successfully init'ed PT%d (fw:0x%02x, I/F:0x%02x)\n",
- ver >> 24, (ver >> 8) & 0xff, (ver >> 16) & 0xff);
+ "successfully init'ed PT%d (fw:0x%02x, I/F:0x%02x).\n",
+ ver >> 24, (ver >> 8) & 0xff, (ver >> 16) & 0xff);
return 0;
err_cleanup_adapters:
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index ac3cd74..4056989 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -173,7 +173,9 @@
dprintk("irq: overrun [full=%d/%d] - Blocks in %d\n",dev->dmasound.read_count,
dev->dmasound.bufsize, dev->dmasound.blocks);
spin_unlock(&dev->slock);
- snd_pcm_stop_xrun(dev->dmasound.substream);
+ snd_pcm_stream_lock(dev->dmasound.substream);
+ snd_pcm_stop(dev->dmasound.substream,SNDRV_PCM_STATE_XRUN);
+ snd_pcm_stream_unlock(dev->dmasound.substream);
return;
}
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index a349e96..236ed72 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -1001,18 +1001,13 @@
saa7134_board_init1(dev);
saa7134_hwinit1(dev);
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail3;
- }
/* get irq */
err = request_irq(pci_dev->irq, saa7134_irq,
IRQF_SHARED, dev->name, dev);
if (err < 0) {
printk(KERN_ERR "%s: can't get IRQ %d\n",
dev->name,pci_dev->irq);
- goto fail4;
+ goto fail3;
}
/* wait a bit, register i2c bus */
@@ -1070,7 +1065,7 @@
if (err < 0) {
printk(KERN_INFO "%s: can't register video device\n",
dev->name);
- goto fail5;
+ goto fail4;
}
printk(KERN_INFO "%s: registered device %s [v4l2]\n",
dev->name, video_device_node_name(dev->video_dev));
@@ -1083,7 +1078,7 @@
err = video_register_device(dev->vbi_dev,VFL_TYPE_VBI,
vbi_nr[dev->nr]);
if (err < 0)
- goto fail5;
+ goto fail4;
printk(KERN_INFO "%s: registered device %s\n",
dev->name, video_device_node_name(dev->vbi_dev));
@@ -1094,7 +1089,7 @@
err = video_register_device(dev->radio_dev,VFL_TYPE_RADIO,
radio_nr[dev->nr]);
if (err < 0)
- goto fail5;
+ goto fail4;
printk(KERN_INFO "%s: registered device %s\n",
dev->name, video_device_node_name(dev->radio_dev));
}
@@ -1108,12 +1103,10 @@
request_submodules(dev);
return 0;
- fail5:
+ fail4:
saa7134_unregister_video(dev);
saa7134_i2c_unregister(dev);
free_irq(pci_dev->irq, dev);
- fail4:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
fail3:
saa7134_hwfini(dev);
iounmap(dev->lmmio);
@@ -1180,7 +1173,6 @@
/* release resources */
free_irq(pci_dev->irq, dev);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
iounmap(dev->lmmio);
release_mem_region(pci_resource_start(pci_dev,0),
pci_resource_len(pci_dev,0));
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 594dc3a..e4ea85f 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -96,6 +96,7 @@
.queue_setup = saa7134_ts_queue_setup,
.buf_init = saa7134_ts_buffer_init,
.buf_prepare = saa7134_ts_buffer_prepare,
+ .buf_finish = saa7134_ts_buffer_finish,
.buf_queue = saa7134_vb2_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
@@ -139,7 +140,7 @@
struct saa7134_dev *dev = video_drvdata(file);
struct v4l2_mbus_framefmt mbus_fmt;
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
saa_call_all(dev, video, s_mbus_fmt, &mbus_fmt);
v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
@@ -156,7 +157,7 @@
struct saa7134_dev *dev = video_drvdata(file);
struct v4l2_mbus_framefmt mbus_fmt;
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
saa_call_all(dev, video, try_mbus_fmt, &mbus_fmt);
v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
diff --git a/drivers/media/pci/saa7134/saa7134-ts.c b/drivers/media/pci/saa7134/saa7134-ts.c
index 2709b83..bd25323 100644
--- a/drivers/media/pci/saa7134/saa7134-ts.c
+++ b/drivers/media/pci/saa7134/saa7134-ts.c
@@ -94,6 +94,7 @@
struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
struct sg_table *dma = vb2_dma_sg_plane_desc(vb2, 0);
unsigned int lines, llength, size;
+ int ret;
dprintk("buffer_prepare [%p]\n", buf);
@@ -107,11 +108,25 @@
vb2_set_plane_payload(vb2, 0, size);
vb2->v4l2_buf.field = dev->field;
+ ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+ if (!ret)
+ return -EIO;
return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
saa7134_buffer_startpage(buf));
}
EXPORT_SYMBOL_GPL(saa7134_ts_buffer_prepare);
+void saa7134_ts_buffer_finish(struct vb2_buffer *vb2)
+{
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+
+ dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+}
+EXPORT_SYMBOL_GPL(saa7134_ts_buffer_finish);
+
int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
@@ -127,7 +142,6 @@
*nbuffers = 3;
*nplanes = 1;
sizes[0] = size;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
EXPORT_SYMBOL_GPL(saa7134_ts_queue_setup);
@@ -173,6 +187,7 @@
.queue_setup = saa7134_ts_queue_setup,
.buf_init = saa7134_ts_buffer_init,
.buf_prepare = saa7134_ts_buffer_prepare,
+ .buf_finish = saa7134_ts_buffer_finish,
.buf_queue = saa7134_vb2_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134-vbi.c b/drivers/media/pci/saa7134/saa7134-vbi.c
index 5306e54..4f0b101 100644
--- a/drivers/media/pci/saa7134/saa7134-vbi.c
+++ b/drivers/media/pci/saa7134/saa7134-vbi.c
@@ -120,6 +120,7 @@
struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
unsigned int size;
+ int ret;
if (dma->sgl->offset) {
pr_err("The buffer is not page-aligned\n");
@@ -131,6 +132,9 @@
vb2_set_plane_payload(vb2, 0, size);
+ ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+ if (!ret)
+ return -EIO;
return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
saa7134_buffer_startpage(buf));
}
@@ -152,7 +156,6 @@
*nbuffers = saa7134_buffer_count(size, *nbuffers);
*nplanes = 1;
sizes[0] = size;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
@@ -166,10 +169,21 @@
return 0;
}
+static void buffer_finish(struct vb2_buffer *vb2)
+{
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+
+ dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+}
+
struct vb2_ops saa7134_vbi_qops = {
.queue_setup = queue_setup,
.buf_init = buffer_init,
.buf_prepare = buffer_prepare,
+ .buf_finish = buffer_finish,
.buf_queue = saa7134_vb2_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index 87ca35a..b0f279c 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -883,6 +883,7 @@
struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
unsigned int size;
+ int ret;
if (dma->sgl->offset) {
pr_err("The buffer is not page-aligned\n");
@@ -895,10 +896,23 @@
vb2_set_plane_payload(vb2, 0, size);
vb2->v4l2_buf.field = dev->field;
+ ret = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+ if (!ret)
+ return -EIO;
return saa7134_pgtable_build(dev->pci, &dmaq->pt, dma->sgl, dma->nents,
saa7134_buffer_startpage(buf));
}
+static void buffer_finish(struct vb2_buffer *vb2)
+{
+ struct saa7134_dmaqueue *dmaq = vb2->vb2_queue->drv_priv;
+ struct saa7134_dev *dev = dmaq->dev;
+ struct saa7134_buf *buf = container_of(vb2, struct saa7134_buf, vb2);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(&buf->vb2, 0);
+
+ dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+}
+
static int queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
@@ -918,7 +932,6 @@
*nbuffers = saa7134_buffer_count(size, *nbuffers);
*nplanes = 1;
sizes[0] = size;
- alloc_ctxs[0] = dev->alloc_ctx;
return 0;
}
@@ -991,6 +1004,7 @@
.queue_setup = queue_setup,
.buf_init = buffer_init,
.buf_prepare = buffer_prepare,
+ .buf_finish = buffer_finish,
.buf_queue = saa7134_vb2_buffer_queue,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
diff --git a/drivers/media/pci/saa7134/saa7134.h b/drivers/media/pci/saa7134/saa7134.h
index d244ab1..5e9cc30 100644
--- a/drivers/media/pci/saa7134/saa7134.h
+++ b/drivers/media/pci/saa7134/saa7134.h
@@ -588,7 +588,6 @@
/* video+ts+vbi capture */
- void *alloc_ctx;
struct saa7134_dmaqueue video_q;
struct vb2_queue video_vbq;
struct saa7134_dmaqueue vbi_q;
@@ -815,6 +814,7 @@
int saa7134_ts_buffer_init(struct vb2_buffer *vb2);
int saa7134_ts_buffer_prepare(struct vb2_buffer *vb2);
+void saa7134_ts_buffer_finish(struct vb2_buffer *vb2);
int saa7134_ts_queue_setup(struct vb2_queue *q, const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[]);
diff --git a/drivers/media/pci/saa7164/saa7164-buffer.c b/drivers/media/pci/saa7164/saa7164-buffer.c
index 9bd1f73..66696fa 100644
--- a/drivers/media/pci/saa7164/saa7164-buffer.c
+++ b/drivers/media/pci/saa7164/saa7164-buffer.c
@@ -130,9 +130,9 @@
goto fail2;
/* init the buffers to a known pattern, easier during debugging */
- memset(buf->cpu, 0xff, buf->pci_size);
+ memset_io(buf->cpu, 0xff, buf->pci_size);
buf->crc = crc32(0, buf->cpu, buf->actual_size);
- memset(buf->pt_cpu, 0xff, buf->pt_size);
+ memset_io(buf->pt_cpu, 0xff, buf->pt_size);
dprintk(DBGLVL_BUF, "%s() allocated buffer @ 0x%p (%d pageptrs)\n",
__func__, buf, params->numpagetables);
diff --git a/drivers/media/pci/saa7164/saa7164-bus.c b/drivers/media/pci/saa7164/saa7164-bus.c
index 6c73f5b..5f6f309 100644
--- a/drivers/media/pci/saa7164/saa7164-bus.c
+++ b/drivers/media/pci/saa7164/saa7164-bus.c
@@ -33,12 +33,12 @@
b->Type = TYPE_BUS_PCIe;
b->m_wMaxReqSize = SAA_DEVICE_MAXREQUESTSIZE;
- b->m_pdwSetRing = (u8 __iomem *)(dev->bmmio +
+ b->m_pdwSetRing = (u8 *)(dev->bmmio +
((u32)dev->busdesc.CommandRing));
b->m_dwSizeSetRing = SAA_DEVICE_BUFFERBLOCKSIZE;
- b->m_pdwGetRing = (u8 __iomem *)(dev->bmmio +
+ b->m_pdwGetRing = (u8 *)(dev->bmmio +
((u32)dev->busdesc.ResponseRing));
b->m_dwSizeGetRing = SAA_DEVICE_BUFFERBLOCKSIZE;
@@ -138,7 +138,6 @@
u32 bytes_to_write, free_write_space, timeout, curr_srp, curr_swp;
u32 new_swp, space_rem;
int ret = SAA_ERR_BAD_PARAMETER;
- u16 size;
if (!msg) {
printk(KERN_ERR "%s() !msg\n", __func__);
@@ -149,6 +148,10 @@
saa7164_bus_verify(dev);
+ msg->size = cpu_to_le16(msg->size);
+ msg->command = cpu_to_le32(msg->command);
+ msg->controlselector = cpu_to_le16(msg->controlselector);
+
if (msg->size > dev->bus.m_wMaxReqSize) {
printk(KERN_ERR "%s() Exceeded dev->bus.m_wMaxReqSize\n",
__func__);
@@ -166,8 +169,8 @@
bytes_to_write = sizeof(*msg) + msg->size;
free_write_space = 0;
timeout = SAA_BUS_TIMEOUT;
- curr_srp = saa7164_readl(bus->m_dwSetReadPos);
- curr_swp = saa7164_readl(bus->m_dwSetWritePos);
+ curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
+ curr_swp = le32_to_cpu(saa7164_readl(bus->m_dwSetWritePos));
/* Deal with ring wrapping issues */
if (curr_srp > curr_swp)
@@ -200,7 +203,7 @@
mdelay(1);
/* Check the space usage again */
- curr_srp = saa7164_readl(bus->m_dwSetReadPos);
+ curr_srp = le32_to_cpu(saa7164_readl(bus->m_dwSetReadPos));
/* Deal with ring wrapping issues */
if (curr_srp > curr_swp)
@@ -220,16 +223,6 @@
dprintk(DBGLVL_BUS, "%s() bus->m_dwSizeSetRing = %x\n", __func__,
bus->m_dwSizeSetRing);
- /*
- * Make a copy of msg->size before it is converted to le16 since it is
- * used in the code below.
- */
- size = msg->size;
- /* Convert to le16/le32 */
- msg->size = (__force u16)cpu_to_le16(msg->size);
- msg->command = (__force u32)cpu_to_le32(msg->command);
- msg->controlselector = (__force u16)cpu_to_le16(msg->controlselector);
-
/* Mental Note: line 462 tmmhComResBusPCIe.cpp */
/* Check if we're going to wrap again */
@@ -250,28 +243,28 @@
dprintk(DBGLVL_BUS, "%s() tr4\n", __func__);
/* Split the msg into pieces as the ring wraps */
- memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, space_rem);
- memcpy_toio(bus->m_pdwSetRing, (u8 *)msg + space_rem,
+ memcpy(bus->m_pdwSetRing + curr_swp, msg, space_rem);
+ memcpy(bus->m_pdwSetRing, (u8 *)msg + space_rem,
sizeof(*msg) - space_rem);
- memcpy_toio(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
- buf, size);
+ memcpy(bus->m_pdwSetRing + sizeof(*msg) - space_rem,
+ buf, msg->size);
} else if (space_rem == sizeof(*msg)) {
dprintk(DBGLVL_BUS, "%s() tr5\n", __func__);
/* Additional data at the beginning of the ring */
- memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
- memcpy_toio(bus->m_pdwSetRing, buf, size);
+ memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+ memcpy(bus->m_pdwSetRing, buf, msg->size);
} else {
/* Additional data wraps around the ring */
- memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
- if (size > 0) {
- memcpy_toio(bus->m_pdwSetRing + curr_swp +
+ memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+ if (msg->size > 0) {
+ memcpy(bus->m_pdwSetRing + curr_swp +
sizeof(*msg), buf, space_rem -
sizeof(*msg));
- memcpy_toio(bus->m_pdwSetRing, (u8 *)buf +
+ memcpy(bus->m_pdwSetRing, (u8 *)buf +
space_rem - sizeof(*msg),
bytes_to_write - space_rem);
}
@@ -283,20 +276,15 @@
dprintk(DBGLVL_BUS, "%s() tr6\n", __func__);
/* The ring buffer doesn't wrap, two simple copies */
- memcpy_toio(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
- memcpy_toio(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
- size);
+ memcpy(bus->m_pdwSetRing + curr_swp, msg, sizeof(*msg));
+ memcpy(bus->m_pdwSetRing + curr_swp + sizeof(*msg), buf,
+ msg->size);
}
dprintk(DBGLVL_BUS, "%s() new_swp = %x\n", __func__, new_swp);
/* Update the bus write position */
- saa7164_writel(bus->m_dwSetWritePos, new_swp);
-
- /* Convert back to cpu after writing the msg to the ringbuffer. */
- msg->size = le16_to_cpu((__force __le16)msg->size);
- msg->command = le32_to_cpu((__force __le32)msg->command);
- msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector);
+ saa7164_writel(bus->m_dwSetWritePos, cpu_to_le32(new_swp));
ret = SAA_OK;
out:
@@ -348,8 +336,8 @@
/* Peek the bus to see if a msg exists, if it's not what we're expecting
* then return cleanly else read the message from the bus.
*/
- curr_gwp = saa7164_readl(bus->m_dwGetWritePos);
- curr_grp = saa7164_readl(bus->m_dwGetReadPos);
+ curr_gwp = le32_to_cpu(saa7164_readl(bus->m_dwGetWritePos));
+ curr_grp = le32_to_cpu(saa7164_readl(bus->m_dwGetReadPos));
if (curr_gwp == curr_grp) {
ret = SAA_ERR_EMPTY;
@@ -381,18 +369,14 @@
new_grp -= bus->m_dwSizeGetRing;
space_rem = bus->m_dwSizeGetRing - curr_grp;
- memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
- memcpy_fromio((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
+ memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, space_rem);
+ memcpy((u8 *)&msg_tmp + space_rem, bus->m_pdwGetRing,
bytes_to_read - space_rem);
} else {
/* No wrapping */
- memcpy_fromio(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
+ memcpy(&msg_tmp, bus->m_pdwGetRing + curr_grp, bytes_to_read);
}
- /* Convert from little endian to CPU */
- msg_tmp.size = le16_to_cpu((__force __le16)msg_tmp.size);
- msg_tmp.command = le32_to_cpu((__force __le32)msg_tmp.command);
- msg_tmp.controlselector = le16_to_cpu((__force __le16)msg_tmp.controlselector);
/* No need to update the read positions, because this was a peek */
/* If the caller specifically want to peek, return */
@@ -443,24 +427,24 @@
if (space_rem < sizeof(*msg)) {
/* msg wraps around the ring */
- memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, space_rem);
- memcpy_fromio((u8 *)msg + space_rem, bus->m_pdwGetRing,
+ memcpy(msg, bus->m_pdwGetRing + curr_grp, space_rem);
+ memcpy((u8 *)msg + space_rem, bus->m_pdwGetRing,
sizeof(*msg) - space_rem);
if (buf)
- memcpy_fromio(buf, bus->m_pdwGetRing + sizeof(*msg) -
+ memcpy(buf, bus->m_pdwGetRing + sizeof(*msg) -
space_rem, buf_size);
} else if (space_rem == sizeof(*msg)) {
- memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+ memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
if (buf)
- memcpy_fromio(buf, bus->m_pdwGetRing, buf_size);
+ memcpy(buf, bus->m_pdwGetRing, buf_size);
} else {
/* Additional data wraps around the ring */
- memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+ memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
if (buf) {
- memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp +
+ memcpy(buf, bus->m_pdwGetRing + curr_grp +
sizeof(*msg), space_rem - sizeof(*msg));
- memcpy_fromio(buf + space_rem - sizeof(*msg),
+ memcpy(buf + space_rem - sizeof(*msg),
bus->m_pdwGetRing, bytes_to_read -
space_rem);
}
@@ -469,20 +453,19 @@
} else {
/* No wrapping */
- memcpy_fromio(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
+ memcpy(msg, bus->m_pdwGetRing + curr_grp, sizeof(*msg));
if (buf)
- memcpy_fromio(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
+ memcpy(buf, bus->m_pdwGetRing + curr_grp + sizeof(*msg),
buf_size);
}
- /* Convert from little endian to CPU */
- msg->size = le16_to_cpu((__force __le16)msg->size);
- msg->command = le32_to_cpu((__force __le32)msg->command);
- msg->controlselector = le16_to_cpu((__force __le16)msg->controlselector);
/* Update the read positions, adjusting the ring */
- saa7164_writel(bus->m_dwGetReadPos, new_grp);
+ saa7164_writel(bus->m_dwGetReadPos, cpu_to_le32(new_grp));
peekout:
+ msg->size = le16_to_cpu(msg->size);
+ msg->command = le32_to_cpu(msg->command);
+ msg->controlselector = le16_to_cpu(msg->controlselector);
ret = SAA_OK;
out:
mutex_unlock(&bus->lock);
diff --git a/drivers/media/pci/saa7164/saa7164-core.c b/drivers/media/pci/saa7164/saa7164-core.c
index 4b0bec3..cc1be8a 100644
--- a/drivers/media/pci/saa7164/saa7164-core.c
+++ b/drivers/media/pci/saa7164/saa7164-core.c
@@ -119,7 +119,7 @@
u32 i;
u8 cc, a;
u16 pid;
- u8 *bufcpu = (u8 *)buf->cpu;
+ u8 __iomem *bufcpu = (u8 *)buf->cpu;
port->sync_errors = 0;
port->v_cc_errors = 0;
@@ -260,7 +260,7 @@
struct saa7164_user_buffer *ubuf = NULL;
struct list_head *c, *n;
int i = 0;
- u8 *p;
+ u8 __iomem *p;
mutex_lock(&port->dmaqueue_lock);
list_for_each_safe(c, n, &port->dmaqueue.list) {
@@ -318,7 +318,8 @@
if (buf->actual_size <= ubuf->actual_size) {
- memcpy(ubuf->data, buf->cpu, ubuf->actual_size);
+ memcpy_fromio(ubuf->data, buf->cpu,
+ ubuf->actual_size);
if (crc_checking) {
/* Throw a new checksum on the read buffer */
@@ -345,7 +346,7 @@
* with known bad data. We check for this data at a later point
* in time. */
saa7164_buffer_zero_offsets(port, bufnr);
- memset(buf->cpu, 0xff, buf->pci_size);
+ memset_io(buf->cpu, 0xff, buf->pci_size);
if (crc_checking) {
/* Throw yet aanother new checksum on the dma buffer */
buf->crc = crc32(0, buf->cpu, buf->actual_size);
@@ -1095,7 +1096,7 @@
if (c == 0)
seq_printf(m, " %04x:", i);
- seq_printf(m, " %02x", readb(b->m_pdwSetRing + i));
+ seq_printf(m, " %02x", *(b->m_pdwSetRing + i));
if (++c == 16) {
seq_printf(m, "\n");
@@ -1110,7 +1111,7 @@
if (c == 0)
seq_printf(m, " %04x:", i);
- seq_printf(m, " %02x", readb(b->m_pdwGetRing + i));
+ seq_printf(m, " %02x", *(b->m_pdwGetRing + i));
if (++c == 16) {
seq_printf(m, "\n");
diff --git a/drivers/media/pci/saa7164/saa7164-fw.c b/drivers/media/pci/saa7164/saa7164-fw.c
index add06ab..8676320 100644
--- a/drivers/media/pci/saa7164/saa7164-fw.c
+++ b/drivers/media/pci/saa7164/saa7164-fw.c
@@ -72,7 +72,7 @@
/* TODO: move dlflags into dev-> and change to write/readl/b */
/* TODO: Excessive levels of debug */
static int saa7164_downloadimage(struct saa7164_dev *dev, u8 *src, u32 srcsize,
- u32 dlflags, u8 __iomem *dst, u32 dstsize)
+ u32 dlflags, u8 *dst, u32 dstsize)
{
u32 reg, timeout, offset;
u8 *srcbuf = NULL;
@@ -136,7 +136,7 @@
srcsize -= dstsize, offset += dstsize) {
dprintk(DBGLVL_FW, "%s() memcpy %d\n", __func__, dstsize);
- memcpy_toio(dst, srcbuf + offset, dstsize);
+ memcpy(dst, srcbuf + offset, dstsize);
/* Flag the data as ready */
saa7164_writel(drflag, 1);
@@ -154,7 +154,7 @@
dprintk(DBGLVL_FW, "%s() memcpy(l) %d\n", __func__, dstsize);
/* Write last block to the device */
- memcpy_toio(dst, srcbuf+offset, srcsize);
+ memcpy(dst, srcbuf+offset, srcsize);
/* Flag the data as ready */
saa7164_writel(drflag, 1);
diff --git a/drivers/media/pci/saa7164/saa7164-types.h b/drivers/media/pci/saa7164/saa7164-types.h
index f48ba97..1d2140a 100644
--- a/drivers/media/pci/saa7164/saa7164-types.h
+++ b/drivers/media/pci/saa7164/saa7164-types.h
@@ -78,9 +78,9 @@
struct tmComResBusInfo {
enum tmBusType Type;
u16 m_wMaxReqSize;
- u8 __iomem *m_pdwSetRing;
+ u8 *m_pdwSetRing;
u32 m_dwSizeSetRing;
- u8 __iomem *m_pdwGetRing;
+ u8 *m_pdwGetRing;
u32 m_dwSizeGetRing;
u32 m_dwSetWritePos;
u32 m_dwSetReadPos;
diff --git a/drivers/media/pci/saa7164/saa7164.h b/drivers/media/pci/saa7164/saa7164.h
index cd1a07c..8b29e89 100644
--- a/drivers/media/pci/saa7164/saa7164.h
+++ b/drivers/media/pci/saa7164/saa7164.h
@@ -313,13 +313,13 @@
/* A block of page align PCI memory */
u32 pci_size; /* PCI allocation size in bytes */
- u64 *cpu; /* Virtual address */
+ u64 __iomem *cpu; /* Virtual address */
dma_addr_t dma; /* Physical address */
u32 crc; /* Checksum for the entire buffer data */
/* A page table that splits the block into a number of entries */
u32 pt_size; /* PCI allocation size in bytes */
- u64 *pt_cpu; /* Virtual address */
+ u64 __iomem *pt_cpu; /* Virtual address */
dma_addr_t pt_dma; /* Physical address */
/* Encoder fops */
diff --git a/drivers/media/pci/smipcie/Kconfig b/drivers/media/pci/smipcie/Kconfig
deleted file mode 100644
index 45d6a31..0000000
--- a/drivers/media/pci/smipcie/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-config DVB_SMIPCIE
- depends on !KERNEL_3_4
- tristate "SMI PCIe DVBSky cards"
- depends on m
- depends on DVB_CORE && PCI && I2C
- depends on I2C_ALGOBIT
- select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
- select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
- select MEDIA_TUNER_M88RS6000T if MEDIA_SUBDRV_AUTOSELECT
- select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
- help
- Support for cards with SMI PCIe bridge:
- - DVBSky S950 V3
- - DVBSky S952 V3
- - DVBSky T9580 V3
-
- Say Y or M if you own such a device and want to use it.
- If unsure say N.
diff --git a/drivers/media/pci/smipcie/Makefile b/drivers/media/pci/smipcie/Makefile
deleted file mode 100644
index ac5f289..0000000
--- a/drivers/media/pci/smipcie/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-obj-$(CPTCFG_DVB_SMIPCIE) += smipcie.o
-
-ccflags-y += -I$(backport_srctree)/drivers/media/tuners
-ccflags-y += -I$(backport_srctree)/drivers/media/dvb-core
-ccflags-y += -I$(backport_srctree)/drivers/media/dvb-frontends
-
diff --git a/drivers/media/pci/smipcie/smipcie.c b/drivers/media/pci/smipcie/smipcie.c
deleted file mode 100644
index f773350..0000000
--- a/drivers/media/pci/smipcie/smipcie.c
+++ /dev/null
@@ -1,1099 +0,0 @@
-/*
- * SMI PCIe driver for DVBSky cards.
- *
- * Copyright (C) 2014 Max nibble <nibble.max@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.
- *
- * 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 "smipcie.h"
-#include "m88ds3103.h"
-#include "m88ts2022.h"
-#include "m88rs6000t.h"
-#include "si2168.h"
-#include "si2157.h"
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static int smi_hw_init(struct smi_dev *dev)
-{
- u32 port_mux, port_ctrl, int_stat;
-
- /* set port mux.*/
- port_mux = smi_read(MUX_MODE_CTRL);
- port_mux &= ~(rbPaMSMask);
- port_mux |= rbPaMSDtvNoGpio;
- port_mux &= ~(rbPbMSMask);
- port_mux |= rbPbMSDtvNoGpio;
- port_mux &= ~(0x0f0000);
- port_mux |= 0x50000;
- smi_write(MUX_MODE_CTRL, port_mux);
-
- /* set DTV register.*/
- /* Port A */
- port_ctrl = smi_read(VIDEO_CTRL_STATUS_A);
- port_ctrl &= ~0x01;
- smi_write(VIDEO_CTRL_STATUS_A, port_ctrl);
- port_ctrl = smi_read(MPEG2_CTRL_A);
- port_ctrl &= ~0x40;
- port_ctrl |= 0x80;
- smi_write(MPEG2_CTRL_A, port_ctrl);
- /* Port B */
- port_ctrl = smi_read(VIDEO_CTRL_STATUS_B);
- port_ctrl &= ~0x01;
- smi_write(VIDEO_CTRL_STATUS_B, port_ctrl);
- port_ctrl = smi_read(MPEG2_CTRL_B);
- port_ctrl &= ~0x40;
- port_ctrl |= 0x80;
- smi_write(MPEG2_CTRL_B, port_ctrl);
-
- /* disable and clear interrupt.*/
- smi_write(MSI_INT_ENA_CLR, ALL_INT);
- int_stat = smi_read(MSI_INT_STATUS);
- smi_write(MSI_INT_STATUS_CLR, int_stat);
-
- /* reset demod.*/
- smi_clear(PERIPHERAL_CTRL, 0x0303);
- msleep(50);
- smi_set(PERIPHERAL_CTRL, 0x0101);
- return 0;
-}
-
-/* i2c bit bus.*/
-static void smi_i2c_cfg(struct smi_dev *dev, u32 sw_ctl)
-{
- u32 dwCtrl;
-
- dwCtrl = smi_read(sw_ctl);
- dwCtrl &= ~0x18; /* disable output.*/
- dwCtrl |= 0x21; /* reset and software mode.*/
- dwCtrl &= ~0xff00;
- dwCtrl |= 0x6400;
- smi_write(sw_ctl, dwCtrl);
- msleep(20);
- dwCtrl = smi_read(sw_ctl);
- dwCtrl &= ~0x20;
- smi_write(sw_ctl, dwCtrl);
-}
-
-static void smi_i2c_setsda(struct smi_dev *dev, int state, u32 sw_ctl)
-{
- if (state) {
- /* set as input.*/
- smi_clear(sw_ctl, SW_I2C_MSK_DAT_EN);
- } else {
- smi_clear(sw_ctl, SW_I2C_MSK_DAT_OUT);
- /* set as output.*/
- smi_set(sw_ctl, SW_I2C_MSK_DAT_EN);
- }
-}
-
-static void smi_i2c_setscl(void *data, int state, u32 sw_ctl)
-{
- struct smi_dev *dev = data;
-
- if (state) {
- /* set as input.*/
- smi_clear(sw_ctl, SW_I2C_MSK_CLK_EN);
- } else {
- smi_clear(sw_ctl, SW_I2C_MSK_CLK_OUT);
- /* set as output.*/
- smi_set(sw_ctl, SW_I2C_MSK_CLK_EN);
- }
-}
-
-static int smi_i2c_getsda(void *data, u32 sw_ctl)
-{
- struct smi_dev *dev = data;
- /* set as input.*/
- smi_clear(sw_ctl, SW_I2C_MSK_DAT_EN);
- udelay(1);
- return (smi_read(sw_ctl) & SW_I2C_MSK_DAT_IN) ? 1 : 0;
-}
-
-static int smi_i2c_getscl(void *data, u32 sw_ctl)
-{
- struct smi_dev *dev = data;
- /* set as input.*/
- smi_clear(sw_ctl, SW_I2C_MSK_CLK_EN);
- udelay(1);
- return (smi_read(sw_ctl) & SW_I2C_MSK_CLK_IN) ? 1 : 0;
-}
-/* i2c 0.*/
-static void smi_i2c0_setsda(void *data, int state)
-{
- struct smi_dev *dev = data;
-
- smi_i2c_setsda(dev, state, I2C_A_SW_CTL);
-}
-
-static void smi_i2c0_setscl(void *data, int state)
-{
- struct smi_dev *dev = data;
-
- smi_i2c_setscl(dev, state, I2C_A_SW_CTL);
-}
-
-static int smi_i2c0_getsda(void *data)
-{
- struct smi_dev *dev = data;
-
- return smi_i2c_getsda(dev, I2C_A_SW_CTL);
-}
-
-static int smi_i2c0_getscl(void *data)
-{
- struct smi_dev *dev = data;
-
- return smi_i2c_getscl(dev, I2C_A_SW_CTL);
-}
-/* i2c 1.*/
-static void smi_i2c1_setsda(void *data, int state)
-{
- struct smi_dev *dev = data;
-
- smi_i2c_setsda(dev, state, I2C_B_SW_CTL);
-}
-
-static void smi_i2c1_setscl(void *data, int state)
-{
- struct smi_dev *dev = data;
-
- smi_i2c_setscl(dev, state, I2C_B_SW_CTL);
-}
-
-static int smi_i2c1_getsda(void *data)
-{
- struct smi_dev *dev = data;
-
- return smi_i2c_getsda(dev, I2C_B_SW_CTL);
-}
-
-static int smi_i2c1_getscl(void *data)
-{
- struct smi_dev *dev = data;
-
- return smi_i2c_getscl(dev, I2C_B_SW_CTL);
-}
-
-static int smi_i2c_init(struct smi_dev *dev)
-{
- int ret;
-
- /* i2c bus 0 */
- smi_i2c_cfg(dev, I2C_A_SW_CTL);
- i2c_set_adapdata(&dev->i2c_bus[0], dev);
- strcpy(dev->i2c_bus[0].name, "SMI-I2C0");
- dev->i2c_bus[0].owner = THIS_MODULE;
- dev->i2c_bus[0].dev.parent = &dev->pci_dev->dev;
- dev->i2c_bus[0].algo_data = &dev->i2c_bit[0];
- dev->i2c_bit[0].data = dev;
- dev->i2c_bit[0].setsda = smi_i2c0_setsda;
- dev->i2c_bit[0].setscl = smi_i2c0_setscl;
- dev->i2c_bit[0].getsda = smi_i2c0_getsda;
- dev->i2c_bit[0].getscl = smi_i2c0_getscl;
- dev->i2c_bit[0].udelay = 12;
- dev->i2c_bit[0].timeout = 10;
- /* Raise SCL and SDA */
- smi_i2c0_setsda(dev, 1);
- smi_i2c0_setscl(dev, 1);
-
- ret = i2c_bit_add_bus(&dev->i2c_bus[0]);
- if (ret < 0)
- return ret;
-
- /* i2c bus 1 */
- smi_i2c_cfg(dev, I2C_B_SW_CTL);
- i2c_set_adapdata(&dev->i2c_bus[1], dev);
- strcpy(dev->i2c_bus[1].name, "SMI-I2C1");
- dev->i2c_bus[1].owner = THIS_MODULE;
- dev->i2c_bus[1].dev.parent = &dev->pci_dev->dev;
- dev->i2c_bus[1].algo_data = &dev->i2c_bit[1];
- dev->i2c_bit[1].data = dev;
- dev->i2c_bit[1].setsda = smi_i2c1_setsda;
- dev->i2c_bit[1].setscl = smi_i2c1_setscl;
- dev->i2c_bit[1].getsda = smi_i2c1_getsda;
- dev->i2c_bit[1].getscl = smi_i2c1_getscl;
- dev->i2c_bit[1].udelay = 12;
- dev->i2c_bit[1].timeout = 10;
- /* Raise SCL and SDA */
- smi_i2c1_setsda(dev, 1);
- smi_i2c1_setscl(dev, 1);
-
- ret = i2c_bit_add_bus(&dev->i2c_bus[1]);
- if (ret < 0)
- i2c_del_adapter(&dev->i2c_bus[0]);
-
- return ret;
-}
-
-static void smi_i2c_exit(struct smi_dev *dev)
-{
- i2c_del_adapter(&dev->i2c_bus[0]);
- i2c_del_adapter(&dev->i2c_bus[1]);
-}
-
-static int smi_read_eeprom(struct i2c_adapter *i2c, u16 reg, u8 *data, u16 size)
-{
- int ret;
- u8 b0[2] = { (reg >> 8) & 0xff, reg & 0xff };
-
- struct i2c_msg msg[] = {
- { .addr = 0x50, .flags = 0,
- .buf = b0, .len = 2 },
- { .addr = 0x50, .flags = I2C_M_RD,
- .buf = data, .len = size }
- };
-
- ret = i2c_transfer(i2c, msg, 2);
-
- if (ret != 2) {
- dev_err(&i2c->dev, "%s: reg=0x%x (error=%d)\n",
- __func__, reg, ret);
- return ret;
- }
- return ret;
-}
-
-/* ts port interrupt operations */
-static void smi_port_disableInterrupt(struct smi_port *port)
-{
- struct smi_dev *dev = port->dev;
-
- smi_write(MSI_INT_ENA_CLR,
- (port->_dmaInterruptCH0 | port->_dmaInterruptCH1));
-}
-
-static void smi_port_enableInterrupt(struct smi_port *port)
-{
- struct smi_dev *dev = port->dev;
-
- smi_write(MSI_INT_ENA_SET,
- (port->_dmaInterruptCH0 | port->_dmaInterruptCH1));
-}
-
-static void smi_port_clearInterrupt(struct smi_port *port)
-{
- struct smi_dev *dev = port->dev;
-
- smi_write(MSI_INT_STATUS_CLR,
- (port->_dmaInterruptCH0 | port->_dmaInterruptCH1));
-}
-
-/* tasklet handler: DMA data to dmx.*/
-static void smi_dma_xfer(unsigned long data)
-{
- struct smi_port *port = (struct smi_port *) data;
- struct smi_dev *dev = port->dev;
- u32 intr_status, finishedData, dmaManagement;
- u8 dmaChan0State, dmaChan1State;
-
- intr_status = port->_int_status;
- dmaManagement = smi_read(port->DMA_MANAGEMENT);
- dmaChan0State = (u8)((dmaManagement & 0x00000030) >> 4);
- dmaChan1State = (u8)((dmaManagement & 0x00300000) >> 20);
-
- /* CH-0 DMA interrupt.*/
- if ((intr_status & port->_dmaInterruptCH0) && (dmaChan0State == 0x01)) {
- dev_dbg(&dev->pci_dev->dev,
- "Port[%d]-DMA CH0 engine complete successful !\n",
- port->idx);
- finishedData = smi_read(port->DMA_CHAN0_TRANS_STATE);
- finishedData &= 0x003FFFFF;
- /* value of DMA_PORT0_CHAN0_TRANS_STATE register [21:0]
- * indicate dma total transfer length and
- * zero of [21:0] indicate dma total transfer length
- * equal to 0x400000 (4MB)*/
- if (finishedData == 0)
- finishedData = 0x00400000;
- if (finishedData != SMI_TS_DMA_BUF_SIZE) {
- dev_dbg(&dev->pci_dev->dev,
- "DMA CH0 engine complete length mismatched, finish data=%d !\n",
- finishedData);
- }
- dvb_dmx_swfilter_packets(&port->demux,
- port->cpu_addr[0], (finishedData / 188));
- /*dvb_dmx_swfilter(&port->demux,
- port->cpu_addr[0], finishedData);*/
- }
- /* CH-1 DMA interrupt.*/
- if ((intr_status & port->_dmaInterruptCH1) && (dmaChan1State == 0x01)) {
- dev_dbg(&dev->pci_dev->dev,
- "Port[%d]-DMA CH1 engine complete successful !\n",
- port->idx);
- finishedData = smi_read(port->DMA_CHAN1_TRANS_STATE);
- finishedData &= 0x003FFFFF;
- /* value of DMA_PORT0_CHAN0_TRANS_STATE register [21:0]
- * indicate dma total transfer length and
- * zero of [21:0] indicate dma total transfer length
- * equal to 0x400000 (4MB)*/
- if (finishedData == 0)
- finishedData = 0x00400000;
- if (finishedData != SMI_TS_DMA_BUF_SIZE) {
- dev_dbg(&dev->pci_dev->dev,
- "DMA CH1 engine complete length mismatched, finish data=%d !\n",
- finishedData);
- }
- dvb_dmx_swfilter_packets(&port->demux,
- port->cpu_addr[1], (finishedData / 188));
- /*dvb_dmx_swfilter(&port->demux,
- port->cpu_addr[1], finishedData);*/
- }
- /* restart DMA.*/
- if (intr_status & port->_dmaInterruptCH0)
- dmaManagement |= 0x00000002;
- if (intr_status & port->_dmaInterruptCH1)
- dmaManagement |= 0x00020000;
- smi_write(port->DMA_MANAGEMENT, dmaManagement);
- /* Re-enable interrupts */
- smi_port_enableInterrupt(port);
-}
-
-static void smi_port_dma_free(struct smi_port *port)
-{
- if (port->cpu_addr[0]) {
- pci_free_consistent(port->dev->pci_dev, SMI_TS_DMA_BUF_SIZE,
- port->cpu_addr[0], port->dma_addr[0]);
- port->cpu_addr[0] = NULL;
- }
- if (port->cpu_addr[1]) {
- pci_free_consistent(port->dev->pci_dev, SMI_TS_DMA_BUF_SIZE,
- port->cpu_addr[1], port->dma_addr[1]);
- port->cpu_addr[1] = NULL;
- }
-}
-
-static int smi_port_init(struct smi_port *port, int dmaChanUsed)
-{
- dev_dbg(&port->dev->pci_dev->dev,
- "%s, port %d, dmaused %d\n", __func__, port->idx, dmaChanUsed);
- port->enable = 0;
- if (port->idx == 0) {
- /* Port A */
- port->_dmaInterruptCH0 = dmaChanUsed & 0x01;
- port->_dmaInterruptCH1 = dmaChanUsed & 0x02;
-
- port->DMA_CHAN0_ADDR_LOW = DMA_PORTA_CHAN0_ADDR_LOW;
- port->DMA_CHAN0_ADDR_HI = DMA_PORTA_CHAN0_ADDR_HI;
- port->DMA_CHAN0_TRANS_STATE = DMA_PORTA_CHAN0_TRANS_STATE;
- port->DMA_CHAN0_CONTROL = DMA_PORTA_CHAN0_CONTROL;
- port->DMA_CHAN1_ADDR_LOW = DMA_PORTA_CHAN1_ADDR_LOW;
- port->DMA_CHAN1_ADDR_HI = DMA_PORTA_CHAN1_ADDR_HI;
- port->DMA_CHAN1_TRANS_STATE = DMA_PORTA_CHAN1_TRANS_STATE;
- port->DMA_CHAN1_CONTROL = DMA_PORTA_CHAN1_CONTROL;
- port->DMA_MANAGEMENT = DMA_PORTA_MANAGEMENT;
- } else {
- /* Port B */
- port->_dmaInterruptCH0 = (dmaChanUsed << 2) & 0x04;
- port->_dmaInterruptCH1 = (dmaChanUsed << 2) & 0x08;
-
- port->DMA_CHAN0_ADDR_LOW = DMA_PORTB_CHAN0_ADDR_LOW;
- port->DMA_CHAN0_ADDR_HI = DMA_PORTB_CHAN0_ADDR_HI;
- port->DMA_CHAN0_TRANS_STATE = DMA_PORTB_CHAN0_TRANS_STATE;
- port->DMA_CHAN0_CONTROL = DMA_PORTB_CHAN0_CONTROL;
- port->DMA_CHAN1_ADDR_LOW = DMA_PORTB_CHAN1_ADDR_LOW;
- port->DMA_CHAN1_ADDR_HI = DMA_PORTB_CHAN1_ADDR_HI;
- port->DMA_CHAN1_TRANS_STATE = DMA_PORTB_CHAN1_TRANS_STATE;
- port->DMA_CHAN1_CONTROL = DMA_PORTB_CHAN1_CONTROL;
- port->DMA_MANAGEMENT = DMA_PORTB_MANAGEMENT;
- }
-
- if (port->_dmaInterruptCH0) {
- port->cpu_addr[0] = pci_alloc_consistent(port->dev->pci_dev,
- SMI_TS_DMA_BUF_SIZE,
- &port->dma_addr[0]);
- if (!port->cpu_addr[0]) {
- dev_err(&port->dev->pci_dev->dev,
- "Port[%d] DMA CH0 memory allocation failed!\n",
- port->idx);
- goto err;
- }
- }
-
- if (port->_dmaInterruptCH1) {
- port->cpu_addr[1] = pci_alloc_consistent(port->dev->pci_dev,
- SMI_TS_DMA_BUF_SIZE,
- &port->dma_addr[1]);
- if (!port->cpu_addr[1]) {
- dev_err(&port->dev->pci_dev->dev,
- "Port[%d] DMA CH1 memory allocation failed!\n",
- port->idx);
- goto err;
- }
- }
-
- smi_port_disableInterrupt(port);
- tasklet_init(&port->tasklet, smi_dma_xfer, (unsigned long)port);
- tasklet_disable(&port->tasklet);
- port->enable = 1;
- return 0;
-err:
- smi_port_dma_free(port);
- return -ENOMEM;
-}
-
-static void smi_port_exit(struct smi_port *port)
-{
- smi_port_disableInterrupt(port);
- tasklet_kill(&port->tasklet);
- smi_port_dma_free(port);
- port->enable = 0;
-}
-
-static void smi_port_irq(struct smi_port *port, u32 int_status)
-{
- u32 port_req_irq = port->_dmaInterruptCH0 | port->_dmaInterruptCH1;
-
- if (int_status & port_req_irq) {
- smi_port_disableInterrupt(port);
- port->_int_status = int_status;
- smi_port_clearInterrupt(port);
- tasklet_schedule(&port->tasklet);
- }
-}
-
-static irqreturn_t smi_irq_handler(int irq, void *dev_id)
-{
- struct smi_dev *dev = dev_id;
- struct smi_port *port0 = &dev->ts_port[0];
- struct smi_port *port1 = &dev->ts_port[1];
-
- u32 intr_status = smi_read(MSI_INT_STATUS);
-
- /* ts0 interrupt.*/
- if (dev->info->ts_0)
- smi_port_irq(port0, intr_status);
-
- /* ts1 interrupt.*/
- if (dev->info->ts_1)
- smi_port_irq(port1, intr_status);
-
- return IRQ_HANDLED;
-}
-
-static struct i2c_client *smi_add_i2c_client(struct i2c_adapter *adapter,
- struct i2c_board_info *info)
-{
- struct i2c_client *client;
-
- request_module(info->type);
- client = i2c_new_device(adapter, info);
- if (client == NULL || client->dev.driver == NULL)
- goto err_add_i2c_client;
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- goto err_add_i2c_client;
- }
- return client;
-
-err_add_i2c_client:
- client = NULL;
- return client;
-}
-
-static void smi_del_i2c_client(struct i2c_client *client)
-{
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
-}
-
-static const struct m88ds3103_config smi_dvbsky_m88ds3103_cfg = {
- .i2c_addr = 0x68,
- .clock = 27000000,
- .i2c_wr_max = 33,
- .clock_out = 0,
- .ts_mode = M88DS3103_TS_PARALLEL,
- .ts_clk = 16000,
- .ts_clk_pol = 1,
- .agc = 0x99,
- .lnb_hv_pol = 0,
- .lnb_en_pol = 1,
-};
-
-static int smi_dvbsky_m88ds3103_fe_attach(struct smi_port *port)
-{
- int ret = 0;
- struct smi_dev *dev = port->dev;
- struct i2c_adapter *i2c;
- /* tuner I2C module */
- struct i2c_adapter *tuner_i2c_adapter;
- struct i2c_client *tuner_client;
- struct i2c_board_info tuner_info;
- struct m88ts2022_config m88ts2022_config = {
- .clock = 27000000,
- };
- memset(&tuner_info, 0, sizeof(struct i2c_board_info));
- i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];
-
- /* attach demod */
- port->fe = dvb_attach(m88ds3103_attach,
- &smi_dvbsky_m88ds3103_cfg, i2c, &tuner_i2c_adapter);
- if (!port->fe) {
- ret = -ENODEV;
- return ret;
- }
- /* attach tuner */
- m88ts2022_config.fe = port->fe;
- strlcpy(tuner_info.type, "m88ts2022", I2C_NAME_SIZE);
- tuner_info.addr = 0x60;
- tuner_info.platform_data = &m88ts2022_config;
- tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info);
- if (!tuner_client) {
- ret = -ENODEV;
- goto err_tuner_i2c_device;
- }
-
- /* delegate signal strength measurement to tuner */
- port->fe->ops.read_signal_strength =
- port->fe->ops.tuner_ops.get_rf_strength;
-
- port->i2c_client_tuner = tuner_client;
- return ret;
-
-err_tuner_i2c_device:
- dvb_frontend_detach(port->fe);
- return ret;
-}
-
-static const struct m88ds3103_config smi_dvbsky_m88rs6000_cfg = {
- .i2c_addr = 0x69,
- .clock = 27000000,
- .i2c_wr_max = 33,
- .ts_mode = M88DS3103_TS_PARALLEL,
- .ts_clk = 16000,
- .ts_clk_pol = 1,
- .agc = 0x99,
- .lnb_hv_pol = 0,
- .lnb_en_pol = 1,
-};
-
-static int smi_dvbsky_m88rs6000_fe_attach(struct smi_port *port)
-{
- int ret = 0;
- struct smi_dev *dev = port->dev;
- struct i2c_adapter *i2c;
- /* tuner I2C module */
- struct i2c_adapter *tuner_i2c_adapter;
- struct i2c_client *tuner_client;
- struct i2c_board_info tuner_info;
- struct m88rs6000t_config m88rs6000t_config;
-
- memset(&tuner_info, 0, sizeof(struct i2c_board_info));
- i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];
-
- /* attach demod */
- port->fe = dvb_attach(m88ds3103_attach,
- &smi_dvbsky_m88rs6000_cfg, i2c, &tuner_i2c_adapter);
- if (!port->fe) {
- ret = -ENODEV;
- return ret;
- }
- /* attach tuner */
- m88rs6000t_config.fe = port->fe;
- strlcpy(tuner_info.type, "m88rs6000t", I2C_NAME_SIZE);
- tuner_info.addr = 0x21;
- tuner_info.platform_data = &m88rs6000t_config;
- tuner_client = smi_add_i2c_client(tuner_i2c_adapter, &tuner_info);
- if (!tuner_client) {
- ret = -ENODEV;
- goto err_tuner_i2c_device;
- }
-
- /* delegate signal strength measurement to tuner */
- port->fe->ops.read_signal_strength =
- port->fe->ops.tuner_ops.get_rf_strength;
-
- port->i2c_client_tuner = tuner_client;
- return ret;
-
-err_tuner_i2c_device:
- dvb_frontend_detach(port->fe);
- return ret;
-}
-
-static int smi_dvbsky_sit2_fe_attach(struct smi_port *port)
-{
- int ret = 0;
- struct smi_dev *dev = port->dev;
- struct i2c_adapter *i2c;
- struct i2c_adapter *tuner_i2c_adapter;
- struct i2c_client *client_tuner, *client_demod;
- struct i2c_board_info client_info;
- struct si2168_config si2168_config;
- struct si2157_config si2157_config;
-
- /* select i2c bus */
- i2c = (port->idx == 0) ? &dev->i2c_bus[0] : &dev->i2c_bus[1];
-
- /* attach demod */
- memset(&si2168_config, 0, sizeof(si2168_config));
- si2168_config.i2c_adapter = &tuner_i2c_adapter;
- si2168_config.fe = &port->fe;
- si2168_config.ts_mode = SI2168_TS_PARALLEL;
-
- memset(&client_info, 0, sizeof(struct i2c_board_info));
- strlcpy(client_info.type, "si2168", I2C_NAME_SIZE);
- client_info.addr = 0x64;
- client_info.platform_data = &si2168_config;
-
- client_demod = smi_add_i2c_client(i2c, &client_info);
- if (!client_demod) {
- ret = -ENODEV;
- return ret;
- }
- port->i2c_client_demod = client_demod;
-
- /* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
- si2157_config.fe = port->fe;
-
- memset(&client_info, 0, sizeof(struct i2c_board_info));
- strlcpy(client_info.type, "si2157", I2C_NAME_SIZE);
- client_info.addr = 0x60;
- client_info.platform_data = &si2157_config;
-
- client_tuner = smi_add_i2c_client(tuner_i2c_adapter, &client_info);
- if (!client_tuner) {
- smi_del_i2c_client(port->i2c_client_demod);
- port->i2c_client_demod = NULL;
- ret = -ENODEV;
- return ret;
- }
- port->i2c_client_tuner = client_tuner;
- return ret;
-}
-
-static int smi_fe_init(struct smi_port *port)
-{
- int ret = 0;
- struct smi_dev *dev = port->dev;
- struct dvb_adapter *adap = &port->dvb_adapter;
- u8 mac_ee[16];
-
- dev_dbg(&port->dev->pci_dev->dev,
- "%s: port %d, fe_type = %d\n",
- __func__, port->idx, port->fe_type);
- switch (port->fe_type) {
- case DVBSKY_FE_M88DS3103:
- ret = smi_dvbsky_m88ds3103_fe_attach(port);
- break;
- case DVBSKY_FE_M88RS6000:
- ret = smi_dvbsky_m88rs6000_fe_attach(port);
- break;
- case DVBSKY_FE_SIT2:
- ret = smi_dvbsky_sit2_fe_attach(port);
- break;
- }
- if (ret < 0)
- return ret;
-
- /* register dvb frontend */
- ret = dvb_register_frontend(adap, port->fe);
- if (ret < 0) {
- if (port->i2c_client_tuner)
- smi_del_i2c_client(port->i2c_client_tuner);
- if (port->i2c_client_demod)
- smi_del_i2c_client(port->i2c_client_demod);
- dvb_frontend_detach(port->fe);
- return ret;
- }
- /* init MAC.*/
- ret = smi_read_eeprom(&dev->i2c_bus[0], 0xc0, mac_ee, 16);
- dev_info(&port->dev->pci_dev->dev,
- "DVBSky SMI PCIe MAC= %pM\n", mac_ee + (port->idx)*8);
- memcpy(adap->proposed_mac, mac_ee + (port->idx)*8, 6);
- return ret;
-}
-
-static void smi_fe_exit(struct smi_port *port)
-{
- dvb_unregister_frontend(port->fe);
- /* remove I2C demod and tuner */
- if (port->i2c_client_tuner)
- smi_del_i2c_client(port->i2c_client_tuner);
- if (port->i2c_client_demod)
- smi_del_i2c_client(port->i2c_client_demod);
- dvb_frontend_detach(port->fe);
-}
-
-static int my_dvb_dmx_ts_card_init(struct dvb_demux *dvbdemux, char *id,
- int (*start_feed)(struct dvb_demux_feed *),
- int (*stop_feed)(struct dvb_demux_feed *),
- void *priv)
-{
- dvbdemux->priv = priv;
-
- dvbdemux->filternum = 256;
- dvbdemux->feednum = 256;
- dvbdemux->start_feed = start_feed;
- dvbdemux->stop_feed = stop_feed;
- dvbdemux->write_to_decoder = NULL;
- dvbdemux->dmx.capabilities = (DMX_TS_FILTERING |
- DMX_SECTION_FILTERING |
- DMX_MEMORY_BASED_FILTERING);
- return dvb_dmx_init(dvbdemux);
-}
-
-static int my_dvb_dmxdev_ts_card_init(struct dmxdev *dmxdev,
- struct dvb_demux *dvbdemux,
- struct dmx_frontend *hw_frontend,
- struct dmx_frontend *mem_frontend,
- struct dvb_adapter *dvb_adapter)
-{
- int ret;
-
- dmxdev->filternum = 256;
- dmxdev->demux = &dvbdemux->dmx;
- dmxdev->capabilities = 0;
- ret = dvb_dmxdev_init(dmxdev, dvb_adapter);
- if (ret < 0)
- return ret;
-
- hw_frontend->source = DMX_FRONTEND_0;
- dvbdemux->dmx.add_frontend(&dvbdemux->dmx, hw_frontend);
- mem_frontend->source = DMX_MEMORY_FE;
- dvbdemux->dmx.add_frontend(&dvbdemux->dmx, mem_frontend);
- return dvbdemux->dmx.connect_frontend(&dvbdemux->dmx, hw_frontend);
-}
-
-static u32 smi_config_DMA(struct smi_port *port)
-{
- struct smi_dev *dev = port->dev;
- u32 totalLength = 0, dmaMemPtrLow, dmaMemPtrHi, dmaCtlReg;
- u8 chanLatencyTimer = 0, dmaChanEnable = 1, dmaTransStart = 1;
- u32 dmaManagement = 0, tlpTransUnit = DMA_TRANS_UNIT_188;
- u8 tlpTc = 0, tlpTd = 1, tlpEp = 0, tlpAttr = 0;
- u64 mem;
-
- dmaManagement = smi_read(port->DMA_MANAGEMENT);
- /* Setup Channel-0 */
- if (port->_dmaInterruptCH0) {
- totalLength = SMI_TS_DMA_BUF_SIZE;
- mem = port->dma_addr[0];
- dmaMemPtrLow = mem & 0xffffffff;
- dmaMemPtrHi = mem >> 32;
- dmaCtlReg = (totalLength) | (tlpTransUnit << 22) | (tlpTc << 25)
- | (tlpTd << 28) | (tlpEp << 29) | (tlpAttr << 30);
- dmaManagement |= dmaChanEnable | (dmaTransStart << 1)
- | (chanLatencyTimer << 8);
- /* write DMA register, start DMA engine */
- smi_write(port->DMA_CHAN0_ADDR_LOW, dmaMemPtrLow);
- smi_write(port->DMA_CHAN0_ADDR_HI, dmaMemPtrHi);
- smi_write(port->DMA_CHAN0_CONTROL, dmaCtlReg);
- }
- /* Setup Channel-1 */
- if (port->_dmaInterruptCH1) {
- totalLength = SMI_TS_DMA_BUF_SIZE;
- mem = port->dma_addr[1];
- dmaMemPtrLow = mem & 0xffffffff;
- dmaMemPtrHi = mem >> 32;
- dmaCtlReg = (totalLength) | (tlpTransUnit << 22) | (tlpTc << 25)
- | (tlpTd << 28) | (tlpEp << 29) | (tlpAttr << 30);
- dmaManagement |= (dmaChanEnable << 16) | (dmaTransStart << 17)
- | (chanLatencyTimer << 24);
- /* write DMA register, start DMA engine */
- smi_write(port->DMA_CHAN1_ADDR_LOW, dmaMemPtrLow);
- smi_write(port->DMA_CHAN1_ADDR_HI, dmaMemPtrHi);
- smi_write(port->DMA_CHAN1_CONTROL, dmaCtlReg);
- }
- return dmaManagement;
-}
-
-static int smi_start_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
- struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
- struct smi_port *port = dvbdmx->priv;
- struct smi_dev *dev = port->dev;
- u32 dmaManagement;
-
- if (port->users++ == 0) {
- dmaManagement = smi_config_DMA(port);
- smi_port_clearInterrupt(port);
- smi_port_enableInterrupt(port);
- smi_write(port->DMA_MANAGEMENT, dmaManagement);
- tasklet_enable(&port->tasklet);
- }
- return port->users;
-}
-
-static int smi_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
-{
- struct dvb_demux *dvbdmx = dvbdmxfeed->demux;
- struct smi_port *port = dvbdmx->priv;
- struct smi_dev *dev = port->dev;
-
- if (--port->users)
- return port->users;
-
- tasklet_disable(&port->tasklet);
- smi_port_disableInterrupt(port);
- smi_clear(port->DMA_MANAGEMENT, 0x30003);
- return 0;
-}
-
-static int smi_dvb_init(struct smi_port *port)
-{
- int ret;
- struct dvb_adapter *adap = &port->dvb_adapter;
- struct dvb_demux *dvbdemux = &port->demux;
-
- dev_dbg(&port->dev->pci_dev->dev,
- "%s, port %d\n", __func__, port->idx);
-
- ret = dvb_register_adapter(adap, "SMI_DVB", THIS_MODULE,
- &port->dev->pci_dev->dev,
- adapter_nr);
- if (ret < 0) {
- dev_err(&port->dev->pci_dev->dev, "Fail to register DVB adapter.\n");
- return ret;
- }
- ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
- smi_start_feed,
- smi_stop_feed, port);
- if (ret < 0)
- goto err_del_dvb_register_adapter;
-
- ret = my_dvb_dmxdev_ts_card_init(&port->dmxdev, &port->demux,
- &port->hw_frontend,
- &port->mem_frontend, adap);
- if (ret < 0)
- goto err_del_dvb_dmx;
-
- ret = dvb_net_init(adap, &port->dvbnet, port->dmxdev.demux);
- if (ret < 0)
- goto err_del_dvb_dmxdev;
- return 0;
-err_del_dvb_dmxdev:
- dvbdemux->dmx.close(&dvbdemux->dmx);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->hw_frontend);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->mem_frontend);
- dvb_dmxdev_release(&port->dmxdev);
-err_del_dvb_dmx:
- dvb_dmx_release(&port->demux);
-err_del_dvb_register_adapter:
- dvb_unregister_adapter(&port->dvb_adapter);
- return ret;
-}
-
-static void smi_dvb_exit(struct smi_port *port)
-{
- struct dvb_demux *dvbdemux = &port->demux;
-
- dvb_net_release(&port->dvbnet);
-
- dvbdemux->dmx.close(&dvbdemux->dmx);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->hw_frontend);
- dvbdemux->dmx.remove_frontend(&dvbdemux->dmx, &port->mem_frontend);
- dvb_dmxdev_release(&port->dmxdev);
- dvb_dmx_release(&port->demux);
-
- dvb_unregister_adapter(&port->dvb_adapter);
-}
-
-static int smi_port_attach(struct smi_dev *dev,
- struct smi_port *port, int index)
-{
- int ret, dmachs;
-
- port->dev = dev;
- port->idx = index;
- port->fe_type = (index == 0) ? dev->info->fe_0 : dev->info->fe_1;
- dmachs = (index == 0) ? dev->info->ts_0 : dev->info->ts_1;
- /* port init.*/
- ret = smi_port_init(port, dmachs);
- if (ret < 0)
- return ret;
- /* dvb init.*/
- ret = smi_dvb_init(port);
- if (ret < 0)
- goto err_del_port_init;
- /* fe init.*/
- ret = smi_fe_init(port);
- if (ret < 0)
- goto err_del_dvb_init;
- return 0;
-err_del_dvb_init:
- smi_dvb_exit(port);
-err_del_port_init:
- smi_port_exit(port);
- return ret;
-}
-
-static void smi_port_detach(struct smi_port *port)
-{
- smi_fe_exit(port);
- smi_dvb_exit(port);
- smi_port_exit(port);
-}
-
-static int smi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
-{
- struct smi_dev *dev;
- int ret = -ENOMEM;
-
- if (pci_enable_device(pdev) < 0)
- return -ENODEV;
-
- dev = kzalloc(sizeof(struct smi_dev), GFP_KERNEL);
- if (!dev) {
- ret = -ENOMEM;
- goto err_pci_disable_device;
- }
-
- dev->pci_dev = pdev;
- pci_set_drvdata(pdev, dev);
- dev->info = (struct smi_cfg_info *) id->driver_data;
- dev_info(&dev->pci_dev->dev,
- "card detected: %s\n", dev->info->name);
-
- dev->nr = dev->info->type;
- dev->lmmio = ioremap(pci_resource_start(dev->pci_dev, 0),
- pci_resource_len(dev->pci_dev, 0));
- if (!dev->lmmio) {
- ret = -ENOMEM;
- goto err_kfree;
- }
-
- /* should we set to 32bit DMA? */
- ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
- if (ret < 0)
- goto err_pci_iounmap;
-
- pci_set_master(pdev);
-
- ret = smi_hw_init(dev);
- if (ret < 0)
- goto err_pci_iounmap;
-
- ret = smi_i2c_init(dev);
- if (ret < 0)
- goto err_pci_iounmap;
-
- if (dev->info->ts_0) {
- ret = smi_port_attach(dev, &dev->ts_port[0], 0);
- if (ret < 0)
- goto err_del_i2c_adaptor;
- }
-
- if (dev->info->ts_1) {
- ret = smi_port_attach(dev, &dev->ts_port[1], 1);
- if (ret < 0)
- goto err_del_port0_attach;
- }
-
-#ifdef CONFIG_PCI_MSI /* to do msi interrupt.???*/
- if (pci_msi_enabled())
- ret = pci_enable_msi(dev->pci_dev);
- if (ret)
- dev_info(&dev->pci_dev->dev, "MSI not available.\n");
-#endif
-
- ret = request_irq(dev->pci_dev->irq, smi_irq_handler,
- IRQF_SHARED, "SMI_PCIE", dev);
- if (ret < 0)
- goto err_del_port1_attach;
-
- return 0;
-
-err_del_port1_attach:
- if (dev->info->ts_1)
- smi_port_detach(&dev->ts_port[1]);
-err_del_port0_attach:
- if (dev->info->ts_0)
- smi_port_detach(&dev->ts_port[0]);
-err_del_i2c_adaptor:
- smi_i2c_exit(dev);
-err_pci_iounmap:
- iounmap(dev->lmmio);
-err_kfree:
- pci_set_drvdata(pdev, NULL);
- kfree(dev);
-err_pci_disable_device:
- pci_disable_device(pdev);
- return ret;
-}
-
-static void smi_remove(struct pci_dev *pdev)
-{
- struct smi_dev *dev = pci_get_drvdata(pdev);
-
- smi_write(MSI_INT_ENA_CLR, ALL_INT);
- free_irq(dev->pci_dev->irq, dev);
-#ifdef CONFIG_PCI_MSI
- pci_disable_msi(dev->pci_dev);
-#endif
- if (dev->info->ts_1)
- smi_port_detach(&dev->ts_port[1]);
- if (dev->info->ts_0)
- smi_port_detach(&dev->ts_port[0]);
-
- smi_i2c_exit(dev);
- iounmap(dev->lmmio);
- pci_set_drvdata(pdev, NULL);
- pci_disable_device(pdev);
- kfree(dev);
-}
-
-/* DVBSky cards */
-static struct smi_cfg_info dvbsky_s950_cfg = {
- .type = SMI_DVBSKY_S950,
- .name = "DVBSky S950 V3",
- .ts_0 = SMI_TS_NULL,
- .ts_1 = SMI_TS_DMA_BOTH,
- .fe_0 = DVBSKY_FE_NULL,
- .fe_1 = DVBSKY_FE_M88DS3103,
-};
-
-static struct smi_cfg_info dvbsky_s952_cfg = {
- .type = SMI_DVBSKY_S952,
- .name = "DVBSky S952 V3",
- .ts_0 = SMI_TS_DMA_BOTH,
- .ts_1 = SMI_TS_DMA_BOTH,
- .fe_0 = DVBSKY_FE_M88RS6000,
- .fe_1 = DVBSKY_FE_M88RS6000,
-};
-
-static struct smi_cfg_info dvbsky_t9580_cfg = {
- .type = SMI_DVBSKY_T9580,
- .name = "DVBSky T9580 V3",
- .ts_0 = SMI_TS_DMA_BOTH,
- .ts_1 = SMI_TS_DMA_BOTH,
- .fe_0 = DVBSKY_FE_SIT2,
- .fe_1 = DVBSKY_FE_M88DS3103,
-};
-
-/* PCI IDs */
-#define SMI_ID(_subvend, _subdev, _driverdata) { \
- .vendor = SMI_VID, .device = SMI_PID, \
- .subvendor = _subvend, .subdevice = _subdev, \
- .driver_data = (unsigned long)&_driverdata }
-
-static const struct pci_device_id smi_id_table[] = {
- SMI_ID(0x4254, 0x0550, dvbsky_s950_cfg),
- SMI_ID(0x4254, 0x0552, dvbsky_s952_cfg),
- SMI_ID(0x4254, 0x5580, dvbsky_t9580_cfg),
- {0}
-};
-MODULE_DEVICE_TABLE(pci, smi_id_table);
-
-static struct pci_driver smipcie_driver = {
- .name = "SMI PCIe driver",
- .id_table = smi_id_table,
- .probe = smi_probe,
- .remove = smi_remove,
-};
-
-module_pci_driver(smipcie_driver);
-
-MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
-MODULE_DESCRIPTION("SMI PCIe driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/pci/smipcie/smipcie.h b/drivers/media/pci/smipcie/smipcie.h
deleted file mode 100644
index 10cdf20..0000000
--- a/drivers/media/pci/smipcie/smipcie.h
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * SMI PCIe driver for DVBSky cards.
- *
- * Copyright (C) 2014 Max nibble <nibble.max@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.
- *
- * 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 _SMI_PCIE_H_
-#define _SMI_PCIE_H_
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/proc_fs.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <media/rc-core.h>
-
-#include "demux.h"
-#include "dmxdev.h"
-#include "dvb_demux.h"
-#include "dvb_frontend.h"
-#include "dvb_net.h"
-#include "dvbdev.h"
-
-/* -------- Register Base -------- */
-#define MSI_CONTROL_REG_BASE 0x0800
-#define SYSTEM_CONTROL_REG_BASE 0x0880
-#define PCIE_EP_DEBUG_REG_BASE 0x08C0
-#define IR_CONTROL_REG_BASE 0x0900
-#define I2C_A_CONTROL_REG_BASE 0x0940
-#define I2C_B_CONTROL_REG_BASE 0x0980
-#define ATV_PORTA_CONTROL_REG_BASE 0x09C0
-#define DTV_PORTA_CONTROL_REG_BASE 0x0A00
-#define AES_PORTA_CONTROL_REG_BASE 0x0A80
-#define DMA_PORTA_CONTROL_REG_BASE 0x0AC0
-#define ATV_PORTB_CONTROL_REG_BASE 0x0B00
-#define DTV_PORTB_CONTROL_REG_BASE 0x0B40
-#define AES_PORTB_CONTROL_REG_BASE 0x0BC0
-#define DMA_PORTB_CONTROL_REG_BASE 0x0C00
-#define UART_A_REGISTER_BASE 0x0C40
-#define UART_B_REGISTER_BASE 0x0C80
-#define GPS_CONTROL_REG_BASE 0x0CC0
-#define DMA_PORTC_CONTROL_REG_BASE 0x0D00
-#define DMA_PORTD_CONTROL_REG_BASE 0x0D00
-#define AES_RANDOM_DATA_BASE 0x0D80
-#define AES_KEY_IN_BASE 0x0D90
-#define RANDOM_DATA_LIB_BASE 0x0E00
-#define IR_DATA_BUFFER_BASE 0x0F00
-#define PORTA_TS_BUFFER_BASE 0x1000
-#define PORTA_I2S_BUFFER_BASE 0x1400
-#define PORTB_TS_BUFFER_BASE 0x1800
-#define PORTB_I2S_BUFFER_BASE 0x1C00
-
-/* -------- MSI control and state register -------- */
-#define MSI_DELAY_TIMER (MSI_CONTROL_REG_BASE + 0x00)
-#define MSI_INT_STATUS (MSI_CONTROL_REG_BASE + 0x08)
-#define MSI_INT_STATUS_CLR (MSI_CONTROL_REG_BASE + 0x0C)
-#define MSI_INT_STATUS_SET (MSI_CONTROL_REG_BASE + 0x10)
-#define MSI_INT_ENA (MSI_CONTROL_REG_BASE + 0x14)
-#define MSI_INT_ENA_CLR (MSI_CONTROL_REG_BASE + 0x18)
-#define MSI_INT_ENA_SET (MSI_CONTROL_REG_BASE + 0x1C)
-#define MSI_SOFT_RESET (MSI_CONTROL_REG_BASE + 0x20)
-#define MSI_CFG_SRC0 (MSI_CONTROL_REG_BASE + 0x24)
-
-/* -------- Hybird Controller System Control register -------- */
-#define MUX_MODE_CTRL (SYSTEM_CONTROL_REG_BASE + 0x00)
- #define rbPaMSMask 0x07
- #define rbPaMSDtvNoGpio 0x00 /*[2:0], DTV Simple mode */
- #define rbPaMSDtv4bitGpio 0x01 /*[2:0], DTV TS2 Serial mode)*/
- #define rbPaMSDtv7bitGpio 0x02 /*[2:0], DTV TS0 Serial mode*/
- #define rbPaMS8bitGpio 0x03 /*[2:0], GPIO mode selected;(8bit GPIO)*/
- #define rbPaMSAtv 0x04 /*[2:0], 3'b1xx: ATV mode select*/
- #define rbPbMSMask 0x38
- #define rbPbMSDtvNoGpio 0x00 /*[5:3], DTV Simple mode */
- #define rbPbMSDtv4bitGpio 0x08 /*[5:3], DTV TS2 Serial mode*/
- #define rbPbMSDtv7bitGpio 0x10 /*[5:3], DTV TS0 Serial mode*/
- #define rbPbMS8bitGpio 0x18 /*[5:3], GPIO mode selected;(8bit GPIO)*/
- #define rbPbMSAtv 0x20 /*[5:3], 3'b1xx: ATV mode select*/
- #define rbPaAESEN 0x40 /*[6], port A AES enable bit*/
- #define rbPbAESEN 0x80 /*[7], port B AES enable bit*/
-
-#define INTERNAL_RST (SYSTEM_CONTROL_REG_BASE + 0x04)
-#define PERIPHERAL_CTRL (SYSTEM_CONTROL_REG_BASE + 0x08)
-#define GPIO_0to7_CTRL (SYSTEM_CONTROL_REG_BASE + 0x0C)
-#define GPIO_8to15_CTRL (SYSTEM_CONTROL_REG_BASE + 0x10)
-#define GPIO_16to24_CTRL (SYSTEM_CONTROL_REG_BASE + 0x14)
-#define GPIO_INT_SRC_CFG (SYSTEM_CONTROL_REG_BASE + 0x18)
-#define SYS_BUF_STATUS (SYSTEM_CONTROL_REG_BASE + 0x1C)
-#define PCIE_IP_REG_ACS (SYSTEM_CONTROL_REG_BASE + 0x20)
-#define PCIE_IP_REG_ACS_ADDR (SYSTEM_CONTROL_REG_BASE + 0x24)
-#define PCIE_IP_REG_ACS_DATA (SYSTEM_CONTROL_REG_BASE + 0x28)
-
-/* -------- IR Control register -------- */
-#define IR_Init_Reg (IR_CONTROL_REG_BASE + 0x00)
-#define IR_Idle_Cnt_Low (IR_CONTROL_REG_BASE + 0x04)
-#define IR_Idle_Cnt_High (IR_CONTROL_REG_BASE + 0x05)
-#define IR_Unit_Cnt_Low (IR_CONTROL_REG_BASE + 0x06)
-#define IR_Unit_Cnt_High (IR_CONTROL_REG_BASE + 0x07)
-#define IR_Data_Cnt (IR_CONTROL_REG_BASE + 0x08)
-#define rbIRen 0x80
-#define rbIRhighidle 0x10
-#define rbIRlowidle 0x00
-#define rbIRVld 0x04
-
-/* -------- I2C A control and state register -------- */
-#define I2C_A_CTL_STATUS (I2C_A_CONTROL_REG_BASE + 0x00)
-#define I2C_A_ADDR (I2C_A_CONTROL_REG_BASE + 0x04)
-#define I2C_A_SW_CTL (I2C_A_CONTROL_REG_BASE + 0x08)
-#define I2C_A_TIME_OUT_CNT (I2C_A_CONTROL_REG_BASE + 0x0C)
-#define I2C_A_FIFO_STATUS (I2C_A_CONTROL_REG_BASE + 0x10)
-#define I2C_A_FS_EN (I2C_A_CONTROL_REG_BASE + 0x14)
-#define I2C_A_FIFO_DATA (I2C_A_CONTROL_REG_BASE + 0x20)
-
-/* -------- I2C B control and state register -------- */
-#define I2C_B_CTL_STATUS (I2C_B_CONTROL_REG_BASE + 0x00)
-#define I2C_B_ADDR (I2C_B_CONTROL_REG_BASE + 0x04)
-#define I2C_B_SW_CTL (I2C_B_CONTROL_REG_BASE + 0x08)
-#define I2C_B_TIME_OUT_CNT (I2C_B_CONTROL_REG_BASE + 0x0C)
-#define I2C_B_FIFO_STATUS (I2C_B_CONTROL_REG_BASE + 0x10)
-#define I2C_B_FS_EN (I2C_B_CONTROL_REG_BASE + 0x14)
-#define I2C_B_FIFO_DATA (I2C_B_CONTROL_REG_BASE + 0x20)
-
-#define VIDEO_CTRL_STATUS_A (ATV_PORTA_CONTROL_REG_BASE + 0x04)
-
-/* -------- Digital TV control register, Port A -------- */
-#define MPEG2_CTRL_A (DTV_PORTA_CONTROL_REG_BASE + 0x00)
-#define SERIAL_IN_ADDR_A (DTV_PORTA_CONTROL_REG_BASE + 0x4C)
-#define VLD_CNT_ADDR_A (DTV_PORTA_CONTROL_REG_BASE + 0x60)
-#define ERR_CNT_ADDR_A (DTV_PORTA_CONTROL_REG_BASE + 0x64)
-#define BRD_CNT_ADDR_A (DTV_PORTA_CONTROL_REG_BASE + 0x68)
-
-/* -------- DMA Control Register, Port A -------- */
-#define DMA_PORTA_CHAN0_ADDR_LOW (DMA_PORTA_CONTROL_REG_BASE + 0x00)
-#define DMA_PORTA_CHAN0_ADDR_HI (DMA_PORTA_CONTROL_REG_BASE + 0x04)
-#define DMA_PORTA_CHAN0_TRANS_STATE (DMA_PORTA_CONTROL_REG_BASE + 0x08)
-#define DMA_PORTA_CHAN0_CONTROL (DMA_PORTA_CONTROL_REG_BASE + 0x0C)
-#define DMA_PORTA_CHAN1_ADDR_LOW (DMA_PORTA_CONTROL_REG_BASE + 0x10)
-#define DMA_PORTA_CHAN1_ADDR_HI (DMA_PORTA_CONTROL_REG_BASE + 0x14)
-#define DMA_PORTA_CHAN1_TRANS_STATE (DMA_PORTA_CONTROL_REG_BASE + 0x18)
-#define DMA_PORTA_CHAN1_CONTROL (DMA_PORTA_CONTROL_REG_BASE + 0x1C)
-#define DMA_PORTA_MANAGEMENT (DMA_PORTA_CONTROL_REG_BASE + 0x20)
-#define VIDEO_CTRL_STATUS_B (ATV_PORTB_CONTROL_REG_BASE + 0x04)
-
-/* -------- Digital TV control register, Port B -------- */
-#define MPEG2_CTRL_B (DTV_PORTB_CONTROL_REG_BASE + 0x00)
-#define SERIAL_IN_ADDR_B (DTV_PORTB_CONTROL_REG_BASE + 0x4C)
-#define VLD_CNT_ADDR_B (DTV_PORTB_CONTROL_REG_BASE + 0x60)
-#define ERR_CNT_ADDR_B (DTV_PORTB_CONTROL_REG_BASE + 0x64)
-#define BRD_CNT_ADDR_B (DTV_PORTB_CONTROL_REG_BASE + 0x68)
-
-/* -------- AES control register, Port B -------- */
-#define AES_CTRL_B (AES_PORTB_CONTROL_REG_BASE + 0x00)
-#define AES_KEY_BASE_B (AES_PORTB_CONTROL_REG_BASE + 0x04)
-
-/* -------- DMA Control Register, Port B -------- */
-#define DMA_PORTB_CHAN0_ADDR_LOW (DMA_PORTB_CONTROL_REG_BASE + 0x00)
-#define DMA_PORTB_CHAN0_ADDR_HI (DMA_PORTB_CONTROL_REG_BASE + 0x04)
-#define DMA_PORTB_CHAN0_TRANS_STATE (DMA_PORTB_CONTROL_REG_BASE + 0x08)
-#define DMA_PORTB_CHAN0_CONTROL (DMA_PORTB_CONTROL_REG_BASE + 0x0C)
-#define DMA_PORTB_CHAN1_ADDR_LOW (DMA_PORTB_CONTROL_REG_BASE + 0x10)
-#define DMA_PORTB_CHAN1_ADDR_HI (DMA_PORTB_CONTROL_REG_BASE + 0x14)
-#define DMA_PORTB_CHAN1_TRANS_STATE (DMA_PORTB_CONTROL_REG_BASE + 0x18)
-#define DMA_PORTB_CHAN1_CONTROL (DMA_PORTB_CONTROL_REG_BASE + 0x1C)
-#define DMA_PORTB_MANAGEMENT (DMA_PORTB_CONTROL_REG_BASE + 0x20)
-
-#define DMA_TRANS_UNIT_188 (0x00000007)
-
-/* -------- Macro define of 24 interrupt resource --------*/
-#define DMA_A_CHAN0_DONE_INT (0x00000001)
-#define DMA_A_CHAN1_DONE_INT (0x00000002)
-#define DMA_B_CHAN0_DONE_INT (0x00000004)
-#define DMA_B_CHAN1_DONE_INT (0x00000008)
-#define DMA_C_CHAN0_DONE_INT (0x00000010)
-#define DMA_C_CHAN1_DONE_INT (0x00000020)
-#define DMA_D_CHAN0_DONE_INT (0x00000040)
-#define DMA_D_CHAN1_DONE_INT (0x00000080)
-#define DATA_BUF_OVERFLOW_INT (0x00000100)
-#define UART_0_X_INT (0x00000200)
-#define UART_1_X_INT (0x00000400)
-#define IR_X_INT (0x00000800)
-#define GPIO_0_INT (0x00001000)
-#define GPIO_1_INT (0x00002000)
-#define GPIO_2_INT (0x00004000)
-#define GPIO_3_INT (0x00008000)
-#define ALL_INT (0x0000FFFF)
-
-/* software I2C bit mask */
-#define SW_I2C_MSK_MODE 0x01
-#define SW_I2C_MSK_CLK_OUT 0x02
-#define SW_I2C_MSK_DAT_OUT 0x04
-#define SW_I2C_MSK_CLK_EN 0x08
-#define SW_I2C_MSK_DAT_EN 0x10
-#define SW_I2C_MSK_DAT_IN 0x40
-#define SW_I2C_MSK_CLK_IN 0x80
-
-#define SMI_VID 0x1ADE
-#define SMI_PID 0x3038
-#define SMI_TS_DMA_BUF_SIZE (1024 * 188)
-
-struct smi_cfg_info {
-#define SMI_DVBSKY_S952 0
-#define SMI_DVBSKY_S950 1
-#define SMI_DVBSKY_T9580 2
-#define SMI_DVBSKY_T982 3
- int type;
- char *name;
-#define SMI_TS_NULL 0
-#define SMI_TS_DMA_SINGLE 1
-#define SMI_TS_DMA_BOTH 3
-/* SMI_TS_NULL: not use;
- * SMI_TS_DMA_SINGLE: use DMA 0 only;
- * SMI_TS_DMA_BOTH:use DMA 0 and 1.*/
- int ts_0;
- int ts_1;
-#define DVBSKY_FE_NULL 0
-#define DVBSKY_FE_M88RS6000 1
-#define DVBSKY_FE_M88DS3103 2
-#define DVBSKY_FE_SIT2 3
- int fe_0;
- int fe_1;
-};
-
-struct smi_port {
- struct smi_dev *dev;
- int idx;
- int enable;
- int fe_type;
- /* regs */
- u32 DMA_CHAN0_ADDR_LOW;
- u32 DMA_CHAN0_ADDR_HI;
- u32 DMA_CHAN0_TRANS_STATE;
- u32 DMA_CHAN0_CONTROL;
- u32 DMA_CHAN1_ADDR_LOW;
- u32 DMA_CHAN1_ADDR_HI;
- u32 DMA_CHAN1_TRANS_STATE;
- u32 DMA_CHAN1_CONTROL;
- u32 DMA_MANAGEMENT;
- /* dma */
- dma_addr_t dma_addr[2];
- u8 *cpu_addr[2];
- u32 _dmaInterruptCH0;
- u32 _dmaInterruptCH1;
- u32 _int_status;
- struct tasklet_struct tasklet;
- /* dvb */
- struct dmx_frontend hw_frontend;
- struct dmx_frontend mem_frontend;
- struct dmxdev dmxdev;
- struct dvb_adapter dvb_adapter;
- struct dvb_demux demux;
- struct dvb_net dvbnet;
- int users;
- struct dvb_frontend *fe;
- /* frontend i2c module */
- struct i2c_client *i2c_client_demod;
- struct i2c_client *i2c_client_tuner;
-};
-
-struct smi_dev {
- int nr;
- struct smi_cfg_info *info;
-
- /* pcie */
- struct pci_dev *pci_dev;
- u32 __iomem *lmmio;
-
- /* ts port */
- struct smi_port ts_port[2];
-
- /* i2c */
- struct i2c_adapter i2c_bus[2];
- struct i2c_algo_bit_data i2c_bit[2];
-};
-
-#define smi_read(reg) readl(dev->lmmio + ((reg)>>2))
-#define smi_write(reg, value) writel((value), dev->lmmio + ((reg)>>2))
-
-#define smi_andor(reg, mask, value) \
- writel((readl(dev->lmmio+((reg)>>2)) & ~(mask)) |\
- ((value) & (mask)), dev->lmmio+((reg)>>2))
-
-#define smi_set(reg, bit) smi_andor((reg), (bit), (bit))
-#define smi_clear(reg, bit) smi_andor((reg), (bit), 0)
-
-#endif /* #ifndef _SMI_PCIE_H_ */
diff --git a/drivers/media/pci/solo6x10/solo6x10-core.c b/drivers/media/pci/solo6x10/solo6x10-core.c
index 8cbe6b4..172583d 100644
--- a/drivers/media/pci/solo6x10/solo6x10-core.c
+++ b/drivers/media/pci/solo6x10/solo6x10-core.c
@@ -105,8 +105,11 @@
if (!status)
return IRQ_NONE;
- /* Acknowledge all interrupts immediately */
- solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
+ if (status & ~solo_dev->irq_mask) {
+ solo_reg_write(solo_dev, SOLO_IRQ_STAT,
+ status & ~solo_dev->irq_mask);
+ status &= solo_dev->irq_mask;
+ }
if (status & SOLO_IRQ_PCI_ERR)
solo_p2m_error_isr(solo_dev);
@@ -129,6 +132,9 @@
if (status & SOLO_IRQ_G723)
solo_g723_isr(solo_dev);
+ /* Clear all interrupts handled */
+ solo_reg_write(solo_dev, SOLO_IRQ_STAT, status);
+
return IRQ_HANDLED;
}
diff --git a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
index 6e933d3..28023f9 100644
--- a/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/media/pci/solo6x10/solo6x10-v4l2-enc.c
@@ -463,6 +463,7 @@
struct solo_dev *solo_dev = solo_enc->solo_dev;
struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
int frame_size;
+ int ret;
vb->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
@@ -472,10 +473,22 @@
frame_size = ALIGN(vop_jpeg_size(vh) + solo_enc->jpeg_len, DMA_ALIGN);
vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
- return solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
+ /* may discard all previous data in vbuf->sgl */
+ if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+ DMA_FROM_DEVICE))
+ return -ENOMEM;
+ ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
SOLO_JPEG_EXT_SIZE(solo_dev));
+ dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+ DMA_FROM_DEVICE);
+
+ /* add the header only after dma_unmap_sg() */
+ sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+ solo_enc->jpeg_header, solo_enc->jpeg_len);
+
+ return ret;
}
static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
@@ -485,6 +498,7 @@
struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
int frame_off, frame_size;
int skip = 0;
+ int ret;
if (vb2_plane_size(vb, 0) < vop_mpeg_size(vh))
return -EIO;
@@ -507,9 +521,21 @@
sizeof(*vh)) % SOLO_MP4E_EXT_SIZE(solo_dev);
frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
- return solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
+ /* may discard all previous data in vbuf->sgl */
+ if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+ DMA_FROM_DEVICE))
+ return -ENOMEM;
+ ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
SOLO_MP4E_EXT_ADDR(solo_dev),
SOLO_MP4E_EXT_SIZE(solo_dev));
+ dma_unmap_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+ DMA_FROM_DEVICE);
+
+ /* add the header only after dma_unmap_sg() */
+ if (!vop_type(vh))
+ sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
+ solo_enc->vop, solo_enc->vop_len);
+ return ret;
}
static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
@@ -677,7 +703,9 @@
if (timeout == -ERESTARTSYS || kthread_should_stop())
break;
+ solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
solo_handle_ring(solo_dev);
+ solo_irq_on(solo_dev, SOLO_IRQ_ENCODER);
try_to_freeze();
}
@@ -692,10 +720,7 @@
unsigned int *num_planes, unsigned int sizes[],
void *alloc_ctxs[])
{
- struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
-
sizes[0] = FRAME_BUF_SIZE;
- alloc_ctxs[0] = solo_enc->alloc_ctx;
*num_planes = 1;
if (*num_buffers < MIN_VID_BUFFERS)
@@ -745,51 +770,26 @@
static int solo_enc_start_streaming(struct vb2_queue *q, unsigned int count)
{
struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
+ int ret;
- return solo_enc_on(solo_enc);
+ ret = solo_enc_on(solo_enc);
+ if (ret)
+ return ret;
+ return solo_ring_start(solo_enc->solo_dev);
}
static void solo_enc_stop_streaming(struct vb2_queue *q)
{
struct solo_enc_dev *solo_enc = vb2_get_drv_priv(q);
- unsigned long flags;
- spin_lock_irqsave(&solo_enc->av_lock, flags);
solo_enc_off(solo_enc);
- while (!list_empty(&solo_enc->vidq_active)) {
- struct solo_vb2_buf *buf = list_entry(
- solo_enc->vidq_active.next,
- struct solo_vb2_buf, list);
-
- list_del(&buf->list);
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
- }
- spin_unlock_irqrestore(&solo_enc->av_lock, flags);
-}
-
-static void solo_enc_buf_finish(struct vb2_buffer *vb)
-{
- struct solo_enc_dev *solo_enc = vb2_get_drv_priv(vb->vb2_queue);
- struct sg_table *vbuf = vb2_dma_sg_plane_desc(vb, 0);
-
- switch (solo_enc->fmt) {
- case V4L2_PIX_FMT_MPEG4:
- case V4L2_PIX_FMT_H264:
- if (vb->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME)
- sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
- solo_enc->vop, solo_enc->vop_len);
- break;
- default: /* V4L2_PIX_FMT_MJPEG */
- sg_copy_from_buffer(vbuf->sgl, vbuf->nents,
- solo_enc->jpeg_header, solo_enc->jpeg_len);
- break;
- }
+ INIT_LIST_HEAD(&solo_enc->vidq_active);
+ solo_ring_stop(solo_enc->solo_dev);
}
static struct vb2_ops solo_enc_video_qops = {
.queue_setup = solo_enc_queue_setup,
.buf_queue = solo_enc_buf_queue,
- .buf_finish = solo_enc_buf_finish,
.start_streaming = solo_enc_start_streaming,
.stop_streaming = solo_enc_stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
@@ -1263,11 +1263,6 @@
return ERR_PTR(-ENOMEM);
hdl = &solo_enc->hdl;
- solo_enc->alloc_ctx = vb2_dma_sg_init_ctx(&solo_dev->pdev->dev);
- if (IS_ERR(solo_enc->alloc_ctx)) {
- ret = PTR_ERR(solo_enc->alloc_ctx);
- goto hdl_free;
- }
v4l2_ctrl_handler_init(hdl, 10);
v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
@@ -1371,7 +1366,6 @@
solo_enc->desc_items, solo_enc->desc_dma);
hdl_free:
v4l2_ctrl_handler_free(hdl);
- vb2_dma_sg_cleanup_ctx(solo_enc->alloc_ctx);
kfree(solo_enc);
return ERR_PTR(ret);
}
@@ -1381,12 +1375,8 @@
if (solo_enc == NULL)
return;
- pci_free_consistent(solo_enc->solo_dev->pdev,
- sizeof(struct solo_p2m_desc) * solo_enc->desc_nelts,
- solo_enc->desc_items, solo_enc->desc_dma);
video_unregister_device(solo_enc->vfd);
v4l2_ctrl_handler_free(&solo_enc->hdl);
- vb2_dma_sg_cleanup_ctx(solo_enc->alloc_ctx);
kfree(solo_enc);
}
@@ -1429,15 +1419,13 @@
solo_dev->v4l2_enc[0]->vfd->num,
solo_dev->v4l2_enc[solo_dev->nr_chans - 1]->vfd->num);
- return solo_ring_start(solo_dev);
+ return 0;
}
void solo_enc_v4l2_exit(struct solo_dev *solo_dev)
{
int i;
- solo_ring_stop(solo_dev);
-
for (i = 0; i < solo_dev->nr_chans; i++)
solo_enc_free(solo_dev->v4l2_enc[i]);
diff --git a/drivers/media/pci/solo6x10/solo6x10.h b/drivers/media/pci/solo6x10/solo6x10.h
index bd8edfa..72017b7 100644
--- a/drivers/media/pci/solo6x10/solo6x10.h
+++ b/drivers/media/pci/solo6x10/solo6x10.h
@@ -180,7 +180,6 @@
u32 sequence;
struct vb2_queue vidq;
struct list_head vidq_active;
- void *alloc_ctx;
int desc_count;
int desc_nelts;
struct solo_p2m_desc *desc_items;
diff --git a/drivers/media/pci/ttpci/budget-patch.c b/drivers/media/pci/ttpci/budget-patch.c
index a4d8867..2cb35c2 100644
--- a/drivers/media/pci/ttpci/budget-patch.c
+++ b/drivers/media/pci/ttpci/budget-patch.c
@@ -490,7 +490,7 @@
if(detected == 0)
printk("budget-patch not detected or saa7146 in non-default state.\n"
- "try enabling resetting of 7146 with MASK_31 in MC1 register\n");
+ "try enabling ressetting of 7146 with MASK_31 in MC1 register\n");
else
printk("BUDGET-PATCH DETECTED.\n");
diff --git a/drivers/media/pci/tw68/Kconfig b/drivers/media/pci/tw68/Kconfig
index 45b845e..61b3e24 100644
--- a/drivers/media/pci/tw68/Kconfig
+++ b/drivers/media/pci/tw68/Kconfig
@@ -2,6 +2,7 @@
tristate "Techwell tw68x Video For Linux"
depends on m
depends on VIDEO_DEV && PCI && VIDEO_V4L2
+ depends on I2C_ALGOBIT
select VIDEOBUF2_DMA_SG
---help---
Support for Techwell tw68xx based frame grabber boards.
diff --git a/drivers/media/pci/tw68/tw68-core.c b/drivers/media/pci/tw68/tw68-core.c
index c135165..a6fb48c 100644
--- a/drivers/media/pci/tw68/tw68-core.c
+++ b/drivers/media/pci/tw68/tw68-core.c
@@ -304,19 +304,13 @@
/* Then do any initialisation wanted before interrupts are on */
tw68_hw_init1(dev);
- dev->alloc_ctx = vb2_dma_sg_init_ctx(&pci_dev->dev);
- if (IS_ERR(dev->alloc_ctx)) {
- err = PTR_ERR(dev->alloc_ctx);
- goto fail3;
- }
-
/* get irq */
err = devm_request_irq(&pci_dev->dev, pci_dev->irq, tw68_irq,
- IRQF_SHARED, dev->name, dev);
+ IRQF_SHARED | IRQF_DISABLED, dev->name, dev);
if (err < 0) {
pr_err("%s: can't get IRQ %d\n",
dev->name, pci_dev->irq);
- goto fail4;
+ goto fail3;
}
/*
@@ -330,7 +324,7 @@
if (err < 0) {
pr_err("%s: can't register video device\n",
dev->name);
- goto fail5;
+ goto fail4;
}
tw_setl(TW68_INTMASK, dev->pci_irqmask);
@@ -339,10 +333,8 @@
return 0;
-fail5:
- video_unregister_device(&dev->vdev);
fail4:
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
+ video_unregister_device(&dev->vdev);
fail3:
iounmap(dev->lmmio);
fail2:
@@ -366,7 +358,6 @@
/* unregister */
video_unregister_device(&dev->vdev);
v4l2_ctrl_handler_free(&dev->hdl);
- vb2_dma_sg_cleanup_ctx(dev->alloc_ctx);
/* release resources */
iounmap(dev->lmmio);
diff --git a/drivers/media/pci/tw68/tw68-video.c b/drivers/media/pci/tw68/tw68-video.c
index abe6314..25f0cc8 100644
--- a/drivers/media/pci/tw68/tw68-video.c
+++ b/drivers/media/pci/tw68/tw68-video.c
@@ -384,7 +384,6 @@
unsigned tot_bufs = q->num_buffers + *num_buffers;
sizes[0] = (dev->fmt->depth * dev->width * dev->height) >> 3;
- alloc_ctxs[0] = dev->alloc_ctx;
/*
* We allow create_bufs, but only if the sizeimage is the same as the
* current sizeimage. The tw68_buffer_count calculation becomes quite
@@ -462,12 +461,17 @@
struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
unsigned size, bpl;
+ int rc;
size = (dev->width * dev->height * dev->fmt->depth) >> 3;
if (vb2_plane_size(vb, 0) < size)
return -EINVAL;
vb2_set_plane_payload(vb, 0, size);
+ rc = dma_map_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+ if (!rc)
+ return -EIO;
+
bpl = (dev->width * dev->fmt->depth) >> 3;
switch (dev->field) {
case V4L2_FIELD_TOP:
@@ -501,8 +505,11 @@
{
struct vb2_queue *vq = vb->vb2_queue;
struct tw68_dev *dev = vb2_get_drv_priv(vq);
+ struct sg_table *dma = vb2_dma_sg_plane_desc(vb, 0);
struct tw68_buf *buf = container_of(vb, struct tw68_buf, vb);
+ dma_unmap_sg(&dev->pci->dev, dma->sgl, dma->nents, DMA_FROM_DEVICE);
+
pci_free_consistent(dev->pci, buf->size, buf->cpu, buf->dma);
}
diff --git a/drivers/media/pci/tw68/tw68.h b/drivers/media/pci/tw68/tw68.h
index 7a7501b..2c8abe2 100644
--- a/drivers/media/pci/tw68/tw68.h
+++ b/drivers/media/pci/tw68/tw68.h
@@ -181,7 +181,6 @@
unsigned field;
struct vb2_queue vidq;
struct list_head active;
- void *alloc_ctx;
/* various v4l controls */
const struct tw68_tvnorm *tvnorm; /* video */
diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c
index 2b25d31..099d5fb 100644
--- a/drivers/media/pci/zoran/zoran_driver.c
+++ b/drivers/media/pci/zoran/zoran_driver.c
@@ -1528,9 +1528,8 @@
strncpy(cap->driver, "zoran", sizeof(cap->driver)-1);
snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s",
pci_name(zr->pci_dev));
- cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
- V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OVERLAY;
return 0;
}
diff --git a/drivers/media/pci/zoran/zoran_procfs.c b/drivers/media/pci/zoran/zoran_procfs.c
index 4376527..f7ceee0 100644
--- a/drivers/media/pci/zoran/zoran_procfs.c
+++ b/drivers/media/pci/zoran/zoran_procfs.c
@@ -157,8 +157,8 @@
return -EFAULT;
}
string[count] = 0;
- dprintk(4, KERN_INFO "%s: write_proc: name=%pD count=%zu zr=%p\n",
- ZR_DEVNAME(zr), file, count, zr);
+ dprintk(4, KERN_INFO "%s: write_proc: name=%s count=%zu zr=%p\n",
+ ZR_DEVNAME(zr), file->f_path.dentry->d_name.name, count, zr);
ldelim = " \t\n";
tdelim = "=";
line = strpbrk(sp, ldelim);
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 4a5f12a..56ec66e 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -58,7 +58,7 @@
In doubt, say N.
config VIDEO_TIMBERDALE
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Support for timberdale Video In/LogiWIN"
depends on m
depends on VIDEO_V4L2 && I2C && DMADEVICES
@@ -70,6 +70,15 @@
---help---
Add support for the Video In peripherial of the timberdale FPGA.
+config VIDEO_VINO
+ tristate "SGI Vino Video For Linux"
+ depends on m
+ depends on I2C && SGI_IP22 && VIDEO_V4L2
+ select VIDEO_SAA7191 if MEDIA_SUBDRV_AUTOSELECT
+ help
+ Say Y here to build in support for the Vino video input system found
+ on SGI Indy machines.
+
config VIDEO_M32R_AR
tristate "AR devices"
depends on m
@@ -113,7 +122,7 @@
tristate "Samsung S3C24XX/S3C64XX SoC Camera Interface driver"
depends on m
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
- depends on PM
+ depends on PM_RUNTIME
depends on ARCH_S3C64XX || PLAT_S3C24XX || COMPILE_TEST
depends on HAS_DMA
select VIDEOBUF2_DMA_CONTIG
@@ -157,7 +166,7 @@
H.264, MPEG-4, and other video formats.
config VIDEO_MEM2MEM_DEINTERLACE
- depends on !KERNEL_3_3
+ depends on !BACKPORT_KERNEL_3_3
tristate "Deinterlace support"
depends on m
depends on VIDEO_DEV && VIDEO_V4L2 && DMA_ENGINE
@@ -171,7 +180,7 @@
tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver"
depends on m
depends on VIDEO_DEV && VIDEO_V4L2
- depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+ depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
depends on HAS_DMA
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
@@ -184,7 +193,7 @@
tristate "Samsung S5P/Exynos3250/Exynos4 JPEG codec driver"
depends on m
depends on VIDEO_DEV && VIDEO_V4L2
- depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+ depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
depends on HAS_DMA
select VIDEOBUF2_DMA_CONTIG
select V4L2_MEM2MEM_DEV
@@ -196,7 +205,7 @@
tristate "Samsung S5P MFC Video Codec"
depends on m
depends on VIDEO_DEV && VIDEO_V4L2
- depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+ depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
depends on HAS_DMA
select VIDEOBUF2_DMA_CONTIG
default n
@@ -239,7 +248,7 @@
SH-Mobile SoCs.
config VIDEO_RENESAS_VSP1
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Renesas VSP1 Video Processing Engine"
depends on m
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA
@@ -280,8 +289,8 @@
source "drivers/media/platform/vivid/Kconfig"
-config VIDEO_VIM2M
- tristate "Virtual Memory-to-Memory Driver"
+config VIDEO_MEM2MEM_TESTDEV
+ tristate "Virtual test device for mem2mem framework"
depends on m
depends on VIDEO_DEV && VIDEO_V4L2
select VIDEOBUF2_VMALLOC
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
index 6449a06..140e3e5 100644
--- a/drivers/media/platform/Makefile
+++ b/drivers/media/platform/Makefile
@@ -2,6 +2,9 @@
# Makefile for the video capture/playback device drivers.
#
+obj-$(CPTCFG_VIDEO_VINO) += indycam.o
+obj-$(CPTCFG_VIDEO_VINO) += vino.o
+
obj-$(CPTCFG_VIDEO_TIMBERDALE) += timblogiw.o
obj-$(CPTCFG_VIDEO_M32R_AR_M64278) += arv.o
@@ -14,7 +17,7 @@
obj-$(CPTCFG_VIDEO_VIU) += fsl-viu.o
obj-$(CPTCFG_VIDEO_VIVID) += vivid/
-obj-$(CPTCFG_VIDEO_VIM2M) += vim2m.o
+obj-$(CPTCFG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
obj-$(CPTCFG_VIDEO_TI_VPE) += ti-vpe/
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index 8f66986..9b5daa6 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -49,7 +49,7 @@
struct bcap_format {
char *desc;
u32 pixelformat;
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
int bpp; /* bits per pixel */
int dlen; /* data length for ppi in bits */
};
@@ -116,35 +116,35 @@
{
.desc = "YCbCr 4:2:2 Interleaved UYVY",
.pixelformat = V4L2_PIX_FMT_UYVY,
- .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
.bpp = 16,
.dlen = 8,
},
{
.desc = "YCbCr 4:2:2 Interleaved YUYV",
.pixelformat = V4L2_PIX_FMT_YUYV,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.bpp = 16,
.dlen = 8,
},
{
.desc = "YCbCr 4:2:2 Interleaved UYVY",
.pixelformat = V4L2_PIX_FMT_UYVY,
- .mbus_code = MEDIA_BUS_FMT_UYVY8_1X16,
+ .mbus_code = V4L2_MBUS_FMT_UYVY8_1X16,
.bpp = 16,
.dlen = 16,
},
{
.desc = "RGB 565",
.pixelformat = V4L2_PIX_FMT_RGB565,
- .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
.bpp = 16,
.dlen = 8,
},
{
.desc = "RGB 444",
.pixelformat = V4L2_PIX_FMT_RGB444,
- .mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE,
+ .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
.bpp = 16,
.dlen = 8,
},
@@ -161,7 +161,7 @@
static int bcap_init_sensor_formats(struct bcap_device *bcap_dev)
{
- u32 code;
+ enum v4l2_mbus_pixelcode code;
struct bcap_format *sf;
unsigned int num_formats = 0;
int i, j;
@@ -349,6 +349,18 @@
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);
@@ -445,8 +457,8 @@
.buf_prepare = bcap_buffer_prepare,
.buf_cleanup = bcap_buffer_cleanup,
.buf_queue = bcap_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .wait_prepare = bcap_unlock,
+ .wait_finish = bcap_lock,
.start_streaming = bcap_start_streaming,
.stop_streaming = bcap_stop_streaming,
};
@@ -829,8 +841,7 @@
{
struct bcap_device *bcap_dev = video_drvdata(file);
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ 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));
@@ -984,7 +995,6 @@
q->ops = &bcap_video_qops;
q->mem_ops = &vb2_dma_contig_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->lock = &bcap_dev->mutex;
ret = vb2_queue_init(q);
if (ret)
@@ -1120,6 +1130,7 @@
static struct platform_driver bcap_driver = {
.driver = {
.name = CAPTURE_DRV_NAME,
+ .owner = THIS_MODULE,
},
.probe = bcap_probe,
.remove = bcap_remove,
diff --git a/drivers/media/platform/coda/Makefile b/drivers/media/platform/coda/Makefile
index eee8998..fb7529f 100644
--- a/drivers/media/platform/coda/Makefile
+++ b/drivers/media/platform/coda/Makefile
@@ -1,3 +1,3 @@
-coda-objs := coda-common.o coda-bit.o coda-h264.o coda-jpeg.o
+coda-objs := coda-common.o coda-bit.o coda-h264.o
obj-$(CPTCFG_VIDEO_CODA) += coda.o
diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c
index b4029ae..9b8ea8b 100644
--- a/drivers/media/platform/coda/coda-bit.c
+++ b/drivers/media/platform/coda/coda-bit.c
@@ -217,34 +217,11 @@
void coda_fill_bitstream(struct coda_ctx *ctx)
{
struct vb2_buffer *src_buf;
- struct coda_buffer_meta *meta;
- u32 start;
+ struct coda_timestamp *ts;
while (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) > 0) {
- /*
- * Only queue a single JPEG into the bitstream buffer, except
- * to increase payload over 512 bytes or if in hold state.
- */
- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
- (coda_get_bitstream_payload(ctx) >= 512) && !ctx->hold)
- break;
-
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
- /* Drop frames that do not start/end with a SOI/EOI markers */
- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG &&
- !coda_jpeg_check_buffer(ctx, src_buf)) {
- v4l2_err(&ctx->dev->v4l2_dev,
- "dropping invalid JPEG frame\n");
- src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_ERROR);
- continue;
- }
-
- /* Buffer start position */
- start = ctx->bitstream_fifo.kfifo.in &
- ctx->bitstream_fifo.kfifo.mask;
-
if (coda_bitstream_try_queue(ctx, src_buf)) {
/*
* Source buffer is queued in the bitstream ringbuffer;
@@ -252,16 +229,12 @@
*/
src_buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
- meta = kmalloc(sizeof(*meta), GFP_KERNEL);
- if (meta) {
- meta->sequence = src_buf->v4l2_buf.sequence;
- meta->timecode = src_buf->v4l2_buf.timecode;
- meta->timestamp = src_buf->v4l2_buf.timestamp;
- meta->start = start;
- meta->end = ctx->bitstream_fifo.kfifo.in &
- ctx->bitstream_fifo.kfifo.mask;
- list_add_tail(&meta->list,
- &ctx->buffer_meta_list);
+ ts = kmalloc(sizeof(*ts), GFP_KERNEL);
+ if (ts) {
+ ts->sequence = src_buf->v4l2_buf.sequence;
+ ts->timecode = src_buf->v4l2_buf.timecode;
+ ts->timestamp = src_buf->v4l2_buf.timestamp;
+ list_add_tail(&ts->list, &ctx->timestamp_list);
}
v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
@@ -718,7 +691,6 @@
struct vb2_buffer *buf;
int gamma, ret, value;
u32 dst_fourcc;
- u32 stride;
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
@@ -738,14 +710,6 @@
return -EFAULT;
}
- if (dst_fourcc == V4L2_PIX_FMT_JPEG) {
- if (!ctx->params.jpeg_qmat_tab[0])
- ctx->params.jpeg_qmat_tab[0] = kmalloc(64, GFP_KERNEL);
- if (!ctx->params.jpeg_qmat_tab[1])
- ctx->params.jpeg_qmat_tab[1] = kmalloc(64, GFP_KERNEL);
- coda_set_jpeg_compression_quality(ctx, ctx->params.jpeg_quality);
- }
-
mutex_lock(&dev->coda_mutex);
coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
@@ -765,10 +729,10 @@
break;
}
- ctx->frame_mem_ctrl &= ~CODA_FRAME_CHROMA_INTERLEAVE;
- if (q_data_src->fourcc == V4L2_PIX_FMT_NV12)
- ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
- coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
+ value = coda_read(dev, CODA_REG_BIT_FRAME_MEM_CTRL);
+ value &= ~(1 << 2 | 0x7 << 9);
+ ctx->frame_mem_ctrl = value;
+ coda_write(dev, value, CODA_REG_BIT_FRAME_MEM_CTRL);
if (dev->devtype->product == CODA_DX6) {
/* Configure the coda */
@@ -777,7 +741,6 @@
}
/* Could set rotation here if needed */
- value = 0;
switch (dev->devtype->product) {
case CODA_DX6:
value = (q_data_src->width & CODADX6_PICWIDTH_MASK)
@@ -801,8 +764,6 @@
<< CODA_PICHEIGHT_OFFSET;
}
coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE);
- if (dst_fourcc == V4L2_PIX_FMT_JPEG)
- ctx->params.framerate = 0;
coda_write(dev, ctx->params.framerate,
CODA_CMD_ENC_SEQ_SRC_F_RATE);
@@ -836,16 +797,6 @@
}
coda_write(dev, value, CODA_CMD_ENC_SEQ_264_PARA);
break;
- case V4L2_PIX_FMT_JPEG:
- coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_PARA);
- coda_write(dev, ctx->params.jpeg_restart_interval,
- CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL);
- coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_EN);
- coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE);
- coda_write(dev, 0, CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET);
-
- coda_jpeg_write_tables(ctx);
- break;
default:
v4l2_err(v4l2_dev,
"dst format (0x%08x) invalid.\n", dst_fourcc);
@@ -853,36 +804,28 @@
goto out;
}
- /*
- * slice mode and GOP size registers are used for thumb size/offset
- * in JPEG mode
- */
- if (dst_fourcc != V4L2_PIX_FMT_JPEG) {
- switch (ctx->params.slice_mode) {
- case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
- value = 0;
- break;
- case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB:
- value = (ctx->params.slice_max_mb &
- CODA_SLICING_SIZE_MASK)
- << CODA_SLICING_SIZE_OFFSET;
- value |= (1 & CODA_SLICING_UNIT_MASK)
- << CODA_SLICING_UNIT_OFFSET;
- value |= 1 & CODA_SLICING_MODE_MASK;
- break;
- case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES:
- value = (ctx->params.slice_max_bits &
- CODA_SLICING_SIZE_MASK)
- << CODA_SLICING_SIZE_OFFSET;
- value |= (0 & CODA_SLICING_UNIT_MASK)
- << CODA_SLICING_UNIT_OFFSET;
- value |= 1 & CODA_SLICING_MODE_MASK;
- break;
- }
- coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
- value = ctx->params.gop_size & CODA_GOP_SIZE_MASK;
- coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
+ switch (ctx->params.slice_mode) {
+ case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
+ value = 0;
+ break;
+ case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB:
+ value = (ctx->params.slice_max_mb & CODA_SLICING_SIZE_MASK)
+ << CODA_SLICING_SIZE_OFFSET;
+ value |= (1 & CODA_SLICING_UNIT_MASK)
+ << CODA_SLICING_UNIT_OFFSET;
+ value |= 1 & CODA_SLICING_MODE_MASK;
+ break;
+ case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES:
+ value = (ctx->params.slice_max_bits & CODA_SLICING_SIZE_MASK)
+ << CODA_SLICING_SIZE_OFFSET;
+ value |= (0 & CODA_SLICING_UNIT_MASK)
+ << CODA_SLICING_UNIT_OFFSET;
+ value |= 1 & CODA_SLICING_MODE_MASK;
+ break;
}
+ coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
+ value = ctx->params.gop_size & CODA_GOP_SIZE_MASK;
+ coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
if (ctx->params.bitrate) {
/* Rate control enabled */
@@ -973,24 +916,19 @@
goto out;
}
- if (dst_fourcc != V4L2_PIX_FMT_JPEG) {
- if (dev->devtype->product == CODA_960)
- ctx->num_internal_frames = 4;
- else
- ctx->num_internal_frames = 2;
- ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
- if (ret < 0) {
- v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
- goto out;
- }
- stride = q_data_src->bytesperline;
- } else {
- ctx->num_internal_frames = 0;
- stride = 0;
+ if (dev->devtype->product == CODA_960)
+ ctx->num_internal_frames = 4;
+ else
+ ctx->num_internal_frames = 2;
+ ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
+ if (ret < 0) {
+ v4l2_err(v4l2_dev, "failed to allocate framebuffers\n");
+ goto out;
}
- coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
- coda_write(dev, stride, CODA_CMD_SET_FRAME_BUF_STRIDE);
+ coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
+ coda_write(dev, q_data_src->bytesperline,
+ CODA_CMD_SET_FRAME_BUF_STRIDE);
if (dev->devtype->product == CODA_7541) {
coda_write(dev, q_data_src->bytesperline,
CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
@@ -1098,10 +1036,9 @@
struct coda_dev *dev = ctx->dev;
int force_ipicture;
int quant_param = 0;
+ u32 picture_y, picture_cb, picture_cr;
u32 pic_stream_buffer_addr, pic_stream_buffer_size;
- u32 rot_mode = 0;
u32 dst_fourcc;
- u32 reg;
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
@@ -1139,7 +1076,7 @@
ctx->vpu_header_size[0] +
ctx->vpu_header_size[1] +
ctx->vpu_header_size[2];
- pic_stream_buffer_size = q_data_dst->sizeimage -
+ pic_stream_buffer_size = CODA_MAX_FRAME_SIZE -
ctx->vpu_header_size[0] -
ctx->vpu_header_size[1] -
ctx->vpu_header_size[2];
@@ -1153,7 +1090,7 @@
} else {
pic_stream_buffer_addr =
vb2_dma_contig_plane_dma_addr(dst_buf, 0);
- pic_stream_buffer_size = q_data_dst->sizeimage;
+ pic_stream_buffer_size = CODA_MAX_FRAME_SIZE;
}
if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
@@ -1165,9 +1102,6 @@
case V4L2_PIX_FMT_MPEG4:
quant_param = ctx->params.mpeg4_intra_qp;
break;
- case V4L2_PIX_FMT_JPEG:
- quant_param = 30;
- break;
default:
v4l2_warn(&ctx->dev->v4l2_dev,
"cannot set intra qp, fmt not supported\n");
@@ -1190,22 +1124,42 @@
}
/* submit */
- if (ctx->params.rot_mode)
- rot_mode = CODA_ROT_MIR_ENABLE | ctx->params.rot_mode;
- coda_write(dev, rot_mode, CODA_CMD_ENC_PIC_ROT_MODE);
+ coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
+ CODA_CMD_ENC_PIC_ROT_MODE);
coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS);
+
+ picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+ switch (q_data_src->fourcc) {
+ case V4L2_PIX_FMT_YVU420:
+ /* Switch Cb and Cr for YVU420 format */
+ picture_cr = picture_y + q_data_src->bytesperline *
+ q_data_src->height;
+ picture_cb = picture_cr + q_data_src->bytesperline / 2 *
+ q_data_src->height / 2;
+ break;
+ case V4L2_PIX_FMT_YUV420:
+ default:
+ picture_cb = picture_y + q_data_src->bytesperline *
+ q_data_src->height;
+ picture_cr = picture_cb + q_data_src->bytesperline / 2 *
+ q_data_src->height / 2;
+ break;
+ }
+
if (dev->devtype->product == CODA_960) {
coda_write(dev, 4/*FIXME: 0*/, CODA9_CMD_ENC_PIC_SRC_INDEX);
coda_write(dev, q_data_src->width, CODA9_CMD_ENC_PIC_SRC_STRIDE);
coda_write(dev, 0, CODA9_CMD_ENC_PIC_SUB_FRAME_SYNC);
- reg = CODA9_CMD_ENC_PIC_SRC_ADDR_Y;
+ coda_write(dev, picture_y, CODA9_CMD_ENC_PIC_SRC_ADDR_Y);
+ coda_write(dev, picture_cb, CODA9_CMD_ENC_PIC_SRC_ADDR_CB);
+ coda_write(dev, picture_cr, CODA9_CMD_ENC_PIC_SRC_ADDR_CR);
} else {
- reg = CODA_CMD_ENC_PIC_SRC_ADDR_Y;
+ coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y);
+ coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB);
+ coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR);
}
- coda_write_base(ctx, q_data_src, src_buf, reg);
-
coda_write(dev, force_ipicture << 1 & 0x2,
CODA_CMD_ENC_PIC_OPTION);
@@ -1339,7 +1293,7 @@
u32 bitstream_buf, bitstream_size;
struct coda_dev *dev = ctx->dev;
int width, height;
- u32 src_fourcc, dst_fourcc;
+ u32 src_fourcc;
u32 val;
int ret;
@@ -1349,7 +1303,6 @@
bitstream_buf = ctx->bitstream.paddr;
bitstream_size = ctx->bitstream.size;
src_fourcc = q_data_src->fourcc;
- dst_fourcc = q_data_dst->fourcc;
/* Allocate per-instance buffers */
ret = coda_alloc_context_buffers(ctx, q_data_src);
@@ -1361,11 +1314,6 @@
/* Update coda bitstream read and write pointers from kfifo */
coda_kfifo_sync_to_device_full(ctx);
- ctx->frame_mem_ctrl &= ~CODA_FRAME_CHROMA_INTERLEAVE;
- if (dst_fourcc == V4L2_PIX_FMT_NV12)
- ctx->frame_mem_ctrl |= CODA_FRAME_CHROMA_INTERLEAVE;
- coda_write(dev, ctx->frame_mem_ctrl, CODA_REG_BIT_FRAME_MEM_CTRL);
-
ctx->display_idx = -1;
ctx->frm_dis_flg = 0;
coda_write(dev, 0, CODA_REG_BIT_FRM_DIS_FLG(ctx->reg_idx));
@@ -1379,8 +1327,6 @@
if ((dev->devtype->product == CODA_7541) ||
(dev->devtype->product == CODA_960))
val |= CODA_REORDER_ENABLE;
- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG)
- val |= CODA_NO_INT_ENABLE;
coda_write(dev, val, CODA_CMD_DEC_SEQ_OPTION);
ctx->params.codec_mode = ctx->codec->mode;
@@ -1496,23 +1442,13 @@
}
if (dev->devtype->product == CODA_960) {
- int cbb_size, crb_size;
-
coda_write(dev, -1, CODA9_CMD_SET_FRAME_DELAY);
- /* Luma 2x0 page, 2x6 cache, chroma 2x0 page, 2x4 cache size */
- coda_write(dev, 0x20262024, CODA9_CMD_SET_FRAME_CACHE_SIZE);
- if (dst_fourcc == V4L2_PIX_FMT_NV12) {
- cbb_size = 0;
- crb_size = 16;
- } else {
- cbb_size = 8;
- crb_size = 8;
- }
+ coda_write(dev, 0x20262024, CODA9_CMD_SET_FRAME_CACHE_SIZE);
coda_write(dev, 2 << CODA9_CACHE_PAGEMERGE_OFFSET |
32 << CODA9_CACHE_LUMA_BUFFER_SIZE_OFFSET |
- cbb_size << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET |
- crb_size << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET,
+ 8 << CODA9_CACHE_CB_BUFFER_SIZE_OFFSET |
+ 8 << CODA9_CACHE_CR_BUFFER_SIZE_OFFSET,
CODA9_CMD_SET_FRAME_CACHE_CONFIG);
}
@@ -1565,11 +1501,20 @@
struct vb2_buffer *dst_buf;
struct coda_dev *dev = ctx->dev;
struct coda_q_data *q_data_dst;
- u32 reg_addr, reg_stride;
+ u32 stridey, height;
+ u32 picture_y, picture_cb, picture_cr;
dst_buf = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ if (ctx->params.rot_mode & CODA_ROT_90) {
+ stridey = q_data_dst->height;
+ height = q_data_dst->width;
+ } else {
+ stridey = q_data_dst->width;
+ height = q_data_dst->height;
+ }
+
/* Try to copy source buffer contents into the bitstream ringbuffer */
mutex_lock(&ctx->bitstream_mutex);
coda_fill_bitstream(ctx);
@@ -1600,6 +1545,17 @@
if (dev->devtype->product == CODA_960)
coda_set_gdi_regs(ctx);
+ /* Set rotator output */
+ picture_y = vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+ if (q_data_dst->fourcc == V4L2_PIX_FMT_YVU420) {
+ /* Switch Cr and Cb for YVU420 format */
+ picture_cr = picture_y + stridey * height;
+ picture_cb = picture_cr + stridey / 2 * height / 2;
+ } else {
+ picture_cb = picture_y + stridey * height;
+ picture_cr = picture_cb + stridey / 2 * height / 2;
+ }
+
if (dev->devtype->product == CODA_960) {
/*
* The CODA960 seems to have an internal list of buffers with
@@ -1609,16 +1565,16 @@
*/
coda_write(dev, CODA_MAX_FRAMEBUFFERS + dst_buf->v4l2_buf.index,
CODA9_CMD_DEC_PIC_ROT_INDEX);
-
- reg_addr = CODA9_CMD_DEC_PIC_ROT_ADDR_Y;
- reg_stride = CODA9_CMD_DEC_PIC_ROT_STRIDE;
+ coda_write(dev, picture_y, CODA9_CMD_DEC_PIC_ROT_ADDR_Y);
+ coda_write(dev, picture_cb, CODA9_CMD_DEC_PIC_ROT_ADDR_CB);
+ coda_write(dev, picture_cr, CODA9_CMD_DEC_PIC_ROT_ADDR_CR);
+ coda_write(dev, stridey, CODA9_CMD_DEC_PIC_ROT_STRIDE);
} else {
- reg_addr = CODA_CMD_DEC_PIC_ROT_ADDR_Y;
- reg_stride = CODA_CMD_DEC_PIC_ROT_STRIDE;
+ coda_write(dev, picture_y, CODA_CMD_DEC_PIC_ROT_ADDR_Y);
+ coda_write(dev, picture_cb, CODA_CMD_DEC_PIC_ROT_ADDR_CB);
+ coda_write(dev, picture_cr, CODA_CMD_DEC_PIC_ROT_ADDR_CR);
+ coda_write(dev, stridey, CODA_CMD_DEC_PIC_ROT_STRIDE);
}
- coda_write_base(ctx, q_data_dst, dst_buf, reg_addr);
- coda_write(dev, q_data_dst->bytesperline, reg_stride);
-
coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode,
CODA_CMD_DEC_PIC_ROT_MODE);
@@ -1643,26 +1599,6 @@
coda_write(dev, ctx->iram_info.axi_sram_use,
CODA7_REG_BIT_AXI_SRAM_USE);
- if (ctx->codec->src_fourcc == V4L2_PIX_FMT_JPEG) {
- struct coda_buffer_meta *meta;
-
- /* If this is the last buffer in the bitstream, add padding */
- meta = list_first_entry(&ctx->buffer_meta_list,
- struct coda_buffer_meta, list);
- if (meta->end == (ctx->bitstream_fifo.kfifo.in &
- ctx->bitstream_fifo.kfifo.mask)) {
- static unsigned char buf[512];
- unsigned int pad;
-
- /* Pad to multiple of 256 and then add 256 more */
- pad = ((0 - meta->end) & 0xff) + 256;
-
- memset(buf, 0xff, sizeof(buf));
-
- kfifo_in(&ctx->bitstream_fifo, buf, pad);
- }
- }
-
coda_kfifo_sync_to_device_full(ctx);
coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
@@ -1676,8 +1612,7 @@
struct coda_q_data *q_data_src;
struct coda_q_data *q_data_dst;
struct vb2_buffer *dst_buf;
- struct coda_buffer_meta *meta;
- unsigned long payload;
+ struct coda_timestamp *ts;
int width, height;
int decoded_idx;
int display_idx;
@@ -1804,23 +1739,23 @@
val = coda_read(dev, CODA_RET_DEC_PIC_FRAME_NUM) - 1;
val -= ctx->sequence_offset;
mutex_lock(&ctx->bitstream_mutex);
- if (!list_empty(&ctx->buffer_meta_list)) {
- meta = list_first_entry(&ctx->buffer_meta_list,
- struct coda_buffer_meta, list);
- list_del(&meta->list);
- if (val != (meta->sequence & 0xffff)) {
+ if (!list_empty(&ctx->timestamp_list)) {
+ ts = list_first_entry(&ctx->timestamp_list,
+ struct coda_timestamp, list);
+ list_del(&ts->list);
+ if (val != (ts->sequence & 0xffff)) {
v4l2_err(&dev->v4l2_dev,
"sequence number mismatch (%d(%d) != %d)\n",
val, ctx->sequence_offset,
- meta->sequence);
+ ts->sequence);
}
- ctx->frame_metas[decoded_idx] = *meta;
- kfree(meta);
+ ctx->frame_timestamps[decoded_idx] = *ts;
+ kfree(ts);
} else {
v4l2_err(&dev->v4l2_dev, "empty timestamp list!\n");
- memset(&ctx->frame_metas[decoded_idx], 0,
- sizeof(struct coda_buffer_meta));
- ctx->frame_metas[decoded_idx].sequence = val;
+ memset(&ctx->frame_timestamps[decoded_idx], 0,
+ sizeof(struct coda_timestamp));
+ ctx->frame_timestamps[decoded_idx].sequence = val;
}
mutex_unlock(&ctx->bitstream_mutex);
@@ -1859,22 +1794,11 @@
V4L2_BUF_FLAG_PFRAME |
V4L2_BUF_FLAG_BFRAME);
dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx->display_idx];
- meta = &ctx->frame_metas[ctx->display_idx];
- dst_buf->v4l2_buf.timecode = meta->timecode;
- dst_buf->v4l2_buf.timestamp = meta->timestamp;
+ ts = &ctx->frame_timestamps[ctx->display_idx];
+ dst_buf->v4l2_buf.timecode = ts->timecode;
+ dst_buf->v4l2_buf.timestamp = ts->timestamp;
- switch (q_data_dst->fourcc) {
- case V4L2_PIX_FMT_YUV420:
- case V4L2_PIX_FMT_YVU420:
- case V4L2_PIX_FMT_NV12:
- default:
- payload = width * height * 3 / 2;
- break;
- case V4L2_PIX_FMT_YUV422P:
- payload = width * height * 2;
- break;
- }
- vb2_set_plane_payload(dst_buf, 0, payload);
+ vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2);
v4l2_m2m_buf_done(dst_buf, ctx->frame_errors[display_idx] ?
VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c
index 0813f46..ced4760 100644
--- a/drivers/media/platform/coda/coda-common.c
+++ b/drivers/media/platform/coda/coda-common.c
@@ -43,7 +43,6 @@
#define CODA_NAME "coda"
#define CODADX6_MAX_INSTANCES 4
-#define CODA_MAX_FORMATS 4
#define CODA_PARA_BUF_SIZE (10 * 1024)
#define CODA_ISRAM_SIZE (2048 * 2)
@@ -83,34 +82,6 @@
return data;
}
-void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
- struct vb2_buffer *buf, unsigned int reg_y)
-{
- u32 base_y = vb2_dma_contig_plane_dma_addr(buf, 0);
- u32 base_cb, base_cr;
-
- switch (q_data->fourcc) {
- case V4L2_PIX_FMT_YVU420:
- /* Switch Cb and Cr for YVU420 format */
- base_cr = base_y + q_data->bytesperline * q_data->height;
- base_cb = base_cr + q_data->bytesperline * q_data->height / 4;
- break;
- case V4L2_PIX_FMT_YUV420:
- case V4L2_PIX_FMT_NV12:
- default:
- base_cb = base_y + q_data->bytesperline * q_data->height;
- base_cr = base_cb + q_data->bytesperline * q_data->height / 4;
- break;
- case V4L2_PIX_FMT_YUV422P:
- base_cb = base_y + q_data->bytesperline * q_data->height;
- base_cr = base_cb + q_data->bytesperline * q_data->height / 2;
- }
-
- coda_write(ctx->dev, base_y, reg_y);
- coda_write(ctx->dev, base_cb, reg_y + 4);
- coda_write(ctx->dev, base_cr, reg_y + 8);
-}
-
/*
* Array of all formats supported by any version of Coda:
*/
@@ -124,14 +95,6 @@
.fourcc = V4L2_PIX_FMT_YVU420,
},
{
- .name = "YUV 4:2:0 Partial interleaved Y/CbCr",
- .fourcc = V4L2_PIX_FMT_NV12,
- },
- {
- .name = "YUV 4:2:2 Planar, YCbCr",
- .fourcc = V4L2_PIX_FMT_YUV422P,
- },
- {
.name = "H264 Encoded Stream",
.fourcc = V4L2_PIX_FMT_H264,
},
@@ -139,10 +102,6 @@
.name = "MPEG4 Encoded Stream",
.fourcc = V4L2_PIX_FMT_MPEG4,
},
- {
- .name = "JPEG Encoded Images",
- .fourcc = V4L2_PIX_FMT_JPEG,
- },
};
#define CODA_CODEC(mode, src_fourcc, dst_fourcc, max_w, max_h) \
@@ -163,10 +122,8 @@
static const struct coda_codec coda7_codecs[] = {
CODA_CODEC(CODA7_MODE_ENCODE_H264, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_H264, 1280, 720),
CODA_CODEC(CODA7_MODE_ENCODE_MP4, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_MPEG4, 1280, 720),
- CODA_CODEC(CODA7_MODE_ENCODE_MJPG, V4L2_PIX_FMT_YUV420, V4L2_PIX_FMT_JPEG, 8192, 8192),
CODA_CODEC(CODA7_MODE_DECODE_H264, V4L2_PIX_FMT_H264, V4L2_PIX_FMT_YUV420, 1920, 1088),
CODA_CODEC(CODA7_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088),
- CODA_CODEC(CODA7_MODE_DECODE_MJPG, V4L2_PIX_FMT_JPEG, V4L2_PIX_FMT_YUV420, 8192, 8192),
};
static const struct coda_codec coda9_codecs[] = {
@@ -176,115 +133,17 @@
CODA_CODEC(CODA9_MODE_DECODE_MP4, V4L2_PIX_FMT_MPEG4, V4L2_PIX_FMT_YUV420, 1920, 1088),
};
-struct coda_video_device {
- const char *name;
- enum coda_inst_type type;
- const struct coda_context_ops *ops;
- u32 src_formats[CODA_MAX_FORMATS];
- u32 dst_formats[CODA_MAX_FORMATS];
-};
-
-static const struct coda_video_device coda_bit_encoder = {
- .name = "coda-encoder",
- .type = CODA_INST_ENCODER,
- .ops = &coda_bit_encode_ops,
- .src_formats = {
- V4L2_PIX_FMT_YUV420,
- V4L2_PIX_FMT_YVU420,
- V4L2_PIX_FMT_NV12,
- },
- .dst_formats = {
- V4L2_PIX_FMT_H264,
- V4L2_PIX_FMT_MPEG4,
- },
-};
-
-static const struct coda_video_device coda_bit_jpeg_encoder = {
- .name = "coda-jpeg-encoder",
- .type = CODA_INST_ENCODER,
- .ops = &coda_bit_encode_ops,
- .src_formats = {
- V4L2_PIX_FMT_YUV420,
- V4L2_PIX_FMT_YVU420,
- V4L2_PIX_FMT_NV12,
- V4L2_PIX_FMT_YUV422P,
- },
- .dst_formats = {
- V4L2_PIX_FMT_JPEG,
- },
-};
-
-static const struct coda_video_device coda_bit_decoder = {
- .name = "coda-decoder",
- .type = CODA_INST_DECODER,
- .ops = &coda_bit_decode_ops,
- .src_formats = {
- V4L2_PIX_FMT_H264,
- V4L2_PIX_FMT_MPEG4,
- },
- .dst_formats = {
- V4L2_PIX_FMT_YUV420,
- V4L2_PIX_FMT_YVU420,
- V4L2_PIX_FMT_NV12,
- },
-};
-
-static const struct coda_video_device coda_bit_jpeg_decoder = {
- .name = "coda-jpeg-decoder",
- .type = CODA_INST_DECODER,
- .ops = &coda_bit_decode_ops,
- .src_formats = {
- V4L2_PIX_FMT_JPEG,
- },
- .dst_formats = {
- V4L2_PIX_FMT_YUV420,
- V4L2_PIX_FMT_YVU420,
- V4L2_PIX_FMT_NV12,
- V4L2_PIX_FMT_YUV422P,
- },
-};
-
-static const struct coda_video_device *codadx6_video_devices[] = {
- &coda_bit_encoder,
-};
-
-static const struct coda_video_device *coda7_video_devices[] = {
- &coda_bit_jpeg_encoder,
- &coda_bit_jpeg_decoder,
- &coda_bit_encoder,
- &coda_bit_decoder,
-};
-
-static const struct coda_video_device *coda9_video_devices[] = {
- &coda_bit_encoder,
- &coda_bit_decoder,
-};
-
static bool coda_format_is_yuv(u32 fourcc)
{
switch (fourcc) {
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
- case V4L2_PIX_FMT_NV12:
- case V4L2_PIX_FMT_YUV422P:
return true;
default:
return false;
}
}
-static const char *coda_format_name(u32 fourcc)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(coda_formats); i++) {
- if (coda_formats[i].fourcc == fourcc)
- return coda_formats[i].name;
- }
-
- return NULL;
-}
-
/*
* Normalize all supported YUV 4:2:0 formats to the value used in the codec
* tables.
@@ -343,17 +202,6 @@
*max_h = h;
}
-const struct coda_video_device *to_coda_video_device(struct video_device *vdev)
-{
- struct coda_dev *dev = video_get_drvdata(vdev);
- unsigned int i = vdev - dev->vfd;
-
- if (i >= dev->devtype->num_vdevs)
- return NULL;
-
- return dev->devtype->vdevs[i];
-}
-
const char *coda_product_name(int product)
{
static char buf[9];
@@ -392,28 +240,58 @@
static int coda_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
- struct video_device *vdev = video_devdata(file);
- const struct coda_video_device *cvd = to_coda_video_device(vdev);
- const u32 *formats;
- const char *name;
+ struct coda_ctx *ctx = fh_to_ctx(priv);
+ const struct coda_codec *codecs = ctx->dev->devtype->codecs;
+ const struct coda_fmt *formats = coda_formats;
+ const struct coda_fmt *fmt;
+ int num_codecs = ctx->dev->devtype->num_codecs;
+ int num_formats = ARRAY_SIZE(coda_formats);
+ int i, k, num = 0;
+ bool yuv;
- if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
- formats = cvd->src_formats;
- else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- formats = cvd->dst_formats;
+ if (ctx->inst_type == CODA_INST_ENCODER)
+ yuv = (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
else
- return -EINVAL;
+ yuv = (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE);
- if (f->index >= CODA_MAX_FORMATS || formats[f->index] == 0)
- return -EINVAL;
+ for (i = 0; i < num_formats; i++) {
+ /* Skip either raw or compressed formats */
+ if (yuv != coda_format_is_yuv(formats[i].fourcc))
+ continue;
+ /* All uncompressed formats are always supported */
+ if (yuv) {
+ if (num == f->index)
+ break;
+ ++num;
+ continue;
+ }
+ /* Compressed formats may be supported, check the codec list */
+ for (k = 0; k < num_codecs; k++) {
+ if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ formats[i].fourcc == codecs[k].dst_fourcc)
+ break;
+ if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
+ formats[i].fourcc == codecs[k].src_fourcc)
+ break;
+ }
+ if (k < num_codecs) {
+ if (num == f->index)
+ break;
+ ++num;
+ }
+ }
- name = coda_format_name(formats[f->index]);
- strlcpy(f->description, name, sizeof(f->description));
- f->pixelformat = formats[f->index];
- if (!coda_format_is_yuv(formats[f->index]))
- f->flags |= V4L2_FMT_FLAG_COMPRESSED;
+ if (i < num_formats) {
+ fmt = &formats[i];
+ strlcpy(f->description, fmt->name, sizeof(f->description));
+ f->pixelformat = fmt->fourcc;
+ if (!yuv)
+ f->flags |= V4L2_FMT_FLAG_COMPRESSED;
+ return 0;
+ }
- return 0;
+ /* Format not found */
+ return -EINVAL;
}
static int coda_g_fmt(struct file *file, void *priv,
@@ -433,37 +311,7 @@
f->fmt.pix.bytesperline = q_data->bytesperline;
f->fmt.pix.sizeimage = q_data->sizeimage;
- if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG)
- f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
- else
- f->fmt.pix.colorspace = ctx->colorspace;
-
- return 0;
-}
-
-static int coda_try_pixelformat(struct coda_ctx *ctx, struct v4l2_format *f)
-{
- struct coda_q_data *q_data;
- const u32 *formats;
- int i;
-
- if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
- formats = ctx->cvd->src_formats;
- else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- formats = ctx->cvd->dst_formats;
- else
- return -EINVAL;
-
- for (i = 0; i < CODA_MAX_FORMATS; i++) {
- if (formats[i] == f->fmt.pix.pixelformat) {
- f->fmt.pix.pixelformat = formats[i];
- return 0;
- }
- }
-
- /* Fall back to currently set pixelformat */
- q_data = get_q_data(ctx, f->type);
- f->fmt.pix.pixelformat = q_data->fourcc;
+ f->fmt.pix.colorspace = ctx->colorspace;
return 0;
}
@@ -472,6 +320,7 @@
struct v4l2_format *f)
{
struct coda_dev *dev = ctx->dev;
+ struct coda_q_data *q_data;
unsigned int max_w, max_h;
enum v4l2_field field;
@@ -493,35 +342,30 @@
switch (f->fmt.pix.pixelformat) {
case V4L2_PIX_FMT_YUV420:
case V4L2_PIX_FMT_YVU420:
- case V4L2_PIX_FMT_NV12:
- /*
- * Frame stride must be at least multiple of 8,
- * but multiple of 16 for h.264 or JPEG 4:2:x
- */
+ case V4L2_PIX_FMT_H264:
+ case V4L2_PIX_FMT_MPEG4:
+ case V4L2_PIX_FMT_JPEG:
+ break;
+ default:
+ q_data = get_q_data(ctx, f->type);
+ if (!q_data)
+ return -EINVAL;
+ f->fmt.pix.pixelformat = q_data->fourcc;
+ }
+
+ switch (f->fmt.pix.pixelformat) {
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ /* Frame stride must be multiple of 8, but 16 for h.264 */
f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
f->fmt.pix.height * 3 / 2;
break;
- case V4L2_PIX_FMT_YUV422P:
- f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 16);
- f->fmt.pix.sizeimage = f->fmt.pix.bytesperline *
- f->fmt.pix.height * 2;
- break;
- case V4L2_PIX_FMT_JPEG:
- f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
- /* fallthrough */
case V4L2_PIX_FMT_H264:
case V4L2_PIX_FMT_MPEG4:
+ case V4L2_PIX_FMT_JPEG:
f->fmt.pix.bytesperline = 0;
- /*
- * This is a rough estimate for sensible compressed buffer
- * sizes (between 1 and 16 bits per pixel). This could be
- * improved by better format specific worst case estimates.
- */
- f->fmt.pix.sizeimage = round_up(clamp(f->fmt.pix.sizeimage,
- f->fmt.pix.width * f->fmt.pix.height / 8,
- f->fmt.pix.width * f->fmt.pix.height * 2),
- PAGE_SIZE);
+ f->fmt.pix.sizeimage = CODA_MAX_FRAME_SIZE;
break;
default:
BUG();
@@ -534,35 +378,34 @@
struct v4l2_format *f)
{
struct coda_ctx *ctx = fh_to_ctx(priv);
- const struct coda_q_data *q_data_src;
- const struct coda_codec *codec;
+ const struct coda_codec *codec = NULL;
struct vb2_queue *src_vq;
int ret;
- ret = coda_try_pixelformat(ctx, f);
- if (ret < 0)
- return ret;
-
- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-
/*
- * If the source format is already fixed, only allow the same output
- * resolution
+ * If the source format is already fixed, try to find a codec that
+ * converts to the given destination format
*/
src_vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (vb2_is_streaming(src_vq)) {
+ struct coda_q_data *q_data_src;
+
+ q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
+ f->fmt.pix.pixelformat);
+ if (!codec)
+ return -EINVAL;
+
f->fmt.pix.width = q_data_src->width;
f->fmt.pix.height = q_data_src->height;
+ } else {
+ /* Otherwise determine codec by encoded format, if possible */
+ codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_YUV420,
+ f->fmt.pix.pixelformat);
}
f->fmt.pix.colorspace = ctx->colorspace;
- q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
- codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
- f->fmt.pix.pixelformat);
- if (!codec)
- return -EINVAL;
-
ret = coda_try_fmt(ctx, codec, f);
if (ret < 0)
return ret;
@@ -583,24 +426,21 @@
struct v4l2_format *f)
{
struct coda_ctx *ctx = fh_to_ctx(priv);
- struct coda_dev *dev = ctx->dev;
- const struct coda_q_data *q_data_dst;
- const struct coda_codec *codec;
- int ret;
+ const struct coda_codec *codec = NULL;
- ret = coda_try_pixelformat(ctx, f);
- if (ret < 0)
- return ret;
-
- if (!f->fmt.pix.colorspace) {
- if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_JPEG)
- f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
- else
- f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+ /* Determine codec by encoded format, returns NULL if raw or invalid */
+ if (ctx->inst_type == CODA_INST_DECODER) {
+ codec = coda_find_codec(ctx->dev, f->fmt.pix.pixelformat,
+ V4L2_PIX_FMT_YUV420);
+ if (!codec)
+ codec = coda_find_codec(ctx->dev, V4L2_PIX_FMT_H264,
+ V4L2_PIX_FMT_YUV420);
+ if (!codec)
+ return -EINVAL;
}
- q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- codec = coda_find_codec(dev, f->fmt.pix.pixelformat, q_data_dst->fourcc);
+ if (!f->fmt.pix.colorspace)
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
return coda_try_fmt(ctx, codec, f);
}
@@ -831,9 +671,7 @@
.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
.vidioc_qbuf = coda_qbuf,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
-#endif
.vidioc_dqbuf = coda_dqbuf,
.vidioc_create_bufs = v4l2_m2m_ioctl_create_bufs,
@@ -943,7 +781,6 @@
if (ctx->hold ||
((ctx->inst_type == CODA_INST_DECODER) &&
- !v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) &&
(coda_get_bitstream_payload(ctx) < 512) &&
!(ctx->bit_stream_param & CODA_BIT_STREAM_END_FLAG))) {
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
@@ -1025,17 +862,25 @@
static void set_default_params(struct coda_ctx *ctx)
{
- unsigned int max_w, max_h, size;
+ u32 src_fourcc, dst_fourcc;
+ int max_w;
+ int max_h;
- ctx->codec = coda_find_codec(ctx->dev, ctx->cvd->src_formats[0],
- ctx->cvd->dst_formats[0]);
- max_w = min(ctx->codec->max_w, 1920U);
- max_h = min(ctx->codec->max_h, 1088U);
- size = max_w * max_h * 3 / 2;
+ if (ctx->inst_type == CODA_INST_ENCODER) {
+ src_fourcc = V4L2_PIX_FMT_YUV420;
+ dst_fourcc = V4L2_PIX_FMT_H264;
+ } else {
+ src_fourcc = V4L2_PIX_FMT_H264;
+ dst_fourcc = V4L2_PIX_FMT_YUV420;
+ }
+ ctx->codec = coda_find_codec(ctx->dev, src_fourcc, dst_fourcc);
+ max_w = ctx->codec->max_w;
+ max_h = ctx->codec->max_h;
ctx->params.codec_mode = ctx->codec->mode;
ctx->colorspace = V4L2_COLORSPACE_REC709;
ctx->params.framerate = 30;
+ ctx->aborting = 0;
/* Default formats for output and input queues */
ctx->q_data[V4L2_M2M_SRC].fourcc = ctx->codec->src_fourcc;
@@ -1046,14 +891,14 @@
ctx->q_data[V4L2_M2M_DST].height = max_h;
if (ctx->codec->src_fourcc == V4L2_PIX_FMT_YUV420) {
ctx->q_data[V4L2_M2M_SRC].bytesperline = max_w;
- ctx->q_data[V4L2_M2M_SRC].sizeimage = size;
+ ctx->q_data[V4L2_M2M_SRC].sizeimage = (max_w * max_h * 3) / 2;
ctx->q_data[V4L2_M2M_DST].bytesperline = 0;
- ctx->q_data[V4L2_M2M_DST].sizeimage = round_up(size, PAGE_SIZE);
+ ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE;
} else {
ctx->q_data[V4L2_M2M_SRC].bytesperline = 0;
- ctx->q_data[V4L2_M2M_SRC].sizeimage = round_up(size, PAGE_SIZE);
+ ctx->q_data[V4L2_M2M_SRC].sizeimage = CODA_MAX_FRAME_SIZE;
ctx->q_data[V4L2_M2M_DST].bytesperline = max_w;
- ctx->q_data[V4L2_M2M_DST].sizeimage = size;
+ ctx->q_data[V4L2_M2M_DST].sizeimage = (max_w * max_h * 3) / 2;
}
ctx->q_data[V4L2_M2M_SRC].rect.width = max_w;
ctx->q_data[V4L2_M2M_SRC].rect.height = max_h;
@@ -1119,7 +964,7 @@
* In the decoder case, immediately try to copy the buffer into the
* bitstream ringbuffer and mark it as ready to be dequeued.
*/
- if (ctx->inst_type == CODA_INST_DECODER &&
+ if (q_data->fourcc == V4L2_PIX_FMT_H264 &&
vb->vb2_queue->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
/*
* For backwards compatibility, queuing an empty buffer marks
@@ -1182,13 +1027,12 @@
struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
struct coda_q_data *q_data_src, *q_data_dst;
struct vb2_buffer *buf;
+ u32 dst_fourcc;
int ret = 0;
q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
- if (q_data_src->fourcc == V4L2_PIX_FMT_H264 ||
- (q_data_src->fourcc == V4L2_PIX_FMT_JPEG &&
- ctx->dev->devtype->product == CODA_7541)) {
+ if (q_data_src->fourcc == V4L2_PIX_FMT_H264) {
/* copy the buffers that where queued before streamon */
mutex_lock(&ctx->bitstream_mutex);
coda_fill_bitstream(ctx);
@@ -1219,12 +1063,13 @@
if (!(ctx->streamon_out & ctx->streamon_cap))
return 0;
- /* Allow BIT decoder device_run with no new buffers queued */
+ /* Allow decoder device_run with no new buffers queued */
if (ctx->inst_type == CODA_INST_DECODER)
v4l2_m2m_set_src_buffered(ctx->fh.m2m_ctx, true);
ctx->gopcounter = ctx->params.gop_size - 1;
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+ dst_fourcc = q_data_dst->fourcc;
ctx->codec = coda_find_codec(ctx->dev, q_data_src->fourcc,
q_data_dst->fourcc);
@@ -1234,10 +1079,6 @@
goto err;
}
- if (q_data_dst->fourcc == V4L2_PIX_FMT_JPEG)
- ctx->params.gop_size = 1;
- ctx->gopcounter = ctx->params.gop_size - 1;
-
ret = ctx->ops->start_streaming(ctx);
if (ctx->inst_type == CODA_INST_DECODER) {
if (ret == -EAGAIN)
@@ -1252,10 +1093,10 @@
err:
if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
while ((buf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx)))
- v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
+ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_DEQUEUED);
} else {
while ((buf = v4l2_m2m_dst_buf_remove(ctx->fh.m2m_ctx)))
- v4l2_m2m_buf_done(buf, VB2_BUF_STATE_QUEUED);
+ v4l2_m2m_buf_done(buf, VB2_BUF_STATE_DEQUEUED);
}
return ret;
}
@@ -1290,20 +1131,19 @@
}
if (!ctx->streamon_out && !ctx->streamon_cap) {
- struct coda_buffer_meta *meta;
+ struct coda_timestamp *ts;
mutex_lock(&ctx->bitstream_mutex);
- while (!list_empty(&ctx->buffer_meta_list)) {
- meta = list_first_entry(&ctx->buffer_meta_list,
- struct coda_buffer_meta, list);
- list_del(&meta->list);
- kfree(meta);
+ while (!list_empty(&ctx->timestamp_list)) {
+ ts = list_first_entry(&ctx->timestamp_list,
+ struct coda_timestamp, list);
+ list_del(&ts->list);
+ kfree(ts);
}
mutex_unlock(&ctx->bitstream_mutex);
kfifo_init(&ctx->bitstream_fifo,
ctx->bitstream.vaddr, ctx->bitstream.size);
ctx->runcounter = 0;
- ctx->aborting = 0;
}
}
@@ -1386,12 +1226,6 @@
case V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB:
ctx->params.intra_refresh = ctrl->val;
break;
- case V4L2_CID_JPEG_COMPRESSION_QUALITY:
- coda_set_jpeg_compression_quality(ctx, ctrl->val);
- break;
- case V4L2_CID_JPEG_RESTART_INTERVAL:
- ctx->params.jpeg_restart_interval = ctrl->val;
- break;
default:
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"Invalid control, id=%d, val=%d\n",
@@ -1406,8 +1240,14 @@
.s_ctrl = coda_s_ctrl,
};
-static void coda_encode_ctrls(struct coda_ctx *ctx)
+static int coda_ctrls_setup(struct coda_ctx *ctx)
{
+ v4l2_ctrl_handler_init(&ctx->ctrls, 9);
+
+ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+ V4L2_CID_VFLIP, 0, 1, 1, 0);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1, 0);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
@@ -1451,30 +1291,6 @@
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB, 0,
1920 * 1088 / 256, 1, 0);
-}
-
-static void coda_jpeg_encode_ctrls(struct coda_ctx *ctx)
-{
- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
- V4L2_CID_JPEG_COMPRESSION_QUALITY, 5, 100, 1, 50);
- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
- V4L2_CID_JPEG_RESTART_INTERVAL, 0, 100, 1, 0);
-}
-
-static int coda_ctrls_setup(struct coda_ctx *ctx)
-{
- v4l2_ctrl_handler_init(&ctx->ctrls, 2);
-
- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
- V4L2_CID_HFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
- V4L2_CID_VFLIP, 0, 1, 1, 0);
- if (ctx->inst_type == CODA_INST_ENCODER) {
- if (ctx->cvd->dst_formats[0] == V4L2_PIX_FMT_JPEG)
- coda_jpeg_encode_ctrls(ctx);
- else
- coda_encode_ctrls(ctx);
- }
if (ctx->ctrls.error) {
v4l2_err(&ctx->dev->v4l2_dev,
@@ -1548,14 +1364,10 @@
return idx;
}
-/*
- * File operations
- */
-
-static int coda_open(struct file *file)
+static int coda_open(struct file *file, enum coda_inst_type inst_type,
+ const struct coda_context_ops *ctx_ops)
{
- struct video_device *vdev = video_devdata(file);
- struct coda_dev *dev = video_get_drvdata(vdev);
+ struct coda_dev *dev = video_drvdata(file);
struct coda_ctx *ctx = NULL;
char *name;
int ret;
@@ -1576,9 +1388,8 @@
ctx->debugfs_entry = debugfs_create_dir(name, dev->debugfs_root);
kfree(name);
- ctx->cvd = to_coda_video_device(vdev);
- ctx->inst_type = ctx->cvd->type;
- ctx->ops = ctx->cvd->ops;
+ ctx->inst_type = inst_type;
+ ctx->ops = ctx_ops;
init_completion(&ctx->completion);
INIT_WORK(&ctx->pic_run_work, coda_pic_run_work);
INIT_WORK(&ctx->seq_end_work, ctx->ops->seq_end_work);
@@ -1588,10 +1399,8 @@
ctx->dev = dev;
ctx->idx = idx;
switch (dev->devtype->product) {
- case CODA_960:
- ctx->frame_mem_ctrl = 1 << 12;
- /* fallthrough */
case CODA_7541:
+ case CODA_960:
ctx->reg_idx = 0;
break;
default:
@@ -1632,17 +1441,16 @@
ctx->fh.ctrl_handler = &ctx->ctrls;
- ret = coda_alloc_context_buf(ctx, &ctx->parabuf,
- CODA_PARA_BUF_SIZE, "parabuf");
+ ret = coda_alloc_context_buf(ctx, &ctx->parabuf, CODA_PARA_BUF_SIZE,
+ "parabuf");
if (ret < 0) {
v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf");
goto err_dma_alloc;
}
ctx->bitstream.size = CODA_MAX_FRAME_SIZE;
- ctx->bitstream.vaddr = dma_alloc_writecombine(
- &dev->plat_dev->dev, ctx->bitstream.size,
- &ctx->bitstream.paddr, GFP_KERNEL);
+ ctx->bitstream.vaddr = dma_alloc_writecombine(&dev->plat_dev->dev,
+ ctx->bitstream.size, &ctx->bitstream.paddr, GFP_KERNEL);
if (!ctx->bitstream.vaddr) {
v4l2_err(&dev->v4l2_dev,
"failed to allocate bitstream ringbuffer");
@@ -1653,7 +1461,7 @@
ctx->bitstream.vaddr, ctx->bitstream.size);
mutex_init(&ctx->bitstream_mutex);
mutex_init(&ctx->buffer_mutex);
- INIT_LIST_HEAD(&ctx->buffer_meta_list);
+ INIT_LIST_HEAD(&ctx->timestamp_list);
coda_lock(ctx);
list_add(&ctx->list, &dev->instances);
@@ -1687,6 +1495,16 @@
return ret;
}
+static int coda_encoder_open(struct file *file)
+{
+ return coda_open(file, CODA_INST_ENCODER, &coda_bit_encode_ops);
+}
+
+static int coda_decoder_open(struct file *file)
+{
+ return coda_open(file, CODA_INST_DECODER, &coda_bit_decode_ops);
+}
+
static int coda_release(struct file *file)
{
struct coda_dev *dev = video_drvdata(file);
@@ -1697,9 +1515,6 @@
debugfs_remove_recursive(ctx->debugfs_entry);
- if (ctx->inst_type == CODA_INST_DECODER)
- coda_bit_stream_end_flag(ctx);
-
/* If this instance is running, call .job_abort and wait for it to end */
v4l2_m2m_ctx_release(ctx->fh.m2m_ctx);
@@ -1713,10 +1528,8 @@
list_del(&ctx->list);
coda_unlock(ctx);
- if (ctx->bitstream.vaddr) {
- dma_free_writecombine(&dev->plat_dev->dev, ctx->bitstream.size,
- ctx->bitstream.vaddr, ctx->bitstream.paddr);
- }
+ dma_free_writecombine(&dev->plat_dev->dev, ctx->bitstream.size,
+ ctx->bitstream.vaddr, ctx->bitstream.paddr);
if (ctx->dev->devtype->product == CODA_DX6)
coda_free_aux_buf(dev, &ctx->workbuf);
@@ -1735,9 +1548,18 @@
return 0;
}
-static const struct v4l2_file_operations coda_fops = {
+static const struct v4l2_file_operations coda_encoder_fops = {
.owner = THIS_MODULE,
- .open = coda_open,
+ .open = coda_encoder_open,
+ .release = coda_release,
+ .poll = v4l2_m2m_fop_poll,
+ .unlocked_ioctl = video_ioctl2,
+ .mmap = v4l2_m2m_fop_mmap,
+};
+
+static const struct v4l2_file_operations coda_decoder_fops = {
+ .owner = THIS_MODULE,
+ .open = coda_decoder_open,
.release = coda_release,
.poll = v4l2_m2m_fop_poll,
.unlocked_ioctl = video_ioctl2,
@@ -1842,16 +1664,8 @@
return ret;
}
-static int coda_register_device(struct coda_dev *dev, int i)
+static int coda_register_device(struct coda_dev *dev, struct video_device *vfd)
{
- struct video_device *vfd = &dev->vfd[i];
-
- if (i > ARRAY_SIZE(dev->vfd))
- return -EINVAL;
-
- snprintf(vfd->name, sizeof(vfd->name), dev->devtype->vdevs[i]->name);
- vfd->fops = &coda_fops;
- vfd->ioctl_ops = &coda_ioctl_ops;
vfd->release = video_device_release_empty,
vfd->lock = &dev->dev_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
@@ -1870,7 +1684,7 @@
{
struct coda_dev *dev = context;
struct platform_device *pdev = dev->plat_dev;
- int i, ret;
+ int ret;
if (!fw) {
v4l2_err(&dev->v4l2_dev, "firmware request failed\n");
@@ -1911,25 +1725,33 @@
goto rel_ctx;
}
- for (i = 0; i < dev->devtype->num_vdevs; i++) {
- ret = coda_register_device(dev, i);
- if (ret) {
- v4l2_err(&dev->v4l2_dev,
- "Failed to register %s video device: %d\n",
- dev->devtype->vdevs[i]->name, ret);
- goto rel_vfd;
- }
+ dev->vfd[0].fops = &coda_encoder_fops,
+ dev->vfd[0].ioctl_ops = &coda_ioctl_ops;
+ snprintf(dev->vfd[0].name, sizeof(dev->vfd[0].name), "coda-encoder");
+ ret = coda_register_device(dev, &dev->vfd[0]);
+ if (ret) {
+ v4l2_err(&dev->v4l2_dev,
+ "Failed to register encoder video device\n");
+ goto rel_m2m;
+ }
+
+ dev->vfd[1].fops = &coda_decoder_fops,
+ dev->vfd[1].ioctl_ops = &coda_ioctl_ops;
+ snprintf(dev->vfd[1].name, sizeof(dev->vfd[1].name), "coda-decoder");
+ ret = coda_register_device(dev, &dev->vfd[1]);
+ if (ret) {
+ v4l2_err(&dev->v4l2_dev,
+ "Failed to register decoder video device\n");
+ goto rel_m2m;
}
v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video[%d-%d]\n",
- dev->vfd[0].num, dev->vfd[i - 1].num);
+ dev->vfd[0].num, dev->vfd[1].num);
pm_runtime_put_sync(&pdev->dev);
return;
-rel_vfd:
- while (--i >= 0)
- video_unregister_device(&dev->vfd[i]);
+rel_m2m:
v4l2_m2m_release(dev->m2m_dev);
rel_ctx:
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
@@ -1961,8 +1783,6 @@
.product = CODA_DX6,
.codecs = codadx6_codecs,
.num_codecs = ARRAY_SIZE(codadx6_codecs),
- .vdevs = codadx6_video_devices,
- .num_vdevs = ARRAY_SIZE(codadx6_video_devices),
.workbuf_size = 288 * 1024 + FMO_SLICE_SAVE_BUF_SIZE * 8 * 1024,
.iram_size = 0xb000,
},
@@ -1971,8 +1791,6 @@
.product = CODA_7541,
.codecs = coda7_codecs,
.num_codecs = ARRAY_SIZE(coda7_codecs),
- .vdevs = coda7_video_devices,
- .num_vdevs = ARRAY_SIZE(coda7_video_devices),
.workbuf_size = 128 * 1024,
.tempbuf_size = 304 * 1024,
.iram_size = 0x14000,
@@ -1982,8 +1800,6 @@
.product = CODA_960,
.codecs = coda9_codecs,
.num_codecs = ARRAY_SIZE(coda9_codecs),
- .vdevs = coda9_video_devices,
- .num_vdevs = ARRAY_SIZE(coda9_video_devices),
.workbuf_size = 80 * 1024,
.tempbuf_size = 204 * 1024,
.iram_size = 0x21000,
@@ -1993,8 +1809,6 @@
.product = CODA_960,
.codecs = coda9_codecs,
.num_codecs = ARRAY_SIZE(coda9_codecs),
- .vdevs = coda9_video_devices,
- .num_vdevs = ARRAY_SIZE(coda9_video_devices),
.workbuf_size = 80 * 1024,
.tempbuf_size = 204 * 1024,
.iram_size = 0x20000,
@@ -2032,18 +1846,10 @@
int ret, irq;
dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
- if (!dev)
+ if (!dev) {
+ dev_err(&pdev->dev, "Not enough memory for %s\n",
+ CODA_NAME);
return -ENOMEM;
-
- pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
-
- if (of_id) {
- dev->devtype = of_id->data;
- } else if (pdev_id) {
- dev->devtype = &coda_devdata[pdev_id->driver_data];
- } else {
- ret = -EINVAL;
- goto err_v4l2_register;
}
spin_lock_init(&dev->irqlock);
@@ -2113,6 +1919,17 @@
mutex_init(&dev->dev_mutex);
mutex_init(&dev->coda_mutex);
+ pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
+
+ if (of_id) {
+ dev->devtype = of_id->data;
+ } else if (pdev_id) {
+ dev->devtype = &coda_devdata[pdev_id->driver_data];
+ } else {
+ v4l2_device_unregister(&dev->v4l2_dev);
+ return -EINVAL;
+ }
+
dev->debugfs_root = debugfs_create_dir("coda", NULL);
if (!dev->debugfs_root)
dev_warn(&pdev->dev, "failed to create debugfs root\n");
@@ -2124,7 +1941,8 @@
dev->debugfs_root);
if (ret < 0) {
dev_err(&pdev->dev, "failed to allocate work buffer\n");
- goto err_v4l2_register;
+ v4l2_device_unregister(&dev->v4l2_dev);
+ return ret;
}
}
@@ -2134,7 +1952,8 @@
dev->debugfs_root);
if (ret < 0) {
dev_err(&pdev->dev, "failed to allocate temp buffer\n");
- goto err_v4l2_register;
+ v4l2_device_unregister(&dev->v4l2_dev);
+ return ret;
}
}
@@ -2154,15 +1973,14 @@
dev->workqueue = alloc_workqueue("coda", WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
if (!dev->workqueue) {
dev_err(&pdev->dev, "unable to alloc workqueue\n");
- ret = -ENOMEM;
- goto err_v4l2_register;
+ return -ENOMEM;
}
platform_set_drvdata(pdev, dev);
/*
* Start activated so we can directly call coda_hw_init in
- * coda_fw_callback regardless of whether CONFIG_PM is
+ * coda_fw_callback regardless of whether CONFIG_PM_RUNTIME is
* enabled or whether the device is associated with a PM domain.
*/
pm_runtime_get_noresume(&pdev->dev);
@@ -2170,21 +1988,14 @@
pm_runtime_enable(&pdev->dev);
return coda_firmware_request(dev);
-
-err_v4l2_register:
- v4l2_device_unregister(&dev->v4l2_dev);
- return ret;
}
static int coda_remove(struct platform_device *pdev)
{
struct coda_dev *dev = platform_get_drvdata(pdev);
- int i;
- for (i = 0; i < ARRAY_SIZE(dev->vfd); i++) {
- if (video_get_drvdata(&dev->vfd[i]))
- video_unregister_device(&dev->vfd[i]);
- }
+ video_unregister_device(&dev->vfd[0]);
+ video_unregister_device(&dev->vfd[1]);
if (dev->m2m_dev)
v4l2_m2m_release(dev->m2m_dev);
pm_runtime_disable(&pdev->dev);
@@ -2202,7 +2013,7 @@
return 0;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
static int coda_runtime_resume(struct device *dev)
{
struct coda_dev *cdev = dev_get_drvdata(dev);
@@ -2227,6 +2038,7 @@
.remove = coda_remove,
.driver = {
.name = CODA_NAME,
+ .owner = THIS_MODULE,
.of_match_table = of_match_ptr(coda_dt_ids),
.pm = &coda_pm_ops,
},
diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c
deleted file mode 100644
index 8fa3e35..0000000
--- a/drivers/media/platform/coda/coda-jpeg.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/*
- * Coda multi-standard codec IP - JPEG support functions
- *
- * Copyright (C) 2014 Philipp Zabel, Pengutronix
- *
- * 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 <linux/kernel.h>
-#include <linux/swab.h>
-
-#include "coda.h"
-
-#define SOI_MARKER 0xffd8
-#define EOI_MARKER 0xffd9
-
-/*
- * Typical Huffman tables for 8-bit precision luminance and
- * chrominance from JPEG ITU-T.81 (ISO/IEC 10918-1) Annex K.3
- */
-
-static const unsigned char luma_dc_bits[16] = {
- 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static const unsigned char luma_dc_value[12] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b,
-};
-
-static const unsigned char chroma_dc_bits[16] = {
- 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static const unsigned char chroma_dc_value[12] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b,
-};
-
-static const unsigned char luma_ac_bits[16] = {
- 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
- 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
-};
-
-static const unsigned char luma_ac_value[162 + 2] = {
- 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
- 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
- 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
- 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
- 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
- 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
- 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
- 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
- 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
- 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
- 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
- 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
- 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
- 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
- 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
- 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
- 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
- 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
- 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa, /* padded to 32-bit */
-};
-
-static const unsigned char chroma_ac_bits[16] = {
- 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
- 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
-};
-
-static const unsigned char chroma_ac_value[162 + 2] = {
- 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
- 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
- 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
- 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
- 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
- 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
- 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
- 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
- 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
- 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
- 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
- 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
- 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
- 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
- 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
- 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
- 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
- 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
- 0xf9, 0xfa, /* padded to 32-bit */
-};
-
-/*
- * Quantization tables for luminance and chrominance components in
- * zig-zag scan order from the Freescale i.MX VPU libaries
- */
-
-static unsigned char luma_q[64] = {
- 0x06, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x05,
- 0x05, 0x06, 0x09, 0x06, 0x05, 0x06, 0x09, 0x0b,
- 0x08, 0x06, 0x06, 0x08, 0x0b, 0x0c, 0x0a, 0x0a,
- 0x0b, 0x0a, 0x0a, 0x0c, 0x10, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x10, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-};
-
-static unsigned char chroma_q[64] = {
- 0x07, 0x07, 0x07, 0x0d, 0x0c, 0x0d, 0x18, 0x10,
- 0x10, 0x18, 0x14, 0x0e, 0x0e, 0x0e, 0x14, 0x14,
- 0x0e, 0x0e, 0x0e, 0x0e, 0x14, 0x11, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x11, 0x11, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x11, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
- 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
-};
-
-struct coda_memcpy_desc {
- int offset;
- const void *src;
- size_t len;
-};
-
-static void coda_memcpy_parabuf(void *parabuf,
- const struct coda_memcpy_desc *desc)
-{
- u32 *dst = parabuf + desc->offset;
- const u32 *src = desc->src;
- int len = desc->len / 4;
- int i;
-
- for (i = 0; i < len; i += 2) {
- dst[i + 1] = swab32(src[i]);
- dst[i] = swab32(src[i + 1]);
- }
-}
-
-int coda_jpeg_write_tables(struct coda_ctx *ctx)
-{
- int i;
- static const struct coda_memcpy_desc huff[8] = {
- { 0, luma_dc_bits, sizeof(luma_dc_bits) },
- { 16, luma_dc_value, sizeof(luma_dc_value) },
- { 32, luma_ac_bits, sizeof(luma_ac_bits) },
- { 48, luma_ac_value, sizeof(luma_ac_value) },
- { 216, chroma_dc_bits, sizeof(chroma_dc_bits) },
- { 232, chroma_dc_value, sizeof(chroma_dc_value) },
- { 248, chroma_ac_bits, sizeof(chroma_ac_bits) },
- { 264, chroma_ac_value, sizeof(chroma_ac_value) },
- };
- struct coda_memcpy_desc qmat[3] = {
- { 512, ctx->params.jpeg_qmat_tab[0], 64 },
- { 576, ctx->params.jpeg_qmat_tab[1], 64 },
- { 640, ctx->params.jpeg_qmat_tab[1], 64 },
- };
-
- /* Write huffman tables to parameter memory */
- for (i = 0; i < ARRAY_SIZE(huff); i++)
- coda_memcpy_parabuf(ctx->parabuf.vaddr, huff + i);
-
- /* Write Q-matrix to parameter memory */
- for (i = 0; i < ARRAY_SIZE(qmat); i++)
- coda_memcpy_parabuf(ctx->parabuf.vaddr, qmat + i);
-
- return 0;
-}
-
-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb)
-{
- void *vaddr = vb2_plane_vaddr(vb, 0);
- u16 soi = be16_to_cpup((__be16 *)vaddr);
- u16 eoi = be16_to_cpup((__be16 *)(vaddr +
- vb2_get_plane_payload(vb, 0) - 2));
-
- return soi == SOI_MARKER && eoi == EOI_MARKER;
-}
-
-/*
- * Scale quantization table using nonlinear scaling factor
- * u8 qtab[64], scale [50,190]
- */
-static void coda_scale_quant_table(u8 *q_tab, int scale)
-{
- unsigned int temp;
- int i;
-
- for (i = 0; i < 64; i++) {
- temp = DIV_ROUND_CLOSEST((unsigned int)q_tab[i] * scale, 100);
- if (temp <= 0)
- temp = 1;
- if (temp > 255)
- temp = 255;
- q_tab[i] = (unsigned char)temp;
- }
-}
-
-void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality)
-{
- unsigned int scale;
-
- ctx->params.jpeg_quality = quality;
-
- /* Clip quality setting to [5,100] interval */
- if (quality > 100)
- quality = 100;
- if (quality < 5)
- quality = 5;
-
- /*
- * Non-linear scaling factor:
- * [5,50] -> [1000..100], [51,100] -> [98..0]
- */
- if (quality < 50)
- scale = 5000 / quality;
- else
- scale = 200 - 2 * quality;
-
- if (ctx->params.jpeg_qmat_tab[0]) {
- memcpy(ctx->params.jpeg_qmat_tab[0], luma_q, 64);
- coda_scale_quant_table(ctx->params.jpeg_qmat_tab[0], scale);
- }
- if (ctx->params.jpeg_qmat_tab[1]) {
- memcpy(ctx->params.jpeg_qmat_tab[1], chroma_q, 64);
- coda_scale_quant_table(ctx->params.jpeg_qmat_tab[1], scale);
- }
-}
diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h
index 5dd47e5..bbc18c0 100644
--- a/drivers/media/platform/coda/coda.h
+++ b/drivers/media/platform/coda/coda.h
@@ -45,15 +45,11 @@
CODA_960 = 0xf020,
};
-struct coda_video_device;
-
struct coda_devtype {
char *firmware;
enum coda_product product;
const struct coda_codec *codecs;
unsigned int num_codecs;
- const struct coda_video_device **vdevs;
- unsigned int num_vdevs;
size_t workbuf_size;
size_t tempbuf_size;
size_t iram_size;
@@ -69,7 +65,7 @@
struct coda_dev {
struct v4l2_device v4l2_dev;
- struct video_device vfd[5];
+ struct video_device vfd[2];
struct platform_device *plat_dev;
const struct coda_devtype *devtype;
@@ -118,9 +114,6 @@
u8 mpeg4_inter_qp;
u8 gop_size;
int intra_refresh;
- u8 jpeg_quality;
- u8 jpeg_restart_interval;
- u8 *jpeg_qmat_tab[3];
int codec_mode;
int codec_mode_aux;
enum v4l2_mpeg_video_multi_slice_mode slice_mode;
@@ -130,13 +123,11 @@
u32 slice_max_mb;
};
-struct coda_buffer_meta {
+struct coda_timestamp {
struct list_head list;
u32 sequence;
struct v4l2_timecode timecode;
struct timeval timestamp;
- u32 start;
- u32 end;
};
/* Per-queue, driver-specific private data */
@@ -192,7 +183,6 @@
struct work_struct pic_run_work;
struct work_struct seq_end_work;
struct completion completion;
- const struct coda_video_device *cvd;
const struct coda_context_ops *ops;
int aborting;
int initialized;
@@ -222,9 +212,9 @@
struct coda_aux_buf slicebuf;
struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS];
u32 frame_types[CODA_MAX_FRAMEBUFFERS];
- struct coda_buffer_meta frame_metas[CODA_MAX_FRAMEBUFFERS];
+ struct coda_timestamp frame_timestamps[CODA_MAX_FRAMEBUFFERS];
u32 frame_errors[CODA_MAX_FRAMEBUFFERS];
- struct list_head buffer_meta_list;
+ struct list_head timestamp_list;
struct coda_aux_buf workbuf;
int num_internal_frames;
int idx;
@@ -242,8 +232,6 @@
void coda_write(struct coda_dev *dev, u32 data, u32 reg);
unsigned int coda_read(struct coda_dev *dev, u32 reg);
-void coda_write_base(struct coda_ctx *ctx, struct coda_q_data *q_data,
- struct vb2_buffer *buf, unsigned int reg_y);
int coda_alloc_aux_buf(struct coda_dev *dev, struct coda_aux_buf *buf,
size_t size, const char *name, struct dentry *parent);
@@ -293,10 +281,6 @@
int coda_h264_padding(int size, char *p);
-bool coda_jpeg_check_buffer(struct coda_ctx *ctx, struct vb2_buffer *vb);
-int coda_jpeg_write_tables(struct coda_ctx *ctx);
-void coda_set_jpeg_compression_quality(struct coda_ctx *ctx, int quality);
-
extern const struct coda_context_ops coda_bit_encode_ops;
extern const struct coda_context_ops coda_bit_decode_ops;
diff --git a/drivers/media/platform/coda/coda_regs.h b/drivers/media/platform/coda/coda_regs.h
index 8e015b8..c791275 100644
--- a/drivers/media/platform/coda/coda_regs.h
+++ b/drivers/media/platform/coda/coda_regs.h
@@ -147,7 +147,6 @@
#define CODA_CMD_DEC_SEQ_BB_START 0x180
#define CODA_CMD_DEC_SEQ_BB_SIZE 0x184
#define CODA_CMD_DEC_SEQ_OPTION 0x188
-#define CODA_NO_INT_ENABLE (1 << 10)
#define CODA_REORDER_ENABLE (1 << 1)
#define CODADX6_QP_REPORT (1 << 0)
#define CODA7_MP4_DEBLK_ENABLE (1 << 0)
@@ -333,12 +332,6 @@
#define CODA9_CMD_ENC_SEQ_ME_OPTION 0x1d8
#define CODA_RET_ENC_SEQ_SUCCESS 0x1c0
-#define CODA_CMD_ENC_SEQ_JPG_PARA 0x198
-#define CODA_CMD_ENC_SEQ_JPG_RST_INTERVAL 0x19C
-#define CODA_CMD_ENC_SEQ_JPG_THUMB_EN 0x1a0
-#define CODA_CMD_ENC_SEQ_JPG_THUMB_SIZE 0x1a4
-#define CODA_CMD_ENC_SEQ_JPG_THUMB_OFFSET 0x1a8
-
/* Encoder Picture Run */
#define CODA9_CMD_ENC_PIC_SRC_INDEX 0x180
#define CODA9_CMD_ENC_PIC_SRC_STRIDE 0x184
diff --git a/drivers/media/platform/davinci/dm355_ccdc.c b/drivers/media/platform/davinci/dm355_ccdc.c
index c90b9a4..3f44deb 100644
--- a/drivers/media/platform/davinci/dm355_ccdc.c
+++ b/drivers/media/platform/davinci/dm355_ccdc.c
@@ -1030,6 +1030,7 @@
static struct platform_driver dm355_ccdc_driver = {
.driver = {
.name = "dm355_ccdc",
+ .owner = THIS_MODULE,
},
.remove = dm355_ccdc_remove,
.probe = dm355_ccdc_probe,
diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c
index ffbefdf..62a0ebb 100644
--- a/drivers/media/platform/davinci/dm644x_ccdc.c
+++ b/drivers/media/platform/davinci/dm644x_ccdc.c
@@ -1029,6 +1029,7 @@
static struct platform_driver dm644x_ccdc_driver = {
.driver = {
.name = "dm644x_ccdc",
+ .owner = THIS_MODULE,
.pm = &dm644x_ccdc_pm_ops,
},
.remove = dm644x_ccdc_remove,
diff --git a/drivers/media/platform/davinci/isif.c b/drivers/media/platform/davinci/isif.c
index 99faea2..3332cca 100644
--- a/drivers/media/platform/davinci/isif.c
+++ b/drivers/media/platform/davinci/isif.c
@@ -1134,6 +1134,7 @@
static struct platform_driver isif_driver = {
.driver = {
.name = "isif",
+ .owner = THIS_MODULE,
},
.remove = isif_remove,
.probe = isif_probe,
diff --git a/drivers/media/platform/davinci/vpbe.c b/drivers/media/platform/davinci/vpbe.c
index 9a6c2cc..33b9660 100644
--- a/drivers/media/platform/davinci/vpbe.c
+++ b/drivers/media/platform/davinci/vpbe.c
@@ -227,7 +227,7 @@
vpbe_current_encoder_info(vpbe_dev);
struct vpbe_config *cfg = vpbe_dev->cfg;
struct venc_platform_data *venc_device = vpbe_dev->venc_device;
- u32 if_params;
+ enum v4l2_mbus_pixelcode if_params;
int enc_out_index;
int sd_index;
int ret = 0;
@@ -341,7 +341,7 @@
if (!(cfg->outputs[out_index].output.capabilities &
V4L2_OUT_CAP_DV_TIMINGS))
- return -ENODATA;
+ return -EINVAL;
for (i = 0; i < output->num_modes; i++) {
if (output->modes[i].timings_type == VPBE_ENC_DV_TIMINGS &&
@@ -384,13 +384,6 @@
static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev,
struct v4l2_dv_timings *dv_timings)
{
- struct vpbe_config *cfg = vpbe_dev->cfg;
- int out_index = vpbe_dev->current_out_index;
-
- if (!(cfg->outputs[out_index].output.capabilities &
- V4L2_OUT_CAP_DV_TIMINGS))
- return -ENODATA;
-
if (vpbe_dev->current_timings.timings_type &
VPBE_ENC_DV_TIMINGS) {
*dv_timings = vpbe_dev->current_timings.dv_timings;
@@ -416,7 +409,7 @@
int i;
if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS))
- return -ENODATA;
+ return -EINVAL;
for (i = 0; i < output->num_modes; i++) {
if (output->modes[i].timings_type == VPBE_ENC_DV_TIMINGS) {
@@ -447,7 +440,7 @@
if (!(cfg->outputs[out_index].output.capabilities &
V4L2_OUT_CAP_STD))
- return -ENODATA;
+ return -EINVAL;
ret = vpbe_get_std_info(vpbe_dev, std_id);
if (ret)
@@ -480,11 +473,6 @@
static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
{
struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings;
- struct vpbe_config *cfg = vpbe_dev->cfg;
- int out_index = vpbe_dev->current_out_index;
-
- if (!(cfg->outputs[out_index].output.capabilities & V4L2_OUT_CAP_STD))
- return -ENODATA;
if (cur_timings->timings_type & VPBE_ENC_STD) {
*std_id = cur_timings->std_id;
@@ -625,7 +613,6 @@
}
if (clk_prepare_enable(vpbe_dev->dac_clk)) {
ret = -ENODEV;
- clk_put(vpbe_dev->dac_clk);
goto fail_mutex_unlock;
}
}
@@ -876,6 +863,7 @@
static struct platform_driver vpbe_driver = {
.driver = {
.name = "vpbe_controller",
+ .owner = THIS_MODULE,
},
.probe = vpbe_probe,
.remove = vpbe_remove,
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index c4ab46f..73496d9 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -152,8 +152,8 @@
for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
layer = disp_dev->dev[i];
-
- if (!vb2_start_streaming_called(&layer->buffer_queue))
+ /* If streaming is started in this layer */
+ if (!layer->started)
continue;
if (layer->layer_first_int) {
@@ -207,23 +207,31 @@
*/
static int vpbe_buffer_prepare(struct vb2_buffer *vb)
{
+ struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
struct vb2_queue *q = vb->vb2_queue;
- struct vpbe_layer *layer = vb2_get_drv_priv(q);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
unsigned long addr;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
"vpbe_buffer_prepare\n");
- vb2_set_plane_payload(vb, 0, layer->pix_fmt.sizeimage);
- if (vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
- return -EINVAL;
+ if (vb->state != VB2_BUF_STATE_ACTIVE &&
+ vb->state != VB2_BUF_STATE_PREPARED) {
+ vb2_set_plane_payload(vb, 0, layer->pix_fmt.sizeimage);
+ if (vb2_plane_vaddr(vb, 0) &&
+ vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
+ return -EINVAL;
- addr = vb2_dma_contig_plane_dma_addr(vb, 0);
- if (!IS_ALIGNED(addr, 8)) {
- v4l2_err(&vpbe_dev->v4l2_dev,
- "buffer_prepare:offset is not aligned to 32 bytes\n");
- return -EINVAL;
+ addr = vb2_dma_contig_plane_dma_addr(vb, 0);
+ if (q->streaming) {
+ if (!IS_ALIGNED(addr, 8)) {
+ v4l2_err(&vpbe_dev->v4l2_dev,
+ "buffer_prepare:offset is \
+ not aligned to 32 bytes\n");
+ return -EINVAL;
+ }
+ }
}
return 0;
}
@@ -239,20 +247,18 @@
{
/* Get the file handle object and layer object */
- struct vpbe_layer *layer = vb2_get_drv_priv(vq);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_buffer_setup\n");
- if (fmt && fmt->fmt.pix.sizeimage < layer->pix_fmt.sizeimage)
- return -EINVAL;
-
/* Store number of buffers allocated in numbuffer member */
- if (vq->num_buffers + *nbuffers < VPBE_DEFAULT_NUM_BUFS)
- *nbuffers = VPBE_DEFAULT_NUM_BUFS - vq->num_buffers;
+ if (*nbuffers < VPBE_DEFAULT_NUM_BUFS)
+ *nbuffers = layer->numbuffers = VPBE_DEFAULT_NUM_BUFS;
*nplanes = 1;
- sizes[0] = fmt ? fmt->fmt.pix.sizeimage : layer->pix_fmt.sizeimage;
+ sizes[0] = layer->pix_fmt.sizeimage;
alloc_ctxs[0] = layer->alloc_ctx;
return 0;
@@ -265,11 +271,12 @@
static void vpbe_buffer_queue(struct vb2_buffer *vb)
{
/* Get the file handle object and layer object */
+ struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
struct vpbe_disp_buffer *buf = container_of(vb,
struct vpbe_disp_buffer, vb);
- struct vpbe_layer *layer = vb2_get_drv_priv(vb->vb2_queue);
- struct vpbe_display *disp = layer->disp_dev;
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_display *disp = fh->disp_dev;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
unsigned long flags;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
@@ -281,14 +288,61 @@
spin_unlock_irqrestore(&disp->dma_queue_lock, flags);
}
+/*
+ * vpbe_buf_cleanup()
+ * This function is called from the vb2 layer to free memory allocated to
+ * the buffers
+ */
+static void vpbe_buf_cleanup(struct vb2_buffer *vb)
+{
+ /* Get the file handle object and layer object */
+ struct vpbe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+ struct vpbe_disp_buffer *buf = container_of(vb,
+ struct vpbe_disp_buffer, vb);
+ unsigned long flags;
+
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+ "vpbe_buf_cleanup\n");
+
+ spin_lock_irqsave(&layer->irqlock, flags);
+ if (vb->state == VB2_BUF_STATE_ACTIVE)
+ list_del_init(&buf->list);
+ spin_unlock_irqrestore(&layer->irqlock, flags);
+}
+
+static void vpbe_wait_prepare(struct vb2_queue *vq)
+{
+ struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+ struct vpbe_layer *layer = fh->layer;
+
+ mutex_unlock(&layer->opslock);
+}
+
+static void vpbe_wait_finish(struct vb2_queue *vq)
+{
+ struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+ struct vpbe_layer *layer = fh->layer;
+
+ mutex_lock(&layer->opslock);
+}
+
+static int vpbe_buffer_init(struct vb2_buffer *vb)
+{
+ struct vpbe_disp_buffer *buf = container_of(vb,
+ struct vpbe_disp_buffer, vb);
+
+ INIT_LIST_HEAD(&buf->list);
+ return 0;
+}
+
static int vpbe_start_streaming(struct vb2_queue *vq, unsigned int count)
{
- struct vpbe_layer *layer = vb2_get_drv_priv(vq);
- struct osd_state *osd_device = layer->disp_dev->osd_device;
+ struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+ struct vpbe_layer *layer = fh->layer;
int ret;
- osd_device->ops.disable_layer(osd_device, layer->layer_info.id);
-
/* Get the next frame from the buffer queue */
layer->next_frm = layer->cur_frm = list_entry(layer->dma_queue.next,
struct vpbe_disp_buffer, list);
@@ -300,7 +354,7 @@
layer->field_id = 0;
/* Set parameters in OSD and VENC */
- ret = vpbe_set_osd_display_params(layer->disp_dev, layer);
+ ret = vpbe_set_osd_display_params(fh->disp_dev, layer);
if (ret < 0) {
struct vpbe_disp_buffer *buf, *tmp;
@@ -317,6 +371,7 @@
* if request format is yuv420 semiplanar, need to
* enable both video windows
*/
+ layer->started = 1;
layer->layer_first_int = 1;
return ret;
@@ -324,16 +379,14 @@
static void vpbe_stop_streaming(struct vb2_queue *vq)
{
- struct vpbe_layer *layer = vb2_get_drv_priv(vq);
- struct osd_state *osd_device = layer->disp_dev->osd_device;
- struct vpbe_display *disp = layer->disp_dev;
+ struct vpbe_fh *fh = vb2_get_drv_priv(vq);
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_display *disp = fh->disp_dev;
unsigned long flags;
if (!vb2_is_streaming(vq))
return;
- osd_device->ops.disable_layer(osd_device, layer->layer_info.id);
-
/* release all active buffers */
spin_lock_irqsave(&disp->dma_queue_lock, flags);
if (layer->cur_frm == layer->next_frm) {
@@ -358,11 +411,13 @@
static struct vb2_ops video_qops = {
.queue_setup = vpbe_buffer_queue_setup,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .wait_prepare = vpbe_wait_prepare,
+ .wait_finish = vpbe_wait_finish,
+ .buf_init = vpbe_buffer_init,
.buf_prepare = vpbe_buffer_prepare,
.start_streaming = vpbe_start_streaming,
.stop_streaming = vpbe_stop_streaming,
+ .buf_cleanup = vpbe_buf_cleanup,
.buf_queue = vpbe_buffer_queue,
};
@@ -636,9 +691,10 @@
static int vpbe_display_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+ cap->version = VPBE_DISPLAY_VERSION_CODE;
cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
snprintf(cap->driver, sizeof(cap->driver), "%s",
@@ -653,8 +709,9 @@
static int vpbe_display_s_crop(struct file *file, void *priv,
const struct v4l2_crop *crop)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_display *disp_dev = layer->disp_dev;
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_display *disp_dev = fh->disp_dev;
struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
struct osd_layer_config *cfg = &layer->layer_info.config;
struct osd_state *osd_device = disp_dev->osd_device;
@@ -721,10 +778,11 @@
static int vpbe_display_g_crop(struct file *file, void *priv,
struct v4l2_crop *crop)
{
- struct vpbe_layer *layer = video_drvdata(file);
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
struct osd_layer_config *cfg = &layer->layer_info.config;
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
- struct osd_state *osd_device = layer->disp_dev->osd_device;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+ struct osd_state *osd_device = fh->disp_dev->osd_device;
struct v4l2_rect *rect = &crop->c;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
@@ -748,8 +806,8 @@
static int vpbe_display_cropcap(struct file *file, void *priv,
struct v4l2_cropcap *cropcap)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_CROPCAP ioctl\n");
@@ -766,8 +824,9 @@
static int vpbe_display_g_fmt(struct file *file, void *priv,
struct v4l2_format *fmt)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
"VIDIOC_G_FMT, layer id = %d\n",
@@ -787,8 +846,9 @@
static int vpbe_display_enum_fmt(struct file *file, void *priv,
struct v4l2_fmtdesc *fmt)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
unsigned int index = 0;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
@@ -818,8 +878,9 @@
static int vpbe_display_s_fmt(struct file *file, void *priv,
struct v4l2_format *fmt)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_display *disp_dev = layer->disp_dev;
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_display *disp_dev = fh->disp_dev;
struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
struct osd_layer_config *cfg = &layer->layer_info.config;
struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
@@ -830,9 +891,11 @@
"VIDIOC_S_FMT, layer id = %d\n",
layer->device_id);
- if (vb2_is_busy(&layer->buffer_queue))
+ /* If streaming is started, return error */
+ if (layer->started) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
return -EBUSY;
-
+ }
if (V4L2_BUF_TYPE_VIDEO_OUTPUT != fmt->type) {
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "invalid type\n");
return -EINVAL;
@@ -904,9 +967,9 @@
static int vpbe_display_try_fmt(struct file *file, void *priv,
struct v4l2_format *fmt)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_display *disp_dev = layer->disp_dev;
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_display *disp_dev = fh->disp_dev;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_TRY_FMT\n");
@@ -930,15 +993,18 @@
static int vpbe_display_s_std(struct file *file, void *priv,
v4l2_std_id std_id)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = priv;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
int ret;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_STD\n");
- if (vb2_is_busy(&layer->buffer_queue))
+ /* If streaming is started, return error */
+ if (layer->started) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
return -EBUSY;
-
+ }
if (NULL != vpbe_dev->ops.s_std) {
ret = vpbe_dev->ops.s_std(vpbe_dev, std_id);
if (ret) {
@@ -962,8 +1028,8 @@
static int vpbe_display_g_std(struct file *file, void *priv,
v4l2_std_id *std_id)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = priv;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_STD\n");
@@ -985,8 +1051,8 @@
static int vpbe_display_enum_output(struct file *file, void *priv,
struct v4l2_output *output)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = priv;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
int ret;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_OUTPUT\n");
@@ -1013,15 +1079,17 @@
static int vpbe_display_s_output(struct file *file, void *priv,
unsigned int i)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = priv;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
int ret;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_OUTPUT\n");
-
- if (vb2_is_busy(&layer->buffer_queue))
+ /* If streaming is started, return error */
+ if (layer->started) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
return -EBUSY;
-
+ }
if (NULL == vpbe_dev->ops.set_output)
return -EINVAL;
@@ -1042,8 +1110,8 @@
static int vpbe_display_g_output(struct file *file, void *priv,
unsigned int *i)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = priv;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_OUTPUT\n");
/* Get the standard from the current encoder */
@@ -1062,8 +1130,8 @@
vpbe_display_enum_dv_timings(struct file *file, void *priv,
struct v4l2_enum_dv_timings *timings)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = priv;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
int ret;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_TIMINGS\n");
@@ -1092,14 +1160,19 @@
vpbe_display_s_dv_timings(struct file *file, void *priv,
struct v4l2_dv_timings *timings)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = priv;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
int ret;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_TIMINGS\n");
- if (vb2_is_busy(&layer->buffer_queue))
+
+ /* If streaming is started, return error */
+ if (layer->started) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Streaming is started\n");
return -EBUSY;
+ }
/* Set the given standard in the encoder */
if (!vpbe_dev->ops.s_dv_timings)
@@ -1125,8 +1198,8 @@
vpbe_display_g_dv_timings(struct file *file, void *priv,
struct v4l2_dv_timings *dv_timings)
{
- struct vpbe_layer *layer = video_drvdata(file);
- struct vpbe_device *vpbe_dev = layer->disp_dev->vpbe_dev;
+ struct vpbe_fh *fh = priv;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_TIMINGS\n");
@@ -1142,6 +1215,259 @@
return 0;
}
+static int vpbe_display_streamoff(struct file *file, void *priv,
+ enum v4l2_buf_type buf_type)
+{
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+ struct osd_state *osd_device = fh->disp_dev->osd_device;
+ int ret;
+
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+ "VIDIOC_STREAMOFF,layer id = %d\n",
+ layer->device_id);
+
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+ return -EINVAL;
+ }
+
+ /* If io is allowed for this file handle, return error */
+ if (!fh->io_allowed) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+ return -EACCES;
+ }
+
+ /* If streaming is not started, return error */
+ if (!layer->started) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "streaming not started in layer"
+ " id = %d\n", layer->device_id);
+ return -EINVAL;
+ }
+
+ osd_device->ops.disable_layer(osd_device,
+ layer->layer_info.id);
+ layer->started = 0;
+ ret = vb2_streamoff(&layer->buffer_queue, buf_type);
+
+ return ret;
+}
+
+static int vpbe_display_streamon(struct file *file, void *priv,
+ enum v4l2_buf_type buf_type)
+{
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_display *disp_dev = fh->disp_dev;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+ struct osd_state *osd_device = disp_dev->osd_device;
+ int ret;
+
+ osd_device->ops.disable_layer(osd_device,
+ layer->layer_info.id);
+
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_STREAMON, layerid=%d\n",
+ layer->device_id);
+
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf_type) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+ return -EINVAL;
+ }
+
+ /* If file handle is not allowed IO, return error */
+ if (!fh->io_allowed) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+ return -EACCES;
+ }
+ /* If Streaming is already started, return error */
+ if (layer->started) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "layer is already streaming\n");
+ return -EBUSY;
+ }
+
+ /*
+ * Call vb2_streamon to start streaming
+ * in videobuf
+ */
+ ret = vb2_streamon(&layer->buffer_queue, buf_type);
+ if (ret) {
+ v4l2_err(&vpbe_dev->v4l2_dev,
+ "error in vb2_streamon\n");
+ return ret;
+ }
+ return ret;
+}
+
+static int vpbe_display_dqbuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+ int ret;
+
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+ "VIDIOC_DQBUF, layer id = %d\n",
+ layer->device_id);
+
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+ return -EINVAL;
+ }
+ /* If this file handle is not allowed to do IO, return error */
+ if (!fh->io_allowed) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+ return -EACCES;
+ }
+ if (file->f_flags & O_NONBLOCK)
+ /* Call videobuf_dqbuf for non blocking mode */
+ ret = vb2_dqbuf(&layer->buffer_queue, buf, 1);
+ else
+ /* Call videobuf_dqbuf for blocking mode */
+ ret = vb2_dqbuf(&layer->buffer_queue, buf, 0);
+
+ return ret;
+}
+
+static int vpbe_display_qbuf(struct file *file, void *priv,
+ struct v4l2_buffer *p)
+{
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+ "VIDIOC_QBUF, layer id = %d\n",
+ layer->device_id);
+
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != p->type) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+ return -EINVAL;
+ }
+
+ /* If this file handle is not allowed to do IO, return error */
+ if (!fh->io_allowed) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "No io_allowed\n");
+ return -EACCES;
+ }
+
+ return vb2_qbuf(&layer->buffer_queue, p);
+}
+
+static int vpbe_display_querybuf(struct file *file, void *priv,
+ struct v4l2_buffer *buf)
+{
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+ "VIDIOC_QUERYBUF, layer id = %d\n",
+ layer->device_id);
+
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != buf->type) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+ return -EINVAL;
+ }
+ /* Call vb2_querybuf to get information */
+ return vb2_querybuf(&layer->buffer_queue, buf);
+}
+
+static int vpbe_display_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *req_buf)
+{
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+ struct vb2_queue *q;
+ int ret;
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_reqbufs\n");
+
+ if (V4L2_BUF_TYPE_VIDEO_OUTPUT != req_buf->type) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Invalid buffer type\n");
+ return -EINVAL;
+ }
+
+ /* If io users of the layer is not zero, return error */
+ if (0 != layer->io_usrs) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "not IO user\n");
+ return -EBUSY;
+ }
+ /* Initialize videobuf queue as per the buffer type */
+ layer->alloc_ctx = vb2_dma_contig_init_ctx(vpbe_dev->pdev);
+ if (IS_ERR(layer->alloc_ctx)) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "Failed to get the context\n");
+ return PTR_ERR(layer->alloc_ctx);
+ }
+ q = &layer->buffer_queue;
+ memset(q, 0, sizeof(*q));
+ q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ q->io_modes = VB2_MMAP | VB2_USERPTR;
+ q->drv_priv = fh;
+ q->ops = &video_qops;
+ q->mem_ops = &vb2_dma_contig_memops;
+ q->buf_struct_size = sizeof(struct vpbe_disp_buffer);
+ q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ q->min_buffers_needed = 1;
+
+ ret = vb2_queue_init(q);
+ if (ret) {
+ v4l2_err(&vpbe_dev->v4l2_dev, "vb2_queue_init() failed\n");
+ vb2_dma_contig_cleanup_ctx(layer->alloc_ctx);
+ return ret;
+ }
+ /* Set io allowed member of file handle to TRUE */
+ fh->io_allowed = 1;
+ /* Increment io usrs member of layer object to 1 */
+ layer->io_usrs = 1;
+ /* Store type of memory requested in layer object */
+ layer->memory = req_buf->memory;
+ /* Initialize buffer queue */
+ INIT_LIST_HEAD(&layer->dma_queue);
+ /* Allocate buffers */
+ return vb2_reqbufs(q, req_buf);
+}
+
+/*
+ * vpbe_display_mmap()
+ * It is used to map kernel space buffers into user spaces
+ */
+static int vpbe_display_mmap(struct file *filep, struct vm_area_struct *vma)
+{
+ /* Get the layer object and file handle object */
+ struct vpbe_fh *fh = filep->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+ int ret;
+
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_mmap\n");
+
+ if (mutex_lock_interruptible(&layer->opslock))
+ return -ERESTARTSYS;
+ ret = vb2_mmap(&layer->buffer_queue, vma);
+ mutex_unlock(&layer->opslock);
+ return ret;
+}
+
+/* vpbe_display_poll(): It is used for select/poll system call
+ */
+static unsigned int vpbe_display_poll(struct file *filep, poll_table *wait)
+{
+ struct vpbe_fh *fh = filep->private_data;
+ struct vpbe_layer *layer = fh->layer;
+ struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+ unsigned int err = 0;
+
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_poll\n");
+ if (layer->started) {
+ mutex_lock(&layer->opslock);
+ err = vb2_poll(&layer->buffer_queue, filep, wait);
+ mutex_unlock(&layer->opslock);
+ }
+ return err;
+}
+
/*
* vpbe_display_open()
* It creates object of file handle structure and stores it in private_data
@@ -1149,22 +1475,30 @@
*/
static int vpbe_display_open(struct file *file)
{
+ struct vpbe_fh *fh = NULL;
struct vpbe_layer *layer = video_drvdata(file);
+ struct video_device *vdev = video_devdata(file);
struct vpbe_display *disp_dev = layer->disp_dev;
struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
struct osd_state *osd_device = disp_dev->osd_device;
int err;
- /* creating context for file descriptor */
- err = v4l2_fh_open(file);
- if (err) {
- v4l2_err(&vpbe_dev->v4l2_dev, "v4l2_fh_open failed\n");
- return err;
+ /* Allocate memory for the file handle object */
+ fh = kmalloc(sizeof(struct vpbe_fh), GFP_KERNEL);
+ if (fh == NULL) {
+ v4l2_err(&vpbe_dev->v4l2_dev,
+ "unable to allocate memory for file handle object\n");
+ return -ENOMEM;
}
+ v4l2_fh_init(&fh->fh, vdev);
+ v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
+ "vpbe display open plane = %d\n",
+ layer->device_id);
- /* leaving if layer is already initialized */
- if (!v4l2_fh_is_singular_file(file))
- return err;
+ /* store pointer to fh in private_data member of filep */
+ file->private_data = fh;
+ fh->layer = layer;
+ fh->disp_dev = disp_dev;
if (!layer->usrs) {
if (mutex_lock_interruptible(&layer->opslock))
@@ -1177,12 +1511,15 @@
/* Couldn't get layer */
v4l2_err(&vpbe_dev->v4l2_dev,
"Display Manager failed to allocate layer\n");
- v4l2_fh_release(file);
+ kfree(fh);
return -EINVAL;
}
}
/* Increment layer usrs counter */
layer->usrs++;
+ /* Set io_allowed member to false */
+ fh->io_allowed = 0;
+ v4l2_fh_add(&fh->fh);
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
"vpbe display device opened successfully\n");
return 0;
@@ -1195,18 +1532,30 @@
*/
static int vpbe_display_release(struct file *file)
{
- struct vpbe_layer *layer = video_drvdata(file);
+ /* Get the layer object and file handle object */
+ struct vpbe_fh *fh = file->private_data;
+ struct vpbe_layer *layer = fh->layer;
struct osd_layer_config *cfg = &layer->layer_info.config;
- struct vpbe_display *disp_dev = layer->disp_dev;
+ struct vpbe_display *disp_dev = fh->disp_dev;
struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
struct osd_state *osd_device = disp_dev->osd_device;
v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_release\n");
mutex_lock(&layer->opslock);
+ /* if this instance is doing IO */
+ if (fh->io_allowed) {
+ /* Reset io_usrs member of layer object */
+ layer->io_usrs = 0;
- osd_device->ops.disable_layer(osd_device,
- layer->layer_info.id);
+ osd_device->ops.disable_layer(osd_device,
+ layer->layer_info.id);
+ layer->started = 0;
+ /* Free buffers allocated */
+ vb2_queue_release(&layer->buffer_queue);
+ vb2_dma_contig_cleanup_ctx(&layer->buffer_queue);
+ }
+
/* Decrement layer usrs counter */
layer->usrs--;
/* If this file handle has initialize encoder device, reset it */
@@ -1226,9 +1575,14 @@
layer->layer_info.id);
}
- _vb2_fop_release(file, NULL);
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
+ file->private_data = NULL;
mutex_unlock(&layer->opslock);
+ /* Free memory allocated to file handle object */
+ kfree(fh);
+
disp_dev->cbcr_ofst = 0;
return 0;
@@ -1241,27 +1595,20 @@
.vidioc_enum_fmt_vid_out = vpbe_display_enum_fmt,
.vidioc_s_fmt_vid_out = vpbe_display_s_fmt,
.vidioc_try_fmt_vid_out = vpbe_display_try_fmt,
-
- .vidioc_reqbufs = vb2_ioctl_reqbufs,
- .vidioc_create_bufs = vb2_ioctl_create_bufs,
- .vidioc_querybuf = vb2_ioctl_querybuf,
- .vidioc_qbuf = vb2_ioctl_qbuf,
- .vidioc_dqbuf = vb2_ioctl_dqbuf,
- .vidioc_streamon = vb2_ioctl_streamon,
- .vidioc_streamoff = vb2_ioctl_streamoff,
- .vidioc_expbuf = vb2_ioctl_expbuf,
-
+ .vidioc_reqbufs = vpbe_display_reqbufs,
+ .vidioc_querybuf = vpbe_display_querybuf,
+ .vidioc_qbuf = vpbe_display_qbuf,
+ .vidioc_dqbuf = vpbe_display_dqbuf,
+ .vidioc_streamon = vpbe_display_streamon,
+ .vidioc_streamoff = vpbe_display_streamoff,
.vidioc_cropcap = vpbe_display_cropcap,
.vidioc_g_crop = vpbe_display_g_crop,
.vidioc_s_crop = vpbe_display_s_crop,
-
.vidioc_s_std = vpbe_display_s_std,
.vidioc_g_std = vpbe_display_g_std,
-
.vidioc_enum_output = vpbe_display_enum_output,
.vidioc_s_output = vpbe_display_s_output,
.vidioc_g_output = vpbe_display_g_output,
-
.vidioc_s_dv_timings = vpbe_display_s_dv_timings,
.vidioc_g_dv_timings = vpbe_display_g_dv_timings,
.vidioc_enum_dv_timings = vpbe_display_enum_dv_timings,
@@ -1272,8 +1619,8 @@
.open = vpbe_display_open,
.release = vpbe_display_release,
.unlocked_ioctl = video_ioctl2,
- .mmap = vb2_fop_mmap,
- .poll = vb2_fop_poll,
+ .mmap = vpbe_display_mmap,
+ .poll = vpbe_display_poll
};
static int vpbe_device_get(struct device *dev, void *data)
@@ -1353,7 +1700,6 @@
(int)vpbe_display_layer,
(int)&vpbe_display_layer->video_dev);
- vpbe_display_layer->video_dev.queue = &vpbe_display_layer->buffer_queue;
err = video_register_device(&vpbe_display_layer->video_dev,
VFL_TYPE_GRABBER,
-1);
@@ -1378,10 +1724,9 @@
*/
static int vpbe_display_probe(struct platform_device *pdev)
{
+ struct vpbe_layer *vpbe_display_layer;
struct vpbe_display *disp_dev;
- struct v4l2_device *v4l2_dev;
struct resource *res = NULL;
- struct vb2_queue *q;
int k;
int i;
int err;
@@ -1403,14 +1748,13 @@
vpbe_device_get);
if (err < 0)
return err;
-
- v4l2_dev = &disp_dev->vpbe_dev->v4l2_dev;
/* Initialize the vpbe display controller */
if (NULL != disp_dev->vpbe_dev->ops.initialize) {
err = disp_dev->vpbe_dev->ops.initialize(&pdev->dev,
disp_dev->vpbe_dev);
if (err) {
- v4l2_err(v4l2_dev, "Error initing vpbe\n");
+ v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
+ "Error initing vpbe\n");
err = -ENOMEM;
goto probe_out;
}
@@ -1425,7 +1769,8 @@
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
if (!res) {
- v4l2_err(v4l2_dev, "Unable to get VENC interrupt resource\n");
+ v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
+ "Unable to get VENC interrupt resource\n");
err = -ENODEV;
goto probe_out;
}
@@ -1434,57 +1779,30 @@
err = devm_request_irq(&pdev->dev, irq, venc_isr, 0,
VPBE_DISPLAY_DRIVER, disp_dev);
if (err) {
- v4l2_err(v4l2_dev, "VPBE IRQ request failed\n");
+ v4l2_err(&disp_dev->vpbe_dev->v4l2_dev,
+ "Unable to request interrupt\n");
goto probe_out;
}
for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
- /* initialize vb2 queue */
- q = &disp_dev->dev[i]->buffer_queue;
- memset(q, 0, sizeof(*q));
- q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
- q->drv_priv = disp_dev->dev[i];
- q->ops = &video_qops;
- q->mem_ops = &vb2_dma_contig_memops;
- q->buf_struct_size = sizeof(struct vpbe_disp_buffer);
- q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- q->min_buffers_needed = 1;
- q->lock = &disp_dev->dev[i]->opslock;
- err = vb2_queue_init(q);
- if (err) {
- v4l2_err(v4l2_dev, "vb2_queue_init() failed\n");
- goto probe_out;
- }
-
- disp_dev->dev[i]->alloc_ctx =
- vb2_dma_contig_init_ctx(disp_dev->vpbe_dev->pdev);
- if (IS_ERR(disp_dev->dev[i]->alloc_ctx)) {
- v4l2_err(v4l2_dev, "Failed to get the context\n");
- err = PTR_ERR(disp_dev->dev[i]->alloc_ctx);
- goto probe_out;
- }
-
- INIT_LIST_HEAD(&disp_dev->dev[i]->dma_queue);
-
if (register_device(disp_dev->dev[i], disp_dev, pdev)) {
err = -ENODEV;
goto probe_out;
}
}
- v4l2_dbg(1, debug, v4l2_dev,
- "Successfully completed the probing of vpbe v4l2 device\n");
-
+ printk(KERN_DEBUG "Successfully completed the probing of vpbe v4l2 device\n");
return 0;
probe_out:
for (k = 0; k < VPBE_DISPLAY_MAX_DEVICES; k++) {
+ /* Get the pointer to the layer object */
+ vpbe_display_layer = disp_dev->dev[k];
/* Unregister video device */
- if (disp_dev->dev[k] != NULL) {
- vb2_dma_contig_cleanup_ctx(disp_dev->dev[k]->alloc_ctx);
- video_unregister_device(&disp_dev->dev[k]->video_dev);
- kfree(disp_dev->dev[k]);
+ if (vpbe_display_layer) {
+ video_unregister_device(
+ &vpbe_display_layer->video_dev);
+ kfree(disp_dev->dev[k]);
}
}
return err;
@@ -1510,7 +1828,6 @@
for (i = 0; i < VPBE_DISPLAY_MAX_DEVICES; i++) {
/* Get the pointer to the layer object */
vpbe_display_layer = disp_dev->dev[i];
- vb2_dma_contig_cleanup_ctx(vpbe_display_layer->alloc_ctx);
/* Unregister video device */
video_unregister_device(&vpbe_display_layer->video_dev);
@@ -1526,6 +1843,7 @@
static struct platform_driver vpbe_display_driver = {
.driver = {
.name = VPBE_DISPLAY_DRIVER,
+ .owner = THIS_MODULE,
.bus = &platform_bus_type,
},
.probe = vpbe_display_probe,
diff --git a/drivers/media/platform/davinci/vpbe_osd.c b/drivers/media/platform/davinci/vpbe_osd.c
index 7d96a4b..d053c26 100644
--- a/drivers/media/platform/davinci/vpbe_osd.c
+++ b/drivers/media/platform/davinci/vpbe_osd.c
@@ -1585,6 +1585,7 @@
.remove = osd_remove,
.driver = {
.name = MODULE_NAME,
+ .owner = THIS_MODULE,
},
.id_table = vpbe_osd_devtype
};
diff --git a/drivers/media/platform/davinci/vpbe_venc.c b/drivers/media/platform/davinci/vpbe_venc.c
index 36ed146..14a023a 100644
--- a/drivers/media/platform/davinci/vpbe_venc.c
+++ b/drivers/media/platform/davinci/vpbe_venc.c
@@ -687,6 +687,7 @@
.remove = venc_remove,
.driver = {
.name = MODULE_NAME,
+ .owner = THIS_MODULE,
},
.id_table = vpbe_venc_devtype
};
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
index b41bf7e..de55f47 100644
--- a/drivers/media/platform/davinci/vpfe_capture.c
+++ b/drivers/media/platform/davinci/vpfe_capture.c
@@ -414,13 +414,13 @@
/* assume V4L2_PIX_FMT_UYVY as default */
pix->pixelformat = V4L2_PIX_FMT_UYVY;
v4l2_fill_mbus_format(&mbus_fmt, pix,
- MEDIA_BUS_FMT_YUYV10_2X10);
+ V4L2_MBUS_FMT_YUYV10_2X10);
} else {
pix->field = V4L2_FIELD_NONE;
/* assume V4L2_PIX_FMT_SBGGR8 */
pix->pixelformat = V4L2_PIX_FMT_SBGGR8;
v4l2_fill_mbus_format(&mbus_fmt, pix,
- MEDIA_BUS_FMT_SBGGR8_1X8);
+ V4L2_MBUS_FMT_SBGGR8_1X8);
}
/* if sub device supports g_mbus_fmt, override the defaults */
@@ -930,8 +930,8 @@
v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ cap->version = VPFE_CAPTURE_VERSION_CODE;
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
@@ -2031,6 +2031,7 @@
static struct platform_driver vpfe_driver = {
.driver = {
.name = CAPTURE_DRV_NAME,
+ .owner = THIS_MODULE,
.pm = &vpfe_dev_pm_ops,
},
.probe = vpfe_probe,
diff --git a/drivers/media/platform/davinci/vpif.c b/drivers/media/platform/davinci/vpif.c
index 0380cf2..3dad5bd 100644
--- a/drivers/media/platform/davinci/vpif.c
+++ b/drivers/media/platform/davinci/vpif.c
@@ -467,6 +467,7 @@
static struct platform_driver vpif_driver = {
.driver = {
.name = "vpif",
+ .owner = THIS_MODULE,
.pm = vpif_pm_ops,
},
.remove = vpif_remove,
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index fa0a515..3ccb26f 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -311,8 +311,6 @@
.start_streaming = vpif_start_streaming,
.stop_streaming = vpif_stop_streaming,
.buf_queue = vpif_buffer_queue,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
};
/**
@@ -1658,6 +1656,7 @@
static __refdata struct platform_driver vpif_driver = {
.driver = {
.name = VPIF_DRIVER_NAME,
+ .owner = THIS_MODULE,
.pm = &vpif_pm_ops,
},
.probe = vpif_probe,
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index 839c24d..8d6ced5 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -1459,6 +1459,7 @@
static __refdata struct platform_driver vpif_driver = {
.driver = {
.name = VPIF_DRIVER_NAME,
+ .owner = THIS_MODULE,
.pm = &vpif_pm_ops,
},
.probe = vpif_probe,
diff --git a/drivers/media/platform/davinci/vpss.c b/drivers/media/platform/davinci/vpss.c
index fce86f1..31120b4 100644
--- a/drivers/media/platform/davinci/vpss.c
+++ b/drivers/media/platform/davinci/vpss.c
@@ -504,6 +504,7 @@
static struct platform_driver vpss_driver = {
.driver = {
.name = "vpss",
+ .owner = THIS_MODULE,
.pm = &vpss_pm_ops,
},
.remove = vpss_remove,
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
index fd2891c..b4c9f1d 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.c
+++ b/drivers/media/platform/exynos-gsc/gsc-core.c
@@ -54,7 +54,7 @@
.corder = GSC_CBCR,
.num_planes = 1,
.num_comp = 1,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
}, {
.name = "YUV 4:2:2 packed, CbYCrY",
.pixelformat = V4L2_PIX_FMT_UYVY,
@@ -64,7 +64,7 @@
.corder = GSC_CBCR,
.num_planes = 1,
.num_comp = 1,
- .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
}, {
.name = "YUV 4:2:2 packed, CrYCbY",
.pixelformat = V4L2_PIX_FMT_VYUY,
@@ -74,7 +74,7 @@
.corder = GSC_CRCB,
.num_planes = 1,
.num_comp = 1,
- .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8,
}, {
.name = "YUV 4:2:2 packed, YCrYCb",
.pixelformat = V4L2_PIX_FMT_YVYU,
@@ -84,7 +84,7 @@
.corder = GSC_CRCB,
.num_planes = 1,
.num_comp = 1,
- .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8,
}, {
.name = "YUV 4:4:4 planar, YCbYCr",
.pixelformat = V4L2_PIX_FMT_YUV32,
@@ -319,22 +319,21 @@
return 0;
}
-static int get_plane_info(struct gsc_frame *frm, u32 addr, u32 *index, u32 *ret_addr)
+static u32 get_plane_info(struct gsc_frame *frm, u32 addr, u32 *index)
{
if (frm->addr.y == addr) {
*index = 0;
- *ret_addr = frm->addr.y;
+ return frm->addr.y;
} else if (frm->addr.cb == addr) {
*index = 1;
- *ret_addr = frm->addr.cb;
+ return frm->addr.cb;
} else if (frm->addr.cr == addr) {
*index = 2;
- *ret_addr = frm->addr.cr;
+ return frm->addr.cr;
} else {
pr_err("Plane address is wrong");
return -EINVAL;
}
- return 0;
}
void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm)
@@ -353,11 +352,9 @@
u32 t_min, t_max;
t_min = min3(frm->addr.y, frm->addr.cb, frm->addr.cr);
- if (get_plane_info(frm, t_min, &low_plane, &low_addr))
- return;
+ low_addr = get_plane_info(frm, t_min, &low_plane);
t_max = max3(frm->addr.y, frm->addr.cb, frm->addr.cr);
- if (get_plane_info(frm, t_max, &high_plane, &high_addr))
- return;
+ high_addr = get_plane_info(frm, t_max, &high_plane);
mid_plane = 3 - (low_plane + high_plane);
if (mid_plane == 0)
@@ -1256,6 +1253,7 @@
.id_table = gsc_driver_ids,
.driver = {
.name = GSC_MODULE_NAME,
+ .owner = THIS_MODULE,
.pm = &gsc_pm_ops,
.of_match_table = exynos_gsc_match,
}
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
index 0abdb17..ef0a656 100644
--- a/drivers/media/platform/exynos-gsc/gsc-core.h
+++ b/drivers/media/platform/exynos-gsc/gsc-core.h
@@ -117,7 +117,7 @@
* @flags: flags indicating which operation mode format applies to
*/
struct gsc_fmt {
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
char *name;
u32 pixelformat;
u32 color;
diff --git a/drivers/media/platform/exynos4-is/Kconfig b/drivers/media/platform/exynos4-is/Kconfig
index 9986ed7..8b0a506 100644
--- a/drivers/media/platform/exynos4-is/Kconfig
+++ b/drivers/media/platform/exynos4-is/Kconfig
@@ -2,7 +2,7 @@
config VIDEO_SAMSUNG_EXYNOS4_IS
bool "Samsung S5P/EXYNOS4 SoC series Camera Subsystem driver"
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
- depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+ depends on (PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST)
depends on OF && COMMON_CLK
help
Say Y here to enable camera host interface devices for
diff --git a/drivers/media/platform/exynos4-is/fimc-capture.c b/drivers/media/platform/exynos4-is/fimc-capture.c
index 8a2fd8c..3d2babd 100644
--- a/drivers/media/platform/exynos4-is/fimc-capture.c
+++ b/drivers/media/platform/exynos4-is/fimc-capture.c
@@ -749,7 +749,7 @@
return -EINVAL;
strncpy(f->description, fmt->name, sizeof(f->description) - 1);
f->pixelformat = fmt->fourcc;
- if (fmt->fourcc == MEDIA_BUS_FMT_JPEG_1X8)
+ if (fmt->fourcc == V4L2_MBUS_FMT_JPEG_1X8)
f->flags |= V4L2_FMT_FLAG_COMPRESSED;
return 0;
}
diff --git a/drivers/media/platform/exynos4-is/fimc-core.c b/drivers/media/platform/exynos4-is/fimc-core.c
index 1101c41..b70fd99 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.c
+++ b/drivers/media/platform/exynos4-is/fimc-core.c
@@ -81,7 +81,7 @@
.flags = FMT_FLAGS_M2M_OUT | FMT_HAS_ALPHA,
}, {
.name = "YUV 4:4:4",
- .mbus_code = MEDIA_BUS_FMT_YUV10_1X30,
+ .mbus_code = V4L2_MBUS_FMT_YUV10_1X30,
.flags = FMT_FLAGS_WRITEBACK,
}, {
.name = "YUV 4:2:2 packed, YCbYCr",
@@ -90,7 +90,7 @@
.color = FIMC_FMT_YCBYCR422,
.memplanes = 1,
.colplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
}, {
.name = "YUV 4:2:2 packed, CbYCrY",
@@ -99,7 +99,7 @@
.color = FIMC_FMT_CBYCRY422,
.memplanes = 1,
.colplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
.flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
}, {
.name = "YUV 4:2:2 packed, CrYCbY",
@@ -108,7 +108,7 @@
.color = FIMC_FMT_CRYCBY422,
.memplanes = 1,
.colplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8,
.flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
}, {
.name = "YUV 4:2:2 packed, YCrYCb",
@@ -117,7 +117,7 @@
.color = FIMC_FMT_YCRYCB422,
.memplanes = 1,
.colplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8,
.flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
}, {
.name = "YUV 4:2:2 planar, Y/Cb/Cr",
@@ -190,7 +190,7 @@
.depth = { 8 },
.memplanes = 1,
.colplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_JPEG_1X8,
+ .mbus_code = V4L2_MBUS_FMT_JPEG_1X8,
.flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
}, {
.name = "S5C73MX interleaved UYVY/JPEG",
@@ -200,7 +200,7 @@
.memplanes = 2,
.colplanes = 1,
.mdataplanes = 0x2, /* plane 1 holds frame meta data */
- .mbus_code = MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8,
+ .mbus_code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
.flags = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
},
};
@@ -832,7 +832,6 @@
return -ENXIO;
}
-#ifdef CONFIG_PM
static int fimc_m2m_suspend(struct fimc_dev *fimc)
{
unsigned long flags;
@@ -871,7 +870,6 @@
return 0;
}
-#endif /* CONFIG_PM */
static const struct of_device_id fimc_of_match[];
@@ -1039,7 +1037,7 @@
return ret;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
static int fimc_runtime_resume(struct device *dev)
{
struct fimc_dev *fimc = dev_get_drvdata(dev);
@@ -1294,6 +1292,7 @@
.driver = {
.of_match_table = fimc_of_match,
.name = FIMC_DRIVER_NAME,
+ .owner = THIS_MODULE,
.pm = &fimc_pm_ops,
}
};
diff --git a/drivers/media/platform/exynos4-is/fimc-core.h b/drivers/media/platform/exynos4-is/fimc-core.h
index 7328f08..6c75c6c 100644
--- a/drivers/media/platform/exynos4-is/fimc-core.h
+++ b/drivers/media/platform/exynos4-is/fimc-core.h
@@ -579,8 +579,8 @@
static inline bool fimc_user_defined_mbus_fmt(u32 code)
{
- return (code == MEDIA_BUS_FMT_JPEG_1X8 ||
- code == MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8);
+ return (code == V4L2_MBUS_FMT_JPEG_1X8 ||
+ code == V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8);
}
/* Return the alpha component bit mask */
diff --git a/drivers/media/platform/exynos4-is/fimc-is-i2c.c b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
index 7521aa5..371cad4 100644
--- a/drivers/media/platform/exynos4-is/fimc-is-i2c.c
+++ b/drivers/media/platform/exynos4-is/fimc-is-i2c.c
@@ -81,7 +81,7 @@
return 0;
}
-#ifdef CONFIG_PM
+#if defined(CONFIG_PM_RUNTIME) || defined(CONFIG_PM_SLEEP)
static int fimc_is_i2c_runtime_suspend(struct device *dev)
{
struct fimc_is_i2c *isp_i2c = dev_get_drvdata(dev);
@@ -133,6 +133,7 @@
.driver = {
.of_match_table = fimc_is_i2c_of_match,
.name = "fimc-isp-i2c",
+ .owner = THIS_MODULE,
.pm = &fimc_is_i2c_pm_ops,
}
};
diff --git a/drivers/media/platform/exynos4-is/fimc-is.c b/drivers/media/platform/exynos4-is/fimc-is.c
index 49658ca..22162b2 100644
--- a/drivers/media/platform/exynos4-is/fimc-is.c
+++ b/drivers/media/platform/exynos4-is/fimc-is.c
@@ -428,7 +428,8 @@
* needed around for copying to the IS working memory every
* time before the Cortex-A5 is restarted.
*/
- release_firmware(is->fw.f_w);
+ if (is->fw.f_w)
+ release_firmware(is->fw.f_w);
is->fw.f_w = fw;
done:
mutex_unlock(&is->lock);
@@ -813,9 +814,9 @@
return -ENOMEM;
is->irq = irq_of_parse_and_map(dev->of_node, 0);
- if (!is->irq) {
+ if (is->irq < 0) {
dev_err(dev, "no irq found\n");
- return -EINVAL;
+ return is->irq;
}
ret = fimc_is_get_clocks(is);
@@ -936,7 +937,8 @@
vb2_dma_contig_cleanup_ctx(is->alloc_ctx);
fimc_is_put_clocks(is);
fimc_is_debugfs_remove(is);
- release_firmware(is->fw.f_w);
+ if (is->fw.f_w)
+ release_firmware(is->fw.f_w);
fimc_is_free_cpu_memory(is);
return 0;
@@ -960,6 +962,7 @@
.driver = {
.of_match_table = fimc_is_of_match,
.name = FIMC_IS_DRV_NAME,
+ .owner = THIS_MODULE,
.pm = &fimc_is_pm_ops,
}
};
diff --git a/drivers/media/platform/exynos4-is/fimc-isp.c b/drivers/media/platform/exynos4-is/fimc-isp.c
index 60c7449..be62d6b 100644
--- a/drivers/media/platform/exynos4-is/fimc-isp.c
+++ b/drivers/media/platform/exynos4-is/fimc-isp.c
@@ -41,21 +41,21 @@
.depth = { 8 },
.color = FIMC_FMT_RAW8,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .mbus_code = V4L2_MBUS_FMT_SGRBG8_1X8,
}, {
.name = "RAW10 (GRBG)",
.fourcc = V4L2_PIX_FMT_SGRBG10,
.depth = { 10 },
.color = FIMC_FMT_RAW10,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
}, {
.name = "RAW12 (GRBG)",
.fourcc = V4L2_PIX_FMT_SGRBG12,
.depth = { 12 },
.color = FIMC_FMT_RAW12,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
+ .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12,
},
};
@@ -149,7 +149,7 @@
if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) {
mf->colorspace = V4L2_COLORSPACE_JPEG;
- mf->code = MEDIA_BUS_FMT_YUV10_1X30;
+ mf->code = V4L2_MBUS_FMT_YUV10_1X30;
}
}
@@ -175,7 +175,7 @@
FIMC_ISP_SINK_WIDTH_MAX, 0,
&mf->height, FIMC_ISP_SINK_HEIGHT_MIN,
FIMC_ISP_SINK_HEIGHT_MAX, 0, 0);
- mf->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ mf->code = V4L2_MBUS_FMT_SGRBG10_1X10;
} else {
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY)
format = v4l2_subdev_get_try_format(fh,
@@ -188,7 +188,7 @@
mf->height = format->height - FIMC_ISP_CAC_MARGIN_HEIGHT;
if (fmt->pad == FIMC_ISP_SD_PAD_SRC_FIFO) {
- mf->code = MEDIA_BUS_FMT_YUV10_1X30;
+ mf->code = V4L2_MBUS_FMT_YUV10_1X30;
mf->colorspace = V4L2_COLORSPACE_JPEG;
} else {
mf->code = format->code;
@@ -680,11 +680,11 @@
FIMC_ISP_CAC_MARGIN_WIDTH;
isp->sink_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT +
FIMC_ISP_CAC_MARGIN_HEIGHT;
- isp->sink_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ isp->sink_fmt.code = V4L2_MBUS_FMT_SGRBG10_1X10;
isp->src_fmt.width = DEFAULT_PREVIEW_STILL_WIDTH;
isp->src_fmt.height = DEFAULT_PREVIEW_STILL_HEIGHT;
- isp->src_fmt.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ isp->src_fmt.code = V4L2_MBUS_FMT_SGRBG10_1X10;
__is_set_frame_size(is, &isp->src_fmt);
}
diff --git a/drivers/media/platform/exynos4-is/fimc-lite-reg.c b/drivers/media/platform/exynos4-is/fimc-lite-reg.c
index 0477716..bc3ec7d 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite-reg.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite-reg.c
@@ -112,24 +112,24 @@
}
static const u32 src_pixfmt_map[8][3] = {
- { MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR,
+ { V4L2_MBUS_FMT_YUYV8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCBYCR,
FLITE_REG_CIGCTRL_YUV422_1P },
- { MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB,
+ { V4L2_MBUS_FMT_YVYU8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_YCRYCB,
FLITE_REG_CIGCTRL_YUV422_1P },
- { MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY,
+ { V4L2_MBUS_FMT_UYVY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CBYCRY,
FLITE_REG_CIGCTRL_YUV422_1P },
- { MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY,
+ { V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY,
FLITE_REG_CIGCTRL_YUV422_1P },
- { MEDIA_BUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 },
- { MEDIA_BUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 },
- { MEDIA_BUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 },
- { MEDIA_BUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) },
+ { V4L2_MBUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 },
+ { V4L2_MBUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 },
+ { V4L2_MBUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 },
+ { V4L2_MBUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) },
};
/* Set camera input pixel format and resolution */
void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f)
{
- u32 pixelcode = f->fmt->mbus_code;
+ enum v4l2_mbus_pixelcode pixelcode = f->fmt->mbus_code;
int i = ARRAY_SIZE(src_pixfmt_map);
u32 cfg;
@@ -232,10 +232,10 @@
static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f)
{
static const u32 pixcode[4][2] = {
- { MEDIA_BUS_FMT_YUYV8_2X8, FLITE_REG_CIODMAFMT_YCBYCR },
- { MEDIA_BUS_FMT_YVYU8_2X8, FLITE_REG_CIODMAFMT_YCRYCB },
- { MEDIA_BUS_FMT_UYVY8_2X8, FLITE_REG_CIODMAFMT_CBYCRY },
- { MEDIA_BUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY },
+ { V4L2_MBUS_FMT_YUYV8_2X8, FLITE_REG_CIODMAFMT_YCBYCR },
+ { V4L2_MBUS_FMT_YVYU8_2X8, FLITE_REG_CIODMAFMT_YCRYCB },
+ { V4L2_MBUS_FMT_UYVY8_2X8, FLITE_REG_CIODMAFMT_CBYCRY },
+ { V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY },
};
u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT);
int i = ARRAY_SIZE(pixcode);
diff --git a/drivers/media/platform/exynos4-is/fimc-lite.c b/drivers/media/platform/exynos4-is/fimc-lite.c
index 2510f18..a97d235 100644
--- a/drivers/media/platform/exynos4-is/fimc-lite.c
+++ b/drivers/media/platform/exynos4-is/fimc-lite.c
@@ -48,7 +48,7 @@
.depth = { 16 },
.color = FIMC_FMT_YCBYCR422,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.flags = FMT_FLAGS_YUV,
}, {
.name = "YUV 4:2:2 packed, CbYCrY",
@@ -57,7 +57,7 @@
.depth = { 16 },
.color = FIMC_FMT_CBYCRY422,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
.flags = FMT_FLAGS_YUV,
}, {
.name = "YUV 4:2:2 packed, CrYCbY",
@@ -66,7 +66,7 @@
.depth = { 16 },
.color = FIMC_FMT_CRYCBY422,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_VYUY8_2X8,
.flags = FMT_FLAGS_YUV,
}, {
.name = "YUV 4:2:2 packed, YCrYCb",
@@ -75,7 +75,7 @@
.depth = { 16 },
.color = FIMC_FMT_YCRYCB422,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YVYU8_2X8,
.flags = FMT_FLAGS_YUV,
}, {
.name = "RAW8 (GRBG)",
@@ -84,7 +84,7 @@
.depth = { 8 },
.color = FIMC_FMT_RAW8,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .mbus_code = V4L2_MBUS_FMT_SGRBG8_1X8,
.flags = FMT_FLAGS_RAW_BAYER,
}, {
.name = "RAW10 (GRBG)",
@@ -93,7 +93,7 @@
.depth = { 16 },
.color = FIMC_FMT_RAW10,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .mbus_code = V4L2_MBUS_FMT_SGRBG10_1X10,
.flags = FMT_FLAGS_RAW_BAYER,
}, {
.name = "RAW12 (GRBG)",
@@ -102,7 +102,7 @@
.depth = { 16 },
.color = FIMC_FMT_RAW12,
.memplanes = 1,
- .mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
+ .mbus_code = V4L2_MBUS_FMT_SGRBG12_1X12,
.flags = FMT_FLAGS_RAW_BAYER,
},
};
@@ -1588,7 +1588,7 @@
return ret;
}
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
static int fimc_lite_runtime_resume(struct device *dev)
{
struct fimc_lite *fimc = dev_get_drvdata(dev);
@@ -1720,6 +1720,7 @@
.driver = {
.of_match_table = flite_of_match,
.name = FIMC_LITE_DRV_NAME,
+ .owner = THIS_MODULE,
.pm = &fimc_lite_pm_ops,
}
};
diff --git a/drivers/media/platform/exynos4-is/fimc-m2m.c b/drivers/media/platform/exynos4-is/fimc-m2m.c
index f3ed10b..0ad1b6f 100644
--- a/drivers/media/platform/exynos4-is/fimc-m2m.c
+++ b/drivers/media/platform/exynos4-is/fimc-m2m.c
@@ -538,9 +538,7 @@
.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
.vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
-#endif
.vidioc_streamon = v4l2_m2m_ioctl_streamon,
.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
.vidioc_g_crop = fimc_m2m_g_crop,
diff --git a/drivers/media/platform/exynos4-is/fimc-reg.c b/drivers/media/platform/exynos4-is/fimc-reg.c
index df0cbcb..2d77fd8 100644
--- a/drivers/media/platform/exynos4-is/fimc-reg.c
+++ b/drivers/media/platform/exynos4-is/fimc-reg.c
@@ -592,10 +592,10 @@
};
static const struct mbus_pixfmt_desc pix_desc[] = {
- { MEDIA_BUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 },
- { MEDIA_BUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 },
- { MEDIA_BUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 },
- { MEDIA_BUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 },
+ { V4L2_MBUS_FMT_YUYV8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCBYCR, 8 },
+ { V4L2_MBUS_FMT_YVYU8_2X8, FIMC_REG_CISRCFMT_ORDER422_YCRYCB, 8 },
+ { V4L2_MBUS_FMT_VYUY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CRYCBY, 8 },
+ { V4L2_MBUS_FMT_UYVY8_2X8, FIMC_REG_CISRCFMT_ORDER422_CBYCRY, 8 },
};
int fimc_hw_set_camera_source(struct fimc_dev *fimc,
@@ -689,11 +689,11 @@
/* TODO: add remaining supported formats. */
switch (vid_cap->ci_fmt.code) {
- case MEDIA_BUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
break;
- case MEDIA_BUS_FMT_JPEG_1X8:
- case MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8:
+ case V4L2_MBUS_FMT_JPEG_1X8:
+ case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8:
tmp = FIMC_REG_CSIIMGFMT_USER(1);
cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
break;
diff --git a/drivers/media/platform/exynos4-is/media-dev.c b/drivers/media/platform/exynos4-is/media-dev.c
index f315ef9..54c49d5 100644
--- a/drivers/media/platform/exynos4-is/media-dev.c
+++ b/drivers/media/platform/exynos4-is/media-dev.c
@@ -1469,6 +1469,7 @@
.driver = {
.of_match_table = of_match_ptr(fimc_md_of_match),
.name = "s5p-fimc-md",
+ .owner = THIS_MODULE,
}
};
diff --git a/drivers/media/platform/exynos4-is/mipi-csis.c b/drivers/media/platform/exynos4-is/mipi-csis.c
index 2504aa8..db6fd14 100644
--- a/drivers/media/platform/exynos4-is/mipi-csis.c
+++ b/drivers/media/platform/exynos4-is/mipi-csis.c
@@ -238,34 +238,34 @@
*/
struct csis_pix_format {
unsigned int pix_width_alignment;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
u32 fmt_reg;
u8 data_alignment;
};
static const struct csis_pix_format s5pcsis_formats[] = {
{
- .code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .code = V4L2_MBUS_FMT_VYUY8_2X8,
.fmt_reg = S5PCSIS_CFG_FMT_YCBCR422_8BIT,
.data_alignment = 32,
}, {
- .code = MEDIA_BUS_FMT_JPEG_1X8,
+ .code = V4L2_MBUS_FMT_JPEG_1X8,
.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
.data_alignment = 32,
}, {
- .code = MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8,
+ .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
.fmt_reg = S5PCSIS_CFG_FMT_USER(1),
.data_alignment = 32,
}, {
- .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .code = V4L2_MBUS_FMT_SGRBG8_1X8,
.fmt_reg = S5PCSIS_CFG_FMT_RAW8,
.data_alignment = 24,
}, {
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .code = V4L2_MBUS_FMT_SGRBG10_1X10,
.fmt_reg = S5PCSIS_CFG_FMT_RAW10,
.data_alignment = 24,
}, {
- .code = MEDIA_BUS_FMT_SGRBG12_1X12,
+ .code = V4L2_MBUS_FMT_SGRBG12_1X12,
.fmt_reg = S5PCSIS_CFG_FMT_RAW12,
.data_alignment = 24,
}
@@ -978,7 +978,7 @@
}
#endif
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
static int s5pcsis_runtime_suspend(struct device *dev)
{
return s5pcsis_pm_suspend(dev, true);
@@ -1041,6 +1041,7 @@
.driver = {
.of_match_table = s5pcsis_of_match,
.name = CSIS_DRIVER_NAME,
+ .owner = THIS_MODULE,
.pm = &s5pcsis_pm_ops,
},
};
diff --git a/drivers/media/platform/fsl-viu.c b/drivers/media/platform/fsl-viu.c
index bbf4281..d5dc198 100644
--- a/drivers/media/platform/fsl-viu.c
+++ b/drivers/media/platform/fsl-viu.c
@@ -604,11 +604,10 @@
{
strcpy(cap->driver, "viu");
strcpy(cap->card, "viu");
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_STREAMING |
V4L2_CAP_VIDEO_OVERLAY |
V4L2_CAP_READWRITE;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
@@ -1681,6 +1680,7 @@
#endif
.driver = {
.name = DRV_NAME,
+ .owner = THIS_MODULE,
.of_match_table = mpc512x_viu_of_match,
},
};
diff --git a/drivers/media/platform/indycam.c b/drivers/media/platform/indycam.c
new file mode 100644
index 0000000..f1d192b
--- /dev/null
+++ b/drivers/media/platform/indycam.c
@@ -0,0 +1,378 @@
+/*
+ * indycam.c - Silicon Graphics IndyCam digital camera driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+/* IndyCam decodes stream of photons into digital image representation ;-) */
+#include <linux/videodev2.h>
+#include <linux/i2c.h>
+#include <media/v4l2-device.h>
+
+#include "indycam.h"
+
+#define INDYCAM_MODULE_VERSION "0.0.5"
+
+MODULE_DESCRIPTION("SGI IndyCam driver");
+MODULE_VERSION(INDYCAM_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+
+// #define INDYCAM_DEBUG
+
+#ifdef INDYCAM_DEBUG
+#define dprintk(x...) printk("IndyCam: " x);
+#define indycam_regdump(client) indycam_regdump_debug(client)
+#else
+#define dprintk(x...)
+#define indycam_regdump(client)
+#endif
+
+struct indycam {
+ struct v4l2_subdev sd;
+ u8 version;
+};
+
+static inline struct indycam *to_indycam(struct v4l2_subdev *sd)
+{
+ return container_of(sd, struct indycam, sd);
+}
+
+static const u8 initseq[] = {
+ INDYCAM_CONTROL_AGCENA, /* INDYCAM_CONTROL */
+ INDYCAM_SHUTTER_60, /* INDYCAM_SHUTTER */
+ INDYCAM_GAIN_DEFAULT, /* INDYCAM_GAIN */
+ 0x00, /* INDYCAM_BRIGHTNESS (read-only) */
+ INDYCAM_RED_BALANCE_DEFAULT, /* INDYCAM_RED_BALANCE */
+ INDYCAM_BLUE_BALANCE_DEFAULT, /* INDYCAM_BLUE_BALANCE */
+ INDYCAM_RED_SATURATION_DEFAULT, /* INDYCAM_RED_SATURATION */
+ INDYCAM_BLUE_SATURATION_DEFAULT,/* INDYCAM_BLUE_SATURATION */
+};
+
+/* IndyCam register handling */
+
+static int indycam_read_reg(struct v4l2_subdev *sd, u8 reg, u8 *value)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int ret;
+
+ if (reg == INDYCAM_REG_RESET) {
+ dprintk("indycam_read_reg(): "
+ "skipping write-only register %d\n", reg);
+ *value = 0;
+ return 0;
+ }
+
+ ret = i2c_smbus_read_byte_data(client, reg);
+
+ if (ret < 0) {
+ printk(KERN_ERR "IndyCam: indycam_read_reg(): read failed, "
+ "register = 0x%02x\n", reg);
+ return ret;
+ }
+
+ *value = (u8)ret;
+
+ return 0;
+}
+
+static int indycam_write_reg(struct v4l2_subdev *sd, u8 reg, u8 value)
+{
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
+ int err;
+
+ if (reg == INDYCAM_REG_BRIGHTNESS || reg == INDYCAM_REG_VERSION) {
+ dprintk("indycam_write_reg(): "
+ "skipping read-only register %d\n", reg);
+ return 0;
+ }
+
+ dprintk("Writing Reg %d = 0x%02x\n", reg, value);
+ err = i2c_smbus_write_byte_data(client, reg, value);
+
+ if (err) {
+ printk(KERN_ERR "IndyCam: indycam_write_reg(): write failed, "
+ "register = 0x%02x, value = 0x%02x\n", reg, value);
+ }
+ return err;
+}
+
+static int indycam_write_block(struct v4l2_subdev *sd, u8 reg,
+ u8 length, u8 *data)
+{
+ int i, err;
+
+ for (i = 0; i < length; i++) {
+ err = indycam_write_reg(sd, reg + i, data[i]);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/* Helper functions */
+
+#ifdef INDYCAM_DEBUG
+static void indycam_regdump_debug(struct v4l2_subdev *sd)
+{
+ int i;
+ u8 val;
+
+ for (i = 0; i < 9; i++) {
+ indycam_read_reg(sd, i, &val);
+ dprintk("Reg %d = 0x%02x\n", i, val);
+ }
+}
+#endif
+
+static int indycam_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct indycam *camera = to_indycam(sd);
+ u8 reg;
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUTOGAIN:
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, ®);
+ if (ret)
+ return -EIO;
+ if (ctrl->id == V4L2_CID_AUTOGAIN)
+ ctrl->value = (reg & INDYCAM_CONTROL_AGCENA)
+ ? 1 : 0;
+ else
+ ctrl->value = (reg & INDYCAM_CONTROL_AWBCTL)
+ ? 1 : 0;
+ break;
+ case V4L2_CID_EXPOSURE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_SHUTTER, ®);
+ if (ret)
+ return -EIO;
+ ctrl->value = ((s32)reg == 0x00) ? 0xff : ((s32)reg - 1);
+ break;
+ case V4L2_CID_GAIN:
+ ret = indycam_read_reg(sd, INDYCAM_REG_GAIN, ®);
+ if (ret)
+ return -EIO;
+ ctrl->value = (s32)reg;
+ break;
+ case V4L2_CID_RED_BALANCE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_RED_BALANCE, ®);
+ if (ret)
+ return -EIO;
+ ctrl->value = (s32)reg;
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_BLUE_BALANCE, ®);
+ if (ret)
+ return -EIO;
+ ctrl->value = (s32)reg;
+ break;
+ case INDYCAM_CONTROL_RED_SATURATION:
+ ret = indycam_read_reg(sd,
+ INDYCAM_REG_RED_SATURATION, ®);
+ if (ret)
+ return -EIO;
+ ctrl->value = (s32)reg;
+ break;
+ case INDYCAM_CONTROL_BLUE_SATURATION:
+ ret = indycam_read_reg(sd,
+ INDYCAM_REG_BLUE_SATURATION, ®);
+ if (ret)
+ return -EIO;
+ ctrl->value = (s32)reg;
+ break;
+ case V4L2_CID_GAMMA:
+ if (camera->version == CAMERA_VERSION_MOOSE) {
+ ret = indycam_read_reg(sd,
+ INDYCAM_REG_GAMMA, ®);
+ if (ret)
+ return -EIO;
+ ctrl->value = (s32)reg;
+ } else {
+ ctrl->value = INDYCAM_GAMMA_DEFAULT;
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int indycam_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+ struct indycam *camera = to_indycam(sd);
+ u8 reg;
+ int ret = 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_AUTOGAIN:
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ ret = indycam_read_reg(sd, INDYCAM_REG_CONTROL, ®);
+ if (ret)
+ break;
+
+ if (ctrl->id == V4L2_CID_AUTOGAIN) {
+ if (ctrl->value)
+ reg |= INDYCAM_CONTROL_AGCENA;
+ else
+ reg &= ~INDYCAM_CONTROL_AGCENA;
+ } else {
+ if (ctrl->value)
+ reg |= INDYCAM_CONTROL_AWBCTL;
+ else
+ reg &= ~INDYCAM_CONTROL_AWBCTL;
+ }
+
+ ret = indycam_write_reg(sd, INDYCAM_REG_CONTROL, reg);
+ break;
+ case V4L2_CID_EXPOSURE:
+ reg = (ctrl->value == 0xff) ? 0x00 : (ctrl->value + 1);
+ ret = indycam_write_reg(sd, INDYCAM_REG_SHUTTER, reg);
+ break;
+ case V4L2_CID_GAIN:
+ ret = indycam_write_reg(sd, INDYCAM_REG_GAIN, ctrl->value);
+ break;
+ case V4L2_CID_RED_BALANCE:
+ ret = indycam_write_reg(sd, INDYCAM_REG_RED_BALANCE,
+ ctrl->value);
+ break;
+ case V4L2_CID_BLUE_BALANCE:
+ ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_BALANCE,
+ ctrl->value);
+ break;
+ case INDYCAM_CONTROL_RED_SATURATION:
+ ret = indycam_write_reg(sd, INDYCAM_REG_RED_SATURATION,
+ ctrl->value);
+ break;
+ case INDYCAM_CONTROL_BLUE_SATURATION:
+ ret = indycam_write_reg(sd, INDYCAM_REG_BLUE_SATURATION,
+ ctrl->value);
+ break;
+ case V4L2_CID_GAMMA:
+ if (camera->version == CAMERA_VERSION_MOOSE) {
+ ret = indycam_write_reg(sd, INDYCAM_REG_GAMMA,
+ ctrl->value);
+ }
+ break;
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+/* I2C-interface */
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_subdev_core_ops indycam_core_ops = {
+ .g_ctrl = indycam_g_ctrl,
+ .s_ctrl = indycam_s_ctrl,
+};
+
+static const struct v4l2_subdev_ops indycam_ops = {
+ .core = &indycam_core_ops,
+};
+
+static int indycam_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ int err = 0;
+ struct indycam *camera;
+ struct v4l2_subdev *sd;
+
+ v4l_info(client, "chip found @ 0x%x (%s)\n",
+ client->addr << 1, client->adapter->name);
+
+ camera = kzalloc(sizeof(struct indycam), GFP_KERNEL);
+ if (!camera)
+ return -ENOMEM;
+
+ sd = &camera->sd;
+ v4l2_i2c_subdev_init(sd, client, &indycam_ops);
+
+ camera->version = i2c_smbus_read_byte_data(client,
+ INDYCAM_REG_VERSION);
+ if (camera->version != CAMERA_VERSION_INDY &&
+ camera->version != CAMERA_VERSION_MOOSE) {
+ kfree(camera);
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "IndyCam v%d.%d detected\n",
+ INDYCAM_VERSION_MAJOR(camera->version),
+ INDYCAM_VERSION_MINOR(camera->version));
+
+ indycam_regdump(sd);
+
+ // initialize
+ err = indycam_write_block(sd, 0, sizeof(initseq), (u8 *)&initseq);
+ if (err) {
+ printk(KERN_ERR "IndyCam initialization failed\n");
+ kfree(camera);
+ return -EIO;
+ }
+
+ indycam_regdump(sd);
+
+ // white balance
+ err = indycam_write_reg(sd, INDYCAM_REG_CONTROL,
+ INDYCAM_CONTROL_AGCENA | INDYCAM_CONTROL_AWBCTL);
+ if (err) {
+ printk(KERN_ERR "IndyCam: White balancing camera failed\n");
+ kfree(camera);
+ return -EIO;
+ }
+
+ indycam_regdump(sd);
+
+ printk(KERN_INFO "IndyCam initialized\n");
+
+ return 0;
+}
+
+static int indycam_remove(struct i2c_client *client)
+{
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
+
+ v4l2_device_unregister_subdev(sd);
+ kfree(to_indycam(sd));
+ return 0;
+}
+
+static const struct i2c_device_id indycam_id[] = {
+ { "indycam", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, indycam_id);
+
+static struct i2c_driver indycam_driver = {
+ .driver = {
+ .owner = THIS_MODULE,
+ .name = "indycam",
+ },
+ .probe = indycam_probe,
+ .remove = indycam_remove,
+ .id_table = indycam_id,
+};
+
+module_i2c_driver(indycam_driver);
diff --git a/drivers/media/platform/indycam.h b/drivers/media/platform/indycam.h
new file mode 100644
index 0000000..881f21c
--- /dev/null
+++ b/drivers/media/platform/indycam.h
@@ -0,0 +1,93 @@
+/*
+ * indycam.h - Silicon Graphics IndyCam digital camera driver
+ *
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * 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 _INDYCAM_H_
+#define _INDYCAM_H_
+
+/* I2C address for the Guinness Camera */
+#define INDYCAM_ADDR 0x56
+
+/* Camera version */
+#define CAMERA_VERSION_INDY 0x10 /* v1.0 */
+#define CAMERA_VERSION_MOOSE 0x12 /* v1.2 */
+#define INDYCAM_VERSION_MAJOR(x) (((x) & 0xf0) >> 4)
+#define INDYCAM_VERSION_MINOR(x) ((x) & 0x0f)
+
+/* Register bus addresses */
+#define INDYCAM_REG_CONTROL 0x00
+#define INDYCAM_REG_SHUTTER 0x01
+#define INDYCAM_REG_GAIN 0x02
+#define INDYCAM_REG_BRIGHTNESS 0x03 /* read-only */
+#define INDYCAM_REG_RED_BALANCE 0x04
+#define INDYCAM_REG_BLUE_BALANCE 0x05
+#define INDYCAM_REG_RED_SATURATION 0x06
+#define INDYCAM_REG_BLUE_SATURATION 0x07
+#define INDYCAM_REG_GAMMA 0x08
+#define INDYCAM_REG_VERSION 0x0e /* read-only */
+#define INDYCAM_REG_RESET 0x0f /* write-only */
+
+#define INDYCAM_REG_LED 0x46
+#define INDYCAM_REG_ORIENTATION 0x47
+#define INDYCAM_REG_BUTTON 0x48
+
+/* Field definitions of registers */
+#define INDYCAM_CONTROL_AGCENA (1<<0) /* automatic gain control */
+#define INDYCAM_CONTROL_AWBCTL (1<<1) /* automatic white balance */
+ /* 2-3 are reserved */
+#define INDYCAM_CONTROL_EVNFLD (1<<4) /* read-only */
+
+#define INDYCAM_SHUTTER_10000 0x02 /* 1/10000 second */
+#define INDYCAM_SHUTTER_4000 0x04 /* 1/4000 second */
+#define INDYCAM_SHUTTER_2000 0x08 /* 1/2000 second */
+#define INDYCAM_SHUTTER_1000 0x10 /* 1/1000 second */
+#define INDYCAM_SHUTTER_500 0x20 /* 1/500 second */
+#define INDYCAM_SHUTTER_250 0x3f /* 1/250 second */
+#define INDYCAM_SHUTTER_125 0x7e /* 1/125 second */
+#define INDYCAM_SHUTTER_100 0x9e /* 1/100 second */
+#define INDYCAM_SHUTTER_60 0x00 /* 1/60 second */
+
+#define INDYCAM_LED_ACTIVE 0x10
+#define INDYCAM_LED_INACTIVE 0x30
+#define INDYCAM_ORIENTATION_BOTTOM_TO_TOP 0x40
+#define INDYCAM_BUTTON_RELEASED 0x10
+
+/* Values for controls */
+#define INDYCAM_SHUTTER_MIN 0x00
+#define INDYCAM_SHUTTER_MAX 0xff
+#define INDYCAM_GAIN_MIN 0x00
+#define INDYCAM_GAIN_MAX 0xff
+#define INDYCAM_RED_BALANCE_MIN 0x00
+#define INDYCAM_RED_BALANCE_MAX 0xff
+#define INDYCAM_BLUE_BALANCE_MIN 0x00
+#define INDYCAM_BLUE_BALANCE_MAX 0xff
+#define INDYCAM_RED_SATURATION_MIN 0x00
+#define INDYCAM_RED_SATURATION_MAX 0xff
+#define INDYCAM_BLUE_SATURATION_MIN 0x00
+#define INDYCAM_BLUE_SATURATION_MAX 0xff
+#define INDYCAM_GAMMA_MIN 0x00
+#define INDYCAM_GAMMA_MAX 0xff
+
+#define INDYCAM_AGC_DEFAULT 1
+#define INDYCAM_AWB_DEFAULT 0
+#define INDYCAM_SHUTTER_DEFAULT 0xff
+#define INDYCAM_GAIN_DEFAULT 0x80
+#define INDYCAM_RED_BALANCE_DEFAULT 0x18
+#define INDYCAM_BLUE_BALANCE_DEFAULT 0xa4
+#define INDYCAM_RED_SATURATION_DEFAULT 0x80
+#define INDYCAM_BLUE_SATURATION_DEFAULT 0xc0
+#define INDYCAM_GAMMA_DEFAULT 0x80
+
+/* Driver interface definitions */
+
+#define INDYCAM_CONTROL_RED_SATURATION (V4L2_CID_PRIVATE_BASE + 0)
+#define INDYCAM_CONTROL_BLUE_SATURATION (V4L2_CID_PRIVATE_BASE + 1)
+
+#endif
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index b70c1ae..d36c507 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -1101,6 +1101,7 @@
.remove = deinterlace_remove,
.driver = {
.name = MEM2MEM_NAME,
+ .owner = THIS_MODULE,
},
};
module_platform_driver(deinterlace_pdrv);
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.c b/drivers/media/platform/marvell-ccic/mcam-core.c
index 137ffa2..6895e12 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.c
+++ b/drivers/media/platform/marvell-ccic/mcam-core.c
@@ -106,61 +106,61 @@
__u32 pixelformat;
int bpp; /* Bytes per pixel */
bool planar;
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
} mcam_formats[] = {
{
.desc = "YUYV 4:2:2",
.pixelformat = V4L2_PIX_FMT_YUYV,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.bpp = 2,
.planar = false,
},
{
.desc = "UYVY 4:2:2",
.pixelformat = V4L2_PIX_FMT_UYVY,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.bpp = 2,
.planar = false,
},
{
.desc = "YUV 4:2:2 PLANAR",
.pixelformat = V4L2_PIX_FMT_YUV422P,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.bpp = 2,
.planar = true,
},
{
.desc = "YUV 4:2:0 PLANAR",
.pixelformat = V4L2_PIX_FMT_YUV420,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.bpp = 2,
.planar = true,
},
{
.desc = "YVU 4:2:0 PLANAR",
.pixelformat = V4L2_PIX_FMT_YVU420,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.bpp = 2,
.planar = true,
},
{
.desc = "RGB 444",
.pixelformat = V4L2_PIX_FMT_RGB444,
- .mbus_code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE,
+ .mbus_code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE,
.bpp = 2,
.planar = false,
},
{
.desc = "RGB 565",
.pixelformat = V4L2_PIX_FMT_RGB565,
- .mbus_code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+ .mbus_code = V4L2_MBUS_FMT_RGB565_2X8_LE,
.bpp = 2,
.planar = false,
},
{
.desc = "Raw RGB Bayer",
.pixelformat = V4L2_PIX_FMT_SBGGR8,
- .mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .mbus_code = V4L2_MBUS_FMT_SBGGR8_1X8,
.bpp = 1,
.planar = false,
},
@@ -190,7 +190,8 @@
.sizeimage = VGA_WIDTH*VGA_HEIGHT*2,
};
-static const u32 mcam_def_mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
+static const enum v4l2_mbus_pixelcode mcam_def_mbus_code =
+ V4L2_MBUS_FMT_YUYV8_2X8;
/*
@@ -1079,8 +1080,6 @@
*nbufs = minbufs;
if (cam->buffer_mode == B_DMA_contig)
alloc_ctxs[0] = cam->vb_alloc_ctx;
- else if (cam->buffer_mode == B_DMA_sg)
- alloc_ctxs[0] = cam->vb_alloc_ctx_sg;
return 0;
}
@@ -1102,6 +1101,26 @@
mcam_read_setup(cam);
}
+
+/*
+ * vb2 uses these to release the mutex when waiting in dqbuf. I'm
+ * not actually sure we need to do this (I'm not sure that vb2_dqbuf() needs
+ * to be called with the mutex held), but better safe than sorry.
+ */
+static void mcam_vb_wait_prepare(struct vb2_queue *vq)
+{
+ struct mcam_camera *cam = vb2_get_drv_priv(vq);
+
+ mutex_unlock(&cam->s_mutex);
+}
+
+static void mcam_vb_wait_finish(struct vb2_queue *vq)
+{
+ struct mcam_camera *cam = vb2_get_drv_priv(vq);
+
+ mutex_lock(&cam->s_mutex);
+}
+
/*
* These need to be called with the mutex held from vb2
*/
@@ -1171,8 +1190,8 @@
.buf_queue = mcam_vb_buf_queue,
.start_streaming = mcam_vb_start_streaming,
.stop_streaming = mcam_vb_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .wait_prepare = mcam_vb_wait_prepare,
+ .wait_finish = mcam_vb_wait_finish,
};
@@ -1200,12 +1219,17 @@
static int mcam_vb_sg_buf_prepare(struct vb2_buffer *vb)
{
struct mcam_vb_buffer *mvb = vb_to_mvb(vb);
+ struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
struct mcam_dma_desc *desc = mvb->dma_desc;
struct scatterlist *sg;
int i;
- for_each_sg(sg_table->sgl, sg, sg_table->nents, i) {
+ mvb->dma_desc_nent = dma_map_sg(cam->dev, sg_table->sgl,
+ sg_table->nents, DMA_FROM_DEVICE);
+ if (mvb->dma_desc_nent <= 0)
+ return -EIO; /* Not sure what's right here */
+ for_each_sg(sg_table->sgl, sg, mvb->dma_desc_nent, i) {
desc->dma_addr = sg_dma_address(sg);
desc->segment_len = sg_dma_len(sg);
desc++;
@@ -1213,6 +1237,16 @@
return 0;
}
+static void mcam_vb_sg_buf_finish(struct vb2_buffer *vb)
+{
+ struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
+ struct sg_table *sg_table = vb2_dma_sg_plane_desc(vb, 0);
+
+ if (sg_table)
+ dma_unmap_sg(cam->dev, sg_table->sgl,
+ sg_table->nents, DMA_FROM_DEVICE);
+}
+
static void mcam_vb_sg_buf_cleanup(struct vb2_buffer *vb)
{
struct mcam_camera *cam = vb2_get_drv_priv(vb->vb2_queue);
@@ -1229,11 +1263,12 @@
.buf_init = mcam_vb_sg_buf_init,
.buf_prepare = mcam_vb_sg_buf_prepare,
.buf_queue = mcam_vb_buf_queue,
+ .buf_finish = mcam_vb_sg_buf_finish,
.buf_cleanup = mcam_vb_sg_buf_cleanup,
.start_streaming = mcam_vb_start_streaming,
.stop_streaming = mcam_vb_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .wait_prepare = mcam_vb_wait_prepare,
+ .wait_finish = mcam_vb_wait_finish,
};
#endif /* MCAM_MODE_DMA_SG */
@@ -1245,7 +1280,6 @@
memset(vq, 0, sizeof(*vq));
vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
vq->drv_priv = cam;
- vq->lock = &cam->s_mutex;
INIT_LIST_HEAD(&cam->buffers);
switch (cam->buffer_mode) {
case B_DMA_contig:
@@ -1253,12 +1287,10 @@
vq->ops = &mcam_vb2_ops;
vq->mem_ops = &vb2_dma_contig_memops;
vq->buf_struct_size = sizeof(struct mcam_vb_buffer);
+ cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
vq->io_modes = VB2_MMAP | VB2_USERPTR;
cam->dma_setup = mcam_ctlr_dma_contig;
cam->frame_complete = mcam_dma_contig_done;
- cam->vb_alloc_ctx = vb2_dma_contig_init_ctx(cam->dev);
- if (IS_ERR(cam->vb_alloc_ctx))
- return PTR_ERR(cam->vb_alloc_ctx);
#endif
break;
case B_DMA_sg:
@@ -1269,9 +1301,6 @@
vq->io_modes = VB2_MMAP | VB2_USERPTR;
cam->dma_setup = mcam_ctlr_dma_sg;
cam->frame_complete = mcam_dma_sg_done;
- cam->vb_alloc_ctx_sg = vb2_dma_sg_init_ctx(cam->dev);
- if (IS_ERR(cam->vb_alloc_ctx_sg))
- return PTR_ERR(cam->vb_alloc_ctx_sg);
#endif
break;
case B_vmalloc:
@@ -1297,10 +1326,6 @@
if (cam->buffer_mode == B_DMA_contig)
vb2_dma_contig_cleanup_ctx(cam->vb_alloc_ctx);
#endif
-#ifdef MCAM_MODE_DMA_SG
- if (cam->buffer_mode == B_DMA_sg)
- vb2_dma_sg_cleanup_ctx(cam->vb_alloc_ctx_sg);
-#endif
}
@@ -1389,9 +1414,9 @@
{
strcpy(cap->driver, "marvell_ccic");
strcpy(cap->card, "marvell_ccic");
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+ cap->version = 1;
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
diff --git a/drivers/media/platform/marvell-ccic/mcam-core.h b/drivers/media/platform/marvell-ccic/mcam-core.h
index 6ccfbb6..4dcdb69 100644
--- a/drivers/media/platform/marvell-ccic/mcam-core.h
+++ b/drivers/media/platform/marvell-ccic/mcam-core.h
@@ -176,7 +176,6 @@
/* DMA buffers - DMA modes */
struct mcam_vb_buffer *vb_bufs[MAX_DMA_BUFS];
struct vb2_alloc_ctx *vb_alloc_ctx;
- struct vb2_alloc_ctx *vb_alloc_ctx_sg;
/* Mode-specific ops, set at open time */
void (*dma_setup)(struct mcam_camera *cam);
@@ -184,7 +183,7 @@
/* Current operating parameters */
struct v4l2_pix_format pix_format;
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
/* Locks */
struct mutex s_mutex; /* Access to this structure */
diff --git a/drivers/media/platform/marvell-ccic/mmp-driver.c b/drivers/media/platform/marvell-ccic/mmp-driver.c
index 0ed9b3a..054507f 100644
--- a/drivers/media/platform/marvell-ccic/mmp-driver.c
+++ b/drivers/media/platform/marvell-ccic/mmp-driver.c
@@ -512,6 +512,7 @@
#endif
.driver = {
.name = "mmp-camera",
+ .owner = THIS_MODULE
}
};
diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/mem2mem_testdev.c
similarity index 81%
rename from drivers/media/platform/vim2m.c
rename to drivers/media/platform/mem2mem_testdev.c
index a3b6383..c1b03cf 100644
--- a/drivers/media/platform/vim2m.c
+++ b/drivers/media/platform/mem2mem_testdev.c
@@ -31,11 +31,12 @@
#include <media/v4l2-event.h>
#include <media/videobuf2-vmalloc.h>
+#define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev"
+
MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
MODULE_LICENSE("GPL");
MODULE_VERSION("0.1.1");
-MODULE_ALIAS("mem2mem_testdev");
static unsigned debug;
module_param(debug, uint, 0644);
@@ -51,7 +52,7 @@
#define MEM2MEM_CAPTURE (1 << 0)
#define MEM2MEM_OUTPUT (1 << 1)
-#define MEM2MEM_NAME "vim2m"
+#define MEM2MEM_NAME "m2m-testdev"
/* Per queue */
#define MEM2MEM_DEF_NUM_BUFS VIDEO_MAX_FRAME
@@ -71,15 +72,15 @@
v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
-static void vim2m_dev_release(struct device *dev)
+static void m2mtest_dev_release(struct device *dev)
{}
-static struct platform_device vim2m_pdev = {
+static struct platform_device m2mtest_pdev = {
.name = MEM2MEM_NAME,
- .dev.release = vim2m_dev_release,
+ .dev.release = m2mtest_dev_release,
};
-struct vim2m_fmt {
+struct m2mtest_fmt {
char *name;
u32 fourcc;
int depth;
@@ -87,7 +88,7 @@
u32 types;
};
-static struct vim2m_fmt formats[] = {
+static struct m2mtest_fmt formats[] = {
{
.name = "RGB565 (BE)",
.fourcc = V4L2_PIX_FMT_RGB565X, /* rrrrrggg gggbbbbb */
@@ -107,12 +108,12 @@
#define NUM_FORMATS ARRAY_SIZE(formats)
/* Per-queue, driver-specific private data */
-struct vim2m_q_data {
+struct m2mtest_q_data {
unsigned int width;
unsigned int height;
unsigned int sizeimage;
unsigned int sequence;
- struct vim2m_fmt *fmt;
+ struct m2mtest_fmt *fmt;
};
enum {
@@ -123,9 +124,9 @@
#define V4L2_CID_TRANS_TIME_MSEC (V4L2_CID_USER_BASE + 0x1000)
#define V4L2_CID_TRANS_NUM_BUFS (V4L2_CID_USER_BASE + 0x1001)
-static struct vim2m_fmt *find_format(struct v4l2_format *f)
+static struct m2mtest_fmt *find_format(struct v4l2_format *f)
{
- struct vim2m_fmt *fmt;
+ struct m2mtest_fmt *fmt;
unsigned int k;
for (k = 0; k < NUM_FORMATS; k++) {
@@ -140,7 +141,7 @@
return &formats[k];
}
-struct vim2m_dev {
+struct m2mtest_dev {
struct v4l2_device v4l2_dev;
struct video_device *vfd;
@@ -153,9 +154,9 @@
struct v4l2_m2m_dev *m2m_dev;
};
-struct vim2m_ctx {
+struct m2mtest_ctx {
struct v4l2_fh fh;
- struct vim2m_dev *dev;
+ struct m2mtest_dev *dev;
struct v4l2_ctrl_handler hdl;
@@ -176,15 +177,15 @@
enum v4l2_colorspace colorspace;
/* Source and destination queue data */
- struct vim2m_q_data q_data[2];
+ struct m2mtest_q_data q_data[2];
};
-static inline struct vim2m_ctx *file2ctx(struct file *file)
+static inline struct m2mtest_ctx *file2ctx(struct file *file)
{
- return container_of(file->private_data, struct vim2m_ctx, fh);
+ return container_of(file->private_data, struct m2mtest_ctx, fh);
}
-static struct vim2m_q_data *get_q_data(struct vim2m_ctx *ctx,
+static struct m2mtest_q_data *get_q_data(struct m2mtest_ctx *ctx,
enum v4l2_buf_type type)
{
switch (type) {
@@ -199,12 +200,12 @@
}
-static int device_process(struct vim2m_ctx *ctx,
+static int device_process(struct m2mtest_ctx *ctx,
struct vb2_buffer *in_vb,
struct vb2_buffer *out_vb)
{
- struct vim2m_dev *dev = ctx->dev;
- struct vim2m_q_data *q_data;
+ struct m2mtest_dev *dev = ctx->dev;
+ struct m2mtest_q_data *q_data;
u8 *p_in, *p_out;
int x, y, t, w;
int tile_w, bytes_left;
@@ -333,7 +334,7 @@
return 0;
}
-static void schedule_irq(struct vim2m_dev *dev, int msec_timeout)
+static void schedule_irq(struct m2mtest_dev *dev, int msec_timeout)
{
dprintk(dev, "Scheduling a simulated irq\n");
mod_timer(&dev->timer, jiffies + msecs_to_jiffies(msec_timeout));
@@ -348,7 +349,7 @@
*/
static int job_ready(void *priv)
{
- struct vim2m_ctx *ctx = priv;
+ struct m2mtest_ctx *ctx = priv;
if (v4l2_m2m_num_src_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen
|| v4l2_m2m_num_dst_bufs_ready(ctx->fh.m2m_ctx) < ctx->translen) {
@@ -361,7 +362,7 @@
static void job_abort(void *priv)
{
- struct vim2m_ctx *ctx = priv;
+ struct m2mtest_ctx *ctx = priv;
/* Will cancel the transaction in the next interrupt handler */
ctx->aborting = 1;
@@ -375,8 +376,8 @@
*/
static void device_run(void *priv)
{
- struct vim2m_ctx *ctx = priv;
- struct vim2m_dev *dev = ctx->dev;
+ struct m2mtest_ctx *ctx = priv;
+ struct m2mtest_dev *dev = ctx->dev;
struct vb2_buffer *src_buf, *dst_buf;
src_buf = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
@@ -390,12 +391,12 @@
static void device_isr(unsigned long priv)
{
- struct vim2m_dev *vim2m_dev = (struct vim2m_dev *)priv;
- struct vim2m_ctx *curr_ctx;
+ struct m2mtest_dev *m2mtest_dev = (struct m2mtest_dev *)priv;
+ struct m2mtest_ctx *curr_ctx;
struct vb2_buffer *src_vb, *dst_vb;
unsigned long flags;
- curr_ctx = v4l2_m2m_get_curr_priv(vim2m_dev->m2m_dev);
+ curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev);
if (NULL == curr_ctx) {
pr_err("Instance released before the end of transaction\n");
@@ -407,16 +408,16 @@
curr_ctx->num_processed++;
- spin_lock_irqsave(&vim2m_dev->irqlock, flags);
+ spin_lock_irqsave(&m2mtest_dev->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(&vim2m_dev->irqlock, flags);
+ spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
if (curr_ctx->num_processed == curr_ctx->translen
|| curr_ctx->aborting) {
dprintk(curr_ctx->dev, "Finishing transaction\n");
curr_ctx->num_processed = 0;
- v4l2_m2m_job_finish(vim2m_dev->m2m_dev, curr_ctx->fh.m2m_ctx);
+ v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->fh.m2m_ctx);
} else {
device_run(curr_ctx);
}
@@ -440,7 +441,7 @@
static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
{
int i, num;
- struct vim2m_fmt *fmt;
+ struct m2mtest_fmt *fmt;
num = 0;
@@ -479,10 +480,10 @@
return enum_fmt(f, MEM2MEM_OUTPUT);
}
-static int vidioc_g_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
+static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
{
struct vb2_queue *vq;
- struct vim2m_q_data *q_data;
+ struct m2mtest_q_data *q_data;
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
if (!vq)
@@ -513,7 +514,7 @@
return vidioc_g_fmt(file2ctx(file), f);
}
-static int vidioc_try_fmt(struct v4l2_format *f, struct vim2m_fmt *fmt)
+static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt)
{
/* V4L2 specification suggests the driver corrects the format struct
* if any of the dimensions is unsupported */
@@ -538,8 +539,8 @@
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct vim2m_fmt *fmt;
- struct vim2m_ctx *ctx = file2ctx(file);
+ struct m2mtest_fmt *fmt;
+ struct m2mtest_ctx *ctx = file2ctx(file);
fmt = find_format(f);
if (!fmt) {
@@ -560,8 +561,8 @@
static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct vim2m_fmt *fmt;
- struct vim2m_ctx *ctx = file2ctx(file);
+ struct m2mtest_fmt *fmt;
+ struct m2mtest_ctx *ctx = file2ctx(file);
fmt = find_format(f);
if (!fmt) {
@@ -580,9 +581,9 @@
return vidioc_try_fmt(f, fmt);
}
-static int vidioc_s_fmt(struct vim2m_ctx *ctx, struct v4l2_format *f)
+static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
{
- struct vim2m_q_data *q_data;
+ struct m2mtest_q_data *q_data;
struct vb2_queue *vq;
vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, f->type);
@@ -626,7 +627,7 @@
static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
struct v4l2_format *f)
{
- struct vim2m_ctx *ctx = file2ctx(file);
+ struct m2mtest_ctx *ctx = file2ctx(file);
int ret;
ret = vidioc_try_fmt_vid_out(file, priv, f);
@@ -639,10 +640,10 @@
return ret;
}
-static int vim2m_s_ctrl(struct v4l2_ctrl *ctrl)
+static int m2mtest_s_ctrl(struct v4l2_ctrl *ctrl)
{
- struct vim2m_ctx *ctx =
- container_of(ctrl->handler, struct vim2m_ctx, hdl);
+ struct m2mtest_ctx *ctx =
+ container_of(ctrl->handler, struct m2mtest_ctx, hdl);
switch (ctrl->id) {
case V4L2_CID_HFLIP:
@@ -675,12 +676,12 @@
return 0;
}
-static const struct v4l2_ctrl_ops vim2m_ctrl_ops = {
- .s_ctrl = vim2m_s_ctrl,
+static const struct v4l2_ctrl_ops m2mtest_ctrl_ops = {
+ .s_ctrl = m2mtest_s_ctrl,
};
-static const struct v4l2_ioctl_ops vim2m_ioctl_ops = {
+static const struct v4l2_ioctl_ops m2mtest_ioctl_ops = {
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
@@ -697,9 +698,6 @@
.vidioc_querybuf = v4l2_m2m_ioctl_querybuf,
.vidioc_qbuf = v4l2_m2m_ioctl_qbuf,
.vidioc_dqbuf = v4l2_m2m_ioctl_dqbuf,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- .vidioc_expbuf = v4l2_m2m_ioctl_expbuf,
-#endif
.vidioc_streamon = v4l2_m2m_ioctl_streamon,
.vidioc_streamoff = v4l2_m2m_ioctl_streamoff,
@@ -713,13 +711,13 @@
* Queue operations
*/
-static int vim2m_queue_setup(struct vb2_queue *vq,
+static int m2mtest_queue_setup(struct vb2_queue *vq,
const struct v4l2_format *fmt,
unsigned int *nbuffers, unsigned int *nplanes,
unsigned int sizes[], void *alloc_ctxs[])
{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(vq);
- struct vim2m_q_data *q_data;
+ struct m2mtest_ctx *ctx = vb2_get_drv_priv(vq);
+ struct m2mtest_q_data *q_data;
unsigned int size, count = *nbuffers;
q_data = get_q_data(ctx, vq->type);
@@ -743,10 +741,10 @@
return 0;
}
-static int vim2m_buf_prepare(struct vb2_buffer *vb)
+static int m2mtest_buf_prepare(struct vb2_buffer *vb)
{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
- struct vim2m_q_data *q_data;
+ struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct m2mtest_q_data *q_data;
dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
@@ -772,25 +770,25 @@
return 0;
}
-static void vim2m_buf_queue(struct vb2_buffer *vb)
+static void m2mtest_buf_queue(struct vb2_buffer *vb)
{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+ struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
v4l2_m2m_buf_queue(ctx->fh.m2m_ctx, vb);
}
-static int vim2m_start_streaming(struct vb2_queue *q, unsigned count)
+static int m2mtest_start_streaming(struct vb2_queue *q, unsigned count)
{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
- struct vim2m_q_data *q_data = get_q_data(ctx, q->type);
+ struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
+ struct m2mtest_q_data *q_data = get_q_data(ctx, q->type);
q_data->sequence = 0;
return 0;
}
-static void vim2m_stop_streaming(struct vb2_queue *q)
+static void m2mtest_stop_streaming(struct vb2_queue *q)
{
- struct vim2m_ctx *ctx = vb2_get_drv_priv(q);
+ struct m2mtest_ctx *ctx = vb2_get_drv_priv(q);
struct vb2_buffer *vb;
unsigned long flags;
@@ -807,26 +805,26 @@
}
}
-static struct vb2_ops vim2m_qops = {
- .queue_setup = vim2m_queue_setup,
- .buf_prepare = vim2m_buf_prepare,
- .buf_queue = vim2m_buf_queue,
- .start_streaming = vim2m_start_streaming,
- .stop_streaming = vim2m_stop_streaming,
+static struct vb2_ops m2mtest_qops = {
+ .queue_setup = m2mtest_queue_setup,
+ .buf_prepare = m2mtest_buf_prepare,
+ .buf_queue = m2mtest_buf_queue,
+ .start_streaming = m2mtest_start_streaming,
+ .stop_streaming = m2mtest_stop_streaming,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
};
static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
{
- struct vim2m_ctx *ctx = priv;
+ struct m2mtest_ctx *ctx = priv;
int ret;
src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
src_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
src_vq->drv_priv = ctx;
src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
- src_vq->ops = &vim2m_qops;
+ src_vq->ops = &m2mtest_qops;
src_vq->mem_ops = &vb2_vmalloc_memops;
src_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
src_vq->lock = &ctx->dev->dev_mutex;
@@ -839,7 +837,7 @@
dst_vq->io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
dst_vq->drv_priv = ctx;
dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
- dst_vq->ops = &vim2m_qops;
+ dst_vq->ops = &m2mtest_qops;
dst_vq->mem_ops = &vb2_vmalloc_memops;
dst_vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
dst_vq->lock = &ctx->dev->dev_mutex;
@@ -847,8 +845,8 @@
return vb2_queue_init(dst_vq);
}
-static const struct v4l2_ctrl_config vim2m_ctrl_trans_time_msec = {
- .ops = &vim2m_ctrl_ops,
+static const struct v4l2_ctrl_config m2mtest_ctrl_trans_time_msec = {
+ .ops = &m2mtest_ctrl_ops,
.id = V4L2_CID_TRANS_TIME_MSEC,
.name = "Transaction Time (msec)",
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -858,8 +856,8 @@
.step = 1,
};
-static const struct v4l2_ctrl_config vim2m_ctrl_trans_num_bufs = {
- .ops = &vim2m_ctrl_ops,
+static const struct v4l2_ctrl_config m2mtest_ctrl_trans_num_bufs = {
+ .ops = &m2mtest_ctrl_ops,
.id = V4L2_CID_TRANS_NUM_BUFS,
.name = "Buffers Per Transaction",
.type = V4L2_CTRL_TYPE_INTEGER,
@@ -872,10 +870,10 @@
/*
* File operations
*/
-static int vim2m_open(struct file *file)
+static int m2mtest_open(struct file *file)
{
- struct vim2m_dev *dev = video_drvdata(file);
- struct vim2m_ctx *ctx = NULL;
+ struct m2mtest_dev *dev = video_drvdata(file);
+ struct m2mtest_ctx *ctx = NULL;
struct v4l2_ctrl_handler *hdl;
int rc = 0;
@@ -892,10 +890,10 @@
ctx->dev = dev;
hdl = &ctx->hdl;
v4l2_ctrl_handler_init(hdl, 4);
- v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_std(hdl, &vim2m_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
- v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_time_msec, NULL);
- v4l2_ctrl_new_custom(hdl, &vim2m_ctrl_trans_num_bufs, NULL);
+ v4l2_ctrl_new_std(hdl, &m2mtest_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_std(hdl, &m2mtest_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
+ v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_time_msec, NULL);
+ v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_num_bufs, NULL);
if (hdl->error) {
rc = hdl->error;
v4l2_ctrl_handler_free(hdl);
@@ -935,10 +933,10 @@
return rc;
}
-static int vim2m_release(struct file *file)
+static int m2mtest_release(struct file *file)
{
- struct vim2m_dev *dev = video_drvdata(file);
- struct vim2m_ctx *ctx = file2ctx(file);
+ struct m2mtest_dev *dev = video_drvdata(file);
+ struct m2mtest_ctx *ctx = file2ctx(file);
dprintk(dev, "Releasing instance %p\n", ctx);
@@ -955,20 +953,20 @@
return 0;
}
-static const struct v4l2_file_operations vim2m_fops = {
+static const struct v4l2_file_operations m2mtest_fops = {
.owner = THIS_MODULE,
- .open = vim2m_open,
- .release = vim2m_release,
+ .open = m2mtest_open,
+ .release = m2mtest_release,
.poll = v4l2_m2m_fop_poll,
.unlocked_ioctl = video_ioctl2,
.mmap = v4l2_m2m_fop_mmap,
};
-static struct video_device vim2m_videodev = {
+static struct video_device m2mtest_videodev = {
.name = MEM2MEM_NAME,
.vfl_dir = VFL_DIR_M2M,
- .fops = &vim2m_fops,
- .ioctl_ops = &vim2m_ioctl_ops,
+ .fops = &m2mtest_fops,
+ .ioctl_ops = &m2mtest_ioctl_ops,
.minor = -1,
.release = video_device_release,
};
@@ -979,9 +977,9 @@
.job_abort = job_abort,
};
-static int vim2m_probe(struct platform_device *pdev)
+static int m2mtest_probe(struct platform_device *pdev)
{
- struct vim2m_dev *dev;
+ struct m2mtest_dev *dev;
struct video_device *vfd;
int ret;
@@ -1005,7 +1003,7 @@
goto unreg_dev;
}
- *vfd = vim2m_videodev;
+ *vfd = m2mtest_videodev;
vfd->lock = &dev->dev_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
@@ -1016,7 +1014,7 @@
}
video_set_drvdata(vfd, dev);
- snprintf(vfd->name, sizeof(vfd->name), "%s", vim2m_videodev.name);
+ snprintf(vfd->name, sizeof(vfd->name), "%s", m2mtest_videodev.name);
dev->vfd = vfd;
v4l2_info(&dev->v4l2_dev,
"Device registered as /dev/video%d\n", vfd->num);
@@ -1044,11 +1042,11 @@
return ret;
}
-static int vim2m_remove(struct platform_device *pdev)
+static int m2mtest_remove(struct platform_device *pdev)
{
- struct vim2m_dev *dev = platform_get_drvdata(pdev);
+ struct m2mtest_dev *dev = platform_get_drvdata(pdev);
- v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_NAME);
+ v4l2_info(&dev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
v4l2_m2m_release(dev->m2m_dev);
del_timer_sync(&dev->timer);
video_unregister_device(dev->vfd);
@@ -1057,34 +1055,35 @@
return 0;
}
-static struct platform_driver vim2m_pdrv = {
- .probe = vim2m_probe,
- .remove = vim2m_remove,
+static struct platform_driver m2mtest_pdrv = {
+ .probe = m2mtest_probe,
+ .remove = m2mtest_remove,
.driver = {
.name = MEM2MEM_NAME,
+ .owner = THIS_MODULE,
},
};
-static void __exit vim2m_exit(void)
+static void __exit m2mtest_exit(void)
{
- platform_driver_unregister(&vim2m_pdrv);
- platform_device_unregister(&vim2m_pdev);
+ platform_driver_unregister(&m2mtest_pdrv);
+ platform_device_unregister(&m2mtest_pdev);
}
-static int __init vim2m_init(void)
+static int __init m2mtest_init(void)
{
int ret;
- ret = platform_device_register(&vim2m_pdev);
+ ret = platform_device_register(&m2mtest_pdev);
if (ret)
return ret;
- ret = platform_driver_register(&vim2m_pdrv);
+ ret = platform_driver_register(&m2mtest_pdrv);
if (ret)
- platform_device_unregister(&vim2m_pdev);
+ platform_device_unregister(&m2mtest_pdev);
return 0;
}
-module_init(vim2m_init);
-module_exit(vim2m_exit);
+module_init(m2mtest_init);
+module_exit(m2mtest_exit);
diff --git a/drivers/media/platform/mx2_emmaprp.c b/drivers/media/platform/mx2_emmaprp.c
index 87314b7..4971ff2 100644
--- a/drivers/media/platform/mx2_emmaprp.c
+++ b/drivers/media/platform/mx2_emmaprp.c
@@ -402,8 +402,13 @@
{
strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
- cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ /*
+ * This is only a mem-to-mem video device. The capture and output
+ * device capability flags are left only for backward compatibility
+ * and are scheduled for removal.
+ */
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
return 0;
}
@@ -1005,6 +1010,7 @@
.remove = emmaprp_remove,
.driver = {
.name = MEM2MEM_NAME,
+ .owner = THIS_MODULE,
},
};
module_platform_driver(emmaprp_pdrv);
diff --git a/drivers/media/platform/omap/Kconfig b/drivers/media/platform/omap/Kconfig
index 97c28fd..f0bc674 100644
--- a/drivers/media/platform/omap/Kconfig
+++ b/drivers/media/platform/omap/Kconfig
@@ -4,8 +4,7 @@
config VIDEO_OMAP2_VOUT
tristate "OMAP2/OMAP3 V4L2-Display driver"
depends on m
- depends on MMU
- depends on ARCH_OMAP2 || ARCH_OMAP3
+ depends on ARCH_OMAP2 || ARCH_OMAP3 || (COMPILE_TEST && HAS_MMU)
select VIDEOBUF_GEN
select VIDEOBUF_DMA_CONTIG
select OMAP2_DSS if HAS_IOMEM && ARCH_OMAP2PLUS
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index ba2d8f9..64ab6fb 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -198,7 +198,7 @@
* omap_vout_uservirt_to_phys: This inline function is used to convert user
* space virtual address to physical address.
*/
-static unsigned long omap_vout_uservirt_to_phys(unsigned long virtp)
+static u32 omap_vout_uservirt_to_phys(u32 virtp)
{
unsigned long physp = 0;
struct vm_area_struct *vma;
@@ -418,10 +418,10 @@
}
v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
- "%s enable=%d addr=%pad width=%d\n height=%d color_mode=%d\n"
+ "%s enable=%d addr=%x width=%d\n height=%d color_mode=%d\n"
"rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
"out_height=%d rotation_type=%d screen_width=%d\n",
- __func__, ovl->is_enabled(ovl), &info.paddr, info.width, info.height,
+ __func__, ovl->is_enabled(ovl), info.paddr, info.width, info.height,
info.color_mode, info.rotation, info.mirror, info.pos_x,
info.pos_y, info.out_width, info.out_height, info.rotation_type,
info.screen_width);
@@ -794,7 +794,7 @@
vout->queued_buf_addr[vb->i] = (u8 *)
omap_vout_uservirt_to_phys(vb->baddr);
} else {
- unsigned long addr, dma_addr;
+ u32 addr, dma_addr;
unsigned long size;
addr = (unsigned long) vout->buf_virt_addr[vb->i];
@@ -1054,9 +1054,8 @@
strlcpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
strlcpy(cap->card, vout->vfd->name, sizeof(cap->card));
cap->bus_info[0] = '\0';
- cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
+ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c
index 51c2129..72265e5 100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -2380,6 +2380,7 @@
.remove = isp_remove,
.id_table = omap3isp_id_table,
.driver = {
+ .owner = THIS_MODULE,
.name = "omap3isp",
.pm = &omap3isp_pm_ops,
},
diff --git a/drivers/media/platform/omap3isp/ispccdc.c b/drivers/media/platform/omap3isp/ispccdc.c
index 587489a..81a9dc0 100644
--- a/drivers/media/platform/omap3isp/ispccdc.c
+++ b/drivers/media/platform/omap3isp/ispccdc.c
@@ -36,23 +36,23 @@
unsigned int pad, enum v4l2_subdev_format_whence which);
static const unsigned int ccdc_fmts[] = {
- MEDIA_BUS_FMT_Y8_1X8,
- MEDIA_BUS_FMT_Y10_1X10,
- MEDIA_BUS_FMT_Y12_1X12,
- MEDIA_BUS_FMT_SGRBG8_1X8,
- MEDIA_BUS_FMT_SRGGB8_1X8,
- MEDIA_BUS_FMT_SBGGR8_1X8,
- MEDIA_BUS_FMT_SGBRG8_1X8,
- MEDIA_BUS_FMT_SGRBG10_1X10,
- MEDIA_BUS_FMT_SRGGB10_1X10,
- MEDIA_BUS_FMT_SBGGR10_1X10,
- MEDIA_BUS_FMT_SGBRG10_1X10,
- MEDIA_BUS_FMT_SGRBG12_1X12,
- MEDIA_BUS_FMT_SRGGB12_1X12,
- MEDIA_BUS_FMT_SBGGR12_1X12,
- MEDIA_BUS_FMT_SGBRG12_1X12,
- MEDIA_BUS_FMT_YUYV8_2X8,
- MEDIA_BUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_Y8_1X8,
+ V4L2_MBUS_FMT_Y10_1X10,
+ V4L2_MBUS_FMT_Y12_1X12,
+ V4L2_MBUS_FMT_SGRBG8_1X8,
+ V4L2_MBUS_FMT_SRGGB8_1X8,
+ V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_MBUS_FMT_SGBRG8_1X8,
+ V4L2_MBUS_FMT_SGRBG10_1X10,
+ V4L2_MBUS_FMT_SRGGB10_1X10,
+ V4L2_MBUS_FMT_SBGGR10_1X10,
+ V4L2_MBUS_FMT_SGBRG10_1X10,
+ V4L2_MBUS_FMT_SGRBG12_1X12,
+ V4L2_MBUS_FMT_SRGGB12_1X12,
+ V4L2_MBUS_FMT_SBGGR12_1X12,
+ V4L2_MBUS_FMT_SGBRG12_1X12,
+ V4L2_MBUS_FMT_YUYV8_2X8,
+ V4L2_MBUS_FMT_UYVY8_2X8,
};
/*
@@ -266,10 +266,10 @@
__ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
V4L2_SUBDEV_FORMAT_ACTIVE);
- if ((format->code != MEDIA_BUS_FMT_SGRBG10_1X10) &&
- (format->code != MEDIA_BUS_FMT_SRGGB10_1X10) &&
- (format->code != MEDIA_BUS_FMT_SBGGR10_1X10) &&
- (format->code != MEDIA_BUS_FMT_SGBRG10_1X10))
+ if ((format->code != V4L2_MBUS_FMT_SGRBG10_1X10) &&
+ (format->code != V4L2_MBUS_FMT_SRGGB10_1X10) &&
+ (format->code != V4L2_MBUS_FMT_SBGGR10_1X10) &&
+ (format->code != V4L2_MBUS_FMT_SGBRG10_1X10))
return -EINVAL;
if (enable)
@@ -971,8 +971,8 @@
format = &ccdc->formats[CCDC_PAD_SINK];
- if (format->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
- format->code == MEDIA_BUS_FMT_UYVY8_2X8) {
+ if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+ format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
/* According to the OMAP3 TRM the input mode only affects SYNC
* mode, enabling BT.656 mode should take precedence. However,
* in practice setting the input mode to YCbCr data on 8 bits
@@ -1020,7 +1020,7 @@
/* The CCDC_CFG.Y8POS bit is used in YCbCr8 input mode only. The
* hardware seems to ignore it in all other input modes.
*/
- if (format->code == MEDIA_BUS_FMT_UYVY8_2X8)
+ if (format->code == V4L2_MBUS_FMT_UYVY8_2X8)
isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
ISPCCDC_CFG_Y8POS);
else
@@ -1168,9 +1168,9 @@
if (ccdc->bt656)
bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
- else if (fmt_info->code == MEDIA_BUS_FMT_YUYV8_2X8)
+ else if (fmt_info->code == V4L2_MBUS_FMT_YUYV8_2X8)
bridge = ISPCTRL_PAR_BRIDGE_LENDIAN;
- else if (fmt_info->code == MEDIA_BUS_FMT_UYVY8_2X8)
+ else if (fmt_info->code == V4L2_MBUS_FMT_UYVY8_2X8)
bridge = ISPCTRL_PAR_BRIDGE_BENDIAN;
else
bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
@@ -1199,16 +1199,16 @@
/* Mosaic filter */
switch (format->code) {
- case MEDIA_BUS_FMT_SRGGB10_1X10:
- case MEDIA_BUS_FMT_SRGGB12_1X12:
+ case V4L2_MBUS_FMT_SRGGB10_1X10:
+ case V4L2_MBUS_FMT_SRGGB12_1X12:
ccdc_pattern = ccdc_srggb_pattern;
break;
- case MEDIA_BUS_FMT_SBGGR10_1X10:
- case MEDIA_BUS_FMT_SBGGR12_1X12:
+ case V4L2_MBUS_FMT_SBGGR10_1X10:
+ case V4L2_MBUS_FMT_SBGGR12_1X12:
ccdc_pattern = ccdc_sbggr_pattern;
break;
- case MEDIA_BUS_FMT_SGBRG10_1X10:
- case MEDIA_BUS_FMT_SGBRG12_1X12:
+ case V4L2_MBUS_FMT_SGBRG10_1X10:
+ case V4L2_MBUS_FMT_SGBRG12_1X12:
ccdc_pattern = ccdc_sgbrg_pattern;
break;
default:
@@ -1267,7 +1267,7 @@
/* The CCDC outputs data in UYVY order by default. Swap bytes to get
* YUYV.
*/
- if (format->code == MEDIA_BUS_FMT_YUYV8_1X16)
+ if (format->code == V4L2_MBUS_FMT_YUYV8_1X16)
isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
ISPCCDC_CFG_BSWD);
else
@@ -1967,7 +1967,7 @@
enum v4l2_subdev_format_whence which)
{
const struct isp_format_info *info;
- u32 pixelcode;
+ enum v4l2_mbus_pixelcode pixelcode;
unsigned int width = fmt->width;
unsigned int height = fmt->height;
struct v4l2_rect *crop;
@@ -1983,7 +1983,7 @@
/* If not found, use SGRBG10 as default */
if (i >= ARRAY_SIZE(ccdc_fmts))
- fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
/* Clamp the input size. */
fmt->width = clamp_t(u32, width, 32, 4096);
@@ -2007,19 +2007,19 @@
* configured to pack bytes in BT.656, hiding the inaccuracy.
* In all cases bytes can be swapped.
*/
- if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
- fmt->code == MEDIA_BUS_FMT_UYVY8_2X8) {
+ if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+ fmt->code == V4L2_MBUS_FMT_UYVY8_2X8) {
/* Use the user requested format if YUV. */
- if (pixelcode == MEDIA_BUS_FMT_YUYV8_2X8 ||
- pixelcode == MEDIA_BUS_FMT_UYVY8_2X8 ||
- pixelcode == MEDIA_BUS_FMT_YUYV8_1X16 ||
- pixelcode == MEDIA_BUS_FMT_UYVY8_1X16)
+ if (pixelcode == V4L2_MBUS_FMT_YUYV8_2X8 ||
+ pixelcode == V4L2_MBUS_FMT_UYVY8_2X8 ||
+ pixelcode == V4L2_MBUS_FMT_YUYV8_1X16 ||
+ pixelcode == V4L2_MBUS_FMT_UYVY8_1X16)
fmt->code = pixelcode;
- if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8)
- fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
- else if (fmt->code == MEDIA_BUS_FMT_UYVY8_2X8)
- fmt->code = MEDIA_BUS_FMT_UYVY8_1X16;
+ if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8)
+ fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
+ else if (fmt->code == V4L2_MBUS_FMT_UYVY8_2X8)
+ fmt->code = V4L2_MBUS_FMT_UYVY8_1X16;
}
/* Hardcode the output size to the crop rectangle size. */
@@ -2047,8 +2047,8 @@
fmt->code = info->truncated;
/* YUV formats are not supported by the video port. */
- if (fmt->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
- fmt->code == MEDIA_BUS_FMT_UYVY8_2X8)
+ if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+ fmt->code == V4L2_MBUS_FMT_UYVY8_2X8)
fmt->code = 0;
/* The number of lines that can be clocked out from the video
@@ -2083,7 +2083,7 @@
* to keep the Bayer pattern.
*/
info = omap3isp_video_format_info(sink->code);
- if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) {
+ if (info->flavor != V4L2_MBUS_FMT_Y8_1X8) {
crop->left &= ~1;
crop->top &= ~1;
}
@@ -2103,7 +2103,7 @@
sink->height - crop->top);
/* Odd width/height values don't make sense for Bayer formats. */
- if (info->flavor != MEDIA_BUS_FMT_Y8_1X8) {
+ if (info->flavor != V4L2_MBUS_FMT_Y8_1X8) {
crop->width &= ~1;
crop->height &= ~1;
}
@@ -2135,13 +2135,13 @@
format = __ccdc_get_format(ccdc, fh, code->pad,
V4L2_SUBDEV_FORMAT_TRY);
- if (format->code == MEDIA_BUS_FMT_YUYV8_2X8 ||
- format->code == MEDIA_BUS_FMT_UYVY8_2X8) {
+ if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+ format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
/* In YUV mode the CCDC can swap bytes. */
if (code->index == 0)
- code->code = MEDIA_BUS_FMT_YUYV8_1X16;
+ code->code = V4L2_MBUS_FMT_YUYV8_1X16;
else if (code->index == 1)
- code->code = MEDIA_BUS_FMT_UYVY8_1X16;
+ code->code = V4L2_MBUS_FMT_UYVY8_1X16;
else
return -EINVAL;
} else {
@@ -2383,7 +2383,9 @@
* return true if the combination is possible
* return false otherwise
*/
-static bool ccdc_is_shiftable(u32 in, u32 out, unsigned int additional_shift)
+static bool ccdc_is_shiftable(enum v4l2_mbus_pixelcode in,
+ enum v4l2_mbus_pixelcode out,
+ unsigned int additional_shift)
{
const struct isp_format_info *in_info, *out_info;
@@ -2450,7 +2452,7 @@
memset(&format, 0, sizeof(format));
format.pad = CCDC_PAD_SINK;
format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
format.format.width = 4096;
format.format.height = 4096;
ccdc_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/ispccp2.c b/drivers/media/platform/omap3isp/ispccp2.c
index f4aedb3..9cb49b3 100644
--- a/drivers/media/platform/omap3isp/ispccp2.c
+++ b/drivers/media/platform/omap3isp/ispccp2.c
@@ -289,10 +289,10 @@
u32 val, format;
switch (config->format) {
- case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
+ case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
format = ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP;
break;
- case MEDIA_BUS_FMT_SGRBG10_1X10:
+ case V4L2_MBUS_FMT_SGRBG10_1X10:
default:
format = ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP; /* RAW10+VP */
break;
@@ -438,7 +438,7 @@
u32 val, hwords;
if (sink_pixcode != source_pixcode &&
- sink_pixcode == MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8)
+ sink_pixcode == V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
dpcm_decompress = 1;
ccp2_pwr_cfg(ccp2);
@@ -604,8 +604,8 @@
*/
static const unsigned int ccp2_fmts[] = {
- MEDIA_BUS_FMT_SGRBG10_1X10,
- MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
+ V4L2_MBUS_FMT_SGRBG10_1X10,
+ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
};
/*
@@ -643,8 +643,8 @@
switch (pad) {
case CCP2_PAD_SINK:
- if (fmt->code != MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8)
- fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ if (fmt->code != V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
if (ccp2->input == CCP2_INPUT_SENSOR) {
fmt->width = clamp_t(u32, fmt->width,
@@ -671,7 +671,7 @@
*/
format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK, which);
memcpy(fmt, format, sizeof(*fmt));
- fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
break;
}
@@ -808,7 +808,7 @@
memset(&format, 0, sizeof(format));
format.pad = CCP2_PAD_SINK;
format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
format.format.width = 4096;
format.format.height = 4096;
ccp2_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/ispcsi2.c b/drivers/media/platform/omap3isp/ispcsi2.c
index 09c686d..6530b25 100644
--- a/drivers/media/platform/omap3isp/ispcsi2.c
+++ b/drivers/media/platform/omap3isp/ispcsi2.c
@@ -78,15 +78,15 @@
}
static const unsigned int csi2_input_fmts[] = {
- MEDIA_BUS_FMT_SGRBG10_1X10,
- MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
- MEDIA_BUS_FMT_SRGGB10_1X10,
- MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8,
- MEDIA_BUS_FMT_SBGGR10_1X10,
- MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8,
- MEDIA_BUS_FMT_SGBRG10_1X10,
- MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8,
- MEDIA_BUS_FMT_YUYV8_2X8,
+ V4L2_MBUS_FMT_SGRBG10_1X10,
+ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+ V4L2_MBUS_FMT_SRGGB10_1X10,
+ V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
+ V4L2_MBUS_FMT_SBGGR10_1X10,
+ V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
+ V4L2_MBUS_FMT_SGBRG10_1X10,
+ V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
+ V4L2_MBUS_FMT_YUYV8_2X8,
};
/* To set the format on the CSI2 requires a mapping function that takes
@@ -171,19 +171,19 @@
int fmtidx, destidx, is_3630;
switch (fmt->code) {
- case MEDIA_BUS_FMT_SGRBG10_1X10:
- case MEDIA_BUS_FMT_SRGGB10_1X10:
- case MEDIA_BUS_FMT_SBGGR10_1X10:
- case MEDIA_BUS_FMT_SGBRG10_1X10:
+ case V4L2_MBUS_FMT_SGRBG10_1X10:
+ case V4L2_MBUS_FMT_SRGGB10_1X10:
+ case V4L2_MBUS_FMT_SBGGR10_1X10:
+ case V4L2_MBUS_FMT_SGBRG10_1X10:
fmtidx = 0;
break;
- case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
- case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
- case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
- case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
+ case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+ case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
+ case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
+ case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
fmtidx = 1;
break;
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
fmtidx = 2;
break;
default:
@@ -843,7 +843,7 @@
unsigned int pad, struct v4l2_mbus_framefmt *fmt,
enum v4l2_subdev_format_whence which)
{
- u32 pixelcode;
+ enum v4l2_mbus_pixelcode pixelcode;
struct v4l2_mbus_framefmt *format;
const struct isp_format_info *info;
unsigned int i;
@@ -858,7 +858,7 @@
/* If not found, use SGRBG10 as default */
if (i >= ARRAY_SIZE(csi2_input_fmts))
- fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
fmt->width = clamp_t(u32, fmt->width, 1, 8191);
fmt->height = clamp_t(u32, fmt->height, 1, 8191);
@@ -1029,7 +1029,7 @@
memset(&format, 0, sizeof(format));
format.pad = CSI2_PAD_SINK;
format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
format.format.width = 4096;
format.format.height = 4096;
csi2_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/isppreview.c b/drivers/media/platform/omap3isp/isppreview.c
index dd9eed4..605f57e 100644
--- a/drivers/media/platform/omap3isp/isppreview.c
+++ b/drivers/media/platform/omap3isp/isppreview.c
@@ -964,16 +964,18 @@
* @prev: pointer to previewer private structure
* @pixelcode: pixel code
*/
-static void preview_config_ycpos(struct isp_prev_device *prev, u32 pixelcode)
+static void
+preview_config_ycpos(struct isp_prev_device *prev,
+ enum v4l2_mbus_pixelcode pixelcode)
{
struct isp_device *isp = to_isp_device(prev);
enum preview_ycpos_mode mode;
switch (pixelcode) {
- case MEDIA_BUS_FMT_YUYV8_1X16:
+ case V4L2_MBUS_FMT_YUYV8_1X16:
mode = YCPOS_CrYCbY;
break;
- case MEDIA_BUS_FMT_UYVY8_1X16:
+ case V4L2_MBUS_FMT_UYVY8_1X16:
mode = YCPOS_YCrYCb;
break;
default:
@@ -1026,16 +1028,16 @@
ISPPRV_PCR_WIDTH);
switch (info->flavor) {
- case MEDIA_BUS_FMT_SGRBG8_1X8:
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
prev->params.cfa_order = 0;
break;
- case MEDIA_BUS_FMT_SRGGB8_1X8:
+ case V4L2_MBUS_FMT_SRGGB8_1X8:
prev->params.cfa_order = 1;
break;
- case MEDIA_BUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
prev->params.cfa_order = 2;
break;
- case MEDIA_BUS_FMT_SGBRG8_1X8:
+ case V4L2_MBUS_FMT_SGBRG8_1X8:
prev->params.cfa_order = 3;
break;
default:
@@ -1076,8 +1078,8 @@
unsigned int elv = prev->crop.top + prev->crop.height - 1;
u32 features;
- if (format->code != MEDIA_BUS_FMT_Y8_1X8 &&
- format->code != MEDIA_BUS_FMT_Y10_1X10) {
+ if (format->code != V4L2_MBUS_FMT_Y8_1X8 &&
+ format->code != V4L2_MBUS_FMT_Y10_1X10) {
sph -= 2;
eph += 2;
slv -= 2;
@@ -1707,21 +1709,21 @@
/* previewer format descriptions */
static const unsigned int preview_input_fmts[] = {
- MEDIA_BUS_FMT_Y8_1X8,
- MEDIA_BUS_FMT_SGRBG8_1X8,
- MEDIA_BUS_FMT_SRGGB8_1X8,
- MEDIA_BUS_FMT_SBGGR8_1X8,
- MEDIA_BUS_FMT_SGBRG8_1X8,
- MEDIA_BUS_FMT_Y10_1X10,
- MEDIA_BUS_FMT_SGRBG10_1X10,
- MEDIA_BUS_FMT_SRGGB10_1X10,
- MEDIA_BUS_FMT_SBGGR10_1X10,
- MEDIA_BUS_FMT_SGBRG10_1X10,
+ V4L2_MBUS_FMT_Y8_1X8,
+ V4L2_MBUS_FMT_SGRBG8_1X8,
+ V4L2_MBUS_FMT_SRGGB8_1X8,
+ V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_MBUS_FMT_SGBRG8_1X8,
+ V4L2_MBUS_FMT_Y10_1X10,
+ V4L2_MBUS_FMT_SGRBG10_1X10,
+ V4L2_MBUS_FMT_SRGGB10_1X10,
+ V4L2_MBUS_FMT_SBGGR10_1X10,
+ V4L2_MBUS_FMT_SGBRG10_1X10,
};
static const unsigned int preview_output_fmts[] = {
- MEDIA_BUS_FMT_UYVY8_1X16,
- MEDIA_BUS_FMT_YUYV8_1X16,
+ V4L2_MBUS_FMT_UYVY8_1X16,
+ V4L2_MBUS_FMT_YUYV8_1X16,
};
/*
@@ -1740,7 +1742,7 @@
struct v4l2_mbus_framefmt *fmt,
enum v4l2_subdev_format_whence which)
{
- u32 pixelcode;
+ enum v4l2_mbus_pixelcode pixelcode;
struct v4l2_rect *crop;
unsigned int i;
@@ -1772,7 +1774,7 @@
/* If not found, use SGRBG10 as default */
if (i >= ARRAY_SIZE(preview_input_fmts))
- fmt->code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
break;
case PREV_PAD_SOURCE:
@@ -1780,13 +1782,13 @@
*fmt = *__preview_get_format(prev, fh, PREV_PAD_SINK, which);
switch (pixelcode) {
- case MEDIA_BUS_FMT_YUYV8_1X16:
- case MEDIA_BUS_FMT_UYVY8_1X16:
+ case V4L2_MBUS_FMT_YUYV8_1X16:
+ case V4L2_MBUS_FMT_UYVY8_1X16:
fmt->code = pixelcode;
break;
default:
- fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
+ fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
break;
}
@@ -1841,8 +1843,8 @@
* and no columns in other modes. Increase the margins based on the sink
* format.
*/
- if (sink->code != MEDIA_BUS_FMT_Y8_1X8 &&
- sink->code != MEDIA_BUS_FMT_Y10_1X10) {
+ if (sink->code != V4L2_MBUS_FMT_Y8_1X8 &&
+ sink->code != V4L2_MBUS_FMT_Y10_1X10) {
left += 2;
right -= 2;
top += 2;
@@ -2090,7 +2092,7 @@
memset(&format, 0, sizeof(format));
format.pad = PREV_PAD_SINK;
format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- format.format.code = MEDIA_BUS_FMT_SGRBG10_1X10;
+ format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
format.format.width = 4096;
format.format.height = 4096;
preview_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/ispresizer.c b/drivers/media/platform/omap3isp/ispresizer.c
index 2b9bc48..05d1ace 100644
--- a/drivers/media/platform/omap3isp/ispresizer.c
+++ b/drivers/media/platform/omap3isp/ispresizer.c
@@ -198,16 +198,17 @@
* @res: Device context.
* @pixelcode: pixel code.
*/
-static void resizer_set_ycpos(struct isp_res_device *res, u32 pixelcode)
+static void resizer_set_ycpos(struct isp_res_device *res,
+ enum v4l2_mbus_pixelcode pixelcode)
{
struct isp_device *isp = to_isp_device(res);
switch (pixelcode) {
- case MEDIA_BUS_FMT_YUYV8_1X16:
+ case V4L2_MBUS_FMT_YUYV8_1X16:
isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
ISPRSZ_CNT_YCPOS);
break;
- case MEDIA_BUS_FMT_UYVY8_1X16:
+ case V4L2_MBUS_FMT_UYVY8_1X16:
isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
ISPRSZ_CNT_YCPOS);
break;
@@ -1347,8 +1348,8 @@
/* resizer pixel formats */
static const unsigned int resizer_formats[] = {
- MEDIA_BUS_FMT_UYVY8_1X16,
- MEDIA_BUS_FMT_YUYV8_1X16,
+ V4L2_MBUS_FMT_UYVY8_1X16,
+ V4L2_MBUS_FMT_YUYV8_1X16,
};
static unsigned int resizer_max_in_width(struct isp_res_device *res)
@@ -1384,9 +1385,9 @@
switch (pad) {
case RESZ_PAD_SINK:
- if (fmt->code != MEDIA_BUS_FMT_YUYV8_1X16 &&
- fmt->code != MEDIA_BUS_FMT_UYVY8_1X16)
- fmt->code = MEDIA_BUS_FMT_YUYV8_1X16;
+ if (fmt->code != V4L2_MBUS_FMT_YUYV8_1X16 &&
+ fmt->code != V4L2_MBUS_FMT_UYVY8_1X16)
+ fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH,
resizer_max_in_width(res));
@@ -1570,7 +1571,7 @@
memset(&format, 0, sizeof(format));
format.pad = RESZ_PAD_SINK;
format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
- format.format.code = MEDIA_BUS_FMT_YUYV8_1X16;
+ format.format.code = V4L2_MBUS_FMT_YUYV8_1X16;
format.format.width = 4096;
format.format.height = 4096;
resizer_set_format(sd, fh, &format);
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index b463fe1..bc38c88 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -39,74 +39,74 @@
* corresponding in-memory formats to the table below!!!
*/
static struct isp_format_info formats[] = {
- { MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
- MEDIA_BUS_FMT_Y8_1X8, MEDIA_BUS_FMT_Y8_1X8,
+ { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
+ V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
V4L2_PIX_FMT_GREY, 8, 1, },
- { MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y10_1X10,
- MEDIA_BUS_FMT_Y10_1X10, MEDIA_BUS_FMT_Y8_1X8,
+ { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
+ V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
V4L2_PIX_FMT_Y10, 10, 2, },
- { MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y10_1X10,
- MEDIA_BUS_FMT_Y12_1X12, MEDIA_BUS_FMT_Y8_1X8,
+ { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
+ V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
V4L2_PIX_FMT_Y12, 12, 2, },
- { MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
- MEDIA_BUS_FMT_SBGGR8_1X8, MEDIA_BUS_FMT_SBGGR8_1X8,
+ { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+ V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
V4L2_PIX_FMT_SBGGR8, 8, 1, },
- { MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
- MEDIA_BUS_FMT_SGBRG8_1X8, MEDIA_BUS_FMT_SGBRG8_1X8,
+ { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+ V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
V4L2_PIX_FMT_SGBRG8, 8, 1, },
- { MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
- MEDIA_BUS_FMT_SGRBG8_1X8, MEDIA_BUS_FMT_SGRBG8_1X8,
+ { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+ V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
V4L2_PIX_FMT_SGRBG8, 8, 1, },
- { MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
- MEDIA_BUS_FMT_SRGGB8_1X8, MEDIA_BUS_FMT_SRGGB8_1X8,
+ { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+ V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
V4L2_PIX_FMT_SRGGB8, 8, 1, },
- { MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8, MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8,
- MEDIA_BUS_FMT_SBGGR10_1X10, 0,
+ { V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
+ V4L2_MBUS_FMT_SBGGR10_1X10, 0,
V4L2_PIX_FMT_SBGGR10DPCM8, 8, 1, },
- { MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8, MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8,
- MEDIA_BUS_FMT_SGBRG10_1X10, 0,
+ { V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
+ V4L2_MBUS_FMT_SGBRG10_1X10, 0,
V4L2_PIX_FMT_SGBRG10DPCM8, 8, 1, },
- { MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8, MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
- MEDIA_BUS_FMT_SGRBG10_1X10, 0,
+ { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+ V4L2_MBUS_FMT_SGRBG10_1X10, 0,
V4L2_PIX_FMT_SGRBG10DPCM8, 8, 1, },
- { MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8, MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8,
- MEDIA_BUS_FMT_SRGGB10_1X10, 0,
+ { V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
+ V4L2_MBUS_FMT_SRGGB10_1X10, 0,
V4L2_PIX_FMT_SRGGB10DPCM8, 8, 1, },
- { MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR10_1X10,
- MEDIA_BUS_FMT_SBGGR10_1X10, MEDIA_BUS_FMT_SBGGR8_1X8,
+ { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
+ V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
V4L2_PIX_FMT_SBGGR10, 10, 2, },
- { MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG10_1X10,
- MEDIA_BUS_FMT_SGBRG10_1X10, MEDIA_BUS_FMT_SGBRG8_1X8,
+ { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
+ V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
V4L2_PIX_FMT_SGBRG10, 10, 2, },
- { MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG10_1X10,
- MEDIA_BUS_FMT_SGRBG10_1X10, MEDIA_BUS_FMT_SGRBG8_1X8,
+ { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
+ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
V4L2_PIX_FMT_SGRBG10, 10, 2, },
- { MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB10_1X10,
- MEDIA_BUS_FMT_SRGGB10_1X10, MEDIA_BUS_FMT_SRGGB8_1X8,
+ { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
+ V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
V4L2_PIX_FMT_SRGGB10, 10, 2, },
- { MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR10_1X10,
- MEDIA_BUS_FMT_SBGGR12_1X12, MEDIA_BUS_FMT_SBGGR8_1X8,
+ { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
+ V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
V4L2_PIX_FMT_SBGGR12, 12, 2, },
- { MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG10_1X10,
- MEDIA_BUS_FMT_SGBRG12_1X12, MEDIA_BUS_FMT_SGBRG8_1X8,
+ { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
+ V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
V4L2_PIX_FMT_SGBRG12, 12, 2, },
- { MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG10_1X10,
- MEDIA_BUS_FMT_SGRBG12_1X12, MEDIA_BUS_FMT_SGRBG8_1X8,
+ { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
+ V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
V4L2_PIX_FMT_SGRBG12, 12, 2, },
- { MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB10_1X10,
- MEDIA_BUS_FMT_SRGGB12_1X12, MEDIA_BUS_FMT_SRGGB8_1X8,
+ { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
+ V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
V4L2_PIX_FMT_SRGGB12, 12, 2, },
- { MEDIA_BUS_FMT_UYVY8_1X16, MEDIA_BUS_FMT_UYVY8_1X16,
- MEDIA_BUS_FMT_UYVY8_1X16, 0,
+ { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
+ V4L2_MBUS_FMT_UYVY8_1X16, 0,
V4L2_PIX_FMT_UYVY, 16, 2, },
- { MEDIA_BUS_FMT_YUYV8_1X16, MEDIA_BUS_FMT_YUYV8_1X16,
- MEDIA_BUS_FMT_YUYV8_1X16, 0,
+ { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
+ V4L2_MBUS_FMT_YUYV8_1X16, 0,
V4L2_PIX_FMT_YUYV, 16, 2, },
- { MEDIA_BUS_FMT_UYVY8_2X8, MEDIA_BUS_FMT_UYVY8_2X8,
- MEDIA_BUS_FMT_UYVY8_2X8, 0,
+ { V4L2_MBUS_FMT_UYVY8_2X8, V4L2_MBUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_UYVY8_2X8, 0,
V4L2_PIX_FMT_UYVY, 8, 2, },
- { MEDIA_BUS_FMT_YUYV8_2X8, MEDIA_BUS_FMT_YUYV8_2X8,
- MEDIA_BUS_FMT_YUYV8_2X8, 0,
+ { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_MBUS_FMT_YUYV8_2X8,
+ V4L2_MBUS_FMT_YUYV8_2X8, 0,
V4L2_PIX_FMT_YUYV, 8, 2, },
/* Empty entry to catch the unsupported pixel code (0) used by the CCDC
* module and avoid NULL pointer dereferences.
@@ -114,7 +114,8 @@
{ 0, }
};
-const struct isp_format_info *omap3isp_video_format_info(u32 code)
+const struct isp_format_info *
+omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
{
unsigned int i;
diff --git a/drivers/media/platform/omap3isp/ispvideo.h b/drivers/media/platform/omap3isp/ispvideo.h
index 4071dd7..0b7efed 100644
--- a/drivers/media/platform/omap3isp/ispvideo.h
+++ b/drivers/media/platform/omap3isp/ispvideo.h
@@ -44,10 +44,10 @@
* @bpp: Bytes per pixel (when stored in memory)
*/
struct isp_format_info {
- u32 code;
- u32 truncated;
- u32 uncompressed;
- u32 flavor;
+ enum v4l2_mbus_pixelcode code;
+ enum v4l2_mbus_pixelcode truncated;
+ enum v4l2_mbus_pixelcode uncompressed;
+ enum v4l2_mbus_pixelcode flavor;
u32 pixelformat;
unsigned int width;
unsigned int bpp;
@@ -206,6 +206,6 @@
struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
const struct isp_format_info *
-omap3isp_video_format_info(u32 code);
+omap3isp_video_format_info(enum v4l2_mbus_pixelcode code);
#endif /* OMAP3_ISP_VIDEO_H */
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index aa40c82..4f81b4c 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -1218,11 +1218,11 @@
}
/* Media bus pixel formats supported at the camif input */
-static const u32 camif_mbus_formats[] = {
- MEDIA_BUS_FMT_YUYV8_2X8,
- MEDIA_BUS_FMT_YVYU8_2X8,
- MEDIA_BUS_FMT_UYVY8_2X8,
- MEDIA_BUS_FMT_VYUY8_2X8,
+static const enum v4l2_mbus_pixelcode camif_mbus_formats[] = {
+ V4L2_MBUS_FMT_YUYV8_2X8,
+ V4L2_MBUS_FMT_YVYU8_2X8,
+ V4L2_MBUS_FMT_UYVY8_2X8,
+ V4L2_MBUS_FMT_VYUY8_2X8,
};
/*
diff --git a/drivers/media/platform/s3c-camif/camif-core.c b/drivers/media/platform/s3c-camif/camif-core.c
index 2d5bd3a..b385747 100644
--- a/drivers/media/platform/s3c-camif/camif-core.c
+++ b/drivers/media/platform/s3c-camif/camif-core.c
@@ -256,7 +256,8 @@
v4l2_device_unregister_subdev(sd);
camif->sensor.sd = NULL;
i2c_unregister_device(client);
- i2c_put_adapter(adapter);
+ if (adapter)
+ i2c_put_adapter(adapter);
}
static int camif_create_media_links(struct camif_dev *camif)
@@ -651,6 +652,7 @@
.id_table = s3c_camif_driver_ids,
.driver = {
.name = S3C_CAMIF_DRIVER_NAME,
+ .owner = THIS_MODULE,
.pm = &s3c_camif_pm_ops,
}
};
diff --git a/drivers/media/platform/s3c-camif/camif-regs.c b/drivers/media/platform/s3c-camif/camif-regs.c
index 812fb3a..6e0c998 100644
--- a/drivers/media/platform/s3c-camif/camif-regs.c
+++ b/drivers/media/platform/s3c-camif/camif-regs.c
@@ -96,10 +96,10 @@
}
static const u32 src_pixfmt_map[8][2] = {
- { MEDIA_BUS_FMT_YUYV8_2X8, CISRCFMT_ORDER422_YCBYCR },
- { MEDIA_BUS_FMT_YVYU8_2X8, CISRCFMT_ORDER422_YCRYCB },
- { MEDIA_BUS_FMT_UYVY8_2X8, CISRCFMT_ORDER422_CBYCRY },
- { MEDIA_BUS_FMT_VYUY8_2X8, CISRCFMT_ORDER422_CRYCBY },
+ { V4L2_MBUS_FMT_YUYV8_2X8, CISRCFMT_ORDER422_YCBYCR },
+ { V4L2_MBUS_FMT_YVYU8_2X8, CISRCFMT_ORDER422_YCRYCB },
+ { V4L2_MBUS_FMT_UYVY8_2X8, CISRCFMT_ORDER422_CBYCRY },
+ { V4L2_MBUS_FMT_VYUY8_2X8, CISRCFMT_ORDER422_CRYCBY },
};
/* Set camera input pixel format and resolution */
diff --git a/drivers/media/platform/s5p-g2d/g2d.c b/drivers/media/platform/s5p-g2d/g2d.c
index 47ba8fb..d79e214 100644
--- a/drivers/media/platform/s5p-g2d/g2d.c
+++ b/drivers/media/platform/s5p-g2d/g2d.c
@@ -297,8 +297,14 @@
strncpy(cap->driver, G2D_NAME, sizeof(cap->driver) - 1);
strncpy(cap->card, G2D_NAME, sizeof(cap->card) - 1);
cap->bus_info[0] = 0;
- cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ cap->version = KERNEL_VERSION(1, 0, 0);
+ /*
+ * This is only a mem-to-mem video device. The capture and output
+ * device capability flags are left only for backward compatibility
+ * and are scheduled for removal.
+ */
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+ V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
return 0;
}
@@ -806,6 +812,7 @@
.id_table = g2d_driver_ids,
.driver = {
.name = G2D_NAME,
+ .owner = THIS_MODULE,
.of_match_table = exynos_g2d_match,
},
};
diff --git a/drivers/media/platform/s5p-jpeg/jpeg-core.c b/drivers/media/platform/s5p-jpeg/jpeg-core.c
index 12f7452..e525a7c 100644
--- a/drivers/media/platform/s5p-jpeg/jpeg-core.c
+++ b/drivers/media/platform/s5p-jpeg/jpeg-core.c
@@ -893,7 +893,7 @@
unsigned long buffer, unsigned long size,
struct s5p_jpeg_ctx *ctx)
{
- int c, components = 0, notfound;
+ int c, components, notfound;
unsigned int height, width, word, subsampling = 0;
long length;
struct s5p_jpeg_buffer jpeg_buffer;
@@ -1001,8 +1001,13 @@
sizeof(cap->card));
}
cap->bus_info[0] = 0;
- cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ /*
+ * This is only a mem-to-mem video device. The capture and output
+ * device capability flags are left only for backward compatibility
+ * and are scheduled for removal.
+ */
+ cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M |
+ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
return 0;
}
@@ -2627,7 +2632,6 @@
return 0;
}
-#ifdef CONFIG_PM
static int s5p_jpeg_runtime_suspend(struct device *dev)
{
struct s5p_jpeg *jpeg = dev_get_drvdata(dev);
@@ -2677,9 +2681,7 @@
return 0;
}
-#endif /* CONFIG_PM */
-#ifdef CONFIG_PM_SLEEP
static int s5p_jpeg_suspend(struct device *dev)
{
if (pm_runtime_suspended(dev))
@@ -2695,7 +2697,6 @@
return s5p_jpeg_runtime_resume(dev);
}
-#endif
static const struct dev_pm_ops s5p_jpeg_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(s5p_jpeg_suspend, s5p_jpeg_resume)
@@ -2763,6 +2764,7 @@
.remove = s5p_jpeg_remove,
.driver = {
.of_match_table = of_match_ptr(samsung_jpeg_match),
+ .owner = THIS_MODULE,
.name = S5P_JPEG_M2M_NAME,
.pm = &s5p_jpeg_pm_ops,
},
diff --git a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
index 83e01f3..51cb2dd 100644
--- a/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
+++ b/drivers/media/platform/s5p-mfc/regs-mfc-v6.h
@@ -71,7 +71,6 @@
#define S5P_FIMV_R2H_CMD_ENC_BUFFER_FUL_RET_V6 16
#define S5P_FIMV_R2H_CMD_ERR_RET_V6 32
-#define S5P_FIMV_MFC_BUS_RESET_CTRL 0x7110
#define S5P_FIMV_FW_VERSION_V6 0xf000
#define S5P_FIMV_INSTANCE_ID_V6 0xf008
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index fbfdf03..165bc86 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -159,10 +159,6 @@
}
clear_bit(0, &dev->hw_lock);
spin_unlock_irqrestore(&dev->irqlock, flags);
-
- /* De-init MFC */
- s5p_mfc_deinit_hw(dev);
-
/* Double check if there is at least one instance running.
* If no instance is in memory than no firmware should be present */
if (dev->num_inst > 0) {
@@ -224,14 +220,11 @@
size_t dec_y_addr;
unsigned int frame_type;
- /* Make sure we actually have a new frame before continuing. */
- frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
- if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED)
- return;
dec_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dec_y_adr, dev);
+ frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev);
/* Copy timestamp / timecode from decoded src to dst and set
- appropriate flags. */
+ appropriate flags */
src_buf = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
list_for_each_entry(dst_buf, &ctx->dst_queue, list) {
if (vb2_dma_contig_plane_dma_addr(dst_buf->b, 0) == dec_y_addr) {
@@ -257,11 +250,6 @@
dst_buf->b->v4l2_buf.flags |=
V4L2_BUF_FLAG_BFRAME;
break;
- default:
- /* Don't know how to handle
- S5P_FIMV_DECODE_FRAME_OTHER_FRAME. */
- mfc_debug(2, "Unexpected frame type: %d\n",
- frame_type);
}
break;
}
@@ -346,7 +334,8 @@
ctx->state = MFCINST_RES_CHANGE_INIT;
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err);
- WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+ BUG();
s5p_mfc_clock_off();
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
return;
@@ -418,7 +407,8 @@
clear_work_bit(ctx);
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err);
- WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+ BUG();
s5p_mfc_clock_off();
/* if suspending, wake up device and do not try_run again*/
if (test_bit(0, &dev->enter_suspend))
@@ -465,7 +455,8 @@
break;
}
}
- WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+ BUG();
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
s5p_mfc_clock_off();
wake_up_dev(dev, reason, err);
@@ -519,7 +510,8 @@
}
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
clear_work_bit(ctx);
- WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+ BUG();
s5p_mfc_clock_off();
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
wake_up_ctx(ctx, reason, err);
@@ -557,14 +549,16 @@
} else {
ctx->dpb_flush_flag = 0;
}
- WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+ BUG();
s5p_mfc_clock_off();
wake_up(&ctx->queue);
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
} else {
- WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+ BUG();
s5p_mfc_clock_off();
@@ -641,7 +635,8 @@
mfc_err("post_frame_start() failed\n");
s5p_mfc_hw_call_void(dev->mfc_ops, clear_int_flags, dev);
wake_up_ctx(ctx, reason, err);
- WARN_ON(test_and_clear_bit(0, &dev->hw_lock) == 0);
+ if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+ BUG();
s5p_mfc_clock_off();
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
} else {
@@ -820,7 +815,7 @@
ret = -ENOENT;
goto err_queue_init;
}
- q->mem_ops = &vb2_dma_contig_memops;
+ q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
ret = vb2_queue_init(q);
if (ret) {
@@ -842,7 +837,7 @@
ret = -ENOENT;
goto err_queue_init;
}
- q->mem_ops = &vb2_dma_contig_memops;
+ q->mem_ops = (struct vb2_mem_ops *)&vb2_dma_contig_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY;
ret = vb2_queue_init(q);
if (ret) {
@@ -1289,17 +1284,11 @@
m_dev->int_cond, msecs_to_jiffies(MFC_INT_TIMEOUT));
if (ret == 0) {
mfc_err("Waiting for hardware to finish timed out\n");
- clear_bit(0, &m_dev->enter_suspend);
return -EIO;
}
}
- ret = s5p_mfc_sleep(m_dev);
- if (ret) {
- clear_bit(0, &m_dev->enter_suspend);
- clear_bit(0, &m_dev->hw_lock);
- }
- return ret;
+ return s5p_mfc_sleep(m_dev);
}
static int s5p_mfc_resume(struct device *dev)
@@ -1313,7 +1302,7 @@
}
#endif
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
static int s5p_mfc_runtime_suspend(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
@@ -1516,6 +1505,7 @@
.id_table = mfc_driver_ids,
.driver = {
.name = S5P_MFC_NAME,
+ .owner = THIS_MODULE,
.pm = &s5p_mfc_pm_ops,
.of_match_table = exynos_mfc_match,
},
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index 15f7663..3e41ca1 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_common.h
@@ -237,6 +237,8 @@
/**
* struct s5p_mfc_priv_buf - represents internal used buffer
+ * @alloc: allocation-specific context for each buffer
+ * (videobuf2 allocator)
* @ofs: offset of each buffer, will be used for MFC
* @virt: kernel virtual address, only valid when the
* buffer accessed by driver
@@ -244,6 +246,7 @@
* @size: size of the buffer
*/
struct s5p_mfc_priv_buf {
+ void *alloc;
unsigned long ofs;
void *virt;
dma_addr_t dma;
@@ -337,7 +340,6 @@
struct s5p_mfc_hw_cmds *mfc_cmds;
const struct s5p_mfc_regs *mfc_regs;
enum s5p_mfc_fw_ver fw_ver;
- bool risc_on; /* indicates if RISC is on or off */
};
/**
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 40d8a03..0c885a8 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -129,25 +129,6 @@
return 0;
}
-static int s5p_mfc_bus_reset(struct s5p_mfc_dev *dev)
-{
- unsigned int status;
- unsigned long timeout;
-
- /* Reset */
- mfc_write(dev, 0x1, S5P_FIMV_MFC_BUS_RESET_CTRL);
- timeout = jiffies + msecs_to_jiffies(MFC_BW_TIMEOUT);
- /* Check bus status */
- do {
- if (time_after(jiffies, timeout)) {
- mfc_err("Timeout while resetting MFC.\n");
- return -EIO;
- }
- status = mfc_read(dev, S5P_FIMV_MFC_BUS_RESET_CTRL);
- } while ((status & 0x2) == 0);
- return 0;
-}
-
/* Reset the device */
int s5p_mfc_reset(struct s5p_mfc_dev *dev)
{
@@ -158,6 +139,12 @@
mfc_debug_enter();
if (IS_MFCV6_PLUS(dev)) {
+ /* Reset IP */
+ /* except RISC, reset */
+ mfc_write(dev, 0xFEE, S5P_FIMV_MFC_RESET_V6);
+ /* reset release */
+ mfc_write(dev, 0x0, S5P_FIMV_MFC_RESET_V6);
+
/* Zero Initialization of MFC registers */
mfc_write(dev, 0, S5P_FIMV_RISC2HOST_CMD_V6);
mfc_write(dev, 0, S5P_FIMV_HOST2RISC_CMD_V6);
@@ -166,17 +153,8 @@
for (i = 0; i < S5P_FIMV_REG_CLEAR_COUNT_V6; i++)
mfc_write(dev, 0, S5P_FIMV_REG_CLEAR_BEGIN_V6 + (i*4));
- /* check bus reset control before reset */
- if (dev->risc_on)
- if (s5p_mfc_bus_reset(dev))
- return -EIO;
- /* Reset
- * set RISC_ON to 0 during power_on & wake_up.
- * V6 needs RISC_ON set to 0 during reset also.
- */
- if ((!dev->risc_on) || (!IS_MFCV7_PLUS(dev)))
- mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
-
+ /* Reset */
+ mfc_write(dev, 0, S5P_FIMV_RISC_ON_V6);
mfc_write(dev, 0x1FFF, S5P_FIMV_MFC_RESET_V6);
mfc_write(dev, 0, S5P_FIMV_MFC_RESET_V6);
} else {
@@ -248,7 +226,6 @@
/* 0. MFC reset */
mfc_debug(2, "MFC reset..\n");
s5p_mfc_clock_on();
- dev->risc_on = 0;
ret = s5p_mfc_reset(dev);
if (ret) {
mfc_err("Failed to reset MFC - timeout\n");
@@ -261,10 +238,8 @@
s5p_mfc_clear_cmds(dev);
/* 3. Release reset signal to the RISC */
s5p_mfc_clean_dev_int_flags(dev);
- if (IS_MFCV6_PLUS(dev)) {
- dev->risc_on = 1;
+ if (IS_MFCV6_PLUS(dev))
mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
- }
else
mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
mfc_debug(2, "Will now wait for completion of firmware transfer\n");
@@ -353,58 +328,6 @@
return ret;
}
-static int s5p_mfc_v8_wait_wakeup(struct s5p_mfc_dev *dev)
-{
- int ret;
-
- /* Release reset signal to the RISC */
- dev->risc_on = 1;
- mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
-
- if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_FW_STATUS_RET)) {
- mfc_err("Failed to reset MFCV8\n");
- return -EIO;
- }
- mfc_debug(2, "Write command to wakeup MFCV8\n");
- ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
- if (ret) {
- mfc_err("Failed to send command to MFCV8 - timeout\n");
- return ret;
- }
-
- if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
- mfc_err("Failed to wakeup MFC\n");
- return -EIO;
- }
- return ret;
-}
-
-static int s5p_mfc_wait_wakeup(struct s5p_mfc_dev *dev)
-{
- int ret;
-
- /* Send MFC wakeup command */
- ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
- if (ret) {
- mfc_err("Failed to send command to MFC - timeout\n");
- return ret;
- }
-
- /* Release reset signal to the RISC */
- if (IS_MFCV6_PLUS(dev)) {
- dev->risc_on = 1;
- mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
- } else {
- mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
- }
-
- if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
- mfc_err("Failed to wakeup MFC\n");
- return -EIO;
- }
- return ret;
-}
-
int s5p_mfc_wakeup(struct s5p_mfc_dev *dev)
{
int ret;
@@ -413,11 +336,9 @@
/* 0. MFC reset */
mfc_debug(2, "MFC reset..\n");
s5p_mfc_clock_on();
- dev->risc_on = 0;
ret = s5p_mfc_reset(dev);
if (ret) {
mfc_err("Failed to reset MFC - timeout\n");
- s5p_mfc_clock_off();
return ret;
}
mfc_debug(2, "Done MFC reset..\n");
@@ -426,16 +347,23 @@
/* 2. Initialize registers of channel I/F */
s5p_mfc_clear_cmds(dev);
s5p_mfc_clean_dev_int_flags(dev);
- /* 3. Send MFC wakeup command and wait for completion*/
- if (IS_MFCV8(dev))
- ret = s5p_mfc_v8_wait_wakeup(dev);
- else
- ret = s5p_mfc_wait_wakeup(dev);
-
- s5p_mfc_clock_off();
- if (ret)
+ /* 3. Initialize firmware */
+ ret = s5p_mfc_hw_call(dev->mfc_cmds, wakeup_cmd, dev);
+ if (ret) {
+ mfc_err("Failed to send command to MFC - timeout\n");
return ret;
-
+ }
+ /* 4. Release reset signal to the RISC */
+ if (IS_MFCV6_PLUS(dev))
+ mfc_write(dev, 0x1, S5P_FIMV_RISC_ON_V6);
+ else
+ mfc_write(dev, 0x3ff, S5P_FIMV_SW_RESET);
+ mfc_debug(2, "Ok, now will write a command to wakeup the system\n");
+ if (s5p_mfc_wait_for_done_dev(dev, S5P_MFC_R2H_CMD_WAKEUP_RET)) {
+ mfc_err("Failed to load firmware\n");
+ return -EIO;
+ }
+ s5p_mfc_clock_off();
dev->int_cond = 0;
if (dev->int_err != 0 || dev->int_type !=
S5P_MFC_R2H_CMD_WAKEUP_RET) {
@@ -468,6 +396,7 @@
}
set_work_bit_irqsave(ctx);
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
if (s5p_mfc_wait_for_done_ctx(ctx,
S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
@@ -493,6 +422,7 @@
{
ctx->state = MFCINST_RETURN_INST;
set_work_bit_irqsave(ctx);
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
/* Wait until instance is returned or timeout occurred */
if (s5p_mfc_wait_for_done_ctx(ctx,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index c6c3452..a98fe02 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -269,13 +269,15 @@
strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1);
strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
cap->bus_info[0] = 0;
+ cap->version = KERNEL_VERSION(1, 0, 0);
/*
* This is only a mem-to-mem video device. The capture and output
* device capability flags are left only for backward compatibility
* and are scheduled for removal.
*/
- cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING |
+ V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+ V4L2_CAP_VIDEO_OUTPUT_MPLANE;
return 0;
}
@@ -332,6 +334,7 @@
MFCINST_RES_CHANGE_END)) {
/* If the MFC is parsing the header,
* so wait until it is finished */
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
0);
}
@@ -737,12 +740,12 @@
ctx->state < MFCINST_ABORT) {
ctrl->val = ctx->pb_count;
break;
- } else if (ctx->state != MFCINST_INIT &&
- ctx->state != MFCINST_RES_CHANGE_END) {
+ } else if (ctx->state != MFCINST_INIT) {
v4l2_err(&dev->v4l2_dev, "Decoding not initialised\n");
return -EINVAL;
}
/* Should wait for the header to be parsed */
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_wait_for_done_ctx(ctx,
S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
if (ctx->state >= MFCINST_HEAD_PARSED &&
@@ -1054,6 +1057,7 @@
if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) {
ctx->state = MFCINST_FLUSH;
set_work_bit_irqsave(ctx);
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
if (s5p_mfc_wait_for_done_ctx(ctx,
S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0))
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index bd64f1d..a904a1c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
@@ -32,7 +32,7 @@
#include "s5p_mfc_intr.h"
#include "s5p_mfc_opr.h"
-#define DEF_SRC_FMT_ENC V4L2_PIX_FMT_NV12M
+#define DEF_SRC_FMT_ENC V4L2_PIX_FMT_NV12MT
#define DEF_DST_FMT_ENC V4L2_PIX_FMT_H264
static struct s5p_mfc_fmt formats[] = {
@@ -67,7 +67,8 @@
.codec_mode = S5P_MFC_CODEC_NONE,
.type = MFC_FMT_RAW,
.num_planes = 2,
- .versions = MFC_V6_BIT | MFC_V7_BIT | MFC_V8_BIT,
+ .versions = MFC_V5_BIT | MFC_V6_BIT | MFC_V7_BIT |
+ MFC_V8_BIT,
},
{
.name = "H264 Encoded Stream",
@@ -689,16 +690,6 @@
.step = 1,
.default_value = 0,
},
- {
- .id = V4L2_CID_MIN_BUFFERS_FOR_OUTPUT,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "Minimum number of output bufs",
- .minimum = 1,
- .maximum = 32,
- .step = 1,
- .default_value = 1,
- .is_volatile = 1,
- },
};
#define NUM_CTRLS ARRAY_SIZE(controls)
@@ -947,13 +938,15 @@
strncpy(cap->driver, dev->plat_dev->name, sizeof(cap->driver) - 1);
strncpy(cap->card, dev->plat_dev->name, sizeof(cap->card) - 1);
cap->bus_info[0] = 0;
+ cap->version = KERNEL_VERSION(1, 0, 0);
/*
* This is only a mem-to-mem video device. The capture and output
* device capability flags are left only for backward compatibility
* and are scheduled for removal.
*/
- cap->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING |
+ V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+ V4L2_CAP_VIDEO_OUTPUT_MPLANE;
return 0;
}
@@ -1144,11 +1137,6 @@
(reqbufs->memory != V4L2_MEMORY_USERPTR))
return -EINVAL;
if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- if (reqbufs->count == 0) {
- ret = vb2_reqbufs(&ctx->vq_dst, reqbufs);
- ctx->capture_state = QUEUE_FREE;
- return ret;
- }
if (ctx->capture_state != QUEUE_FREE) {
mfc_err("invalid capture state: %d\n",
ctx->capture_state);
@@ -1170,14 +1158,6 @@
return -ENOMEM;
}
} else if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
- if (reqbufs->count == 0) {
- mfc_debug(2, "Freeing buffers\n");
- ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
- s5p_mfc_hw_call_void(dev->mfc_ops, release_codec_buffers,
- ctx);
- ctx->output_state = QUEUE_FREE;
- return ret;
- }
if (ctx->output_state != QUEUE_FREE) {
mfc_err("invalid output state: %d\n",
ctx->output_state);
@@ -1644,39 +1624,8 @@
return ret;
}
-static int s5p_mfc_enc_g_v_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct s5p_mfc_ctx *ctx = ctrl_to_ctx(ctrl);
- struct s5p_mfc_dev *dev = ctx->dev;
-
- switch (ctrl->id) {
- case V4L2_CID_MIN_BUFFERS_FOR_OUTPUT:
- if (ctx->state >= MFCINST_HEAD_PARSED &&
- ctx->state < MFCINST_ABORT) {
- ctrl->val = ctx->pb_count;
- break;
- } else if (ctx->state != MFCINST_INIT) {
- v4l2_err(&dev->v4l2_dev, "Encoding not initialised\n");
- return -EINVAL;
- }
- /* Should wait for the header to be produced */
- s5p_mfc_wait_for_done_ctx(ctx,
- S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
- if (ctx->state >= MFCINST_HEAD_PARSED &&
- ctx->state < MFCINST_ABORT) {
- ctrl->val = ctx->pb_count;
- } else {
- v4l2_err(&dev->v4l2_dev, "Encoding not initialised\n");
- return -EINVAL;
- }
- break;
- }
- return 0;
-}
-
static const struct v4l2_ctrl_ops s5p_mfc_enc_ctrl_ops = {
.s_ctrl = s5p_mfc_enc_s_ctrl,
- .g_volatile_ctrl = s5p_mfc_enc_g_v_ctrl,
};
static int vidioc_s_parm(struct file *file, void *priv,
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
index 0c4fcf2..7cf0796 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
@@ -1178,6 +1178,7 @@
s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
}
@@ -1191,6 +1192,7 @@
last_frame = MFC_DEC_LAST_FRAME;
s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_decode_one_frame_v5(ctx, last_frame);
return 0;
}
@@ -1210,6 +1212,7 @@
ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
last_frame = MFC_DEC_LAST_FRAME;
mfc_debug(2, "Setting ctx->state to FINISHING\n");
@@ -1270,6 +1273,7 @@
s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
mfc_debug(2, "encoding buffer with index=%d state=%d\n",
src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
s5p_mfc_encode_one_frame_v5(ctx);
@@ -1293,6 +1297,7 @@
0, temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_init_decode_v5(ctx);
}
@@ -1312,6 +1317,7 @@
s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_init_encode_v5(ctx);
}
@@ -1346,6 +1352,7 @@
0, temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
if (ret) {
mfc_err("Failed to alloc frame mem\n");
@@ -1389,8 +1396,6 @@
* Now obtaining frames from MFC buffer
*/
s5p_mfc_clock_on();
- s5p_mfc_clean_ctx_int_flags(ctx);
-
if (ctx->type == MFCINST_DECODER) {
s5p_mfc_set_dec_desc_buffer(ctx);
switch (ctx->state) {
@@ -1401,10 +1406,12 @@
ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
break;
case MFCINST_INIT:
+ s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
ctx);
break;
case MFCINST_RETURN_INST:
+ s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
ctx);
break;
@@ -1437,10 +1444,12 @@
ret = s5p_mfc_run_enc_frame(ctx);
break;
case MFCINST_INIT:
+ s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
ctx);
break;
case MFCINST_RETURN_INST:
+ s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
ctx);
break;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
index 9aea179..8798b14 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c
@@ -1394,6 +1394,7 @@
if (flush) {
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
writel(ctx->inst_no, mfc_regs->instance_id);
s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev,
S5P_FIMV_H2R_CMD_FLUSH_V6, NULL);
@@ -1531,10 +1532,27 @@
static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
{
struct s5p_mfc_dev *dev = ctx->dev;
+ struct s5p_mfc_buf *temp_vb;
+ unsigned long flags;
- s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0);
+ spin_lock_irqsave(&dev->irqlock, flags);
+
+ /* Frames are being decoded */
+ if (list_empty(&ctx->src_queue)) {
+ mfc_debug(2, "No src buffers.\n");
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+ return;
+ }
+ /* Get the next source buffer */
+ temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
+ temp_vb->flags |= MFC_BUF_FLAG_USED;
+ s5p_mfc_set_dec_stream_buffer_v6(ctx,
+ vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), 0, 0);
+ spin_unlock_irqrestore(&dev->irqlock, flags);
+
dev->curr_ctx = ctx->num;
- s5p_mfc_decode_one_frame_v6(ctx, MFC_DEC_LAST_FRAME);
+ s5p_mfc_clean_ctx_int_flags(ctx);
+ s5p_mfc_decode_one_frame_v6(ctx, 1);
}
static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
@@ -1570,6 +1588,7 @@
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
last_frame = 1;
mfc_debug(2, "Setting ctx->state to FINISHING\n");
@@ -1626,6 +1645,7 @@
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_encode_one_frame_v6(ctx);
return 0;
@@ -1647,6 +1667,7 @@
temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_init_decode_v6(ctx);
}
@@ -1666,6 +1687,7 @@
s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_init_encode_v6(ctx);
}
@@ -1685,6 +1707,7 @@
}
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
if (ret) {
mfc_err("Failed to alloc frame mem.\n");
@@ -1699,6 +1722,7 @@
int ret;
dev->curr_ctx = ctx->num;
+ s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
if (ret) {
mfc_err("Failed to alloc frame mem.\n");
@@ -1747,8 +1771,6 @@
* Now obtaining frames from MFC buffer */
s5p_mfc_clock_on();
- s5p_mfc_clean_ctx_int_flags(ctx);
-
if (ctx->type == MFCINST_DECODER) {
switch (ctx->state) {
case MFCINST_FINISHING:
@@ -1758,10 +1780,12 @@
ret = s5p_mfc_run_dec_frame(ctx);
break;
case MFCINST_INIT:
+ s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
ctx);
break;
case MFCINST_RETURN_INST:
+ s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
ctx);
break;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 5f97a33..826c489 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -13,7 +13,9 @@
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/platform_device.h>
+#ifdef CONFIG_PM_RUNTIME
#include <linux/pm_runtime.h>
+#endif
#include "s5p_mfc_common.h"
#include "s5p_mfc_debug.h"
#include "s5p_mfc_pm.h"
@@ -65,7 +67,7 @@
}
atomic_set(&pm->power, 0);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
pm->device = &dev->plat_dev->dev;
pm_runtime_enable(pm->device);
#endif
@@ -91,7 +93,7 @@
}
clk_unprepare(pm->clock_gate);
clk_put(pm->clock_gate);
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
pm_runtime_disable(pm->device);
#endif
}
@@ -118,7 +120,7 @@
int s5p_mfc_power_on(void)
{
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
return pm_runtime_get_sync(pm->device);
#else
atomic_set(&pm->power, 1);
@@ -128,7 +130,7 @@
int s5p_mfc_power_off(void)
{
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
return pm_runtime_put_sync(pm->device);
#else
atomic_set(&pm->power, 0);
diff --git a/drivers/media/platform/s5p-tv/Kconfig b/drivers/media/platform/s5p-tv/Kconfig
index 8f78739..c22aac6 100644
--- a/drivers/media/platform/s5p-tv/Kconfig
+++ b/drivers/media/platform/s5p-tv/Kconfig
@@ -8,8 +8,8 @@
config VIDEO_SAMSUNG_S5P_TV
bool "Samsung TV driver for S5P platform"
- depends on PM
- depends on ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
+ depends on PM_RUNTIME
+ depends on PLAT_S5P || ARCH_EXYNOS || COMPILE_TEST
default n
---help---
Say Y here to enable selecting the TV output devices for
diff --git a/drivers/media/platform/s5p-tv/hdmi_drv.c b/drivers/media/platform/s5p-tv/hdmi_drv.c
index c78b0cf..1434ba4 100644
--- a/drivers/media/platform/s5p-tv/hdmi_drv.c
+++ b/drivers/media/platform/s5p-tv/hdmi_drv.c
@@ -660,7 +660,7 @@
memset(fmt, 0, sizeof(*fmt));
fmt->width = t->hact.end - t->hact.beg;
fmt->height = t->vact[0].end - t->vact[0].beg;
- fmt->code = MEDIA_BUS_FMT_FIXED; /* means RGB888 */
+ fmt->code = V4L2_MBUS_FMT_FIXED; /* means RGB888 */
fmt->colorspace = V4L2_COLORSPACE_SRGB;
if (t->interlaced) {
fmt->field = V4L2_FIELD_INTERLACED;
@@ -1046,6 +1046,7 @@
.id_table = hdmi_driver_types,
.driver = {
.name = "s5p-hdmi",
+ .owner = THIS_MODULE,
.pm = &hdmi_pm_ops,
}
};
diff --git a/drivers/media/platform/s5p-tv/mixer_drv.c b/drivers/media/platform/s5p-tv/mixer_drv.c
index 2a9501d..bc08b5f 100644
--- a/drivers/media/platform/s5p-tv/mixer_drv.c
+++ b/drivers/media/platform/s5p-tv/mixer_drv.c
@@ -487,6 +487,7 @@
.remove = mxr_remove,
.driver = {
.name = MXR_DRIVER_NAME,
+ .owner = THIS_MODULE,
.pm = &mxr_pm_ops,
}
};
diff --git a/drivers/media/platform/s5p-tv/sdo_drv.c b/drivers/media/platform/s5p-tv/sdo_drv.c
index 3621af9..72cf892 100644
--- a/drivers/media/platform/s5p-tv/sdo_drv.c
+++ b/drivers/media/platform/s5p-tv/sdo_drv.c
@@ -170,7 +170,7 @@
/* all modes are 720 pixels wide */
fmt->width = 720;
fmt->height = sdev->fmt->height;
- fmt->code = MEDIA_BUS_FMT_FIXED;
+ fmt->code = V4L2_MBUS_FMT_FIXED;
fmt->field = V4L2_FIELD_INTERLACED;
fmt->colorspace = V4L2_COLORSPACE_JPEG;
return 0;
@@ -482,6 +482,7 @@
.remove = sdo_remove,
.driver = {
.name = "s5p-sdo",
+ .owner = THIS_MODULE,
.pm = &sdo_pm_ops,
}
};
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index aaa1f6f..be3b3bc 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -1235,6 +1235,7 @@
.remove = sh_veu_remove,
.driver = {
.name = "sh_veu",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/media/platform/sh_vou.c b/drivers/media/platform/sh_vou.c
index 261f119..e5f1d4c 100644
--- a/drivers/media/platform/sh_vou.c
+++ b/drivers/media/platform/sh_vou.c
@@ -396,8 +396,7 @@
dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
strlcpy(cap->card, "SuperH VOU", sizeof(cap->card));
- cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+ cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
return 0;
}
@@ -681,7 +680,7 @@
struct sh_vou_geometry geo;
struct v4l2_mbus_framefmt mbfmt = {
/* Revisit: is this the correct code? */
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
.field = V4L2_FIELD_INTERLACED,
.colorspace = V4L2_COLORSPACE_SMPTE170M,
};
@@ -734,7 +733,7 @@
/* Sanity checks */
if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH ||
(unsigned)mbfmt.height > img_height_max ||
- mbfmt.code != MEDIA_BUS_FMT_YUYV8_2X8)
+ mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8)
return -EIO;
if (mbfmt.width != geo.output.width ||
@@ -944,7 +943,7 @@
struct sh_vou_geometry geo;
struct v4l2_mbus_framefmt mbfmt = {
/* Revisit: is this the correct code? */
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
.field = V4L2_FIELD_INTERLACED,
.colorspace = V4L2_COLORSPACE_SMPTE170M,
};
@@ -995,7 +994,7 @@
/* Sanity checks */
if ((unsigned)mbfmt.width > VOU_MAX_IMAGE_WIDTH ||
(unsigned)mbfmt.height > img_height_max ||
- mbfmt.code != MEDIA_BUS_FMT_YUYV8_2X8)
+ mbfmt.code != V4L2_MBUS_FMT_YUYV8_2X8)
return -EIO;
geo.output.width = mbfmt.width;
@@ -1450,6 +1449,7 @@
.remove = sh_vou_remove,
.driver = {
.name = "sh-vou",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
index fa5bceb..aebae21 100644
--- a/drivers/media/platform/soc_camera/Kconfig
+++ b/drivers/media/platform/soc_camera/Kconfig
@@ -1,6 +1,6 @@
config SOC_CAMERA
- depends on !KERNEL_3_4
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_5
tristate "SoC camera support"
depends on m
depends on VIDEO_V4L2 && HAS_DMA && I2C
diff --git a/drivers/media/platform/soc_camera/atmel-isi.c b/drivers/media/platform/soc_camera/atmel-isi.c
index 8efe403..c5291b0 100644
--- a/drivers/media/platform/soc_camera/atmel-isi.c
+++ b/drivers/media/platform/soc_camera/atmel-isi.c
@@ -105,25 +105,25 @@
}
static int configure_geometry(struct atmel_isi *isi, u32 width,
- u32 height, u32 code)
+ u32 height, enum v4l2_mbus_pixelcode code)
{
u32 cfg2, cr;
switch (code) {
/* YUV, including grey */
- case MEDIA_BUS_FMT_Y8_1X8:
+ case V4L2_MBUS_FMT_Y8_1X8:
cr = ISI_CFG2_GRAYSCALE;
break;
- case MEDIA_BUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
cr = ISI_CFG2_YCC_SWAP_MODE_3;
break;
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
cr = ISI_CFG2_YCC_SWAP_MODE_2;
break;
- case MEDIA_BUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
cr = ISI_CFG2_YCC_SWAP_MODE_1;
break;
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
cr = ISI_CFG2_YCC_SWAP_DEFAULT;
break;
/* RGB, TODO */
@@ -645,7 +645,7 @@
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
int formats = 0, ret;
/* sensor format */
- u32 code;
+ enum v4l2_mbus_pixelcode code;
/* soc camera host format */
const struct soc_mbus_pixelfmt *fmt;
@@ -670,10 +670,10 @@
}
switch (code) {
- case MEDIA_BUS_FMT_UYVY8_2X8:
- case MEDIA_BUS_FMT_VYUY8_2X8:
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
formats++;
if (xlate) {
xlate->host_fmt = &isi_camera_formats[0];
@@ -1068,6 +1068,7 @@
.remove = atmel_isi_remove,
.driver = {
.name = "atmel_isi",
+ .owner = THIS_MODULE,
.of_match_table = of_match_ptr(atmel_isi_of_match),
},
};
diff --git a/drivers/media/platform/soc_camera/mx2_camera.c b/drivers/media/platform/soc_camera/mx2_camera.c
index ce72bd2..2347612 100644
--- a/drivers/media/platform/soc_camera/mx2_camera.c
+++ b/drivers/media/platform/soc_camera/mx2_camera.c
@@ -211,7 +211,7 @@
/* prp configuration for a client-host fmt pair */
struct mx2_fmt_cfg {
- u32 in_fmt;
+ enum v4l2_mbus_pixelcode in_fmt;
u32 out_fmt;
struct mx2_prp_cfg cfg;
};
@@ -309,7 +309,7 @@
}
},
{
- .in_fmt = MEDIA_BUS_FMT_UYVY8_2X8,
+ .in_fmt = V4L2_MBUS_FMT_UYVY8_2X8,
.out_fmt = V4L2_PIX_FMT_YUYV,
.cfg = {
.channel = 1,
@@ -323,7 +323,7 @@
}
},
{
- .in_fmt = MEDIA_BUS_FMT_YUYV8_2X8,
+ .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8,
.out_fmt = V4L2_PIX_FMT_YUYV,
.cfg = {
.channel = 1,
@@ -337,7 +337,7 @@
}
},
{
- .in_fmt = MEDIA_BUS_FMT_YUYV8_2X8,
+ .in_fmt = V4L2_MBUS_FMT_YUYV8_2X8,
.out_fmt = V4L2_PIX_FMT_YUV420,
.cfg = {
.channel = 2,
@@ -351,7 +351,7 @@
}
},
{
- .in_fmt = MEDIA_BUS_FMT_UYVY8_2X8,
+ .in_fmt = V4L2_MBUS_FMT_UYVY8_2X8,
.out_fmt = V4L2_PIX_FMT_YUV420,
.cfg = {
.channel = 2,
@@ -366,7 +366,9 @@
},
};
-static struct mx2_fmt_cfg *mx27_emma_prp_get_format(u32 in_fmt, u32 out_fmt)
+static struct mx2_fmt_cfg *mx27_emma_prp_get_format(
+ enum v4l2_mbus_pixelcode in_fmt,
+ u32 out_fmt)
{
int i;
@@ -943,7 +945,7 @@
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
const struct soc_mbus_pixelfmt *fmt;
struct device *dev = icd->parent;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
int ret, formats = 0;
ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -957,8 +959,8 @@
return 0;
}
- if (code == MEDIA_BUS_FMT_YUYV8_2X8 ||
- code == MEDIA_BUS_FMT_UYVY8_2X8) {
+ if (code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+ code == V4L2_MBUS_FMT_UYVY8_2X8) {
formats++;
if (xlate) {
/*
@@ -966,7 +968,7 @@
* soc_mediabus.c
*/
xlate->host_fmt =
- soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_1_5X8);
+ soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_1_5X8);
xlate->code = code;
dev_dbg(dev, "Providing host format %s for sensor code %d\n",
xlate->host_fmt->name, code);
@@ -974,11 +976,11 @@
}
}
- if (code == MEDIA_BUS_FMT_UYVY8_2X8) {
+ if (code == V4L2_MBUS_FMT_UYVY8_2X8) {
formats++;
if (xlate) {
xlate->host_fmt =
- soc_mbus_get_fmtdesc(MEDIA_BUS_FMT_YUYV8_2X8);
+ soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_2X8);
xlate->code = code;
dev_dbg(dev, "Providing host format %s for sensor code %d\n",
xlate->host_fmt->name, code);
diff --git a/drivers/media/platform/soc_camera/mx3_camera.c b/drivers/media/platform/soc_camera/mx3_camera.c
index a60c3bb..7696a87 100644
--- a/drivers/media/platform/soc_camera/mx3_camera.c
+++ b/drivers/media/platform/soc_camera/mx3_camera.c
@@ -656,7 +656,7 @@
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
int formats = 0, ret;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
const struct soc_mbus_pixelfmt *fmt;
ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -677,7 +677,7 @@
return 0;
switch (code) {
- case MEDIA_BUS_FMT_SBGGR10_1X10:
+ case V4L2_MBUS_FMT_SBGGR10_1X10:
formats++;
if (xlate) {
xlate->host_fmt = &mx3_camera_formats[0];
@@ -687,7 +687,7 @@
mx3_camera_formats[0].name, code);
}
break;
- case MEDIA_BUS_FMT_Y10_1X10:
+ case V4L2_MBUS_FMT_Y10_1X10:
formats++;
if (xlate) {
xlate->host_fmt = &mx3_camera_formats[1];
@@ -1253,6 +1253,7 @@
static struct platform_driver mx3_camera_driver = {
.driver = {
.name = MX3_CAM_DRV_NAME,
+ .owner = THIS_MODULE,
},
.probe = mx3_camera_probe,
.remove = mx3_camera_remove,
diff --git a/drivers/media/platform/soc_camera/omap1_camera.c b/drivers/media/platform/soc_camera/omap1_camera.c
index e6b9328..74ce8b6 100644
--- a/drivers/media/platform/soc_camera/omap1_camera.c
+++ b/drivers/media/platform/soc_camera/omap1_camera.c
@@ -140,7 +140,7 @@
/* buffer for one video frame */
struct omap1_cam_buf {
struct videobuf_buffer vb;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
int inwork;
struct scatterlist *sgbuf;
int sgcount;
@@ -980,7 +980,7 @@
/* Duplicate standard formats based on host capability of byte swapping */
static const struct soc_mbus_lookup omap1_cam_formats[] = {
{
- .code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .code = V4L2_MBUS_FMT_UYVY8_2X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_YUYV,
.name = "YUYV",
@@ -990,7 +990,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .code = V4L2_MBUS_FMT_VYUY8_2X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_YVYU,
.name = "YVYU",
@@ -1000,7 +1000,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_UYVY,
.name = "UYVY",
@@ -1010,7 +1010,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_YVYU8_2X8,
+ .code = V4L2_MBUS_FMT_YVYU8_2X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_VYUY,
.name = "VYUY",
@@ -1020,7 +1020,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+ .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB555,
.name = "RGB555",
@@ -1030,7 +1030,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+ .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB555X,
.name = "RGB555X",
@@ -1040,7 +1040,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+ .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB565,
.name = "RGB565",
@@ -1050,7 +1050,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+ .code = V4L2_MBUS_FMT_RGB565_2X8_LE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB565X,
.name = "RGB565X",
@@ -1068,7 +1068,7 @@
struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
struct device *dev = icd->parent;
int formats = 0, ret;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
const struct soc_mbus_pixelfmt *fmt;
ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -1088,14 +1088,14 @@
return 0;
switch (code) {
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_YVYU8_2X8:
- case MEDIA_BUS_FMT_UYVY8_2X8:
- case MEDIA_BUS_FMT_VYUY8_2X8:
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
+ case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
+ case V4L2_MBUS_FMT_RGB565_2X8_BE:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
formats++;
if (xlate) {
xlate->host_fmt = soc_mbus_find_fmtdesc(code,
diff --git a/drivers/media/platform/soc_camera/pxa_camera.c b/drivers/media/platform/soc_camera/pxa_camera.c
index 951226a..66178fc 100644
--- a/drivers/media/platform/soc_camera/pxa_camera.c
+++ b/drivers/media/platform/soc_camera/pxa_camera.c
@@ -187,7 +187,7 @@
struct pxa_buffer {
/* common v4l buffer stuff -- must be first */
struct videobuf_buffer vb;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
/* our descriptor lists for Y, U and V channels */
struct pxa_cam_dma dmas[3];
int inwork;
@@ -1253,7 +1253,7 @@
struct device *dev = icd->parent;
int formats = 0, ret;
struct pxa_cam *cam;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
const struct soc_mbus_pixelfmt *fmt;
ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -1283,7 +1283,7 @@
}
switch (code) {
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
formats++;
if (xlate) {
xlate->host_fmt = &pxa_camera_formats[0];
@@ -1292,11 +1292,11 @@
dev_dbg(dev, "Providing format %s using code %d\n",
pxa_camera_formats[0].name, code);
}
- case MEDIA_BUS_FMT_VYUY8_2X8:
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_YVYU8_2X8:
- case MEDIA_BUS_FMT_RGB565_2X8_LE:
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_RGB565_2X8_LE:
+ case V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE:
if (xlate)
dev_dbg(dev, "Providing format %s packed\n",
fmt->name);
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index 0c1f556..20defcb 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -64,30 +64,6 @@
#define VNDMR_REG 0x58 /* Video n Data Mode Register */
#define VNDMR2_REG 0x5C /* Video n Data Mode Register 2 */
#define VNUVAOF_REG 0x60 /* Video n UV Address Offset Register */
-#define VNC1A_REG 0x80 /* Video n Coefficient Set C1A Register */
-#define VNC1B_REG 0x84 /* Video n Coefficient Set C1B Register */
-#define VNC1C_REG 0x88 /* Video n Coefficient Set C1C Register */
-#define VNC2A_REG 0x90 /* Video n Coefficient Set C2A Register */
-#define VNC2B_REG 0x94 /* Video n Coefficient Set C2B Register */
-#define VNC2C_REG 0x98 /* Video n Coefficient Set C2C Register */
-#define VNC3A_REG 0xA0 /* Video n Coefficient Set C3A Register */
-#define VNC3B_REG 0xA4 /* Video n Coefficient Set C3B Register */
-#define VNC3C_REG 0xA8 /* Video n Coefficient Set C3C Register */
-#define VNC4A_REG 0xB0 /* Video n Coefficient Set C4A Register */
-#define VNC4B_REG 0xB4 /* Video n Coefficient Set C4B Register */
-#define VNC4C_REG 0xB8 /* Video n Coefficient Set C4C Register */
-#define VNC5A_REG 0xC0 /* Video n Coefficient Set C5A Register */
-#define VNC5B_REG 0xC4 /* Video n Coefficient Set C5B Register */
-#define VNC5C_REG 0xC8 /* Video n Coefficient Set C5C Register */
-#define VNC6A_REG 0xD0 /* Video n Coefficient Set C6A Register */
-#define VNC6B_REG 0xD4 /* Video n Coefficient Set C6B Register */
-#define VNC6C_REG 0xD8 /* Video n Coefficient Set C6C Register */
-#define VNC7A_REG 0xE0 /* Video n Coefficient Set C7A Register */
-#define VNC7B_REG 0xE4 /* Video n Coefficient Set C7B Register */
-#define VNC7C_REG 0xE8 /* Video n Coefficient Set C7C Register */
-#define VNC8A_REG 0xF0 /* Video n Coefficient Set C8A Register */
-#define VNC8B_REG 0xF4 /* Video n Coefficient Set C8B Register */
-#define VNC8C_REG 0xF8 /* Video n Coefficient Set C8C Register */
/* Register bit fields for R-Car VIN */
/* Video n Main Control Register bits */
@@ -130,7 +106,6 @@
#define VNDMR2_VPS (1 << 30)
#define VNDMR2_HPS (1 << 29)
#define VNDMR2_FTEV (1 << 17)
-#define VNDMR2_VLV(n) ((n & 0xf) << 12)
#define VIN_MAX_WIDTH 2048
#define VIN_MAX_HEIGHT 2048
@@ -142,324 +117,6 @@
RCAR_E1,
};
-struct vin_coeff {
- unsigned short xs_value;
- u32 coeff_set[24];
-};
-
-static const struct vin_coeff vin_coeff_set[] = {
- { 0x0000, {
- 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000 },
- },
- { 0x1000, {
- 0x000fa400, 0x000fa400, 0x09625902,
- 0x000003f8, 0x00000403, 0x3de0d9f0,
- 0x001fffed, 0x00000804, 0x3cc1f9c3,
- 0x001003de, 0x00000c01, 0x3cb34d7f,
- 0x002003d2, 0x00000c00, 0x3d24a92d,
- 0x00200bca, 0x00000bff, 0x3df600d2,
- 0x002013cc, 0x000007ff, 0x3ed70c7e,
- 0x00100fde, 0x00000000, 0x3f87c036 },
- },
- { 0x1200, {
- 0x002ffff1, 0x002ffff1, 0x02a0a9c8,
- 0x002003e7, 0x001ffffa, 0x000185bc,
- 0x002007dc, 0x000003ff, 0x3e52859c,
- 0x00200bd4, 0x00000002, 0x3d53996b,
- 0x00100fd0, 0x00000403, 0x3d04ad2d,
- 0x00000bd5, 0x00000403, 0x3d35ace7,
- 0x3ff003e4, 0x00000801, 0x3dc674a1,
- 0x3fffe800, 0x00000800, 0x3e76f461 },
- },
- { 0x1400, {
- 0x00100be3, 0x00100be3, 0x04d1359a,
- 0x00000fdb, 0x002003ed, 0x0211fd93,
- 0x00000fd6, 0x002003f4, 0x0002d97b,
- 0x000007d6, 0x002ffffb, 0x3e93b956,
- 0x3ff003da, 0x001003ff, 0x3db49926,
- 0x3fffefe9, 0x00100001, 0x3d655cee,
- 0x3fffd400, 0x00000003, 0x3d65f4b6,
- 0x000fb421, 0x00000402, 0x3dc6547e },
- },
- { 0x1600, {
- 0x00000bdd, 0x00000bdd, 0x06519578,
- 0x3ff007da, 0x00000be3, 0x03c24973,
- 0x3ff003d9, 0x00000be9, 0x01b30d5f,
- 0x3ffff7df, 0x001003f1, 0x0003c542,
- 0x000fdfec, 0x001003f7, 0x3ec4711d,
- 0x000fc400, 0x002ffffd, 0x3df504f1,
- 0x001fa81a, 0x002ffc00, 0x3d957cc2,
- 0x002f8c3c, 0x00100000, 0x3db5c891 },
- },
- { 0x1800, {
- 0x3ff003dc, 0x3ff003dc, 0x0791e558,
- 0x000ff7dd, 0x3ff007de, 0x05328554,
- 0x000fe7e3, 0x3ff00be2, 0x03232546,
- 0x000fd7ee, 0x000007e9, 0x0143bd30,
- 0x001fb800, 0x000007ee, 0x00044511,
- 0x002fa015, 0x000007f4, 0x3ef4bcee,
- 0x002f8832, 0x001003f9, 0x3e4514c7,
- 0x001f7853, 0x001003fd, 0x3de54c9f },
- },
- { 0x1a00, {
- 0x000fefe0, 0x000fefe0, 0x08721d3c,
- 0x001fdbe7, 0x000ffbde, 0x0652a139,
- 0x001fcbf0, 0x000003df, 0x0463292e,
- 0x002fb3ff, 0x3ff007e3, 0x0293a91d,
- 0x002f9c12, 0x3ff00be7, 0x01241905,
- 0x001f8c29, 0x000007ed, 0x3fe470eb,
- 0x000f7c46, 0x000007f2, 0x3f04b8ca,
- 0x3fef7865, 0x000007f6, 0x3e74e4a8 },
- },
- { 0x1c00, {
- 0x001fd3e9, 0x001fd3e9, 0x08f23d26,
- 0x002fbff3, 0x001fe3e4, 0x0712ad23,
- 0x002fa800, 0x000ff3e0, 0x05631d1b,
- 0x001f9810, 0x000ffbe1, 0x03b3890d,
- 0x000f8c23, 0x000003e3, 0x0233e8fa,
- 0x3fef843b, 0x000003e7, 0x00f430e4,
- 0x3fbf8456, 0x3ff00bea, 0x00046cc8,
- 0x3f8f8c72, 0x3ff00bef, 0x3f3490ac },
- },
- { 0x1e00, {
- 0x001fbbf4, 0x001fbbf4, 0x09425112,
- 0x001fa800, 0x002fc7ed, 0x0792b110,
- 0x000f980e, 0x001fdbe6, 0x0613110a,
- 0x3fff8c20, 0x001fe7e3, 0x04a368fd,
- 0x3fcf8c33, 0x000ff7e2, 0x0343b8ed,
- 0x3f9f8c4a, 0x000fffe3, 0x0203f8da,
- 0x3f5f9c61, 0x000003e6, 0x00e428c5,
- 0x3f1fb07b, 0x000003eb, 0x3fe440af },
- },
- { 0x2000, {
- 0x000fa400, 0x000fa400, 0x09625902,
- 0x3fff980c, 0x001fb7f5, 0x0812b0ff,
- 0x3fdf901c, 0x001fc7ed, 0x06b2fcfa,
- 0x3faf902d, 0x001fd3e8, 0x055348f1,
- 0x3f7f983f, 0x001fe3e5, 0x04038ce3,
- 0x3f3fa454, 0x001fefe3, 0x02e3c8d1,
- 0x3f0fb86a, 0x001ff7e4, 0x01c3e8c0,
- 0x3ecfd880, 0x000fffe6, 0x00c404ac },
- },
- { 0x2200, {
- 0x3fdf9c0b, 0x3fdf9c0b, 0x09725cf4,
- 0x3fbf9818, 0x3fffa400, 0x0842a8f1,
- 0x3f8f9827, 0x000fb3f7, 0x0702f0ec,
- 0x3f5fa037, 0x000fc3ef, 0x05d330e4,
- 0x3f2fac49, 0x001fcfea, 0x04a364d9,
- 0x3effc05c, 0x001fdbe7, 0x038394ca,
- 0x3ecfdc6f, 0x001fe7e6, 0x0273b0bb,
- 0x3ea00083, 0x001fefe6, 0x0183c0a9 },
- },
- { 0x2400, {
- 0x3f9fa014, 0x3f9fa014, 0x098260e6,
- 0x3f7f9c23, 0x3fcf9c0a, 0x08629ce5,
- 0x3f4fa431, 0x3fefa400, 0x0742d8e1,
- 0x3f1fb440, 0x3fffb3f8, 0x062310d9,
- 0x3eefc850, 0x000fbbf2, 0x050340d0,
- 0x3ecfe062, 0x000fcbec, 0x041364c2,
- 0x3ea00073, 0x001fd3ea, 0x03037cb5,
- 0x3e902086, 0x001fdfe8, 0x022388a5 },
- },
- { 0x2600, {
- 0x3f5fa81e, 0x3f5fa81e, 0x096258da,
- 0x3f3fac2b, 0x3f8fa412, 0x088290d8,
- 0x3f0fbc38, 0x3fafa408, 0x0772c8d5,
- 0x3eefcc47, 0x3fcfa800, 0x0672f4ce,
- 0x3ecfe456, 0x3fefaffa, 0x05531cc6,
- 0x3eb00066, 0x3fffbbf3, 0x047334bb,
- 0x3ea01c77, 0x000fc7ee, 0x039348ae,
- 0x3ea04486, 0x000fd3eb, 0x02b350a1 },
- },
- { 0x2800, {
- 0x3f2fb426, 0x3f2fb426, 0x094250ce,
- 0x3f0fc032, 0x3f4fac1b, 0x086284cd,
- 0x3eefd040, 0x3f7fa811, 0x0782acc9,
- 0x3ecfe84c, 0x3f9fa807, 0x06a2d8c4,
- 0x3eb0005b, 0x3fbfac00, 0x05b2f4bc,
- 0x3eb0186a, 0x3fdfb3fa, 0x04c308b4,
- 0x3eb04077, 0x3fefbbf4, 0x03f31ca8,
- 0x3ec06884, 0x000fbff2, 0x03031c9e },
- },
- { 0x2a00, {
- 0x3f0fc42d, 0x3f0fc42d, 0x090240c4,
- 0x3eefd439, 0x3f2fb822, 0x08526cc2,
- 0x3edfe845, 0x3f4fb018, 0x078294bf,
- 0x3ec00051, 0x3f6fac0f, 0x06b2b4bb,
- 0x3ec0185f, 0x3f8fac07, 0x05e2ccb4,
- 0x3ec0386b, 0x3fafac00, 0x0502e8ac,
- 0x3ed05c77, 0x3fcfb3fb, 0x0432f0a3,
- 0x3ef08482, 0x3fdfbbf6, 0x0372f898 },
- },
- { 0x2c00, {
- 0x3eefdc31, 0x3eefdc31, 0x08e238b8,
- 0x3edfec3d, 0x3f0fc828, 0x082258b9,
- 0x3ed00049, 0x3f1fc01e, 0x077278b6,
- 0x3ed01455, 0x3f3fb815, 0x06c294b2,
- 0x3ed03460, 0x3f5fb40d, 0x0602acac,
- 0x3ef0506c, 0x3f7fb006, 0x0542c0a4,
- 0x3f107476, 0x3f9fb400, 0x0472c89d,
- 0x3f309c80, 0x3fbfb7fc, 0x03b2cc94 },
- },
- { 0x2e00, {
- 0x3eefec37, 0x3eefec37, 0x088220b0,
- 0x3ee00041, 0x3effdc2d, 0x07f244ae,
- 0x3ee0144c, 0x3f0fd023, 0x07625cad,
- 0x3ef02c57, 0x3f1fc81a, 0x06c274a9,
- 0x3f004861, 0x3f3fbc13, 0x060288a6,
- 0x3f20686b, 0x3f5fb80c, 0x05529c9e,
- 0x3f408c74, 0x3f6fb805, 0x04b2ac96,
- 0x3f80ac7e, 0x3f8fb800, 0x0402ac8e },
- },
- { 0x3000, {
- 0x3ef0003a, 0x3ef0003a, 0x084210a6,
- 0x3ef01045, 0x3effec32, 0x07b228a7,
- 0x3f00284e, 0x3f0fdc29, 0x073244a4,
- 0x3f104058, 0x3f0fd420, 0x06a258a2,
- 0x3f305c62, 0x3f2fc818, 0x0612689d,
- 0x3f508069, 0x3f3fc011, 0x05728496,
- 0x3f80a072, 0x3f4fc00a, 0x04d28c90,
- 0x3fc0c07b, 0x3f6fbc04, 0x04429088 },
- },
- { 0x3200, {
- 0x3f00103e, 0x3f00103e, 0x07f1fc9e,
- 0x3f102447, 0x3f000035, 0x0782149d,
- 0x3f203c4f, 0x3f0ff02c, 0x07122c9c,
- 0x3f405458, 0x3f0fe424, 0x06924099,
- 0x3f607061, 0x3f1fd41d, 0x06024c97,
- 0x3f909068, 0x3f2fcc16, 0x05726490,
- 0x3fc0b070, 0x3f3fc80f, 0x04f26c8a,
- 0x0000d077, 0x3f4fc409, 0x04627484 },
- },
- { 0x3400, {
- 0x3f202040, 0x3f202040, 0x07a1e898,
- 0x3f303449, 0x3f100c38, 0x0741fc98,
- 0x3f504c50, 0x3f10002f, 0x06e21495,
- 0x3f706459, 0x3f1ff028, 0x06722492,
- 0x3fa08060, 0x3f1fe421, 0x05f2348f,
- 0x3fd09c67, 0x3f1fdc19, 0x05824c89,
- 0x0000bc6e, 0x3f2fd014, 0x04f25086,
- 0x0040dc74, 0x3f3fcc0d, 0x04825c7f },
- },
- { 0x3600, {
- 0x3f403042, 0x3f403042, 0x0761d890,
- 0x3f504848, 0x3f301c3b, 0x0701f090,
- 0x3f805c50, 0x3f200c33, 0x06a2008f,
- 0x3fa07458, 0x3f10002b, 0x06520c8d,
- 0x3fd0905e, 0x3f1ff424, 0x05e22089,
- 0x0000ac65, 0x3f1fe81d, 0x05823483,
- 0x0030cc6a, 0x3f2fdc18, 0x04f23c81,
- 0x0080e871, 0x3f2fd412, 0x0482407c },
- },
- { 0x3800, {
- 0x3f604043, 0x3f604043, 0x0721c88a,
- 0x3f80544a, 0x3f502c3c, 0x06d1d88a,
- 0x3fb06851, 0x3f301c35, 0x0681e889,
- 0x3fd08456, 0x3f30082f, 0x0611fc88,
- 0x00009c5d, 0x3f200027, 0x05d20884,
- 0x0030b863, 0x3f2ff421, 0x05621880,
- 0x0070d468, 0x3f2fe81b, 0x0502247c,
- 0x00c0ec6f, 0x3f2fe015, 0x04a22877 },
- },
- { 0x3a00, {
- 0x3f904c44, 0x3f904c44, 0x06e1b884,
- 0x3fb0604a, 0x3f70383e, 0x0691c885,
- 0x3fe07451, 0x3f502c36, 0x0661d483,
- 0x00009055, 0x3f401831, 0x0601ec81,
- 0x0030a85b, 0x3f300c2a, 0x05b1f480,
- 0x0070c061, 0x3f300024, 0x0562047a,
- 0x00b0d867, 0x3f3ff41e, 0x05020c77,
- 0x00f0f46b, 0x3f2fec19, 0x04a21474 },
- },
- { 0x3c00, {
- 0x3fb05c43, 0x3fb05c43, 0x06c1b07e,
- 0x3fe06c4b, 0x3f902c3f, 0x0681c081,
- 0x0000844f, 0x3f703838, 0x0631cc7d,
- 0x00309855, 0x3f602433, 0x05d1d47e,
- 0x0060b459, 0x3f50142e, 0x0581e47b,
- 0x00a0c85f, 0x3f400828, 0x0531f078,
- 0x00e0e064, 0x3f300021, 0x0501fc73,
- 0x00b0fc6a, 0x3f3ff41d, 0x04a20873 },
- },
- { 0x3e00, {
- 0x3fe06444, 0x3fe06444, 0x0681a07a,
- 0x00007849, 0x3fc0503f, 0x0641b07a,
- 0x0020904d, 0x3fa0403a, 0x05f1c07a,
- 0x0060a453, 0x3f803034, 0x05c1c878,
- 0x0090b858, 0x3f70202f, 0x0571d477,
- 0x00d0d05d, 0x3f501829, 0x0531e073,
- 0x0110e462, 0x3f500825, 0x04e1e471,
- 0x01510065, 0x3f40001f, 0x04a1f06d },
- },
- { 0x4000, {
- 0x00007044, 0x00007044, 0x06519476,
- 0x00208448, 0x3fe05c3f, 0x0621a476,
- 0x0050984d, 0x3fc04c3a, 0x05e1b075,
- 0x0080ac52, 0x3fa03c35, 0x05a1b875,
- 0x00c0c056, 0x3f803030, 0x0561c473,
- 0x0100d45b, 0x3f70202b, 0x0521d46f,
- 0x0140e860, 0x3f601427, 0x04d1d46e,
- 0x01810064, 0x3f500822, 0x0491dc6b },
- },
- { 0x5000, {
- 0x0110a442, 0x0110a442, 0x0551545e,
- 0x0140b045, 0x00e0983f, 0x0531585f,
- 0x0160c047, 0x00c08c3c, 0x0511645e,
- 0x0190cc4a, 0x00908039, 0x04f1685f,
- 0x01c0dc4c, 0x00707436, 0x04d1705e,
- 0x0200e850, 0x00506833, 0x04b1785b,
- 0x0230f453, 0x00305c30, 0x0491805a,
- 0x02710056, 0x0010542d, 0x04718059 },
- },
- { 0x6000, {
- 0x01c0bc40, 0x01c0bc40, 0x04c13052,
- 0x01e0c841, 0x01a0b43d, 0x04c13851,
- 0x0210cc44, 0x0180a83c, 0x04a13453,
- 0x0230d845, 0x0160a03a, 0x04913c52,
- 0x0260e047, 0x01409838, 0x04714052,
- 0x0280ec49, 0x01208c37, 0x04514c50,
- 0x02b0f44b, 0x01008435, 0x04414c50,
- 0x02d1004c, 0x00e07c33, 0x0431544f },
- },
- { 0x7000, {
- 0x0230c83e, 0x0230c83e, 0x04711c4c,
- 0x0250d03f, 0x0210c43c, 0x0471204b,
- 0x0270d840, 0x0200b83c, 0x0451244b,
- 0x0290dc42, 0x01e0b43a, 0x0441244c,
- 0x02b0e443, 0x01c0b038, 0x0441284b,
- 0x02d0ec44, 0x01b0a438, 0x0421304a,
- 0x02f0f445, 0x0190a036, 0x04213449,
- 0x0310f847, 0x01709c34, 0x04213848 },
- },
- { 0x8000, {
- 0x0280d03d, 0x0280d03d, 0x04310c48,
- 0x02a0d43e, 0x0270c83c, 0x04311047,
- 0x02b0dc3e, 0x0250c83a, 0x04311447,
- 0x02d0e040, 0x0240c03a, 0x04211446,
- 0x02e0e840, 0x0220bc39, 0x04111847,
- 0x0300e842, 0x0210b438, 0x04012445,
- 0x0310f043, 0x0200b037, 0x04012045,
- 0x0330f444, 0x01e0ac36, 0x03f12445 },
- },
- { 0xefff, {
- 0x0340dc3a, 0x0340dc3a, 0x03b0ec40,
- 0x0340e03a, 0x0330e039, 0x03c0f03e,
- 0x0350e03b, 0x0330dc39, 0x03c0ec3e,
- 0x0350e43a, 0x0320dc38, 0x03c0f43e,
- 0x0360e43b, 0x0320d839, 0x03b0f03e,
- 0x0360e83b, 0x0310d838, 0x03c0fc3b,
- 0x0370e83b, 0x0310d439, 0x03a0f83d,
- 0x0370e83c, 0x0300d438, 0x03b0fc3c },
- }
-};
-
enum rcar_vin_state {
STOPPED = 0,
RUNNING,
@@ -504,9 +161,6 @@
/* Client output, as seen by the VIN */
unsigned int width;
unsigned int height;
- /* User window from S_FMT */
- unsigned int out_width;
- unsigned int out_height;
/*
* User window from S_CROP / G_CROP, produced by client cropping and
* scaling, VIN scaling and VIN cropping, mapped back onto the client
@@ -618,16 +272,16 @@
/* input interface */
switch (icd->current_fmt->code) {
- case MEDIA_BUS_FMT_YUYV8_1X16:
+ case V4L2_MBUS_FMT_YUYV8_1X16:
/* BT.601/BT.1358 16bit YCbCr422 */
vnmc |= VNMC_INF_YUV16;
break;
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
break;
- case MEDIA_BUS_FMT_YUYV10_2X10:
+ case V4L2_MBUS_FMT_YUYV10_2X10:
/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
@@ -678,7 +332,7 @@
vnmc |= VNMC_BPS;
/* progressive or interlaced mode */
- interrupts = progressive ? VNIE_FIE : VNIE_EFE;
+ interrupts = progressive ? VNIE_FIE | VNIE_EFE : VNIE_EFE;
/* ack interrupts */
iowrite32(interrupts, priv->base + VNINTS_REG);
@@ -1013,60 +667,6 @@
/* VIN does not have "mclk" */
}
-static void set_coeff(struct rcar_vin_priv *priv, unsigned short xs)
-{
- int i;
- const struct vin_coeff *p_prev_set = NULL;
- const struct vin_coeff *p_set = NULL;
-
- /* Look for suitable coefficient values */
- for (i = 0; i < ARRAY_SIZE(vin_coeff_set); i++) {
- p_prev_set = p_set;
- p_set = &vin_coeff_set[i];
-
- if (xs < p_set->xs_value)
- break;
- }
-
- /* Use previous value if its XS value is closer */
- if (p_prev_set && p_set &&
- xs - p_prev_set->xs_value < p_set->xs_value - xs)
- p_set = p_prev_set;
-
- /* Set coefficient registers */
- iowrite32(p_set->coeff_set[0], priv->base + VNC1A_REG);
- iowrite32(p_set->coeff_set[1], priv->base + VNC1B_REG);
- iowrite32(p_set->coeff_set[2], priv->base + VNC1C_REG);
-
- iowrite32(p_set->coeff_set[3], priv->base + VNC2A_REG);
- iowrite32(p_set->coeff_set[4], priv->base + VNC2B_REG);
- iowrite32(p_set->coeff_set[5], priv->base + VNC2C_REG);
-
- iowrite32(p_set->coeff_set[6], priv->base + VNC3A_REG);
- iowrite32(p_set->coeff_set[7], priv->base + VNC3B_REG);
- iowrite32(p_set->coeff_set[8], priv->base + VNC3C_REG);
-
- iowrite32(p_set->coeff_set[9], priv->base + VNC4A_REG);
- iowrite32(p_set->coeff_set[10], priv->base + VNC4B_REG);
- iowrite32(p_set->coeff_set[11], priv->base + VNC4C_REG);
-
- iowrite32(p_set->coeff_set[12], priv->base + VNC5A_REG);
- iowrite32(p_set->coeff_set[13], priv->base + VNC5B_REG);
- iowrite32(p_set->coeff_set[14], priv->base + VNC5C_REG);
-
- iowrite32(p_set->coeff_set[15], priv->base + VNC6A_REG);
- iowrite32(p_set->coeff_set[16], priv->base + VNC6B_REG);
- iowrite32(p_set->coeff_set[17], priv->base + VNC6C_REG);
-
- iowrite32(p_set->coeff_set[18], priv->base + VNC7A_REG);
- iowrite32(p_set->coeff_set[19], priv->base + VNC7B_REG);
- iowrite32(p_set->coeff_set[20], priv->base + VNC7C_REG);
-
- iowrite32(p_set->coeff_set[21], priv->base + VNC8A_REG);
- iowrite32(p_set->coeff_set[22], priv->base + VNC8B_REG);
- iowrite32(p_set->coeff_set[23], priv->base + VNC8C_REG);
-}
-
/* rect is guaranteed to not exceed the scaled camera rectangle */
static int rcar_vin_set_rect(struct soc_camera_device *icd)
{
@@ -1076,7 +676,6 @@
unsigned int left_offset, top_offset;
unsigned char dsize = 0;
struct v4l2_rect *cam_subrect = &cam->subrect;
- u32 value;
dev_dbg(icd->parent, "Crop %ux%u@%u:%u\n",
icd->user_width, icd->user_height, cam->vin_left, cam->vin_top);
@@ -1096,64 +695,40 @@
/* Set Start/End Pixel/Line Pre-Clip */
iowrite32(left_offset << dsize, priv->base + VNSPPRC_REG);
- iowrite32((left_offset + cam_subrect->width - 1) << dsize,
+ iowrite32((left_offset + cam->width - 1) << dsize,
priv->base + VNEPPRC_REG);
switch (priv->field) {
case V4L2_FIELD_INTERLACED:
case V4L2_FIELD_INTERLACED_TB:
case V4L2_FIELD_INTERLACED_BT:
iowrite32(top_offset / 2, priv->base + VNSLPRC_REG);
- iowrite32((top_offset + cam_subrect->height) / 2 - 1,
+ iowrite32((top_offset + cam->height) / 2 - 1,
priv->base + VNELPRC_REG);
break;
default:
iowrite32(top_offset, priv->base + VNSLPRC_REG);
- iowrite32(top_offset + cam_subrect->height - 1,
+ iowrite32(top_offset + cam->height - 1,
priv->base + VNELPRC_REG);
break;
}
- /* Set scaling coefficient */
- value = 0;
- if (cam_subrect->height != cam->out_height)
- value = (4096 * cam_subrect->height) / cam->out_height;
- dev_dbg(icd->parent, "YS Value: %x\n", value);
- iowrite32(value, priv->base + VNYS_REG);
-
- value = 0;
- if (cam_subrect->width != cam->out_width)
- value = (4096 * cam_subrect->width) / cam->out_width;
-
- /* Horizontal upscaling is up to double size */
- if (0 < value && value < 2048)
- value = 2048;
-
- dev_dbg(icd->parent, "XS Value: %x\n", value);
- iowrite32(value, priv->base + VNXS_REG);
-
- /* Horizontal upscaling is carried out by scaling down from double size */
- if (value < 4096)
- value *= 2;
-
- set_coeff(priv, value);
-
/* Set Start/End Pixel/Line Post-Clip */
iowrite32(0, priv->base + VNSPPOC_REG);
iowrite32(0, priv->base + VNSLPOC_REG);
- iowrite32((cam->out_width - 1) << dsize, priv->base + VNEPPOC_REG);
+ iowrite32((cam_subrect->width - 1) << dsize, priv->base + VNEPPOC_REG);
switch (priv->field) {
case V4L2_FIELD_INTERLACED:
case V4L2_FIELD_INTERLACED_TB:
case V4L2_FIELD_INTERLACED_BT:
- iowrite32(cam->out_height / 2 - 1,
+ iowrite32(cam_subrect->height / 2 - 1,
priv->base + VNELPOC_REG);
break;
default:
- iowrite32(cam->out_height - 1, priv->base + VNELPOC_REG);
+ iowrite32(cam_subrect->height - 1, priv->base + VNELPOC_REG);
break;
}
- iowrite32(ALIGN(cam->out_width, 0x10), priv->base + VNIS_REG);
+ iowrite32(ALIGN(cam->width, 0x10), priv->base + VNIS_REG);
return 0;
}
@@ -1244,7 +819,7 @@
if (ret < 0 && ret != -ENOIOCTLCMD)
return ret;
- val = VNDMR2_FTEV | VNDMR2_VLV(1);
+ val = priv->field == V4L2_FIELD_NONE ? VNDMR2_FTEV : 0;
if (!(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW))
val |= VNDMR2_VPS;
if (!(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW))
@@ -1305,14 +880,6 @@
.layout = SOC_MBUS_LAYOUT_PLANAR_Y_C,
},
{
- .fourcc = V4L2_PIX_FMT_YUYV,
- .name = "YUYV",
- .bits_per_sample = 16,
- .packing = SOC_MBUS_PACKING_NONE,
- .order = SOC_MBUS_ORDER_LE,
- .layout = SOC_MBUS_LAYOUT_PACKED,
- },
- {
.fourcc = V4L2_PIX_FMT_UYVY,
.name = "UYVY",
.bits_per_sample = 16,
@@ -1354,7 +921,7 @@
int ret, k, n;
int formats = 0;
struct rcar_vin_cam *cam;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
const struct soc_mbus_pixelfmt *fmt;
ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -1432,8 +999,6 @@
cam->subrect = rect;
cam->width = mf.width;
cam->height = mf.height;
- cam->out_width = mf.width;
- cam->out_height = mf.height;
icd->host_priv = cam;
} else {
@@ -1445,9 +1010,9 @@
cam->extra_fmt = NULL;
switch (code) {
- case MEDIA_BUS_FMT_YUYV8_1X16:
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_YUYV10_2X10:
+ case V4L2_MBUS_FMT_YUYV8_1X16:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV10_2X10:
if (cam->extra_fmt)
break;
@@ -1694,9 +1259,6 @@
dev_dbg(dev, "W: %u : %u, H: %u : %u\n",
vin_sub_width, pix->width, vin_sub_height, pix->height);
- cam->out_width = pix->width;
- cam->out_height = pix->height;
-
icd->current_fmt = xlate;
priv->field = field;
@@ -1748,12 +1310,8 @@
if (ret < 0)
return ret;
- /* Adjust only if VIN cannot scale */
- if (pix->width > mf.width * 2)
- pix->width = mf.width * 2;
- if (pix->height > mf.height * 3)
- pix->height = mf.height * 3;
-
+ pix->width = mf.width;
+ pix->height = mf.height;
pix->field = mf.field;
pix->colorspace = mf.colorspace;
@@ -1837,8 +1395,6 @@
#ifdef CONFIG_OF
static struct of_device_id rcar_vin_of_table[] = {
- { .compatible = "renesas,vin-r8a7794", .data = (void *)RCAR_GEN2 },
- { .compatible = "renesas,vin-r8a7793", .data = (void *)RCAR_GEN2 },
{ .compatible = "renesas,vin-r8a7791", .data = (void *)RCAR_GEN2 },
{ .compatible = "renesas,vin-r8a7790", .data = (void *)RCAR_GEN2 },
{ .compatible = "renesas,vin-r8a7779", .data = (void *)RCAR_H1 },
@@ -1987,6 +1543,7 @@
.remove = rcar_vin_remove,
.driver = {
.name = DRV_NAME,
+ .owner = THIS_MODULE,
.of_match_table = of_match_ptr(rcar_vin_of_table),
},
.id_table = rcar_vin_id_table,
diff --git a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 8b27b3e..20ad4a5 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
@@ -149,7 +149,7 @@
/* Camera cropping rectangle */
struct v4l2_rect rect;
const struct soc_mbus_pixelfmt *extra_fmt;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
};
static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_buffer *vb)
@@ -861,16 +861,16 @@
case V4L2_PIX_FMT_NV16:
case V4L2_PIX_FMT_NV61:
switch (cam->code) {
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
value = 0x00000000; /* Cb0, Y0, Cr0, Y1 */
break;
- case MEDIA_BUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
value = 0x00000100; /* Cr0, Y0, Cb0, Y1 */
break;
- case MEDIA_BUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
value = 0x00000200; /* Y0, Cb0, Y1, Cr0 */
break;
- case MEDIA_BUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
value = 0x00000300; /* Y0, Cr0, Y1, Cb0 */
break;
default:
@@ -1048,7 +1048,7 @@
int ret, k, n;
int formats = 0;
struct sh_mobile_ceu_cam *cam;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
const struct soc_mbus_pixelfmt *fmt;
ret = v4l2_subdev_call(sd, video, enum_mbus_fmt, idx, &code);
@@ -1141,10 +1141,10 @@
cam->extra_fmt = NULL;
switch (code) {
- case MEDIA_BUS_FMT_UYVY8_2X8:
- case MEDIA_BUS_FMT_VYUY8_2X8:
- case MEDIA_BUS_FMT_YUYV8_2X8:
- case MEDIA_BUS_FMT_YVYU8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_VYUY8_2X8:
+ case V4L2_MBUS_FMT_YUYV8_2X8:
+ case V4L2_MBUS_FMT_YVYU8_2X8:
if (cam->extra_fmt)
break;
@@ -2009,6 +2009,7 @@
static struct platform_driver sh_mobile_ceu_driver = {
.driver = {
.name = "sh_mobile_ceu",
+ .owner = THIS_MODULE,
.pm = &sh_mobile_ceu_dev_pm_ops,
.of_match_table = sh_mobile_ceu_of_match,
},
diff --git a/drivers/media/platform/soc_camera/sh_mobile_csi2.c b/drivers/media/platform/soc_camera/sh_mobile_csi2.c
index c4e7aa0..05dd21a 100644
--- a/drivers/media/platform/soc_camera/sh_mobile_csi2.c
+++ b/drivers/media/platform/soc_camera/sh_mobile_csi2.c
@@ -59,28 +59,28 @@
switch (pdata->type) {
case SH_CSI2C:
switch (mf->code) {
- case MEDIA_BUS_FMT_UYVY8_2X8: /* YUV422 */
- case MEDIA_BUS_FMT_YUYV8_1_5X8: /* YUV420 */
- case MEDIA_BUS_FMT_Y8_1X8: /* RAW8 */
- case MEDIA_BUS_FMT_SBGGR8_1X8:
- case MEDIA_BUS_FMT_SGRBG8_1X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8: /* YUV422 */
+ case V4L2_MBUS_FMT_YUYV8_1_5X8: /* YUV420 */
+ case V4L2_MBUS_FMT_Y8_1X8: /* RAW8 */
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
break;
default:
/* All MIPI CSI-2 devices must support one of primary formats */
- mf->code = MEDIA_BUS_FMT_YUYV8_2X8;
+ mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
}
break;
case SH_CSI2I:
switch (mf->code) {
- case MEDIA_BUS_FMT_Y8_1X8: /* RAW8 */
- case MEDIA_BUS_FMT_SBGGR8_1X8:
- case MEDIA_BUS_FMT_SGRBG8_1X8:
- case MEDIA_BUS_FMT_SBGGR10_1X10: /* RAW10 */
- case MEDIA_BUS_FMT_SBGGR12_1X12: /* RAW12 */
+ case V4L2_MBUS_FMT_Y8_1X8: /* RAW8 */
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
+ case V4L2_MBUS_FMT_SBGGR10_1X10: /* RAW10 */
+ case V4L2_MBUS_FMT_SBGGR12_1X12: /* RAW12 */
break;
default:
/* All MIPI CSI-2 devices must support one of primary formats */
- mf->code = MEDIA_BUS_FMT_SBGGR8_1X8;
+ mf->code = V4L2_MBUS_FMT_SBGGR8_1X8;
}
break;
}
@@ -104,21 +104,21 @@
return -EINVAL;
switch (mf->code) {
- case MEDIA_BUS_FMT_UYVY8_2X8:
+ case V4L2_MBUS_FMT_UYVY8_2X8:
tmp |= 0x1e; /* YUV422 8 bit */
break;
- case MEDIA_BUS_FMT_YUYV8_1_5X8:
+ case V4L2_MBUS_FMT_YUYV8_1_5X8:
tmp |= 0x18; /* YUV420 8 bit */
break;
- case MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE:
+ case V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE:
tmp |= 0x21; /* RGB555 */
break;
- case MEDIA_BUS_FMT_RGB565_2X8_BE:
+ case V4L2_MBUS_FMT_RGB565_2X8_BE:
tmp |= 0x22; /* RGB565 */
break;
- case MEDIA_BUS_FMT_Y8_1X8:
- case MEDIA_BUS_FMT_SBGGR8_1X8:
- case MEDIA_BUS_FMT_SGRBG8_1X8:
+ case V4L2_MBUS_FMT_Y8_1X8:
+ case V4L2_MBUS_FMT_SBGGR8_1X8:
+ case V4L2_MBUS_FMT_SGRBG8_1X8:
tmp |= 0x2a; /* RAW8 */
break;
default:
@@ -391,6 +391,7 @@
.probe = sh_csi2_probe,
.driver = {
.name = "sh-mobile-csi2",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index b3db51c..8e61b97 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -460,7 +460,7 @@
struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
unsigned int i, fmts = 0, raw_fmts = 0;
int ret;
- u32 code;
+ enum v4l2_mbus_pixelcode code;
while (!v4l2_subdev_call(sd, video, enum_mbus_fmt, raw_fmts, &code))
raw_fmts++;
@@ -2236,6 +2236,7 @@
.remove = soc_camera_pdrv_remove,
.driver = {
.name = "soc-camera-pdrv",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/media/platform/soc_camera/soc_camera_platform.c b/drivers/media/platform/soc_camera/soc_camera_platform.c
index f535910..ceaddfb 100644
--- a/drivers/media/platform/soc_camera/soc_camera_platform.c
+++ b/drivers/media/platform/soc_camera/soc_camera_platform.c
@@ -62,7 +62,7 @@
};
static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
- u32 *code)
+ enum v4l2_mbus_pixelcode *code)
{
struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
@@ -180,6 +180,7 @@
static struct platform_driver soc_camera_platform_driver = {
.driver = {
.name = "soc_camera_platform",
+ .owner = THIS_MODULE,
},
.probe = soc_camera_platform_probe,
.remove = soc_camera_platform_remove,
diff --git a/drivers/media/platform/soc_camera/soc_mediabus.c b/drivers/media/platform/soc_camera/soc_mediabus.c
index 1dbcd42..dc02dec 100644
--- a/drivers/media/platform/soc_camera/soc_mediabus.c
+++ b/drivers/media/platform/soc_camera/soc_mediabus.c
@@ -17,7 +17,7 @@
static const struct soc_mbus_lookup mbus_fmt[] = {
{
- .code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .code = V4L2_MBUS_FMT_YUYV8_2X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_YUYV,
.name = "YUYV",
@@ -27,7 +27,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_YVYU8_2X8,
+ .code = V4L2_MBUS_FMT_YVYU8_2X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_YVYU,
.name = "YVYU",
@@ -37,7 +37,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_UYVY8_2X8,
+ .code = V4L2_MBUS_FMT_UYVY8_2X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_UYVY,
.name = "UYVY",
@@ -47,7 +47,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_VYUY8_2X8,
+ .code = V4L2_MBUS_FMT_VYUY8_2X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_VYUY,
.name = "VYUY",
@@ -57,7 +57,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE,
+ .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB555,
.name = "RGB555",
@@ -67,7 +67,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE,
+ .code = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB555X,
.name = "RGB555X",
@@ -77,7 +77,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB565_2X8_LE,
+ .code = V4L2_MBUS_FMT_RGB565_2X8_LE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB565,
.name = "RGB565",
@@ -87,7 +87,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB565_2X8_BE,
+ .code = V4L2_MBUS_FMT_RGB565_2X8_BE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB565X,
.name = "RGB565X",
@@ -97,7 +97,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB666_1X18,
+ .code = V4L2_MBUS_FMT_RGB666_1X18,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB32,
.name = "RGB666/32bpp",
@@ -106,7 +106,7 @@
.order = SOC_MBUS_ORDER_LE,
},
}, {
- .code = MEDIA_BUS_FMT_RGB888_1X24,
+ .code = V4L2_MBUS_FMT_RGB888_1X24,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB32,
.name = "RGB888/32bpp",
@@ -115,7 +115,7 @@
.order = SOC_MBUS_ORDER_LE,
},
}, {
- .code = MEDIA_BUS_FMT_RGB888_2X12_BE,
+ .code = V4L2_MBUS_FMT_RGB888_2X12_BE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB32,
.name = "RGB888/32bpp",
@@ -124,7 +124,7 @@
.order = SOC_MBUS_ORDER_BE,
},
}, {
- .code = MEDIA_BUS_FMT_RGB888_2X12_LE,
+ .code = V4L2_MBUS_FMT_RGB888_2X12_LE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB32,
.name = "RGB888/32bpp",
@@ -133,7 +133,7 @@
.order = SOC_MBUS_ORDER_LE,
},
}, {
- .code = MEDIA_BUS_FMT_SBGGR8_1X8,
+ .code = V4L2_MBUS_FMT_SBGGR8_1X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_SBGGR8,
.name = "Bayer 8 BGGR",
@@ -143,7 +143,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SBGGR10_1X10,
+ .code = V4L2_MBUS_FMT_SBGGR10_1X10,
.fmt = {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.name = "Bayer 10 BGGR",
@@ -153,7 +153,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_Y8_1X8,
+ .code = V4L2_MBUS_FMT_Y8_1X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_GREY,
.name = "Grey",
@@ -163,7 +163,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_Y10_1X10,
+ .code = V4L2_MBUS_FMT_Y10_1X10,
.fmt = {
.fourcc = V4L2_PIX_FMT_Y10,
.name = "Grey 10bit",
@@ -173,7 +173,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE,
+ .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE,
.fmt = {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.name = "Bayer 10 BGGR",
@@ -183,7 +183,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE,
+ .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE,
.fmt = {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.name = "Bayer 10 BGGR",
@@ -193,7 +193,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE,
+ .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE,
.fmt = {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.name = "Bayer 10 BGGR",
@@ -203,7 +203,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE,
+ .code = V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE,
.fmt = {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.name = "Bayer 10 BGGR",
@@ -213,7 +213,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_JPEG_1X8,
+ .code = V4L2_MBUS_FMT_JPEG_1X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_JPEG,
.name = "JPEG",
@@ -223,7 +223,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE,
+ .code = V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE,
.fmt = {
.fourcc = V4L2_PIX_FMT_RGB444,
.name = "RGB444",
@@ -233,7 +233,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_YUYV8_1_5X8,
+ .code = V4L2_MBUS_FMT_YUYV8_1_5X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_YUV420,
.name = "YUYV 4:2:0",
@@ -243,7 +243,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_YVYU8_1_5X8,
+ .code = V4L2_MBUS_FMT_YVYU8_1_5X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_YVU420,
.name = "YVYU 4:2:0",
@@ -253,7 +253,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_UYVY8_1X16,
+ .code = V4L2_MBUS_FMT_UYVY8_1X16,
.fmt = {
.fourcc = V4L2_PIX_FMT_UYVY,
.name = "UYVY 16bit",
@@ -263,7 +263,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_VYUY8_1X16,
+ .code = V4L2_MBUS_FMT_VYUY8_1X16,
.fmt = {
.fourcc = V4L2_PIX_FMT_VYUY,
.name = "VYUY 16bit",
@@ -273,7 +273,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_YUYV8_1X16,
+ .code = V4L2_MBUS_FMT_YUYV8_1X16,
.fmt = {
.fourcc = V4L2_PIX_FMT_YUYV,
.name = "YUYV 16bit",
@@ -283,7 +283,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_YVYU8_1X16,
+ .code = V4L2_MBUS_FMT_YVYU8_1X16,
.fmt = {
.fourcc = V4L2_PIX_FMT_YVYU,
.name = "YVYU 16bit",
@@ -293,7 +293,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SGRBG8_1X8,
+ .code = V4L2_MBUS_FMT_SGRBG8_1X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_SGRBG8,
.name = "Bayer 8 GRBG",
@@ -303,7 +303,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8,
+ .code = V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
.fmt = {
.fourcc = V4L2_PIX_FMT_SGRBG10DPCM8,
.name = "Bayer 10 BGGR DPCM 8",
@@ -313,7 +313,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SGBRG10_1X10,
+ .code = V4L2_MBUS_FMT_SGBRG10_1X10,
.fmt = {
.fourcc = V4L2_PIX_FMT_SGBRG10,
.name = "Bayer 10 GBRG",
@@ -323,7 +323,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SGRBG10_1X10,
+ .code = V4L2_MBUS_FMT_SGRBG10_1X10,
.fmt = {
.fourcc = V4L2_PIX_FMT_SGRBG10,
.name = "Bayer 10 GRBG",
@@ -333,7 +333,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SRGGB10_1X10,
+ .code = V4L2_MBUS_FMT_SRGGB10_1X10,
.fmt = {
.fourcc = V4L2_PIX_FMT_SRGGB10,
.name = "Bayer 10 RGGB",
@@ -343,7 +343,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SBGGR12_1X12,
+ .code = V4L2_MBUS_FMT_SBGGR12_1X12,
.fmt = {
.fourcc = V4L2_PIX_FMT_SBGGR12,
.name = "Bayer 12 BGGR",
@@ -353,7 +353,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SGBRG12_1X12,
+ .code = V4L2_MBUS_FMT_SGBRG12_1X12,
.fmt = {
.fourcc = V4L2_PIX_FMT_SGBRG12,
.name = "Bayer 12 GBRG",
@@ -363,7 +363,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SGRBG12_1X12,
+ .code = V4L2_MBUS_FMT_SGRBG12_1X12,
.fmt = {
.fourcc = V4L2_PIX_FMT_SGRBG12,
.name = "Bayer 12 GRBG",
@@ -373,7 +373,7 @@
.layout = SOC_MBUS_LAYOUT_PACKED,
},
}, {
- .code = MEDIA_BUS_FMT_SRGGB12_1X12,
+ .code = V4L2_MBUS_FMT_SRGGB12_1X12,
.fmt = {
.fourcc = V4L2_PIX_FMT_SRGGB12,
.name = "Bayer 12 RGGB",
@@ -458,7 +458,7 @@
EXPORT_SYMBOL(soc_mbus_image_size);
const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
- u32 code,
+ enum v4l2_mbus_pixelcode code,
const struct soc_mbus_lookup *lookup,
int n)
{
@@ -473,7 +473,7 @@
EXPORT_SYMBOL(soc_mbus_find_fmtdesc);
const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
- u32 code)
+ enum v4l2_mbus_pixelcode code)
{
return soc_mbus_find_fmtdesc(code, mbus_fmt, ARRAY_SIZE(mbus_fmt));
}
diff --git a/drivers/media/platform/ti-vpe/csc.c b/drivers/media/platform/ti-vpe/csc.c
index bec6749..940df40 100644
--- a/drivers/media/platform/ti-vpe/csc.c
+++ b/drivers/media/platform/ti-vpe/csc.c
@@ -93,8 +93,12 @@
{
struct device *dev = &csc->pdev->dev;
-#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, \
- ioread32(csc->base + CSC_##r))
+ u32 read_reg(struct csc_data *csc, int offset)
+ {
+ return ioread32(csc->base + offset);
+ }
+
+#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(csc, CSC_##r))
DUMPREG(CSC00);
DUMPREG(CSC01);
@@ -185,7 +189,7 @@
csc->base = devm_ioremap_resource(&pdev->dev, csc->res);
if (IS_ERR(csc->base)) {
dev_err(&pdev->dev, "failed to ioremap\n");
- return ERR_CAST(csc->base);
+ return csc->base;
}
return csc;
diff --git a/drivers/media/platform/ti-vpe/sc.c b/drivers/media/platform/ti-vpe/sc.c
index f82d1c7..6314171 100644
--- a/drivers/media/platform/ti-vpe/sc.c
+++ b/drivers/media/platform/ti-vpe/sc.c
@@ -24,8 +24,12 @@
{
struct device *dev = &sc->pdev->dev;
-#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, \
- ioread32(sc->base + CFG_##r))
+ u32 read_reg(struct sc_data *sc, int offset)
+ {
+ return ioread32(sc->base + offset);
+ }
+
+#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(sc, CFG_##r))
DUMPREG(SC0);
DUMPREG(SC1);
@@ -300,7 +304,7 @@
sc->base = devm_ioremap_resource(&pdev->dev, sc->res);
if (IS_ERR(sc->base)) {
dev_err(&pdev->dev, "failed to ioremap\n");
- return ERR_CAST(sc->base);
+ return sc->base;
}
return sc;
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index d628d1a..9a081c2 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -2376,6 +2376,7 @@
.remove = vpe_remove,
.driver = {
.name = VPE_MODULE_NAME,
+ .owner = THIS_MODULE,
.of_match_table = vpe_of_match,
},
};
diff --git a/drivers/media/platform/timblogiw.c b/drivers/media/platform/timblogiw.c
index 5820e45..3cb2f35 100644
--- a/drivers/media/platform/timblogiw.c
+++ b/drivers/media/platform/timblogiw.c
@@ -857,6 +857,7 @@
static struct platform_driver timblogiw_platform_driver = {
.driver = {
.name = DRIVER_NAME,
+ .owner = THIS_MODULE,
},
.probe = timblogiw_probe,
.remove = timblogiw_remove,
diff --git a/drivers/media/platform/via-camera.c b/drivers/media/platform/via-camera.c
index 86989d8..ae6870c 100644
--- a/drivers/media/platform/via-camera.c
+++ b/drivers/media/platform/via-camera.c
@@ -101,7 +101,7 @@
*/
struct v4l2_pix_format sensor_format;
struct v4l2_pix_format user_format;
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
};
/*
@@ -143,12 +143,12 @@
__u8 *desc;
__u32 pixelformat;
int bpp; /* Bytes per pixel */
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
} via_formats[] = {
{
.desc = "YUYV 4:2:2",
.pixelformat = V4L2_PIX_FMT_YUYV,
- .mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
+ .mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
.bpp = 2,
},
/* RGB444 and Bayer should be doable, but have never been
@@ -849,7 +849,7 @@
.sizeimage = VGA_WIDTH * VGA_HEIGHT * 2,
};
-static const u32 via_def_mbus_code = MEDIA_BUS_FMT_YUYV8_2X8;
+static const enum v4l2_mbus_pixelcode via_def_mbus_code = V4L2_MBUS_FMT_YUYV8_2X8;
static int viacam_enum_fmt_vid_cap(struct file *filp, void *priv,
struct v4l2_fmtdesc *fmt)
@@ -985,9 +985,9 @@
{
strcpy(cap->driver, "via-camera");
strcpy(cap->card, "via-camera");
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+ cap->version = 1;
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_READWRITE | V4L2_CAP_STREAMING;
- cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
diff --git a/drivers/media/platform/vino.c b/drivers/media/platform/vino.c
new file mode 100644
index 0000000..91d44ea
--- /dev/null
+++ b/drivers/media/platform/vino.c
@@ -0,0 +1,4347 @@
+/*
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * Copyright (C) 2004,2005 Mikael Nousiainen <tmnousia@cc.hut.fi>
+ *
+ * Based on the previous version of the driver for 2.4 kernels by:
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ *
+ * v4l2_device/v4l2_subdev conversion by:
+ * Copyright (C) 2009 Hans Verkuil <hverkuil@xs4all.nl>
+ *
+ * Note: this conversion is untested! Please contact the linux-media
+ * mailinglist if you can test this, together with the test results.
+ */
+
+/*
+ * TODO:
+ * - remove "mark pages reserved-hacks" from memory allocation code
+ * and implement fault()
+ * - check decimation, calculating and reporting image size when
+ * using decimation
+ * - implement read(), user mode buffers and overlay (?)
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/time.h>
+#include <linux/kmod.h>
+
+#include <linux/i2c.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/mutex.h>
+
+#include <asm/paccess.h>
+#include <asm/io.h>
+#include <asm/sgi/ip22.h>
+#include <asm/sgi/mc.h>
+
+#include "vino.h"
+#include "saa7191.h"
+#include "indycam.h"
+
+/* Uncomment the following line to get lots and lots of (mostly useless)
+ * debug info.
+ * Note that the debug output also slows down the driver significantly */
+// #define VINO_DEBUG
+// #define VINO_DEBUG_INT
+
+#define VINO_MODULE_VERSION "0.0.7"
+
+MODULE_DESCRIPTION("SGI VINO Video4Linux2 driver");
+MODULE_VERSION(VINO_MODULE_VERSION);
+MODULE_AUTHOR("Mikael Nousiainen <tmnousia@cc.hut.fi>");
+MODULE_LICENSE("GPL");
+
+#ifdef VINO_DEBUG
+#define dprintk(x...) printk("VINO: " x);
+#else
+#define dprintk(x...)
+#endif
+
+#define VINO_NO_CHANNEL 0
+#define VINO_CHANNEL_A 1
+#define VINO_CHANNEL_B 2
+
+#define VINO_PAL_WIDTH 768
+#define VINO_PAL_HEIGHT 576
+#define VINO_NTSC_WIDTH 640
+#define VINO_NTSC_HEIGHT 480
+
+#define VINO_MIN_WIDTH 32
+#define VINO_MIN_HEIGHT 32
+
+#define VINO_CLIPPING_START_ODD_D1 1
+#define VINO_CLIPPING_START_ODD_PAL 15
+#define VINO_CLIPPING_START_ODD_NTSC 12
+
+#define VINO_CLIPPING_START_EVEN_D1 2
+#define VINO_CLIPPING_START_EVEN_PAL 15
+#define VINO_CLIPPING_START_EVEN_NTSC 12
+
+#define VINO_INPUT_CHANNEL_COUNT 3
+
+/* the number is the index for vino_inputs */
+#define VINO_INPUT_NONE -1
+#define VINO_INPUT_COMPOSITE 0
+#define VINO_INPUT_SVIDEO 1
+#define VINO_INPUT_D1 2
+
+#define VINO_PAGE_RATIO (PAGE_SIZE / VINO_PAGE_SIZE)
+
+#define VINO_FIFO_THRESHOLD_DEFAULT 16
+
+#define VINO_FRAMEBUFFER_SIZE ((VINO_PAL_WIDTH \
+ * VINO_PAL_HEIGHT * 4 \
+ + 3 * PAGE_SIZE) & ~(PAGE_SIZE - 1))
+
+#define VINO_FRAMEBUFFER_COUNT_MAX 8
+
+#define VINO_FRAMEBUFFER_UNUSED 0
+#define VINO_FRAMEBUFFER_IN_USE 1
+#define VINO_FRAMEBUFFER_READY 2
+
+#define VINO_QUEUE_ERROR -1
+#define VINO_QUEUE_MAGIC 0x20050125
+
+#define VINO_MEMORY_NONE 0
+#define VINO_MEMORY_MMAP 1
+#define VINO_MEMORY_USERPTR 2
+
+#define VINO_DUMMY_DESC_COUNT 4
+#define VINO_DESC_FETCH_DELAY 5 /* microseconds */
+
+#define VINO_MAX_FRAME_SKIP_COUNT 128
+
+/* the number is the index for vino_data_formats */
+#define VINO_DATA_FMT_NONE -1
+#define VINO_DATA_FMT_GREY 0
+#define VINO_DATA_FMT_RGB332 1
+#define VINO_DATA_FMT_RGB32 2
+#define VINO_DATA_FMT_YUV 3
+
+#define VINO_DATA_FMT_COUNT 4
+
+/* the number is the index for vino_data_norms */
+#define VINO_DATA_NORM_NONE -1
+#define VINO_DATA_NORM_NTSC 0
+#define VINO_DATA_NORM_PAL 1
+#define VINO_DATA_NORM_SECAM 2
+#define VINO_DATA_NORM_D1 3
+
+#define VINO_DATA_NORM_COUNT 4
+
+/* I2C controller flags */
+#define SGI_I2C_FORCE_IDLE (0 << 0)
+#define SGI_I2C_NOT_IDLE (1 << 0)
+#define SGI_I2C_WRITE (0 << 1)
+#define SGI_I2C_READ (1 << 1)
+#define SGI_I2C_RELEASE_BUS (0 << 2)
+#define SGI_I2C_HOLD_BUS (1 << 2)
+#define SGI_I2C_XFER_DONE (0 << 4)
+#define SGI_I2C_XFER_BUSY (1 << 4)
+#define SGI_I2C_ACK (0 << 5)
+#define SGI_I2C_NACK (1 << 5)
+#define SGI_I2C_BUS_OK (0 << 7)
+#define SGI_I2C_BUS_ERR (1 << 7)
+
+/* Internal data structure definitions */
+
+struct vino_input {
+ char *name;
+ v4l2_std_id std;
+};
+
+struct vino_clipping {
+ unsigned int left, right, top, bottom;
+};
+
+struct vino_data_format {
+ /* the description */
+ char *description;
+ /* bytes per pixel */
+ unsigned int bpp;
+ /* V4L2 fourcc code */
+ __u32 pixelformat;
+ /* V4L2 colorspace (duh!) */
+ enum v4l2_colorspace colorspace;
+};
+
+struct vino_data_norm {
+ char *description;
+ unsigned int width, height;
+ struct vino_clipping odd;
+ struct vino_clipping even;
+
+ v4l2_std_id std;
+ unsigned int fps_min, fps_max;
+ __u32 framelines;
+};
+
+struct vino_descriptor_table {
+ /* the number of PAGE_SIZE sized pages in the buffer */
+ unsigned int page_count;
+ /* virtual (kmalloc'd) pointers to the actual data
+ * (in PAGE_SIZE chunks, used with mmap streaming) */
+ unsigned long *virtual;
+
+ /* cpu address for the VINO descriptor table
+ * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+ unsigned long *dma_cpu;
+ /* dma address for the VINO descriptor table
+ * (contains DMA addresses, VINO_PAGE_SIZE chunks) */
+ dma_addr_t dma;
+};
+
+struct vino_framebuffer {
+ /* identifier nubmer */
+ unsigned int id;
+ /* the length of the whole buffer */
+ unsigned int size;
+ /* the length of actual data in buffer */
+ unsigned int data_size;
+ /* the data format */
+ unsigned int data_format;
+ /* the state of buffer data */
+ unsigned int state;
+ /* is the buffer mapped in user space? */
+ unsigned int map_count;
+ /* memory offset for mmap() */
+ unsigned int offset;
+ /* frame counter */
+ unsigned int frame_counter;
+ /* timestamp (written when image capture finishes) */
+ struct timeval timestamp;
+
+ struct vino_descriptor_table desc_table;
+
+ spinlock_t state_lock;
+};
+
+struct vino_framebuffer_fifo {
+ unsigned int length;
+
+ unsigned int used;
+ unsigned int head;
+ unsigned int tail;
+
+ unsigned int data[VINO_FRAMEBUFFER_COUNT_MAX];
+};
+
+struct vino_framebuffer_queue {
+ unsigned int magic;
+
+ /* VINO_MEMORY_NONE, VINO_MEMORY_MMAP or VINO_MEMORY_USERPTR */
+ unsigned int type;
+ unsigned int length;
+
+ /* data field of in and out contain index numbers for buffer */
+ struct vino_framebuffer_fifo in;
+ struct vino_framebuffer_fifo out;
+
+ struct vino_framebuffer *buffer[VINO_FRAMEBUFFER_COUNT_MAX];
+
+ spinlock_t queue_lock;
+ struct mutex queue_mutex;
+ wait_queue_head_t frame_wait_queue;
+};
+
+struct vino_interrupt_data {
+ struct timeval timestamp;
+ unsigned int frame_counter;
+ unsigned int skip_count;
+ unsigned int skip;
+};
+
+struct vino_channel_settings {
+ unsigned int channel;
+
+ int input;
+ unsigned int data_format;
+ unsigned int data_norm;
+ struct vino_clipping clipping;
+ unsigned int decimation;
+ unsigned int line_size;
+ unsigned int alpha;
+ unsigned int fps;
+ unsigned int framert_reg;
+
+ unsigned int fifo_threshold;
+
+ struct vino_framebuffer_queue fb_queue;
+
+ /* number of the current field */
+ unsigned int field;
+
+ /* read in progress */
+ int reading;
+ /* streaming is active */
+ int streaming;
+ /* the driver is currently processing the queue */
+ int capturing;
+
+ struct mutex mutex;
+ spinlock_t capture_lock;
+
+ unsigned int users;
+
+ struct vino_interrupt_data int_data;
+
+ /* V4L support */
+ struct video_device *vdev;
+};
+
+struct vino_settings {
+ struct v4l2_device v4l2_dev;
+ struct vino_channel_settings a;
+ struct vino_channel_settings b;
+
+ /* the channel which owns this client:
+ * VINO_NO_CHANNEL, VINO_CHANNEL_A or VINO_CHANNEL_B */
+ unsigned int decoder_owner;
+ struct v4l2_subdev *decoder;
+ unsigned int camera_owner;
+ struct v4l2_subdev *camera;
+
+ /* a lock for vino register access */
+ spinlock_t vino_lock;
+ /* a lock for channel input changes */
+ spinlock_t input_lock;
+
+ unsigned long dummy_page;
+ struct vino_descriptor_table dummy_desc_table;
+};
+
+/* Module parameters */
+
+/*
+ * Using vino_pixel_conversion the ABGR32-format pixels supplied
+ * by the VINO chip can be converted to more common formats
+ * like RGBA32 (or probably RGB24 in the future). This way we
+ * can give out data that can be specified correctly with
+ * the V4L2-definitions.
+ *
+ * The pixel format is specified as RGBA32 when no conversion
+ * is used.
+ *
+ * Note that this only affects the 32-bit bit depth.
+ *
+ * Use non-zero value to enable conversion.
+ */
+static int vino_pixel_conversion;
+
+module_param_named(pixelconv, vino_pixel_conversion, int, 0);
+
+MODULE_PARM_DESC(pixelconv,
+ "enable pixel conversion (non-zero value enables)");
+
+/* Internal data structures */
+
+static struct sgi_vino *vino;
+
+static struct vino_settings *vino_drvdata;
+
+#define camera_call(o, f, args...) \
+ v4l2_subdev_call(vino_drvdata->camera, o, f, ##args)
+#define decoder_call(o, f, args...) \
+ v4l2_subdev_call(vino_drvdata->decoder, o, f, ##args)
+
+static const char *vino_driver_name = "vino";
+static const char *vino_driver_description = "SGI VINO";
+static const char *vino_bus_name = "GIO64 bus";
+static const char *vino_vdev_name_a = "SGI VINO Channel A";
+static const char *vino_vdev_name_b = "SGI VINO Channel B";
+
+static void vino_capture_tasklet(unsigned long channel);
+
+DECLARE_TASKLET(vino_tasklet_a, vino_capture_tasklet, VINO_CHANNEL_A);
+DECLARE_TASKLET(vino_tasklet_b, vino_capture_tasklet, VINO_CHANNEL_B);
+
+static const struct vino_input vino_inputs[] = {
+ {
+ .name = "Composite",
+ .std = V4L2_STD_NTSC | V4L2_STD_PAL
+ | V4L2_STD_SECAM,
+ }, {
+ .name = "S-Video",
+ .std = V4L2_STD_NTSC | V4L2_STD_PAL
+ | V4L2_STD_SECAM,
+ }, {
+ .name = "D1/IndyCam",
+ .std = V4L2_STD_NTSC,
+ }
+};
+
+static const struct vino_data_format vino_data_formats[] = {
+ {
+ .description = "8-bit greyscale",
+ .bpp = 1,
+ .pixelformat = V4L2_PIX_FMT_GREY,
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ }, {
+ .description = "8-bit dithered RGB 3-3-2",
+ .bpp = 1,
+ .pixelformat = V4L2_PIX_FMT_RGB332,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ }, {
+ .description = "32-bit RGB",
+ .bpp = 4,
+ .pixelformat = V4L2_PIX_FMT_RGB32,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ }, {
+ .description = "YUV 4:2:2",
+ .bpp = 2,
+ .pixelformat = V4L2_PIX_FMT_YUYV, // XXX: swapped?
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ }
+};
+
+static const struct vino_data_norm vino_data_norms[] = {
+ {
+ .description = "NTSC",
+ .std = V4L2_STD_NTSC,
+ .fps_min = 6,
+ .fps_max = 30,
+ .framelines = 525,
+ .width = VINO_NTSC_WIDTH,
+ .height = VINO_NTSC_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_NTSC,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_NTSC
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_NTSC,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_NTSC
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ }, {
+ .description = "PAL",
+ .std = V4L2_STD_PAL,
+ .fps_min = 5,
+ .fps_max = 25,
+ .framelines = 625,
+ .width = VINO_PAL_WIDTH,
+ .height = VINO_PAL_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ }, {
+ .description = "SECAM",
+ .std = V4L2_STD_SECAM,
+ .fps_min = 5,
+ .fps_max = 25,
+ .framelines = 625,
+ .width = VINO_PAL_WIDTH,
+ .height = VINO_PAL_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_PAL,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_PAL
+ + VINO_PAL_HEIGHT / 2 - 1,
+ .right = VINO_PAL_WIDTH,
+ },
+ }, {
+ .description = "NTSC/D1",
+ .std = V4L2_STD_NTSC,
+ .fps_min = 6,
+ .fps_max = 30,
+ .framelines = 525,
+ .width = VINO_NTSC_WIDTH,
+ .height = VINO_NTSC_HEIGHT,
+ .odd = {
+ .top = VINO_CLIPPING_START_ODD_D1,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_ODD_D1
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ .even = {
+ .top = VINO_CLIPPING_START_EVEN_D1,
+ .left = 0,
+ .bottom = VINO_CLIPPING_START_EVEN_D1
+ + VINO_NTSC_HEIGHT / 2 - 1,
+ .right = VINO_NTSC_WIDTH,
+ },
+ }
+};
+
+#define VINO_INDYCAM_V4L2_CONTROL_COUNT 9
+
+struct v4l2_queryctrl vino_indycam_v4l2_controls[] = {
+ {
+ .id = V4L2_CID_AUTOGAIN,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Automatic Gain Control",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = INDYCAM_AGC_DEFAULT,
+ }, {
+ .id = V4L2_CID_AUTO_WHITE_BALANCE,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Automatic White Balance",
+ .minimum = 0,
+ .maximum = 1,
+ .step = 1,
+ .default_value = INDYCAM_AWB_DEFAULT,
+ }, {
+ .id = V4L2_CID_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gain",
+ .minimum = INDYCAM_GAIN_MIN,
+ .maximum = INDYCAM_GAIN_MAX,
+ .step = 1,
+ .default_value = INDYCAM_GAIN_DEFAULT,
+ }, {
+ .id = INDYCAM_CONTROL_RED_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red Saturation",
+ .minimum = INDYCAM_RED_SATURATION_MIN,
+ .maximum = INDYCAM_RED_SATURATION_MAX,
+ .step = 1,
+ .default_value = INDYCAM_RED_SATURATION_DEFAULT,
+ }, {
+ .id = INDYCAM_CONTROL_BLUE_SATURATION,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue Saturation",
+ .minimum = INDYCAM_BLUE_SATURATION_MIN,
+ .maximum = INDYCAM_BLUE_SATURATION_MAX,
+ .step = 1,
+ .default_value = INDYCAM_BLUE_SATURATION_DEFAULT,
+ }, {
+ .id = V4L2_CID_RED_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Red Balance",
+ .minimum = INDYCAM_RED_BALANCE_MIN,
+ .maximum = INDYCAM_RED_BALANCE_MAX,
+ .step = 1,
+ .default_value = INDYCAM_RED_BALANCE_DEFAULT,
+ }, {
+ .id = V4L2_CID_BLUE_BALANCE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Blue Balance",
+ .minimum = INDYCAM_BLUE_BALANCE_MIN,
+ .maximum = INDYCAM_BLUE_BALANCE_MAX,
+ .step = 1,
+ .default_value = INDYCAM_BLUE_BALANCE_DEFAULT,
+ }, {
+ .id = V4L2_CID_EXPOSURE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Shutter Control",
+ .minimum = INDYCAM_SHUTTER_MIN,
+ .maximum = INDYCAM_SHUTTER_MAX,
+ .step = 1,
+ .default_value = INDYCAM_SHUTTER_DEFAULT,
+ }, {
+ .id = V4L2_CID_GAMMA,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Gamma",
+ .minimum = INDYCAM_GAMMA_MIN,
+ .maximum = INDYCAM_GAMMA_MAX,
+ .step = 1,
+ .default_value = INDYCAM_GAMMA_DEFAULT,
+ }
+};
+
+#define VINO_SAA7191_V4L2_CONTROL_COUNT 9
+
+struct v4l2_queryctrl vino_saa7191_v4l2_controls[] = {
+ {
+ .id = V4L2_CID_HUE,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Hue",
+ .minimum = SAA7191_HUE_MIN,
+ .maximum = SAA7191_HUE_MAX,
+ .step = 1,
+ .default_value = SAA7191_HUE_DEFAULT,
+ }, {
+ .id = SAA7191_CONTROL_BANDPASS,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Luminance Bandpass",
+ .minimum = SAA7191_BANDPASS_MIN,
+ .maximum = SAA7191_BANDPASS_MAX,
+ .step = 1,
+ .default_value = SAA7191_BANDPASS_DEFAULT,
+ }, {
+ .id = SAA7191_CONTROL_BANDPASS_WEIGHT,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Luminance Bandpass Weight",
+ .minimum = SAA7191_BANDPASS_WEIGHT_MIN,
+ .maximum = SAA7191_BANDPASS_WEIGHT_MAX,
+ .step = 1,
+ .default_value = SAA7191_BANDPASS_WEIGHT_DEFAULT,
+ }, {
+ .id = SAA7191_CONTROL_CORING,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "HF Luminance Coring",
+ .minimum = SAA7191_CORING_MIN,
+ .maximum = SAA7191_CORING_MAX,
+ .step = 1,
+ .default_value = SAA7191_CORING_DEFAULT,
+ }, {
+ .id = SAA7191_CONTROL_FORCE_COLOUR,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "Force Colour",
+ .minimum = SAA7191_FORCE_COLOUR_MIN,
+ .maximum = SAA7191_FORCE_COLOUR_MAX,
+ .step = 1,
+ .default_value = SAA7191_FORCE_COLOUR_DEFAULT,
+ }, {
+ .id = SAA7191_CONTROL_CHROMA_GAIN,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Chrominance Gain Control",
+ .minimum = SAA7191_CHROMA_GAIN_MIN,
+ .maximum = SAA7191_CHROMA_GAIN_MAX,
+ .step = 1,
+ .default_value = SAA7191_CHROMA_GAIN_DEFAULT,
+ }, {
+ .id = SAA7191_CONTROL_VTRC,
+ .type = V4L2_CTRL_TYPE_BOOLEAN,
+ .name = "VTR Time Constant",
+ .minimum = SAA7191_VTRC_MIN,
+ .maximum = SAA7191_VTRC_MAX,
+ .step = 1,
+ .default_value = SAA7191_VTRC_DEFAULT,
+ }, {
+ .id = SAA7191_CONTROL_LUMA_DELAY,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Luminance Delay Compensation",
+ .minimum = SAA7191_LUMA_DELAY_MIN,
+ .maximum = SAA7191_LUMA_DELAY_MAX,
+ .step = 1,
+ .default_value = SAA7191_LUMA_DELAY_DEFAULT,
+ }, {
+ .id = SAA7191_CONTROL_VNR,
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .name = "Vertical Noise Reduction",
+ .minimum = SAA7191_VNR_MIN,
+ .maximum = SAA7191_VNR_MAX,
+ .step = 1,
+ .default_value = SAA7191_VNR_DEFAULT,
+ }
+};
+
+/* VINO framebuffer/DMA descriptor management */
+
+static void vino_free_buffer_with_count(struct vino_framebuffer *fb,
+ unsigned int count)
+{
+ unsigned int i;
+
+ dprintk("vino_free_buffer_with_count(): count = %d\n", count);
+
+ for (i = 0; i < count; i++) {
+ ClearPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
+ dma_unmap_single(NULL,
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ free_page(fb->desc_table.virtual[i]);
+ }
+
+ dma_free_coherent(NULL,
+ VINO_PAGE_RATIO * (fb->desc_table.page_count + 4) *
+ sizeof(dma_addr_t), (void *)fb->desc_table.dma_cpu,
+ fb->desc_table.dma);
+ kfree(fb->desc_table.virtual);
+
+ memset(fb, 0, sizeof(struct vino_framebuffer));
+}
+
+static void vino_free_buffer(struct vino_framebuffer *fb)
+{
+ vino_free_buffer_with_count(fb, fb->desc_table.page_count);
+}
+
+static int vino_allocate_buffer(struct vino_framebuffer *fb,
+ unsigned int size)
+{
+ unsigned int count, i, j;
+ int ret = 0;
+
+ dprintk("vino_allocate_buffer():\n");
+
+ if (size < 1)
+ return -EINVAL;
+
+ memset(fb, 0, sizeof(struct vino_framebuffer));
+
+ count = ((size / PAGE_SIZE) + 4) & ~3;
+
+ dprintk("vino_allocate_buffer(): size = %d, count = %d\n",
+ size, count);
+
+ /* allocate memory for table with virtual (page) addresses */
+ fb->desc_table.virtual =
+ kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+ if (!fb->desc_table.virtual)
+ return -ENOMEM;
+
+ /* allocate memory for table with dma addresses
+ * (has space for four extra descriptors) */
+ fb->desc_table.dma_cpu =
+ dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+ sizeof(dma_addr_t), &fb->desc_table.dma,
+ GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.dma_cpu) {
+ ret = -ENOMEM;
+ goto out_free_virtual;
+ }
+
+ /* allocate pages for the buffer and acquire the according
+ * dma addresses */
+ for (i = 0; i < count; i++) {
+ dma_addr_t dma_data_addr;
+
+ fb->desc_table.virtual[i] =
+ get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.virtual[i]) {
+ ret = -ENOBUFS;
+ break;
+ }
+
+ dma_data_addr =
+ dma_map_single(NULL,
+ (void *)fb->desc_table.virtual[i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+
+ for (j = 0; j < VINO_PAGE_RATIO; j++) {
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+ dma_data_addr + VINO_PAGE_SIZE * j;
+ }
+
+ SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
+ }
+
+ /* page_count needs to be set anyway, because the descriptor table has
+ * been allocated according to this number */
+ fb->desc_table.page_count = count;
+
+ if (ret) {
+ /* the descriptor with index i doesn't contain
+ * a valid address yet */
+ vino_free_buffer_with_count(fb, i);
+ return ret;
+ }
+
+ //fb->size = size;
+ fb->size = count * PAGE_SIZE;
+ fb->data_format = VINO_DATA_FMT_NONE;
+
+ /* set the dma stop-bit for the last (count+1)th descriptor */
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+ return 0;
+
+ out_free_virtual:
+ kfree(fb->desc_table.virtual);
+ return ret;
+}
+
+#if 0
+/* user buffers not fully implemented yet */
+static int vino_prepare_user_buffer(struct vino_framebuffer *fb,
+ void *user,
+ unsigned int size)
+{
+ unsigned int count, i, j;
+ int ret = 0;
+
+ dprintk("vino_prepare_user_buffer():\n");
+
+ if (size < 1)
+ return -EINVAL;
+
+ memset(fb, 0, sizeof(struct vino_framebuffer));
+
+ count = ((size / PAGE_SIZE)) & ~3;
+
+ dprintk("vino_prepare_user_buffer(): size = %d, count = %d\n",
+ size, count);
+
+ /* allocate memory for table with virtual (page) addresses */
+ fb->desc_table.virtual = (unsigned long *)
+ kmalloc(count * sizeof(unsigned long), GFP_KERNEL);
+ if (!fb->desc_table.virtual)
+ return -ENOMEM;
+
+ /* allocate memory for table with dma addresses
+ * (has space for four extra descriptors) */
+ fb->desc_table.dma_cpu =
+ dma_alloc_coherent(NULL, VINO_PAGE_RATIO * (count + 4) *
+ sizeof(dma_addr_t), &fb->desc_table.dma,
+ GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.dma_cpu) {
+ ret = -ENOMEM;
+ goto out_free_virtual;
+ }
+
+ /* allocate pages for the buffer and acquire the according
+ * dma addresses */
+ for (i = 0; i < count; i++) {
+ dma_addr_t dma_data_addr;
+
+ fb->desc_table.virtual[i] =
+ get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!fb->desc_table.virtual[i]) {
+ ret = -ENOBUFS;
+ break;
+ }
+
+ dma_data_addr =
+ dma_map_single(NULL,
+ (void *)fb->desc_table.virtual[i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+
+ for (j = 0; j < VINO_PAGE_RATIO; j++) {
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i + j] =
+ dma_data_addr + VINO_PAGE_SIZE * j;
+ }
+
+ SetPageReserved(virt_to_page((void *)fb->desc_table.virtual[i]));
+ }
+
+ /* page_count needs to be set anyway, because the descriptor table has
+ * been allocated according to this number */
+ fb->desc_table.page_count = count;
+
+ if (ret) {
+ /* the descriptor with index i doesn't contain
+ * a valid address yet */
+ vino_free_buffer_with_count(fb, i);
+ return ret;
+ }
+
+ //fb->size = size;
+ fb->size = count * PAGE_SIZE;
+
+ /* set the dma stop-bit for the last (count+1)th descriptor */
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * count] = VINO_DESC_STOP;
+ return 0;
+
+ out_free_virtual:
+ kfree(fb->desc_table.virtual);
+ return ret;
+}
+#endif
+
+static void vino_sync_buffer(struct vino_framebuffer *fb)
+{
+ int i;
+
+ dprintk("vino_sync_buffer():\n");
+
+ for (i = 0; i < fb->desc_table.page_count; i++)
+ dma_sync_single_for_cpu(NULL,
+ fb->desc_table.dma_cpu[VINO_PAGE_RATIO * i],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+}
+
+/* Framebuffer fifo functions (need to be locked externally) */
+
+static inline void vino_fifo_init(struct vino_framebuffer_fifo *f,
+ unsigned int length)
+{
+ f->length = 0;
+ f->used = 0;
+ f->head = 0;
+ f->tail = 0;
+
+ if (length > VINO_FRAMEBUFFER_COUNT_MAX)
+ length = VINO_FRAMEBUFFER_COUNT_MAX;
+
+ f->length = length;
+}
+
+/* returns true/false */
+static inline int vino_fifo_has_id(struct vino_framebuffer_fifo *f,
+ unsigned int id)
+{
+ unsigned int i;
+
+ for (i = f->head; i == (f->tail - 1); i = (i + 1) % f->length) {
+ if (f->data[i] == id)
+ return 1;
+ }
+
+ return 0;
+}
+
+#if 0
+/* returns true/false */
+static inline int vino_fifo_full(struct vino_framebuffer_fifo *f)
+{
+ return (f->used == f->length);
+}
+#endif
+
+static inline unsigned int vino_fifo_get_used(struct vino_framebuffer_fifo *f)
+{
+ return f->used;
+}
+
+static int vino_fifo_enqueue(struct vino_framebuffer_fifo *f, unsigned int id)
+{
+ if (id >= f->length) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ if (vino_fifo_has_id(f, id)) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ if (f->used < f->length) {
+ f->data[f->tail] = id;
+ f->tail = (f->tail + 1) % f->length;
+ f->used++;
+ } else {
+ return VINO_QUEUE_ERROR;
+ }
+
+ return 0;
+}
+
+static int vino_fifo_peek(struct vino_framebuffer_fifo *f, unsigned int *id)
+{
+ if (f->used > 0) {
+ *id = f->data[f->head];
+ } else {
+ return VINO_QUEUE_ERROR;
+ }
+
+ return 0;
+}
+
+static int vino_fifo_dequeue(struct vino_framebuffer_fifo *f, unsigned int *id)
+{
+ if (f->used > 0) {
+ *id = f->data[f->head];
+ f->head = (f->head + 1) % f->length;
+ f->used--;
+ } else {
+ return VINO_QUEUE_ERROR;
+ }
+
+ return 0;
+}
+
+/* Framebuffer queue functions */
+
+/* execute with queue_lock locked */
+static void vino_queue_free_with_count(struct vino_framebuffer_queue *q,
+ unsigned int length)
+{
+ unsigned int i;
+
+ q->length = 0;
+ memset(&q->in, 0, sizeof(struct vino_framebuffer_fifo));
+ memset(&q->out, 0, sizeof(struct vino_framebuffer_fifo));
+ for (i = 0; i < length; i++) {
+ dprintk("vino_queue_free_with_count(): freeing buffer %d\n",
+ i);
+ vino_free_buffer(q->buffer[i]);
+ kfree(q->buffer[i]);
+ }
+
+ q->type = VINO_MEMORY_NONE;
+ q->magic = 0;
+}
+
+static void vino_queue_free(struct vino_framebuffer_queue *q)
+{
+ dprintk("vino_queue_free():\n");
+
+ if (q->magic != VINO_QUEUE_MAGIC)
+ return;
+ if (q->type != VINO_MEMORY_MMAP)
+ return;
+
+ mutex_lock(&q->queue_mutex);
+
+ vino_queue_free_with_count(q, q->length);
+
+ mutex_unlock(&q->queue_mutex);
+}
+
+static int vino_queue_init(struct vino_framebuffer_queue *q,
+ unsigned int *length)
+{
+ unsigned int i;
+ int ret = 0;
+
+ dprintk("vino_queue_init(): length = %d\n", *length);
+
+ if (q->magic == VINO_QUEUE_MAGIC) {
+ dprintk("vino_queue_init(): queue already initialized!\n");
+ return -EINVAL;
+ }
+
+ if (q->type != VINO_MEMORY_NONE) {
+ dprintk("vino_queue_init(): queue already initialized!\n");
+ return -EINVAL;
+ }
+
+ if (*length < 1)
+ return -EINVAL;
+
+ mutex_lock(&q->queue_mutex);
+
+ if (*length > VINO_FRAMEBUFFER_COUNT_MAX)
+ *length = VINO_FRAMEBUFFER_COUNT_MAX;
+
+ q->length = 0;
+
+ for (i = 0; i < *length; i++) {
+ dprintk("vino_queue_init(): allocating buffer %d\n", i);
+ q->buffer[i] = kmalloc(sizeof(struct vino_framebuffer),
+ GFP_KERNEL);
+ if (!q->buffer[i]) {
+ dprintk("vino_queue_init(): kmalloc() failed\n");
+ ret = -ENOMEM;
+ break;
+ }
+
+ ret = vino_allocate_buffer(q->buffer[i],
+ VINO_FRAMEBUFFER_SIZE);
+ if (ret) {
+ kfree(q->buffer[i]);
+ dprintk("vino_queue_init(): "
+ "vino_allocate_buffer() failed\n");
+ break;
+ }
+
+ q->buffer[i]->id = i;
+ if (i > 0) {
+ q->buffer[i]->offset = q->buffer[i - 1]->offset +
+ q->buffer[i - 1]->size;
+ } else {
+ q->buffer[i]->offset = 0;
+ }
+
+ spin_lock_init(&q->buffer[i]->state_lock);
+
+ dprintk("vino_queue_init(): buffer = %d, offset = %d, "
+ "size = %d\n", i, q->buffer[i]->offset,
+ q->buffer[i]->size);
+ }
+
+ if (ret) {
+ vino_queue_free_with_count(q, i);
+ *length = 0;
+ } else {
+ q->length = *length;
+ vino_fifo_init(&q->in, q->length);
+ vino_fifo_init(&q->out, q->length);
+ q->type = VINO_MEMORY_MMAP;
+ q->magic = VINO_QUEUE_MAGIC;
+ }
+
+ mutex_unlock(&q->queue_mutex);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_add(struct
+ vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned int total;
+ unsigned long flags;
+
+ dprintk("vino_queue_add(): id = %d\n", id);
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (id >= q->length)
+ goto out;
+
+ /* not needed?: if (vino_fifo_full(&q->out)) {
+ goto out;
+ }*/
+ /* check that outgoing queue isn't already full
+ * (or that it won't become full) */
+ total = vino_fifo_get_used(&q->in) +
+ vino_fifo_get_used(&q->out);
+ if (total >= q->length)
+ goto out;
+
+ if (vino_fifo_enqueue(&q->in, id))
+ goto out;
+
+ ret = q->buffer[id];
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_transfer(struct
+ vino_framebuffer_queue *q)
+{
+ struct vino_framebuffer *ret = NULL;
+ struct vino_framebuffer *fb;
+ int id;
+ unsigned long flags;
+
+ dprintk("vino_queue_transfer():\n");
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ // now this actually removes an entry from the incoming queue
+ if (vino_fifo_dequeue(&q->in, &id)) {
+ goto out;
+ }
+
+ dprintk("vino_queue_transfer(): id = %d\n", id);
+ fb = q->buffer[id];
+
+ // we have already checked that the outgoing queue is not full, but...
+ if (vino_fifo_enqueue(&q->out, id)) {
+ printk(KERN_ERR "vino_queue_transfer(): "
+ "outgoing queue is full, this shouldn't happen!\n");
+ goto out;
+ }
+
+ ret = fb;
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+/* returns true/false */
+static int vino_queue_incoming_contains(struct vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ ret = vino_fifo_has_id(&q->in, id);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+/* returns true/false */
+static int vino_queue_outgoing_contains(struct vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ ret = vino_fifo_has_id(&q->out, id);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static int vino_queue_get_incoming(struct vino_framebuffer_queue *q,
+ unsigned int *used)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0) {
+ ret = VINO_QUEUE_ERROR;
+ goto out;
+ }
+
+ *used = vino_fifo_get_used(&q->in);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static int vino_queue_get_outgoing(struct vino_framebuffer_queue *q,
+ unsigned int *used)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0) {
+ ret = VINO_QUEUE_ERROR;
+ goto out;
+ }
+
+ *used = vino_fifo_get_used(&q->out);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+#if 0
+static int vino_queue_get_total(struct vino_framebuffer_queue *q,
+ unsigned int *total)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return VINO_QUEUE_ERROR;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0) {
+ ret = VINO_QUEUE_ERROR;
+ goto out;
+ }
+
+ *total = vino_fifo_get_used(&q->in) +
+ vino_fifo_get_used(&q->out);
+
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+#endif
+
+static struct vino_framebuffer *vino_queue_peek(struct
+ vino_framebuffer_queue *q,
+ unsigned int *id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (vino_fifo_peek(&q->in, id)) {
+ goto out;
+ }
+
+ ret = q->buffer[*id];
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct vino_framebuffer *vino_queue_remove(struct
+ vino_framebuffer_queue *q,
+ unsigned int *id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned long flags;
+ dprintk("vino_queue_remove():\n");
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (vino_fifo_dequeue(&q->out, id)) {
+ goto out;
+ }
+
+ dprintk("vino_queue_remove(): id = %d\n", *id);
+ ret = q->buffer[*id];
+out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static struct
+vino_framebuffer *vino_queue_get_buffer(struct vino_framebuffer_queue *q,
+ unsigned int id)
+{
+ struct vino_framebuffer *ret = NULL;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+
+ if (q->length == 0)
+ goto out;
+
+ if (id >= q->length)
+ goto out;
+
+ ret = q->buffer[id];
+ out:
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+static unsigned int vino_queue_get_length(struct vino_framebuffer_queue *q)
+{
+ unsigned int length = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return length;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+ length = q->length;
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return length;
+}
+
+static int vino_queue_has_mapped_buffers(struct vino_framebuffer_queue *q)
+{
+ unsigned int i;
+ int ret = 0;
+ unsigned long flags;
+
+ if (q->magic != VINO_QUEUE_MAGIC) {
+ return ret;
+ }
+
+ spin_lock_irqsave(&q->queue_lock, flags);
+ for (i = 0; i < q->length; i++) {
+ if (q->buffer[i]->map_count > 0) {
+ ret = 1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&q->queue_lock, flags);
+
+ return ret;
+}
+
+/* VINO functions */
+
+/* execute with input_lock locked */
+static void vino_update_line_size(struct vino_channel_settings *vcs)
+{
+ unsigned int w = vcs->clipping.right - vcs->clipping.left;
+ unsigned int d = vcs->decimation;
+ unsigned int bpp = vino_data_formats[vcs->data_format].bpp;
+ unsigned int lsize;
+
+ dprintk("update_line_size(): before: w = %d, d = %d, "
+ "line_size = %d\n", w, d, vcs->line_size);
+
+ /* line size must be multiple of 8 bytes */
+ lsize = (bpp * (w / d)) & ~7;
+ w = (lsize / bpp) * d;
+
+ vcs->clipping.right = vcs->clipping.left + w;
+ vcs->line_size = lsize;
+
+ dprintk("update_line_size(): after: w = %d, d = %d, "
+ "line_size = %d\n", w, d, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static void vino_set_clipping(struct vino_channel_settings *vcs,
+ unsigned int x, unsigned int y,
+ unsigned int w, unsigned int h)
+{
+ unsigned int maxwidth, maxheight;
+ unsigned int d;
+
+ maxwidth = vino_data_norms[vcs->data_norm].width;
+ maxheight = vino_data_norms[vcs->data_norm].height;
+ d = vcs->decimation;
+
+ y &= ~1; /* odd/even fields */
+
+ if (x > maxwidth) {
+ x = 0;
+ }
+ if (y > maxheight) {
+ y = 0;
+ }
+
+ if (((w / d) < VINO_MIN_WIDTH)
+ || ((h / d) < VINO_MIN_HEIGHT)) {
+ w = VINO_MIN_WIDTH * d;
+ h = VINO_MIN_HEIGHT * d;
+ }
+
+ if ((x + w) > maxwidth) {
+ w = maxwidth - x;
+ if ((w / d) < VINO_MIN_WIDTH)
+ x = maxwidth - VINO_MIN_WIDTH * d;
+ }
+ if ((y + h) > maxheight) {
+ h = maxheight - y;
+ if ((h / d) < VINO_MIN_HEIGHT)
+ y = maxheight - VINO_MIN_HEIGHT * d;
+ }
+
+ vcs->clipping.left = x;
+ vcs->clipping.top = y;
+ vcs->clipping.right = x + w;
+ vcs->clipping.bottom = y + h;
+
+ vino_update_line_size(vcs);
+
+ dprintk("clipping %d, %d, %d, %d / %d - %d\n",
+ vcs->clipping.left, vcs->clipping.top, vcs->clipping.right,
+ vcs->clipping.bottom, vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static inline void vino_set_default_clipping(struct vino_channel_settings *vcs)
+{
+ vino_set_clipping(vcs, 0, 0, vino_data_norms[vcs->data_norm].width,
+ vino_data_norms[vcs->data_norm].height);
+}
+
+/* execute with input_lock locked */
+static void vino_set_scaling(struct vino_channel_settings *vcs,
+ unsigned int w, unsigned int h)
+{
+ unsigned int x, y, curw, curh, d;
+
+ x = vcs->clipping.left;
+ y = vcs->clipping.top;
+ curw = vcs->clipping.right - vcs->clipping.left;
+ curh = vcs->clipping.bottom - vcs->clipping.top;
+
+ d = max(curw / w, curh / h);
+
+ dprintk("scaling w: %d, h: %d, curw: %d, curh: %d, d: %d\n",
+ w, h, curw, curh, d);
+
+ if (d < 1) {
+ d = 1;
+ } else if (d > 8) {
+ d = 8;
+ }
+
+ vcs->decimation = d;
+ vino_set_clipping(vcs, x, y, w * d, h * d);
+
+ dprintk("scaling %d, %d, %d, %d / %d - %d\n", vcs->clipping.left,
+ vcs->clipping.top, vcs->clipping.right, vcs->clipping.bottom,
+ vcs->decimation, vcs->line_size);
+}
+
+/* execute with input_lock locked */
+static inline void vino_set_default_scaling(struct vino_channel_settings *vcs)
+{
+ vino_set_scaling(vcs, vcs->clipping.right - vcs->clipping.left,
+ vcs->clipping.bottom - vcs->clipping.top);
+}
+
+/* execute with input_lock locked */
+static void vino_set_framerate(struct vino_channel_settings *vcs,
+ unsigned int fps)
+{
+ unsigned int mask;
+
+ switch (vcs->data_norm) {
+ case VINO_DATA_NORM_NTSC:
+ case VINO_DATA_NORM_D1:
+ fps = (unsigned int)(fps / 6) * 6; // FIXME: round!
+
+ if (fps < vino_data_norms[vcs->data_norm].fps_min)
+ fps = vino_data_norms[vcs->data_norm].fps_min;
+ if (fps > vino_data_norms[vcs->data_norm].fps_max)
+ fps = vino_data_norms[vcs->data_norm].fps_max;
+
+ switch (fps) {
+ case 6:
+ mask = 0x003;
+ break;
+ case 12:
+ mask = 0x0c3;
+ break;
+ case 18:
+ mask = 0x333;
+ break;
+ case 24:
+ mask = 0x3ff;
+ break;
+ case 30:
+ mask = 0xfff;
+ break;
+ default:
+ mask = VINO_FRAMERT_FULL;
+ }
+ vcs->framert_reg = VINO_FRAMERT_RT(mask);
+ break;
+ case VINO_DATA_NORM_PAL:
+ case VINO_DATA_NORM_SECAM:
+ fps = (unsigned int)(fps / 5) * 5; // FIXME: round!
+
+ if (fps < vino_data_norms[vcs->data_norm].fps_min)
+ fps = vino_data_norms[vcs->data_norm].fps_min;
+ if (fps > vino_data_norms[vcs->data_norm].fps_max)
+ fps = vino_data_norms[vcs->data_norm].fps_max;
+
+ switch (fps) {
+ case 5:
+ mask = 0x003;
+ break;
+ case 10:
+ mask = 0x0c3;
+ break;
+ case 15:
+ mask = 0x333;
+ break;
+ case 20:
+ mask = 0x0ff;
+ break;
+ case 25:
+ mask = 0x3ff;
+ break;
+ default:
+ mask = VINO_FRAMERT_FULL;
+ }
+ vcs->framert_reg = VINO_FRAMERT_RT(mask) | VINO_FRAMERT_PAL;
+ break;
+ }
+
+ vcs->fps = fps;
+}
+
+/* execute with input_lock locked */
+static inline void vino_set_default_framerate(struct
+ vino_channel_settings *vcs)
+{
+ vino_set_framerate(vcs, vino_data_norms[vcs->data_norm].fps_max);
+}
+
+/* VINO I2C bus functions */
+
+struct i2c_algo_sgi_data {
+ void *data; /* private data for lowlevel routines */
+ unsigned (*getctrl)(void *data);
+ void (*setctrl)(void *data, unsigned val);
+ unsigned (*rdata)(void *data);
+ void (*wdata)(void *data, unsigned val);
+
+ int xfer_timeout;
+ int ack_timeout;
+};
+
+static int wait_xfer_done(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ for (i = 0; i < adap->xfer_timeout; i++) {
+ if ((adap->getctrl(adap->data) & SGI_I2C_XFER_BUSY) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int wait_ack(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ if (wait_xfer_done(adap))
+ return -ETIMEDOUT;
+ for (i = 0; i < adap->ack_timeout; i++) {
+ if ((adap->getctrl(adap->data) & SGI_I2C_NACK) == 0)
+ return 0;
+ udelay(1);
+ }
+
+ return -ETIMEDOUT;
+}
+
+static int force_idle(struct i2c_algo_sgi_data *adap)
+{
+ int i;
+
+ adap->setctrl(adap->data, SGI_I2C_FORCE_IDLE);
+ for (i = 0; i < adap->xfer_timeout; i++) {
+ if ((adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE) == 0)
+ goto out;
+ udelay(1);
+ }
+ return -ETIMEDOUT;
+out:
+ if (adap->getctrl(adap->data) & SGI_I2C_BUS_ERR)
+ return -EIO;
+ return 0;
+}
+
+static int do_address(struct i2c_algo_sgi_data *adap, unsigned int addr,
+ int rd)
+{
+ if (rd)
+ adap->setctrl(adap->data, SGI_I2C_NOT_IDLE);
+ /* Check if bus is idle, eventually force it to do so */
+ if (adap->getctrl(adap->data) & SGI_I2C_NOT_IDLE)
+ if (force_idle(adap))
+ return -EIO;
+ /* Write out the i2c chip address and specify operation */
+ adap->setctrl(adap->data,
+ SGI_I2C_HOLD_BUS | SGI_I2C_WRITE | SGI_I2C_NOT_IDLE);
+ if (rd)
+ addr |= 1;
+ adap->wdata(adap->data, addr);
+ if (wait_ack(adap))
+ return -EIO;
+ return 0;
+}
+
+static int i2c_read(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+ unsigned int len)
+{
+ int i;
+
+ adap->setctrl(adap->data,
+ SGI_I2C_HOLD_BUS | SGI_I2C_READ | SGI_I2C_NOT_IDLE);
+ for (i = 0; i < len; i++) {
+ if (wait_xfer_done(adap))
+ return -EIO;
+ buf[i] = adap->rdata(adap->data);
+ }
+ adap->setctrl(adap->data, SGI_I2C_RELEASE_BUS | SGI_I2C_FORCE_IDLE);
+
+ return 0;
+
+}
+
+static int i2c_write(struct i2c_algo_sgi_data *adap, unsigned char *buf,
+ unsigned int len)
+{
+ int i;
+
+ /* We are already in write state */
+ for (i = 0; i < len; i++) {
+ adap->wdata(adap->data, buf[i]);
+ if (wait_ack(adap))
+ return -EIO;
+ }
+ return 0;
+}
+
+static int sgi_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+ int num)
+{
+ struct i2c_algo_sgi_data *adap = i2c_adap->algo_data;
+ struct i2c_msg *p;
+ int i, err = 0;
+
+ for (i = 0; !err && i < num; i++) {
+ p = &msgs[i];
+ err = do_address(adap, p->addr, p->flags & I2C_M_RD);
+ if (err || !p->len)
+ continue;
+ if (p->flags & I2C_M_RD)
+ err = i2c_read(adap, p->buf, p->len);
+ else
+ err = i2c_write(adap, p->buf, p->len);
+ }
+
+ return (err < 0) ? err : i;
+}
+
+static u32 sgi_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_SMBUS_EMUL;
+}
+
+static const struct i2c_algorithm sgi_algo = {
+ .master_xfer = sgi_xfer,
+ .functionality = sgi_func,
+};
+
+static unsigned i2c_vino_getctrl(void *data)
+{
+ return vino->i2c_control;
+}
+
+static void i2c_vino_setctrl(void *data, unsigned val)
+{
+ vino->i2c_control = val;
+}
+
+static unsigned i2c_vino_rdata(void *data)
+{
+ return vino->i2c_data;
+}
+
+static void i2c_vino_wdata(void *data, unsigned val)
+{
+ vino->i2c_data = val;
+}
+
+static struct i2c_algo_sgi_data i2c_sgi_vino_data = {
+ .getctrl = &i2c_vino_getctrl,
+ .setctrl = &i2c_vino_setctrl,
+ .rdata = &i2c_vino_rdata,
+ .wdata = &i2c_vino_wdata,
+ .xfer_timeout = 200,
+ .ack_timeout = 1000,
+};
+
+static struct i2c_adapter vino_i2c_adapter = {
+ .name = "VINO I2C bus",
+ .algo = &sgi_algo,
+ .algo_data = &i2c_sgi_vino_data,
+ .owner = THIS_MODULE,
+};
+
+/*
+ * Prepare VINO for DMA transfer...
+ * (execute only with vino_lock and input_lock locked)
+ */
+static int vino_dma_setup(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb)
+{
+ u32 ctrl, intr;
+ struct sgi_vino_channel *ch;
+ const struct vino_data_norm *norm;
+
+ dprintk("vino_dma_setup():\n");
+
+ vcs->field = 0;
+ fb->frame_counter = 0;
+
+ ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+ norm = &vino_data_norms[vcs->data_norm];
+
+ ch->page_index = 0;
+ ch->line_count = 0;
+
+ /* VINO line size register is set 8 bytes less than actual */
+ ch->line_size = vcs->line_size - 8;
+
+ /* let VINO know where to transfer data */
+ ch->start_desc_tbl = fb->desc_table.dma;
+ ch->next_4_desc = fb->desc_table.dma;
+
+ /* give vino time to fetch the first four descriptors, 5 usec
+ * should be more than enough time */
+ udelay(VINO_DESC_FETCH_DELAY);
+
+ dprintk("vino_dma_setup(): start desc = %08x, next 4 desc = %08x\n",
+ ch->start_desc_tbl, ch->next_4_desc);
+
+ /* set the alpha register */
+ ch->alpha = vcs->alpha;
+
+ /* set clipping registers */
+ ch->clip_start = VINO_CLIP_ODD(norm->odd.top + vcs->clipping.top / 2) |
+ VINO_CLIP_EVEN(norm->even.top +
+ vcs->clipping.top / 2) |
+ VINO_CLIP_X(vcs->clipping.left);
+ ch->clip_end = VINO_CLIP_ODD(norm->odd.top +
+ vcs->clipping.bottom / 2 - 1) |
+ VINO_CLIP_EVEN(norm->even.top +
+ vcs->clipping.bottom / 2 - 1) |
+ VINO_CLIP_X(vcs->clipping.right);
+
+ /* set the size of actual content in the buffer (DECIMATION !) */
+ fb->data_size = ((vcs->clipping.right - vcs->clipping.left) /
+ vcs->decimation) *
+ ((vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation) *
+ vino_data_formats[vcs->data_format].bpp;
+
+ ch->frame_rate = vcs->framert_reg;
+
+ ctrl = vino->control;
+ intr = vino->intr_status;
+
+ if (vcs->channel == VINO_CHANNEL_A) {
+ /* All interrupt conditions for this channel was cleared
+ * so clear the interrupt status register and enable
+ * interrupts */
+ intr &= ~VINO_INTSTAT_A;
+ ctrl |= VINO_CTRL_A_INT;
+
+ /* enable synchronization */
+ ctrl |= VINO_CTRL_A_SYNC_ENBL;
+
+ /* enable frame assembly */
+ ctrl |= VINO_CTRL_A_INTERLEAVE_ENBL;
+
+ /* set decimation used */
+ if (vcs->decimation < 2)
+ ctrl &= ~VINO_CTRL_A_DEC_ENBL;
+ else {
+ ctrl |= VINO_CTRL_A_DEC_ENBL;
+ ctrl &= ~VINO_CTRL_A_DEC_SCALE_MASK;
+ ctrl |= (vcs->decimation - 1) <<
+ VINO_CTRL_A_DEC_SCALE_SHIFT;
+ }
+
+ /* select input interface */
+ if (vcs->input == VINO_INPUT_D1)
+ ctrl |= VINO_CTRL_A_SELECT;
+ else
+ ctrl &= ~VINO_CTRL_A_SELECT;
+
+ /* palette */
+ ctrl &= ~(VINO_CTRL_A_LUMA_ONLY | VINO_CTRL_A_RGB |
+ VINO_CTRL_A_DITHER);
+ } else {
+ intr &= ~VINO_INTSTAT_B;
+ ctrl |= VINO_CTRL_B_INT;
+
+ ctrl |= VINO_CTRL_B_SYNC_ENBL;
+ ctrl |= VINO_CTRL_B_INTERLEAVE_ENBL;
+
+ if (vcs->decimation < 2)
+ ctrl &= ~VINO_CTRL_B_DEC_ENBL;
+ else {
+ ctrl |= VINO_CTRL_B_DEC_ENBL;
+ ctrl &= ~VINO_CTRL_B_DEC_SCALE_MASK;
+ ctrl |= (vcs->decimation - 1) <<
+ VINO_CTRL_B_DEC_SCALE_SHIFT;
+
+ }
+ if (vcs->input == VINO_INPUT_D1)
+ ctrl |= VINO_CTRL_B_SELECT;
+ else
+ ctrl &= ~VINO_CTRL_B_SELECT;
+
+ ctrl &= ~(VINO_CTRL_B_LUMA_ONLY | VINO_CTRL_B_RGB |
+ VINO_CTRL_B_DITHER);
+ }
+
+ /* set palette */
+ fb->data_format = vcs->data_format;
+
+ switch (vcs->data_format) {
+ case VINO_DATA_FMT_GREY:
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_LUMA_ONLY : VINO_CTRL_B_LUMA_ONLY;
+ break;
+ case VINO_DATA_FMT_RGB32:
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_RGB : VINO_CTRL_B_RGB;
+ break;
+ case VINO_DATA_FMT_YUV:
+ /* nothing needs to be done */
+ break;
+ case VINO_DATA_FMT_RGB332:
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_RGB | VINO_CTRL_A_DITHER :
+ VINO_CTRL_B_RGB | VINO_CTRL_B_DITHER;
+ break;
+ }
+
+ vino->intr_status = intr;
+ vino->control = ctrl;
+
+ return 0;
+}
+
+/* (execute only with vino_lock locked) */
+static inline void vino_dma_start(struct vino_channel_settings *vcs)
+{
+ u32 ctrl = vino->control;
+
+ dprintk("vino_dma_start():\n");
+ ctrl |= (vcs->channel == VINO_CHANNEL_A) ?
+ VINO_CTRL_A_DMA_ENBL : VINO_CTRL_B_DMA_ENBL;
+ vino->control = ctrl;
+}
+
+/* (execute only with vino_lock locked) */
+static inline void vino_dma_stop(struct vino_channel_settings *vcs)
+{
+ u32 ctrl = vino->control;
+
+ ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
+ ~VINO_CTRL_A_DMA_ENBL : ~VINO_CTRL_B_DMA_ENBL;
+ ctrl &= (vcs->channel == VINO_CHANNEL_A) ?
+ ~VINO_CTRL_A_INT : ~VINO_CTRL_B_INT;
+ vino->control = ctrl;
+ dprintk("vino_dma_stop():\n");
+}
+
+/*
+ * Load dummy page to descriptor registers. This prevents generating of
+ * spurious interrupts. (execute only with vino_lock locked)
+ */
+static void vino_clear_interrupt(struct vino_channel_settings *vcs)
+{
+ struct sgi_vino_channel *ch;
+
+ ch = (vcs->channel == VINO_CHANNEL_A) ? &vino->a : &vino->b;
+
+ ch->page_index = 0;
+ ch->line_count = 0;
+
+ ch->start_desc_tbl = vino_drvdata->dummy_desc_table.dma;
+ ch->next_4_desc = vino_drvdata->dummy_desc_table.dma;
+
+ udelay(VINO_DESC_FETCH_DELAY);
+ dprintk("channel %c clear interrupt condition\n",
+ (vcs->channel == VINO_CHANNEL_A) ? 'A':'B');
+}
+
+static int vino_capture(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb)
+{
+ int err = 0;
+ unsigned long flags, flags2;
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+
+ if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+ err = -EBUSY;
+ fb->state = VINO_FRAMEBUFFER_IN_USE;
+
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ if (err)
+ return err;
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags2);
+
+ vino_dma_setup(vcs, fb);
+ vino_dma_start(vcs);
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags2);
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+ return err;
+}
+
+static
+struct vino_framebuffer *vino_capture_enqueue(struct
+ vino_channel_settings *vcs,
+ unsigned int index)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+
+ dprintk("vino_capture_enqueue():\n");
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ fb = vino_queue_add(&vcs->fb_queue, index);
+ if (fb == NULL) {
+ dprintk("vino_capture_enqueue(): vino_queue_add() failed, "
+ "queue full?\n");
+ goto out;
+ }
+out:
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ return fb;
+}
+
+static int vino_capture_next(struct vino_channel_settings *vcs, int start)
+{
+ struct vino_framebuffer *fb;
+ unsigned int incoming, id;
+ int err = 0;
+ unsigned long flags;
+
+ dprintk("vino_capture_next():\n");
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ if (start) {
+ /* start capture only if capture isn't in progress already */
+ if (vcs->capturing) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ return 0;
+ }
+
+ } else {
+ /* capture next frame:
+ * stop capture if capturing is not set */
+ if (!vcs->capturing) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ return 0;
+ }
+ }
+
+ err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+ if (err) {
+ dprintk("vino_capture_next(): vino_queue_get_incoming() "
+ "failed\n");
+ err = -EINVAL;
+ goto out;
+ }
+ if (incoming == 0) {
+ dprintk("vino_capture_next(): no buffers available\n");
+ goto out;
+ }
+
+ fb = vino_queue_peek(&vcs->fb_queue, &id);
+ if (fb == NULL) {
+ dprintk("vino_capture_next(): vino_queue_peek() failed\n");
+ err = -EINVAL;
+ goto out;
+ }
+
+ if (start) {
+ vcs->capturing = 1;
+ }
+
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ err = vino_capture(vcs, fb);
+
+ return err;
+
+out:
+ vcs->capturing = 0;
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ return err;
+}
+
+static inline int vino_is_capturing(struct vino_channel_settings *vcs)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ ret = vcs->capturing;
+
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ return ret;
+}
+
+/* waits until a frame is captured */
+static int vino_wait_for_frame(struct vino_channel_settings *vcs)
+{
+ wait_queue_t wait;
+ int err = 0;
+
+ dprintk("vino_wait_for_frame():\n");
+
+ init_waitqueue_entry(&wait, current);
+ /* add ourselves into wait queue */
+ add_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+
+ /* to ensure that schedule_timeout will return immediately
+ * if VINO interrupt was triggered meanwhile */
+ schedule_timeout_interruptible(msecs_to_jiffies(100));
+
+ if (signal_pending(current))
+ err = -EINTR;
+
+ remove_wait_queue(&vcs->fb_queue.frame_wait_queue, &wait);
+
+ dprintk("vino_wait_for_frame(): waiting for frame %s\n",
+ err ? "failed" : "ok");
+
+ return err;
+}
+
+/* the function assumes that PAGE_SIZE % 4 == 0 */
+static void vino_convert_to_rgba(struct vino_framebuffer *fb) {
+ unsigned char *pageptr;
+ unsigned int page, i;
+ unsigned char a;
+
+ for (page = 0; page < fb->desc_table.page_count; page++) {
+ pageptr = (unsigned char *)fb->desc_table.virtual[page];
+
+ for (i = 0; i < PAGE_SIZE; i += 4) {
+ a = pageptr[0];
+ pageptr[0] = pageptr[3];
+ pageptr[1] = pageptr[2];
+ pageptr[2] = pageptr[1];
+ pageptr[3] = a;
+ pageptr += 4;
+ }
+ }
+}
+
+/* checks if the buffer is in correct state and syncs data */
+static int vino_check_buffer(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb)
+{
+ int err = 0;
+ unsigned long flags;
+
+ dprintk("vino_check_buffer():\n");
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ switch (fb->state) {
+ case VINO_FRAMEBUFFER_IN_USE:
+ err = -EIO;
+ break;
+ case VINO_FRAMEBUFFER_READY:
+ vino_sync_buffer(fb);
+ fb->state = VINO_FRAMEBUFFER_UNUSED;
+ break;
+ default:
+ err = -EINVAL;
+ }
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ if (!err) {
+ if (vino_pixel_conversion
+ && (fb->data_format == VINO_DATA_FMT_RGB32)) {
+ vino_convert_to_rgba(fb);
+ }
+ } else if (err && (err != -EINVAL)) {
+ dprintk("vino_check_buffer(): buffer not ready\n");
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+ vino_dma_stop(vcs);
+ vino_clear_interrupt(vcs);
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+ }
+
+ return err;
+}
+
+/* forcefully terminates capture */
+static void vino_capture_stop(struct vino_channel_settings *vcs)
+{
+ unsigned int incoming = 0, outgoing = 0, id;
+ unsigned long flags, flags2;
+
+ dprintk("vino_capture_stop():\n");
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+
+ /* unset capturing to stop queue processing */
+ vcs->capturing = 0;
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags2);
+
+ vino_dma_stop(vcs);
+ vino_clear_interrupt(vcs);
+
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags2);
+
+ /* remove all items from the queue */
+ if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_incoming() failed\n");
+ goto out;
+ }
+ while (incoming > 0) {
+ vino_queue_transfer(&vcs->fb_queue);
+
+ if (vino_queue_get_incoming(&vcs->fb_queue, &incoming)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_incoming() failed\n");
+ goto out;
+ }
+ }
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_outgoing() failed\n");
+ goto out;
+ }
+ while (outgoing > 0) {
+ vino_queue_remove(&vcs->fb_queue, &id);
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("vino_capture_stop(): "
+ "vino_queue_get_outgoing() failed\n");
+ goto out;
+ }
+ }
+
+out:
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+}
+
+#if 0
+static int vino_capture_failed(struct vino_channel_settings *vcs)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+ unsigned int i;
+ int ret;
+
+ dprintk("vino_capture_failed():\n");
+
+ spin_lock_irqsave(&vino_drvdata->vino_lock, flags);
+
+ vino_dma_stop(vcs);
+ vino_clear_interrupt(vcs);
+
+ spin_unlock_irqrestore(&vino_drvdata->vino_lock, flags);
+
+ ret = vino_queue_get_incoming(&vcs->fb_queue, &i);
+ if (ret == VINO_QUEUE_ERROR) {
+ dprintk("vino_queue_get_incoming() failed\n");
+ return -EINVAL;
+ }
+ if (i == 0) {
+ /* no buffers to process */
+ return 0;
+ }
+
+ fb = vino_queue_peek(&vcs->fb_queue, &i);
+ if (fb == NULL) {
+ dprintk("vino_queue_peek() failed\n");
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ if (fb->state == VINO_FRAMEBUFFER_IN_USE) {
+ fb->state = VINO_FRAMEBUFFER_UNUSED;
+ vino_queue_transfer(&vcs->fb_queue);
+ vino_queue_remove(&vcs->fb_queue, &i);
+ /* we should actually discard the newest frame,
+ * but who cares ... */
+ }
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ return 0;
+}
+#endif
+
+static void vino_skip_frame(struct vino_channel_settings *vcs)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+ unsigned int id;
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+ fb = vino_queue_peek(&vcs->fb_queue, &id);
+ if (!fb) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ dprintk("vino_skip_frame(): vino_queue_peek() failed!\n");
+ return;
+ }
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ fb->state = VINO_FRAMEBUFFER_UNUSED;
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ vino_capture_next(vcs, 0);
+}
+
+static void vino_frame_done(struct vino_channel_settings *vcs)
+{
+ struct vino_framebuffer *fb;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vcs->capture_lock, flags);
+ fb = vino_queue_transfer(&vcs->fb_queue);
+ if (!fb) {
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+ dprintk("vino_frame_done(): vino_queue_transfer() failed!\n");
+ return;
+ }
+ spin_unlock_irqrestore(&vcs->capture_lock, flags);
+
+ fb->frame_counter = vcs->int_data.frame_counter;
+ memcpy(&fb->timestamp, &vcs->int_data.timestamp,
+ sizeof(struct timeval));
+
+ spin_lock_irqsave(&fb->state_lock, flags);
+ if (fb->state == VINO_FRAMEBUFFER_IN_USE)
+ fb->state = VINO_FRAMEBUFFER_READY;
+ spin_unlock_irqrestore(&fb->state_lock, flags);
+
+ wake_up(&vcs->fb_queue.frame_wait_queue);
+
+ vino_capture_next(vcs, 0);
+}
+
+static void vino_capture_tasklet(unsigned long channel) {
+ struct vino_channel_settings *vcs;
+
+ vcs = (channel == VINO_CHANNEL_A)
+ ? &vino_drvdata->a : &vino_drvdata->b;
+
+ if (vcs->int_data.skip)
+ vcs->int_data.skip_count++;
+
+ if (vcs->int_data.skip && (vcs->int_data.skip_count
+ <= VINO_MAX_FRAME_SKIP_COUNT)) {
+ vino_skip_frame(vcs);
+ } else {
+ vcs->int_data.skip_count = 0;
+ vino_frame_done(vcs);
+ }
+}
+
+static irqreturn_t vino_interrupt(int irq, void *dev_id)
+{
+ u32 ctrl, intr;
+ unsigned int fc_a, fc_b;
+ int handled_a = 0, skip_a = 0, done_a = 0;
+ int handled_b = 0, skip_b = 0, done_b = 0;
+
+#ifdef VINO_DEBUG_INT
+ int loop = 0;
+ unsigned int line_count = vino->a.line_count,
+ page_index = vino->a.page_index,
+ field_counter = vino->a.field_counter,
+ start_desc_tbl = vino->a.start_desc_tbl,
+ next_4_desc = vino->a.next_4_desc;
+ unsigned int line_count_2,
+ page_index_2,
+ field_counter_2,
+ start_desc_tbl_2,
+ next_4_desc_2;
+#endif
+
+ spin_lock(&vino_drvdata->vino_lock);
+
+ while ((intr = vino->intr_status)) {
+ fc_a = vino->a.field_counter >> 1;
+ fc_b = vino->b.field_counter >> 1;
+
+ /* handle error-interrupts in some special way ?
+ * --> skips frames */
+ if (intr & VINO_INTSTAT_A) {
+ if (intr & VINO_INTSTAT_A_EOF) {
+ vino_drvdata->a.field++;
+ if (vino_drvdata->a.field > 1) {
+ vino_dma_stop(&vino_drvdata->a);
+ vino_clear_interrupt(&vino_drvdata->a);
+ vino_drvdata->a.field = 0;
+ done_a = 1;
+ } else {
+ if (vino->a.page_index
+ != vino_drvdata->a.line_size) {
+ vino->a.line_count = 0;
+ vino->a.page_index =
+ vino_drvdata->
+ a.line_size;
+ vino->a.next_4_desc =
+ vino->a.start_desc_tbl;
+ }
+ }
+ dprintk("channel A end-of-field "
+ "interrupt: %04x\n", intr);
+ } else {
+ vino_dma_stop(&vino_drvdata->a);
+ vino_clear_interrupt(&vino_drvdata->a);
+ vino_drvdata->a.field = 0;
+ skip_a = 1;
+ dprintk("channel A error interrupt: %04x\n",
+ intr);
+ }
+
+#ifdef VINO_DEBUG_INT
+ line_count_2 = vino->a.line_count;
+ page_index_2 = vino->a.page_index;
+ field_counter_2 = vino->a.field_counter;
+ start_desc_tbl_2 = vino->a.start_desc_tbl;
+ next_4_desc_2 = vino->a.next_4_desc;
+
+ printk("intr = %04x, loop = %d, field = %d\n",
+ intr, loop, vino_drvdata->a.field);
+ printk("1- line count = %04d, page index = %04d, "
+ "start = %08x, next = %08x\n"
+ " fieldc = %d, framec = %d\n",
+ line_count, page_index, start_desc_tbl,
+ next_4_desc, field_counter, fc_a);
+ printk("12-line count = %04d, page index = %04d, "
+ " start = %08x, next = %08x\n",
+ line_count_2, page_index_2, start_desc_tbl_2,
+ next_4_desc_2);
+
+ if (done_a)
+ printk("\n");
+#endif
+ }
+
+ if (intr & VINO_INTSTAT_B) {
+ if (intr & VINO_INTSTAT_B_EOF) {
+ vino_drvdata->b.field++;
+ if (vino_drvdata->b.field > 1) {
+ vino_dma_stop(&vino_drvdata->b);
+ vino_clear_interrupt(&vino_drvdata->b);
+ vino_drvdata->b.field = 0;
+ done_b = 1;
+ }
+ dprintk("channel B end-of-field "
+ "interrupt: %04x\n", intr);
+ } else {
+ vino_dma_stop(&vino_drvdata->b);
+ vino_clear_interrupt(&vino_drvdata->b);
+ vino_drvdata->b.field = 0;
+ skip_b = 1;
+ dprintk("channel B error interrupt: %04x\n",
+ intr);
+ }
+ }
+
+ /* Always remember to clear interrupt status.
+ * Disable VINO interrupts while we do this. */
+ ctrl = vino->control;
+ vino->control = ctrl & ~(VINO_CTRL_A_INT | VINO_CTRL_B_INT);
+ vino->intr_status = ~intr;
+ vino->control = ctrl;
+
+ spin_unlock(&vino_drvdata->vino_lock);
+
+ if ((!handled_a) && (done_a || skip_a)) {
+ if (!skip_a) {
+ v4l2_get_timestamp(
+ &vino_drvdata->a.int_data.timestamp);
+ vino_drvdata->a.int_data.frame_counter = fc_a;
+ }
+ vino_drvdata->a.int_data.skip = skip_a;
+
+ dprintk("channel A %s, interrupt: %d\n",
+ skip_a ? "skipping frame" : "frame done",
+ intr);
+ tasklet_hi_schedule(&vino_tasklet_a);
+ handled_a = 1;
+ }
+
+ if ((!handled_b) && (done_b || skip_b)) {
+ if (!skip_b) {
+ v4l2_get_timestamp(
+ &vino_drvdata->b.int_data.timestamp);
+ vino_drvdata->b.int_data.frame_counter = fc_b;
+ }
+ vino_drvdata->b.int_data.skip = skip_b;
+
+ dprintk("channel B %s, interrupt: %d\n",
+ skip_b ? "skipping frame" : "frame done",
+ intr);
+ tasklet_hi_schedule(&vino_tasklet_b);
+ handled_b = 1;
+ }
+
+#ifdef VINO_DEBUG_INT
+ loop++;
+#endif
+ spin_lock(&vino_drvdata->vino_lock);
+ }
+
+ spin_unlock(&vino_drvdata->vino_lock);
+
+ return IRQ_HANDLED;
+}
+
+/* VINO video input management */
+
+static int vino_get_saa7191_input(int input)
+{
+ switch (input) {
+ case VINO_INPUT_COMPOSITE:
+ return SAA7191_INPUT_COMPOSITE;
+ case VINO_INPUT_SVIDEO:
+ return SAA7191_INPUT_SVIDEO;
+ default:
+ printk(KERN_ERR "VINO: vino_get_saa7191_input(): "
+ "invalid input!\n");
+ return -1;
+ }
+}
+
+/* execute with input_lock locked */
+static int vino_is_input_owner(struct vino_channel_settings *vcs)
+{
+ switch(vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ return vino_drvdata->decoder_owner == vcs->channel;
+ case VINO_INPUT_D1:
+ return vino_drvdata->camera_owner == vcs->channel;
+ default:
+ return 0;
+ }
+}
+
+static int vino_acquire_input(struct vino_channel_settings *vcs)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ dprintk("vino_acquire_input():\n");
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ /* First try D1 and then SAA7191 */
+ if (vino_drvdata->camera
+ && (vino_drvdata->camera_owner == VINO_NO_CHANNEL)) {
+ vino_drvdata->camera_owner = vcs->channel;
+ vcs->input = VINO_INPUT_D1;
+ vcs->data_norm = VINO_DATA_NORM_D1;
+ } else if (vino_drvdata->decoder
+ && (vino_drvdata->decoder_owner == VINO_NO_CHANNEL)) {
+ int input;
+ int data_norm = 0;
+ v4l2_std_id norm;
+
+ input = VINO_INPUT_COMPOSITE;
+
+ ret = decoder_call(video, s_routing,
+ vino_get_saa7191_input(input), 0, 0);
+ if (ret) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ /* Don't hold spinlocks while auto-detecting norm
+ * as it may take a while... */
+
+ ret = decoder_call(video, querystd, &norm);
+ if (!ret) {
+ for (data_norm = 0; data_norm < 3; data_norm++) {
+ if (vino_data_norms[data_norm].std & norm)
+ break;
+ }
+ if (data_norm == 3)
+ data_norm = VINO_DATA_NORM_PAL;
+ ret = decoder_call(video, s_std, norm);
+ }
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ if (ret) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ vino_drvdata->decoder_owner = vcs->channel;
+
+ vcs->input = input;
+ vcs->data_norm = data_norm;
+ } else {
+ vcs->input = (vcs->channel == VINO_CHANNEL_A) ?
+ vino_drvdata->b.input : vino_drvdata->a.input;
+ vcs->data_norm = (vcs->channel == VINO_CHANNEL_A) ?
+ vino_drvdata->b.data_norm : vino_drvdata->a.data_norm;
+ }
+
+ if (vcs->input == VINO_INPUT_NONE) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ vino_set_default_clipping(vcs);
+ vino_set_default_scaling(vcs);
+ vino_set_default_framerate(vcs);
+
+ dprintk("vino_acquire_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return ret;
+}
+
+static int vino_set_input(struct vino_channel_settings *vcs, int input)
+{
+ struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+ &vino_drvdata->b : &vino_drvdata->a;
+ unsigned long flags;
+ int ret = 0;
+
+ dprintk("vino_set_input():\n");
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ if (vcs->input == input)
+ goto out;
+
+ switch (input) {
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ if (!vino_drvdata->decoder) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (vino_drvdata->decoder_owner == VINO_NO_CHANNEL) {
+ vino_drvdata->decoder_owner = vcs->channel;
+ }
+
+ if (vino_drvdata->decoder_owner == vcs->channel) {
+ int data_norm = 0;
+ v4l2_std_id norm;
+
+ ret = decoder_call(video, s_routing,
+ vino_get_saa7191_input(input), 0, 0);
+ if (ret) {
+ vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
+ ret = -EINVAL;
+ goto out;
+ }
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ /* Don't hold spinlocks while auto-detecting norm
+ * as it may take a while... */
+
+ ret = decoder_call(video, querystd, &norm);
+ if (!ret) {
+ for (data_norm = 0; data_norm < 3; data_norm++) {
+ if (vino_data_norms[data_norm].std & norm)
+ break;
+ }
+ if (data_norm == 3)
+ data_norm = VINO_DATA_NORM_PAL;
+ ret = decoder_call(video, s_std, norm);
+ }
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ if (ret) {
+ vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
+ ret = -EINVAL;
+ goto out;
+ }
+
+ vcs->input = input;
+ vcs->data_norm = data_norm;
+ } else {
+ if (input != vcs2->input) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ vcs->input = input;
+ vcs->data_norm = vcs2->data_norm;
+ }
+
+ if (vino_drvdata->camera_owner == vcs->channel) {
+ /* Transfer the ownership or release the input */
+ if (vcs2->input == VINO_INPUT_D1) {
+ vino_drvdata->camera_owner = vcs2->channel;
+ } else {
+ vino_drvdata->camera_owner = VINO_NO_CHANNEL;
+ }
+ }
+ break;
+ case VINO_INPUT_D1:
+ if (!vino_drvdata->camera) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (vino_drvdata->camera_owner == VINO_NO_CHANNEL)
+ vino_drvdata->camera_owner = vcs->channel;
+
+ if (vino_drvdata->decoder_owner == vcs->channel) {
+ /* Transfer the ownership or release the input */
+ if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+ (vcs2->input == VINO_INPUT_SVIDEO)) {
+ vino_drvdata->decoder_owner = vcs2->channel;
+ } else {
+ vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
+ }
+ }
+
+ vcs->input = input;
+ vcs->data_norm = VINO_DATA_NORM_D1;
+ break;
+ default:
+ ret = -EINVAL;
+ goto out;
+ }
+
+ vino_set_default_clipping(vcs);
+ vino_set_default_scaling(vcs);
+ vino_set_default_framerate(vcs);
+
+ dprintk("vino_set_input(): %s\n", vino_inputs[vcs->input].name);
+
+out:
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return ret;
+}
+
+static void vino_release_input(struct vino_channel_settings *vcs)
+{
+ struct vino_channel_settings *vcs2 = (vcs->channel == VINO_CHANNEL_A) ?
+ &vino_drvdata->b : &vino_drvdata->a;
+ unsigned long flags;
+
+ dprintk("vino_release_input():\n");
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ /* Release ownership of the channel
+ * and if the other channel takes input from
+ * the same source, transfer the ownership */
+ if (vino_drvdata->camera_owner == vcs->channel) {
+ if (vcs2->input == VINO_INPUT_D1) {
+ vino_drvdata->camera_owner = vcs2->channel;
+ } else {
+ vino_drvdata->camera_owner = VINO_NO_CHANNEL;
+ }
+ } else if (vino_drvdata->decoder_owner == vcs->channel) {
+ if ((vcs2->input == VINO_INPUT_COMPOSITE) ||
+ (vcs2->input == VINO_INPUT_SVIDEO)) {
+ vino_drvdata->decoder_owner = vcs2->channel;
+ } else {
+ vino_drvdata->decoder_owner = VINO_NO_CHANNEL;
+ }
+ }
+ vcs->input = VINO_INPUT_NONE;
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+}
+
+/* execute with input_lock locked */
+static int vino_set_data_norm(struct vino_channel_settings *vcs,
+ unsigned int data_norm,
+ unsigned long *flags)
+{
+ int err = 0;
+
+ if (data_norm == vcs->data_norm)
+ return 0;
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ /* only one "norm" supported */
+ if (data_norm != VINO_DATA_NORM_D1)
+ return -EINVAL;
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO: {
+ v4l2_std_id norm;
+
+ if ((data_norm != VINO_DATA_NORM_PAL)
+ && (data_norm != VINO_DATA_NORM_NTSC)
+ && (data_norm != VINO_DATA_NORM_SECAM))
+ return -EINVAL;
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, *flags);
+
+ /* Don't hold spinlocks while setting norm
+ * as it may take a while... */
+
+ norm = vino_data_norms[data_norm].std;
+ err = decoder_call(video, s_std, norm);
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, *flags);
+
+ if (err)
+ goto out;
+
+ vcs->data_norm = data_norm;
+
+ vino_set_default_clipping(vcs);
+ vino_set_default_scaling(vcs);
+ vino_set_default_framerate(vcs);
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+
+out:
+ return err;
+}
+
+/* V4L2 helper functions */
+
+static int vino_find_data_format(__u32 pixelformat)
+{
+ int i;
+
+ for (i = 0; i < VINO_DATA_FMT_COUNT; i++) {
+ if (vino_data_formats[i].pixelformat == pixelformat)
+ return i;
+ }
+
+ return VINO_DATA_FMT_NONE;
+}
+
+static int vino_int_enum_input(struct vino_channel_settings *vcs, __u32 index)
+{
+ int input = VINO_INPUT_NONE;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+ if (vino_drvdata->decoder && vino_drvdata->camera) {
+ switch (index) {
+ case 0:
+ input = VINO_INPUT_COMPOSITE;
+ break;
+ case 1:
+ input = VINO_INPUT_SVIDEO;
+ break;
+ case 2:
+ input = VINO_INPUT_D1;
+ break;
+ }
+ } else if (vino_drvdata->decoder) {
+ switch (index) {
+ case 0:
+ input = VINO_INPUT_COMPOSITE;
+ break;
+ case 1:
+ input = VINO_INPUT_SVIDEO;
+ break;
+ }
+ } else if (vino_drvdata->camera) {
+ switch (index) {
+ case 0:
+ input = VINO_INPUT_D1;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return input;
+}
+
+/* execute with input_lock locked */
+static __u32 vino_find_input_index(struct vino_channel_settings *vcs)
+{
+ __u32 index = 0;
+ // FIXME: detect when no inputs available
+
+ if (vino_drvdata->decoder && vino_drvdata->camera) {
+ switch (vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ index = 0;
+ break;
+ case VINO_INPUT_SVIDEO:
+ index = 1;
+ break;
+ case VINO_INPUT_D1:
+ index = 2;
+ break;
+ }
+ } else if (vino_drvdata->decoder) {
+ switch (vcs->input) {
+ case VINO_INPUT_COMPOSITE:
+ index = 0;
+ break;
+ case VINO_INPUT_SVIDEO:
+ index = 1;
+ break;
+ }
+ } else if (vino_drvdata->camera) {
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ index = 0;
+ break;
+ }
+ }
+
+ return index;
+}
+
+/* V4L2 ioctls */
+
+static int vino_querycap(struct file *file, void *__fh,
+ struct v4l2_capability *cap)
+{
+ memset(cap, 0, sizeof(struct v4l2_capability));
+
+ strcpy(cap->driver, vino_driver_name);
+ strcpy(cap->card, vino_driver_description);
+ strcpy(cap->bus_info, vino_bus_name);
+ cap->capabilities =
+ V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_STREAMING;
+ // V4L2_CAP_OVERLAY, V4L2_CAP_READWRITE
+ return 0;
+}
+
+static int vino_enum_input(struct file *file, void *__fh,
+ struct v4l2_input *i)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ __u32 index = i->index;
+ int input;
+ dprintk("requested index = %d\n", index);
+
+ input = vino_int_enum_input(vcs, index);
+ if (input == VINO_INPUT_NONE)
+ return -EINVAL;
+
+ i->type = V4L2_INPUT_TYPE_CAMERA;
+ i->std = vino_inputs[input].std;
+ strcpy(i->name, vino_inputs[input].name);
+
+ if (input == VINO_INPUT_COMPOSITE || input == VINO_INPUT_SVIDEO)
+ decoder_call(video, g_input_status, &i->status);
+ return 0;
+}
+
+static int vino_g_input(struct file *file, void *__fh,
+ unsigned int *i)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ __u32 index;
+ int input;
+ unsigned long flags;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+ input = vcs->input;
+ index = vino_find_input_index(vcs);
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ dprintk("input = %d\n", input);
+
+ if (input == VINO_INPUT_NONE) {
+ return -EINVAL;
+ }
+
+ *i = index;
+
+ return 0;
+}
+
+static int vino_s_input(struct file *file, void *__fh,
+ unsigned int i)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ int input;
+ dprintk("requested input = %d\n", i);
+
+ input = vino_int_enum_input(vcs, i);
+ if (input == VINO_INPUT_NONE)
+ return -EINVAL;
+
+ return vino_set_input(vcs, input);
+}
+
+static int vino_querystd(struct file *file, void *__fh,
+ v4l2_std_id *std)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+ int err = 0;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ *std = vino_inputs[vcs->input].std;
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO: {
+ decoder_call(video, querystd, std);
+ break;
+ }
+ default:
+ err = -EINVAL;
+ }
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return err;
+}
+
+static int vino_g_std(struct file *file, void *__fh,
+ v4l2_std_id *std)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ *std = vino_data_norms[vcs->data_norm].std;
+ dprintk("current standard = %d\n", vcs->data_norm);
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return 0;
+}
+
+static int vino_s_std(struct file *file, void *__fh,
+ v4l2_std_id std)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ if (!vino_is_input_owner(vcs)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ /* check if the standard is valid for the current input */
+ if (std & vino_inputs[vcs->input].std) {
+ dprintk("standard accepted\n");
+
+ /* change the video norm for SAA7191
+ * and accept NTSC for D1 (do nothing) */
+
+ if (vcs->input == VINO_INPUT_D1)
+ goto out;
+
+ if (std & V4L2_STD_PAL) {
+ ret = vino_set_data_norm(vcs, VINO_DATA_NORM_PAL,
+ &flags);
+ } else if (std & V4L2_STD_NTSC) {
+ ret = vino_set_data_norm(vcs, VINO_DATA_NORM_NTSC,
+ &flags);
+ } else if (std & V4L2_STD_SECAM) {
+ ret = vino_set_data_norm(vcs, VINO_DATA_NORM_SECAM,
+ &flags);
+ } else {
+ ret = -EINVAL;
+ }
+
+ if (ret) {
+ ret = -EINVAL;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+
+out:
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return ret;
+}
+
+static int vino_enum_fmt_vid_cap(struct file *file, void *__fh,
+ struct v4l2_fmtdesc *fd)
+{
+ dprintk("format index = %d\n", fd->index);
+
+ if (fd->index >= VINO_DATA_FMT_COUNT)
+ return -EINVAL;
+ dprintk("format name = %s\n", vino_data_formats[fd->index].description);
+
+ fd->pixelformat = vino_data_formats[fd->index].pixelformat;
+ strcpy(fd->description, vino_data_formats[fd->index].description);
+ return 0;
+}
+
+static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
+ struct v4l2_format *f)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ struct vino_channel_settings tempvcs;
+ unsigned long flags;
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+
+ dprintk("requested: w = %d, h = %d\n",
+ pf->width, pf->height);
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+ memcpy(&tempvcs, vcs, sizeof(struct vino_channel_settings));
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ tempvcs.data_format = vino_find_data_format(pf->pixelformat);
+ if (tempvcs.data_format == VINO_DATA_FMT_NONE) {
+ tempvcs.data_format = VINO_DATA_FMT_GREY;
+ pf->pixelformat =
+ vino_data_formats[tempvcs.data_format].
+ pixelformat;
+ }
+
+ /* data format must be set before clipping/scaling */
+ vino_set_scaling(&tempvcs, pf->width, pf->height);
+
+ dprintk("data format = %s\n",
+ vino_data_formats[tempvcs.data_format].description);
+
+ pf->width = (tempvcs.clipping.right - tempvcs.clipping.left) /
+ tempvcs.decimation;
+ pf->height = (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+ tempvcs.decimation;
+
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = tempvcs.line_size;
+ pf->sizeimage = tempvcs.line_size *
+ (tempvcs.clipping.bottom - tempvcs.clipping.top) /
+ tempvcs.decimation;
+ pf->colorspace =
+ vino_data_formats[tempvcs.data_format].colorspace;
+
+ return 0;
+}
+
+static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
+ struct v4l2_format *f)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ pf->width = (vcs->clipping.right - vcs->clipping.left) /
+ vcs->decimation;
+ pf->height = (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->pixelformat =
+ vino_data_formats[vcs->data_format].pixelformat;
+
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = vcs->line_size;
+ pf->sizeimage = vcs->line_size *
+ (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->colorspace =
+ vino_data_formats[vcs->data_format].colorspace;
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+ return 0;
+}
+
+static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
+ struct v4l2_format *f)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ int data_format;
+ unsigned long flags;
+ struct v4l2_pix_format *pf = &f->fmt.pix;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ data_format = vino_find_data_format(pf->pixelformat);
+
+ if (data_format == VINO_DATA_FMT_NONE) {
+ vcs->data_format = VINO_DATA_FMT_GREY;
+ pf->pixelformat =
+ vino_data_formats[vcs->data_format].
+ pixelformat;
+ } else {
+ vcs->data_format = data_format;
+ }
+
+ /* data format must be set before clipping/scaling */
+ vino_set_scaling(vcs, pf->width, pf->height);
+
+ dprintk("data format = %s\n",
+ vino_data_formats[vcs->data_format].description);
+
+ pf->width = vcs->clipping.right - vcs->clipping.left;
+ pf->height = vcs->clipping.bottom - vcs->clipping.top;
+
+ pf->field = V4L2_FIELD_INTERLACED;
+ pf->bytesperline = vcs->line_size;
+ pf->sizeimage = vcs->line_size *
+ (vcs->clipping.bottom - vcs->clipping.top) /
+ vcs->decimation;
+ pf->colorspace =
+ vino_data_formats[vcs->data_format].colorspace;
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+ return 0;
+}
+
+static int vino_cropcap(struct file *file, void *__fh,
+ struct v4l2_cropcap *ccap)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ const struct vino_data_norm *norm;
+ unsigned long flags;
+
+ switch (ccap->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ norm = &vino_data_norms[vcs->data_norm];
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ ccap->bounds.left = 0;
+ ccap->bounds.top = 0;
+ ccap->bounds.width = norm->width;
+ ccap->bounds.height = norm->height;
+ memcpy(&ccap->defrect, &ccap->bounds,
+ sizeof(struct v4l2_rect));
+
+ ccap->pixelaspect.numerator = 1;
+ ccap->pixelaspect.denominator = 1;
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_g_crop(struct file *file, void *__fh,
+ struct v4l2_crop *c)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+
+ switch (c->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ c->c.left = vcs->clipping.left;
+ c->c.top = vcs->clipping.top;
+ c->c.width = vcs->clipping.right - vcs->clipping.left;
+ c->c.height = vcs->clipping.bottom - vcs->clipping.top;
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_s_crop(struct file *file, void *__fh,
+ const struct v4l2_crop *c)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+
+ switch (c->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ vino_set_clipping(vcs, c->c.left, c->c.top,
+ c->c.width, c->c.height);
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+ break;
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int vino_g_parm(struct file *file, void *__fh,
+ struct v4l2_streamparm *sp)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+ struct v4l2_captureparm *cp = &sp->parm.capture;
+
+ cp->capability = V4L2_CAP_TIMEPERFRAME;
+ cp->timeperframe.numerator = 1;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ cp->timeperframe.denominator = vcs->fps;
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ /* TODO: cp->readbuffers = xxx; */
+
+ return 0;
+}
+
+static int vino_s_parm(struct file *file, void *__fh,
+ struct v4l2_streamparm *sp)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+ struct v4l2_captureparm *cp = &sp->parm.capture;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ if ((cp->timeperframe.numerator == 0) ||
+ (cp->timeperframe.denominator == 0)) {
+ /* reset framerate */
+ vino_set_default_framerate(vcs);
+ } else {
+ vino_set_framerate(vcs, cp->timeperframe.denominator /
+ cp->timeperframe.numerator);
+ }
+
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return 0;
+}
+
+static int vino_reqbufs(struct file *file, void *__fh,
+ struct v4l2_requestbuffers *rb)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+
+ if (vcs->reading)
+ return -EBUSY;
+
+ /* TODO: check queue type */
+ if (rb->memory != V4L2_MEMORY_MMAP) {
+ dprintk("type not mmap\n");
+ return -EINVAL;
+ }
+
+ dprintk("count = %d\n", rb->count);
+ if (rb->count > 0) {
+ if (vino_is_capturing(vcs)) {
+ dprintk("busy, capturing\n");
+ return -EBUSY;
+ }
+
+ if (vino_queue_has_mapped_buffers(&vcs->fb_queue)) {
+ dprintk("busy, buffers still mapped\n");
+ return -EBUSY;
+ } else {
+ vcs->streaming = 0;
+ vino_queue_free(&vcs->fb_queue);
+ vino_queue_init(&vcs->fb_queue, &rb->count);
+ }
+ } else {
+ vcs->streaming = 0;
+ vino_capture_stop(vcs);
+ vino_queue_free(&vcs->fb_queue);
+ }
+
+ return 0;
+}
+
+static void vino_v4l2_get_buffer_status(struct vino_channel_settings *vcs,
+ struct vino_framebuffer *fb,
+ struct v4l2_buffer *b)
+{
+ if (vino_queue_outgoing_contains(&vcs->fb_queue,
+ fb->id)) {
+ b->flags &= ~V4L2_BUF_FLAG_QUEUED;
+ b->flags |= V4L2_BUF_FLAG_DONE;
+ } else if (vino_queue_incoming_contains(&vcs->fb_queue,
+ fb->id)) {
+ b->flags &= ~V4L2_BUF_FLAG_DONE;
+ b->flags |= V4L2_BUF_FLAG_QUEUED;
+ } else {
+ b->flags &= ~(V4L2_BUF_FLAG_DONE |
+ V4L2_BUF_FLAG_QUEUED);
+ }
+
+ b->flags &= ~(V4L2_BUF_FLAG_TIMECODE);
+
+ if (fb->map_count > 0)
+ b->flags |= V4L2_BUF_FLAG_MAPPED;
+
+ b->flags &= ~V4L2_BUF_FLAG_TIMESTAMP_MASK;
+ b->flags |= V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+
+ b->index = fb->id;
+ b->memory = (vcs->fb_queue.type == VINO_MEMORY_MMAP) ?
+ V4L2_MEMORY_MMAP : V4L2_MEMORY_USERPTR;
+ b->m.offset = fb->offset;
+ b->bytesused = fb->data_size;
+ b->length = fb->size;
+ b->field = V4L2_FIELD_INTERLACED;
+ b->sequence = fb->frame_counter;
+ memcpy(&b->timestamp, &fb->timestamp,
+ sizeof(struct timeval));
+ // b->input ?
+
+ dprintk("buffer %d: length = %d, bytesused = %d, offset = %d\n",
+ fb->id, fb->size, fb->data_size, fb->offset);
+}
+
+static int vino_querybuf(struct file *file, void *__fh,
+ struct v4l2_buffer *b)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ struct vino_framebuffer *fb;
+
+ if (vcs->reading)
+ return -EBUSY;
+
+ /* TODO: check queue type */
+ if (b->index >= vino_queue_get_length(&vcs->fb_queue)) {
+ dprintk("invalid index = %d\n",
+ b->index);
+ return -EINVAL;
+ }
+
+ fb = vino_queue_get_buffer(&vcs->fb_queue,
+ b->index);
+ if (fb == NULL) {
+ dprintk("vino_queue_get_buffer() failed");
+ return -EINVAL;
+ }
+
+ vino_v4l2_get_buffer_status(vcs, fb, b);
+
+ return 0;
+}
+
+static int vino_qbuf(struct file *file, void *__fh,
+ struct v4l2_buffer *b)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ struct vino_framebuffer *fb;
+ int ret;
+
+ if (vcs->reading)
+ return -EBUSY;
+
+ /* TODO: check queue type */
+ if (b->memory != V4L2_MEMORY_MMAP) {
+ dprintk("type not mmap\n");
+ return -EINVAL;
+ }
+
+ fb = vino_capture_enqueue(vcs, b->index);
+ if (fb == NULL)
+ return -EINVAL;
+
+ vino_v4l2_get_buffer_status(vcs, fb, b);
+
+ if (vcs->streaming) {
+ ret = vino_capture_next(vcs, 1);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int vino_dqbuf(struct file *file, void *__fh,
+ struct v4l2_buffer *b)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned int nonblocking = file->f_flags & O_NONBLOCK;
+ struct vino_framebuffer *fb;
+ unsigned int incoming, outgoing;
+ int err;
+
+ if (vcs->reading)
+ return -EBUSY;
+
+ /* TODO: check queue type */
+
+ err = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+ if (err) {
+ dprintk("vino_queue_get_incoming() failed\n");
+ return -EINVAL;
+ }
+ err = vino_queue_get_outgoing(&vcs->fb_queue, &outgoing);
+ if (err) {
+ dprintk("vino_queue_get_outgoing() failed\n");
+ return -EINVAL;
+ }
+
+ dprintk("incoming = %d, outgoing = %d\n", incoming, outgoing);
+
+ if (outgoing == 0) {
+ if (incoming == 0) {
+ dprintk("no incoming or outgoing buffers\n");
+ return -EINVAL;
+ }
+ if (nonblocking) {
+ dprintk("non-blocking I/O was selected and "
+ "there are no buffers to dequeue\n");
+ return -EAGAIN;
+ }
+
+ err = vino_wait_for_frame(vcs);
+ if (err) {
+ err = vino_wait_for_frame(vcs);
+ if (err) {
+ /* interrupted or no frames captured because of
+ * frame skipping */
+ /* vino_capture_failed(vcs); */
+ return -EIO;
+ }
+ }
+ }
+
+ fb = vino_queue_remove(&vcs->fb_queue, &b->index);
+ if (fb == NULL) {
+ dprintk("vino_queue_remove() failed\n");
+ return -EINVAL;
+ }
+
+ err = vino_check_buffer(vcs, fb);
+
+ vino_v4l2_get_buffer_status(vcs, fb, b);
+
+ if (err)
+ return -EIO;
+
+ return 0;
+}
+
+static int vino_streamon(struct file *file, void *__fh,
+ enum v4l2_buf_type i)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned int incoming;
+ int ret;
+ if (vcs->reading)
+ return -EBUSY;
+
+ if (vcs->streaming)
+ return 0;
+
+ // TODO: check queue type
+
+ if (vino_queue_get_length(&vcs->fb_queue) < 1) {
+ dprintk("no buffers allocated\n");
+ return -EINVAL;
+ }
+
+ ret = vino_queue_get_incoming(&vcs->fb_queue, &incoming);
+ if (ret) {
+ dprintk("vino_queue_get_incoming() failed\n");
+ return -EINVAL;
+ }
+
+ vcs->streaming = 1;
+
+ if (incoming > 0) {
+ ret = vino_capture_next(vcs, 1);
+ if (ret) {
+ vcs->streaming = 0;
+
+ dprintk("couldn't start capture\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+static int vino_streamoff(struct file *file, void *__fh,
+ enum v4l2_buf_type i)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ if (vcs->reading)
+ return -EBUSY;
+
+ if (!vcs->streaming)
+ return 0;
+
+ vcs->streaming = 0;
+ vino_capture_stop(vcs);
+
+ return 0;
+}
+
+static int vino_queryctrl(struct file *file, void *__fh,
+ struct v4l2_queryctrl *queryctrl)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+ int i;
+ int err = 0;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1:
+ for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+ if (vino_indycam_v4l2_controls[i].id ==
+ queryctrl->id) {
+ memcpy(queryctrl,
+ &vino_indycam_v4l2_controls[i],
+ sizeof(struct v4l2_queryctrl));
+ queryctrl->reserved[0] = 0;
+ goto found;
+ }
+ }
+
+ err = -EINVAL;
+ break;
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO:
+ for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+ if (vino_saa7191_v4l2_controls[i].id ==
+ queryctrl->id) {
+ memcpy(queryctrl,
+ &vino_saa7191_v4l2_controls[i],
+ sizeof(struct v4l2_queryctrl));
+ queryctrl->reserved[0] = 0;
+ goto found;
+ }
+ }
+
+ err = -EINVAL;
+ break;
+ default:
+ err = -EINVAL;
+ }
+
+ found:
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return err;
+}
+
+static int vino_g_ctrl(struct file *file, void *__fh,
+ struct v4l2_control *control)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+ int i;
+ int err = 0;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1: {
+ err = -EINVAL;
+ for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+ if (vino_indycam_v4l2_controls[i].id == control->id) {
+ err = 0;
+ break;
+ }
+ }
+
+ if (err)
+ goto out;
+
+ err = camera_call(core, g_ctrl, control);
+ if (err)
+ err = -EINVAL;
+ break;
+ }
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO: {
+ err = -EINVAL;
+ for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+ if (vino_saa7191_v4l2_controls[i].id == control->id) {
+ err = 0;
+ break;
+ }
+ }
+
+ if (err)
+ goto out;
+
+ err = decoder_call(core, g_ctrl, control);
+ if (err)
+ err = -EINVAL;
+ break;
+ }
+ default:
+ err = -EINVAL;
+ }
+
+out:
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return err;
+}
+
+static int vino_s_ctrl(struct file *file, void *__fh,
+ struct v4l2_control *control)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned long flags;
+ int i;
+ int err = 0;
+
+ spin_lock_irqsave(&vino_drvdata->input_lock, flags);
+
+ if (!vino_is_input_owner(vcs)) {
+ err = -EBUSY;
+ goto out;
+ }
+
+ switch (vcs->input) {
+ case VINO_INPUT_D1: {
+ err = -EINVAL;
+ for (i = 0; i < VINO_INDYCAM_V4L2_CONTROL_COUNT; i++) {
+ if (vino_indycam_v4l2_controls[i].id == control->id) {
+ err = 0;
+ break;
+ }
+ }
+ if (err)
+ goto out;
+ if (control->value < vino_indycam_v4l2_controls[i].minimum ||
+ control->value > vino_indycam_v4l2_controls[i].maximum) {
+ err = -ERANGE;
+ goto out;
+ }
+ err = camera_call(core, s_ctrl, control);
+ if (err)
+ err = -EINVAL;
+ break;
+ }
+ case VINO_INPUT_COMPOSITE:
+ case VINO_INPUT_SVIDEO: {
+ err = -EINVAL;
+ for (i = 0; i < VINO_SAA7191_V4L2_CONTROL_COUNT; i++) {
+ if (vino_saa7191_v4l2_controls[i].id == control->id) {
+ err = 0;
+ break;
+ }
+ }
+ if (err)
+ goto out;
+ if (control->value < vino_saa7191_v4l2_controls[i].minimum ||
+ control->value > vino_saa7191_v4l2_controls[i].maximum) {
+ err = -ERANGE;
+ goto out;
+ }
+
+ err = decoder_call(core, s_ctrl, control);
+ if (err)
+ err = -EINVAL;
+ break;
+ }
+ default:
+ err = -EINVAL;
+ }
+
+out:
+ spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
+
+ return err;
+}
+
+/* File operations */
+
+static int vino_open(struct file *file)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ int ret = 0;
+ dprintk("open(): channel = %c\n",
+ (vcs->channel == VINO_CHANNEL_A) ? 'A' : 'B');
+
+ mutex_lock(&vcs->mutex);
+
+ if (vcs->users) {
+ dprintk("open(): driver busy\n");
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ret = vino_acquire_input(vcs);
+ if (ret) {
+ dprintk("open(): vino_acquire_input() failed\n");
+ goto out;
+ }
+
+ vcs->users++;
+
+ out:
+ mutex_unlock(&vcs->mutex);
+
+ dprintk("open(): %s!\n", ret ? "failed" : "complete");
+
+ return ret;
+}
+
+static int vino_close(struct file *file)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ dprintk("close():\n");
+
+ mutex_lock(&vcs->mutex);
+
+ vcs->users--;
+
+ if (!vcs->users) {
+ vino_release_input(vcs);
+
+ /* stop DMA and free buffers */
+ vino_capture_stop(vcs);
+ vino_queue_free(&vcs->fb_queue);
+ }
+
+ mutex_unlock(&vcs->mutex);
+
+ return 0;
+}
+
+static void vino_vm_open(struct vm_area_struct *vma)
+{
+ struct vino_framebuffer *fb = vma->vm_private_data;
+
+ fb->map_count++;
+ dprintk("vino_vm_open(): count = %d\n", fb->map_count);
+}
+
+static void vino_vm_close(struct vm_area_struct *vma)
+{
+ struct vino_framebuffer *fb = vma->vm_private_data;
+
+ fb->map_count--;
+ dprintk("vino_vm_close(): count = %d\n", fb->map_count);
+}
+
+static const struct vm_operations_struct vino_vm_ops = {
+ .open = vino_vm_open,
+ .close = vino_vm_close,
+};
+
+static int vino_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+
+ unsigned long start = vma->vm_start;
+ unsigned long size = vma->vm_end - vma->vm_start;
+ unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+
+ struct vino_framebuffer *fb = NULL;
+ unsigned int i, length;
+ int ret = 0;
+
+ dprintk("mmap():\n");
+
+ // TODO: reject mmap if already mapped
+
+ if (mutex_lock_interruptible(&vcs->mutex))
+ return -EINTR;
+
+ if (vcs->reading) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ // TODO: check queue type
+
+ if (!(vma->vm_flags & VM_WRITE)) {
+ dprintk("mmap(): app bug: PROT_WRITE please\n");
+ ret = -EINVAL;
+ goto out;
+ }
+ if (!(vma->vm_flags & VM_SHARED)) {
+ dprintk("mmap(): app bug: MAP_SHARED please\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* find the correct buffer using offset */
+ length = vino_queue_get_length(&vcs->fb_queue);
+ if (length == 0) {
+ dprintk("mmap(): queue not initialized\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < length; i++) {
+ fb = vino_queue_get_buffer(&vcs->fb_queue, i);
+ if (fb == NULL) {
+ dprintk("mmap(): vino_queue_get_buffer() failed\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (fb->offset == offset)
+ goto found;
+ }
+
+ dprintk("mmap(): invalid offset = %lu\n", offset);
+ ret = -EINVAL;
+ goto out;
+
+found:
+ dprintk("mmap(): buffer = %d\n", i);
+
+ if (size > (fb->desc_table.page_count * PAGE_SIZE)) {
+ dprintk("mmap(): failed: size = %lu > %lu\n",
+ size, fb->desc_table.page_count * PAGE_SIZE);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ for (i = 0; i < fb->desc_table.page_count; i++) {
+ unsigned long pfn =
+ virt_to_phys((void *)fb->desc_table.virtual[i]) >>
+ PAGE_SHIFT;
+
+ if (size < PAGE_SIZE)
+ break;
+
+ // protection was: PAGE_READONLY
+ if (remap_pfn_range(vma, start, pfn, PAGE_SIZE,
+ vma->vm_page_prot)) {
+ dprintk("mmap(): remap_pfn_range() failed\n");
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ start += PAGE_SIZE;
+ size -= PAGE_SIZE;
+ }
+
+ fb->map_count = 1;
+
+ vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+ vma->vm_flags &= ~VM_IO;
+ vma->vm_private_data = fb;
+ vma->vm_file = file;
+ vma->vm_ops = &vino_vm_ops;
+
+out:
+ mutex_unlock(&vcs->mutex);
+
+ return ret;
+}
+
+static unsigned int vino_poll(struct file *file, poll_table *pt)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ unsigned int outgoing;
+ unsigned int ret = 0;
+
+ // lock mutex (?)
+ // TODO: this has to be corrected for different read modes
+
+ dprintk("poll():\n");
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("poll(): vino_queue_get_outgoing() failed\n");
+ ret = POLLERR;
+ goto error;
+ }
+ if (outgoing > 0)
+ goto over;
+
+ poll_wait(file, &vcs->fb_queue.frame_wait_queue, pt);
+
+ if (vino_queue_get_outgoing(&vcs->fb_queue, &outgoing)) {
+ dprintk("poll(): vino_queue_get_outgoing() failed\n");
+ ret = POLLERR;
+ goto error;
+ }
+
+over:
+ dprintk("poll(): data %savailable\n",
+ (outgoing > 0) ? "" : "not ");
+
+ if (outgoing > 0)
+ ret = POLLIN | POLLRDNORM;
+
+error:
+ return ret;
+}
+
+static long vino_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ struct vino_channel_settings *vcs = video_drvdata(file);
+ long ret;
+
+ if (mutex_lock_interruptible(&vcs->mutex))
+ return -EINTR;
+
+ ret = video_ioctl2(file, cmd, arg);
+
+ mutex_unlock(&vcs->mutex);
+
+ return ret;
+}
+
+/* Initialization and cleanup */
+
+/* __initdata */
+static int vino_init_stage;
+
+const struct v4l2_ioctl_ops vino_ioctl_ops = {
+ .vidioc_enum_fmt_vid_cap = vino_enum_fmt_vid_cap,
+ .vidioc_g_fmt_vid_cap = vino_g_fmt_vid_cap,
+ .vidioc_s_fmt_vid_cap = vino_s_fmt_vid_cap,
+ .vidioc_try_fmt_vid_cap = vino_try_fmt_vid_cap,
+ .vidioc_querycap = vino_querycap,
+ .vidioc_enum_input = vino_enum_input,
+ .vidioc_g_input = vino_g_input,
+ .vidioc_s_input = vino_s_input,
+ .vidioc_g_std = vino_g_std,
+ .vidioc_s_std = vino_s_std,
+ .vidioc_querystd = vino_querystd,
+ .vidioc_cropcap = vino_cropcap,
+ .vidioc_s_crop = vino_s_crop,
+ .vidioc_g_crop = vino_g_crop,
+ .vidioc_s_parm = vino_s_parm,
+ .vidioc_g_parm = vino_g_parm,
+ .vidioc_reqbufs = vino_reqbufs,
+ .vidioc_querybuf = vino_querybuf,
+ .vidioc_qbuf = vino_qbuf,
+ .vidioc_dqbuf = vino_dqbuf,
+ .vidioc_streamon = vino_streamon,
+ .vidioc_streamoff = vino_streamoff,
+ .vidioc_queryctrl = vino_queryctrl,
+ .vidioc_g_ctrl = vino_g_ctrl,
+ .vidioc_s_ctrl = vino_s_ctrl,
+};
+
+static const struct v4l2_file_operations vino_fops = {
+ .owner = THIS_MODULE,
+ .open = vino_open,
+ .release = vino_close,
+ .unlocked_ioctl = vino_ioctl,
+ .mmap = vino_mmap,
+ .poll = vino_poll,
+};
+
+static struct video_device vdev_template = {
+ .name = "NOT SET",
+ .fops = &vino_fops,
+ .ioctl_ops = &vino_ioctl_ops,
+ .tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM,
+};
+
+static void vino_module_cleanup(int stage)
+{
+ switch(stage) {
+ case 11:
+ video_unregister_device(vino_drvdata->b.vdev);
+ vino_drvdata->b.vdev = NULL;
+ case 10:
+ video_unregister_device(vino_drvdata->a.vdev);
+ vino_drvdata->a.vdev = NULL;
+ case 9:
+ i2c_del_adapter(&vino_i2c_adapter);
+ case 8:
+ free_irq(SGI_VINO_IRQ, NULL);
+ case 7:
+ if (vino_drvdata->b.vdev) {
+ video_device_release(vino_drvdata->b.vdev);
+ vino_drvdata->b.vdev = NULL;
+ }
+ case 6:
+ if (vino_drvdata->a.vdev) {
+ video_device_release(vino_drvdata->a.vdev);
+ vino_drvdata->a.vdev = NULL;
+ }
+ case 5:
+ /* all entries in dma_cpu dummy table have the same address */
+ dma_unmap_single(NULL,
+ vino_drvdata->dummy_desc_table.dma_cpu[0],
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ dma_free_coherent(NULL, VINO_DUMMY_DESC_COUNT
+ * sizeof(dma_addr_t),
+ (void *)vino_drvdata->
+ dummy_desc_table.dma_cpu,
+ vino_drvdata->dummy_desc_table.dma);
+ case 4:
+ free_page(vino_drvdata->dummy_page);
+ case 3:
+ v4l2_device_unregister(&vino_drvdata->v4l2_dev);
+ case 2:
+ kfree(vino_drvdata);
+ case 1:
+ iounmap(vino);
+ case 0:
+ break;
+ default:
+ dprintk("vino_module_cleanup(): invalid cleanup stage = %d\n",
+ stage);
+ }
+}
+
+static int vino_probe(void)
+{
+ unsigned long rev_id;
+
+ if (ip22_is_fullhouse()) {
+ printk(KERN_ERR "VINO doesn't exist in IP22 Fullhouse\n");
+ return -ENODEV;
+ }
+
+ if (!(sgimc->systemid & SGIMC_SYSID_EPRESENT)) {
+ printk(KERN_ERR "VINO is not found (EISA BUS not present)\n");
+ return -ENODEV;
+ }
+
+ vino = (struct sgi_vino *)ioremap(VINO_BASE, sizeof(struct sgi_vino));
+ if (!vino) {
+ printk(KERN_ERR "VINO: ioremap() failed\n");
+ return -EIO;
+ }
+ vino_init_stage++;
+
+ if (get_dbe(rev_id, &(vino->rev_id))) {
+ printk(KERN_ERR "Failed to read VINO revision register\n");
+ vino_module_cleanup(vino_init_stage);
+ return -ENODEV;
+ }
+
+ if (VINO_ID_VALUE(rev_id) != VINO_CHIP_ID) {
+ printk(KERN_ERR "Unknown VINO chip ID (Rev/ID: 0x%02lx)\n",
+ rev_id);
+ vino_module_cleanup(vino_init_stage);
+ return -ENODEV;
+ }
+
+ printk(KERN_INFO "VINO revision %ld found\n", VINO_REV_NUM(rev_id));
+
+ return 0;
+}
+
+static int vino_init(void)
+{
+ dma_addr_t dma_dummy_address;
+ int err;
+ int i;
+
+ vino_drvdata = kzalloc(sizeof(struct vino_settings), GFP_KERNEL);
+ if (!vino_drvdata) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
+ }
+ vino_init_stage++;
+ strlcpy(vino_drvdata->v4l2_dev.name, "vino",
+ sizeof(vino_drvdata->v4l2_dev.name));
+ err = v4l2_device_register(NULL, &vino_drvdata->v4l2_dev);
+ if (err)
+ return err;
+ vino_init_stage++;
+
+ /* create a dummy dma descriptor */
+ vino_drvdata->dummy_page = get_zeroed_page(GFP_KERNEL | GFP_DMA);
+ if (!vino_drvdata->dummy_page) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
+ }
+ vino_init_stage++;
+
+ // TODO: use page_count in dummy_desc_table
+
+ vino_drvdata->dummy_desc_table.dma_cpu =
+ dma_alloc_coherent(NULL,
+ VINO_DUMMY_DESC_COUNT * sizeof(dma_addr_t),
+ &vino_drvdata->dummy_desc_table.dma,
+ GFP_KERNEL | GFP_DMA);
+ if (!vino_drvdata->dummy_desc_table.dma_cpu) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
+ }
+ vino_init_stage++;
+
+ dma_dummy_address = dma_map_single(NULL,
+ (void *)vino_drvdata->dummy_page,
+ PAGE_SIZE, DMA_FROM_DEVICE);
+ for (i = 0; i < VINO_DUMMY_DESC_COUNT; i++) {
+ vino_drvdata->dummy_desc_table.dma_cpu[i] = dma_dummy_address;
+ }
+
+ /* initialize VINO */
+
+ vino->control = 0;
+ vino->a.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+ vino->b.next_4_desc = vino_drvdata->dummy_desc_table.dma;
+ udelay(VINO_DESC_FETCH_DELAY);
+
+ vino->intr_status = 0;
+
+ vino->a.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+ vino->b.fifo_thres = VINO_FIFO_THRESHOLD_DEFAULT;
+
+ return 0;
+}
+
+static int vino_init_channel_settings(struct vino_channel_settings *vcs,
+ unsigned int channel, const char *name)
+{
+ vcs->channel = channel;
+ vcs->input = VINO_INPUT_NONE;
+ vcs->alpha = 0;
+ vcs->users = 0;
+ vcs->data_format = VINO_DATA_FMT_GREY;
+ vcs->data_norm = VINO_DATA_NORM_NTSC;
+ vcs->decimation = 1;
+ vino_set_default_clipping(vcs);
+ vino_set_default_framerate(vcs);
+
+ vcs->capturing = 0;
+
+ mutex_init(&vcs->mutex);
+ spin_lock_init(&vcs->capture_lock);
+
+ mutex_init(&vcs->fb_queue.queue_mutex);
+ spin_lock_init(&vcs->fb_queue.queue_lock);
+ init_waitqueue_head(&vcs->fb_queue.frame_wait_queue);
+
+ vcs->vdev = video_device_alloc();
+ if (!vcs->vdev) {
+ vino_module_cleanup(vino_init_stage);
+ return -ENOMEM;
+ }
+ vino_init_stage++;
+
+ memcpy(vcs->vdev, &vdev_template,
+ sizeof(struct video_device));
+ strcpy(vcs->vdev->name, name);
+ vcs->vdev->release = video_device_release;
+ vcs->vdev->v4l2_dev = &vino_drvdata->v4l2_dev;
+
+ video_set_drvdata(vcs->vdev, vcs);
+
+ return 0;
+}
+
+static int __init vino_module_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "SGI VINO driver version %s\n",
+ VINO_MODULE_VERSION);
+
+ ret = vino_probe();
+ if (ret)
+ return ret;
+
+ ret = vino_init();
+ if (ret)
+ return ret;
+
+ /* initialize data structures */
+
+ spin_lock_init(&vino_drvdata->vino_lock);
+ spin_lock_init(&vino_drvdata->input_lock);
+
+ ret = vino_init_channel_settings(&vino_drvdata->a, VINO_CHANNEL_A,
+ vino_vdev_name_a);
+ if (ret)
+ return ret;
+
+ ret = vino_init_channel_settings(&vino_drvdata->b, VINO_CHANNEL_B,
+ vino_vdev_name_b);
+ if (ret)
+ return ret;
+
+ /* initialize hardware and register V4L devices */
+
+ ret = request_irq(SGI_VINO_IRQ, vino_interrupt, 0,
+ vino_driver_description, NULL);
+ if (ret) {
+ printk(KERN_ERR "VINO: requesting IRQ %02d failed\n",
+ SGI_VINO_IRQ);
+ vino_module_cleanup(vino_init_stage);
+ return -EAGAIN;
+ }
+ vino_init_stage++;
+
+ ret = i2c_add_adapter(&vino_i2c_adapter);
+ if (ret) {
+ printk(KERN_ERR "VINO I2C bus registration failed\n");
+ vino_module_cleanup(vino_init_stage);
+ return ret;
+ }
+ i2c_set_adapdata(&vino_i2c_adapter, &vino_drvdata->v4l2_dev);
+ vino_init_stage++;
+
+ ret = video_register_device(vino_drvdata->a.vdev,
+ VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ printk(KERN_ERR "VINO channel A Video4Linux-device "
+ "registration failed\n");
+ vino_module_cleanup(vino_init_stage);
+ return -EINVAL;
+ }
+ vino_init_stage++;
+
+ ret = video_register_device(vino_drvdata->b.vdev,
+ VFL_TYPE_GRABBER, -1);
+ if (ret < 0) {
+ printk(KERN_ERR "VINO channel B Video4Linux-device "
+ "registration failed\n");
+ vino_module_cleanup(vino_init_stage);
+ return -EINVAL;
+ }
+ vino_init_stage++;
+
+ vino_drvdata->decoder =
+ v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
+ "saa7191", 0, I2C_ADDRS(0x45));
+ vino_drvdata->camera =
+ v4l2_i2c_new_subdev(&vino_drvdata->v4l2_dev, &vino_i2c_adapter,
+ "indycam", 0, I2C_ADDRS(0x2b));
+
+ dprintk("init complete!\n");
+
+ return 0;
+}
+
+static void __exit vino_module_exit(void)
+{
+ dprintk("exiting, stage = %d ...\n", vino_init_stage);
+ vino_module_cleanup(vino_init_stage);
+ dprintk("cleanup complete, exit!\n");
+}
+
+module_init(vino_module_init);
+module_exit(vino_module_exit);
diff --git a/drivers/media/platform/vino.h b/drivers/media/platform/vino.h
new file mode 100644
index 0000000..de2d615
--- /dev/null
+++ b/drivers/media/platform/vino.h
@@ -0,0 +1,138 @@
+/*
+ * Driver for the VINO (Video In No Out) system found in SGI Indys.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * Copyright (C) 1999 Ulf Karlsson <ulfc@bun.falkenberg.se>
+ * Copyright (C) 2003 Ladislav Michl <ladis@linux-mips.org>
+ */
+
+#ifndef _VINO_H_
+#define _VINO_H_
+
+#define VINO_BASE 0x00080000 /* Vino is in the EISA address space,
+ * but it is not an EISA bus card */
+#define VINO_PAGE_SIZE 4096
+
+struct sgi_vino_channel {
+ u32 _pad_alpha;
+ volatile u32 alpha;
+
+#define VINO_CLIP_X(x) ((x) & 0x3ff) /* bits 0:9 */
+#define VINO_CLIP_ODD(x) (((x) & 0x1ff) << 10) /* bits 10:18 */
+#define VINO_CLIP_EVEN(x) (((x) & 0x1ff) << 19) /* bits 19:27 */
+ u32 _pad_clip_start;
+ volatile u32 clip_start;
+ u32 _pad_clip_end;
+ volatile u32 clip_end;
+
+#define VINO_FRAMERT_FULL 0xfff
+#define VINO_FRAMERT_PAL (1<<0) /* 0=NTSC 1=PAL */
+#define VINO_FRAMERT_RT(x) (((x) & 0xfff) << 1) /* bits 1:12 */
+ u32 _pad_frame_rate;
+ volatile u32 frame_rate;
+
+ u32 _pad_field_counter;
+ volatile u32 field_counter;
+ u32 _pad_line_size;
+ volatile u32 line_size;
+ u32 _pad_line_count;
+ volatile u32 line_count;
+ u32 _pad_page_index;
+ volatile u32 page_index;
+ u32 _pad_next_4_desc;
+ volatile u32 next_4_desc;
+ u32 _pad_start_desc_tbl;
+ volatile u32 start_desc_tbl;
+
+#define VINO_DESC_JUMP (1<<30)
+#define VINO_DESC_STOP (1<<31)
+#define VINO_DESC_VALID (1<<32)
+ u32 _pad_desc_0;
+ volatile u32 desc_0;
+ u32 _pad_desc_1;
+ volatile u32 desc_1;
+ u32 _pad_desc_2;
+ volatile u32 desc_2;
+ u32 _pad_Bdesc_3;
+ volatile u32 desc_3;
+
+ u32 _pad_fifo_thres;
+ volatile u32 fifo_thres;
+ u32 _pad_fifo_read;
+ volatile u32 fifo_read;
+ u32 _pad_fifo_write;
+ volatile u32 fifo_write;
+};
+
+struct sgi_vino {
+#define VINO_CHIP_ID 0xb
+#define VINO_REV_NUM(x) ((x) & 0x0f)
+#define VINO_ID_VALUE(x) (((x) & 0xf0) >> 4)
+ u32 _pad_rev_id;
+ volatile u32 rev_id;
+
+#define VINO_CTRL_LITTLE_ENDIAN (1<<0)
+#define VINO_CTRL_A_EOF_INT (1<<1) /* Field transferred int */
+#define VINO_CTRL_A_FIFO_INT (1<<2) /* FIFO overflow int */
+#define VINO_CTRL_A_EOD_INT (1<<3) /* End of desc table int */
+#define VINO_CTRL_A_INT (VINO_CTRL_A_EOF_INT | \
+ VINO_CTRL_A_FIFO_INT | \
+ VINO_CTRL_A_EOD_INT)
+#define VINO_CTRL_B_EOF_INT (1<<4) /* Field transferred int */
+#define VINO_CTRL_B_FIFO_INT (1<<5) /* FIFO overflow int */
+#define VINO_CTRL_B_EOD_INT (1<<6) /* End of desc table int */
+#define VINO_CTRL_B_INT (VINO_CTRL_B_EOF_INT | \
+ VINO_CTRL_B_FIFO_INT | \
+ VINO_CTRL_B_EOD_INT)
+#define VINO_CTRL_A_DMA_ENBL (1<<7)
+#define VINO_CTRL_A_INTERLEAVE_ENBL (1<<8)
+#define VINO_CTRL_A_SYNC_ENBL (1<<9)
+#define VINO_CTRL_A_SELECT (1<<10) /* 1=D1 0=Philips */
+#define VINO_CTRL_A_RGB (1<<11) /* 1=RGB 0=YUV */
+#define VINO_CTRL_A_LUMA_ONLY (1<<12)
+#define VINO_CTRL_A_DEC_ENBL (1<<13) /* Decimation */
+#define VINO_CTRL_A_DEC_SCALE_MASK 0x1c000 /* bits 14:17 */
+#define VINO_CTRL_A_DEC_SCALE_SHIFT (14)
+#define VINO_CTRL_A_DEC_HOR_ONLY (1<<17) /* Horizontal only */
+#define VINO_CTRL_A_DITHER (1<<18) /* 24 -> 8 bit dither */
+#define VINO_CTRL_B_DMA_ENBL (1<<19)
+#define VINO_CTRL_B_INTERLEAVE_ENBL (1<<20)
+#define VINO_CTRL_B_SYNC_ENBL (1<<21)
+#define VINO_CTRL_B_SELECT (1<<22) /* 1=D1 0=Philips */
+#define VINO_CTRL_B_RGB (1<<23) /* 1=RGB 0=YUV */
+#define VINO_CTRL_B_LUMA_ONLY (1<<24)
+#define VINO_CTRL_B_DEC_ENBL (1<<25) /* Decimation */
+#define VINO_CTRL_B_DEC_SCALE_MASK 0x1c000000 /* bits 26:28 */
+#define VINO_CTRL_B_DEC_SCALE_SHIFT (26)
+#define VINO_CTRL_B_DEC_HOR_ONLY (1<<29) /* Decimation horizontal only */
+#define VINO_CTRL_B_DITHER (1<<30) /* ChanB 24 -> 8 bit dither */
+ u32 _pad_control;
+ volatile u32 control;
+
+#define VINO_INTSTAT_A_EOF (1<<0) /* Field transferred int */
+#define VINO_INTSTAT_A_FIFO (1<<1) /* FIFO overflow int */
+#define VINO_INTSTAT_A_EOD (1<<2) /* End of desc table int */
+#define VINO_INTSTAT_A (VINO_INTSTAT_A_EOF | \
+ VINO_INTSTAT_A_FIFO | \
+ VINO_INTSTAT_A_EOD)
+#define VINO_INTSTAT_B_EOF (1<<3) /* Field transferred int */
+#define VINO_INTSTAT_B_FIFO (1<<4) /* FIFO overflow int */
+#define VINO_INTSTAT_B_EOD (1<<5) /* End of desc table int */
+#define VINO_INTSTAT_B (VINO_INTSTAT_B_EOF | \
+ VINO_INTSTAT_B_FIFO | \
+ VINO_INTSTAT_B_EOD)
+ u32 _pad_intr_status;
+ volatile u32 intr_status;
+
+ u32 _pad_i2c_control;
+ volatile u32 i2c_control;
+ u32 _pad_i2c_data;
+ volatile u32 i2c_data;
+
+ struct sgi_vino_channel a;
+ struct sgi_vino_channel b;
+};
+
+#endif
diff --git a/drivers/media/platform/vivid/Kconfig b/drivers/media/platform/vivid/Kconfig
index c03e09c..0d2d7c1 100644
--- a/drivers/media/platform/vivid/Kconfig
+++ b/drivers/media/platform/vivid/Kconfig
@@ -1,12 +1,9 @@
config VIDEO_VIVID
tristate "Virtual Video Test Driver"
depends on m
- depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64 && FB
+ depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
depends on FONT_SUPPORT
depends on FONT_8x16
- depends on FB_CFB_FILLRECT
- depends on FB_CFB_COPYAREA
- depends on FB_CFB_IMAGEBLIT
select VIDEOBUF2_VMALLOC
default n
---help---
diff --git a/drivers/media/platform/vivid/vivid-core.c b/drivers/media/platform/vivid/vivid-core.c
index a7e033a..2c61a62 100644
--- a/drivers/media/platform/vivid/vivid-core.c
+++ b/drivers/media/platform/vivid/vivid-core.c
@@ -100,9 +100,11 @@
"\t\t bit 0=crop, 1=compose, 2=scale,\n"
"\t\t -1=user-controlled (default)");
-static unsigned multiplanar[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 1 };
+static unsigned multiplanar[VIVID_MAX_DEVS];
module_param_array(multiplanar, uint, NULL, 0444);
-MODULE_PARM_DESC(multiplanar, " 1 (default) creates a single planar device, 2 creates a multiplanar device.");
+MODULE_PARM_DESC(multiplanar, " 0 (default) is alternating single and multiplanar devices,\n"
+ "\t\t 1 is single planar devices,\n"
+ "\t\t 2 is multiplanar devices");
/* Default: video + vbi-cap (raw and sliced) + radio rx + radio tx + sdr + vbi-out + vid-out */
static unsigned node_types[VIVID_MAX_DEVS] = { [0 ... (VIVID_MAX_DEVS - 1)] = 0x1d3d };
@@ -195,6 +197,20 @@
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7
};
+void vivid_lock(struct vb2_queue *vq)
+{
+ struct vivid_dev *dev = vb2_get_drv_priv(vq);
+
+ mutex_lock(&dev->mutex);
+}
+
+void vivid_unlock(struct vb2_queue *vq)
+{
+ struct vivid_dev *dev = vb2_get_drv_priv(vq);
+
+ mutex_unlock(&dev->mutex);
+}
+
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -572,7 +588,7 @@
.vidioc_querybuf = vb2_ioctl_querybuf,
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
- .vidioc_expbuf = vb2_ioctl_expbuf,
+/* Not yet .vidioc_expbuf = vb2_ioctl_expbuf,*/
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
@@ -653,7 +669,10 @@
/* start detecting feature set */
/* do we use single- or multi-planar? */
- dev->multiplanar = multiplanar[inst] > 1;
+ if (multiplanar[inst] == 0)
+ dev->multiplanar = inst & 1;
+ else
+ dev->multiplanar = multiplanar[inst] > 1;
v4l2_info(&dev->v4l2_dev, "using %splanar format API\n",
dev->multiplanar ? "multi" : "single ");
@@ -1004,7 +1023,6 @@
q->mem_ops = &vb2_vmalloc_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->min_buffers_needed = 2;
- q->lock = &dev->mutex;
ret = vb2_queue_init(q);
if (ret)
@@ -1023,7 +1041,6 @@
q->mem_ops = &vb2_vmalloc_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->min_buffers_needed = 2;
- q->lock = &dev->mutex;
ret = vb2_queue_init(q);
if (ret)
@@ -1042,7 +1059,6 @@
q->mem_ops = &vb2_vmalloc_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->min_buffers_needed = 2;
- q->lock = &dev->mutex;
ret = vb2_queue_init(q);
if (ret)
@@ -1061,7 +1077,6 @@
q->mem_ops = &vb2_vmalloc_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->min_buffers_needed = 2;
- q->lock = &dev->mutex;
ret = vb2_queue_init(q);
if (ret)
@@ -1079,7 +1094,6 @@
q->mem_ops = &vb2_vmalloc_memops;
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->min_buffers_needed = 8;
- q->lock = &dev->mutex;
ret = vb2_queue_init(q);
if (ret)
diff --git a/drivers/media/platform/vivid/vivid-core.h b/drivers/media/platform/vivid/vivid-core.h
index 4b497df..811c286 100644
--- a/drivers/media/platform/vivid/vivid-core.h
+++ b/drivers/media/platform/vivid/vivid-core.h
@@ -116,17 +116,6 @@
CUSTOM_DV_TIMINGS,
};
-enum vivid_colorspace {
- VIVID_CS_170M,
- VIVID_CS_709,
- VIVID_CS_SRGB,
- VIVID_CS_ADOBERGB,
- VIVID_CS_2020,
- VIVID_CS_240M,
- VIVID_CS_SYS_M,
- VIVID_CS_SYS_BG,
-};
-
#define VIVID_INVALID_SIGNAL(mode) \
((mode) == NO_SIGNAL || (mode) == NO_LOCK || (mode) == OUT_OF_RANGE)
@@ -329,8 +318,6 @@
v4l2_std_id std_out;
struct v4l2_dv_timings dv_timings_out;
u32 colorspace_out;
- u32 ycbcr_enc_out;
- u32 quantization_out;
u32 service_set_out;
u32 bytesperline_out[2];
unsigned tv_field_out;
@@ -527,4 +514,7 @@
return dev->output_type[dev->output] == HDMI;
}
+void vivid_lock(struct vb2_queue *vq);
+void vivid_unlock(struct vb2_queue *vq);
+
#endif
diff --git a/drivers/media/platform/vivid/vivid-ctrls.c b/drivers/media/platform/vivid/vivid-ctrls.c
index 857e786..d5cbf00 100644
--- a/drivers/media/platform/vivid/vivid-ctrls.c
+++ b/drivers/media/platform/vivid/vivid-ctrls.c
@@ -40,9 +40,6 @@
#define VIVID_CID_STRING (VIVID_CID_CUSTOM_BASE + 5)
#define VIVID_CID_BITMASK (VIVID_CID_CUSTOM_BASE + 6)
#define VIVID_CID_INTMENU (VIVID_CID_CUSTOM_BASE + 7)
-#define VIVID_CID_U32_ARRAY (VIVID_CID_CUSTOM_BASE + 8)
-#define VIVID_CID_U16_MATRIX (VIVID_CID_CUSTOM_BASE + 9)
-#define VIVID_CID_U8_4D_ARRAY (VIVID_CID_CUSTOM_BASE + 10)
#define VIVID_CID_VIVID_BASE (0x00f00000 | 0xf000)
#define VIVID_CID_VIVID_CLASS (0x00f00000 | 1)
@@ -62,21 +59,19 @@
#define VIVID_CID_DV_TIMINGS_ASPECT_RATIO (VIVID_CID_VIVID_BASE + 23)
#define VIVID_CID_TSTAMP_SRC (VIVID_CID_VIVID_BASE + 24)
#define VIVID_CID_COLORSPACE (VIVID_CID_VIVID_BASE + 25)
-#define VIVID_CID_YCBCR_ENC (VIVID_CID_VIVID_BASE + 26)
-#define VIVID_CID_QUANTIZATION (VIVID_CID_VIVID_BASE + 27)
-#define VIVID_CID_LIMITED_RGB_RANGE (VIVID_CID_VIVID_BASE + 28)
-#define VIVID_CID_ALPHA_MODE (VIVID_CID_VIVID_BASE + 29)
-#define VIVID_CID_HAS_CROP_CAP (VIVID_CID_VIVID_BASE + 30)
-#define VIVID_CID_HAS_COMPOSE_CAP (VIVID_CID_VIVID_BASE + 31)
-#define VIVID_CID_HAS_SCALER_CAP (VIVID_CID_VIVID_BASE + 32)
-#define VIVID_CID_HAS_CROP_OUT (VIVID_CID_VIVID_BASE + 33)
-#define VIVID_CID_HAS_COMPOSE_OUT (VIVID_CID_VIVID_BASE + 34)
-#define VIVID_CID_HAS_SCALER_OUT (VIVID_CID_VIVID_BASE + 35)
-#define VIVID_CID_LOOP_VIDEO (VIVID_CID_VIVID_BASE + 36)
-#define VIVID_CID_SEQ_WRAP (VIVID_CID_VIVID_BASE + 37)
-#define VIVID_CID_TIME_WRAP (VIVID_CID_VIVID_BASE + 38)
-#define VIVID_CID_MAX_EDID_BLOCKS (VIVID_CID_VIVID_BASE + 39)
-#define VIVID_CID_PERCENTAGE_FILL (VIVID_CID_VIVID_BASE + 40)
+#define VIVID_CID_LIMITED_RGB_RANGE (VIVID_CID_VIVID_BASE + 26)
+#define VIVID_CID_ALPHA_MODE (VIVID_CID_VIVID_BASE + 27)
+#define VIVID_CID_HAS_CROP_CAP (VIVID_CID_VIVID_BASE + 28)
+#define VIVID_CID_HAS_COMPOSE_CAP (VIVID_CID_VIVID_BASE + 29)
+#define VIVID_CID_HAS_SCALER_CAP (VIVID_CID_VIVID_BASE + 30)
+#define VIVID_CID_HAS_CROP_OUT (VIVID_CID_VIVID_BASE + 31)
+#define VIVID_CID_HAS_COMPOSE_OUT (VIVID_CID_VIVID_BASE + 32)
+#define VIVID_CID_HAS_SCALER_OUT (VIVID_CID_VIVID_BASE + 33)
+#define VIVID_CID_LOOP_VIDEO (VIVID_CID_VIVID_BASE + 34)
+#define VIVID_CID_SEQ_WRAP (VIVID_CID_VIVID_BASE + 35)
+#define VIVID_CID_TIME_WRAP (VIVID_CID_VIVID_BASE + 36)
+#define VIVID_CID_MAX_EDID_BLOCKS (VIVID_CID_VIVID_BASE + 37)
+#define VIVID_CID_PERCENTAGE_FILL (VIVID_CID_VIVID_BASE + 38)
#define VIVID_CID_STD_SIGNAL_MODE (VIVID_CID_VIVID_BASE + 60)
#define VIVID_CID_STANDARD (VIVID_CID_VIVID_BASE + 61)
@@ -168,42 +163,6 @@
.step = 1,
};
-static const struct v4l2_ctrl_config vivid_ctrl_u32_array = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_U32_ARRAY,
- .name = "U32 1 Element Array",
- .type = V4L2_CTRL_TYPE_U32,
- .def = 0x18,
- .min = 0x10,
- .max = 0x20000,
- .step = 1,
- .dims = { 1 },
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_u16_matrix = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_U16_MATRIX,
- .name = "U16 8x16 Matrix",
- .type = V4L2_CTRL_TYPE_U16,
- .def = 0x18,
- .min = 0x10,
- .max = 0x2000,
- .step = 1,
- .dims = { 8, 16 },
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_u8_4d_array = {
- .ops = &vivid_user_gen_ctrl_ops,
- .id = VIVID_CID_U8_4D_ARRAY,
- .name = "U8 2x3x4x5 Array",
- .type = V4L2_CTRL_TYPE_U8,
- .def = 0x18,
- .min = 0x10,
- .max = 0x20,
- .step = 1,
- .dims = { 2, 3, 4, 5 },
-};
-
static const char * const vivid_ctrl_menu_strings[] = {
"Menu Item 0 (Skipped)",
"Menu Item 1",
@@ -335,16 +294,6 @@
static int vivid_vid_cap_s_ctrl(struct v4l2_ctrl *ctrl)
{
- static const u32 colorspaces[] = {
- V4L2_COLORSPACE_SMPTE170M,
- V4L2_COLORSPACE_REC709,
- V4L2_COLORSPACE_SRGB,
- V4L2_COLORSPACE_ADOBERGB,
- V4L2_COLORSPACE_BT2020,
- V4L2_COLORSPACE_SMPTE240M,
- V4L2_COLORSPACE_470_SYSTEM_M,
- V4L2_COLORSPACE_470_SYSTEM_BG,
- };
struct vivid_dev *dev = container_of(ctrl->handler, struct vivid_dev, ctrl_hdl_vid_cap);
unsigned i;
@@ -354,21 +303,7 @@
tpg_s_pattern(&dev->tpg, ctrl->val);
break;
case VIVID_CID_COLORSPACE:
- tpg_s_colorspace(&dev->tpg, colorspaces[ctrl->val]);
- vivid_send_source_change(dev, TV);
- vivid_send_source_change(dev, SVID);
- vivid_send_source_change(dev, HDMI);
- vivid_send_source_change(dev, WEBCAM);
- break;
- case VIVID_CID_YCBCR_ENC:
- tpg_s_ycbcr_enc(&dev->tpg, ctrl->val);
- vivid_send_source_change(dev, TV);
- vivid_send_source_change(dev, SVID);
- vivid_send_source_change(dev, HDMI);
- vivid_send_source_change(dev, WEBCAM);
- break;
- case VIVID_CID_QUANTIZATION:
- tpg_s_quantization(&dev->tpg, ctrl->val);
+ tpg_s_colorspace(&dev->tpg, ctrl->val);
vivid_send_source_change(dev, TV);
vivid_send_source_change(dev, SVID);
vivid_send_source_change(dev, HDMI);
@@ -688,14 +623,15 @@
};
static const char * const vivid_ctrl_colorspace_strings[] = {
+ "",
"SMPTE 170M",
- "REC 709",
- "sRGB",
- "AdobeRGB",
- "BT.2020",
"SMPTE 240M",
+ "REC 709",
+ "", /* Skip Bt878 entry */
"470 System M",
"470 System BG",
+ "", /* Skip JPEG entry */
+ "sRGB",
NULL,
};
@@ -704,47 +640,11 @@
.id = VIVID_CID_COLORSPACE,
.name = "Colorspace",
.type = V4L2_CTRL_TYPE_MENU,
- .max = 7,
- .def = 2,
- .qmenu = vivid_ctrl_colorspace_strings,
-};
-
-static const char * const vivid_ctrl_ycbcr_enc_strings[] = {
- "Default",
- "ITU-R 601",
- "Rec. 709",
- "xvYCC 601",
- "xvYCC 709",
- "sYCC",
- "BT.2020 Non-Constant Luminance",
- "BT.2020 Constant Luminance",
- "SMPTE 240M",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_ycbcr_enc = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_YCBCR_ENC,
- .name = "Y'CbCr Encoding",
- .type = V4L2_CTRL_TYPE_MENU,
+ .min = 1,
.max = 8,
- .qmenu = vivid_ctrl_ycbcr_enc_strings,
-};
-
-static const char * const vivid_ctrl_quantization_strings[] = {
- "Default",
- "Full Range",
- "Limited Range",
- NULL,
-};
-
-static const struct v4l2_ctrl_config vivid_ctrl_quantization = {
- .ops = &vivid_vid_cap_ctrl_ops,
- .id = VIVID_CID_QUANTIZATION,
- .name = "Quantization",
- .type = V4L2_CTRL_TYPE_MENU,
- .max = 2,
- .qmenu = vivid_ctrl_quantization_strings,
+ .menu_skip_mask = (1 << 4) | (1 << 7),
+ .def = 8,
+ .qmenu = vivid_ctrl_colorspace_strings,
};
static const struct v4l2_ctrl_config vivid_ctrl_alpha_mode = {
@@ -823,12 +723,8 @@
dev->colorspace_out = V4L2_COLORSPACE_SMPTE170M;
else
dev->colorspace_out = V4L2_COLORSPACE_REC709;
- dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
} else {
dev->colorspace_out = V4L2_COLORSPACE_SRGB;
- dev->quantization_out = dev->dvi_d_out ?
- V4L2_QUANTIZATION_LIM_RANGE :
- V4L2_QUANTIZATION_DEFAULT;
}
if (dev->loop_video)
vivid_send_source_change(dev, HDMI);
@@ -896,15 +792,15 @@
dev->start_streaming_error = true;
break;
case VIVID_CID_QUEUE_ERROR:
- if (vb2_start_streaming_called(&dev->vb_vid_cap_q))
+ if (dev->vb_vid_cap_q.start_streaming_called)
vb2_queue_error(&dev->vb_vid_cap_q);
- if (vb2_start_streaming_called(&dev->vb_vbi_cap_q))
+ if (dev->vb_vbi_cap_q.start_streaming_called)
vb2_queue_error(&dev->vb_vbi_cap_q);
- if (vb2_start_streaming_called(&dev->vb_vid_out_q))
+ if (dev->vb_vid_out_q.start_streaming_called)
vb2_queue_error(&dev->vb_vid_out_q);
- if (vb2_start_streaming_called(&dev->vb_vbi_out_q))
+ if (dev->vb_vbi_out_q.start_streaming_called)
vb2_queue_error(&dev->vb_vbi_out_q);
- if (vb2_start_streaming_called(&dev->vb_sdr_cap_q))
+ if (dev->vb_sdr_cap_q.start_streaming_called)
vb2_queue_error(&dev->vb_sdr_cap_q);
break;
case VIVID_CID_SEQ_WRAP:
@@ -1326,9 +1222,6 @@
dev->string = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_string, NULL);
dev->bitmask = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_bitmask, NULL);
dev->int_menu = v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_int_menu, NULL);
- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u32_array, NULL);
- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u16_matrix, NULL);
- v4l2_ctrl_new_custom(hdl_user_gen, &vivid_ctrl_u8_4d_array, NULL);
if (dev->has_vid_cap) {
/* Image Processing Controls */
@@ -1365,8 +1258,6 @@
v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_tstamp_src, NULL);
dev->colorspace = v4l2_ctrl_new_custom(hdl_vid_cap,
&vivid_ctrl_colorspace, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_ycbcr_enc, NULL);
- v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_quantization, NULL);
v4l2_ctrl_new_custom(hdl_vid_cap, &vivid_ctrl_alpha_mode, NULL);
}
diff --git a/drivers/media/platform/vivid/vivid-sdr-cap.c b/drivers/media/platform/vivid/vivid-sdr-cap.c
index 4af55f1..8c5d661 100644
--- a/drivers/media/platform/vivid/vivid-sdr-cap.c
+++ b/drivers/media/platform/vivid/vivid-sdr-cap.c
@@ -297,8 +297,8 @@
.buf_queue = sdr_cap_buf_queue,
.start_streaming = sdr_cap_start_streaming,
.stop_streaming = sdr_cap_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .wait_prepare = vivid_unlock,
+ .wait_finish = vivid_lock,
};
int vivid_sdr_enum_freq_bands(struct file *file, void *fh, struct v4l2_frequency_band *band)
diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.c b/drivers/media/platform/vivid/vivid-tpg-colors.c
index 424aa7a..2adddc0 100644
--- a/drivers/media/platform/vivid/vivid-tpg-colors.c
+++ b/drivers/media/platform/vivid/vivid-tpg-colors.c
@@ -12,7 +12,7 @@
* This source also contains the code used to generate the tpg_csc_colors
* table. Run the following command to compile it:
*
- * gcc vivid-tpg-colors.c -DCOMPILE_APP -o gen-colors -lm
+ * gcc vivid-colors.c -DCOMPILE_APP -o gen-colors -lm
*
* and run the utility.
*
@@ -78,542 +78,22 @@
#ifndef COMPILE_APP
/* Generated table */
-const unsigned short tpg_rec709_to_linear[255 * 16 + 1] = {
- 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3,
- 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 7, 7,
- 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10,
- 11, 11, 11, 11, 12, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14,
- 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18,
- 18, 18, 18, 18, 19, 19, 19, 19, 20, 20, 20, 20, 20, 21, 21, 21,
- 21, 22, 22, 22, 22, 22, 23, 23, 23, 23, 24, 24, 24, 24, 24, 25,
- 25, 25, 25, 26, 26, 26, 26, 26, 27, 27, 27, 27, 28, 28, 28, 28,
- 28, 29, 29, 29, 29, 30, 30, 30, 30, 30, 31, 31, 31, 31, 32, 32,
- 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 34, 35, 35, 35, 35,
- 36, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39,
- 39, 39, 40, 40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 42,
- 43, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46,
- 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 50,
- 50, 50, 50, 50, 51, 51, 51, 51, 52, 52, 52, 52, 52, 53, 53, 53,
- 53, 54, 54, 54, 54, 54, 55, 55, 55, 55, 56, 56, 56, 56, 56, 57,
- 57, 57, 57, 58, 58, 58, 58, 58, 59, 59, 59, 59, 60, 60, 60, 60,
- 60, 61, 61, 61, 61, 62, 62, 62, 62, 62, 63, 63, 63, 63, 64, 64,
- 64, 64, 64, 65, 65, 65, 65, 66, 66, 66, 66, 66, 67, 67, 67, 67,
- 68, 68, 68, 68, 68, 69, 69, 69, 69, 70, 70, 70, 70, 70, 71, 71,
- 71, 71, 72, 72, 72, 72, 72, 73, 73, 73, 73, 73, 74, 74, 74, 74,
- 74, 75, 75, 75, 75, 76, 76, 76, 76, 76, 77, 77, 77, 77, 78, 78,
- 78, 78, 79, 79, 79, 79, 79, 80, 80, 80, 80, 81, 81, 81, 81, 82,
- 82, 82, 82, 82, 83, 83, 83, 83, 84, 84, 84, 84, 85, 85, 85, 85,
- 86, 86, 86, 86, 87, 87, 87, 87, 88, 88, 88, 88, 89, 89, 89, 89,
- 90, 90, 90, 90, 91, 91, 91, 91, 92, 92, 92, 92, 93, 93, 93, 93,
- 94, 94, 94, 94, 95, 95, 95, 95, 96, 96, 96, 96, 97, 97, 97, 97,
- 98, 98, 98, 98, 99, 99, 99, 99, 100, 100, 100, 101, 101, 101, 101, 102,
- 102, 102, 102, 103, 103, 103, 103, 104, 104, 104, 105, 105, 105, 105, 106, 106,
- 106, 106, 107, 107, 107, 107, 108, 108, 108, 109, 109, 109, 109, 110, 110, 110,
- 111, 111, 111, 111, 112, 112, 112, 112, 113, 113, 113, 114, 114, 114, 114, 115,
- 115, 115, 116, 116, 116, 116, 117, 117, 117, 118, 118, 118, 118, 119, 119, 119,
- 120, 120, 120, 120, 121, 121, 121, 122, 122, 122, 123, 123, 123, 123, 124, 124,
- 124, 125, 125, 125, 125, 126, 126, 126, 127, 127, 127, 128, 128, 128, 128, 129,
- 129, 129, 130, 130, 130, 131, 131, 131, 132, 132, 132, 132, 133, 133, 133, 134,
- 134, 134, 135, 135, 135, 136, 136, 136, 136, 137, 137, 137, 138, 138, 138, 139,
- 139, 139, 140, 140, 140, 141, 141, 141, 142, 142, 142, 142, 143, 143, 143, 144,
- 144, 144, 145, 145, 145, 146, 146, 146, 147, 147, 147, 148, 148, 148, 149, 149,
- 149, 150, 150, 150, 151, 151, 151, 152, 152, 152, 153, 153, 153, 154, 154, 154,
- 155, 155, 155, 156, 156, 156, 157, 157, 157, 158, 158, 158, 159, 159, 159, 160,
- 160, 160, 161, 161, 161, 162, 162, 162, 163, 163, 163, 164, 164, 164, 165, 165,
- 165, 166, 166, 167, 167, 167, 168, 168, 168, 169, 169, 169, 170, 170, 170, 171,
- 171, 171, 172, 172, 172, 173, 173, 174, 174, 174, 175, 175, 175, 176, 176, 176,
- 177, 177, 177, 178, 178, 179, 179, 179, 180, 180, 180, 181, 181, 181, 182, 182,
- 183, 183, 183, 184, 184, 184, 185, 185, 186, 186, 186, 187, 187, 187, 188, 188,
- 188, 189, 189, 190, 190, 190, 191, 191, 191, 192, 192, 193, 193, 193, 194, 194,
- 194, 195, 195, 196, 196, 196, 197, 197, 198, 198, 198, 199, 199, 199, 200, 200,
- 201, 201, 201, 202, 202, 203, 203, 203, 204, 204, 204, 205, 205, 206, 206, 206,
- 207, 207, 208, 208, 208, 209, 209, 210, 210, 210, 211, 211, 212, 212, 212, 213,
- 213, 214, 214, 214, 215, 215, 216, 216, 216, 217, 217, 218, 218, 218, 219, 219,
- 220, 220, 220, 221, 221, 222, 222, 222, 223, 223, 224, 224, 224, 225, 225, 226,
- 226, 227, 227, 227, 228, 228, 229, 229, 229, 230, 230, 231, 231, 232, 232, 232,
- 233, 233, 234, 234, 234, 235, 235, 236, 236, 237, 237, 237, 238, 238, 239, 239,
- 240, 240, 240, 241, 241, 242, 242, 243, 243, 243, 244, 244, 245, 245, 246, 246,
- 246, 247, 247, 248, 248, 249, 249, 249, 250, 250, 251, 251, 252, 252, 252, 253,
- 253, 254, 254, 255, 255, 256, 256, 256, 257, 257, 258, 258, 259, 259, 260, 260,
- 260, 261, 261, 262, 262, 263, 263, 264, 264, 264, 265, 265, 266, 266, 267, 267,
- 268, 268, 269, 269, 269, 270, 270, 271, 271, 272, 272, 273, 273, 274, 274, 274,
- 275, 275, 276, 276, 277, 277, 278, 278, 279, 279, 279, 280, 280, 281, 281, 282,
- 282, 283, 283, 284, 284, 285, 285, 286, 286, 286, 287, 287, 288, 288, 289, 289,
- 290, 290, 291, 291, 292, 292, 293, 293, 294, 294, 295, 295, 295, 296, 296, 297,
- 297, 298, 298, 299, 299, 300, 300, 301, 301, 302, 302, 303, 303, 304, 304, 305,
- 305, 306, 306, 307, 307, 308, 308, 309, 309, 309, 310, 310, 311, 311, 312, 312,
- 313, 313, 314, 314, 315, 315, 316, 316, 317, 317, 318, 318, 319, 319, 320, 320,
- 321, 321, 322, 322, 323, 323, 324, 324, 325, 325, 326, 326, 327, 327, 328, 328,
- 329, 329, 330, 330, 331, 331, 332, 332, 333, 333, 334, 335, 335, 336, 336, 337,
- 337, 338, 338, 339, 339, 340, 340, 341, 341, 342, 342, 343, 343, 344, 344, 345,
- 345, 346, 346, 347, 347, 348, 348, 349, 349, 350, 351, 351, 352, 352, 353, 353,
- 354, 354, 355, 355, 356, 356, 357, 357, 358, 358, 359, 360, 360, 361, 361, 362,
- 362, 363, 363, 364, 364, 365, 365, 366, 366, 367, 368, 368, 369, 369, 370, 370,
- 371, 371, 372, 372, 373, 373, 374, 375, 375, 376, 376, 377, 377, 378, 378, 379,
- 379, 380, 381, 381, 382, 382, 383, 383, 384, 384, 385, 386, 386, 387, 387, 388,
- 388, 389, 389, 390, 391, 391, 392, 392, 393, 393, 394, 394, 395, 396, 396, 397,
- 397, 398, 398, 399, 399, 400, 401, 401, 402, 402, 403, 403, 404, 405, 405, 406,
- 406, 407, 407, 408, 409, 409, 410, 410, 411, 411, 412, 413, 413, 414, 414, 415,
- 415, 416, 417, 417, 418, 418, 419, 419, 420, 421, 421, 422, 422, 423, 424, 424,
- 425, 425, 426, 426, 427, 428, 428, 429, 429, 430, 431, 431, 432, 432, 433, 433,
- 434, 435, 435, 436, 436, 437, 438, 438, 439, 439, 440, 441, 441, 442, 442, 443,
- 444, 444, 445, 445, 446, 447, 447, 448, 448, 449, 450, 450, 451, 451, 452, 453,
- 453, 454, 454, 455, 456, 456, 457, 457, 458, 459, 459, 460, 460, 461, 462, 462,
- 463, 463, 464, 465, 465, 466, 467, 467, 468, 468, 469, 470, 470, 471, 471, 472,
- 473, 473, 474, 475, 475, 476, 476, 477, 478, 478, 479, 480, 480, 481, 481, 482,
- 483, 483, 484, 485, 485, 486, 486, 487, 488, 488, 489, 490, 490, 491, 491, 492,
- 493, 493, 494, 495, 495, 496, 497, 497, 498, 498, 499, 500, 500, 501, 502, 502,
- 503, 504, 504, 505, 505, 506, 507, 507, 508, 509, 509, 510, 511, 511, 512, 513,
- 513, 514, 514, 515, 516, 516, 517, 518, 518, 519, 520, 520, 521, 522, 522, 523,
- 524, 524, 525, 526, 526, 527, 528, 528, 529, 529, 530, 531, 531, 532, 533, 533,
- 534, 535, 535, 536, 537, 537, 538, 539, 539, 540, 541, 541, 542, 543, 543, 544,
- 545, 545, 546, 547, 547, 548, 549, 549, 550, 551, 551, 552, 553, 553, 554, 555,
- 555, 556, 557, 557, 558, 559, 560, 560, 561, 562, 562, 563, 564, 564, 565, 566,
- 566, 567, 568, 568, 569, 570, 570, 571, 572, 572, 573, 574, 575, 575, 576, 577,
- 577, 578, 579, 579, 580, 581, 581, 582, 583, 584, 584, 585, 586, 586, 587, 588,
- 588, 589, 590, 590, 591, 592, 593, 593, 594, 595, 595, 596, 597, 598, 598, 599,
- 600, 600, 601, 602, 602, 603, 604, 605, 605, 606, 607, 607, 608, 609, 610, 610,
- 611, 612, 612, 613, 614, 615, 615, 616, 617, 617, 618, 619, 620, 620, 621, 622,
- 622, 623, 624, 625, 625, 626, 627, 627, 628, 629, 630, 630, 631, 632, 632, 633,
- 634, 635, 635, 636, 637, 638, 638, 639, 640, 640, 641, 642, 643, 643, 644, 645,
- 646, 646, 647, 648, 649, 649, 650, 651, 652, 652, 653, 654, 654, 655, 656, 657,
- 657, 658, 659, 660, 660, 661, 662, 663, 663, 664, 665, 666, 666, 667, 668, 669,
- 669, 670, 671, 672, 672, 673, 674, 675, 675, 676, 677, 678, 678, 679, 680, 681,
- 681, 682, 683, 684, 684, 685, 686, 687, 687, 688, 689, 690, 690, 691, 692, 693,
- 694, 694, 695, 696, 697, 697, 698, 699, 700, 700, 701, 702, 703, 703, 704, 705,
- 706, 707, 707, 708, 709, 710, 710, 711, 712, 713, 714, 714, 715, 716, 717, 717,
- 718, 719, 720, 720, 721, 722, 723, 724, 724, 725, 726, 727, 728, 728, 729, 730,
- 731, 731, 732, 733, 734, 735, 735, 736, 737, 738, 739, 739, 740, 741, 742, 742,
- 743, 744, 745, 746, 746, 747, 748, 749, 750, 750, 751, 752, 753, 754, 754, 755,
- 756, 757, 758, 758, 759, 760, 761, 762, 762, 763, 764, 765, 766, 766, 767, 768,
- 769, 770, 771, 771, 772, 773, 774, 775, 775, 776, 777, 778, 779, 779, 780, 781,
- 782, 783, 783, 784, 785, 786, 787, 788, 788, 789, 790, 791, 792, 793, 793, 794,
- 795, 796, 797, 797, 798, 799, 800, 801, 802, 802, 803, 804, 805, 806, 807, 807,
- 808, 809, 810, 811, 812, 812, 813, 814, 815, 816, 817, 817, 818, 819, 820, 821,
- 822, 822, 823, 824, 825, 826, 827, 827, 828, 829, 830, 831, 832, 832, 833, 834,
- 835, 836, 837, 838, 838, 839, 840, 841, 842, 843, 843, 844, 845, 846, 847, 848,
- 849, 849, 850, 851, 852, 853, 854, 855, 855, 856, 857, 858, 859, 860, 861, 861,
- 862, 863, 864, 865, 866, 867, 867, 868, 869, 870, 871, 872, 873, 873, 874, 875,
- 876, 877, 878, 879, 880, 880, 881, 882, 883, 884, 885, 886, 887, 887, 888, 889,
- 890, 891, 892, 893, 894, 894, 895, 896, 897, 898, 899, 900, 901, 901, 902, 903,
- 904, 905, 906, 907, 908, 909, 909, 910, 911, 912, 913, 914, 915, 916, 916, 917,
- 918, 919, 920, 921, 922, 923, 924, 925, 925, 926, 927, 928, 929, 930, 931, 932,
- 933, 933, 934, 935, 936, 937, 938, 939, 940, 941, 942, 942, 943, 944, 945, 946,
- 947, 948, 949, 950, 951, 952, 952, 953, 954, 955, 956, 957, 958, 959, 960, 961,
- 962, 962, 963, 964, 965, 966, 967, 968, 969, 970, 971, 972, 973, 973, 974, 975,
- 976, 977, 978, 979, 980, 981, 982, 983, 984, 985, 985, 986, 987, 988, 989, 990,
- 991, 992, 993, 994, 995, 996, 997, 998, 998, 999, 1000, 1001, 1002, 1003, 1004, 1005,
- 1006, 1007, 1008, 1009, 1010, 1011, 1012, 1013, 1013, 1014, 1015, 1016, 1017, 1018, 1019, 1020,
- 1021, 1022, 1023, 1024, 1025, 1026, 1027, 1028, 1029, 1030, 1030, 1031, 1032, 1033, 1034, 1035,
- 1036, 1037, 1038, 1039, 1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049, 1050, 1050,
- 1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1065, 1066,
- 1067, 1068, 1069, 1070, 1071, 1072, 1073, 1074, 1075, 1076, 1077, 1078, 1078, 1079, 1080, 1081,
- 1082, 1083, 1084, 1085, 1086, 1087, 1088, 1089, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097,
- 1098, 1099, 1100, 1101, 1102, 1103, 1104, 1105, 1106, 1107, 1108, 1109, 1110, 1111, 1112, 1113,
- 1114, 1115, 1116, 1117, 1118, 1119, 1120, 1121, 1122, 1123, 1124, 1125, 1126, 1127, 1128, 1129,
- 1130, 1131, 1132, 1133, 1134, 1135, 1136, 1137, 1138, 1139, 1140, 1141, 1142, 1143, 1144, 1145,
- 1146, 1147, 1148, 1149, 1150, 1151, 1152, 1153, 1154, 1155, 1156, 1157, 1158, 1159, 1160, 1161,
- 1162, 1163, 1164, 1165, 1166, 1167, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, 1176, 1177,
- 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, 1188, 1189, 1190, 1191, 1193, 1194,
- 1195, 1196, 1197, 1198, 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210,
- 1211, 1212, 1213, 1214, 1215, 1216, 1217, 1218, 1219, 1220, 1221, 1223, 1224, 1225, 1226, 1227,
- 1228, 1229, 1230, 1231, 1232, 1233, 1234, 1235, 1236, 1237, 1238, 1239, 1240, 1241, 1242, 1243,
- 1245, 1246, 1247, 1248, 1249, 1250, 1251, 1252, 1253, 1254, 1255, 1256, 1257, 1258, 1259, 1260,
- 1261, 1262, 1264, 1265, 1266, 1267, 1268, 1269, 1270, 1271, 1272, 1273, 1274, 1275, 1276, 1277,
- 1278, 1280, 1281, 1282, 1283, 1284, 1285, 1286, 1287, 1288, 1289, 1290, 1291, 1292, 1293, 1295,
- 1296, 1297, 1298, 1299, 1300, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1309, 1310, 1311, 1312,
- 1313, 1314, 1315, 1316, 1317, 1318, 1319, 1320, 1322, 1323, 1324, 1325, 1326, 1327, 1328, 1329,
- 1330, 1331, 1332, 1334, 1335, 1336, 1337, 1338, 1339, 1340, 1341, 1342, 1343, 1345, 1346, 1347,
- 1348, 1349, 1350, 1351, 1352, 1353, 1354, 1356, 1357, 1358, 1359, 1360, 1361, 1362, 1363, 1364,
- 1365, 1367, 1368, 1369, 1370, 1371, 1372, 1373, 1374, 1375, 1377, 1378, 1379, 1380, 1381, 1382,
- 1383, 1384, 1385, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1396, 1397, 1398, 1399, 1400,
- 1401, 1402, 1403, 1405, 1406, 1407, 1408, 1409, 1410, 1411, 1412, 1414, 1415, 1416, 1417, 1418,
- 1419, 1420, 1421, 1423, 1424, 1425, 1426, 1427, 1428, 1429, 1431, 1432, 1433, 1434, 1435, 1436,
- 1437, 1439, 1440, 1441, 1442, 1443, 1444, 1445, 1446, 1448, 1449, 1450, 1451, 1452, 1453, 1455,
- 1456, 1457, 1458, 1459, 1460, 1461, 1463, 1464, 1465, 1466, 1467, 1468, 1469, 1471, 1472, 1473,
- 1474, 1475, 1476, 1478, 1479, 1480, 1481, 1482, 1483, 1484, 1486, 1487, 1488, 1489, 1490, 1491,
- 1493, 1494, 1495, 1496, 1497, 1498, 1500, 1501, 1502, 1503, 1504, 1505, 1507, 1508, 1509, 1510,
- 1511, 1512, 1514, 1515, 1516, 1517, 1518, 1519, 1521, 1522, 1523, 1524, 1525, 1527, 1528, 1529,
- 1530, 1531, 1532, 1534, 1535, 1536, 1537, 1538, 1540, 1541, 1542, 1543, 1544, 1545, 1547, 1548,
- 1549, 1550, 1551, 1553, 1554, 1555, 1556, 1557, 1559, 1560, 1561, 1562, 1563, 1564, 1566, 1567,
- 1568, 1569, 1570, 1572, 1573, 1574, 1575, 1576, 1578, 1579, 1580, 1581, 1582, 1584, 1585, 1586,
- 1587, 1588, 1590, 1591, 1592, 1593, 1594, 1596, 1597, 1598, 1599, 1601, 1602, 1603, 1604, 1605,
- 1607, 1608, 1609, 1610, 1611, 1613, 1614, 1615, 1616, 1617, 1619, 1620, 1621, 1622, 1624, 1625,
- 1626, 1627, 1628, 1630, 1631, 1632, 1633, 1635, 1636, 1637, 1638, 1639, 1641, 1642, 1643, 1644,
- 1646, 1647, 1648, 1649, 1650, 1652, 1653, 1654, 1655, 1657, 1658, 1659, 1660, 1662, 1663, 1664,
- 1665, 1667, 1668, 1669, 1670, 1671, 1673, 1674, 1675, 1676, 1678, 1679, 1680, 1681, 1683, 1684,
- 1685, 1686, 1688, 1689, 1690, 1691, 1693, 1694, 1695, 1696, 1698, 1699, 1700, 1701, 1703, 1704,
- 1705, 1706, 1708, 1709, 1710, 1711, 1713, 1714, 1715, 1716, 1718, 1719, 1720, 1721, 1723, 1724,
- 1725, 1726, 1728, 1729, 1730, 1731, 1733, 1734, 1735, 1737, 1738, 1739, 1740, 1742, 1743, 1744,
- 1745, 1747, 1748, 1749, 1750, 1752, 1753, 1754, 1756, 1757, 1758, 1759, 1761, 1762, 1763, 1764,
- 1766, 1767, 1768, 1770, 1771, 1772, 1773, 1775, 1776, 1777, 1778, 1780, 1781, 1782, 1784, 1785,
- 1786, 1787, 1789, 1790, 1791, 1793, 1794, 1795, 1796, 1798, 1799, 1800, 1802, 1803, 1804, 1806,
- 1807, 1808, 1809, 1811, 1812, 1813, 1815, 1816, 1817, 1818, 1820, 1821, 1822, 1824, 1825, 1826,
- 1828, 1829, 1830, 1831, 1833, 1834, 1835, 1837, 1838, 1839, 1841, 1842, 1843, 1844, 1846, 1847,
- 1848, 1850, 1851, 1852, 1854, 1855, 1856, 1858, 1859, 1860, 1862, 1863, 1864, 1865, 1867, 1868,
- 1869, 1871, 1872, 1873, 1875, 1876, 1877, 1879, 1880, 1881, 1883, 1884, 1885, 1887, 1888, 1889,
- 1891, 1892, 1893, 1894, 1896, 1897, 1898, 1900, 1901, 1902, 1904, 1905, 1906, 1908, 1909, 1910,
- 1912, 1913, 1914, 1916, 1917, 1918, 1920, 1921, 1922, 1924, 1925, 1926, 1928, 1929, 1930, 1932,
- 1933, 1935, 1936, 1937, 1939, 1940, 1941, 1943, 1944, 1945, 1947, 1948, 1949, 1951, 1952, 1953,
- 1955, 1956, 1957, 1959, 1960, 1961, 1963, 1964, 1965, 1967, 1968, 1970, 1971, 1972, 1974, 1975,
- 1976, 1978, 1979, 1980, 1982, 1983, 1984, 1986, 1987, 1989, 1990, 1991, 1993, 1994, 1995, 1997,
- 1998, 1999, 2001, 2002, 2004, 2005, 2006, 2008, 2009, 2010, 2012, 2013, 2015, 2016, 2017, 2019,
- 2020, 2021, 2023, 2024, 2026, 2027, 2028, 2030, 2031, 2032, 2034, 2035, 2037, 2038, 2039, 2041,
- 2042, 2043, 2045, 2046, 2048, 2049, 2050, 2052, 2053, 2055, 2056, 2057, 2059, 2060, 2061, 2063,
- 2064, 2066, 2067, 2068, 2070, 2071, 2073, 2074, 2075, 2077, 2078, 2080, 2081, 2082, 2084, 2085,
- 2087, 2088, 2089, 2091, 2092, 2094, 2095, 2096, 2098, 2099, 2101, 2102, 2103, 2105, 2106, 2108,
- 2109, 2110, 2112, 2113, 2115, 2116, 2117, 2119, 2120, 2122, 2123, 2124, 2126, 2127, 2129, 2130,
- 2132, 2133, 2134, 2136, 2137, 2139, 2140, 2141, 2143, 2144, 2146, 2147, 2149, 2150, 2151, 2153,
- 2154, 2156, 2157, 2159, 2160, 2161, 2163, 2164, 2166, 2167, 2169, 2170, 2171, 2173, 2174, 2176,
- 2177, 2179, 2180, 2181, 2183, 2184, 2186, 2187, 2189, 2190, 2191, 2193, 2194, 2196, 2197, 2199,
- 2200, 2202, 2203, 2204, 2206, 2207, 2209, 2210, 2212, 2213, 2214, 2216, 2217, 2219, 2220, 2222,
- 2223, 2225, 2226, 2228, 2229, 2230, 2232, 2233, 2235, 2236, 2238, 2239, 2241, 2242, 2243, 2245,
- 2246, 2248, 2249, 2251, 2252, 2254, 2255, 2257, 2258, 2260, 2261, 2262, 2264, 2265, 2267, 2268,
- 2270, 2271, 2273, 2274, 2276, 2277, 2279, 2280, 2282, 2283, 2284, 2286, 2287, 2289, 2290, 2292,
- 2293, 2295, 2296, 2298, 2299, 2301, 2302, 2304, 2305, 2307, 2308, 2310, 2311, 2312, 2314, 2315,
- 2317, 2318, 2320, 2321, 2323, 2324, 2326, 2327, 2329, 2330, 2332, 2333, 2335, 2336, 2338, 2339,
- 2341, 2342, 2344, 2345, 2347, 2348, 2350, 2351, 2353, 2354, 2356, 2357, 2359, 2360, 2362, 2363,
- 2365, 2366, 2368, 2369, 2371, 2372, 2374, 2375, 2377, 2378, 2380, 2381, 2383, 2384, 2386, 2387,
- 2389, 2390, 2392, 2393, 2395, 2396, 2398, 2399, 2401, 2402, 2404, 2405, 2407, 2408, 2410, 2411,
- 2413, 2414, 2416, 2417, 2419, 2420, 2422, 2423, 2425, 2426, 2428, 2429, 2431, 2433, 2434, 2436,
- 2437, 2439, 2440, 2442, 2443, 2445, 2446, 2448, 2449, 2451, 2452, 2454, 2455, 2457, 2458, 2460,
- 2462, 2463, 2465, 2466, 2468, 2469, 2471, 2472, 2474, 2475, 2477, 2478, 2480, 2481, 2483, 2485,
- 2486, 2488, 2489, 2491, 2492, 2494, 2495, 2497, 2498, 2500, 2502, 2503, 2505, 2506, 2508, 2509,
- 2511, 2512, 2514, 2515, 2517, 2519, 2520, 2522, 2523, 2525, 2526, 2528, 2529, 2531, 2533, 2534,
- 2536, 2537, 2539, 2540, 2542, 2543, 2545, 2547, 2548, 2550, 2551, 2553, 2554, 2556, 2557, 2559,
- 2561, 2562, 2564, 2565, 2567, 2568, 2570, 2572, 2573, 2575, 2576, 2578, 2579, 2581, 2583, 2584,
- 2586, 2587, 2589, 2590, 2592, 2594, 2595, 2597, 2598, 2600, 2601, 2603, 2605, 2606, 2608, 2609,
- 2611, 2613, 2614, 2616, 2617, 2619, 2620, 2622, 2624, 2625, 2627, 2628, 2630, 2632, 2633, 2635,
- 2636, 2638, 2640, 2641, 2643, 2644, 2646, 2647, 2649, 2651, 2652, 2654, 2655, 2657, 2659, 2660,
- 2662, 2663, 2665, 2667, 2668, 2670, 2671, 2673, 2675, 2676, 2678, 2679, 2681, 2683, 2684, 2686,
- 2687, 2689, 2691, 2692, 2694, 2696, 2697, 2699, 2700, 2702, 2704, 2705, 2707, 2708, 2710, 2712,
- 2713, 2715, 2716, 2718, 2720, 2721, 2723, 2725, 2726, 2728, 2729, 2731, 2733, 2734, 2736, 2738,
- 2739, 2741, 2742, 2744, 2746, 2747, 2749, 2751, 2752, 2754, 2755, 2757, 2759, 2760, 2762, 2764,
- 2765, 2767, 2769, 2770, 2772, 2773, 2775, 2777, 2778, 2780, 2782, 2783, 2785, 2787, 2788, 2790,
- 2791, 2793, 2795, 2796, 2798, 2800, 2801, 2803, 2805, 2806, 2808, 2810, 2811, 2813, 2814, 2816,
- 2818, 2819, 2821, 2823, 2824, 2826, 2828, 2829, 2831, 2833, 2834, 2836, 2838, 2839, 2841, 2843,
- 2844, 2846, 2848, 2849, 2851, 2853, 2854, 2856, 2857, 2859, 2861, 2862, 2864, 2866, 2867, 2869,
- 2871, 2872, 2874, 2876, 2877, 2879, 2881, 2882, 2884, 2886, 2888, 2889, 2891, 2893, 2894, 2896,
- 2898, 2899, 2901, 2903, 2904, 2906, 2908, 2909, 2911, 2913, 2914, 2916, 2918, 2919, 2921, 2923,
- 2924, 2926, 2928, 2929, 2931, 2933, 2935, 2936, 2938, 2940, 2941, 2943, 2945, 2946, 2948, 2950,
- 2951, 2953, 2955, 2956, 2958, 2960, 2962, 2963, 2965, 2967, 2968, 2970, 2972, 2973, 2975, 2977,
- 2979, 2980, 2982, 2984, 2985, 2987, 2989, 2990, 2992, 2994, 2996, 2997, 2999, 3001, 3002, 3004,
- 3006, 3008, 3009, 3011, 3013, 3014, 3016, 3018, 3020, 3021, 3023, 3025, 3026, 3028, 3030, 3032,
- 3033, 3035, 3037, 3038, 3040, 3042, 3044, 3045, 3047, 3049, 3050, 3052, 3054, 3056, 3057, 3059,
- 3061, 3063, 3064, 3066, 3068, 3069, 3071, 3073, 3075, 3076, 3078, 3080, 3082, 3083, 3085, 3087,
- 3089, 3090, 3092, 3094, 3095, 3097, 3099, 3101, 3102, 3104, 3106, 3108, 3109, 3111, 3113, 3115,
- 3116, 3118, 3120, 3122, 3123, 3125, 3127, 3129, 3130, 3132, 3134, 3136, 3137, 3139, 3141, 3143,
- 3144, 3146, 3148, 3150, 3151, 3153, 3155, 3157, 3158, 3160, 3162, 3164, 3165, 3167, 3169, 3171,
- 3172, 3174, 3176, 3178, 3179, 3181, 3183, 3185, 3187, 3188, 3190, 3192, 3194, 3195, 3197, 3199,
- 3201, 3202, 3204, 3206, 3208, 3209, 3211, 3213, 3215, 3217, 3218, 3220, 3222, 3224, 3225, 3227,
- 3229, 3231, 3233, 3234, 3236, 3238, 3240, 3241, 3243, 3245, 3247, 3249, 3250, 3252, 3254, 3256,
- 3258, 3259, 3261, 3263, 3265, 3266, 3268, 3270, 3272, 3274, 3275, 3277, 3279, 3281, 3283, 3284,
- 3286, 3288, 3290, 3292, 3293, 3295, 3297, 3299, 3301, 3302, 3304, 3306, 3308, 3310, 3311, 3313,
- 3315, 3317, 3319, 3320, 3322, 3324, 3326, 3328, 3329, 3331, 3333, 3335, 3337, 3338, 3340, 3342,
- 3344, 3346, 3348, 3349, 3351, 3353, 3355, 3357, 3358, 3360, 3362, 3364, 3366, 3368, 3369, 3371,
- 3373, 3375, 3377, 3378, 3380, 3382, 3384, 3386, 3388, 3389, 3391, 3393, 3395, 3397, 3399, 3400,
- 3402, 3404, 3406, 3408, 3410, 3411, 3413, 3415, 3417, 3419, 3421, 3422, 3424, 3426, 3428, 3430,
- 3432, 3433, 3435, 3437, 3439, 3441, 3443, 3444, 3446, 3448, 3450, 3452, 3454, 3455, 3457, 3459,
- 3461, 3463, 3465, 3467, 3468, 3470, 3472, 3474, 3476, 3478, 3480, 3481, 3483, 3485, 3487, 3489,
- 3491, 3492, 3494, 3496, 3498, 3500, 3502, 3504, 3506, 3507, 3509, 3511, 3513, 3515, 3517, 3519,
- 3520, 3522, 3524, 3526, 3528, 3530, 3532, 3533, 3535, 3537, 3539, 3541, 3543, 3545, 3547, 3548,
- 3550, 3552, 3554, 3556, 3558, 3560, 3562, 3563, 3565, 3567, 3569, 3571, 3573, 3575, 3577, 3578,
- 3580, 3582, 3584, 3586, 3588, 3590, 3592, 3594, 3595, 3597, 3599, 3601, 3603, 3605, 3607, 3609,
- 3611, 3612, 3614, 3616, 3618, 3620, 3622, 3624, 3626, 3628, 3629, 3631, 3633, 3635, 3637, 3639,
- 3641, 3643, 3645, 3647, 3648, 3650, 3652, 3654, 3656, 3658, 3660, 3662, 3664, 3666, 3667, 3669,
- 3671, 3673, 3675, 3677, 3679, 3681, 3683, 3685, 3687, 3688, 3690, 3692, 3694, 3696, 3698, 3700,
- 3702, 3704, 3706, 3708, 3710, 3711, 3713, 3715, 3717, 3719, 3721, 3723, 3725, 3727, 3729, 3731,
- 3733, 3735, 3736, 3738, 3740, 3742, 3744, 3746, 3748, 3750, 3752, 3754, 3756, 3758, 3760, 3762,
- 3764, 3765, 3767, 3769, 3771, 3773, 3775, 3777, 3779, 3781, 3783, 3785, 3787, 3789, 3791, 3793,
- 3795, 3796, 3798, 3800, 3802, 3804, 3806, 3808, 3810, 3812, 3814, 3816, 3818, 3820, 3822, 3824,
- 3826, 3828, 3830, 3832, 3833, 3835, 3837, 3839, 3841, 3843, 3845, 3847, 3849, 3851, 3853, 3855,
- 3857, 3859, 3861, 3863, 3865, 3867, 3869, 3871, 3873, 3875, 3877, 3879, 3881, 3883, 3884, 3886,
- 3888, 3890, 3892, 3894, 3896, 3898, 3900, 3902, 3904, 3906, 3908, 3910, 3912, 3914, 3916, 3918,
- 3920, 3922, 3924, 3926, 3928, 3930, 3932, 3934, 3936, 3938, 3940, 3942, 3944, 3946, 3948, 3950,
- 3952, 3954, 3956, 3958, 3960, 3962, 3964, 3966, 3968, 3970, 3972, 3974, 3976, 3978, 3980, 3982,
- 3984, 3986, 3988, 3990, 3992, 3994, 3996, 3998, 4000, 4002, 4004, 4006, 4008, 4010, 4012, 4014,
- 4016, 4018, 4020, 4022, 4024, 4026, 4028, 4030, 4032, 4034, 4036, 4038, 4040, 4042, 4044, 4046,
- 4048, 4050, 4052, 4054, 4056, 4058, 4060, 4062, 4064, 4066, 4068, 4070, 4072, 4074, 4076, 4078,
- 4080,
-};
-
-/* Generated table */
-const unsigned short tpg_linear_to_rec709[255 * 16 + 1] = {
- 0, 5, 9, 14, 18, 22, 27, 32, 36, 41, 45, 50, 54, 59, 63, 68,
- 72, 77, 81, 86, 90, 95, 99, 104, 108, 113, 117, 122, 126, 131, 135, 139,
- 144, 149, 153, 158, 162, 167, 171, 176, 180, 185, 189, 194, 198, 203, 207, 212,
- 216, 221, 225, 230, 234, 239, 243, 248, 252, 257, 261, 266, 270, 275, 279, 284,
- 288, 293, 297, 302, 306, 311, 315, 320, 324, 328, 334, 338, 343, 347, 352, 356,
- 360, 365, 369, 373, 377, 381, 386, 390, 394, 398, 402, 406, 410, 414, 418, 422,
- 426, 430, 433, 437, 441, 445, 449, 452, 456, 460, 464, 467, 471, 475, 478, 482,
- 485, 489, 492, 496, 499, 503, 506, 510, 513, 517, 520, 524, 527, 530, 534, 537,
- 540, 544, 547, 550, 554, 557, 560, 563, 566, 570, 573, 576, 579, 582, 586, 589,
- 592, 595, 598, 601, 604, 607, 610, 613, 616, 619, 622, 625, 628, 631, 634, 637,
- 640, 643, 646, 649, 652, 655, 658, 660, 663, 666, 669, 672, 675, 677, 680, 683,
- 686, 689, 691, 694, 697, 700, 702, 705, 708, 711, 713, 716, 719, 721, 724, 727,
- 729, 732, 735, 737, 740, 743, 745, 748, 750, 753, 756, 758, 761, 763, 766, 768,
- 771, 773, 776, 779, 781, 784, 786, 789, 791, 794, 796, 799, 801, 803, 806, 808,
- 811, 813, 816, 818, 821, 823, 825, 828, 830, 833, 835, 837, 840, 842, 844, 847,
- 849, 851, 854, 856, 858, 861, 863, 865, 868, 870, 872, 875, 877, 879, 881, 884,
- 886, 888, 891, 893, 895, 897, 900, 902, 904, 906, 908, 911, 913, 915, 917, 919,
- 922, 924, 926, 928, 930, 933, 935, 937, 939, 941, 943, 946, 948, 950, 952, 954,
- 956, 958, 960, 963, 965, 967, 969, 971, 973, 975, 977, 979, 981, 984, 986, 988,
- 990, 992, 994, 996, 998, 1000, 1002, 1004, 1006, 1008, 1010, 1012, 1014, 1016, 1018, 1020,
- 1022, 1024, 1026, 1028, 1030, 1032, 1034, 1036, 1038, 1040, 1042, 1044, 1046, 1048, 1050, 1052,
- 1054, 1056, 1058, 1060, 1062, 1064, 1066, 1068, 1069, 1071, 1073, 1075, 1077, 1079, 1081, 1083,
- 1085, 1087, 1089, 1090, 1092, 1094, 1096, 1098, 1100, 1102, 1104, 1106, 1107, 1109, 1111, 1113,
- 1115, 1117, 1119, 1120, 1122, 1124, 1126, 1128, 1130, 1131, 1133, 1135, 1137, 1139, 1141, 1142,
- 1144, 1146, 1148, 1150, 1151, 1153, 1155, 1157, 1159, 1160, 1162, 1164, 1166, 1168, 1169, 1171,
- 1173, 1175, 1176, 1178, 1180, 1182, 1184, 1185, 1187, 1189, 1191, 1192, 1194, 1196, 1198, 1199,
- 1201, 1203, 1204, 1206, 1208, 1210, 1211, 1213, 1215, 1217, 1218, 1220, 1222, 1223, 1225, 1227,
- 1228, 1230, 1232, 1234, 1235, 1237, 1239, 1240, 1242, 1244, 1245, 1247, 1249, 1250, 1252, 1254,
- 1255, 1257, 1259, 1260, 1262, 1264, 1265, 1267, 1269, 1270, 1272, 1274, 1275, 1277, 1279, 1280,
- 1282, 1283, 1285, 1287, 1288, 1290, 1292, 1293, 1295, 1296, 1298, 1300, 1301, 1303, 1305, 1306,
- 1308, 1309, 1311, 1313, 1314, 1316, 1317, 1319, 1321, 1322, 1324, 1325, 1327, 1328, 1330, 1332,
- 1333, 1335, 1336, 1338, 1339, 1341, 1343, 1344, 1346, 1347, 1349, 1350, 1352, 1354, 1355, 1357,
- 1358, 1360, 1361, 1363, 1364, 1366, 1367, 1369, 1371, 1372, 1374, 1375, 1377, 1378, 1380, 1381,
- 1383, 1384, 1386, 1387, 1389, 1390, 1392, 1393, 1395, 1396, 1398, 1399, 1401, 1402, 1404, 1405,
- 1407, 1408, 1410, 1411, 1413, 1414, 1416, 1417, 1419, 1420, 1422, 1423, 1425, 1426, 1428, 1429,
- 1431, 1432, 1434, 1435, 1437, 1438, 1440, 1441, 1442, 1444, 1445, 1447, 1448, 1450, 1451, 1453,
- 1454, 1456, 1457, 1458, 1460, 1461, 1463, 1464, 1466, 1467, 1469, 1470, 1471, 1473, 1474, 1476,
- 1477, 1479, 1480, 1481, 1483, 1484, 1486, 1487, 1489, 1490, 1491, 1493, 1494, 1496, 1497, 1498,
- 1500, 1501, 1503, 1504, 1505, 1507, 1508, 1510, 1511, 1512, 1514, 1515, 1517, 1518, 1519, 1521,
- 1522, 1524, 1525, 1526, 1528, 1529, 1531, 1532, 1533, 1535, 1536, 1537, 1539, 1540, 1542, 1543,
- 1544, 1546, 1547, 1548, 1550, 1551, 1553, 1554, 1555, 1557, 1558, 1559, 1561, 1562, 1563, 1565,
- 1566, 1567, 1569, 1570, 1571, 1573, 1574, 1576, 1577, 1578, 1580, 1581, 1582, 1584, 1585, 1586,
- 1588, 1589, 1590, 1592, 1593, 1594, 1596, 1597, 1598, 1600, 1601, 1602, 1603, 1605, 1606, 1607,
- 1609, 1610, 1611, 1613, 1614, 1615, 1617, 1618, 1619, 1621, 1622, 1623, 1624, 1626, 1627, 1628,
- 1630, 1631, 1632, 1634, 1635, 1636, 1637, 1639, 1640, 1641, 1643, 1644, 1645, 1647, 1648, 1649,
- 1650, 1652, 1653, 1654, 1655, 1657, 1658, 1659, 1661, 1662, 1663, 1664, 1666, 1667, 1668, 1670,
- 1671, 1672, 1673, 1675, 1676, 1677, 1678, 1680, 1681, 1682, 1683, 1685, 1686, 1687, 1688, 1690,
- 1691, 1692, 1693, 1695, 1696, 1697, 1698, 1700, 1701, 1702, 1703, 1705, 1706, 1707, 1708, 1710,
- 1711, 1712, 1713, 1715, 1716, 1717, 1718, 1720, 1721, 1722, 1723, 1724, 1726, 1727, 1728, 1729,
- 1731, 1732, 1733, 1734, 1736, 1737, 1738, 1739, 1740, 1742, 1743, 1744, 1745, 1746, 1748, 1749,
- 1750, 1751, 1753, 1754, 1755, 1756, 1757, 1759, 1760, 1761, 1762, 1763, 1765, 1766, 1767, 1768,
- 1769, 1771, 1772, 1773, 1774, 1775, 1777, 1778, 1779, 1780, 1781, 1783, 1784, 1785, 1786, 1787,
- 1788, 1790, 1791, 1792, 1793, 1794, 1796, 1797, 1798, 1799, 1800, 1801, 1803, 1804, 1805, 1806,
- 1807, 1809, 1810, 1811, 1812, 1813, 1814, 1816, 1817, 1818, 1819, 1820, 1821, 1823, 1824, 1825,
- 1826, 1827, 1828, 1829, 1831, 1832, 1833, 1834, 1835, 1836, 1838, 1839, 1840, 1841, 1842, 1843,
- 1845, 1846, 1847, 1848, 1849, 1850, 1851, 1853, 1854, 1855, 1856, 1857, 1858, 1859, 1861, 1862,
- 1863, 1864, 1865, 1866, 1867, 1868, 1870, 1871, 1872, 1873, 1874, 1875, 1876, 1878, 1879, 1880,
- 1881, 1882, 1883, 1884, 1885, 1887, 1888, 1889, 1890, 1891, 1892, 1893, 1894, 1896, 1897, 1898,
- 1899, 1900, 1901, 1902, 1903, 1904, 1906, 1907, 1908, 1909, 1910, 1911, 1912, 1913, 1914, 1916,
- 1917, 1918, 1919, 1920, 1921, 1922, 1923, 1924, 1925, 1927, 1928, 1929, 1930, 1931, 1932, 1933,
- 1934, 1935, 1936, 1938, 1939, 1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1950, 1951,
- 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959, 1960, 1961, 1963, 1964, 1965, 1966, 1967, 1968,
- 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985,
- 1986, 1987, 1988, 1989, 1990, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007, 2008, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
- 2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029, 2031, 2032, 2033, 2034, 2035, 2036,
- 2037, 2038, 2039, 2040, 2041, 2042, 2043, 2044, 2045, 2046, 2047, 2048, 2049, 2050, 2051, 2052,
- 2053, 2054, 2055, 2056, 2057, 2058, 2060, 2061, 2062, 2063, 2064, 2065, 2066, 2067, 2068, 2069,
- 2070, 2071, 2072, 2073, 2074, 2075, 2076, 2077, 2078, 2079, 2080, 2081, 2082, 2083, 2084, 2085,
- 2086, 2087, 2088, 2089, 2090, 2091, 2092, 2093, 2094, 2095, 2096, 2097, 2098, 2099, 2100, 2101,
- 2102, 2103, 2104, 2105, 2106, 2107, 2108, 2109, 2110, 2111, 2112, 2113, 2114, 2115, 2116, 2117,
- 2118, 2119, 2120, 2121, 2122, 2123, 2124, 2125, 2126, 2127, 2128, 2129, 2130, 2131, 2132, 2133,
- 2134, 2135, 2136, 2137, 2138, 2139, 2140, 2141, 2142, 2143, 2144, 2145, 2146, 2147, 2148, 2149,
- 2150, 2151, 2152, 2153, 2154, 2155, 2156, 2157, 2158, 2159, 2160, 2161, 2162, 2163, 2164, 2165,
- 2166, 2167, 2168, 2169, 2170, 2171, 2172, 2173, 2173, 2174, 2175, 2176, 2177, 2178, 2179, 2180,
- 2181, 2182, 2183, 2184, 2185, 2186, 2187, 2188, 2189, 2190, 2191, 2192, 2193, 2194, 2195, 2196,
- 2197, 2198, 2199, 2200, 2201, 2202, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211,
- 2212, 2213, 2214, 2215, 2216, 2217, 2218, 2219, 2220, 2221, 2222, 2223, 2224, 2224, 2225, 2226,
- 2227, 2228, 2229, 2230, 2231, 2232, 2233, 2234, 2235, 2236, 2237, 2238, 2239, 2240, 2241, 2241,
- 2242, 2243, 2244, 2245, 2246, 2247, 2248, 2249, 2250, 2251, 2252, 2253, 2254, 2255, 2256, 2257,
- 2257, 2258, 2259, 2260, 2261, 2262, 2263, 2264, 2265, 2266, 2267, 2268, 2269, 2270, 2271, 2271,
- 2272, 2273, 2274, 2275, 2276, 2277, 2278, 2279, 2280, 2281, 2282, 2283, 2283, 2284, 2285, 2286,
- 2287, 2288, 2289, 2290, 2291, 2292, 2293, 2294, 2295, 2295, 2296, 2297, 2298, 2299, 2300, 2301,
- 2302, 2303, 2304, 2305, 2306, 2306, 2307, 2308, 2309, 2310, 2311, 2312, 2313, 2314, 2315, 2316,
- 2317, 2317, 2318, 2319, 2320, 2321, 2322, 2323, 2324, 2325, 2326, 2327, 2327, 2328, 2329, 2330,
- 2331, 2332, 2333, 2334, 2335, 2336, 2336, 2337, 2338, 2339, 2340, 2341, 2342, 2343, 2344, 2345,
- 2345, 2346, 2347, 2348, 2349, 2350, 2351, 2352, 2353, 2354, 2354, 2355, 2356, 2357, 2358, 2359,
- 2360, 2361, 2362, 2363, 2363, 2364, 2365, 2366, 2367, 2368, 2369, 2370, 2371, 2371, 2372, 2373,
- 2374, 2375, 2376, 2377, 2378, 2379, 2379, 2380, 2381, 2382, 2383, 2384, 2385, 2386, 2386, 2387,
- 2388, 2389, 2390, 2391, 2392, 2393, 2394, 2394, 2395, 2396, 2397, 2398, 2399, 2400, 2401, 2401,
- 2402, 2403, 2404, 2405, 2406, 2407, 2408, 2408, 2409, 2410, 2411, 2412, 2413, 2414, 2415, 2415,
- 2416, 2417, 2418, 2419, 2420, 2421, 2422, 2422, 2423, 2424, 2425, 2426, 2427, 2428, 2428, 2429,
- 2430, 2431, 2432, 2433, 2434, 2435, 2435, 2436, 2437, 2438, 2439, 2440, 2441, 2441, 2442, 2443,
- 2444, 2445, 2446, 2447, 2447, 2448, 2449, 2450, 2451, 2452, 2453, 2453, 2454, 2455, 2456, 2457,
- 2458, 2459, 2459, 2460, 2461, 2462, 2463, 2464, 2465, 2465, 2466, 2467, 2468, 2469, 2470, 2471,
- 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2477, 2478, 2479, 2480, 2481, 2482, 2482, 2483, 2484,
- 2485, 2486, 2487, 2488, 2488, 2489, 2490, 2491, 2492, 2493, 2493, 2494, 2495, 2496, 2497, 2498,
- 2499, 2499, 2500, 2501, 2502, 2503, 2504, 2504, 2505, 2506, 2507, 2508, 2509, 2509, 2510, 2511,
- 2512, 2513, 2514, 2514, 2515, 2516, 2517, 2518, 2519, 2519, 2520, 2521, 2522, 2523, 2524, 2524,
- 2525, 2526, 2527, 2528, 2529, 2529, 2530, 2531, 2532, 2533, 2534, 2534, 2535, 2536, 2537, 2538,
- 2539, 2539, 2540, 2541, 2542, 2543, 2544, 2544, 2545, 2546, 2547, 2548, 2548, 2549, 2550, 2551,
- 2552, 2553, 2553, 2554, 2555, 2556, 2557, 2558, 2558, 2559, 2560, 2561, 2562, 2562, 2563, 2564,
- 2565, 2566, 2567, 2567, 2568, 2569, 2570, 2571, 2571, 2572, 2573, 2574, 2575, 2576, 2576, 2577,
- 2578, 2579, 2580, 2580, 2581, 2582, 2583, 2584, 2584, 2585, 2586, 2587, 2588, 2589, 2589, 2590,
- 2591, 2592, 2593, 2593, 2594, 2595, 2596, 2597, 2597, 2598, 2599, 2600, 2601, 2601, 2602, 2603,
- 2604, 2605, 2605, 2606, 2607, 2608, 2609, 2610, 2610, 2611, 2612, 2613, 2614, 2614, 2615, 2616,
- 2617, 2618, 2618, 2619, 2620, 2621, 2622, 2622, 2623, 2624, 2625, 2626, 2626, 2627, 2628, 2629,
- 2630, 2630, 2631, 2632, 2633, 2634, 2634, 2635, 2636, 2637, 2637, 2638, 2639, 2640, 2641, 2641,
- 2642, 2643, 2644, 2645, 2645, 2646, 2647, 2648, 2649, 2649, 2650, 2651, 2652, 2653, 2653, 2654,
- 2655, 2656, 2656, 2657, 2658, 2659, 2660, 2660, 2661, 2662, 2663, 2664, 2664, 2665, 2666, 2667,
- 2668, 2668, 2669, 2670, 2671, 2671, 2672, 2673, 2674, 2675, 2675, 2676, 2677, 2678, 2678, 2679,
- 2680, 2681, 2682, 2682, 2683, 2684, 2685, 2686, 2686, 2687, 2688, 2689, 2689, 2690, 2691, 2692,
- 2693, 2693, 2694, 2695, 2696, 2696, 2697, 2698, 2699, 2700, 2700, 2701, 2702, 2703, 2703, 2704,
- 2705, 2706, 2706, 2707, 2708, 2709, 2710, 2710, 2711, 2712, 2713, 2713, 2714, 2715, 2716, 2717,
- 2717, 2718, 2719, 2720, 2720, 2721, 2722, 2723, 2723, 2724, 2725, 2726, 2727, 2727, 2728, 2729,
- 2730, 2730, 2731, 2732, 2733, 2733, 2734, 2735, 2736, 2736, 2737, 2738, 2739, 2740, 2740, 2741,
- 2742, 2743, 2743, 2744, 2745, 2746, 2746, 2747, 2748, 2749, 2749, 2750, 2751, 2752, 2752, 2753,
- 2754, 2755, 2755, 2756, 2757, 2758, 2759, 2759, 2760, 2761, 2762, 2762, 2763, 2764, 2765, 2765,
- 2766, 2767, 2768, 2768, 2769, 2770, 2771, 2771, 2772, 2773, 2774, 2774, 2775, 2776, 2777, 2777,
- 2778, 2779, 2780, 2780, 2781, 2782, 2783, 2783, 2784, 2785, 2786, 2786, 2787, 2788, 2789, 2789,
- 2790, 2791, 2792, 2792, 2793, 2794, 2795, 2795, 2796, 2797, 2798, 2798, 2799, 2800, 2801, 2801,
- 2802, 2803, 2804, 2804, 2805, 2806, 2807, 2807, 2808, 2809, 2810, 2810, 2811, 2812, 2813, 2813,
- 2814, 2815, 2815, 2816, 2817, 2818, 2818, 2819, 2820, 2821, 2821, 2822, 2823, 2824, 2824, 2825,
- 2826, 2827, 2827, 2828, 2829, 2830, 2830, 2831, 2832, 2832, 2833, 2834, 2835, 2835, 2836, 2837,
- 2838, 2838, 2839, 2840, 2841, 2841, 2842, 2843, 2844, 2844, 2845, 2846, 2846, 2847, 2848, 2849,
- 2849, 2850, 2851, 2852, 2852, 2853, 2854, 2855, 2855, 2856, 2857, 2857, 2858, 2859, 2860, 2860,
- 2861, 2862, 2863, 2863, 2864, 2865, 2865, 2866, 2867, 2868, 2868, 2869, 2870, 2871, 2871, 2872,
- 2873, 2873, 2874, 2875, 2876, 2876, 2877, 2878, 2879, 2879, 2880, 2881, 2881, 2882, 2883, 2884,
- 2884, 2885, 2886, 2886, 2887, 2888, 2889, 2889, 2890, 2891, 2892, 2892, 2893, 2894, 2894, 2895,
- 2896, 2897, 2897, 2898, 2899, 2899, 2900, 2901, 2902, 2902, 2903, 2904, 2904, 2905, 2906, 2907,
- 2907, 2908, 2909, 2909, 2910, 2911, 2912, 2912, 2913, 2914, 2914, 2915, 2916, 2917, 2917, 2918,
- 2919, 2919, 2920, 2921, 2922, 2922, 2923, 2924, 2924, 2925, 2926, 2927, 2927, 2928, 2929, 2929,
- 2930, 2931, 2932, 2932, 2933, 2934, 2934, 2935, 2936, 2937, 2937, 2938, 2939, 2939, 2940, 2941,
- 2941, 2942, 2943, 2944, 2944, 2945, 2946, 2946, 2947, 2948, 2949, 2949, 2950, 2951, 2951, 2952,
- 2953, 2953, 2954, 2955, 2956, 2956, 2957, 2958, 2958, 2959, 2960, 2961, 2961, 2962, 2963, 2963,
- 2964, 2965, 2965, 2966, 2967, 2968, 2968, 2969, 2970, 2970, 2971, 2972, 2972, 2973, 2974, 2975,
- 2975, 2976, 2977, 2977, 2978, 2979, 2979, 2980, 2981, 2982, 2982, 2983, 2984, 2984, 2985, 2986,
- 2986, 2987, 2988, 2988, 2989, 2990, 2991, 2991, 2992, 2993, 2993, 2994, 2995, 2995, 2996, 2997,
- 2998, 2998, 2999, 3000, 3000, 3001, 3002, 3002, 3003, 3004, 3004, 3005, 3006, 3006, 3007, 3008,
- 3009, 3009, 3010, 3011, 3011, 3012, 3013, 3013, 3014, 3015, 3015, 3016, 3017, 3018, 3018, 3019,
- 3020, 3020, 3021, 3022, 3022, 3023, 3024, 3024, 3025, 3026, 3026, 3027, 3028, 3029, 3029, 3030,
- 3031, 3031, 3032, 3033, 3033, 3034, 3035, 3035, 3036, 3037, 3037, 3038, 3039, 3039, 3040, 3041,
- 3042, 3042, 3043, 3044, 3044, 3045, 3046, 3046, 3047, 3048, 3048, 3049, 3050, 3050, 3051, 3052,
- 3052, 3053, 3054, 3054, 3055, 3056, 3056, 3057, 3058, 3059, 3059, 3060, 3061, 3061, 3062, 3063,
- 3063, 3064, 3065, 3065, 3066, 3067, 3067, 3068, 3069, 3069, 3070, 3071, 3071, 3072, 3073, 3073,
- 3074, 3075, 3075, 3076, 3077, 3077, 3078, 3079, 3079, 3080, 3081, 3081, 3082, 3083, 3084, 3084,
- 3085, 3086, 3086, 3087, 3088, 3088, 3089, 3090, 3090, 3091, 3092, 3092, 3093, 3094, 3094, 3095,
- 3096, 3096, 3097, 3098, 3098, 3099, 3100, 3100, 3101, 3102, 3102, 3103, 3104, 3104, 3105, 3106,
- 3106, 3107, 3108, 3108, 3109, 3110, 3110, 3111, 3112, 3112, 3113, 3114, 3114, 3115, 3116, 3116,
- 3117, 3118, 3118, 3119, 3120, 3120, 3121, 3122, 3122, 3123, 3124, 3124, 3125, 3126, 3126, 3127,
- 3128, 3128, 3129, 3130, 3130, 3131, 3132, 3132, 3133, 3134, 3134, 3135, 3135, 3136, 3137, 3137,
- 3138, 3139, 3139, 3140, 3141, 3141, 3142, 3143, 3143, 3144, 3145, 3145, 3146, 3147, 3147, 3148,
- 3149, 3149, 3150, 3151, 3151, 3152, 3153, 3153, 3154, 3155, 3155, 3156, 3157, 3157, 3158, 3159,
- 3159, 3160, 3160, 3161, 3162, 3162, 3163, 3164, 3164, 3165, 3166, 3166, 3167, 3168, 3168, 3169,
- 3170, 3170, 3171, 3172, 3172, 3173, 3174, 3174, 3175, 3175, 3176, 3177, 3177, 3178, 3179, 3179,
- 3180, 3181, 3181, 3182, 3183, 3183, 3184, 3185, 3185, 3186, 3187, 3187, 3188, 3188, 3189, 3190,
- 3190, 3191, 3192, 3192, 3193, 3194, 3194, 3195, 3196, 3196, 3197, 3198, 3198, 3199, 3199, 3200,
- 3201, 3201, 3202, 3203, 3203, 3204, 3205, 3205, 3206, 3207, 3207, 3208, 3209, 3209, 3210, 3210,
- 3211, 3212, 3212, 3213, 3214, 3214, 3215, 3216, 3216, 3217, 3218, 3218, 3219, 3219, 3220, 3221,
- 3221, 3222, 3223, 3223, 3224, 3225, 3225, 3226, 3227, 3227, 3228, 3228, 3229, 3230, 3230, 3231,
- 3232, 3232, 3233, 3234, 3234, 3235, 3235, 3236, 3237, 3237, 3238, 3239, 3239, 3240, 3241, 3241,
- 3242, 3242, 3243, 3244, 3244, 3245, 3246, 3246, 3247, 3248, 3248, 3249, 3249, 3250, 3251, 3251,
- 3252, 3253, 3253, 3254, 3255, 3255, 3256, 3256, 3257, 3258, 3258, 3259, 3260, 3260, 3261, 3262,
- 3262, 3263, 3263, 3264, 3265, 3265, 3266, 3267, 3267, 3268, 3268, 3269, 3270, 3270, 3271, 3272,
- 3272, 3273, 3274, 3274, 3275, 3275, 3276, 3277, 3277, 3278, 3279, 3279, 3280, 3280, 3281, 3282,
- 3282, 3283, 3284, 3284, 3285, 3285, 3286, 3287, 3287, 3288, 3289, 3289, 3290, 3290, 3291, 3292,
- 3292, 3293, 3294, 3294, 3295, 3295, 3296, 3297, 3297, 3298, 3299, 3299, 3300, 3300, 3301, 3302,
- 3302, 3303, 3304, 3304, 3305, 3305, 3306, 3307, 3307, 3308, 3309, 3309, 3310, 3310, 3311, 3312,
- 3312, 3313, 3314, 3314, 3315, 3315, 3316, 3317, 3317, 3318, 3319, 3319, 3320, 3320, 3321, 3322,
- 3322, 3323, 3323, 3324, 3325, 3325, 3326, 3327, 3327, 3328, 3328, 3329, 3330, 3330, 3331, 3332,
- 3332, 3333, 3333, 3334, 3335, 3335, 3336, 3336, 3337, 3338, 3338, 3339, 3340, 3340, 3341, 3341,
- 3342, 3343, 3343, 3344, 3345, 3345, 3346, 3346, 3347, 3348, 3348, 3349, 3349, 3350, 3351, 3351,
- 3352, 3352, 3353, 3354, 3354, 3355, 3356, 3356, 3357, 3357, 3358, 3359, 3359, 3360, 3360, 3361,
- 3362, 3362, 3363, 3364, 3364, 3365, 3365, 3366, 3367, 3367, 3368, 3368, 3369, 3370, 3370, 3371,
- 3371, 3372, 3373, 3373, 3374, 3375, 3375, 3376, 3376, 3377, 3378, 3378, 3379, 3379, 3380, 3381,
- 3381, 3382, 3382, 3383, 3384, 3384, 3385, 3385, 3386, 3387, 3387, 3388, 3389, 3389, 3390, 3390,
- 3391, 3392, 3392, 3393, 3393, 3394, 3395, 3395, 3396, 3396, 3397, 3398, 3398, 3399, 3399, 3400,
- 3401, 3401, 3402, 3402, 3403, 3404, 3404, 3405, 3405, 3406, 3407, 3407, 3408, 3408, 3409, 3410,
- 3410, 3411, 3411, 3412, 3413, 3413, 3414, 3414, 3415, 3416, 3416, 3417, 3418, 3418, 3419, 3419,
- 3420, 3421, 3421, 3422, 3422, 3423, 3424, 3424, 3425, 3425, 3426, 3427, 3427, 3428, 3428, 3429,
- 3430, 3430, 3431, 3431, 3432, 3433, 3433, 3434, 3434, 3435, 3435, 3436, 3437, 3437, 3438, 3438,
- 3439, 3440, 3440, 3441, 3441, 3442, 3443, 3443, 3444, 3444, 3445, 3446, 3446, 3447, 3447, 3448,
- 3449, 3449, 3450, 3450, 3451, 3452, 3452, 3453, 3453, 3454, 3455, 3455, 3456, 3456, 3457, 3458,
- 3458, 3459, 3459, 3460, 3461, 3461, 3462, 3462, 3463, 3463, 3464, 3465, 3465, 3466, 3466, 3467,
- 3468, 3468, 3469, 3469, 3470, 3471, 3471, 3472, 3472, 3473, 3474, 3474, 3475, 3475, 3476, 3476,
- 3477, 3478, 3478, 3479, 3479, 3480, 3481, 3481, 3482, 3482, 3483, 3484, 3484, 3485, 3485, 3486,
- 3486, 3487, 3488, 3488, 3489, 3489, 3490, 3491, 3491, 3492, 3492, 3493, 3494, 3494, 3495, 3495,
- 3496, 3496, 3497, 3498, 3498, 3499, 3499, 3500, 3501, 3501, 3502, 3502, 3503, 3504, 3504, 3505,
- 3505, 3506, 3506, 3507, 3508, 3508, 3509, 3509, 3510, 3511, 3511, 3512, 3512, 3513, 3513, 3514,
- 3515, 3515, 3516, 3516, 3517, 3518, 3518, 3519, 3519, 3520, 3520, 3521, 3522, 3522, 3523, 3523,
- 3524, 3525, 3525, 3526, 3526, 3527, 3527, 3528, 3529, 3529, 3530, 3530, 3531, 3531, 3532, 3533,
- 3533, 3534, 3534, 3535, 3536, 3536, 3537, 3537, 3538, 3538, 3539, 3540, 3540, 3541, 3541, 3542,
- 3542, 3543, 3544, 3544, 3545, 3545, 3546, 3547, 3547, 3548, 3548, 3549, 3549, 3550, 3551, 3551,
- 3552, 3552, 3553, 3553, 3554, 3555, 3555, 3556, 3556, 3557, 3557, 3558, 3559, 3559, 3560, 3560,
- 3561, 3561, 3562, 3563, 3563, 3564, 3564, 3565, 3566, 3566, 3567, 3567, 3568, 3568, 3569, 3570,
- 3570, 3571, 3571, 3572, 3572, 3573, 3574, 3574, 3575, 3575, 3576, 3576, 3577, 3578, 3578, 3579,
- 3579, 3580, 3580, 3581, 3582, 3582, 3583, 3583, 3584, 3584, 3585, 3586, 3586, 3587, 3587, 3588,
- 3588, 3589, 3590, 3590, 3591, 3591, 3592, 3592, 3593, 3594, 3594, 3595, 3595, 3596, 3596, 3597,
- 3597, 3598, 3599, 3599, 3600, 3600, 3601, 3601, 3602, 3603, 3603, 3604, 3604, 3605, 3605, 3606,
- 3607, 3607, 3608, 3608, 3609, 3609, 3610, 3611, 3611, 3612, 3612, 3613, 3613, 3614, 3615, 3615,
- 3616, 3616, 3617, 3617, 3618, 3618, 3619, 3620, 3620, 3621, 3621, 3622, 3622, 3623, 3624, 3624,
- 3625, 3625, 3626, 3626, 3627, 3627, 3628, 3629, 3629, 3630, 3630, 3631, 3631, 3632, 3633, 3633,
- 3634, 3634, 3635, 3635, 3636, 3636, 3637, 3638, 3638, 3639, 3639, 3640, 3640, 3641, 3642, 3642,
- 3643, 3643, 3644, 3644, 3645, 3645, 3646, 3647, 3647, 3648, 3648, 3649, 3649, 3650, 3650, 3651,
- 3652, 3652, 3653, 3653, 3654, 3654, 3655, 3656, 3656, 3657, 3657, 3658, 3658, 3659, 3659, 3660,
- 3661, 3661, 3662, 3662, 3663, 3663, 3664, 3664, 3665, 3666, 3666, 3667, 3667, 3668, 3668, 3669,
- 3669, 3670, 3671, 3671, 3672, 3672, 3673, 3673, 3674, 3674, 3675, 3676, 3676, 3677, 3677, 3678,
- 3678, 3679, 3679, 3680, 3681, 3681, 3682, 3682, 3683, 3683, 3684, 3684, 3685, 3686, 3686, 3687,
- 3687, 3688, 3688, 3689, 3689, 3690, 3691, 3691, 3692, 3692, 3693, 3693, 3694, 3694, 3695, 3695,
- 3696, 3697, 3697, 3698, 3698, 3699, 3699, 3700, 3700, 3701, 3702, 3702, 3703, 3703, 3704, 3704,
- 3705, 3705, 3706, 3707, 3707, 3708, 3708, 3709, 3709, 3710, 3710, 3711, 3711, 3712, 3713, 3713,
- 3714, 3714, 3715, 3715, 3716, 3716, 3717, 3717, 3718, 3719, 3719, 3720, 3720, 3721, 3721, 3722,
- 3722, 3723, 3724, 3724, 3725, 3725, 3726, 3726, 3727, 3727, 3728, 3728, 3729, 3730, 3730, 3731,
- 3731, 3732, 3732, 3733, 3733, 3734, 3734, 3735, 3736, 3736, 3737, 3737, 3738, 3738, 3739, 3739,
- 3740, 3740, 3741, 3742, 3742, 3743, 3743, 3744, 3744, 3745, 3745, 3746, 3746, 3747, 3748, 3748,
- 3749, 3749, 3750, 3750, 3751, 3751, 3752, 3752, 3753, 3753, 3754, 3755, 3755, 3756, 3756, 3757,
- 3757, 3758, 3758, 3759, 3759, 3760, 3761, 3761, 3762, 3762, 3763, 3763, 3764, 3764, 3765, 3765,
- 3766, 3766, 3767, 3768, 3768, 3769, 3769, 3770, 3770, 3771, 3771, 3772, 3772, 3773, 3773, 3774,
- 3775, 3775, 3776, 3776, 3777, 3777, 3778, 3778, 3779, 3779, 3780, 3781, 3781, 3782, 3782, 3783,
- 3783, 3784, 3784, 3785, 3785, 3786, 3786, 3787, 3787, 3788, 3789, 3789, 3790, 3790, 3791, 3791,
- 3792, 3792, 3793, 3793, 3794, 3794, 3795, 3796, 3796, 3797, 3797, 3798, 3798, 3799, 3799, 3800,
- 3800, 3801, 3801, 3802, 3802, 3803, 3804, 3804, 3805, 3805, 3806, 3806, 3807, 3807, 3808, 3808,
- 3809, 3809, 3810, 3811, 3811, 3812, 3812, 3813, 3813, 3814, 3814, 3815, 3815, 3816, 3816, 3817,
- 3817, 3818, 3819, 3819, 3820, 3820, 3821, 3821, 3822, 3822, 3823, 3823, 3824, 3824, 3825, 3825,
- 3826, 3826, 3827, 3828, 3828, 3829, 3829, 3830, 3830, 3831, 3831, 3832, 3832, 3833, 3833, 3834,
- 3834, 3835, 3835, 3836, 3837, 3837, 3838, 3838, 3839, 3839, 3840, 3840, 3841, 3841, 3842, 3842,
- 3843, 3843, 3844, 3844, 3845, 3846, 3846, 3847, 3847, 3848, 3848, 3849, 3849, 3850, 3850, 3851,
- 3851, 3852, 3852, 3853, 3853, 3854, 3855, 3855, 3856, 3856, 3857, 3857, 3858, 3858, 3859, 3859,
- 3860, 3860, 3861, 3861, 3862, 3862, 3863, 3863, 3864, 3864, 3865, 3866, 3866, 3867, 3867, 3868,
- 3868, 3869, 3869, 3870, 3870, 3871, 3871, 3872, 3872, 3873, 3873, 3874, 3874, 3875, 3876, 3876,
- 3877, 3877, 3878, 3878, 3879, 3879, 3880, 3880, 3881, 3881, 3882, 3882, 3883, 3883, 3884, 3884,
- 3885, 3885, 3886, 3886, 3887, 3888, 3888, 3889, 3889, 3890, 3890, 3891, 3891, 3892, 3892, 3893,
- 3893, 3894, 3894, 3895, 3895, 3896, 3896, 3897, 3897, 3898, 3898, 3899, 3900, 3900, 3901, 3901,
- 3902, 3902, 3903, 3903, 3904, 3904, 3905, 3905, 3906, 3906, 3907, 3907, 3908, 3908, 3909, 3909,
- 3910, 3910, 3911, 3911, 3912, 3912, 3913, 3914, 3914, 3915, 3915, 3916, 3916, 3917, 3917, 3918,
- 3918, 3919, 3919, 3920, 3920, 3921, 3921, 3922, 3922, 3923, 3923, 3924, 3924, 3925, 3925, 3926,
- 3926, 3927, 3927, 3928, 3929, 3929, 3930, 3930, 3931, 3931, 3932, 3932, 3933, 3933, 3934, 3934,
- 3935, 3935, 3936, 3936, 3937, 3937, 3938, 3938, 3939, 3939, 3940, 3940, 3941, 3941, 3942, 3942,
- 3943, 3943, 3944, 3944, 3945, 3945, 3946, 3947, 3947, 3948, 3948, 3949, 3949, 3950, 3950, 3951,
- 3951, 3952, 3952, 3953, 3953, 3954, 3954, 3955, 3955, 3956, 3956, 3957, 3957, 3958, 3958, 3959,
- 3959, 3960, 3960, 3961, 3961, 3962, 3962, 3963, 3963, 3964, 3964, 3965, 3965, 3966, 3966, 3967,
- 3967, 3968, 3969, 3969, 3970, 3970, 3971, 3971, 3972, 3972, 3973, 3973, 3974, 3974, 3975, 3975,
- 3976, 3976, 3977, 3977, 3978, 3978, 3979, 3979, 3980, 3980, 3981, 3981, 3982, 3982, 3983, 3983,
- 3984, 3984, 3985, 3985, 3986, 3986, 3987, 3987, 3988, 3988, 3989, 3989, 3990, 3990, 3991, 3991,
- 3992, 3992, 3993, 3993, 3994, 3994, 3995, 3995, 3996, 3996, 3997, 3997, 3998, 3998, 3999, 3999,
- 4000, 4001, 4001, 4002, 4002, 4003, 4003, 4004, 4004, 4005, 4005, 4006, 4006, 4007, 4007, 4008,
- 4008, 4009, 4009, 4010, 4010, 4011, 4011, 4012, 4012, 4013, 4013, 4014, 4014, 4015, 4015, 4016,
- 4016, 4017, 4017, 4018, 4018, 4019, 4019, 4020, 4020, 4021, 4021, 4022, 4022, 4023, 4023, 4024,
- 4024, 4025, 4025, 4026, 4026, 4027, 4027, 4028, 4028, 4029, 4029, 4030, 4030, 4031, 4031, 4032,
- 4032, 4033, 4033, 4034, 4034, 4035, 4035, 4036, 4036, 4037, 4037, 4038, 4038, 4039, 4039, 4040,
- 4040, 4041, 4041, 4042, 4042, 4043, 4043, 4044, 4044, 4045, 4045, 4046, 4046, 4047, 4047, 4048,
- 4048, 4049, 4049, 4050, 4050, 4051, 4051, 4052, 4052, 4053, 4053, 4054, 4054, 4055, 4055, 4056,
- 4056, 4057, 4057, 4058, 4058, 4059, 4059, 4060, 4060, 4061, 4061, 4062, 4062, 4063, 4063, 4064,
- 4064, 4065, 4065, 4066, 4066, 4067, 4067, 4068, 4068, 4069, 4069, 4070, 4070, 4071, 4071, 4072,
- 4072, 4073, 4073, 4074, 4074, 4075, 4075, 4076, 4076, 4077, 4077, 4078, 4078, 4079, 4079, 4080,
- 4080,
-};
-
-/* Generated table */
-const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][TPG_COLOR_CSC_BLACK + 1] = {
- [V4L2_COLORSPACE_SMPTE170M][0] = { 2939, 2939, 2939 },
- [V4L2_COLORSPACE_SMPTE170M][1] = { 2953, 2963, 586 },
- [V4L2_COLORSPACE_SMPTE170M][2] = { 0, 2967, 2937 },
- [V4L2_COLORSPACE_SMPTE170M][3] = { 88, 2990, 575 },
- [V4L2_COLORSPACE_SMPTE170M][4] = { 3016, 259, 2933 },
- [V4L2_COLORSPACE_SMPTE170M][5] = { 3030, 405, 558 },
- [V4L2_COLORSPACE_SMPTE170M][6] = { 478, 428, 2931 },
- [V4L2_COLORSPACE_SMPTE170M][7] = { 547, 547, 547 },
+const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = {
+ [V4L2_COLORSPACE_SMPTE170M][0] = { 2953, 2939, 2939 },
+ [V4L2_COLORSPACE_SMPTE170M][1] = { 2954, 2963, 585 },
+ [V4L2_COLORSPACE_SMPTE170M][2] = { 84, 2967, 2937 },
+ [V4L2_COLORSPACE_SMPTE170M][3] = { 93, 2990, 575 },
+ [V4L2_COLORSPACE_SMPTE170M][4] = { 3030, 259, 2933 },
+ [V4L2_COLORSPACE_SMPTE170M][5] = { 3031, 406, 557 },
+ [V4L2_COLORSPACE_SMPTE170M][6] = { 544, 428, 2931 },
+ [V4L2_COLORSPACE_SMPTE170M][7] = { 551, 547, 547 },
[V4L2_COLORSPACE_SMPTE240M][0] = { 2926, 2926, 2926 },
- [V4L2_COLORSPACE_SMPTE240M][1] = { 2941, 2950, 546 },
- [V4L2_COLORSPACE_SMPTE240M][2] = { 0, 2954, 2924 },
- [V4L2_COLORSPACE_SMPTE240M][3] = { 78, 2978, 536 },
- [V4L2_COLORSPACE_SMPTE240M][4] = { 3004, 230, 2920 },
- [V4L2_COLORSPACE_SMPTE240M][5] = { 3018, 363, 518 },
- [V4L2_COLORSPACE_SMPTE240M][6] = { 437, 387, 2918 },
+ [V4L2_COLORSPACE_SMPTE240M][1] = { 2926, 2926, 857 },
+ [V4L2_COLORSPACE_SMPTE240M][2] = { 1594, 2901, 2901 },
+ [V4L2_COLORSPACE_SMPTE240M][3] = { 1594, 2901, 774 },
+ [V4L2_COLORSPACE_SMPTE240M][4] = { 2484, 618, 2858 },
+ [V4L2_COLORSPACE_SMPTE240M][5] = { 2484, 618, 617 },
+ [V4L2_COLORSPACE_SMPTE240M][6] = { 507, 507, 2832 },
[V4L2_COLORSPACE_SMPTE240M][7] = { 507, 507, 507 },
[V4L2_COLORSPACE_REC709][0] = { 2939, 2939, 2939 },
[V4L2_COLORSPACE_REC709][1] = { 2939, 2939, 547 },
@@ -623,21 +103,21 @@
[V4L2_COLORSPACE_REC709][5] = { 2939, 547, 547 },
[V4L2_COLORSPACE_REC709][6] = { 547, 547, 2939 },
[V4L2_COLORSPACE_REC709][7] = { 547, 547, 547 },
- [V4L2_COLORSPACE_470_SYSTEM_M][0] = { 2892, 2988, 2807 },
- [V4L2_COLORSPACE_470_SYSTEM_M][1] = { 2846, 3070, 843 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][0] = { 2894, 2988, 2808 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][1] = { 2847, 3070, 843 },
[V4L2_COLORSPACE_470_SYSTEM_M][2] = { 1656, 2962, 2783 },
[V4L2_COLORSPACE_470_SYSTEM_M][3] = { 1572, 3045, 763 },
- [V4L2_COLORSPACE_470_SYSTEM_M][4] = { 2476, 229, 2742 },
- [V4L2_COLORSPACE_470_SYSTEM_M][5] = { 2420, 672, 614 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][4] = { 2477, 229, 2743 },
+ [V4L2_COLORSPACE_470_SYSTEM_M][5] = { 2422, 672, 614 },
[V4L2_COLORSPACE_470_SYSTEM_M][6] = { 725, 63, 2718 },
[V4L2_COLORSPACE_470_SYSTEM_M][7] = { 534, 561, 509 },
[V4L2_COLORSPACE_470_SYSTEM_BG][0] = { 2939, 2939, 2939 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][1] = { 2939, 2939, 464 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][1] = { 2939, 2939, 621 },
[V4L2_COLORSPACE_470_SYSTEM_BG][2] = { 786, 2939, 2939 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][3] = { 786, 2939, 464 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][4] = { 2879, 547, 2956 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][3] = { 786, 2939, 621 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][4] = { 2879, 547, 2923 },
[V4L2_COLORSPACE_470_SYSTEM_BG][5] = { 2879, 547, 547 },
- [V4L2_COLORSPACE_470_SYSTEM_BG][6] = { 547, 547, 2956 },
+ [V4L2_COLORSPACE_470_SYSTEM_BG][6] = { 547, 547, 2923 },
[V4L2_COLORSPACE_470_SYSTEM_BG][7] = { 547, 547, 547 },
[V4L2_COLORSPACE_SRGB][0] = { 3056, 3056, 3056 },
[V4L2_COLORSPACE_SRGB][1] = { 3056, 3056, 800 },
@@ -647,22 +127,6 @@
[V4L2_COLORSPACE_SRGB][5] = { 3056, 800, 800 },
[V4L2_COLORSPACE_SRGB][6] = { 800, 800, 3056 },
[V4L2_COLORSPACE_SRGB][7] = { 800, 800, 800 },
- [V4L2_COLORSPACE_ADOBERGB][0] = { 3033, 3033, 3033 },
- [V4L2_COLORSPACE_ADOBERGB][1] = { 3033, 3033, 1063 },
- [V4L2_COLORSPACE_ADOBERGB][2] = { 1828, 3033, 3033 },
- [V4L2_COLORSPACE_ADOBERGB][3] = { 1828, 3033, 1063 },
- [V4L2_COLORSPACE_ADOBERGB][4] = { 2633, 851, 2979 },
- [V4L2_COLORSPACE_ADOBERGB][5] = { 2633, 851, 851 },
- [V4L2_COLORSPACE_ADOBERGB][6] = { 851, 851, 2979 },
- [V4L2_COLORSPACE_ADOBERGB][7] = { 851, 851, 851 },
- [V4L2_COLORSPACE_BT2020][0] = { 2939, 2939, 2939 },
- [V4L2_COLORSPACE_BT2020][1] = { 2877, 2923, 1058 },
- [V4L2_COLORSPACE_BT2020][2] = { 1837, 2840, 2916 },
- [V4L2_COLORSPACE_BT2020][3] = { 1734, 2823, 993 },
- [V4L2_COLORSPACE_BT2020][4] = { 2427, 961, 2812 },
- [V4L2_COLORSPACE_BT2020][5] = { 2351, 912, 648 },
- [V4L2_COLORSPACE_BT2020][6] = { 792, 618, 2788 },
- [V4L2_COLORSPACE_BT2020][7] = { 547, 547, 547 },
};
#else
@@ -674,40 +138,29 @@
#include <stdlib.h>
static const double rec709_to_ntsc1953[3][3] = {
- { 0.6689794, 0.2678309, 0.0323187 },
- { 0.0184901, 1.0742442, -0.0602820 },
- { 0.0162259, 0.0431716, 0.8549253 }
+ { 0.6698, 0.2678, 0.0323 },
+ { 0.0185, 1.0742, -0.0603 },
+ { 0.0162, 0.0432, 0.8551 }
};
static const double rec709_to_ebu[3][3] = {
- { 0.9578221, 0.0421779, -0.0000000 },
- { -0.0000000, 1.0000000, 0.0000000 },
- { -0.0000000, -0.0119367, 1.0119367 }
+ { 0.9578, 0.0422, 0 },
+ { 0 , 1 , 0 },
+ { 0 , 0.0118, 0.9882 }
};
static const double rec709_to_170m[3][3] = {
- { 1.0653640, -0.0553900, -0.0099740 },
- { -0.0196361, 1.0363630, -0.0167269 },
- { 0.0016327, 0.0044133, 0.9939540 },
+ { 1.0654, -0.0554, -0.0010 },
+ { -0.0196, 1.0364, -0.0167 },
+ { 0.0016, 0.0044, 0.9940 }
};
static const double rec709_to_240m[3][3] = {
- { 1.0653640, -0.0553900, -0.0099740 },
- { -0.0196361, 1.0363630, -0.0167269 },
- { 0.0016327, 0.0044133, 0.9939540 },
+ { 0.7151, 0.2849, 0 },
+ { 0.0179, 0.9821, 0 },
+ { 0.0177, 0.0472, 0.9350 }
};
-static const double rec709_to_adobergb[3][3] = {
- { 0.7151627, 0.2848373, -0.0000000 },
- { 0.0000000, 1.0000000, 0.0000000 },
- { -0.0000000, 0.0411705, 0.9588295 },
-};
-
-static const double rec709_to_bt2020[3][3] = {
- { 0.6274524, 0.3292485, 0.0432991 },
- { 0.0691092, 0.9195311, 0.0113597 },
- { 0.0163976, 0.0880301, 0.8955723 },
-};
static void mult_matrix(double *r, double *g, double *b, const double m[3][3])
{
@@ -723,18 +176,7 @@
static double transfer_srgb_to_rgb(double v)
{
- if (v < -0.04045)
- return pow((-v + 0.055) / 1.055, 2.4);
- return (v <= 0.04045) ? v / 12.92 : pow((v + 0.055) / 1.055, 2.4);
-}
-
-static double transfer_rgb_to_srgb(double v)
-{
- if (v <= -0.0031308)
- return -1.055 * pow(-v, 1.0 / 2.4) + 0.055;
- if (v <= 0.0031308)
- return v * 12.92;
- return 1.055 * pow(v, 1.0 / 2.4) - 0.055;
+ return (v <= 0.03928) ? v / 12.92 : pow((v + 0.055) / 1.055, 2.4);
}
static double transfer_rgb_to_smpte240m(double v)
@@ -744,21 +186,9 @@
static double transfer_rgb_to_rec709(double v)
{
- if (v <= -0.018)
- return -1.099 * pow(-v, 0.45) + 0.099;
return (v < 0.018) ? v * 4.5 : 1.099 * pow(v, 0.45) - 0.099;
}
-static double transfer_rec709_to_rgb(double v)
-{
- return (v < 0.081) ? v / 4.5 : pow((v + 0.099) / 1.099, 1.0 / 0.45);
-}
-
-static double transfer_rgb_to_adobergb(double v)
-{
- return pow(v, 1.0 / 2.19921875);
-}
-
static double transfer_srgb_to_rec709(double v)
{
return transfer_rgb_to_rec709(transfer_srgb_to_rgb(v));
@@ -766,8 +196,6 @@
static void csc(enum v4l2_colorspace colorspace, double *r, double *g, double *b)
{
- int clamp = 1;
-
/* Convert the primaries of Rec. 709 Linear RGB */
switch (colorspace) {
case V4L2_COLORSPACE_SMPTE240M:
@@ -794,29 +222,15 @@
*b = transfer_srgb_to_rgb(*b);
mult_matrix(r, g, b, rec709_to_ntsc1953);
break;
- case V4L2_COLORSPACE_ADOBERGB:
- *r = transfer_srgb_to_rgb(*r);
- *g = transfer_srgb_to_rgb(*g);
- *b = transfer_srgb_to_rgb(*b);
- mult_matrix(r, g, b, rec709_to_adobergb);
- break;
- case V4L2_COLORSPACE_BT2020:
- *r = transfer_srgb_to_rgb(*r);
- *g = transfer_srgb_to_rgb(*g);
- *b = transfer_srgb_to_rgb(*b);
- mult_matrix(r, g, b, rec709_to_bt2020);
- break;
case V4L2_COLORSPACE_SRGB:
case V4L2_COLORSPACE_REC709:
default:
break;
}
- if (clamp) {
- *r = ((*r) < 0) ? 0 : (((*r) > 1) ? 1 : (*r));
- *g = ((*g) < 0) ? 0 : (((*g) > 1) ? 1 : (*g));
- *b = ((*b) < 0) ? 0 : (((*b) > 1) ? 1 : (*b));
- }
+ *r = ((*r) < 0) ? 0 : (((*r) > 1) ? 1 : (*r));
+ *g = ((*g) < 0) ? 0 : (((*g) > 1) ? 1 : (*g));
+ *b = ((*b) < 0) ? 0 : (((*b) > 1) ? 1 : (*b));
/* Encode to gamma corrected colorspace */
switch (colorspace) {
@@ -828,18 +242,12 @@
case V4L2_COLORSPACE_SMPTE170M:
case V4L2_COLORSPACE_470_SYSTEM_M:
case V4L2_COLORSPACE_470_SYSTEM_BG:
- case V4L2_COLORSPACE_BT2020:
*r = transfer_rgb_to_rec709(*r);
*g = transfer_rgb_to_rec709(*g);
*b = transfer_rgb_to_rec709(*b);
break;
case V4L2_COLORSPACE_SRGB:
break;
- case V4L2_COLORSPACE_ADOBERGB:
- *r = transfer_rgb_to_adobergb(*r);
- *g = transfer_rgb_to_adobergb(*g);
- *b = transfer_rgb_to_adobergb(*b);
- break;
case V4L2_COLORSPACE_REC709:
default:
*r = transfer_srgb_to_rec709(*r);
@@ -861,8 +269,6 @@
V4L2_COLORSPACE_470_SYSTEM_BG,
0,
V4L2_COLORSPACE_SRGB,
- V4L2_COLORSPACE_ADOBERGB,
- V4L2_COLORSPACE_BT2020,
};
static const char * const colorspace_names[] = {
"",
@@ -874,39 +280,13 @@
"V4L2_COLORSPACE_470_SYSTEM_BG",
"",
"V4L2_COLORSPACE_SRGB",
- "V4L2_COLORSPACE_ADOBERGB",
- "V4L2_COLORSPACE_BT2020",
};
int i;
int c;
printf("/* Generated table */\n");
- printf("const unsigned short tpg_rec709_to_linear[255 * 16 + 1] = {");
- for (i = 0; i <= 255 * 16; i++) {
- if (i % 16 == 0)
- printf("\n\t");
- printf("%4d,%s",
- (int)(0.5 + 16.0 * 255.0 *
- transfer_rec709_to_rgb(i / (16.0 * 255.0))),
- i % 16 == 15 || i == 255 * 16 ? "" : " ");
- }
- printf("\n};\n\n");
-
- printf("/* Generated table */\n");
- printf("const unsigned short tpg_linear_to_rec709[255 * 16 + 1] = {");
- for (i = 0; i <= 255 * 16; i++) {
- if (i % 16 == 0)
- printf("\n\t");
- printf("%4d,%s",
- (int)(0.5 + 16.0 * 255.0 *
- transfer_rgb_to_rec709(i / (16.0 * 255.0))),
- i % 16 == 15 || i == 255 * 16 ? "" : " ");
- }
- printf("\n};\n\n");
-
- printf("/* Generated table */\n");
- printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][TPG_COLOR_CSC_BLACK + 1] = {\n");
- for (c = 0; c <= V4L2_COLORSPACE_BT2020; c++) {
+ printf("const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1] = {\n");
+ for (c = 0; c <= V4L2_COLORSPACE_SRGB; c++) {
for (i = 0; i <= TPG_COLOR_CSC_BLACK; i++) {
double r, g, b;
diff --git a/drivers/media/platform/vivid/vivid-tpg-colors.h b/drivers/media/platform/vivid/vivid-tpg-colors.h
index 2c33335..a2678fb 100644
--- a/drivers/media/platform/vivid/vivid-tpg-colors.h
+++ b/drivers/media/platform/vivid/vivid-tpg-colors.h
@@ -59,8 +59,6 @@
};
extern const struct color tpg_colors[TPG_COLOR_MAX];
-extern const unsigned short tpg_rec709_to_linear[255 * 16 + 1];
-extern const unsigned short tpg_linear_to_rec709[255 * 16 + 1];
-extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_BT2020 + 1][TPG_COLOR_CSC_BLACK + 1];
+extern const struct color16 tpg_csc_colors[V4L2_COLORSPACE_SRGB + 1][TPG_COLOR_CSC_BLACK + 1];
#endif
diff --git a/drivers/media/platform/vivid/vivid-tpg.c b/drivers/media/platform/vivid/vivid-tpg.c
index fc9c653..0c6fa53 100644
--- a/drivers/media/platform/vivid/vivid-tpg.c
+++ b/drivers/media/platform/vivid/vivid-tpg.c
@@ -136,7 +136,7 @@
tpg->black_line[plane] = vzalloc(max_w * pixelsz);
if (!tpg->black_line[plane])
return -ENOMEM;
- tpg->random_line[plane] = vzalloc(max_w * 2 * pixelsz);
+ tpg->random_line[plane] = vzalloc(max_w * pixelsz);
if (!tpg->random_line[plane])
return -ENOMEM;
}
@@ -296,193 +296,127 @@
}
}
-static inline int rec709_to_linear(int v)
+static u16 color_to_y(struct tpg_data *tpg, int r, int g, int b)
{
- v = clamp(v, 0, 0xff0);
- return tpg_rec709_to_linear[v];
-}
-
-static inline int linear_to_rec709(int v)
-{
- v = clamp(v, 0, 0xff0);
- return tpg_linear_to_rec709[v];
-}
-
-static void rgb2ycbcr(const int m[3][3], int r, int g, int b,
- int y_offset, int *y, int *cb, int *cr)
-{
- *y = ((m[0][0] * r + m[0][1] * g + m[0][2] * b) >> 16) + (y_offset << 4);
- *cb = ((m[1][0] * r + m[1][1] * g + m[1][2] * b) >> 16) + (128 << 4);
- *cr = ((m[2][0] * r + m[2][1] * g + m[2][2] * b) >> 16) + (128 << 4);
-}
-
-static void color_to_ycbcr(struct tpg_data *tpg, int r, int g, int b,
- int *y, int *cb, int *cr)
-{
-#define COEFF(v, r) ((int)(0.5 + (v) * (r) * 256.0))
-
- static const int bt601[3][3] = {
- { COEFF(0.299, 219), COEFF(0.587, 219), COEFF(0.114, 219) },
- { COEFF(-0.169, 224), COEFF(-0.331, 224), COEFF(0.5, 224) },
- { COEFF(0.5, 224), COEFF(-0.419, 224), COEFF(-0.081, 224) },
- };
- static const int bt601_full[3][3] = {
- { COEFF(0.299, 255), COEFF(0.587, 255), COEFF(0.114, 255) },
- { COEFF(-0.169, 255), COEFF(-0.331, 255), COEFF(0.5, 255) },
- { COEFF(0.5, 255), COEFF(-0.419, 255), COEFF(-0.081, 255) },
- };
- static const int rec709[3][3] = {
- { COEFF(0.2126, 219), COEFF(0.7152, 219), COEFF(0.0722, 219) },
- { COEFF(-0.1146, 224), COEFF(-0.3854, 224), COEFF(0.5, 224) },
- { COEFF(0.5, 224), COEFF(-0.4542, 224), COEFF(-0.0458, 224) },
- };
- static const int rec709_full[3][3] = {
- { COEFF(0.2126, 255), COEFF(0.7152, 255), COEFF(0.0722, 255) },
- { COEFF(-0.1146, 255), COEFF(-0.3854, 255), COEFF(0.5, 255) },
- { COEFF(0.5, 255), COEFF(-0.4542, 255), COEFF(-0.0458, 255) },
- };
- static const int smpte240m[3][3] = {
- { COEFF(0.212, 219), COEFF(0.701, 219), COEFF(0.087, 219) },
- { COEFF(-0.116, 224), COEFF(-0.384, 224), COEFF(0.5, 224) },
- { COEFF(0.5, 224), COEFF(-0.445, 224), COEFF(-0.055, 224) },
- };
- static const int bt2020[3][3] = {
- { COEFF(0.2726, 219), COEFF(0.6780, 219), COEFF(0.0593, 219) },
- { COEFF(-0.1396, 224), COEFF(-0.3604, 224), COEFF(0.5, 224) },
- { COEFF(0.5, 224), COEFF(-0.4629, 224), COEFF(-0.0405, 224) },
- };
- bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
- int lin_y, yc;
-
- switch (tpg->real_ycbcr_enc) {
- case V4L2_YCBCR_ENC_601:
- case V4L2_YCBCR_ENC_XV601:
- case V4L2_YCBCR_ENC_SYCC:
- rgb2ycbcr(full ? bt601_full : bt601, r, g, b, 16, y, cb, cr);
- break;
- case V4L2_YCBCR_ENC_BT2020:
- rgb2ycbcr(bt2020, r, g, b, 16, y, cb, cr);
- break;
- case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
- lin_y = (COEFF(0.2627, 255) * rec709_to_linear(r) +
- COEFF(0.6780, 255) * rec709_to_linear(g) +
- COEFF(0.0593, 255) * rec709_to_linear(b)) >> 16;
- yc = linear_to_rec709(lin_y);
- *y = (yc * 219) / 255 + (16 << 4);
- if (b <= yc)
- *cb = (((b - yc) * COEFF(1.0 / 1.9404, 224)) >> 16) + (128 << 4);
- else
- *cb = (((b - yc) * COEFF(1.0 / 1.5816, 224)) >> 16) + (128 << 4);
- if (r <= yc)
- *cr = (((r - yc) * COEFF(1.0 / 1.7184, 224)) >> 16) + (128 << 4);
- else
- *cr = (((r - yc) * COEFF(1.0 / 0.9936, 224)) >> 16) + (128 << 4);
- break;
- case V4L2_YCBCR_ENC_SMPTE240M:
- rgb2ycbcr(smpte240m, r, g, b, 16, y, cb, cr);
- break;
- case V4L2_YCBCR_ENC_709:
- case V4L2_YCBCR_ENC_XV709:
+ switch (tpg->colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ return ((16829 * r + 33039 * g + 6416 * b + 16 * 32768) >> 16) + (16 << 4);
+ case V4L2_COLORSPACE_SMPTE240M:
+ return ((11932 * r + 39455 * g + 4897 * b + 16 * 32768) >> 16) + (16 << 4);
+ case V4L2_COLORSPACE_REC709:
+ case V4L2_COLORSPACE_SRGB:
default:
- rgb2ycbcr(full ? rec709_full : rec709, r, g, b, 0, y, cb, cr);
- break;
+ return ((11966 * r + 40254 * g + 4064 * b + 16 * 32768) >> 16) + (16 << 4);
}
}
-static void ycbcr2rgb(const int m[3][3], int y, int cb, int cr,
- int y_offset, int *r, int *g, int *b)
+static u16 color_to_cb(struct tpg_data *tpg, int r, int g, int b)
{
- y -= y_offset << 4;
+ switch (tpg->colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ return ((-9714 * r - 19070 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4);
+ case V4L2_COLORSPACE_SMPTE240M:
+ return ((-6684 * r - 22100 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4);
+ case V4L2_COLORSPACE_REC709:
+ case V4L2_COLORSPACE_SRGB:
+ default:
+ return ((-6596 * r - 22189 * g + 28784 * b + 16 * 32768) >> 16) + (128 << 4);
+ }
+}
+
+static u16 color_to_cr(struct tpg_data *tpg, int r, int g, int b)
+{
+ switch (tpg->colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ return ((28784 * r - 24103 * g - 4681 * b + 16 * 32768) >> 16) + (128 << 4);
+ case V4L2_COLORSPACE_SMPTE240M:
+ return ((28784 * r - 25606 * g - 3178 * b + 16 * 32768) >> 16) + (128 << 4);
+ case V4L2_COLORSPACE_REC709:
+ case V4L2_COLORSPACE_SRGB:
+ default:
+ return ((28784 * r - 26145 * g - 2639 * b + 16 * 32768) >> 16) + (128 << 4);
+ }
+}
+
+static u16 ycbcr_to_r(struct tpg_data *tpg, int y, int cb, int cr)
+{
+ int r;
+
+ y -= 16 << 4;
cb -= 128 << 4;
cr -= 128 << 4;
- *r = m[0][0] * y + m[0][1] * cb + m[0][2] * cr;
- *g = m[1][0] * y + m[1][1] * cb + m[1][2] * cr;
- *b = m[2][0] * y + m[2][1] * cb + m[2][2] * cr;
- *r = clamp(*r >> 12, 0, 0xff0);
- *g = clamp(*g >> 12, 0, 0xff0);
- *b = clamp(*b >> 12, 0, 0xff0);
-}
-
-static void ycbcr_to_color(struct tpg_data *tpg, int y, int cb, int cr,
- int *r, int *g, int *b)
-{
-#undef COEFF
-#define COEFF(v, r) ((int)(0.5 + (v) * ((255.0 * 255.0 * 16.0) / (r))))
- static const int bt601[3][3] = {
- { COEFF(1, 219), COEFF(0, 224), COEFF(1.4020, 224) },
- { COEFF(1, 219), COEFF(-0.3441, 224), COEFF(-0.7141, 224) },
- { COEFF(1, 219), COEFF(1.7720, 224), COEFF(0, 224) },
- };
- static const int bt601_full[3][3] = {
- { COEFF(1, 255), COEFF(0, 255), COEFF(1.4020, 255) },
- { COEFF(1, 255), COEFF(-0.3441, 255), COEFF(-0.7141, 255) },
- { COEFF(1, 255), COEFF(1.7720, 255), COEFF(0, 255) },
- };
- static const int rec709[3][3] = {
- { COEFF(1, 219), COEFF(0, 224), COEFF(1.5748, 224) },
- { COEFF(1, 219), COEFF(-0.1873, 224), COEFF(-0.4681, 224) },
- { COEFF(1, 219), COEFF(1.8556, 224), COEFF(0, 224) },
- };
- static const int rec709_full[3][3] = {
- { COEFF(1, 255), COEFF(0, 255), COEFF(1.5748, 255) },
- { COEFF(1, 255), COEFF(-0.1873, 255), COEFF(-0.4681, 255) },
- { COEFF(1, 255), COEFF(1.8556, 255), COEFF(0, 255) },
- };
- static const int smpte240m[3][3] = {
- { COEFF(1, 219), COEFF(0, 224), COEFF(1.5756, 224) },
- { COEFF(1, 219), COEFF(-0.2253, 224), COEFF(-0.4767, 224) },
- { COEFF(1, 219), COEFF(1.8270, 224), COEFF(0, 224) },
- };
- static const int bt2020[3][3] = {
- { COEFF(1, 219), COEFF(0, 224), COEFF(1.4746, 224) },
- { COEFF(1, 219), COEFF(-0.1646, 224), COEFF(-0.5714, 224) },
- { COEFF(1, 219), COEFF(1.8814, 224), COEFF(0, 224) },
- };
- bool full = tpg->real_quantization == V4L2_QUANTIZATION_FULL_RANGE;
- int lin_r, lin_g, lin_b, lin_y;
-
- switch (tpg->real_ycbcr_enc) {
- case V4L2_YCBCR_ENC_601:
- case V4L2_YCBCR_ENC_XV601:
- case V4L2_YCBCR_ENC_SYCC:
- ycbcr2rgb(full ? bt601_full : bt601, y, cb, cr, 16, r, g, b);
+ switch (tpg->colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ r = 4769 * y + 6537 * cr;
break;
- case V4L2_YCBCR_ENC_BT2020:
- ycbcr2rgb(bt2020, y, cb, cr, 16, r, g, b);
+ case V4L2_COLORSPACE_SMPTE240M:
+ r = 4769 * y + 7376 * cr;
break;
- case V4L2_YCBCR_ENC_BT2020_CONST_LUM:
- y -= 16 << 4;
- cb -= 128 << 4;
- cr -= 128 << 4;
-
- if (cb <= 0)
- *b = COEFF(1.0, 219) * y + COEFF(1.9404, 224) * cb;
- else
- *b = COEFF(1.0, 219) * y + COEFF(1.5816, 224) * cb;
- *b = *b >> 12;
- if (cr <= 0)
- *r = COEFF(1.0, 219) * y + COEFF(1.7184, 224) * cr;
- else
- *r = COEFF(1.0, 219) * y + COEFF(0.9936, 224) * cr;
- *r = *r >> 12;
- lin_r = rec709_to_linear(*r);
- lin_b = rec709_to_linear(*b);
- lin_y = rec709_to_linear((y * 255) / 219);
-
- lin_g = COEFF(1.0 / 0.6780, 255) * lin_y -
- COEFF(0.2627 / 0.6780, 255) * lin_r -
- COEFF(0.0593 / 0.6780, 255) * lin_b;
- *g = linear_to_rec709(lin_g >> 12);
- break;
- case V4L2_YCBCR_ENC_SMPTE240M:
- ycbcr2rgb(smpte240m, y, cb, cr, 16, r, g, b);
- break;
- case V4L2_YCBCR_ENC_709:
- case V4L2_YCBCR_ENC_XV709:
+ case V4L2_COLORSPACE_REC709:
+ case V4L2_COLORSPACE_SRGB:
default:
- ycbcr2rgb(full ? rec709_full : rec709, y, cb, cr, 16, r, g, b);
+ r = 4769 * y + 7343 * cr;
break;
}
+ return clamp(r >> 12, 0, 0xff0);
+}
+
+static u16 ycbcr_to_g(struct tpg_data *tpg, int y, int cb, int cr)
+{
+ int g;
+
+ y -= 16 << 4;
+ cb -= 128 << 4;
+ cr -= 128 << 4;
+ switch (tpg->colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ g = 4769 * y - 1605 * cb - 3330 * cr;
+ break;
+ case V4L2_COLORSPACE_SMPTE240M:
+ g = 4769 * y - 1055 * cb - 2341 * cr;
+ break;
+ case V4L2_COLORSPACE_REC709:
+ case V4L2_COLORSPACE_SRGB:
+ default:
+ g = 4769 * y - 873 * cb - 2183 * cr;
+ break;
+ }
+ return clamp(g >> 12, 0, 0xff0);
+}
+
+static u16 ycbcr_to_b(struct tpg_data *tpg, int y, int cb, int cr)
+{
+ int b;
+
+ y -= 16 << 4;
+ cb -= 128 << 4;
+ cr -= 128 << 4;
+ switch (tpg->colorspace) {
+ case V4L2_COLORSPACE_SMPTE170M:
+ case V4L2_COLORSPACE_470_SYSTEM_M:
+ case V4L2_COLORSPACE_470_SYSTEM_BG:
+ b = 4769 * y + 7343 * cb;
+ break;
+ case V4L2_COLORSPACE_SMPTE240M:
+ b = 4769 * y + 8552 * cb;
+ break;
+ case V4L2_COLORSPACE_REC709:
+ case V4L2_COLORSPACE_SRGB:
+ default:
+ b = 4769 * y + 8652 * cb;
+ break;
+ }
+ return clamp(b >> 12, 0, 0xff0);
}
/* precalculate color bar values to speed up rendering */
@@ -522,17 +456,18 @@
g <<= 4;
b <<= 4;
}
- if (tpg->qual == TPG_QUAL_GRAY) {
- /* Rec. 709 Luma function */
- /* (0.2126, 0.7152, 0.0722) * (255 * 256) */
- r = g = b = ((13879 * r + 46688 * g + 4713 * b) >> 16) + (16 << 4);
- }
+ if (tpg->qual == TPG_QUAL_GRAY)
+ r = g = b = color_to_y(tpg, r, g, b);
/*
* The assumption is that the RGB output is always full range,
* so only if the rgb_range overrides the 'real' rgb range do
* we need to convert the RGB values.
*
+ * Currently there is no way of signalling to userspace if you
+ * are actually giving it limited range RGB (or full range
+ * YUV for that matter).
+ *
* Remember that r, g and b are still in the 0 - 0xff0 range.
*/
if (tpg->real_rgb_range == V4L2_DV_RGB_RANGE_LIMITED &&
@@ -562,12 +497,12 @@
if (tpg->brightness != 128 || tpg->contrast != 128 ||
tpg->saturation != 128 || tpg->hue) {
/* Implement these operations */
- int y, cb, cr;
- int tmp_cb, tmp_cr;
/* First convert to YCbCr */
-
- color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
+ int y = color_to_y(tpg, r, g, b); /* Luma */
+ int cb = color_to_cb(tpg, r, g, b); /* Cb */
+ int cr = color_to_cr(tpg, r, g, b); /* Cr */
+ int tmp_cb, tmp_cr;
y = (16 << 4) + ((y - (16 << 4)) * tpg->contrast) / 128;
y += (tpg->brightness << 4) - (128 << 4);
@@ -585,29 +520,21 @@
tpg->colors[k][2] = clamp(cr >> 4, 1, 254);
return;
}
- ycbcr_to_color(tpg, y, cb, cr, &r, &g, &b);
+ r = ycbcr_to_r(tpg, y, cb, cr);
+ g = ycbcr_to_g(tpg, y, cb, cr);
+ b = ycbcr_to_b(tpg, y, cb, cr);
}
if (tpg->is_yuv) {
/* Convert to YCbCr */
- int y, cb, cr;
+ u16 y = color_to_y(tpg, r, g, b); /* Luma */
+ u16 cb = color_to_cb(tpg, r, g, b); /* Cb */
+ u16 cr = color_to_cr(tpg, r, g, b); /* Cr */
- color_to_ycbcr(tpg, r, g, b, &y, &cb, &cr);
-
- if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
- y = clamp(y, 16 << 4, 235 << 4);
- cb = clamp(cb, 16 << 4, 240 << 4);
- cr = clamp(cr, 16 << 4, 240 << 4);
- }
tpg->colors[k][0] = clamp(y >> 4, 1, 254);
tpg->colors[k][1] = clamp(cb >> 4, 1, 254);
tpg->colors[k][2] = clamp(cr >> 4, 1, 254);
} else {
- if (tpg->real_quantization == V4L2_QUANTIZATION_LIM_RANGE) {
- r = (r * 219) / 255 + (16 << 4);
- g = (g * 219) / 255 + (16 << 4);
- b = (b * 219) / 255 + (16 << 4);
- }
switch (tpg->fourcc) {
case V4L2_PIX_FMT_RGB565:
case V4L2_PIX_FMT_RGB565X:
@@ -1225,46 +1152,6 @@
if (tpg->recalc_colors) {
tpg->recalc_colors = false;
tpg->recalc_lines = true;
- tpg->real_ycbcr_enc = tpg->ycbcr_enc;
- tpg->real_quantization = tpg->quantization;
- if (tpg->ycbcr_enc == V4L2_YCBCR_ENC_DEFAULT) {
- switch (tpg->colorspace) {
- case V4L2_COLORSPACE_REC709:
- tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_709;
- break;
- case V4L2_COLORSPACE_SRGB:
- tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_SYCC;
- break;
- case V4L2_COLORSPACE_BT2020:
- tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_BT2020;
- break;
- case V4L2_COLORSPACE_SMPTE240M:
- tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_SMPTE240M;
- break;
- case V4L2_COLORSPACE_SMPTE170M:
- case V4L2_COLORSPACE_470_SYSTEM_M:
- case V4L2_COLORSPACE_470_SYSTEM_BG:
- case V4L2_COLORSPACE_ADOBERGB:
- default:
- tpg->real_ycbcr_enc = V4L2_YCBCR_ENC_601;
- break;
- }
- }
- if (tpg->quantization == V4L2_QUANTIZATION_DEFAULT) {
- tpg->real_quantization = V4L2_QUANTIZATION_FULL_RANGE;
- if (tpg->is_yuv) {
- switch (tpg->real_ycbcr_enc) {
- case V4L2_YCBCR_ENC_SYCC:
- case V4L2_YCBCR_ENC_XV601:
- case V4L2_YCBCR_ENC_XV709:
- break;
- default:
- tpg->real_quantization =
- V4L2_QUANTIZATION_LIM_RANGE;
- break;
- }
- }
- }
tpg_precalculate_colors(tpg);
}
if (tpg->recalc_square_border) {
diff --git a/drivers/media/platform/vivid/vivid-tpg.h b/drivers/media/platform/vivid/vivid-tpg.h
index 9dc463a..8ef3e52 100644
--- a/drivers/media/platform/vivid/vivid-tpg.h
+++ b/drivers/media/platform/vivid/vivid-tpg.h
@@ -119,18 +119,6 @@
u32 fourcc;
bool is_yuv;
u32 colorspace;
- u32 ycbcr_enc;
- /*
- * Stores the actual Y'CbCr encoding, i.e. will never be
- * V4L2_YCBCR_ENC_DEFAULT.
- */
- u32 real_ycbcr_enc;
- u32 quantization;
- /*
- * Stores the actual quantization, i.e. will never be
- * V4L2_QUANTIZATION_DEFAULT.
- */
- u32 real_quantization;
enum tpg_video_aspect vid_aspect;
enum tpg_pixel_aspect pix_aspect;
unsigned rgb_range;
@@ -298,32 +286,6 @@
return tpg->colorspace;
}
-static inline void tpg_s_ycbcr_enc(struct tpg_data *tpg, u32 ycbcr_enc)
-{
- if (tpg->ycbcr_enc == ycbcr_enc)
- return;
- tpg->ycbcr_enc = ycbcr_enc;
- tpg->recalc_colors = true;
-}
-
-static inline u32 tpg_g_ycbcr_enc(const struct tpg_data *tpg)
-{
- return tpg->ycbcr_enc;
-}
-
-static inline void tpg_s_quantization(struct tpg_data *tpg, u32 quantization)
-{
- if (tpg->quantization == quantization)
- return;
- tpg->quantization = quantization;
- tpg->recalc_colors = true;
-}
-
-static inline u32 tpg_g_quantization(const struct tpg_data *tpg)
-{
- return tpg->quantization;
-}
-
static inline unsigned tpg_g_planes(const struct tpg_data *tpg)
{
return tpg->planes;
diff --git a/drivers/media/platform/vivid/vivid-vbi-cap.c b/drivers/media/platform/vivid/vivid-vbi-cap.c
index ef81b01..2166d0b 100644
--- a/drivers/media/platform/vivid/vivid-vbi-cap.c
+++ b/drivers/media/platform/vivid/vivid-vbi-cap.c
@@ -236,8 +236,8 @@
.buf_queue = vbi_cap_buf_queue,
.start_streaming = vbi_cap_start_streaming,
.stop_streaming = vbi_cap_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .wait_prepare = vivid_unlock,
+ .wait_finish = vivid_lock,
};
int vidioc_g_fmt_vbi_cap(struct file *file, void *priv,
diff --git a/drivers/media/platform/vivid/vivid-vbi-out.c b/drivers/media/platform/vivid/vivid-vbi-out.c
index 4e4c70e..9d00a07 100644
--- a/drivers/media/platform/vivid/vivid-vbi-out.c
+++ b/drivers/media/platform/vivid/vivid-vbi-out.c
@@ -131,8 +131,8 @@
.buf_queue = vbi_out_buf_queue,
.start_streaming = vbi_out_start_streaming,
.stop_streaming = vbi_out_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .wait_prepare = vivid_unlock,
+ .wait_finish = vivid_lock,
};
int vidioc_g_fmt_vbi_out(struct file *file, void *priv,
diff --git a/drivers/media/platform/vivid/vivid-vid-cap.c b/drivers/media/platform/vivid/vivid-vid-cap.c
index 867a29a..331c544 100644
--- a/drivers/media/platform/vivid/vivid-vid-cap.c
+++ b/drivers/media/platform/vivid/vivid-vid-cap.c
@@ -288,8 +288,8 @@
.buf_queue = vid_cap_buf_queue,
.start_streaming = vid_cap_start_streaming,
.stop_streaming = vid_cap_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .wait_prepare = vivid_unlock,
+ .wait_finish = vivid_lock,
};
/*
@@ -443,12 +443,12 @@
break;
if (bt->standards & V4L2_DV_BT_STD_CEA861) {
if (bt->width == 720 && bt->height <= 576)
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
+ v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SMPTE170M);
else
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_709);
+ v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_REC709);
v4l2_ctrl_s_ctrl(dev->real_rgb_range_cap, 1);
} else {
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_SRGB);
+ v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SRGB);
v4l2_ctrl_s_ctrl(dev->real_rgb_range_cap, 0);
}
tpg_s_rgb_range(&dev->tpg, v4l2_ctrl_g_ctrl(dev->rgb_range_cap));
@@ -498,20 +498,6 @@
return dev->colorspace_out;
}
-static unsigned vivid_ycbcr_enc_cap(struct vivid_dev *dev)
-{
- if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
- return tpg_g_ycbcr_enc(&dev->tpg);
- return dev->ycbcr_enc_out;
-}
-
-static unsigned vivid_quantization_cap(struct vivid_dev *dev)
-{
- if (!dev->loop_video || vivid_is_webcam(dev) || vivid_is_tv_cap(dev))
- return tpg_g_quantization(&dev->tpg);
- return dev->quantization_out;
-}
-
int vivid_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
@@ -524,8 +510,6 @@
mp->field = dev->field_cap;
mp->pixelformat = dev->fmt_cap->fourcc;
mp->colorspace = vivid_colorspace_cap(dev);
- mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
- mp->quantization = vivid_quantization_cap(dev);
mp->num_planes = dev->fmt_cap->planes;
for (p = 0; p < mp->num_planes; p++) {
mp->plane_fmt[p].bytesperline = tpg_g_bytesperline(&dev->tpg, p);
@@ -611,8 +595,6 @@
memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
}
mp->colorspace = vivid_colorspace_cap(dev);
- mp->ycbcr_enc = vivid_ycbcr_enc_cap(dev);
- mp->quantization = vivid_quantization_cap(dev);
memset(mp->reserved, 0, sizeof(mp->reserved));
return 0;
}
@@ -1325,20 +1307,20 @@
if (dev->colorspace) {
switch (dev->input_type[i]) {
case WEBCAM:
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_SRGB);
+ v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SRGB);
break;
case TV:
case SVID:
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
+ v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SMPTE170M);
break;
case HDMI:
if (bt->standards & V4L2_DV_BT_STD_CEA861) {
if (dev->src_rect.width == 720 && dev->src_rect.height <= 576)
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_170M);
+ v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SMPTE170M);
else
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_709);
+ v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_REC709);
} else {
- v4l2_ctrl_s_ctrl(dev->colorspace, VIVID_CS_SRGB);
+ v4l2_ctrl_s_ctrl(dev->colorspace, V4L2_COLORSPACE_SRGB);
}
break;
}
diff --git a/drivers/media/platform/vivid/vivid-vid-common.c b/drivers/media/platform/vivid/vivid-vid-common.c
index 6bef1e6..16cd6d2 100644
--- a/drivers/media/platform/vivid/vivid-vid-common.c
+++ b/drivers/media/platform/vivid/vivid-vid-common.c
@@ -259,8 +259,6 @@
mp->pixelformat = pix->pixelformat;
mp->field = pix->field;
mp->colorspace = pix->colorspace;
- mp->ycbcr_enc = pix->ycbcr_enc;
- mp->quantization = pix->quantization;
mp->num_planes = 1;
mp->flags = pix->flags;
ppix->sizeimage = pix->sizeimage;
@@ -287,8 +285,6 @@
pix->pixelformat = mp->pixelformat;
pix->field = mp->field;
pix->colorspace = mp->colorspace;
- pix->ycbcr_enc = mp->ycbcr_enc;
- pix->quantization = mp->quantization;
pix->sizeimage = ppix->sizeimage;
pix->bytesperline = ppix->bytesperline;
pix->flags = mp->flags;
diff --git a/drivers/media/platform/vivid/vivid-vid-out.c b/drivers/media/platform/vivid/vivid-vid-out.c
index 39ff79f..69c2dbd 100644
--- a/drivers/media/platform/vivid/vivid-vid-out.c
+++ b/drivers/media/platform/vivid/vivid-vid-out.c
@@ -209,8 +209,8 @@
.buf_queue = vid_out_buf_queue,
.start_streaming = vid_out_start_streaming,
.stop_streaming = vid_out_stop_streaming,
- .wait_prepare = vb2_ops_wait_prepare,
- .wait_finish = vb2_ops_wait_finish,
+ .wait_prepare = vivid_unlock,
+ .wait_finish = vivid_lock,
};
/*
@@ -259,8 +259,6 @@
}
break;
}
- dev->ycbcr_enc_out = V4L2_YCBCR_ENC_DEFAULT;
- dev->quantization_out = V4L2_QUANTIZATION_DEFAULT;
dev->compose_out = dev->sink_rect;
dev->compose_bounds_out = dev->sink_rect;
dev->crop_out = dev->compose_out;
@@ -320,8 +318,6 @@
mp->field = dev->field_out;
mp->pixelformat = dev->fmt_out->fourcc;
mp->colorspace = dev->colorspace_out;
- mp->ycbcr_enc = dev->ycbcr_enc_out;
- mp->quantization = dev->quantization_out;
mp->num_planes = dev->fmt_out->planes;
for (p = 0; p < mp->num_planes; p++) {
mp->plane_fmt[p].bytesperline = dev->bytesperline_out[p];
@@ -398,23 +394,16 @@
pfmt[p].sizeimage = pfmt[p].bytesperline * mp->height;
memset(pfmt[p].reserved, 0, sizeof(pfmt[p].reserved));
}
- mp->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
- mp->quantization = V4L2_QUANTIZATION_DEFAULT;
- if (vivid_is_svid_out(dev)) {
+ if (vivid_is_svid_out(dev))
mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
- } else if (dev->dvi_d_out || !(bt->standards & V4L2_DV_BT_STD_CEA861)) {
+ else if (dev->dvi_d_out || !(bt->standards & V4L2_DV_BT_STD_CEA861))
mp->colorspace = V4L2_COLORSPACE_SRGB;
- if (dev->dvi_d_out)
- mp->quantization = V4L2_QUANTIZATION_LIM_RANGE;
- } else if (bt->width == 720 && bt->height <= 576) {
+ else if (bt->width == 720 && bt->height <= 576)
mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
- } else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M &&
- mp->colorspace != V4L2_COLORSPACE_REC709 &&
- mp->colorspace != V4L2_COLORSPACE_ADOBERGB &&
- mp->colorspace != V4L2_COLORSPACE_BT2020 &&
- mp->colorspace != V4L2_COLORSPACE_SRGB) {
+ else if (mp->colorspace != V4L2_COLORSPACE_SMPTE170M &&
+ mp->colorspace != V4L2_COLORSPACE_REC709 &&
+ mp->colorspace != V4L2_COLORSPACE_SRGB)
mp->colorspace = V4L2_COLORSPACE_REC709;
- }
memset(mp->reserved, 0, sizeof(mp->reserved));
return 0;
}
@@ -533,8 +522,6 @@
set_colorspace:
dev->colorspace_out = mp->colorspace;
- dev->ycbcr_enc_out = mp->ycbcr_enc;
- dev->quantization_out = mp->quantization;
if (dev->loop_video) {
vivid_send_source_change(dev, SVID);
vivid_send_source_change(dev, HDMI);
@@ -625,7 +612,7 @@
sel->r = dev->fmt_out_rect;
break;
case V4L2_SEL_TGT_CROP_BOUNDS:
- if (!dev->has_crop_out)
+ if (!dev->has_compose_out)
return -EINVAL;
sel->r = vivid_max_rect;
break;
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index b21f381..a0c1984 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -187,8 +187,8 @@
struct v4l2_subdev_mbus_code_enum *code)
{
static const unsigned int codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+ V4L2_MBUS_FMT_ARGB8888_1X32,
+ V4L2_MBUS_FMT_AYUV8_1X32,
};
struct v4l2_mbus_framefmt *format;
@@ -215,8 +215,8 @@
if (fse->index)
return -EINVAL;
- if (fse->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
- fse->code != MEDIA_BUS_FMT_AYUV8_1X32)
+ if (fse->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+ fse->code != V4L2_MBUS_FMT_AYUV8_1X32)
return -EINVAL;
fse->min_width = BRU_MIN_SIZE;
@@ -261,9 +261,9 @@
switch (pad) {
case BRU_PAD_SINK(0):
/* Default to YUV if the requested format is not supported. */
- if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
- fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
- fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
+ if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+ fmt->code != V4L2_MBUS_FMT_AYUV8_1X32)
+ fmt->code = V4L2_MBUS_FMT_AYUV8_1X32;
break;
default:
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index 5eb16e8..3e6601b 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -562,6 +562,7 @@
.probe = vsp1_probe,
.remove = vsp1_remove,
.driver = {
+ .owner = THIS_MODULE,
.name = "vsp1",
.pm = &vsp1_pm_ops,
.of_match_table = vsp1_of_match,
diff --git a/drivers/media/platform/vsp1/vsp1_hsit.c b/drivers/media/platform/vsp1/vsp1_hsit.c
index 80bedc5..db2950a 100644
--- a/drivers/media/platform/vsp1/vsp1_hsit.c
+++ b/drivers/media/platform/vsp1/vsp1_hsit.c
@@ -70,9 +70,9 @@
if ((code->pad == HSIT_PAD_SINK && !hsit->inverse) |
(code->pad == HSIT_PAD_SOURCE && hsit->inverse))
- code->code = MEDIA_BUS_FMT_ARGB8888_1X32;
+ code->code = V4L2_MBUS_FMT_ARGB8888_1X32;
else
- code->code = MEDIA_BUS_FMT_AHSV8888_1X32;
+ code->code = V4L2_MBUS_FMT_AHSV8888_1X32;
return 0;
}
@@ -136,8 +136,8 @@
return 0;
}
- format->code = hsit->inverse ? MEDIA_BUS_FMT_AHSV8888_1X32
- : MEDIA_BUS_FMT_ARGB8888_1X32;
+ format->code = hsit->inverse ? V4L2_MBUS_FMT_AHSV8888_1X32
+ : V4L2_MBUS_FMT_ARGB8888_1X32;
format->width = clamp_t(unsigned int, fmt->format.width,
HSIT_MIN_SIZE, HSIT_MAX_SIZE);
format->height = clamp_t(unsigned int, fmt->format.height,
@@ -151,8 +151,8 @@
format = vsp1_entity_get_pad_format(&hsit->entity, fh, HSIT_PAD_SOURCE,
fmt->which);
*format = fmt->format;
- format->code = hsit->inverse ? MEDIA_BUS_FMT_ARGB8888_1X32
- : MEDIA_BUS_FMT_AHSV8888_1X32;
+ format->code = hsit->inverse ? V4L2_MBUS_FMT_ARGB8888_1X32
+ : V4L2_MBUS_FMT_AHSV8888_1X32;
return 0;
}
diff --git a/drivers/media/platform/vsp1/vsp1_lif.c b/drivers/media/platform/vsp1/vsp1_lif.c
index 17a6ca7..d4fb23e 100644
--- a/drivers/media/platform/vsp1/vsp1_lif.c
+++ b/drivers/media/platform/vsp1/vsp1_lif.c
@@ -78,8 +78,8 @@
struct v4l2_subdev_mbus_code_enum *code)
{
static const unsigned int codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+ V4L2_MBUS_FMT_ARGB8888_1X32,
+ V4L2_MBUS_FMT_AYUV8_1X32,
};
if (code->pad == LIF_PAD_SINK) {
@@ -147,9 +147,9 @@
struct v4l2_mbus_framefmt *format;
/* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
- fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
- fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+ if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+ fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32)
+ fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32;
format = vsp1_entity_get_pad_format(&lif->entity, fh, fmt->pad,
fmt->which);
diff --git a/drivers/media/platform/vsp1/vsp1_lut.c b/drivers/media/platform/vsp1/vsp1_lut.c
index 6f185c3..fea36eb 100644
--- a/drivers/media/platform/vsp1/vsp1_lut.c
+++ b/drivers/media/platform/vsp1/vsp1_lut.c
@@ -86,9 +86,9 @@
struct v4l2_subdev_mbus_code_enum *code)
{
static const unsigned int codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AHSV8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+ V4L2_MBUS_FMT_ARGB8888_1X32,
+ V4L2_MBUS_FMT_AHSV8888_1X32,
+ V4L2_MBUS_FMT_AYUV8_1X32,
};
struct v4l2_mbus_framefmt *format;
@@ -158,10 +158,10 @@
struct v4l2_mbus_framefmt *format;
/* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
- fmt->format.code != MEDIA_BUS_FMT_AHSV8888_1X32 &&
- fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
- fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+ if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+ fmt->format.code != V4L2_MBUS_FMT_AHSV8888_1X32 &&
+ fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32)
+ fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32;
format = vsp1_entity_get_pad_format(&lut->entity, fh, fmt->pad,
fmt->which);
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.c b/drivers/media/platform/vsp1/vsp1_rwpf.c
index 1f1ba26..ec3dab6 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.c
@@ -29,8 +29,8 @@
struct v4l2_subdev_mbus_code_enum *code)
{
static const unsigned int codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+ V4L2_MBUS_FMT_ARGB8888_1X32,
+ V4L2_MBUS_FMT_AYUV8_1X32,
};
if (code->index >= ARRAY_SIZE(codes))
@@ -103,9 +103,9 @@
struct v4l2_rect *crop;
/* Default to YUV if the requested format is not supported. */
- if (fmt->format.code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
- fmt->format.code != MEDIA_BUS_FMT_AYUV8_1X32)
- fmt->format.code = MEDIA_BUS_FMT_AYUV8_1X32;
+ if (fmt->format.code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+ fmt->format.code != V4L2_MBUS_FMT_AYUV8_1X32)
+ fmt->format.code = V4L2_MBUS_FMT_AYUV8_1X32;
format = vsp1_entity_get_pad_format(&rwpf->entity, fh, fmt->pad,
fmt->which);
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index 1129494..b7d3c8b 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -139,7 +139,7 @@
input = &sru->entity.formats[SRU_PAD_SINK];
output = &sru->entity.formats[SRU_PAD_SOURCE];
- if (input->code == MEDIA_BUS_FMT_ARGB8888_1X32)
+ if (input->code == V4L2_MBUS_FMT_ARGB8888_1X32)
ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3
| VI6_SRU_CTRL0_PARAM4;
else
@@ -170,8 +170,8 @@
struct v4l2_subdev_mbus_code_enum *code)
{
static const unsigned int codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+ V4L2_MBUS_FMT_ARGB8888_1X32,
+ V4L2_MBUS_FMT_AYUV8_1X32,
};
struct v4l2_mbus_framefmt *format;
@@ -248,9 +248,9 @@
switch (pad) {
case SRU_PAD_SINK:
/* Default to YUV if the requested format is not supported. */
- if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
- fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
- fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
+ if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+ fmt->code != V4L2_MBUS_FMT_AYUV8_1X32)
+ fmt->code = V4L2_MBUS_FMT_AYUV8_1X32;
fmt->width = clamp(fmt->width, SRU_MIN_SIZE, SRU_MAX_SIZE);
fmt->height = clamp(fmt->height, SRU_MIN_SIZE, SRU_MAX_SIZE);
diff --git a/drivers/media/platform/vsp1/vsp1_uds.c b/drivers/media/platform/vsp1/vsp1_uds.c
index a4afec1..de92ef4 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -173,8 +173,8 @@
struct v4l2_subdev_mbus_code_enum *code)
{
static const unsigned int codes[] = {
- MEDIA_BUS_FMT_ARGB8888_1X32,
- MEDIA_BUS_FMT_AYUV8_1X32,
+ V4L2_MBUS_FMT_ARGB8888_1X32,
+ V4L2_MBUS_FMT_AYUV8_1X32,
};
if (code->pad == UDS_PAD_SINK) {
@@ -246,9 +246,9 @@
switch (pad) {
case UDS_PAD_SINK:
/* Default to YUV if the requested format is not supported. */
- if (fmt->code != MEDIA_BUS_FMT_ARGB8888_1X32 &&
- fmt->code != MEDIA_BUS_FMT_AYUV8_1X32)
- fmt->code = MEDIA_BUS_FMT_AYUV8_1X32;
+ if (fmt->code != V4L2_MBUS_FMT_ARGB8888_1X32 &&
+ fmt->code != V4L2_MBUS_FMT_AYUV8_1X32)
+ fmt->code = V4L2_MBUS_FMT_AYUV8_1X32;
fmt->width = clamp(fmt->width, UDS_MIN_SIZE, UDS_MAX_SIZE);
fmt->height = clamp(fmt->height, UDS_MIN_SIZE, UDS_MAX_SIZE);
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index d91f19a..915a20e 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -48,85 +48,85 @@
*/
static const struct vsp1_format_info vsp1_video_formats[] = {
- { V4L2_PIX_FMT_RGB332, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_RGB332, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 8, 0, 0 }, false, false, 1, 1, false },
- { V4L2_PIX_FMT_ARGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_ARGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
1, { 16, 0, 0 }, false, false, 1, 1, true },
- { V4L2_PIX_FMT_XRGB444, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_XRGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
1, { 16, 0, 0 }, false, false, 1, 1, true },
- { V4L2_PIX_FMT_ARGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_ARGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
1, { 16, 0, 0 }, false, false, 1, 1, true },
- { V4L2_PIX_FMT_XRGB555, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_XRGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
1, { 16, 0, 0 }, false, false, 1, 1, false },
- { V4L2_PIX_FMT_RGB565, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_RGB565, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
1, { 16, 0, 0 }, false, false, 1, 1, false },
- { V4L2_PIX_FMT_BGR24, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_BGR24, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 24, 0, 0 }, false, false, 1, 1, false },
- { V4L2_PIX_FMT_RGB24, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_RGB24, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 24, 0, 0 }, false, false, 1, 1, false },
- { V4L2_PIX_FMT_ABGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_ABGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
1, { 32, 0, 0 }, false, false, 1, 1, true },
- { V4L2_PIX_FMT_XBGR32, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_XBGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
1, { 32, 0, 0 }, false, false, 1, 1, false },
- { V4L2_PIX_FMT_ARGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_ARGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 32, 0, 0 }, false, false, 1, 1, true },
- { V4L2_PIX_FMT_XRGB32, MEDIA_BUS_FMT_ARGB8888_1X32,
+ { V4L2_PIX_FMT_XRGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 32, 0, 0 }, false, false, 1, 1, false },
- { V4L2_PIX_FMT_UYVY, MEDIA_BUS_FMT_AYUV8_1X32,
+ { V4L2_PIX_FMT_UYVY, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 16, 0, 0 }, false, false, 2, 1, false },
- { V4L2_PIX_FMT_VYUY, MEDIA_BUS_FMT_AYUV8_1X32,
+ { V4L2_PIX_FMT_VYUY, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 16, 0, 0 }, false, true, 2, 1, false },
- { V4L2_PIX_FMT_YUYV, MEDIA_BUS_FMT_AYUV8_1X32,
+ { V4L2_PIX_FMT_YUYV, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 16, 0, 0 }, true, false, 2, 1, false },
- { V4L2_PIX_FMT_YVYU, MEDIA_BUS_FMT_AYUV8_1X32,
+ { V4L2_PIX_FMT_YVYU, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
1, { 16, 0, 0 }, true, true, 2, 1, false },
- { V4L2_PIX_FMT_NV12M, MEDIA_BUS_FMT_AYUV8_1X32,
+ { V4L2_PIX_FMT_NV12M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
2, { 8, 16, 0 }, false, false, 2, 2, false },
- { V4L2_PIX_FMT_NV21M, MEDIA_BUS_FMT_AYUV8_1X32,
+ { V4L2_PIX_FMT_NV21M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
2, { 8, 16, 0 }, false, true, 2, 2, false },
- { V4L2_PIX_FMT_NV16M, MEDIA_BUS_FMT_AYUV8_1X32,
+ { V4L2_PIX_FMT_NV16M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
2, { 8, 16, 0 }, false, false, 2, 1, false },
- { V4L2_PIX_FMT_NV61M, MEDIA_BUS_FMT_AYUV8_1X32,
+ { V4L2_PIX_FMT_NV61M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
2, { 8, 16, 0 }, false, true, 2, 1, false },
- { V4L2_PIX_FMT_YUV420M, MEDIA_BUS_FMT_AYUV8_1X32,
+ { V4L2_PIX_FMT_YUV420M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
3, { 8, 8, 8 }, false, false, 2, 2, false },
diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c
index da160f4..5215a21 100644
--- a/drivers/media/radio/radio-si476x.c
+++ b/drivers/media/radio/radio-si476x.c
@@ -1575,6 +1575,7 @@
static struct platform_driver si476x_radio_driver = {
.driver = {
.name = DRIVER_NAME,
+ .owner = THIS_MODULE,
},
.probe = si476x_radio_probe,
.remove = si476x_radio_remove,
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index e6b55ed..b9285e6 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -174,6 +174,7 @@
static struct platform_driver timbradio_platform_driver = {
.driver = {
.name = DRIVER_NAME,
+ .owner = THIS_MODULE,
},
.probe = timbradio_probe,
.remove = timbradio_remove,
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c
index b8f3644..9cf6731 100644
--- a/drivers/media/radio/radio-wl1273.c
+++ b/drivers/media/radio/radio-wl1273.c
@@ -1279,12 +1279,10 @@
strlcpy(capability->bus_info, radio->bus_type,
sizeof(capability->bus_info));
- capability->device_caps = V4L2_CAP_HW_FREQ_SEEK |
+ capability->capabilities = V4L2_CAP_HW_FREQ_SEEK |
V4L2_CAP_TUNER | V4L2_CAP_RADIO | V4L2_CAP_AUDIO |
V4L2_CAP_RDS_CAPTURE | V4L2_CAP_MODULATOR |
V4L2_CAP_RDS_OUTPUT;
- capability->capabilities = capability->device_caps |
- V4L2_CAP_DEVICE_CAPS;
return 0;
}
@@ -2150,6 +2148,7 @@
.remove = wl1273_fm_radio_remove,
.driver = {
.name = "wl1273_fm_radio",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/media/radio/si4713/Kconfig b/drivers/media/radio/si4713/Kconfig
index 19f9fde..c8aca65 100644
--- a/drivers/media/radio/si4713/Kconfig
+++ b/drivers/media/radio/si4713/Kconfig
@@ -1,5 +1,4 @@
config USB_SI4713
- depends on !KERNEL_3_13
tristate "Silicon Labs Si4713 FM Radio Transmitter support with USB"
depends on m
depends on USB && I2C && RADIO_SI4713
@@ -16,7 +15,6 @@
module will be called radio-usb-si4713.
config PLATFORM_SI4713
- depends on !KERNEL_3_13
tristate "Silicon Labs Si4713 FM Radio Transmitter support with I2C"
depends on m
depends on I2C && RADIO_SI4713
@@ -32,7 +30,6 @@
module will be called radio-platform-si4713.
config I2C_SI4713
- depends on !KERNEL_3_13
tristate "Silicon Labs Si4713 FM Radio Transmitter support"
depends on m
depends on I2C && RADIO_SI4713
diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c
index 6c75973..a47502a 100644
--- a/drivers/media/radio/si4713/radio-platform-si4713.c
+++ b/drivers/media/radio/si4713/radio-platform-si4713.c
@@ -34,7 +34,7 @@
#include <media/v4l2-fh.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-event.h>
-#include "si4713.h"
+#include <media/radio-si4713.h>
/* module parameters */
static int radio_nr = -1; /* radio device minor (-1 ==> auto assign) */
@@ -153,6 +153,7 @@
{
struct radio_si4713_platform_data *pdata = pdev->dev.platform_data;
struct radio_si4713_device *rsdev;
+ struct i2c_adapter *adapter;
struct v4l2_subdev *sd;
int rval = 0;
@@ -176,13 +177,22 @@
goto exit;
}
- sd = i2c_get_clientdata(pdata->subdev);
- rval = v4l2_device_register_subdev(&rsdev->v4l2_dev, sd);
- if (rval) {
- dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
+ adapter = i2c_get_adapter(pdata->i2c_bus);
+ if (!adapter) {
+ dev_err(&pdev->dev, "Cannot get i2c adapter %d\n",
+ pdata->i2c_bus);
+ rval = -ENODEV;
goto unregister_v4l2_dev;
}
+ sd = v4l2_i2c_new_subdev_board(&rsdev->v4l2_dev, adapter,
+ pdata->subdev_board_info, NULL);
+ if (!sd) {
+ dev_err(&pdev->dev, "Cannot get v4l2 subdevice\n");
+ rval = -ENODEV;
+ goto put_adapter;
+ }
+
rsdev->radio_dev = radio_si4713_vdev_template;
rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev;
rsdev->radio_dev.ctrl_handler = sd->ctrl_handler;
@@ -192,12 +202,14 @@
if (video_register_device(&rsdev->radio_dev, VFL_TYPE_RADIO, radio_nr)) {
dev_err(&pdev->dev, "Could not register video device.\n");
rval = -EIO;
- goto unregister_v4l2_dev;
+ goto put_adapter;
}
dev_info(&pdev->dev, "New device successfully probed\n");
goto exit;
+put_adapter:
+ i2c_put_adapter(adapter);
unregister_v4l2_dev:
v4l2_device_unregister(&rsdev->v4l2_dev);
exit:
@@ -208,10 +220,14 @@
static int radio_si4713_pdriver_remove(struct platform_device *pdev)
{
struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
+ struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
+ struct v4l2_subdev, list);
+ struct i2c_client *client = v4l2_get_subdevdata(sd);
struct radio_si4713_device *rsdev;
rsdev = container_of(v4l2_dev, struct radio_si4713_device, v4l2_dev);
video_unregister_device(&rsdev->radio_dev);
+ i2c_put_adapter(client->adapter);
v4l2_device_unregister(&rsdev->v4l2_dev);
return 0;
@@ -220,6 +236,7 @@
static struct platform_driver radio_si4713_pdriver = {
.driver = {
.name = "radio-si4713",
+ .owner = THIS_MODULE,
},
.probe = radio_si4713_pdriver_probe,
.remove = radio_si4713_pdriver_remove,
diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
index c90004d..b576555 100644
--- a/drivers/media/radio/si4713/si4713.c
+++ b/drivers/media/radio/si4713/si4713.c
@@ -23,7 +23,6 @@
#include <linux/completion.h>
#include <linux/delay.h>
-#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/i2c.h>
#include <linux/slab.h>
@@ -367,25 +366,16 @@
if (sdev->power_state)
return 0;
- if (sdev->vdd) {
- err = regulator_enable(sdev->vdd);
+ if (sdev->supplies) {
+ err = regulator_bulk_enable(sdev->supplies, sdev->supply_data);
if (err) {
- v4l2_err(&sdev->sd, "Failed to enable vdd: %d\n", err);
+ v4l2_err(&sdev->sd, "Failed to enable supplies: %d\n", err);
return err;
}
}
-
- if (sdev->vio) {
- err = regulator_enable(sdev->vio);
- if (err) {
- v4l2_err(&sdev->sd, "Failed to enable vio: %d\n", err);
- return err;
- }
- }
-
- if (!IS_ERR(sdev->gpio_reset)) {
+ if (gpio_is_valid(sdev->gpio_reset)) {
udelay(50);
- gpiod_set_value(sdev->gpio_reset, 1);
+ gpio_set_value(sdev->gpio_reset, 1);
}
if (client->irq)
@@ -407,20 +397,13 @@
SI4713_STC_INT | SI4713_CTS);
return err;
}
- if (!IS_ERR(sdev->gpio_reset))
- gpiod_set_value(sdev->gpio_reset, 0);
-
-
- if (sdev->vdd) {
- err = regulator_disable(sdev->vdd);
+ if (gpio_is_valid(sdev->gpio_reset))
+ gpio_set_value(sdev->gpio_reset, 0);
+ if (sdev->supplies) {
+ err = regulator_bulk_disable(sdev->supplies, sdev->supply_data);
if (err)
- v4l2_err(&sdev->sd, "Failed to disable vdd: %d\n", err);
- }
-
- if (sdev->vio) {
- err = regulator_disable(sdev->vio);
- if (err)
- v4l2_err(&sdev->sd, "Failed to disable vio: %d\n", err);
+ v4l2_err(&sdev->sd,
+ "Failed to disable supplies: %d\n", err);
}
return err;
@@ -447,23 +430,14 @@
v4l2_dbg(1, debug, &sdev->sd, "Power down response: 0x%02x\n",
resp[0]);
v4l2_dbg(1, debug, &sdev->sd, "Device in reset mode\n");
- if (!IS_ERR(sdev->gpio_reset))
- gpiod_set_value(sdev->gpio_reset, 0);
-
- if (sdev->vdd) {
- err = regulator_disable(sdev->vdd);
- if (err) {
+ if (gpio_is_valid(sdev->gpio_reset))
+ gpio_set_value(sdev->gpio_reset, 0);
+ if (sdev->supplies) {
+ err = regulator_bulk_disable(sdev->supplies,
+ sdev->supply_data);
+ if (err)
v4l2_err(&sdev->sd,
- "Failed to disable vdd: %d\n", err);
- }
- }
-
- if (sdev->vio) {
- err = regulator_disable(sdev->vio);
- if (err) {
- v4l2_err(&sdev->sd,
- "Failed to disable vio: %d\n", err);
- }
+ "Failed to disable supplies: %d\n", err);
}
sdev->power_state = POWER_OFF;
}
@@ -1446,51 +1420,38 @@
const struct i2c_device_id *id)
{
struct si4713_device *sdev;
- struct v4l2_ctrl_handler *hdl;
struct si4713_platform_data *pdata = client->dev.platform_data;
- struct device_node *np = client->dev.of_node;
- struct radio_si4713_platform_data si4713_pdev_pdata;
- struct platform_device *si4713_pdev;
- int rval;
+ struct v4l2_ctrl_handler *hdl;
+ int rval, i;
- sdev = devm_kzalloc(&client->dev, sizeof(*sdev), GFP_KERNEL);
+ sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
if (!sdev) {
dev_err(&client->dev, "Failed to alloc video device.\n");
rval = -ENOMEM;
goto exit;
}
- sdev->gpio_reset = devm_gpiod_get(&client->dev, "reset");
- if (!IS_ERR(sdev->gpio_reset)) {
- gpiod_direction_output(sdev->gpio_reset, 0);
- } else if (PTR_ERR(sdev->gpio_reset) == -ENOENT) {
- dev_dbg(&client->dev, "No reset GPIO assigned\n");
- } else if (PTR_ERR(sdev->gpio_reset) == -ENOSYS) {
- dev_dbg(&client->dev, "No reset GPIO support\n");
- } else {
- rval = PTR_ERR(sdev->gpio_reset);
- dev_err(&client->dev, "Failed to request gpio: %d\n", rval);
- goto exit;
+ sdev->gpio_reset = -1;
+ if (pdata && gpio_is_valid(pdata->gpio_reset)) {
+ rval = gpio_request(pdata->gpio_reset, "si4713 reset");
+ if (rval) {
+ dev_err(&client->dev,
+ "Failed to request gpio: %d\n", rval);
+ goto free_sdev;
+ }
+ sdev->gpio_reset = pdata->gpio_reset;
+ gpio_direction_output(sdev->gpio_reset, 0);
+ sdev->supplies = pdata->supplies;
}
- sdev->vdd = devm_regulator_get_optional(&client->dev, "vdd");
- if (IS_ERR(sdev->vdd)) {
- rval = PTR_ERR(sdev->vdd);
- if (rval == -EPROBE_DEFER)
- goto exit;
+ for (i = 0; i < sdev->supplies; i++)
+ sdev->supply_data[i].supply = pdata->supply_names[i];
- dev_dbg(&client->dev, "no vdd regulator found: %d\n", rval);
- sdev->vdd = NULL;
- }
-
- sdev->vio = devm_regulator_get_optional(&client->dev, "vio");
- if (IS_ERR(sdev->vio)) {
- rval = PTR_ERR(sdev->vio);
- if (rval == -EPROBE_DEFER)
- goto exit;
-
- dev_dbg(&client->dev, "no vio regulator found: %d\n", rval);
- sdev->vio = NULL;
+ rval = regulator_bulk_get(&client->dev, sdev->supplies,
+ sdev->supply_data);
+ if (rval) {
+ dev_err(&client->dev, "Cannot get regulators: %d\n", rval);
+ goto free_gpio;
}
v4l2_i2c_subdev_init(&sdev->sd, client, &si4713_subdev_ops);
@@ -1593,12 +1554,12 @@
sdev->sd.ctrl_handler = hdl;
if (client->irq) {
- rval = devm_request_irq(&client->dev, client->irq,
+ rval = request_irq(client->irq,
si4713_handler, IRQF_TRIGGER_FALLING,
client->name, sdev);
if (rval < 0) {
v4l2_err(&sdev->sd, "Could not request IRQ\n");
- goto free_ctrls;
+ goto put_reg;
}
v4l2_dbg(1, debug, &sdev->sd, "IRQ requested.\n");
} else {
@@ -1608,35 +1569,23 @@
rval = si4713_initialize(sdev);
if (rval < 0) {
v4l2_err(&sdev->sd, "Failed to probe device information.\n");
- goto free_ctrls;
+ goto free_irq;
}
- if (!np && (!pdata || !pdata->is_platform_device))
- return 0;
-
- si4713_pdev = platform_device_alloc("radio-si4713", -1);
- if (!si4713_pdev)
- goto put_main_pdev;
-
- si4713_pdev_pdata.subdev = client;
- rval = platform_device_add_data(si4713_pdev, &si4713_pdev_pdata,
- sizeof(si4713_pdev_pdata));
- if (rval)
- goto put_main_pdev;
-
- rval = platform_device_add(si4713_pdev);
- if (rval)
- goto put_main_pdev;
-
- sdev->pd = si4713_pdev;
-
return 0;
-put_main_pdev:
- platform_device_put(si4713_pdev);
- v4l2_device_unregister_subdev(&sdev->sd);
+free_irq:
+ if (client->irq)
+ free_irq(client->irq, sdev);
free_ctrls:
v4l2_ctrl_handler_free(hdl);
+put_reg:
+ regulator_bulk_free(sdev->supplies, sdev->supply_data);
+free_gpio:
+ if (gpio_is_valid(sdev->gpio_reset))
+ gpio_free(sdev->gpio_reset);
+free_sdev:
+ kfree(sdev);
exit:
return rval;
}
@@ -1647,13 +1596,18 @@
struct v4l2_subdev *sd = i2c_get_clientdata(client);
struct si4713_device *sdev = to_si4713_device(sd);
- platform_device_unregister(sdev->pd);
-
if (sdev->power_state)
si4713_set_power_state(sdev, POWER_DOWN);
+ if (client->irq > 0)
+ free_irq(client->irq, sdev);
+
v4l2_device_unregister_subdev(sd);
v4l2_ctrl_handler_free(sd->ctrl_handler);
+ regulator_bulk_free(sdev->supplies, sdev->supply_data);
+ if (gpio_is_valid(sdev->gpio_reset))
+ gpio_free(sdev->gpio_reset);
+ kfree(sdev);
return 0;
}
diff --git a/drivers/media/radio/si4713/si4713.h b/drivers/media/radio/si4713/si4713.h
index 8a376e1..ed700e3 100644
--- a/drivers/media/radio/si4713/si4713.h
+++ b/drivers/media/radio/si4713/si4713.h
@@ -15,9 +15,7 @@
#ifndef SI4713_I2C_H
#define SI4713_I2C_H
-#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
-#include <linux/gpio/consumer.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-ctrls.h>
#include <media/si4713.h>
@@ -192,6 +190,8 @@
#define MIN_ACOMP_THRESHOLD (-40)
#define MAX_ACOMP_GAIN 20
+#define SI4713_NUM_SUPPLIES 2
+
/*
* si4713_device - private data
*/
@@ -236,10 +236,9 @@
struct v4l2_ctrl *tune_ant_cap;
};
struct completion work;
- struct regulator *vdd;
- struct regulator *vio;
- struct gpio_desc *gpio_reset;
- struct platform_device *pd;
+ unsigned supplies;
+ struct regulator_bulk_data supply_data[SI4713_NUM_SUPPLIES];
+ int gpio_reset;
u32 power_state;
u32 rds_enabled;
u32 frequency;
@@ -247,8 +246,4 @@
u32 stereo;
u32 tune_rnl;
};
-
-struct radio_si4713_platform_data {
- struct i2c_client *subdev;
-};
#endif /* ifndef SI4713_I2C_H */
diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c
index 704397f..6f28f6e 100644
--- a/drivers/media/radio/wl128x/fmdrv_common.c
+++ b/drivers/media/radio/wl128x/fmdrv_common.c
@@ -1256,7 +1256,7 @@
fmerr("Unable to read firmware(%s) content\n", fw_name);
return ret;
}
- fmdbg("Firmware(%s) length : %zu bytes\n", fw_name, fw_entry->size);
+ fmdbg("Firmware(%s) length : %d bytes\n", fw_name, fw_entry->size);
fw_data = (void *)fw_entry->data;
fw_len = fw_entry->size;
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c
index a5bd3f6..b55012c 100644
--- a/drivers/media/radio/wl128x/fmdrv_v4l2.c
+++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c
@@ -198,12 +198,10 @@
strlcpy(capability->card, FM_DRV_CARD_SHORT_NAME,
sizeof(capability->card));
sprintf(capability->bus_info, "UART");
- capability->device_caps = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
+ capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
V4L2_CAP_RADIO | V4L2_CAP_MODULATOR |
V4L2_CAP_AUDIO | V4L2_CAP_READWRITE |
V4L2_CAP_RDS_CAPTURE;
- capability->capabilities = capability->device_caps |
- V4L2_CAP_DEVICE_CAPS;
return 0;
}
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 99c880f..a4c907d 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -179,7 +179,7 @@
module will be called ene_ir.
config IR_HIX5HD2
- depends on !KERNEL_3_7
+ depends on !BACKPORT_KERNEL_3_7
depends on CONFIG_MFD_SYSCON
tristate "Hisilicon hix5hd2 IR remote control"
depends on m
@@ -244,18 +244,6 @@
To compile this driver as a module, choose M here: the
module will be called fintek-cir.
-config IR_MESON
- tristate "Amlogic Meson IR remote receiver"
- depends on m
- depends on RC_CORE
- depends on ARCH_MESON || COMPILE_TEST
- ---help---
- Say Y if you want to use the IR remote receiver available
- on Amlogic Meson SoCs.
-
- To compile this driver as a module, choose M here: the
- module will be called meson-ir.
-
config IR_NUVOTON
tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
depends on m
@@ -275,8 +263,8 @@
depends on m
depends on USB_ARCH_HAS_HCD
depends on RC_CORE
- select BPAUTO_NEW_LEDS
- select BPAUTO_LEDS_CLASS
+ select BACKPORT_NEW_LEDS
+ select BACKPORT_LEDS_CLASS
depends on USB
---help---
Say Y here if you want to use a RedRat3 Infrared Transceiver.
@@ -302,8 +290,8 @@
depends on m
depends on X86 && PNP
depends on RC_CORE
- select BPAUTO_NEW_LEDS
- select BPAUTO_LEDS_CLASS
+ select BACKPORT_NEW_LEDS
+ select BACKPORT_LEDS_CLASS
depends on BITREVERSE
---help---
Say Y here if you want to use the IR remote functionality found
@@ -314,22 +302,6 @@
To compile this driver as a module, choose M here: the module will
be called winbond_cir.
-config IR_IGORPLUGUSB
- tristate "IgorPlug-USB IR Receiver"
- depends on m
- depends on USB_ARCH_HAS_HCD
- depends on RC_CORE
- depends on USB
- ---help---
- Say Y here if you want to use the IgorPlug-USB IR Receiver by
- Igor Cesko. This device is included on the Fit-PC2.
-
- Note that this device can only record bursts of 36 IR pulses and
- spaces, which is not enough for the NEC, Sanyo and RC-6 protocol.
-
- To compile this driver as a module, choose M here: the module will
- be called igorplugusb.
-
config IR_IGUANA
tristate "IguanaWorks USB IR Transceiver"
depends on m
@@ -353,8 +325,8 @@
depends on USB_ARCH_HAS_HCD
depends on RC_CORE
depends on USB
- select BPAUTO_NEW_LEDS
- select BPAUTO_LEDS_CLASS
+ select BACKPORT_NEW_LEDS
+ select BACKPORT_LEDS_CLASS
---help---
Say Y here if you want to use the TechnoTrend USB IR Receiver. The
driver can control the led.
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index 0652848..9bba1fd 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -22,7 +22,6 @@
obj-$(CPTCFG_IR_ITE_CIR) += ite-cir.o
obj-$(CPTCFG_IR_MCEUSB) += mceusb.o
obj-$(CPTCFG_IR_FINTEK) += fintek-cir.o
-obj-$(CPTCFG_IR_MESON) += meson-ir.o
obj-$(CPTCFG_IR_NUVOTON) += nuvoton-cir.o
obj-$(CPTCFG_IR_ENE) += ene_ir.o
obj-$(CPTCFG_IR_REDRAT3) += redrat3.o
@@ -31,7 +30,6 @@
obj-$(CPTCFG_IR_WINBOND_CIR) += winbond-cir.o
obj-$(CPTCFG_RC_LOOPBACK) += rc-loopback.o
obj-$(CPTCFG_IR_GPIO_CIR) += gpio-ir-recv.o
-obj-$(CPTCFG_IR_IGORPLUGUSB) += igorplugusb.o
obj-$(CPTCFG_IR_IGUANA) += iguanair.o
obj-$(CPTCFG_IR_TTUSBIR) += ttusbir.o
obj-$(CPTCFG_RC_ST) += st_rc.o
diff --git a/drivers/media/rc/gpio-ir-recv.c b/drivers/media/rc/gpio-ir-recv.c
index 229853d..5985308 100644
--- a/drivers/media/rc/gpio-ir-recv.c
+++ b/drivers/media/rc/gpio-ir-recv.c
@@ -240,6 +240,7 @@
.remove = gpio_ir_recv_remove,
.driver = {
.name = GPIO_IR_DRIVER_NAME,
+ .owner = THIS_MODULE,
.of_match_table = of_match_ptr(gpio_ir_recv_of_match),
#ifdef CONFIG_PM
.pm = &gpio_ir_recv_pm_ops,
diff --git a/drivers/media/rc/igorplugusb.c b/drivers/media/rc/igorplugusb.c
deleted file mode 100644
index b36e515..0000000
--- a/drivers/media/rc/igorplugusb.c
+++ /dev/null
@@ -1,261 +0,0 @@
-/*
- * IgorPlug-USB IR Receiver
- *
- * Copyright (C) 2014 Sean Young <sean@mess.org>
- *
- * Supports the standard homebrew IgorPlugUSB receiver with Igor's firmware.
- * See http://www.cesko.host.sk/IgorPlugUSB/IgorPlug-USB%20(AVR)_eng.htm
- *
- * Based on the lirc_igorplugusb.c driver:
- * Copyright (C) 2004 Jan M. Hochstein
- * <hochstein@algo.informatik.tu-darmstadt.de>
- *
- * 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.
- */
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/usb/input.h>
-#include <media/rc-core.h>
-
-#define DRIVER_DESC "IgorPlug-USB IR Receiver"
-#define DRIVER_NAME "igorplugusb"
-
-#define HEADERLEN 3
-#define BUFLEN 36
-#define MAX_PACKET (HEADERLEN + BUFLEN)
-
-#define SET_INFRABUFFER_EMPTY 1
-#define GET_INFRACODE 2
-
-
-struct igorplugusb {
- struct rc_dev *rc;
- struct device *dev;
-
- struct urb *urb;
- struct usb_ctrlrequest request;
-
- struct timer_list timer;
-
- uint8_t buf_in[MAX_PACKET];
-
- char phys[64];
-};
-
-static void igorplugusb_cmd(struct igorplugusb *ir, int cmd);
-
-static void igorplugusb_irdata(struct igorplugusb *ir, unsigned len)
-{
- DEFINE_IR_RAW_EVENT(rawir);
- unsigned i, start, overflow;
-
- dev_dbg(ir->dev, "irdata: %*ph (len=%u)", len, ir->buf_in, len);
-
- /*
- * If more than 36 pulses and spaces follow each other, the igorplugusb
- * overwrites its buffer from the beginning. The overflow value is the
- * last offset which was not overwritten. Everything from this offset
- * onwards occurred before everything until this offset.
- */
- overflow = ir->buf_in[2];
- i = start = overflow + HEADERLEN;
-
- if (start >= len) {
- dev_err(ir->dev, "receive overflow invalid: %u", overflow);
- } else {
- if (overflow > 0)
- dev_warn(ir->dev, "receive overflow, at least %u lost",
- overflow);
-
- do {
- rawir.duration = ir->buf_in[i] * 85333;
- rawir.pulse = i & 1;
-
- ir_raw_event_store_with_filter(ir->rc, &rawir);
-
- if (++i == len)
- i = HEADERLEN;
- } while (i != start);
-
- /* add a trailing space */
- rawir.duration = ir->rc->timeout;
- rawir.pulse = false;
- ir_raw_event_store_with_filter(ir->rc, &rawir);
-
- ir_raw_event_handle(ir->rc);
- }
-
- igorplugusb_cmd(ir, SET_INFRABUFFER_EMPTY);
-}
-
-static void igorplugusb_callback(struct urb *urb)
-{
- struct usb_ctrlrequest *req;
- struct igorplugusb *ir = urb->context;
-
- req = (struct usb_ctrlrequest *)urb->setup_packet;
-
- switch (urb->status) {
- case 0:
- if (req->bRequest == GET_INFRACODE &&
- urb->actual_length > HEADERLEN)
- igorplugusb_irdata(ir, urb->actual_length);
- else /* request IR */
- mod_timer(&ir->timer, jiffies + msecs_to_jiffies(50));
- break;
- case -EPROTO:
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- usb_unlink_urb(urb);
- return;
- default:
- dev_warn(ir->dev, "Error: urb status = %d\n", urb->status);
- igorplugusb_cmd(ir, SET_INFRABUFFER_EMPTY);
- break;
- }
-}
-
-static void igorplugusb_cmd(struct igorplugusb *ir, int cmd)
-{
- int ret;
-
- ir->request.bRequest = cmd;
- ir->urb->transfer_flags = 0;
- ret = usb_submit_urb(ir->urb, GFP_ATOMIC);
- if (ret)
- dev_err(ir->dev, "submit urb failed: %d", ret);
-}
-
-static void igorplugusb_timer(unsigned long data)
-{
- struct igorplugusb *ir = (struct igorplugusb *)data;
-
- igorplugusb_cmd(ir, GET_INFRACODE);
-}
-
-static int igorplugusb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct usb_device *udev;
- struct usb_host_interface *idesc;
- struct usb_endpoint_descriptor *ep;
- struct igorplugusb *ir;
- struct rc_dev *rc;
- int ret;
-
- udev = interface_to_usbdev(intf);
- idesc = intf->cur_altsetting;
-
- if (idesc->desc.bNumEndpoints != 1) {
- dev_err(&intf->dev, "incorrect number of endpoints");
- return -ENODEV;
- }
-
- ep = &idesc->endpoint[0].desc;
- if (!usb_endpoint_dir_in(ep) || !usb_endpoint_xfer_control(ep)) {
- dev_err(&intf->dev, "endpoint incorrect");
- return -ENODEV;
- }
-
- ir = devm_kzalloc(&intf->dev, sizeof(*ir), GFP_KERNEL);
- if (!ir)
- return -ENOMEM;
-
- ir->dev = &intf->dev;
-
- setup_timer(&ir->timer, igorplugusb_timer, (unsigned long)ir);
-
- ir->request.bRequest = GET_INFRACODE;
- ir->request.bRequestType = USB_TYPE_VENDOR | USB_DIR_IN;
- ir->request.wLength = cpu_to_le16(sizeof(ir->buf_in));
-
- ir->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!ir->urb)
- return -ENOMEM;
-
- usb_fill_control_urb(ir->urb, udev,
- usb_rcvctrlpipe(udev, 0), (uint8_t *)&ir->request,
- ir->buf_in, sizeof(ir->buf_in), igorplugusb_callback, ir);
-
- usb_make_path(udev, ir->phys, sizeof(ir->phys));
-
- rc = rc_allocate_device();
- rc->input_name = DRIVER_DESC;
- rc->input_phys = ir->phys;
- usb_to_input_id(udev, &rc->input_id);
- rc->dev.parent = &intf->dev;
- rc->driver_type = RC_DRIVER_IR_RAW;
- /*
- * This device can only store 36 pulses + spaces, which is not enough
- * for the NEC protocol and many others.
- */
- rc->allowed_protocols = RC_BIT_ALL & ~(RC_BIT_NEC | RC_BIT_RC6_6A_20 |
- RC_BIT_RC6_6A_24 | RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE |
- RC_BIT_SONY20 | RC_BIT_MCE_KBD | RC_BIT_SANYO);
-
- rc->priv = ir;
- rc->driver_name = DRIVER_NAME;
- rc->map_name = RC_MAP_HAUPPAUGE;
- rc->timeout = MS_TO_NS(100);
- rc->rx_resolution = 85333;
-
- ir->rc = rc;
- ret = rc_register_device(rc);
- if (ret) {
- dev_err(&intf->dev, "failed to register rc device: %d", ret);
- rc_free_device(rc);
- usb_free_urb(ir->urb);
- return ret;
- }
-
- usb_set_intfdata(intf, ir);
-
- igorplugusb_cmd(ir, SET_INFRABUFFER_EMPTY);
-
- return 0;
-}
-
-static void igorplugusb_disconnect(struct usb_interface *intf)
-{
- struct igorplugusb *ir = usb_get_intfdata(intf);
-
- rc_unregister_device(ir->rc);
- del_timer_sync(&ir->timer);
- usb_set_intfdata(intf, NULL);
- usb_kill_urb(ir->urb);
- usb_free_urb(ir->urb);
-}
-
-static struct usb_device_id igorplugusb_table[] = {
- /* Igor Plug USB (Atmel's Manufact. ID) */
- { USB_DEVICE(0x03eb, 0x0002) },
- /* Fit PC2 Infrared Adapter */
- { USB_DEVICE(0x03eb, 0x21fe) },
- /* Terminating entry */
- { }
-};
-
-static struct usb_driver igorplugusb_driver = {
- .name = DRIVER_NAME,
- .probe = igorplugusb_probe,
- .disconnect = igorplugusb_disconnect,
- .id_table = igorplugusb_table
-};
-
-module_usb_driver(igorplugusb_driver);
-
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_AUTHOR("Sean Young <sean@mess.org>");
-MODULE_LICENSE("GPL");
-MODULE_DEVICE_TABLE(usb, igorplugusb_table);
diff --git a/drivers/media/rc/img-ir/Kconfig b/drivers/media/rc/img-ir/Kconfig
index 74ba6bb..2e5bf62 100644
--- a/drivers/media/rc/img-ir/Kconfig
+++ b/drivers/media/rc/img-ir/Kconfig
@@ -1,9 +1,8 @@
config IR_IMG
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_5
tristate "ImgTec IR Decoder"
depends on m
depends on RC_CORE
- depends on METAG || MIPS || COMPILE_TEST
select IR_IMG_HW if !IR_IMG_RAW
help
Say Y or M here if you want to use the ImgTec infrared decoder
diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c
index 77c78de..a0cac2f 100644
--- a/drivers/media/rc/img-ir/img-ir-core.c
+++ b/drivers/media/rc/img-ir/img-ir-core.c
@@ -166,6 +166,7 @@
static struct platform_driver img_ir_driver = {
.driver = {
.name = "img-ir",
+ .owner = THIS_MODULE,
.of_match_table = img_ir_match,
.pm = &img_ir_pmops,
},
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
index 44e3c51..2ccc3bd 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -530,22 +530,6 @@
u32 ir_status, irq_en;
spin_lock_irq(&priv->lock);
- /*
- * First record that the protocol is being stopped so that the end timer
- * isn't restarted while we're trying to stop it.
- */
- hw->stopping = true;
-
- /*
- * Release the lock to stop the end timer, since the end timer handler
- * acquires the lock and we don't want to deadlock waiting for it.
- */
- spin_unlock_irq(&priv->lock);
- del_timer_sync(&hw->end_timer);
- spin_lock_irq(&priv->lock);
-
- hw->stopping = false;
-
/* switch off and disable interrupts */
img_ir_write(priv, IMG_IR_CONTROL, 0);
irq_en = img_ir_read(priv, IMG_IR_IRQ_ENABLE);
@@ -557,13 +541,12 @@
if (ir_status & (IMG_IR_RXDVAL | IMG_IR_RXDVALD2)) {
ir_status &= ~(IMG_IR_RXDVAL | IMG_IR_RXDVALD2);
img_ir_write(priv, IMG_IR_STATUS, ir_status);
+ img_ir_read(priv, IMG_IR_DATA_LW);
+ img_ir_read(priv, IMG_IR_DATA_UP);
}
- /* always read data to clear buffer if IR wakes the device */
- img_ir_read(priv, IMG_IR_DATA_LW);
- img_ir_read(priv, IMG_IR_DATA_UP);
-
- /* switch back to normal mode */
+ /* stop the end timer and switch back to normal mode */
+ del_timer_sync(&hw->end_timer);
hw->mode = IMG_IR_M_NORMAL;
/* clear the wakeup scancode filter */
@@ -834,8 +817,7 @@
}
- /* we mustn't update the end timer while trying to stop it */
- if (dec->repeat && !hw->stopping) {
+ if (dec->repeat) {
unsigned long interval;
img_ir_begin_repeat(priv);
diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h
index 463bddf..9119bd1 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.h
+++ b/drivers/media/rc/img-ir/img-ir-hw.h
@@ -186,6 +186,9 @@
struct img_ir_timing_regvals rtimings;
};
+int img_ir_register_decoder(struct img_ir_decoder *dec);
+void img_ir_unregister_decoder(struct img_ir_decoder *dec);
+
struct img_ir_priv;
#ifdef CPTCFG_IR_IMG_HW
@@ -211,8 +214,6 @@
* @flags: IMG_IR_F_*.
* @filters: HW filters (derived from scancode filters).
* @mode: Current decode mode.
- * @stopping: Indicates that decoder is being taken down and timers
- * should not be restarted.
* @suspend_irqen: Saved IRQ enable mask over suspend.
*/
struct img_ir_priv_hw {
@@ -228,7 +229,6 @@
struct img_ir_filter filters[RC_FILTER_MAX];
enum img_ir_mode mode;
- bool stopping;
u32 suspend_irqen;
};
diff --git a/drivers/media/rc/imon.c b/drivers/media/rc/imon.c
index 65f80b8..b8837dd 100644
--- a/drivers/media/rc/imon.c
+++ b/drivers/media/rc/imon.c
@@ -1678,8 +1678,7 @@
if (press_type == 0)
rc_keyup(ictx->rdev);
else {
- if (ictx->rc_type == RC_BIT_RC6_MCE ||
- ictx->rc_type == RC_BIT_OTHER)
+ if (ictx->rc_type == RC_BIT_RC6_MCE)
rc_keydown(ictx->rdev,
ictx->rc_type == RC_BIT_RC6_MCE ? RC_TYPE_RC6_MCE : RC_TYPE_OTHER,
ictx->rc_scancode, ictx->rc_toggle);
diff --git a/drivers/media/rc/ir-hix5hd2.c b/drivers/media/rc/ir-hix5hd2.c
index 3a3192c..b6bcf2b 100644
--- a/drivers/media/rc/ir-hix5hd2.c
+++ b/drivers/media/rc/ir-hix5hd2.c
@@ -298,7 +298,7 @@
return 0;
}
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
static int hix5hd2_ir_suspend(struct device *dev)
{
struct hix5hd2_ir_priv *priv = dev_get_drvdata(dev);
diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c
index 98893a8..ed2c8a1 100644
--- a/drivers/media/rc/ir-lirc-codec.c
+++ b/drivers/media/rc/ir-lirc-codec.c
@@ -42,17 +42,11 @@
return -EINVAL;
/* Packet start */
- if (ev.reset) {
- /* Userspace expects a long space event before the start of
- * the signal to use as a sync. This may be done with repeat
- * packets and normal samples. But if a reset has been sent
- * then we assume that a long time has passed, so we send a
- * space with the maximum time value. */
- sample = LIRC_SPACE(LIRC_VALUE_MASK);
- IR_dprintk(2, "delivering reset sync space to lirc_dev\n");
+ if (ev.reset)
+ return 0;
/* Carrier reports */
- } else if (ev.carrier_report) {
+ if (ev.carrier_report) {
sample = LIRC_FREQUENCY(ev.carrier);
IR_dprintk(2, "carrier report (freq: %d)\n", sample);
diff --git a/drivers/media/rc/ir-rc5-decoder.c b/drivers/media/rc/ir-rc5-decoder.c
index 84fa6e9..2ef7639 100644
--- a/drivers/media/rc/ir-rc5-decoder.c
+++ b/drivers/media/rc/ir-rc5-decoder.c
@@ -53,7 +53,7 @@
u32 scancode;
enum rc_type protocol;
- if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X | RC_BIT_RC5_SZ)))
+ if (!(dev->enabled_protocols & (RC_BIT_RC5 | RC_BIT_RC5X)))
return 0;
if (!is_timing_event(ev)) {
diff --git a/drivers/media/rc/ir-rc6-decoder.c b/drivers/media/rc/ir-rc6-decoder.c
index d16bc67..f1f098e 100644
--- a/drivers/media/rc/ir-rc6-decoder.c
+++ b/drivers/media/rc/ir-rc6-decoder.c
@@ -259,8 +259,8 @@
case 32:
if ((scancode & RC6_6A_LCC_MASK) == RC6_6A_MCE_CC) {
protocol = RC_TYPE_RC6_MCE;
- toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
scancode &= ~RC6_6A_MCE_TOGGLE_MASK;
+ toggle = !!(scancode & RC6_6A_MCE_TOGGLE_MASK);
} else {
protocol = RC_BIT_RC6_6A_32;
toggle = 0;
diff --git a/drivers/media/rc/lirc_dev.c b/drivers/media/rc/lirc_dev.c
index 1e0545a..249d2fb 100644
--- a/drivers/media/rc/lirc_dev.c
+++ b/drivers/media/rc/lirc_dev.c
@@ -518,7 +518,8 @@
WARN_ON(mutex_lock_killable(&lirc_dev_lock));
- rc_close(ir->d.rdev);
+ if (ir->d.rdev)
+ rc_close(ir->d.rdev);
ir->open--;
if (ir->attached) {
diff --git a/drivers/media/rc/meson-ir.c b/drivers/media/rc/meson-ir.c
deleted file mode 100644
index fcc3b82..0000000
--- a/drivers/media/rc/meson-ir.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Driver for Amlogic Meson IR remote receiver
- *
- * Copyright (C) 2014 Beniamino Galvani <b.galvani@gmail.com>
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <linux/device.h>
-#include <linux/err.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/module.h>
-#include <linux/of_platform.h>
-#include <linux/platform_device.h>
-#include <linux/spinlock.h>
-
-#include <media/rc-core.h>
-
-#define DRIVER_NAME "meson-ir"
-
-#define IR_DEC_LDR_ACTIVE 0x00
-#define IR_DEC_LDR_IDLE 0x04
-#define IR_DEC_LDR_REPEAT 0x08
-#define IR_DEC_BIT_0 0x0c
-#define IR_DEC_REG0 0x10
-#define IR_DEC_FRAME 0x14
-#define IR_DEC_STATUS 0x18
-#define IR_DEC_REG1 0x1c
-
-#define REG0_RATE_MASK (BIT(11) - 1)
-
-#define REG1_MODE_MASK (BIT(7) | BIT(8))
-#define REG1_MODE_NEC (0 << 7)
-#define REG1_MODE_GENERAL (2 << 7)
-
-#define REG1_TIME_IV_SHIFT 16
-#define REG1_TIME_IV_MASK ((BIT(13) - 1) << REG1_TIME_IV_SHIFT)
-
-#define REG1_IRQSEL_MASK (BIT(2) | BIT(3))
-#define REG1_IRQSEL_NEC_MODE (0 << 2)
-#define REG1_IRQSEL_RISE_FALL (1 << 2)
-#define REG1_IRQSEL_FALL (2 << 2)
-#define REG1_IRQSEL_RISE (3 << 2)
-
-#define REG1_RESET BIT(0)
-#define REG1_ENABLE BIT(15)
-
-#define STATUS_IR_DEC_IN BIT(8)
-
-#define MESON_TRATE 10 /* us */
-
-struct meson_ir {
- void __iomem *reg;
- struct rc_dev *rc;
- int irq;
- spinlock_t lock;
-};
-
-static void meson_ir_set_mask(struct meson_ir *ir, unsigned int reg,
- u32 mask, u32 value)
-{
- u32 data;
-
- data = readl(ir->reg + reg);
- data &= ~mask;
- data |= (value & mask);
- writel(data, ir->reg + reg);
-}
-
-static irqreturn_t meson_ir_irq(int irqno, void *dev_id)
-{
- struct meson_ir *ir = dev_id;
- u32 duration;
- DEFINE_IR_RAW_EVENT(rawir);
-
- spin_lock(&ir->lock);
-
- duration = readl(ir->reg + IR_DEC_REG1);
- duration = (duration & REG1_TIME_IV_MASK) >> REG1_TIME_IV_SHIFT;
- rawir.duration = US_TO_NS(duration * MESON_TRATE);
-
- rawir.pulse = !!(readl(ir->reg + IR_DEC_STATUS) & STATUS_IR_DEC_IN);
-
- ir_raw_event_store_with_filter(ir->rc, &rawir);
- ir_raw_event_handle(ir->rc);
-
- spin_unlock(&ir->lock);
-
- return IRQ_HANDLED;
-}
-
-static int meson_ir_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *node = dev->of_node;
- struct resource *res;
- const char *map_name;
- struct meson_ir *ir;
- int ret;
-
- ir = devm_kzalloc(dev, sizeof(struct meson_ir), GFP_KERNEL);
- if (!ir)
- return -ENOMEM;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- ir->reg = devm_ioremap_resource(dev, res);
- if (IS_ERR(ir->reg)) {
- dev_err(dev, "failed to map registers\n");
- return PTR_ERR(ir->reg);
- }
-
- ir->irq = platform_get_irq(pdev, 0);
- if (ir->irq < 0) {
- dev_err(dev, "no irq resource\n");
- return ir->irq;
- }
-
- ir->rc = rc_allocate_device();
- if (!ir->rc) {
- dev_err(dev, "failed to allocate rc device\n");
- return -ENOMEM;
- }
-
- ir->rc->priv = ir;
- ir->rc->input_name = DRIVER_NAME;
- ir->rc->input_phys = DRIVER_NAME "/input0";
- ir->rc->input_id.bustype = BUS_HOST;
- map_name = of_get_property(node, "linux,rc-map-name", NULL);
- ir->rc->map_name = map_name ? map_name : RC_MAP_EMPTY;
- ir->rc->dev.parent = dev;
- ir->rc->driver_type = RC_DRIVER_IR_RAW;
- ir->rc->allowed_protocols = RC_BIT_ALL;
- ir->rc->rx_resolution = US_TO_NS(MESON_TRATE);
- ir->rc->timeout = MS_TO_NS(200);
- ir->rc->driver_name = DRIVER_NAME;
-
- spin_lock_init(&ir->lock);
- platform_set_drvdata(pdev, ir);
-
- ret = rc_register_device(ir->rc);
- if (ret) {
- dev_err(dev, "failed to register rc device\n");
- goto out_free;
- }
-
- ret = devm_request_irq(dev, ir->irq, meson_ir_irq, 0, "ir-meson", ir);
- if (ret) {
- dev_err(dev, "failed to request irq\n");
- goto out_unreg;
- }
-
- /* Reset the decoder */
- meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, REG1_RESET);
- meson_ir_set_mask(ir, IR_DEC_REG1, REG1_RESET, 0);
- /* Set general operation mode */
- meson_ir_set_mask(ir, IR_DEC_REG1, REG1_MODE_MASK, REG1_MODE_GENERAL);
- /* Set rate */
- meson_ir_set_mask(ir, IR_DEC_REG0, REG0_RATE_MASK, MESON_TRATE - 1);
- /* IRQ on rising and falling edges */
- meson_ir_set_mask(ir, IR_DEC_REG1, REG1_IRQSEL_MASK,
- REG1_IRQSEL_RISE_FALL);
- /* Enable the decoder */
- meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, REG1_ENABLE);
-
- dev_info(dev, "receiver initialized\n");
-
- return 0;
-out_unreg:
- rc_unregister_device(ir->rc);
- ir->rc = NULL;
-out_free:
- rc_free_device(ir->rc);
-
- return ret;
-}
-
-static int meson_ir_remove(struct platform_device *pdev)
-{
- struct meson_ir *ir = platform_get_drvdata(pdev);
- unsigned long flags;
-
- /* Disable the decoder */
- spin_lock_irqsave(&ir->lock, flags);
- meson_ir_set_mask(ir, IR_DEC_REG1, REG1_ENABLE, 0);
- spin_unlock_irqrestore(&ir->lock, flags);
-
- rc_unregister_device(ir->rc);
-
- return 0;
-}
-
-static const struct of_device_id meson_ir_match[] = {
- { .compatible = "amlogic,meson6-ir" },
- { },
-};
-
-static struct platform_driver meson_ir_driver = {
- .probe = meson_ir_probe,
- .remove = meson_ir_remove,
- .driver = {
- .name = DRIVER_NAME,
- .of_match_table = meson_ir_match,
- },
-};
-
-module_platform_driver(meson_ir_driver);
-
-MODULE_DESCRIPTION("Amlogic Meson IR remote receiver driver");
-MODULE_AUTHOR("Beniamino Galvani <b.galvani@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/rc/rc-ir-raw.c b/drivers/media/rc/rc-ir-raw.c
index b732ac6..e8fff2a 100644
--- a/drivers/media/rc/rc-ir-raw.c
+++ b/drivers/media/rc/rc-ir-raw.c
@@ -262,6 +262,7 @@
return -ENOMEM;
dev->raw->dev = dev;
+ dev->enabled_protocols = ~0;
dev->change_protocol = change_protocol;
rc = kfifo_alloc(&dev->raw->kfifo,
sizeof(struct ir_raw_event) * MAX_IR_EVENT_SIZE,
diff --git a/drivers/media/rc/rc-main.c b/drivers/media/rc/rc-main.c
index 46ee99c..b59eee2 100644
--- a/drivers/media/rc/rc-main.c
+++ b/drivers/media/rc/rc-main.c
@@ -1302,7 +1302,8 @@
if (!dev)
return;
- input_free_device(dev->input_dev);
+ if (dev->input_dev)
+ input_free_device(dev->input_dev);
put_device(&dev->dev);
@@ -1417,18 +1418,13 @@
ir_raw_init();
raw_init = true;
}
- /* calls ir_register_device so unlock mutex here*/
- mutex_unlock(&dev->lock);
rc = ir_raw_event_register(dev);
- mutex_lock(&dev->lock);
if (rc < 0)
goto out_input;
}
if (dev->change_protocol) {
- u64 rc_type = (1ll << rc_map->rc_type);
- if (dev->driver_type == RC_DRIVER_IR_RAW)
- rc_type |= RC_BIT_LIRC;
+ u64 rc_type = (1 << rc_map->rc_type);
rc = dev->change_protocol(dev, &rc_type);
if (rc < 0)
goto out_raw;
diff --git a/drivers/media/rc/redrat3.c b/drivers/media/rc/redrat3.c
index c4def66..795b394 100644
--- a/drivers/media/rc/redrat3.c
+++ b/drivers/media/rc/redrat3.c
@@ -966,7 +966,7 @@
rr3->ep_in = ep_in;
rr3->bulk_in_buf = usb_alloc_coherent(udev,
- le16_to_cpu(ep_in->wMaxPacketSize), GFP_KERNEL, &rr3->dma_in);
+ le16_to_cpu(ep_in->wMaxPacketSize), GFP_ATOMIC, &rr3->dma_in);
if (!rr3->bulk_in_buf) {
dev_err(dev, "Read buffer allocation failure\n");
goto error;
@@ -975,8 +975,6 @@
pipe = usb_rcvbulkpipe(udev, ep_in->bEndpointAddress);
usb_fill_bulk_urb(rr3->read_urb, udev, pipe, rr3->bulk_in_buf,
le16_to_cpu(ep_in->wMaxPacketSize), redrat3_handle_async, rr3);
- rr3->read_urb->transfer_dma = rr3->dma_in;
- rr3->read_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
rr3->ep_out = ep_out;
rr3->udev = udev;
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
index 340f7f5..bcee8e1 100644
--- a/drivers/media/rc/sunxi-cir.c
+++ b/drivers/media/rc/sunxi-cir.c
@@ -306,6 +306,7 @@
.remove = sunxi_ir_remove,
.driver = {
.name = SUNXI_IR_DEV,
+ .owner = THIS_MODULE,
.of_match_table = sunxi_ir_match,
},
};
diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index 86602cc..02f497c 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -228,7 +228,7 @@
Fitipower FC0013 silicon tuner driver.
config MEDIA_TUNER_TDA18212
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "NXP TDA18212 silicon tuner"
depends on m
depends on MEDIA_SUPPORT && I2C
@@ -238,8 +238,8 @@
NXP TDA18212 silicon tuner driver.
config MEDIA_TUNER_E4000
- depends on !KERNEL_3_4
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Elonics E4000 silicon tuner"
depends on m
depends on MEDIA_SUPPORT && I2C
@@ -257,7 +257,7 @@
FCI FC2580 silicon tuner driver.
config MEDIA_TUNER_M88TS2022
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Montage M88TS2022 silicon tuner"
depends on m
depends on MEDIA_SUPPORT && I2C
@@ -266,16 +266,6 @@
help
Montage M88TS2022 silicon tuner driver.
-config MEDIA_TUNER_M88RS6000T
- depends on !KERNEL_3_3
- tristate "Montage M88RS6000 internal tuner"
- depends on m
- depends on MEDIA_SUPPORT && I2C
- depends on REGMAP_I2C
- default m if !MEDIA_SUBDRV_AUTOSELECT
- help
- Montage M88RS6000 internal tuner.
-
config MEDIA_TUNER_TUA9001
tristate "Infineon TUA 9001 silicon tuner"
depends on m
@@ -293,7 +283,7 @@
Silicon Labs Si2157 silicon tuner driver.
config MEDIA_TUNER_IT913X
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "ITE Tech IT913x silicon tuner"
depends on m
depends on MEDIA_SUPPORT && I2C
diff --git a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile
index bc7b685..c3e58a6 100644
--- a/drivers/media/tuners/Makefile
+++ b/drivers/media/tuners/Makefile
@@ -41,7 +41,6 @@
obj-$(CPTCFG_MEDIA_TUNER_R820T) += r820t.o
obj-$(CPTCFG_MEDIA_TUNER_MXL301RF) += mxl301rf.o
obj-$(CPTCFG_MEDIA_TUNER_QM1D1C0042) += qm1d1c0042.o
-obj-$(CPTCFG_MEDIA_TUNER_M88RS6000T) += m88rs6000t.o
ccflags-y += -I$(backport_srctree)/drivers/media/dvb-core
ccflags-y += -I$(backport_srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/tuners/m88rs6000t.c b/drivers/media/tuners/m88rs6000t.c
deleted file mode 100644
index d4c13fe..0000000
--- a/drivers/media/tuners/m88rs6000t.c
+++ /dev/null
@@ -1,744 +0,0 @@
-/*
- * Driver for the internal tuner of Montage M88RS6000
- *
- * Copyright (C) 2014 Max nibble <nibble.max@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.
- *
- * 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 "m88rs6000t.h"
-#include <linux/regmap.h>
-
-struct m88rs6000t_dev {
- struct m88rs6000t_config cfg;
- struct i2c_client *client;
- struct regmap *regmap;
- u32 frequency_khz;
-};
-
-struct m88rs6000t_reg_val {
- u8 reg;
- u8 val;
-};
-
-/* set demod main mclk and ts mclk */
-static int m88rs6000t_set_demod_mclk(struct dvb_frontend *fe)
-{
- struct m88rs6000t_dev *dev = fe->tuner_priv;
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- u8 reg11, reg15, reg16, reg1D, reg1E, reg1F;
- u8 N, f0 = 0, f1 = 0, f2 = 0, f3 = 0;
- u16 pll_div_fb;
- u32 div, ts_mclk;
- unsigned int utmp;
- int ret;
-
- /* select demod main mclk */
- ret = regmap_read(dev->regmap, 0x15, &utmp);
- if (ret)
- goto err;
- reg15 = utmp;
- if (c->symbol_rate > 45010000) {
- reg11 = 0x0E;
- reg15 |= 0x02;
- reg16 = 115; /* mclk = 110.25MHz */
- } else {
- reg11 = 0x0A;
- reg15 &= ~0x02;
- reg16 = 96; /* mclk = 96MHz */
- }
-
- /* set ts mclk */
- if (c->delivery_system == SYS_DVBS)
- ts_mclk = 96000;
- else
- ts_mclk = 144000;
-
- pll_div_fb = (reg15 & 0x01) << 8;
- pll_div_fb += reg16;
- pll_div_fb += 32;
-
- div = 36000 * pll_div_fb;
- div /= ts_mclk;
-
- if (div <= 32) {
- N = 2;
- f0 = 0;
- f1 = div / 2;
- f2 = div - f1;
- f3 = 0;
- } else if (div <= 48) {
- N = 3;
- f0 = div / 3;
- f1 = (div - f0) / 2;
- f2 = div - f0 - f1;
- f3 = 0;
- } else if (div <= 64) {
- N = 4;
- f0 = div / 4;
- f1 = (div - f0) / 3;
- f2 = (div - f0 - f1) / 2;
- f3 = div - f0 - f1 - f2;
- } else {
- N = 4;
- f0 = 16;
- f1 = 16;
- f2 = 16;
- f3 = 16;
- }
-
- if (f0 == 16)
- f0 = 0;
- if (f1 == 16)
- f1 = 0;
- if (f2 == 16)
- f2 = 0;
- if (f3 == 16)
- f3 = 0;
-
- ret = regmap_read(dev->regmap, 0x1D, &utmp);
- if (ret)
- goto err;
- reg1D = utmp;
- reg1D &= ~0x03;
- reg1D |= N - 1;
- reg1E = ((f3 << 4) + f2) & 0xFF;
- reg1F = ((f1 << 4) + f0) & 0xFF;
-
- /* program and recalibrate demod PLL */
- ret = regmap_write(dev->regmap, 0x05, 0x40);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x11, 0x08);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x15, reg15);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x16, reg16);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x1D, reg1D);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x1E, reg1E);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x1F, reg1F);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x17, 0xc1);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x17, 0x81);
- if (ret)
- goto err;
- usleep_range(5000, 50000);
- ret = regmap_write(dev->regmap, 0x05, 0x00);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x11, reg11);
- if (ret)
- goto err;
- usleep_range(5000, 50000);
-err:
- if (ret)
- dev_dbg(&dev->client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static int m88rs6000t_set_pll_freq(struct m88rs6000t_dev *dev,
- u32 tuner_freq_MHz)
-{
- u32 fcry_KHz, ulNDiv1, ulNDiv2, ulNDiv;
- u8 refDiv, ucLoDiv1, ucLomod1, ucLoDiv2, ucLomod2, ucLoDiv, ucLomod;
- u8 reg27, reg29, reg42, reg42buf;
- unsigned int utmp;
- int ret;
-
- fcry_KHz = 27000; /* in kHz */
- refDiv = 27;
-
- ret = regmap_write(dev->regmap, 0x36, (refDiv - 8));
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x31, 0x00);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x2c, 0x02);
- if (ret)
- goto err;
-
- if (tuner_freq_MHz >= 1550) {
- ucLoDiv1 = 2;
- ucLomod1 = 0;
- ucLoDiv2 = 2;
- ucLomod2 = 0;
- } else if (tuner_freq_MHz >= 1380) {
- ucLoDiv1 = 3;
- ucLomod1 = 16;
- ucLoDiv2 = 2;
- ucLomod2 = 0;
- } else if (tuner_freq_MHz >= 1070) {
- ucLoDiv1 = 3;
- ucLomod1 = 16;
- ucLoDiv2 = 3;
- ucLomod2 = 16;
- } else if (tuner_freq_MHz >= 1000) {
- ucLoDiv1 = 3;
- ucLomod1 = 16;
- ucLoDiv2 = 4;
- ucLomod2 = 64;
- } else if (tuner_freq_MHz >= 775) {
- ucLoDiv1 = 4;
- ucLomod1 = 64;
- ucLoDiv2 = 4;
- ucLomod2 = 64;
- } else if (tuner_freq_MHz >= 700) {
- ucLoDiv1 = 6;
- ucLomod1 = 48;
- ucLoDiv2 = 4;
- ucLomod2 = 64;
- } else if (tuner_freq_MHz >= 520) {
- ucLoDiv1 = 6;
- ucLomod1 = 48;
- ucLoDiv2 = 6;
- ucLomod2 = 48;
- } else {
- ucLoDiv1 = 8;
- ucLomod1 = 96;
- ucLoDiv2 = 8;
- ucLomod2 = 96;
- }
-
- ulNDiv1 = ((tuner_freq_MHz * ucLoDiv1 * 1000) * refDiv
- / fcry_KHz - 1024) / 2;
- ulNDiv2 = ((tuner_freq_MHz * ucLoDiv2 * 1000) * refDiv
- / fcry_KHz - 1024) / 2;
-
- reg27 = (((ulNDiv1 >> 8) & 0x0F) + ucLomod1) & 0x7F;
- ret = regmap_write(dev->regmap, 0x27, reg27);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x28, (u8)(ulNDiv1 & 0xFF));
- if (ret)
- goto err;
- reg29 = (((ulNDiv2 >> 8) & 0x0F) + ucLomod2) & 0x7f;
- ret = regmap_write(dev->regmap, 0x29, reg29);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x2a, (u8)(ulNDiv2 & 0xFF));
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x2F, 0xf5);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x30, 0x05);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x08, 0x1f);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x08, 0x3f);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x09, 0x20);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x09, 0x00);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x3e, 0x11);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x08, 0x2f);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x08, 0x3f);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x09, 0x10);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x09, 0x00);
- if (ret)
- goto err;
- usleep_range(2000, 50000);
-
- ret = regmap_read(dev->regmap, 0x42, &utmp);
- if (ret)
- goto err;
- reg42 = utmp;
-
- ret = regmap_write(dev->regmap, 0x3e, 0x10);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x08, 0x2f);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x08, 0x3f);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x09, 0x10);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x09, 0x00);
- if (ret)
- goto err;
- usleep_range(2000, 50000);
-
- ret = regmap_read(dev->regmap, 0x42, &utmp);
- if (ret)
- goto err;
- reg42buf = utmp;
- if (reg42buf < reg42) {
- ret = regmap_write(dev->regmap, 0x3e, 0x11);
- if (ret)
- goto err;
- }
- usleep_range(5000, 50000);
-
- ret = regmap_read(dev->regmap, 0x2d, &utmp);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x2d, utmp);
- if (ret)
- goto err;
- ret = regmap_read(dev->regmap, 0x2e, &utmp);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x2e, utmp);
- if (ret)
- goto err;
-
- ret = regmap_read(dev->regmap, 0x27, &utmp);
- if (ret)
- goto err;
- reg27 = utmp & 0x70;
- ret = regmap_read(dev->regmap, 0x83, &utmp);
- if (ret)
- goto err;
- if (reg27 == (utmp & 0x70)) {
- ucLoDiv = ucLoDiv1;
- ulNDiv = ulNDiv1;
- ucLomod = ucLomod1 / 16;
- } else {
- ucLoDiv = ucLoDiv2;
- ulNDiv = ulNDiv2;
- ucLomod = ucLomod2 / 16;
- }
-
- if ((ucLoDiv == 3) || (ucLoDiv == 6)) {
- refDiv = 18;
- ret = regmap_write(dev->regmap, 0x36, (refDiv - 8));
- if (ret)
- goto err;
- ulNDiv = ((tuner_freq_MHz * ucLoDiv * 1000) * refDiv
- / fcry_KHz - 1024) / 2;
- }
-
- reg27 = (0x80 + ((ucLomod << 4) & 0x70)
- + ((ulNDiv >> 8) & 0x0F)) & 0xFF;
- ret = regmap_write(dev->regmap, 0x27, reg27);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x28, (u8)(ulNDiv & 0xFF));
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x29, 0x80);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x31, 0x03);
- if (ret)
- goto err;
-
- if (ucLoDiv == 3)
- utmp = 0xCE;
- else
- utmp = 0x8A;
- ret = regmap_write(dev->regmap, 0x3b, utmp);
- if (ret)
- goto err;
-
- dev->frequency_khz = fcry_KHz * (ulNDiv * 2 + 1024) / refDiv / ucLoDiv;
-
- dev_dbg(&dev->client->dev,
- "actual tune frequency=%d\n", dev->frequency_khz);
-err:
- if (ret)
- dev_dbg(&dev->client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static int m88rs6000t_set_bb(struct m88rs6000t_dev *dev,
- u32 symbol_rate_KSs, s32 lpf_offset_KHz)
-{
- u32 f3dB;
- u8 reg40;
-
- f3dB = symbol_rate_KSs * 9 / 14 + 2000;
- f3dB += lpf_offset_KHz;
- f3dB = clamp_val(f3dB, 6000U, 43000U);
- reg40 = f3dB / 1000;
- return regmap_write(dev->regmap, 0x40, reg40);
-}
-
-static int m88rs6000t_set_params(struct dvb_frontend *fe)
-{
- struct m88rs6000t_dev *dev = fe->tuner_priv;
- struct dtv_frontend_properties *c = &fe->dtv_property_cache;
- int ret;
- s32 lpf_offset_KHz;
- u32 realFreq, freq_MHz;
-
- dev_dbg(&dev->client->dev,
- "frequency=%d symbol_rate=%d\n",
- c->frequency, c->symbol_rate);
-
- if (c->symbol_rate < 5000000)
- lpf_offset_KHz = 3000;
- else
- lpf_offset_KHz = 0;
-
- realFreq = c->frequency + lpf_offset_KHz;
- /* set tuner pll.*/
- freq_MHz = (realFreq + 500) / 1000;
- ret = m88rs6000t_set_pll_freq(dev, freq_MHz);
- if (ret)
- goto err;
- ret = m88rs6000t_set_bb(dev, c->symbol_rate / 1000, lpf_offset_KHz);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x00, 0x01);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x00, 0x00);
- if (ret)
- goto err;
- /* set demod mlck */
- ret = m88rs6000t_set_demod_mclk(fe);
-err:
- if (ret)
- dev_dbg(&dev->client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static int m88rs6000t_init(struct dvb_frontend *fe)
-{
- struct m88rs6000t_dev *dev = fe->tuner_priv;
- int ret;
-
- dev_dbg(&dev->client->dev, "%s:\n", __func__);
-
- ret = regmap_update_bits(dev->regmap, 0x11, 0x08, 0x08);
- if (ret)
- goto err;
- usleep_range(5000, 50000);
- ret = regmap_update_bits(dev->regmap, 0x10, 0x01, 0x01);
- if (ret)
- goto err;
- usleep_range(10000, 50000);
- ret = regmap_write(dev->regmap, 0x07, 0x7d);
-err:
- if (ret)
- dev_dbg(&dev->client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static int m88rs6000t_sleep(struct dvb_frontend *fe)
-{
- struct m88rs6000t_dev *dev = fe->tuner_priv;
- int ret;
-
- dev_dbg(&dev->client->dev, "%s:\n", __func__);
-
- ret = regmap_write(dev->regmap, 0x07, 0x6d);
- if (ret)
- goto err;
- usleep_range(5000, 10000);
-err:
- if (ret)
- dev_dbg(&dev->client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static int m88rs6000t_get_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
- struct m88rs6000t_dev *dev = fe->tuner_priv;
-
- dev_dbg(&dev->client->dev, "\n");
-
- *frequency = dev->frequency_khz;
- return 0;
-}
-
-static int m88rs6000t_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
-{
- struct m88rs6000t_dev *dev = fe->tuner_priv;
-
- dev_dbg(&dev->client->dev, "\n");
-
- *frequency = 0; /* Zero-IF */
- return 0;
-}
-
-
-static int m88rs6000t_get_rf_strength(struct dvb_frontend *fe, u16 *strength)
-{
- struct m88rs6000t_dev *dev = fe->tuner_priv;
- unsigned int val, i;
- int ret;
- u16 gain;
- u32 PGA2_cri_GS = 46, PGA2_crf_GS = 290, TIA_GS = 290;
- u32 RF_GC = 1200, IF_GC = 1100, BB_GC = 300;
- u32 PGA2_GC = 300, TIA_GC = 300, PGA2_cri = 0, PGA2_crf = 0;
- u32 RFG = 0, IFG = 0, BBG = 0, PGA2G = 0, TIAG = 0;
- u32 RFGS[13] = {0, 245, 266, 268, 270, 285,
- 298, 295, 283, 285, 285, 300, 300};
- u32 IFGS[12] = {0, 300, 230, 270, 270, 285,
- 295, 285, 290, 295, 295, 310};
- u32 BBGS[14] = {0, 286, 275, 290, 294, 300, 290,
- 290, 285, 283, 260, 295, 290, 260};
-
- ret = regmap_read(dev->regmap, 0x5A, &val);
- if (ret)
- goto err;
- RF_GC = val & 0x0f;
-
- ret = regmap_read(dev->regmap, 0x5F, &val);
- if (ret)
- goto err;
- IF_GC = val & 0x0f;
-
- ret = regmap_read(dev->regmap, 0x3F, &val);
- if (ret)
- goto err;
- TIA_GC = (val >> 4) & 0x07;
-
- ret = regmap_read(dev->regmap, 0x77, &val);
- if (ret)
- goto err;
- BB_GC = (val >> 4) & 0x0f;
-
- ret = regmap_read(dev->regmap, 0x76, &val);
- if (ret)
- goto err;
- PGA2_GC = val & 0x3f;
- PGA2_cri = PGA2_GC >> 2;
- PGA2_crf = PGA2_GC & 0x03;
-
- for (i = 0; i <= RF_GC; i++)
- RFG += RFGS[i];
-
- if (RF_GC == 0)
- RFG += 400;
- if (RF_GC == 1)
- RFG += 300;
- if (RF_GC == 2)
- RFG += 200;
- if (RF_GC == 3)
- RFG += 100;
-
- for (i = 0; i <= IF_GC; i++)
- IFG += IFGS[i];
-
- TIAG = TIA_GC * TIA_GS;
-
- for (i = 0; i <= BB_GC; i++)
- BBG += BBGS[i];
-
- PGA2G = PGA2_cri * PGA2_cri_GS + PGA2_crf * PGA2_crf_GS;
-
- gain = RFG + IFG - TIAG + BBG + PGA2G;
-
- /* scale value to 0x0000-0xffff */
- gain = clamp_val(gain, 1000U, 10500U);
- *strength = (10500 - gain) * 0xffff / (10500 - 1000);
-err:
- if (ret)
- dev_dbg(&dev->client->dev, "failed=%d\n", ret);
- return ret;
-}
-
-static const struct dvb_tuner_ops m88rs6000t_tuner_ops = {
- .info = {
- .name = "Montage M88RS6000 Internal Tuner",
- .frequency_min = 950000,
- .frequency_max = 2150000,
- },
-
- .init = m88rs6000t_init,
- .sleep = m88rs6000t_sleep,
- .set_params = m88rs6000t_set_params,
- .get_frequency = m88rs6000t_get_frequency,
- .get_if_frequency = m88rs6000t_get_if_frequency,
- .get_rf_strength = m88rs6000t_get_rf_strength,
-};
-
-static int m88rs6000t_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
-{
- struct m88rs6000t_config *cfg = client->dev.platform_data;
- struct dvb_frontend *fe = cfg->fe;
- struct m88rs6000t_dev *dev;
- int ret, i;
- unsigned int utmp;
- static const struct regmap_config regmap_config = {
- .reg_bits = 8,
- .val_bits = 8,
- };
- static const struct m88rs6000t_reg_val reg_vals[] = {
- {0x10, 0xfb},
- {0x24, 0x38},
- {0x11, 0x0a},
- {0x12, 0x00},
- {0x2b, 0x1c},
- {0x44, 0x48},
- {0x54, 0x24},
- {0x55, 0x06},
- {0x59, 0x00},
- {0x5b, 0x4c},
- {0x60, 0x8b},
- {0x61, 0xf4},
- {0x65, 0x07},
- {0x6d, 0x6f},
- {0x6e, 0x31},
- {0x3c, 0xf3},
- {0x37, 0x0f},
- {0x48, 0x28},
- {0x49, 0xd8},
- {0x70, 0x66},
- {0x71, 0xCF},
- {0x72, 0x81},
- {0x73, 0xA7},
- {0x74, 0x4F},
- {0x75, 0xFC},
- };
-
- dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev) {
- ret = -ENOMEM;
- dev_err(&client->dev, "kzalloc() failed\n");
- goto err;
- }
-
- memcpy(&dev->cfg, cfg, sizeof(struct m88rs6000t_config));
- dev->client = client;
- dev->regmap = devm_regmap_init_i2c(client, ®map_config);
- if (IS_ERR(dev->regmap)) {
- ret = PTR_ERR(dev->regmap);
- goto err;
- }
-
- ret = regmap_update_bits(dev->regmap, 0x11, 0x08, 0x08);
- if (ret)
- goto err;
- usleep_range(5000, 50000);
- ret = regmap_update_bits(dev->regmap, 0x10, 0x01, 0x01);
- if (ret)
- goto err;
- usleep_range(10000, 50000);
- ret = regmap_write(dev->regmap, 0x07, 0x7d);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x04, 0x01);
- if (ret)
- goto err;
-
- /* check tuner chip id */
- ret = regmap_read(dev->regmap, 0x01, &utmp);
- if (ret)
- goto err;
- dev_info(&dev->client->dev, "chip_id=%02x\n", utmp);
- if (utmp != 0x64) {
- ret = -ENODEV;
- goto err;
- }
-
- /* tuner init. */
- ret = regmap_write(dev->regmap, 0x05, 0x40);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x11, 0x08);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x15, 0x6c);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x17, 0xc1);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x17, 0x81);
- if (ret)
- goto err;
- usleep_range(10000, 50000);
- ret = regmap_write(dev->regmap, 0x05, 0x00);
- if (ret)
- goto err;
- ret = regmap_write(dev->regmap, 0x11, 0x0a);
- if (ret)
- goto err;
-
- for (i = 0; i < ARRAY_SIZE(reg_vals); i++) {
- ret = regmap_write(dev->regmap,
- reg_vals[i].reg, reg_vals[i].val);
- if (ret)
- goto err;
- }
-
- dev_info(&dev->client->dev, "Montage M88RS6000 internal tuner successfully identified\n");
-
- fe->tuner_priv = dev;
- memcpy(&fe->ops.tuner_ops, &m88rs6000t_tuner_ops,
- sizeof(struct dvb_tuner_ops));
- i2c_set_clientdata(client, dev);
- return 0;
-err:
- dev_dbg(&client->dev, "failed=%d\n", ret);
- kfree(dev);
- return ret;
-}
-
-static int m88rs6000t_remove(struct i2c_client *client)
-{
- struct m88rs6000t_dev *dev = i2c_get_clientdata(client);
- struct dvb_frontend *fe = dev->cfg.fe;
-
- dev_dbg(&client->dev, "\n");
-
- memset(&fe->ops.tuner_ops, 0, sizeof(struct dvb_tuner_ops));
- fe->tuner_priv = NULL;
- kfree(dev);
-
- return 0;
-}
-
-static const struct i2c_device_id m88rs6000t_id[] = {
- {"m88rs6000t", 0},
- {}
-};
-MODULE_DEVICE_TABLE(i2c, m88rs6000t_id);
-
-static struct i2c_driver m88rs6000t_driver = {
- .driver = {
- .owner = THIS_MODULE,
- .name = "m88rs6000t",
- },
- .probe = m88rs6000t_probe,
- .remove = m88rs6000t_remove,
- .id_table = m88rs6000t_id,
-};
-
-module_i2c_driver(m88rs6000t_driver);
-
-MODULE_AUTHOR("Max nibble <nibble.max@gmail.com>");
-MODULE_DESCRIPTION("Montage M88RS6000 internal tuner driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/m88rs6000t.h b/drivers/media/tuners/m88rs6000t.h
deleted file mode 100644
index 264c13e..0000000
--- a/drivers/media/tuners/m88rs6000t.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Driver for the internal tuner of Montage M88RS6000
- *
- * Copyright (C) 2014 Max nibble <nibble.max@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.
- *
- * 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 _M88RS6000T_H_
-#define _M88RS6000T_H_
-
-#include "dvb_frontend.h"
-
-struct m88rs6000t_config {
- /*
- * pointer to DVB frontend
- */
- struct dvb_frontend *fe;
-};
-
-#endif
diff --git a/drivers/media/tuners/m88ts2022.c b/drivers/media/tuners/m88ts2022.c
index 066e543..caa5423 100644
--- a/drivers/media/tuners/m88ts2022.c
+++ b/drivers/media/tuners/m88ts2022.c
@@ -488,7 +488,6 @@
case 0x83:
break;
default:
- ret = -ENODEV;
goto err;
}
@@ -506,7 +505,6 @@
u8tmp = 0x6c;
break;
default:
- ret = -EINVAL;
goto err;
}
diff --git a/drivers/media/tuners/mxl5007t.c b/drivers/media/tuners/mxl5007t.c
index 1810ad6..69e453e 100644
--- a/drivers/media/tuners/mxl5007t.c
+++ b/drivers/media/tuners/mxl5007t.c
@@ -374,6 +374,7 @@
mxl5007t_set_if_freq_bits(state, cfg->if_freq_hz, cfg->invert_if);
mxl5007t_set_xtal_freq_bits(state, cfg->xtal_freq_hz);
+ set_reg_bits(state->tab_init, 0x04, 0x01, cfg->loop_thru_enable);
set_reg_bits(state->tab_init, 0x03, 0x08, cfg->clk_out_enable << 3);
set_reg_bits(state->tab_init, 0x03, 0x07, cfg->clk_out_amp);
@@ -530,6 +531,10 @@
struct reg_pair_t *init_regs;
int ret;
+ ret = mxl5007t_soft_reset(state);
+ if (mxl_fail(ret))
+ goto fail;
+
/* calculate initialization reg array */
init_regs = mxl5007t_calc_init_regs(state, mode);
@@ -895,32 +900,7 @@
/* existing tuner instance */
break;
}
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- ret = mxl5007t_soft_reset(state);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- if (mxl_fail(ret))
- goto fail;
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 1);
-
- ret = mxl5007t_write_reg(state, 0x04,
- state->config->loop_thru_enable);
-
- if (fe->ops.i2c_gate_ctrl)
- fe->ops.i2c_gate_ctrl(fe, 0);
-
- if (mxl_fail(ret))
- goto fail;
-
fe->tuner_priv = state;
-
mutex_unlock(&mxl5007t_list_mutex);
memcpy(&fe->ops.tuner_ops, &mxl5007t_tuner_ops,
diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c
index 8e040cf..a759742 100644
--- a/drivers/media/tuners/r820t.c
+++ b/drivers/media/tuners/r820t.c
@@ -959,18 +959,6 @@
lt_att = 0x00; /* r31[7], lt att enable */
flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
polyfil_cur = 0x60; /* r25[6:5]:min */
- } else if (delsys == SYS_DVBC_ANNEX_A) {
- if_khz = 5070;
- filt_cal_lo = 73500;
- filt_gain = 0x10; /* +3db, 6mhz on */
- img_r = 0x00; /* image negative */
- filt_q = 0x10; /* r10[4]:low q(1'b1) */
- hp_cor = 0x0b; /* 1.7m disable, +0cap, 1.0mhz */
- ext_enable = 0x40; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */
- loop_through = 0x00; /* r5[7], lt on */
- lt_att = 0x00; /* r31[7], lt att enable */
- flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */
- polyfil_cur = 0x60; /* r25[6:5]:min */
} else {
if (bw <= 6) {
if_khz = 3570;
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index 2180de9..cf97142 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -1,5 +1,5 @@
/*
- * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
+ * Silicon Labs Si2147/2157/2158 silicon tuner driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
@@ -93,13 +93,8 @@
goto warm;
/* power up */
- if (s->chiptype == SI2157_CHIPTYPE_SI2146) {
- memcpy(cmd.args, "\xc0\x05\x01\x00\x00\x0b\x00\x00\x01", 9);
- cmd.wlen = 9;
- } else {
- memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
- cmd.wlen = 15;
- }
+ memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
+ cmd.wlen = 15;
cmd.rlen = 1;
ret = si2157_cmd_execute(s, &cmd);
if (ret)
@@ -117,20 +112,17 @@
cmd.args[4] << 0;
#define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
- #define SI2148_A20 ('A' << 24 | 48 << 16 | '2' << 8 | '0' << 0)
#define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
#define SI2147_A30 ('A' << 24 | 47 << 16 | '3' << 8 | '0' << 0)
- #define SI2146_A10 ('A' << 24 | 46 << 16 | '1' << 8 | '0' << 0)
switch (chip_id) {
case SI2158_A20:
- case SI2148_A20:
fw_file = SI2158_A20_FIRMWARE;
break;
case SI2157_A30:
case SI2147_A30:
- case SI2146_A10:
goto skip_fw_download;
+ break;
default:
dev_err(&s->client->dev,
"unknown chip version Si21%d-%c%c%c\n",
@@ -157,7 +149,7 @@
dev_err(&s->client->dev, "firmware file '%s' is invalid\n",
fw_file);
ret = -EINVAL;
- goto fw_release_exit;
+ goto err;
}
dev_info(&s->client->dev, "downloading firmware from file '%s'\n",
@@ -173,7 +165,7 @@
dev_err(&s->client->dev,
"firmware download failed=%d\n",
ret);
- goto fw_release_exit;
+ goto err;
}
}
@@ -195,9 +187,10 @@
s->active = true;
return 0;
-fw_release_exit:
- release_firmware(fw);
err:
+ if (fw)
+ release_firmware(fw);
+
dev_dbg(&s->client->dev, "failed=%d\n", ret);
return ret;
}
@@ -257,9 +250,6 @@
case SYS_ATSC:
delivery_system = 0x00;
break;
- case SYS_DVBC_ANNEX_B:
- delivery_system = 0x10;
- break;
case SYS_DVBT:
case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
delivery_system = 0x20;
@@ -282,10 +272,7 @@
if (ret)
goto err;
- if (s->chiptype == SI2157_CHIPTYPE_SI2146)
- memcpy(cmd.args, "\x14\x00\x02\x07\x00\x01", 6);
- else
- memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6);
+ memcpy(cmd.args, "\x14\x00\x02\x07\x01\x00", 6);
cmd.wlen = 6;
cmd.rlen = 4;
ret = si2157_cmd_execute(s, &cmd);
@@ -318,7 +305,7 @@
static const struct dvb_tuner_ops si2157_ops = {
.info = {
- .name = "Silicon Labs Si2146/2147/2148/2157/2158",
+ .name = "Silicon Labs Si2157/Si2158",
.frequency_min = 110000000,
.frequency_max = 862000000,
},
@@ -349,7 +336,6 @@
s->fe = cfg->fe;
s->inversion = cfg->inversion;
s->fw_loaded = false;
- s->chiptype = (u8)id->driver_data;
mutex_init(&s->i2c_mutex);
/* check if the tuner is there */
@@ -366,10 +352,7 @@
i2c_set_clientdata(client, s);
dev_info(&s->client->dev,
- "Silicon Labs %s successfully attached\n",
- s->chiptype == SI2157_CHIPTYPE_SI2146 ?
- "Si2146" : "Si2147/2148/2157/2158");
-
+ "Silicon Labs Si2157/Si2158 successfully attached\n");
return 0;
err:
dev_dbg(&client->dev, "failed=%d\n", ret);
@@ -394,7 +377,6 @@
static const struct i2c_device_id si2157_id[] = {
{"si2157", 0},
- {"si2146", 1},
{}
};
MODULE_DEVICE_TABLE(i2c, si2157_id);
@@ -411,7 +393,7 @@
module_i2c_driver(si2157_driver);
-MODULE_DESCRIPTION("Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver");
+MODULE_DESCRIPTION("Silicon Labs Si2157/Si2158 silicon tuner driver");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_LICENSE("GPL");
MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
diff --git a/drivers/media/tuners/si2157.h b/drivers/media/tuners/si2157.h
index a564c4a..d3b19ca 100644
--- a/drivers/media/tuners/si2157.h
+++ b/drivers/media/tuners/si2157.h
@@ -1,5 +1,5 @@
/*
- * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
+ * Silicon Labs Si2147/2157/2158 silicon tuner driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h
index d6e07cd..e71ffaf 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -1,5 +1,5 @@
/*
- * Silicon Labs Si2146/2147/2148/2157/2158 silicon tuner driver
+ * Silicon Labs Si2147/2157/2158 silicon tuner driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
@@ -28,13 +28,9 @@
bool active;
bool fw_loaded;
bool inversion;
- u8 chiptype;
};
-#define SI2157_CHIPTYPE_SI2157 0
-#define SI2157_CHIPTYPE_SI2146 1
-
-/* firmware command struct */
+/* firmare command struct */
#define SI2157_ARGLEN 30
struct si2157_cmd {
u8 args[SI2157_ARGLEN];
diff --git a/drivers/media/tuners/tda18271-common.c b/drivers/media/tuners/tda18271-common.c
index a26bb33..86e5e31 100644
--- a/drivers/media/tuners/tda18271-common.c
+++ b/drivers/media/tuners/tda18271-common.c
@@ -178,7 +178,7 @@
(i != R_EB17) &&
(i != R_EB19) &&
(i != R_EB20))
- regs[i] = regdump[i];
+ regs[i] = regdump[i];
}
if (tda18271_debug & DBG_REG)
diff --git a/drivers/media/tuners/xc5000.c b/drivers/media/tuners/xc5000.c
index 2a039de..e44c8ab 100644
--- a/drivers/media/tuners/xc5000.c
+++ b/drivers/media/tuners/xc5000.c
@@ -62,7 +62,6 @@
unsigned int mode;
u8 rf_mode;
u8 radio_input;
- u16 output_amp;
int chip_id;
u16 pll_register_no;
@@ -745,9 +744,7 @@
return -EIO;
}
- dprintk(1, "%s() setting OUTPUT_AMP to 0x%x\n",
- __func__, priv->output_amp);
- xc_write_reg(priv, XREG_OUTPUT_AMP, priv->output_amp);
+ xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a);
xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
@@ -1336,8 +1333,9 @@
if (priv) {
cancel_delayed_work(&priv->timer_sleep);
- release_firmware(priv->firmware);
hybrid_tuner_release_state(priv);
+ if (priv->firmware)
+ release_firmware(priv->firmware);
}
mutex_unlock(&xc5000_list_mutex);
@@ -1360,9 +1358,6 @@
if (p->radio_input)
priv->radio_input = p->radio_input;
- if (p->output_amp)
- priv->output_amp = p->output_amp;
-
return 0;
}
@@ -1443,12 +1438,6 @@
it can be overridden if this is a hybrid driver */
priv->chip_id = (cfg->chip_id) ? cfg->chip_id : 0;
- /* don't override output_amp if it's already been set
- unless explicitly specified */
- if ((priv->output_amp == 0) || (cfg->output_amp))
- /* use default output_amp value if none specified */
- priv->output_amp = (cfg->output_amp) ? cfg->output_amp : 0x8a;
-
/* Check if firmware has been loaded. It is possible that another
instance of the driver has loaded the firmware.
*/
diff --git a/drivers/media/tuners/xc5000.h b/drivers/media/tuners/xc5000.h
index d3ffe4b..38ff591 100644
--- a/drivers/media/tuners/xc5000.h
+++ b/drivers/media/tuners/xc5000.h
@@ -36,7 +36,6 @@
u32 if_khz;
u8 radio_input;
u16 xtal_khz;
- u16 output_amp;
int chip_id;
};
diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig
index 7496f33..056181f 100644
--- a/drivers/media/usb/Kconfig
+++ b/drivers/media/usb/Kconfig
@@ -24,6 +24,7 @@
comment "Analog TV USB devices"
source "drivers/media/usb/pvrusb2/Kconfig"
source "drivers/media/usb/hdpvr/Kconfig"
+source "drivers/media/usb/tlg2300/Kconfig"
source "drivers/media/usb/usbvision/Kconfig"
source "drivers/media/usb/stk1160/Kconfig"
source "drivers/media/usb/go7007/Kconfig"
diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile
index 920c1ed..417760e 100644
--- a/drivers/media/usb/Makefile
+++ b/drivers/media/usb/Makefile
@@ -16,6 +16,7 @@
obj-$(CPTCFG_VIDEO_AU0828) += au0828/
obj-$(CPTCFG_VIDEO_HDPVR) += hdpvr/
obj-$(CPTCFG_VIDEO_PVRUSB2) += pvrusb2/
+obj-$(CPTCFG_VIDEO_TLG2300) += tlg2300/
obj-$(CPTCFG_VIDEO_USBVISION) += usbvision/
obj-$(CPTCFG_VIDEO_STK1160) += stk1160/
obj-$(CPTCFG_VIDEO_CX231XX) += cx231xx/
diff --git a/drivers/media/usb/au0828/au0828-cards.c b/drivers/media/usb/au0828/au0828-cards.c
index b52f470..6c164d9 100644
--- a/drivers/media/usb/au0828/au0828-cards.c
+++ b/drivers/media/usb/au0828/au0828-cards.c
@@ -36,11 +36,6 @@
au0828_clear(dev, REG_000, 0x10);
}
-/*
- * WARNING: There's a quirks table at sound/usb/quirks-table.h
- * that should also be updated every time a new device with V4L2 support
- * is added here.
- */
struct au0828_board au0828_boards[] = {
[AU0828_BOARD_UNKNOWN] = {
.name = "Unknown board",
diff --git a/drivers/media/usb/au0828/au0828-core.c b/drivers/media/usb/au0828/au0828-core.c
index 73b6093..c697199 100644
--- a/drivers/media/usb/au0828/au0828-core.c
+++ b/drivers/media/usb/au0828/au0828-core.c
@@ -153,14 +153,6 @@
dprintk(1, "%s()\n", __func__);
- /* there is a small window after disconnect, before
- dev->usbdev is NULL, for poll (e.g: IR) try to access
- the device and fill the dmesg with error messages.
- Set the status so poll routines can check and avoid
- access after disconnect.
- */
- dev->dev_state = DEV_DISCONNECTED;
-
au0828_rc_unregister(dev);
/* Digital TV */
au0828_dvb_unregister(dev);
diff --git a/drivers/media/usb/au0828/au0828-dvb.c b/drivers/media/usb/au0828/au0828-dvb.c
index c267d76..00ab156 100644
--- a/drivers/media/usb/au0828/au0828-dvb.c
+++ b/drivers/media/usb/au0828/au0828-dvb.c
@@ -88,14 +88,12 @@
.i2c_address = 0x61,
.if_khz = 6000,
.chip_id = XC5000A,
- .output_amp = 0x8f,
};
static struct xc5000_config hauppauge_xc5000c_config = {
.i2c_address = 0x61,
.if_khz = 6000,
.chip_id = XC5000C,
- .output_amp = 0x8f,
};
static struct mxl5007t_config mxl5007t_hvr950q_config = {
diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c
index b0f0679..63995f9 100644
--- a/drivers/media/usb/au0828/au0828-input.c
+++ b/drivers/media/usb/au0828/au0828-input.c
@@ -129,10 +129,6 @@
int prv_bit, bit, width;
bool first = true;
- /* do nothing if device is disconnected */
- if (ir->dev->dev_state == DEV_DISCONNECTED)
- return 0;
-
/* Check IR int */
rc = au8522_rc_read(ir, 0xe1, -1, buf, 1);
if (rc < 0 || !(buf[0] & (1 << 4))) {
@@ -259,11 +255,8 @@
cancel_delayed_work_sync(&ir->work);
- /* do nothing if device is disconnected */
- if (ir->dev->dev_state != DEV_DISCONNECTED) {
- /* Disable IR */
- au8522_rc_clear(ir, 0xe0, 1 << 4);
- }
+ /* Disable IR */
+ au8522_rc_clear(ir, 0xe0, 1 << 4);
}
static int au0828_probe_i2c_ir(struct au0828_dev *dev)
@@ -370,7 +363,8 @@
if (!ir)
return;
- rc_unregister_device(ir->rc);
+ if (ir->rc)
+ rc_unregister_device(ir->rc);
/* done */
kfree(ir);
diff --git a/drivers/media/usb/cx231xx/Kconfig b/drivers/media/usb/cx231xx/Kconfig
index 0d1ff87..47209ab 100644
--- a/drivers/media/usb/cx231xx/Kconfig
+++ b/drivers/media/usb/cx231xx/Kconfig
@@ -8,7 +8,6 @@
select VIDEOBUF_VMALLOC
select VIDEO_CX25840
select VIDEO_CX2341X
- depends on I2C_MUX
---help---
This is a video4linux driver for Conexant 231xx USB based TV cards.
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
index 64f345d..6afc620 100644
--- a/drivers/media/usb/cx231xx/cx231xx-417.c
+++ b/drivers/media/usb/cx231xx/cx231xx-417.c
@@ -24,8 +24,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "cx231xx.h"
-
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -39,6 +37,9 @@
#include <media/v4l2-event.h>
#include <media/cx2341x.h>
#include <media/tuner.h>
+#include <linux/usb.h>
+
+#include "cx231xx.h"
#define CX231xx_FIRM_IMAGE_SIZE 376836
#define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
@@ -89,10 +90,10 @@
module_param(v4l_debug, int, 0644);
MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
-#define dprintk(level, fmt, arg...) \
- do { \
- if (v4l_debug >= level) \
- printk(KERN_DEBUG pr_fmt(fmt), ## arg); \
+#define dprintk(level, fmt, arg...)\
+ do { if (v4l_debug >= level) \
+ pr_info("%s: " fmt, \
+ (dev) ? dev->name : "cx231xx[?]", ## arg); \
} while (0)
static struct cx231xx_tvnorm cx231xx_tvnorms[] = {
@@ -987,34 +988,29 @@
IVTV_REG_APU, 0);
if (retval != 0) {
- dev_err(dev->dev,
- "%s: Error with mc417_register_write\n", __func__);
+ pr_err("%s: Error with mc417_register_write\n", __func__);
return -1;
}
retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME,
- dev->dev);
+ &dev->udev->dev);
if (retval != 0) {
- dev_err(dev->dev,
- "ERROR: Hotplug firmware request failed (%s).\n",
+ pr_err("ERROR: Hotplug firmware request failed (%s).\n",
CX231xx_FIRM_IMAGE_NAME);
- dev_err(dev->dev,
- "Please fix your hotplug setup, the board will not work without firmware loaded!\n");
+ pr_err("Please fix your hotplug setup, the board will not work without firmware loaded!\n");
return -1;
}
if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) {
- dev_err(dev->dev,
- "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
+ pr_err("ERROR: Firmware size mismatch (have %zd, expected %d)\n",
firmware->size, CX231xx_FIRM_IMAGE_SIZE);
release_firmware(firmware);
return -1;
}
if (0 != memcmp(firmware->data, magic, 8)) {
- dev_err(dev->dev,
- "ERROR: Firmware magic mismatch, wrong file?\n");
+ pr_err("ERROR: Firmware magic mismatch, wrong file?\n");
release_firmware(firmware);
return -1;
}
@@ -1061,8 +1057,7 @@
retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
IVTV_CMD_HW_BLOCKS_RST);
if (retval < 0) {
- dev_err(dev->dev,
- "%s: Error with mc417_register_write\n",
+ pr_err("%s: Error with mc417_register_write\n",
__func__);
return retval;
}
@@ -1074,8 +1069,7 @@
retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
if (retval < 0) {
- dev_err(dev->dev,
- "%s: Error with mc417_register_write\n",
+ pr_err("%s: Error with mc417_register_write\n",
__func__);
return retval;
}
@@ -1120,31 +1114,28 @@
cx231xx_disable656(dev);
retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
if (retval < 0) {
- dprintk(2, "%s: PING OK\n", __func__);
+ dprintk(2, "%s() PING OK\n", __func__);
retval = cx231xx_load_firmware(dev);
if (retval < 0) {
- dev_err(dev->dev,
- "%s: f/w load failed\n", __func__);
+ pr_err("%s() f/w load failed\n", __func__);
return retval;
}
retval = cx231xx_find_mailbox(dev);
if (retval < 0) {
- dev_err(dev->dev, "%s: mailbox < 0, error\n",
+ pr_err("%s() mailbox < 0, error\n",
__func__);
return -1;
}
dev->cx23417_mailbox = retval;
retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
if (retval < 0) {
- dev_err(dev->dev,
- "ERROR: cx23417 firmware ping failed!\n");
+ pr_err("ERROR: cx23417 firmware ping failed!\n");
return -1;
}
retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
&version);
if (retval < 0) {
- dev_err(dev->dev,
- "ERROR: cx23417 firmware get encoder: version failed!\n");
+ pr_err("ERROR: cx23417 firmware get encoder: version failed!\n");
return -1;
}
dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
@@ -1425,9 +1416,8 @@
if (!dev->video_mode.bulk_ctl.num_bufs)
urb_init = 1;
}
- dev_dbg(dev->dev,
- "urb_init=%d dev->video_mode.max_pkt_size=%d\n",
- urb_init, dev->video_mode.max_pkt_size);
+ /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
+ urb_init, dev->video_mode.max_pkt_size);*/
dev->mode_tv = 1;
if (urb_init) {
@@ -1698,7 +1688,7 @@
sizeof(struct cx231xx_buffer), fh, &dev->lock);
/*
videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops,
- dev->dev, &dev->ts1.slock,
+ &dev->udev->dev, &dev->ts1.slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
sizeof(struct cx231xx_buffer),
@@ -1808,6 +1798,7 @@
static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
{
struct cx231xx_fh *fh = file->private_data;
+ struct cx231xx *dev = fh->dev;
dprintk(2, "%s()\n", __func__);
@@ -1887,7 +1878,7 @@
/* fix videodecoder resolution */
fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
fmt.height = cxhdl->height;
- fmt.code = MEDIA_BUS_FMT_FIXED;
+ fmt.code = V4L2_MBUS_FMT_FIXED;
v4l2_subdev_call(dev->sd_cx25840, video, s_mbus_fmt, &fmt);
return 0;
}
diff --git a/drivers/media/usb/cx231xx/cx231xx-audio.c b/drivers/media/usb/cx231xx/cx231xx-audio.c
index de4ae5e..9b92587 100644
--- a/drivers/media/usb/cx231xx/cx231xx-audio.c
+++ b/drivers/media/usb/cx231xx/cx231xx-audio.c
@@ -20,8 +20,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "cx231xx.h"
#include <linux/kernel.h>
+#include <linux/usb.h>
#include <linux/init.h>
#include <linux/sound.h>
#include <linux/spinlock.h>
@@ -37,18 +37,25 @@
#include <sound/initval.h>
#include <sound/control.h>
#include <media/v4l2-common.h>
+#include "cx231xx.h"
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "activates debug info");
+#define dprintk(fmt, arg...) do { \
+ if (debug) \
+ printk(KERN_INFO "cx231xx-audio %s: " fmt, \
+ __func__, ##arg); \
+ } while (0)
+
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static int cx231xx_isoc_audio_deinit(struct cx231xx *dev)
{
int i;
- dev_dbg(dev->dev, "Stopping isoc\n");
+ dprintk("Stopping isoc\n");
for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
if (dev->adev.urb[i]) {
@@ -72,7 +79,7 @@
{
int i;
- dev_dbg(dev->dev, "Stopping bulk\n");
+ dprintk("Stopping bulk\n");
for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
if (dev->adev.urb[i]) {
@@ -116,8 +123,7 @@
case -ESHUTDOWN:
return;
default: /* error */
- dev_dbg(dev->dev, "urb completition error %d.\n",
- urb->status);
+ dprintk("urb completition error %d.\n", urb->status);
break;
}
@@ -176,9 +182,8 @@
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status < 0) {
- dev_err(dev->dev,
- "resubmit of audio urb failed (error=%i)\n",
- status);
+ cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
+ status);
}
return;
}
@@ -206,8 +211,7 @@
case -ESHUTDOWN:
return;
default: /* error */
- dev_dbg(dev->dev, "urb completition error %d.\n",
- urb->status);
+ dprintk("urb completition error %d.\n", urb->status);
break;
}
@@ -262,9 +266,8 @@
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status < 0) {
- dev_err(dev->dev,
- "resubmit of audio urb failed (error=%i)\n",
- status);
+ cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
+ status);
}
return;
}
@@ -274,8 +277,7 @@
int i, errCode;
int sb_size;
- dev_dbg(dev->dev,
- "%s: Starting ISO AUDIO transfers\n", __func__);
+ cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__);
if (dev->state & DEV_DISCONNECTED)
return -ENODEV;
@@ -293,7 +295,7 @@
memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC);
if (!urb) {
- dev_err(dev->dev, "usb_alloc_urb failed!\n");
+ cx231xx_errdev("usb_alloc_urb failed!\n");
for (j = 0; j < i; j++) {
usb_free_urb(dev->adev.urb[j]);
kfree(dev->adev.transfer_buffer[j]);
@@ -336,8 +338,7 @@
int i, errCode;
int sb_size;
- dev_dbg(dev->dev,
- "%s: Starting BULK AUDIO transfers\n", __func__);
+ cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__);
if (dev->state & DEV_DISCONNECTED)
return -ENODEV;
@@ -355,7 +356,7 @@
memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
if (!urb) {
- dev_err(dev->dev, "usb_alloc_urb failed!\n");
+ cx231xx_errdev("usb_alloc_urb failed!\n");
for (j = 0; j < i; j++) {
usb_free_urb(dev->adev.urb[j]);
kfree(dev->adev.transfer_buffer[j]);
@@ -391,9 +392,8 @@
size_t size)
{
struct snd_pcm_runtime *runtime = subs->runtime;
- struct cx231xx *dev = snd_pcm_substream_chip(subs);
- dev_dbg(dev->dev, "Allocating vbuffer\n");
+ dprintk("Allocating vbuffer\n");
if (runtime->dma_area) {
if (runtime->dma_bytes > size)
return 0;
@@ -436,12 +436,16 @@
struct snd_pcm_runtime *runtime = substream->runtime;
int ret = 0;
- dev_dbg(dev->dev,
- "opening device and trying to acquire exclusive lock\n");
+ dprintk("opening device and trying to acquire exclusive lock\n");
+
+ if (!dev) {
+ cx231xx_errdev("BUG: cx231xx can't find device struct."
+ " Can't proceed with open\n");
+ return -ENODEV;
+ }
if (dev->state & DEV_DISCONNECTED) {
- dev_err(dev->dev,
- "Can't open. the device was removed.\n");
+ cx231xx_errdev("Can't open. the device was removed.\n");
return -ENODEV;
}
@@ -454,8 +458,7 @@
ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
mutex_unlock(&dev->lock);
if (ret < 0) {
- dev_err(dev->dev,
- "failed to set alternate setting !\n");
+ cx231xx_errdev("failed to set alternate setting !\n");
return ret;
}
@@ -481,7 +484,7 @@
int ret;
struct cx231xx *dev = snd_pcm_substream_chip(substream);
- dev_dbg(dev->dev, "closing device\n");
+ dprintk("closing device\n");
/* inform hardware to stop streaming */
mutex_lock(&dev->lock);
@@ -491,8 +494,7 @@
/* 1 - 48000 samples per sec */
ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
if (ret < 0) {
- dev_err(dev->dev,
- "failed to set alternate setting !\n");
+ cx231xx_errdev("failed to set alternate setting !\n");
mutex_unlock(&dev->lock);
return ret;
@@ -502,10 +504,10 @@
mutex_unlock(&dev->lock);
if (dev->adev.users == 0 && dev->adev.shutdown == 1) {
- dev_dbg(dev->dev, "audio users: %d\n", dev->adev.users);
- dev_dbg(dev->dev, "disabling audio stream!\n");
+ dprintk("audio users: %d\n", dev->adev.users);
+ dprintk("disabling audio stream!\n");
dev->adev.shutdown = 0;
- dev_dbg(dev->dev, "released lock\n");
+ dprintk("released lock\n");
if (atomic_read(&dev->stream_started) > 0) {
atomic_set(&dev->stream_started, 0);
schedule_work(&dev->wq_trigger);
@@ -517,10 +519,9 @@
static int snd_cx231xx_hw_capture_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
- struct cx231xx *dev = snd_pcm_substream_chip(substream);
int ret;
- dev_dbg(dev->dev, "Setting capture parameters\n");
+ dprintk("Setting capture parameters\n");
ret = snd_pcm_alloc_vmalloc_buffer(substream,
params_buffer_bytes(hw_params));
@@ -542,7 +543,7 @@
{
struct cx231xx *dev = snd_pcm_substream_chip(substream);
- dev_dbg(dev->dev, "Stop capture, if needed\n");
+ dprintk("Stop capture, if needed\n");
if (atomic_read(&dev->stream_started) > 0) {
atomic_set(&dev->stream_started, 0);
@@ -567,7 +568,7 @@
struct cx231xx *dev = container_of(work, struct cx231xx, wq_trigger);
if (atomic_read(&dev->stream_started)) {
- dev_dbg(dev->dev, "starting capture");
+ dprintk("starting capture");
if (is_fw_load(dev) == 0)
cx25840_call(dev, core, load_fw);
if (dev->USE_ISO)
@@ -575,7 +576,7 @@
else
cx231xx_init_audio_bulk(dev);
} else {
- dev_dbg(dev->dev, "stopping capture");
+ dprintk("stopping capture");
cx231xx_isoc_audio_deinit(dev);
}
}
@@ -661,10 +662,10 @@
return 0;
}
- dev_dbg(dev->dev,
- "probing for cx231xx non standard usbaudio\n");
+ cx231xx_info("cx231xx-audio.c: probing for cx231xx "
+ "non standard usbaudio\n");
- err = snd_card_new(dev->dev, index[devnr], "Cx231xx Audio",
+ err = snd_card_new(&dev->udev->dev, index[devnr], "Cx231xx Audio",
THIS_MODULE, 0, &card);
if (err < 0)
return err;
@@ -706,13 +707,14 @@
bEndpointAddress;
adev->num_alt = uif->num_altsetting;
- dev_info(dev->dev,
- "audio EndPoint Addr 0x%x, Alternate settings: %i\n",
- adev->end_point_addr, adev->num_alt);
+ cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+ adev->end_point_addr, adev->num_alt);
adev->alt_max_pkt_size = kmalloc(32 * adev->num_alt, GFP_KERNEL);
- if (adev->alt_max_pkt_size == NULL)
+ if (adev->alt_max_pkt_size == NULL) {
+ cx231xx_errdev("out of memory!\n");
return -ENOMEM;
+ }
for (i = 0; i < adev->num_alt; i++) {
u16 tmp =
@@ -720,9 +722,8 @@
wMaxPacketSize);
adev->alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- dev_dbg(dev->dev,
- "audio alternate setting %i, max size= %i\n", i,
- adev->alt_max_pkt_size[i]);
+ cx231xx_info("Alternate setting %i, max size= %i\n", i,
+ adev->alt_max_pkt_size[i]);
}
return 0;
diff --git a/drivers/media/usb/cx231xx/cx231xx-avcore.c b/drivers/media/usb/cx231xx/cx231xx-avcore.c
index 39e8879..40a6987 100644
--- a/drivers/media/usb/cx231xx/cx231xx-avcore.c
+++ b/drivers/media/usb/cx231xx/cx231xx-avcore.c
@@ -22,12 +22,12 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "cx231xx.h"
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/bitmap.h>
+#include <linux/usb.h>
#include <linux/i2c.h>
#include <linux/mm.h>
#include <linux/mutex.h>
@@ -36,6 +36,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
+#include "cx231xx.h"
#include "cx231xx-dif.h"
#define TUNER_MODE_FM_RADIO 0
@@ -82,10 +83,10 @@
cx231xx_send_gpio_cmd(dev, _gpio_direction, (u8 *)&value, 4, 0, 0);
verve_read_byte(dev, 0x07, &val);
- dev_dbg(dev->dev, "verve_read_byte address0x07=0x%x\n", val);
+ cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
verve_write_byte(dev, 0x07, 0xF4);
verve_read_byte(dev, 0x07, &val);
- dev_dbg(dev->dev, "verve_read_byte address0x07=0x%x\n", val);
+ cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
cx231xx_capture_start(dev, 1, Vbi);
@@ -155,25 +156,22 @@
while (afe_power_status != 0x18) {
status = afe_write_byte(dev, SUP_BLK_PWRDN, 0x18);
if (status < 0) {
- dev_dbg(dev->dev,
- "%s: Init Super Block failed in send cmd\n",
- __func__);
+ cx231xx_info(
+ ": Init Super Block failed in send cmd\n");
break;
}
status = afe_read_byte(dev, SUP_BLK_PWRDN, &afe_power_status);
afe_power_status &= 0xff;
if (status < 0) {
- dev_dbg(dev->dev,
- "%s: Init Super Block failed in receive cmd\n",
- __func__);
+ cx231xx_info(
+ ": Init Super Block failed in receive cmd\n");
break;
}
i++;
if (i == 10) {
- dev_dbg(dev->dev,
- "%s: Init Super Block force break in loop !!!!\n",
- __func__);
+ cx231xx_info(
+ ": Init Super Block force break in loop !!!!\n");
status = -1;
break;
}
@@ -412,7 +410,7 @@
status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
0x00);
} else {
- dev_dbg(dev->dev, "Invalid AV mode input\n");
+ cx231xx_info("Invalid AV mode input\n");
status = -1;
}
break;
@@ -469,7 +467,7 @@
status |= afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3,
0x40);
} else {
- dev_dbg(dev->dev, "Invalid AV mode input\n");
+ cx231xx_info("Invalid AV mode input\n");
status = -1;
}
} /* switch */
@@ -575,9 +573,9 @@
status = cx231xx_set_power_mode(dev,
POLARIS_AVMODE_ENXTERNAL_AV);
if (status < 0) {
- dev_err(dev->dev,
- "%s: Failed to set Power - errCode [%d]!\n",
- __func__, status);
+ cx231xx_errdev("%s: set_power_mode : Failed to"
+ " set Power - errCode [%d]!\n",
+ __func__, status);
return status;
}
}
@@ -593,8 +591,8 @@
status = cx231xx_set_power_mode(dev,
POLARIS_AVMODE_ANALOGT_TV);
if (status < 0) {
- dev_err(dev->dev,
- "%s: Failed to set Power - errCode [%d]!\n",
+ cx231xx_errdev("%s: set_power_mode:Failed"
+ " to set Power - errCode [%d]!\n",
__func__, status);
return status;
}
@@ -610,8 +608,8 @@
break;
default:
- dev_err(dev->dev, "%s: Unknown Input %d !\n",
- __func__, INPUT(input)->type);
+ cx231xx_errdev("%s: set_power_mode : Unknown Input %d !\n",
+ __func__, INPUT(input)->type);
break;
}
@@ -630,8 +628,8 @@
if (pin_type != dev->video_input) {
status = cx231xx_afe_adjust_ref_count(dev, pin_type);
if (status < 0) {
- dev_err(dev->dev,
- "%s: adjust_ref_count :Failed to set AFE input mux - errCode [%d]!\n",
+ cx231xx_errdev("%s: adjust_ref_count :Failed to set"
+ "AFE input mux - errCode [%d]!\n",
__func__, status);
return status;
}
@@ -640,9 +638,9 @@
/* call afe block to set video inputs */
status = cx231xx_afe_set_input_mux(dev, input);
if (status < 0) {
- dev_err(dev->dev,
- "%s: set_input_mux :Failed to set AFE input mux - errCode [%d]!\n",
- __func__, status);
+ cx231xx_errdev("%s: set_input_mux :Failed to set"
+ " AFE input mux - errCode [%d]!\n",
+ __func__, status);
return status;
}
@@ -672,8 +670,8 @@
/* Tell DIF object to go to baseband mode */
status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
if (status < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_dif set to By pass mode- errCode [%d]!\n",
+ cx231xx_errdev("%s: cx231xx_dif set to By pass"
+ " mode- errCode [%d]!\n",
__func__, status);
return status;
}
@@ -717,8 +715,8 @@
/* Tell DIF object to go to baseband mode */
status = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
if (status < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_dif set to By pass mode- errCode [%d]!\n",
+ cx231xx_errdev("%s: cx231xx_dif set to By pass"
+ " mode- errCode [%d]!\n",
__func__, status);
return status;
}
@@ -792,9 +790,9 @@
status = cx231xx_dif_set_standard(dev,
DIF_USE_BASEBAND);
if (status < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_dif set to By pass mode- errCode [%d]!\n",
- __func__, status);
+ cx231xx_errdev("%s: cx231xx_dif set to By pass"
+ " mode- errCode [%d]!\n",
+ __func__, status);
return status;
}
@@ -828,9 +826,9 @@
/* Reinitialize the DIF */
status = cx231xx_dif_set_standard(dev, dev->norm);
if (status < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_dif set to By pass mode- errCode [%d]!\n",
- __func__, status);
+ cx231xx_errdev("%s: cx231xx_dif set to By pass"
+ " mode- errCode [%d]!\n",
+ __func__, status);
return status;
}
@@ -972,14 +970,14 @@
{
int status = 0;
- dev_dbg(dev->dev, "%s: 0x%x\n",
- __func__, (unsigned int)dev->norm);
+ cx231xx_info("do_mode_ctrl_overrides : 0x%x\n",
+ (unsigned int)dev->norm);
/* Change the DFE_CTRL3 bp_percent to fix flagging */
status = vid_blk_write_word(dev, DFE_CTRL3, 0xCD3F0280);
if (dev->norm & (V4L2_STD_NTSC | V4L2_STD_PAL_M)) {
- dev_dbg(dev->dev, "%s: NTSC\n", __func__);
+ cx231xx_info("do_mode_ctrl_overrides NTSC\n");
/* Move the close caption lines out of active video,
adjust the active video start point */
@@ -1006,7 +1004,7 @@
(FLD_HBLANK_CNT, 0x79));
} else if (dev->norm & V4L2_STD_SECAM) {
- dev_dbg(dev->dev, "%s: SECAM\n", __func__);
+ cx231xx_info("do_mode_ctrl_overrides SECAM\n");
status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS,
VERT_TIM_CTRL,
@@ -1033,7 +1031,7 @@
cx231xx_set_field
(FLD_HBLANK_CNT, 0x85));
} else {
- dev_dbg(dev->dev, "%s: PAL\n", __func__);
+ cx231xx_info("do_mode_ctrl_overrides PAL\n");
status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS,
VERT_TIM_CTRL,
@@ -1208,8 +1206,7 @@
/* This is just a casual suggestion to people adding
new boards in case they use a tuner type we don't
currently know about */
- dev_info(dev->dev,
- "Unknown tuner type configuring SIF");
+ printk(KERN_INFO "Unknown tuner type configuring SIF");
break;
}
break;
@@ -1273,13 +1270,8 @@
int status = 0;
bool current_is_port_3;
- /*
- * Should this code check dev->port_3_switch_enabled first
- * to skip unnecessary reading of the register?
- * If yes, the flag dev->port_3_switch_enabled must be initialized
- * correctly.
- */
-
+ if (dev->board.dont_use_port_3)
+ is_port_3 = false;
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
PWR_CTL_EN, value, 4);
if (status < 0)
@@ -1296,13 +1288,12 @@
else
value[0] &= ~I2C_DEMOD_EN;
+ cx231xx_info("Changing the i2c master port to %d\n",
+ is_port_3 ? 3 : 1);
+
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
PWR_CTL_EN, value, 4);
- /* remember status of the switch for usage in is_tuner */
- if (status >= 0)
- dev->port_3_switch_enabled = is_port_3;
-
return status;
}
@@ -1334,131 +1325,113 @@
for (i = 0x100; i < 0x140; i++) {
vid_blk_read_word(dev, i, &value);
- dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value);
+ cx231xx_info("reg0x%x=0x%x\n", i, value);
i = i+3;
}
for (i = 0x300; i < 0x400; i++) {
vid_blk_read_word(dev, i, &value);
- dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value);
+ cx231xx_info("reg0x%x=0x%x\n", i, value);
i = i+3;
}
for (i = 0x400; i < 0x440; i++) {
vid_blk_read_word(dev, i, &value);
- dev_dbg(dev->dev, "reg0x%x=0x%x\n", i, value);
+ cx231xx_info("reg0x%x=0x%x\n", i, value);
i = i+3;
}
vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
- dev_dbg(dev->dev, "AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
+ cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390);
vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
- dev_dbg(dev->dev, "AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
+ cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
}
-#if 0
-static void cx231xx_dump_SC_reg(struct cx231xx *dev)
+void cx231xx_dump_SC_reg(struct cx231xx *dev)
{
u8 value[4] = { 0, 0, 0, 0 };
- dev_dbg(dev->dev, "%s!\n", __func__);
+ cx231xx_info("cx231xx_dump_SC_reg!\n");
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", BOARD_CFG_STAT, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", BOARD_CFG_STAT, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS_MODE_REG,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS_MODE_REG, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS_MODE_REG, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_CFG_REG,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_CFG_REG, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_CFG_REG, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_LENGTH_REG,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_LENGTH_REG, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_LENGTH_REG, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_CFG_REG,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_CFG_REG, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_CFG_REG, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_LENGTH_REG,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_LENGTH_REG, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_LENGTH_REG, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", EP_MODE_SET, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", EP_MODE_SET, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN1,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN1, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN1, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN2,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN2, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN2, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN3,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN3, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN3, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK0,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK0, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK0, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK1,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK1, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK1, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK2,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK2, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK2, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_GAIN,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_GAIN, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_GAIN, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_CAR_REG,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_CAR_REG, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_CAR_REG, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG1,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG1, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG1, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG2,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG2, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG2, value[0],
+ value[1], value[2], value[3]);
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
value, 4);
- dev_dbg(dev->dev,
- "reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0],
- value[1], value[2], value[3]);
+ cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0],
+ value[1], value[2], value[3]);
+
+
}
-#endif
void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev)
@@ -1524,7 +1497,7 @@
u32 standard = 0;
u8 value[4] = { 0, 0, 0, 0 };
- dev_dbg(dev->dev, "Enter cx231xx_set_Colibri_For_LowIF()\n");
+ cx231xx_info("Enter cx231xx_set_Colibri_For_LowIF()\n");
value[0] = (u8) 0x6F;
value[1] = (u8) 0x6F;
value[2] = (u8) 0x6F;
@@ -1544,7 +1517,7 @@
colibri_carrier_offset = cx231xx_Get_Colibri_CarrierOffset(mode,
standard);
- dev_dbg(dev->dev, "colibri_carrier_offset=%d, standard=0x%x\n",
+ cx231xx_info("colibri_carrier_offset=%d, standard=0x%x\n",
colibri_carrier_offset, standard);
/* Set the band Pass filter for DIF*/
@@ -1578,8 +1551,8 @@
u64 pll_freq_u64 = 0;
u32 i = 0;
- dev_dbg(dev->dev, "if_freq=%d;spectral_invert=0x%x;mode=0x%x\n",
- if_freq, spectral_invert, mode);
+ cx231xx_info("if_freq=%d;spectral_invert=0x%x;mode=0x%x\n",
+ if_freq, spectral_invert, mode);
if (mode == TUNER_MODE_FM_RADIO) {
@@ -1622,7 +1595,8 @@
if_freq = 16000000;
}
- dev_dbg(dev->dev, "Enter IF=%zu\n", ARRAY_SIZE(Dif_set_array));
+ cx231xx_info("Enter IF=%zu\n",
+ ARRAY_SIZE(Dif_set_array));
for (i = 0; i < ARRAY_SIZE(Dif_set_array); i++) {
if (Dif_set_array[i].if_freq == if_freq) {
vid_blk_write_word(dev,
@@ -1734,7 +1708,7 @@
u32 dif_misc_ctrl_value = 0;
u32 func_mode = 0;
- dev_dbg(dev->dev, "%s: setStandard to %x\n", __func__, standard);
+ cx231xx_info("%s: setStandard to %x\n", __func__, standard);
status = vid_blk_read_word(dev, DIF_MISC_CTRL, &dif_misc_ctrl_value);
if (standard != DIF_USE_BASEBAND)
@@ -2137,8 +2111,8 @@
{
int status = 0;
u32 dwval;
- dev_dbg(dev->dev, "%s: dev->tuner_type =0%d\n",
- __func__, dev->tuner_type);
+ cx231xx_info("cx231xx_tuner_post_channel_change dev->tuner_type =0%d\n",
+ dev->tuner_type);
/* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for
* SECAM L/B/D standards */
status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval);
@@ -2239,8 +2213,8 @@
if (dev->power_mode != mode)
dev->power_mode = mode;
else {
- dev_dbg(dev->dev, "%s: mode = %d, No Change req.\n",
- __func__, mode);
+ cx231xx_info(" setPowerMode::mode = %d, No Change req.\n",
+ mode);
return 0;
}
@@ -2290,6 +2264,7 @@
case POLARIS_AVMODE_ANALOGT_TV:
tmp |= PWR_DEMOD_EN;
+ tmp |= (I2C_DEMOD_EN);
value[0] = (u8) tmp;
value[1] = (u8) (tmp >> 8);
value[2] = (u8) (tmp >> 16);
@@ -2342,6 +2317,9 @@
}
if (dev->board.tuner_type != TUNER_ABSENT) {
+ /* Enable tuner */
+ cx231xx_enable_i2c_port_3(dev, true);
+
/* reset the Tuner */
if (dev->board.tuner_gpio)
cx231xx_gpio_set(dev, dev->board.tuner_gpio);
@@ -2385,7 +2363,7 @@
}
tmp &= (~PWR_AV_MODE);
- tmp |= POLARIS_AVMODE_DIGITAL;
+ tmp |= POLARIS_AVMODE_DIGITAL | I2C_DEMOD_EN;
value[0] = (u8) tmp;
value[1] = (u8) (tmp >> 8);
value[2] = (u8) (tmp >> 16);
@@ -2406,6 +2384,15 @@
}
if (dev->board.tuner_type != TUNER_ABSENT) {
+ /*
+ * Enable tuner
+ * Hauppauge Exeter seems to need to do something different!
+ */
+ if (dev->model == CX231XX_BOARD_HAUPPAUGE_EXETER)
+ cx231xx_enable_i2c_port_3(dev, false);
+ else
+ cx231xx_enable_i2c_port_3(dev, true);
+
/* reset the Tuner */
if (dev->board.tuner_gpio)
cx231xx_gpio_set(dev, dev->board.tuner_gpio);
@@ -2479,7 +2466,7 @@
u32 tmp = 0;
int status = 0;
- dev_dbg(dev->dev, "%s: ep_mask = %x\n", __func__, ep_mask);
+ cx231xx_info("cx231xx_start_stream():: ep_mask = %x\n", ep_mask);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET,
value, 4);
if (status < 0)
@@ -2504,7 +2491,7 @@
u32 tmp = 0;
int status = 0;
- dev_dbg(dev->dev, "%s: ep_mask = %x\n", __func__, ep_mask);
+ cx231xx_info("cx231xx_stop_stream():: ep_mask = %x\n", ep_mask);
status =
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET, value, 4);
if (status < 0)
@@ -2532,72 +2519,61 @@
if (dev->udev->speed == USB_SPEED_HIGH) {
switch (media_type) {
case Audio:
- dev_dbg(dev->dev,
- "%s: Audio enter HANC\n", __func__);
+ cx231xx_info("%s: Audio enter HANC\n", __func__);
status =
cx231xx_mode_register(dev, TS_MODE_REG, 0x9300);
break;
case Vbi:
- dev_dbg(dev->dev,
- "%s: set vanc registers\n", __func__);
+ cx231xx_info("%s: set vanc registers\n", __func__);
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x300);
break;
case Sliced_cc:
- dev_dbg(dev->dev,
- "%s: set hanc registers\n", __func__);
+ cx231xx_info("%s: set hanc registers\n", __func__);
status =
cx231xx_mode_register(dev, TS_MODE_REG, 0x1300);
break;
case Raw_Video:
- dev_dbg(dev->dev,
- "%s: set video registers\n", __func__);
+ cx231xx_info("%s: set video registers\n", __func__);
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
break;
case TS1_serial_mode:
- dev_dbg(dev->dev,
- "%s: set ts1 registers", __func__);
+ cx231xx_info("%s: set ts1 registers", __func__);
- if (dev->board.has_417) {
- dev_dbg(dev->dev,
- "%s: MPEG\n", __func__);
- value &= 0xFFFFFFFC;
- value |= 0x3;
+ if (dev->board.has_417) {
+ cx231xx_info(" MPEG\n");
+ value &= 0xFFFFFFFC;
+ value |= 0x3;
- status = cx231xx_mode_register(dev,
- TS_MODE_REG, value);
+ status = cx231xx_mode_register(dev, TS_MODE_REG, value);
- val[0] = 0x04;
- val[1] = 0xA3;
- val[2] = 0x3B;
- val[3] = 0x00;
- status = cx231xx_write_ctrl_reg(dev,
- VRT_SET_REGISTER,
- TS1_CFG_REG, val, 4);
+ val[0] = 0x04;
+ val[1] = 0xA3;
+ val[2] = 0x3B;
+ val[3] = 0x00;
+ status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+ TS1_CFG_REG, val, 4);
- val[0] = 0x00;
- val[1] = 0x08;
- val[2] = 0x00;
- val[3] = 0x08;
- status = cx231xx_write_ctrl_reg(dev,
- VRT_SET_REGISTER,
- TS1_LENGTH_REG, val, 4);
- } else {
- dev_dbg(dev->dev, "%s: BDA\n", __func__);
- status = cx231xx_mode_register(dev,
- TS_MODE_REG, 0x101);
- status = cx231xx_mode_register(dev,
- TS1_CFG_REG, 0x010);
- }
+ val[0] = 0x00;
+ val[1] = 0x08;
+ val[2] = 0x00;
+ val[3] = 0x08;
+ status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
+ TS1_LENGTH_REG, val, 4);
+
+ } else {
+ cx231xx_info(" BDA\n");
+ status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
+ status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x010);
+ }
break;
case TS1_parallel_mode:
- dev_dbg(dev->dev,
- "%s: set ts1 parallel mode registers\n",
- __func__);
+ cx231xx_info("%s: set ts1 parallel mode registers\n",
+ __func__);
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400);
break;
@@ -2950,9 +2926,8 @@
(nCnt > 0));
if (nCnt == 0)
- dev_dbg(dev->dev,
- "No ACK after %d msec -GPIO I2C failed!",
- nInit * 10);
+ cx231xx_info("No ACK after %d msec -GPIO I2C failed!",
+ nInit * 10);
/*
* readAck
diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index ae05d59..791f00c 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -20,12 +20,12 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "cx231xx.h"
#include <linux/init.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/i2c.h>
+#include <linux/usb.h>
#include <media/tuner.h>
#include <media/tveeprom.h>
#include <media/v4l2-common.h>
@@ -35,6 +35,7 @@
#include "xc5000.h"
#include "tda18271.h"
+#include "cx231xx.h"
static int tuner = -1;
module_param(tuner, int, 0444);
@@ -103,8 +104,8 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
- .demod_i2c_master = I2C_2,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x02,
.norm = V4L2_STD_PAL,
@@ -143,8 +144,8 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
- .demod_i2c_master = I2C_2,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x32,
.norm = V4L2_STD_NTSC,
@@ -183,8 +184,8 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x1c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
- .demod_i2c_master = I2C_2,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x02,
.norm = V4L2_STD_PAL,
@@ -224,8 +225,8 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x1c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
- .demod_i2c_master = I2C_2,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x02,
.norm = V4L2_STD_PAL,
@@ -261,6 +262,7 @@
.norm = V4L2_STD_PAL,
.no_alt_vanc = 1,
.external_av = 1,
+ .dont_use_port_3 = 1,
/* Actually, it has a 417, but it isn't working correctly.
* So set to 0 for now until someone can manage to get this
* to work reliably. */
@@ -295,8 +297,8 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
- .demod_i2c_master = I2C_2,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x02,
.norm = V4L2_STD_PAL,
@@ -323,8 +325,8 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
- .demod_i2c_master = I2C_2,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x32,
.norm = V4L2_STD_NTSC,
@@ -351,8 +353,8 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_1,
- .demod_i2c_master = I2C_2,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x0e,
.norm = V4L2_STD_NTSC,
@@ -388,6 +390,7 @@
.norm = V4L2_STD_NTSC,
.no_alt_vanc = 1,
.external_av = 1,
+ .dont_use_port_3 = 1,
.input = {{
.type = CX231XX_VMUX_COMPOSITE1,
.vmux = CX231XX_VIN_2_1,
@@ -415,9 +418,9 @@
.tuner_scl_gpio = -1,
.tuner_sda_gpio = -1,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_2,
- .demod_i2c_master = I2C_1_MUX_3,
- .ir_i2c_master = I2C_2,
+ .tuner_i2c_master = 2,
+ .demod_i2c_master = 1,
+ .ir_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x10,
.norm = V4L2_STD_PAL_M,
@@ -453,9 +456,9 @@
.tuner_scl_gpio = -1,
.tuner_sda_gpio = -1,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_2,
- .demod_i2c_master = I2C_1_MUX_3,
- .ir_i2c_master = I2C_2,
+ .tuner_i2c_master = 2,
+ .demod_i2c_master = 1,
+ .ir_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x10,
.norm = V4L2_STD_NTSC_M,
@@ -491,9 +494,9 @@
.tuner_scl_gpio = -1,
.tuner_sda_gpio = -1,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_2,
- .demod_i2c_master = I2C_1_MUX_3,
- .ir_i2c_master = I2C_2,
+ .tuner_i2c_master = 2,
+ .demod_i2c_master = 1,
+ .ir_i2c_master = 2,
.rc_map_name = RC_MAP_PIXELVIEW_002T,
.has_dvb = 1,
.demod_addr = 0x10,
@@ -529,6 +532,7 @@
.norm = V4L2_STD_NTSC,
.no_alt_vanc = 1,
.external_av = 1,
+ .dont_use_port_3 = 1,
.input = {{
.type = CX231XX_VMUX_COMPOSITE1,
@@ -583,7 +587,7 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
+ .tuner_i2c_master = 1,
.norm = V4L2_STD_PAL,
.input = {{
@@ -618,7 +622,7 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
+ .tuner_i2c_master = 1,
.norm = V4L2_STD_NTSC,
.input = {{
@@ -652,6 +656,7 @@
.norm = V4L2_STD_NTSC,
.no_alt_vanc = 1,
.external_av = 1,
+ .dont_use_port_3 = 1,
.input = {{
.type = CX231XX_VMUX_COMPOSITE1,
.vmux = CX231XX_VIN_2_1,
@@ -672,12 +677,13 @@
.decoder = CX231XX_AVDECODER,
.output_mode = OUT_MODE_VIP11,
.ctl_pin_status_mask = 0xFFFFFFC4,
- .agc_analog_digital_select_gpio = 0x0c,
+ .agc_analog_digital_select_gpio = 0x0c,
/* According with PV CxPlrCAP.inf file */
.gpio_pin_status_mask = 0x4001000,
.norm = V4L2_STD_NTSC,
.no_alt_vanc = 1,
.external_av = 1,
+ .dont_use_port_3 = 1,
/*.has_417 = 1, */
/* This board is believed to have a hardware encoding chip
* supporting mpeg1/2/4, but as the 417 is apparently not
@@ -712,8 +718,8 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
- .demod_i2c_master = I2C_2,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x0e,
.norm = V4L2_STD_PAL,
@@ -751,8 +757,8 @@
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
- .tuner_i2c_master = I2C_1_MUX_3,
- .demod_i2c_master = I2C_2,
+ .tuner_i2c_master = 1,
+ .demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x0e,
.norm = V4L2_STD_PAL,
@@ -855,9 +861,9 @@
if (dev->tuner_type == TUNER_XC5000) {
if (command == XC5000_TUNER_RESET) {
- dev_dbg(dev->dev,
- "Tuner CB: RESET: cmd %d : tuner type %d\n",
- command, dev->tuner_type);
+ cx231xx_info
+ ("Tuner CB: RESET: cmd %d : tuner type %d \n",
+ command, dev->tuner_type);
cx231xx_set_gpio_value(dev, dev->board.tuner_gpio->bit,
1);
msleep(10);
@@ -915,8 +921,8 @@
cx231xx_set_model(dev);
- dev_info(dev->dev, "Identified as %s (card=%d)\n",
- dev->board.name, dev->model);
+ cx231xx_info("Identified as %s (card=%d)\n",
+ dev->board.name, dev->model);
/* set the direction for GPIO pins */
if (dev->board.tuner_gpio) {
@@ -974,22 +980,25 @@
}
-static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
- u8 *eedata, int len)
+static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
{
int ret = 0;
+ u8 addr = 0xa0 >> 1;
u8 start_offset = 0;
int len_todo = len;
u8 *eedata_cur = eedata;
int i;
- struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
+ struct i2c_msg msg_write = { .addr = addr, .flags = 0,
.buf = &start_offset, .len = 1 };
- struct i2c_msg msg_read = { .addr = client->addr, .flags = I2C_M_RD };
+ struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD };
+
+ /* mutex_lock(&dev->i2c_lock); */
+ cx231xx_enable_i2c_port_3(dev, false);
/* start reading at offset 0 */
- ret = i2c_transfer(client->adapter, &msg_write, 1);
+ ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1);
if (ret < 0) {
- dev_err(dev->dev, "Can't read eeprom\n");
+ cx231xx_err("Can't read eeprom\n");
return ret;
}
@@ -997,18 +1006,20 @@
msg_read.len = (len_todo > 64) ? 64 : len_todo;
msg_read.buf = eedata_cur;
- ret = i2c_transfer(client->adapter, &msg_read, 1);
+ ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1);
if (ret < 0) {
- dev_err(dev->dev, "Can't read eeprom\n");
+ cx231xx_err("Can't read eeprom\n");
return ret;
}
eedata_cur += msg_read.len;
len_todo -= msg_read.len;
}
+ cx231xx_enable_i2c_port_3(dev, true);
+ /* mutex_unlock(&dev->i2c_lock); */
+
for (i = 0; i + 15 < len; i += 16)
- dev_dbg(dev->dev, "i2c eeprom %02x: %*ph\n",
- i, 16, &eedata[i]);
+ cx231xx_info("i2c eeprom %02x: %*ph\n", i, 16, &eedata[i]);
return 0;
}
@@ -1025,26 +1036,22 @@
/* request some modules */
if (dev->board.decoder == CX231XX_AVDECODER) {
dev->sd_cx25840 = v4l2_i2c_new_subdev(&dev->v4l2_dev,
- cx231xx_get_i2c_adap(dev, I2C_0),
+ &dev->i2c_bus[0].i2c_adap,
"cx25840", 0x88 >> 1, NULL);
if (dev->sd_cx25840 == NULL)
- dev_err(dev->dev,
- "cx25840 subdev registration failure\n");
+ cx231xx_info("cx25840 subdev registration failure\n");
cx25840_call(dev, core, load_fw);
}
/* Initialize the tuner */
if (dev->board.tuner_type != TUNER_ABSENT) {
- struct i2c_adapter *tuner_i2c = cx231xx_get_i2c_adap(dev,
- dev->board.tuner_i2c_master);
dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
- tuner_i2c,
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
"tuner",
dev->tuner_addr, NULL);
if (dev->sd_tuner == NULL)
- dev_err(dev->dev,
- "tuner subdev registration failure\n");
+ cx231xx_info("tuner subdev registration failure\n");
else
cx231xx_config_tuner(dev);
}
@@ -1055,14 +1062,9 @@
{
struct tveeprom tvee;
static u8 eeprom[256];
- struct i2c_client client;
- memset(&client, 0, sizeof(client));
- client.adapter = cx231xx_get_i2c_adap(dev, I2C_1_MUX_1);
- client.addr = 0xa0 >> 1;
-
- read_eeprom(dev, &client, eeprom, sizeof(eeprom));
- tveeprom_hauppauge_analog(&client,
+ read_eeprom(dev, eeprom, sizeof(eeprom));
+ tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client,
&tvee, eeprom + 0xc0);
break;
}
@@ -1150,7 +1152,7 @@
/* Query cx231xx to find what pcb config it is related to */
retval = initialize_cx231xx(dev);
if (retval < 0) {
- dev_err(dev->dev, "Failed to read PCB config\n");
+ cx231xx_errdev("Failed to read PCB config\n");
return retval;
}
@@ -1166,7 +1168,7 @@
retval = cx231xx_config(dev);
if (retval) {
- dev_err(dev->dev, "error configuring device\n");
+ cx231xx_errdev("error configuring device\n");
return -ENOMEM;
}
@@ -1176,9 +1178,8 @@
/* register i2c bus */
retval = cx231xx_dev_init(dev);
if (retval) {
- dev_err(dev->dev,
- "%s: cx231xx_i2c_register - errCode [%d]!\n",
- __func__, retval);
+ cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n",
+ __func__, retval);
goto err_dev_init;
}
@@ -1199,8 +1200,8 @@
retval = cx231xx_config(dev);
if (retval) {
- dev_err(dev->dev, "%s: cx231xx_config - errCode [%d]!\n",
- __func__, retval);
+ cx231xx_errdev("%s: cx231xx_config - errCode [%d]!\n",
+ __func__, retval);
goto err_dev_init;
}
@@ -1216,11 +1217,11 @@
cx231xx_add_into_devlist(dev);
if (dev->board.has_417) {
- dev_info(dev->dev, "attach 417 %d\n", dev->model);
+ printk(KERN_INFO "attach 417 %d\n", dev->model);
if (cx231xx_417_register(dev) < 0) {
- dev_err(dev->dev,
+ printk(KERN_ERR
"%s() Failed to register 417 on VID_B\n",
- __func__);
+ __func__);
}
}
@@ -1284,8 +1285,7 @@
/* compute alternate max packet sizes for video */
idx = dev->current_pcb_config.hs_config_info[0].interface_info.video_index + 1;
if (idx >= dev->max_iad_interface_count) {
- dev_err(dev->dev,
- "Video PCB interface #%d doesn't exist\n", idx);
+ cx231xx_errdev("Video PCB interface #%d doesn't exist\n", idx);
return -ENODEV;
}
@@ -1294,29 +1294,28 @@
dev->video_mode.end_point_addr = uif->altsetting[0].endpoint[isoc_pipe].desc.bEndpointAddress;
dev->video_mode.num_alt = uif->num_altsetting;
- dev_info(dev->dev,
- "video EndPoint Addr 0x%x, Alternate settings: %i\n",
- dev->video_mode.end_point_addr,
- dev->video_mode.num_alt);
+ cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+ dev->video_mode.end_point_addr,
+ dev->video_mode.num_alt);
dev->video_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->video_mode.num_alt, GFP_KERNEL);
- if (dev->video_mode.alt_max_pkt_size == NULL)
+ if (dev->video_mode.alt_max_pkt_size == NULL) {
+ cx231xx_errdev("out of memory!\n");
return -ENOMEM;
+ }
for (i = 0; i < dev->video_mode.num_alt; i++) {
u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].desc.wMaxPacketSize);
dev->video_mode.alt_max_pkt_size[i] = (tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- dev_dbg(dev->dev,
- "Alternate setting %i, max size= %i\n", i,
- dev->video_mode.alt_max_pkt_size[i]);
+ cx231xx_info("Alternate setting %i, max size= %i\n", i,
+ dev->video_mode.alt_max_pkt_size[i]);
}
/* VBI Init */
idx = dev->current_pcb_config.hs_config_info[0].interface_info.vanc_index + 1;
if (idx >= dev->max_iad_interface_count) {
- dev_err(dev->dev,
- "VBI PCB interface #%d doesn't exist\n", idx);
+ cx231xx_errdev("VBI PCB interface #%d doesn't exist\n", idx);
return -ENODEV;
}
uif = udev->actconfig->interface[idx];
@@ -1326,15 +1325,16 @@
bEndpointAddress;
dev->vbi_mode.num_alt = uif->num_altsetting;
- dev_info(dev->dev,
- "VBI EndPoint Addr 0x%x, Alternate settings: %i\n",
- dev->vbi_mode.end_point_addr,
- dev->vbi_mode.num_alt);
+ cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+ dev->vbi_mode.end_point_addr,
+ dev->vbi_mode.num_alt);
/* compute alternate max packet sizes for vbi */
dev->vbi_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->vbi_mode.num_alt, GFP_KERNEL);
- if (dev->vbi_mode.alt_max_pkt_size == NULL)
+ if (dev->vbi_mode.alt_max_pkt_size == NULL) {
+ cx231xx_errdev("out of memory!\n");
return -ENOMEM;
+ }
for (i = 0; i < dev->vbi_mode.num_alt; i++) {
u16 tmp =
@@ -1342,9 +1342,8 @@
desc.wMaxPacketSize);
dev->vbi_mode.alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- dev_dbg(dev->dev,
- "Alternate setting %i, max size= %i\n", i,
- dev->vbi_mode.alt_max_pkt_size[i]);
+ cx231xx_info("Alternate setting %i, max size= %i\n", i,
+ dev->vbi_mode.alt_max_pkt_size[i]);
}
/* Sliced CC VBI init */
@@ -1352,8 +1351,7 @@
/* compute alternate max packet sizes for sliced CC */
idx = dev->current_pcb_config.hs_config_info[0].interface_info.hanc_index + 1;
if (idx >= dev->max_iad_interface_count) {
- dev_err(dev->dev,
- "Sliced CC PCB interface #%d doesn't exist\n", idx);
+ cx231xx_errdev("Sliced CC PCB interface #%d doesn't exist\n", idx);
return -ENODEV;
}
uif = udev->actconfig->interface[idx];
@@ -1363,22 +1361,23 @@
bEndpointAddress;
dev->sliced_cc_mode.num_alt = uif->num_altsetting;
- dev_info(dev->dev,
- "sliced CC EndPoint Addr 0x%x, Alternate settings: %i\n",
- dev->sliced_cc_mode.end_point_addr,
- dev->sliced_cc_mode.num_alt);
+ cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+ dev->sliced_cc_mode.end_point_addr,
+ dev->sliced_cc_mode.num_alt);
dev->sliced_cc_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->sliced_cc_mode.num_alt, GFP_KERNEL);
- if (dev->sliced_cc_mode.alt_max_pkt_size == NULL)
+
+ if (dev->sliced_cc_mode.alt_max_pkt_size == NULL) {
+ cx231xx_errdev("out of memory!\n");
return -ENOMEM;
+ }
for (i = 0; i < dev->sliced_cc_mode.num_alt; i++) {
u16 tmp = le16_to_cpu(uif->altsetting[i].endpoint[isoc_pipe].
desc.wMaxPacketSize);
dev->sliced_cc_mode.alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- dev_dbg(dev->dev,
- "Alternate setting %i, max size= %i\n", i,
- dev->sliced_cc_mode.alt_max_pkt_size[i]);
+ cx231xx_info("Alternate setting %i, max size= %i\n", i,
+ dev->sliced_cc_mode.alt_max_pkt_size[i]);
}
return 0;
@@ -1392,7 +1391,6 @@
const struct usb_device_id *id)
{
struct usb_device *udev;
- struct device *d = &interface->dev;
struct usb_interface *uif;
struct cx231xx *dev = NULL;
int retval = -ENODEV;
@@ -1403,7 +1401,6 @@
struct usb_interface_assoc_descriptor *assoc_desc;
ifnum = interface->altsetting[0].desc.bInterfaceNumber;
- udev = usb_get_dev(interface_to_usbdev(interface));
/*
* Interface number 0 - IR interface (handled by mceusb driver)
@@ -1417,16 +1414,18 @@
nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
if (nr >= CX231XX_MAXBOARDS) {
/* No free device slots */
- dev_err(d,
- "Supports only %i devices.\n",
- CX231XX_MAXBOARDS);
+ cx231xx_err(DRIVER_NAME ": Supports only %i devices.\n",
+ CX231XX_MAXBOARDS);
return -ENOMEM;
}
} while (test_and_set_bit(nr, &cx231xx_devused));
+ udev = usb_get_dev(interface_to_usbdev(interface));
+
/* allocate memory for our device state and initialize it */
dev = devm_kzalloc(&udev->dev, sizeof(*dev), GFP_KERNEL);
if (dev == NULL) {
+ cx231xx_err(DRIVER_NAME ": out of memory!\n");
clear_bit(nr, &cx231xx_devused);
return -ENOMEM;
}
@@ -1435,7 +1434,6 @@
dev->devno = nr;
dev->model = id->driver_info;
dev->video_mode.alt = -1;
- dev->dev = d;
dev->interface_count++;
/* reset gpio dir and value */
@@ -1474,14 +1472,14 @@
speed = "unknown";
}
- dev_info(d,
- "New device %s %s @ %s Mbps (%04x:%04x) with %d interfaces\n",
- udev->manufacturer ? udev->manufacturer : "",
- udev->product ? udev->product : "",
- speed,
- le16_to_cpu(udev->descriptor.idVendor),
- le16_to_cpu(udev->descriptor.idProduct),
- dev->max_iad_interface_count);
+ cx231xx_info("New device %s %s @ %s Mbps "
+ "(%04x:%04x) with %d interfaces\n",
+ udev->manufacturer ? udev->manufacturer : "",
+ udev->product ? udev->product : "",
+ speed,
+ le16_to_cpu(udev->descriptor.idVendor),
+ le16_to_cpu(udev->descriptor.idProduct),
+ dev->max_iad_interface_count);
/* increment interface count */
dev->interface_count++;
@@ -1491,12 +1489,13 @@
assoc_desc = udev->actconfig->intf_assoc[0];
if (assoc_desc->bFirstInterface != ifnum) {
- dev_err(d, "Not found matching IAD interface\n");
+ cx231xx_err(DRIVER_NAME ": Not found "
+ "matching IAD interface\n");
retval = -ENODEV;
goto err_if;
}
- dev_dbg(d, "registering interface %d\n", ifnum);
+ cx231xx_info("registering interface %d\n", ifnum);
/* save our data pointer in this interface device */
usb_set_intfdata(interface, dev);
@@ -1504,7 +1503,7 @@
/* Create v4l2 device */
retval = v4l2_device_register(&interface->dev, &dev->v4l2_dev);
if (retval) {
- dev_err(d, "v4l2_device_register failed\n");
+ cx231xx_errdev("v4l2_device_register failed\n");
goto err_v4l2;
}
@@ -1521,8 +1520,7 @@
/* compute alternate max packet sizes for TS1 */
idx = dev->current_pcb_config.hs_config_info[0].interface_info.ts1_index + 1;
if (idx >= dev->max_iad_interface_count) {
- dev_err(d, "TS1 PCB interface #%d doesn't exist\n",
- idx);
+ cx231xx_errdev("TS1 PCB interface #%d doesn't exist\n", idx);
retval = -ENODEV;
goto err_video_alt;
}
@@ -1533,13 +1531,13 @@
desc.bEndpointAddress;
dev->ts1_mode.num_alt = uif->num_altsetting;
- dev_info(d,
- "TS EndPoint Addr 0x%x, Alternate settings: %i\n",
- dev->ts1_mode.end_point_addr,
- dev->ts1_mode.num_alt);
+ cx231xx_info("EndPoint Addr 0x%x, Alternate settings: %i\n",
+ dev->ts1_mode.end_point_addr,
+ dev->ts1_mode.num_alt);
dev->ts1_mode.alt_max_pkt_size = devm_kmalloc_array(&udev->dev, 32, dev->ts1_mode.num_alt, GFP_KERNEL);
if (dev->ts1_mode.alt_max_pkt_size == NULL) {
+ cx231xx_errdev("out of memory!\n");
retval = -ENOMEM;
goto err_video_alt;
}
@@ -1550,8 +1548,8 @@
wMaxPacketSize);
dev->ts1_mode.alt_max_pkt_size[i] =
(tmp & 0x07ff) * (((tmp & 0x1800) >> 11) + 1);
- dev_dbg(d, "Alternate setting %i, max size= %i\n",
- i, dev->ts1_mode.alt_max_pkt_size[i]);
+ cx231xx_info("Alternate setting %i, max size= %i\n", i,
+ dev->ts1_mode.alt_max_pkt_size[i]);
}
}
@@ -1615,9 +1613,10 @@
wake_up_interruptible_all(&dev->open);
if (dev->users) {
- dev_warn(dev->dev,
- "device %s is open! Deregistration and memory deallocation are deferred on close.\n",
- video_device_node_name(dev->vdev));
+ cx231xx_warn
+ ("device %s is open! Deregistration and memory "
+ "deallocation are deferred on close.\n",
+ video_device_node_name(dev->vdev));
/* Even having users, it is safe to remove the RC i2c driver */
cx231xx_ir_exit(dev);
diff --git a/drivers/media/usb/cx231xx/cx231xx-core.c b/drivers/media/usb/cx231xx/cx231xx-core.c
index 4a3f28c..180103e 100644
--- a/drivers/media/usb/cx231xx/cx231xx-core.c
+++ b/drivers/media/usb/cx231xx/cx231xx-core.c
@@ -20,15 +20,16 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "cx231xx.h"
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/usb.h>
#include <linux/vmalloc.h>
#include <media/v4l2-common.h>
#include <media/tuner.h>
+#include "cx231xx.h"
#include "cx231xx-reg.h"
/* #define ENABLE_DEBUG_ISOC_FRAMES */
@@ -98,10 +99,10 @@
mutex_lock(&cx231xx_devlist_mutex);
list_add_tail(&ops->next, &cx231xx_extension_devlist);
- list_for_each_entry(dev, &cx231xx_devlist, devlist) {
+ list_for_each_entry(dev, &cx231xx_devlist, devlist)
ops->init(dev);
- dev_info(dev->dev, "%s initialized\n", ops->name);
- }
+
+ printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name);
mutex_unlock(&cx231xx_devlist_mutex);
return 0;
}
@@ -112,11 +113,11 @@
struct cx231xx *dev = NULL;
mutex_lock(&cx231xx_devlist_mutex);
- list_for_each_entry(dev, &cx231xx_devlist, devlist) {
+ list_for_each_entry(dev, &cx231xx_devlist, devlist)
ops->fini(dev);
- dev_info(dev->dev, "%s removed\n", ops->name);
- }
+
+ printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name);
list_del(&ops->next);
mutex_unlock(&cx231xx_devlist_mutex);
}
@@ -226,9 +227,10 @@
/* call common vendor command request */
status = cx231xx_send_vendor_cmd(dev, &ven_req);
- if (status < 0 && !dev->i2c_scan_running) {
- dev_err(dev->dev, "%s: failed with status -%d\n",
- __func__, status);
+ if (status < 0) {
+ cx231xx_info
+ ("UsbInterface::sendCommand, failed with status -%d\n",
+ status);
}
return status;
@@ -522,9 +524,9 @@
usb_set_interface(dev->udev, usb_interface_index,
dev->video_mode.alt);
if (errCode < 0) {
- dev_err(dev->dev,
- "cannot change alt number to %d (error=%i)\n",
- dev->video_mode.alt, errCode);
+ cx231xx_errdev
+ ("cannot change alt number to %d (error=%i)\n",
+ dev->video_mode.alt, errCode);
return errCode;
}
}
@@ -598,9 +600,9 @@
}
if (alt > 0 && max_pkt_size == 0) {
- dev_err(dev->dev,
- "can't change interface %d alt no. to %d: Max. Pkt size = 0\n",
- usb_interface_index, alt);
+ cx231xx_errdev
+ ("can't change interface %d alt no. to %d: Max. Pkt size = 0\n",
+ usb_interface_index, alt);
/*To workaround error number=-71 on EP0 for videograbber,
need add following codes.*/
if (dev->board.no_alt_vanc)
@@ -614,9 +616,9 @@
if (usb_interface_index > 0) {
status = usb_set_interface(dev->udev, usb_interface_index, alt);
if (status < 0) {
- dev_err(dev->dev,
- "can't change interface %d alt no. to %d (err=%i)\n",
- usb_interface_index, alt, status);
+ cx231xx_errdev
+ ("can't change interface %d alt no. to %d (err=%i)\n",
+ usb_interface_index, alt, status);
return status;
}
}
@@ -765,17 +767,18 @@
u32 *buffer;
buffer = kzalloc(4096, GFP_KERNEL);
- if (buffer == NULL)
+ if (buffer == NULL) {
+ cx231xx_info("out of mem\n");
return -ENOMEM;
+ }
memcpy(&buffer[0], firmware, 4096);
ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 5),
buffer, 4096, &actlen, 2000);
if (ret)
- dev_err(dev->dev,
- "bulk message failed: %d (%d/%d)", ret,
- size, actlen);
+ cx231xx_info("bulk message failed: %d (%d/%d)", ret,
+ size, actlen);
else {
errCode = actlen != size ? -1 : 0;
}
@@ -984,8 +987,12 @@
cx231xx_uninit_isoc(dev);
dma_q->p_left_data = kzalloc(4096, GFP_KERNEL);
- if (dma_q->p_left_data == NULL)
+ if (dma_q->p_left_data == NULL) {
+ cx231xx_info("out of mem\n");
return -ENOMEM;
+ }
+
+
dev->video_mode.isoc_ctl.isoc_copy = isoc_copy;
dev->video_mode.isoc_ctl.num_bufs = num_bufs;
@@ -1011,16 +1018,14 @@
dev->video_mode.isoc_ctl.urb =
kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
if (!dev->video_mode.isoc_ctl.urb) {
- dev_err(dev->dev,
- "cannot alloc memory for usb buffers\n");
+ cx231xx_errdev("cannot alloc memory for usb buffers\n");
return -ENOMEM;
}
dev->video_mode.isoc_ctl.transfer_buffer =
kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
if (!dev->video_mode.isoc_ctl.transfer_buffer) {
- dev_err(dev->dev,
- "cannot allocate memory for usbtransfer\n");
+ cx231xx_errdev("cannot allocate memory for usbtransfer\n");
kfree(dev->video_mode.isoc_ctl.urb);
return -ENOMEM;
}
@@ -1040,8 +1045,7 @@
for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
urb = usb_alloc_urb(max_packets, GFP_KERNEL);
if (!urb) {
- dev_err(dev->dev,
- "cannot alloc isoc_ctl.urb %i\n", i);
+ cx231xx_err("cannot alloc isoc_ctl.urb %i\n", i);
cx231xx_uninit_isoc(dev);
return -ENOMEM;
}
@@ -1051,10 +1055,10 @@
usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
&urb->transfer_dma);
if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) {
- dev_err(dev->dev,
- "unable to allocate %i bytes for transfer buffer %i%s\n",
- sb_size, i,
- in_interrupt() ? " while in int" : "");
+ cx231xx_err("unable to allocate %i bytes for transfer"
+ " buffer %i%s\n",
+ sb_size, i,
+ in_interrupt() ? " while in int" : "");
cx231xx_uninit_isoc(dev);
return -ENOMEM;
}
@@ -1086,9 +1090,8 @@
rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i],
GFP_ATOMIC);
if (rc) {
- dev_err(dev->dev,
- "submit of urb %i failed (error=%i)\n", i,
- rc);
+ cx231xx_err("submit of urb %i failed (error=%i)\n", i,
+ rc);
cx231xx_uninit_isoc(dev);
return rc;
}
@@ -1148,16 +1151,14 @@
dev->video_mode.bulk_ctl.urb =
kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
if (!dev->video_mode.bulk_ctl.urb) {
- dev_err(dev->dev,
- "cannot alloc memory for usb buffers\n");
+ cx231xx_errdev("cannot alloc memory for usb buffers\n");
return -ENOMEM;
}
dev->video_mode.bulk_ctl.transfer_buffer =
kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
if (!dev->video_mode.bulk_ctl.transfer_buffer) {
- dev_err(dev->dev,
- "cannot allocate memory for usbtransfer\n");
+ cx231xx_errdev("cannot allocate memory for usbtransfer\n");
kfree(dev->video_mode.bulk_ctl.urb);
return -ENOMEM;
}
@@ -1177,8 +1178,7 @@
for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
- dev_err(dev->dev,
- "cannot alloc bulk_ctl.urb %i\n", i);
+ cx231xx_err("cannot alloc bulk_ctl.urb %i\n", i);
cx231xx_uninit_bulk(dev);
return -ENOMEM;
}
@@ -1189,10 +1189,10 @@
usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
&urb->transfer_dma);
if (!dev->video_mode.bulk_ctl.transfer_buffer[i]) {
- dev_err(dev->dev,
- "unable to allocate %i bytes for transfer buffer %i%s\n",
- sb_size, i,
- in_interrupt() ? " while in int" : "");
+ cx231xx_err("unable to allocate %i bytes for transfer"
+ " buffer %i%s\n",
+ sb_size, i,
+ in_interrupt() ? " while in int" : "");
cx231xx_uninit_bulk(dev);
return -ENOMEM;
}
@@ -1212,8 +1212,8 @@
rc = usb_submit_urb(dev->video_mode.bulk_ctl.urb[i],
GFP_ATOMIC);
if (rc) {
- dev_err(dev->dev,
- "submit of urb %i failed (error=%i)\n", i, rc);
+ cx231xx_err("submit of urb %i failed (error=%i)\n", i,
+ rc);
cx231xx_uninit_bulk(dev);
return rc;
}
@@ -1300,15 +1300,6 @@
cx231xx_i2c_register(&dev->i2c_bus[1]);
cx231xx_i2c_register(&dev->i2c_bus[2]);
- cx231xx_i2c_mux_register(dev, 0);
- cx231xx_i2c_mux_register(dev, 1);
-
- /* scan the real bus segments in the order of physical port numbers */
- cx231xx_do_i2c_scan(dev, I2C_0);
- cx231xx_do_i2c_scan(dev, I2C_1_MUX_1);
- cx231xx_do_i2c_scan(dev, I2C_2);
- cx231xx_do_i2c_scan(dev, I2C_1_MUX_3);
-
/* init hardware */
/* Note : with out calling set power mode function,
afe can not be set up correctly */
@@ -1316,18 +1307,18 @@
errCode = cx231xx_set_power_mode(dev,
POLARIS_AVMODE_ENXTERNAL_AV);
if (errCode < 0) {
- dev_err(dev->dev,
- "%s: Failed to set Power - errCode [%d]!\n",
- __func__, errCode);
+ cx231xx_errdev
+ ("%s: Failed to set Power - errCode [%d]!\n",
+ __func__, errCode);
return errCode;
}
} else {
errCode = cx231xx_set_power_mode(dev,
POLARIS_AVMODE_ANALOGT_TV);
if (errCode < 0) {
- dev_err(dev->dev,
- "%s: Failed to set Power - errCode [%d]!\n",
- __func__, errCode);
+ cx231xx_errdev
+ ("%s: Failed to set Power - errCode [%d]!\n",
+ __func__, errCode);
return errCode;
}
}
@@ -1340,43 +1331,42 @@
/* initialize Colibri block */
errCode = cx231xx_afe_init_super_block(dev, 0x23c);
if (errCode < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_afe init super block - errCode [%d]!\n",
- __func__, errCode);
+ cx231xx_errdev
+ ("%s: cx231xx_afe init super block - errCode [%d]!\n",
+ __func__, errCode);
return errCode;
}
errCode = cx231xx_afe_init_channels(dev);
if (errCode < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_afe init channels - errCode [%d]!\n",
- __func__, errCode);
+ cx231xx_errdev
+ ("%s: cx231xx_afe init channels - errCode [%d]!\n",
+ __func__, errCode);
return errCode;
}
/* Set DIF in By pass mode */
errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);
if (errCode < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
- __func__, errCode);
+ cx231xx_errdev
+ ("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
+ __func__, errCode);
return errCode;
}
/* I2S block related functions */
errCode = cx231xx_i2s_blk_initialize(dev);
if (errCode < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_i2s block initialize - errCode [%d]!\n",
- __func__, errCode);
+ cx231xx_errdev
+ ("%s: cx231xx_i2s block initialize - errCode [%d]!\n",
+ __func__, errCode);
return errCode;
}
/* init control pins */
errCode = cx231xx_init_ctrl_pin_status(dev);
if (errCode < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_init ctrl pins - errCode [%d]!\n",
- __func__, errCode);
+ cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n",
+ __func__, errCode);
return errCode;
}
@@ -1401,9 +1391,9 @@
break;
}
if (errCode < 0) {
- dev_err(dev->dev,
- "%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",
- __func__, errCode);
+ cx231xx_errdev
+ ("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",
+ __func__, errCode);
return errCode;
}
@@ -1414,7 +1404,9 @@
if (dev->board.has_dvb)
cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
- errCode = 0;
+ /* set the I2C master port to 3 on channel 1 */
+ errCode = cx231xx_enable_i2c_port_3(dev, true);
+
return errCode;
}
EXPORT_SYMBOL_GPL(cx231xx_dev_init);
@@ -1422,8 +1414,6 @@
void cx231xx_dev_uninit(struct cx231xx *dev)
{
/* Un Initialize I2C bus */
- cx231xx_i2c_mux_unregister(dev, 1);
- cx231xx_i2c_mux_unregister(dev, 0);
cx231xx_i2c_unregister(&dev->i2c_bus[2]);
cx231xx_i2c_unregister(&dev->i2c_bus[1]);
cx231xx_i2c_unregister(&dev->i2c_bus[0]);
@@ -1478,8 +1468,9 @@
/* call common vendor command request */
status = cx231xx_send_vendor_cmd(dev, &ven_req);
if (status < 0) {
- dev_err(dev->dev, "%s: failed with status -%d\n",
- __func__, status);
+ cx231xx_info
+ ("UsbInterface::sendCommand, failed with status -%d\n",
+ status);
}
return status;
diff --git a/drivers/media/usb/cx231xx/cx231xx-dvb.c b/drivers/media/usb/cx231xx/cx231xx-dvb.c
index dd600b9..6c7b5e2 100644
--- a/drivers/media/usb/cx231xx/cx231xx-dvb.c
+++ b/drivers/media/usb/cx231xx/cx231xx-dvb.c
@@ -19,10 +19,11 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "cx231xx.h"
#include <linux/kernel.h>
#include <linux/slab.h>
+#include <linux/usb.h>
+#include "cx231xx.h"
#include <media/v4l2-common.h>
#include <media/videobuf-vmalloc.h>
@@ -45,6 +46,11 @@
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+#define dprintk(level, fmt, arg...) do { \
+if (debug >= level) \
+ printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
+} while (0)
+
#define CX231XX_DVB_NUM_BUFS 5
#define CX231XX_DVB_MAX_PACKETSIZE 564
#define CX231XX_DVB_MAX_PACKETS 64
@@ -191,11 +197,9 @@
break;
}
if (packet < 0) {
- dev_dbg(dev->dev,
- "URB status %d [%s].\n", status, errmsg);
+ dprintk(1, "URB status %d [%s].\n", status, errmsg);
} else {
- dev_dbg(dev->dev,
- "URB packet %d, status %d [%s].\n",
+ dprintk(1, "URB packet %d, status %d [%s].\n",
packet, status, errmsg);
}
}
@@ -261,8 +265,12 @@
struct cx231xx *dev = dvb->adapter.priv;
if (dev->USE_ISO) {
- dev_dbg(dev->dev, "DVB transfer mode is ISO.\n");
+ cx231xx_info("DVB transfer mode is ISO.\n");
+ mutex_lock(&dev->i2c_lock);
+ cx231xx_enable_i2c_port_3(dev, false);
cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
+ cx231xx_enable_i2c_port_3(dev, true);
+ mutex_unlock(&dev->i2c_lock);
rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
if (rc < 0)
return rc;
@@ -272,7 +280,7 @@
dev->ts1_mode.max_pkt_size,
dvb_isoc_copy);
} else {
- dev_dbg(dev->dev, "DVB transfer mode is BULK.\n");
+ cx231xx_info("DVB transfer mode is BULK.\n");
cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
if (rc < 0)
@@ -370,24 +378,24 @@
struct xc5000_config cfg;
memset(&cfg, 0, sizeof(cfg));
- cfg.i2c_adap = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);
+ cfg.i2c_adap = &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap;
cfg.i2c_addr = addr;
if (!dev->dvb->frontend) {
- dev_err(dev->dev, "%s/2: dvb frontend not attached. "
+ printk(KERN_ERR "%s/2: dvb frontend not attached. "
"Can't attach xc5000\n", dev->name);
return -EINVAL;
}
fe = dvb_attach(xc5000_attach, dev->dvb->frontend, &cfg);
if (!fe) {
- dev_err(dev->dev, "%s/2: xc5000 attach failed\n", dev->name);
+ printk(KERN_ERR "%s/2: xc5000 attach failed\n", dev->name);
dvb_frontend_detach(dev->dvb->frontend);
dev->dvb->frontend = NULL;
return -EINVAL;
}
- dev_info(dev->dev, "%s/2: xc5000 attached\n", dev->name);
+ printk(KERN_INFO "%s/2: xc5000 attached\n", dev->name);
return 0;
}
@@ -426,17 +434,16 @@
if (dops->init != NULL && !dev->xc_fw_load_done) {
- dev_dbg(dev->dev,
- "Reloading firmware for XC5000\n");
+ cx231xx_info("Reloading firmware for XC5000\n");
status = dops->init(dev->dvb->frontend);
if (status == 0) {
dev->xc_fw_load_done = 1;
- dev_dbg(dev->dev,
- "XC5000 firmware download completed\n");
+ cx231xx_info
+ ("XC5000 firmware download completed\n");
} else {
dev->xc_fw_load_done = 0;
- dev_dbg(dev->dev,
- "XC5000 firmware download failed !!!\n");
+ cx231xx_info
+ ("XC5000 firmware download failed !!!\n");
}
}
@@ -459,7 +466,7 @@
result = dvb_register_adapter(&dvb->adapter, dev->name, module, device,
adapter_nr);
if (result < 0) {
- dev_warn(dev->dev,
+ printk(KERN_WARNING
"%s: dvb_register_adapter failed (errno = %d)\n",
dev->name, result);
goto fail_adapter;
@@ -473,7 +480,7 @@
/* register frontend */
result = dvb_register_frontend(&dvb->adapter, dvb->frontend);
if (result < 0) {
- dev_warn(dev->dev,
+ printk(KERN_WARNING
"%s: dvb_register_frontend failed (errno = %d)\n",
dev->name, result);
goto fail_frontend;
@@ -491,8 +498,7 @@
result = dvb_dmx_init(&dvb->demux);
if (result < 0) {
- dev_warn(dev->dev,
- "%s: dvb_dmx_init failed (errno = %d)\n",
+ printk(KERN_WARNING "%s: dvb_dmx_init failed (errno = %d)\n",
dev->name, result);
goto fail_dmx;
}
@@ -502,16 +508,15 @@
dvb->dmxdev.capabilities = 0;
result = dvb_dmxdev_init(&dvb->dmxdev, &dvb->adapter);
if (result < 0) {
- dev_warn(dev->dev,
- "%s: dvb_dmxdev_init failed (errno = %d)\n",
- dev->name, result);
+ printk(KERN_WARNING "%s: dvb_dmxdev_init failed (errno = %d)\n",
+ dev->name, result);
goto fail_dmxdev;
}
dvb->fe_hw.source = DMX_FRONTEND_0;
result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_hw);
if (result < 0) {
- dev_warn(dev->dev,
+ printk(KERN_WARNING
"%s: add_frontend failed (DMX_FRONTEND_0, errno = %d)\n",
dev->name, result);
goto fail_fe_hw;
@@ -520,17 +525,17 @@
dvb->fe_mem.source = DMX_MEMORY_FE;
result = dvb->demux.dmx.add_frontend(&dvb->demux.dmx, &dvb->fe_mem);
if (result < 0) {
- dev_warn(dev->dev,
- "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
- dev->name, result);
+ printk(KERN_WARNING
+ "%s: add_frontend failed (DMX_MEMORY_FE, errno = %d)\n",
+ dev->name, result);
goto fail_fe_mem;
}
result = dvb->demux.dmx.connect_frontend(&dvb->demux.dmx, &dvb->fe_hw);
if (result < 0) {
- dev_warn(dev->dev,
- "%s: connect_frontend failed (errno = %d)\n",
- dev->name, result);
+ printk(KERN_WARNING
+ "%s: connect_frontend failed (errno = %d)\n", dev->name,
+ result);
goto fail_fe_conn;
}
@@ -578,8 +583,6 @@
{
int result = 0;
struct cx231xx_dvb *dvb;
- struct i2c_adapter *tuner_i2c;
- struct i2c_adapter *demod_i2c;
if (!dev->board.has_dvb) {
/* This device does not support the extension */
@@ -589,16 +592,13 @@
dvb = kzalloc(sizeof(struct cx231xx_dvb), GFP_KERNEL);
if (dvb == NULL) {
- dev_info(dev->dev,
- "cx231xx_dvb: memory allocation failed\n");
+ printk(KERN_INFO "cx231xx_dvb: memory allocation failed\n");
return -ENOMEM;
}
dev->dvb = dvb;
dev->cx231xx_set_analog_freq = cx231xx_set_analog_freq;
dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
- tuner_i2c = cx231xx_get_i2c_adap(dev, dev->board.tuner_i2c_master);
- demod_i2c = cx231xx_get_i2c_adap(dev, dev->board.demod_i2c_master);
mutex_lock(&dev->lock);
cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
cx231xx_demod_reset(dev);
@@ -609,11 +609,11 @@
dev->dvb->frontend = dvb_attach(s5h1432_attach,
&dvico_s5h1432_config,
- demod_i2c);
+ &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
if (dev->dvb->frontend == NULL) {
- dev_err(dev->dev,
- "Failed to attach s5h1432 front end\n");
+ printk(DRIVER_NAME
+ ": Failed to attach s5h1432 front end\n");
result = -EINVAL;
goto out_free;
}
@@ -622,7 +622,7 @@
dvb->frontend->callback = cx231xx_tuner_callback;
if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
- tuner_i2c,
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
&cnxt_rde250_tunerconfig)) {
result = -EINVAL;
goto out_free;
@@ -634,11 +634,11 @@
dev->dvb->frontend = dvb_attach(s5h1411_attach,
&xc5000_s5h1411_config,
- demod_i2c);
+ &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
if (dev->dvb->frontend == NULL) {
- dev_err(dev->dev,
- "Failed to attach s5h1411 front end\n");
+ printk(DRIVER_NAME
+ ": Failed to attach s5h1411 front end\n");
result = -EINVAL;
goto out_free;
}
@@ -647,7 +647,7 @@
dvb->frontend->callback = cx231xx_tuner_callback;
if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
- tuner_i2c,
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
&cnxt_rdu250_tunerconfig)) {
result = -EINVAL;
goto out_free;
@@ -657,11 +657,11 @@
dev->dvb->frontend = dvb_attach(s5h1432_attach,
&dvico_s5h1432_config,
- demod_i2c);
+ &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
if (dev->dvb->frontend == NULL) {
- dev_err(dev->dev,
- "Failed to attach s5h1432 front end\n");
+ printk(DRIVER_NAME
+ ": Failed to attach s5h1432 front end\n");
result = -EINVAL;
goto out_free;
}
@@ -670,7 +670,7 @@
dvb->frontend->callback = cx231xx_tuner_callback;
if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
- 0x60, tuner_i2c,
+ 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
&cnxt_rde253s_tunerconfig)) {
result = -EINVAL;
goto out_free;
@@ -681,11 +681,11 @@
dev->dvb->frontend = dvb_attach(s5h1411_attach,
&tda18271_s5h1411_config,
- demod_i2c);
+ &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
if (dev->dvb->frontend == NULL) {
- dev_err(dev->dev,
- "Failed to attach s5h1411 front end\n");
+ printk(DRIVER_NAME
+ ": Failed to attach s5h1411 front end\n");
result = -EINVAL;
goto out_free;
}
@@ -694,7 +694,7 @@
dvb->frontend->callback = cx231xx_tuner_callback;
if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
- 0x60, tuner_i2c,
+ 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
&cnxt_rde253s_tunerconfig)) {
result = -EINVAL;
goto out_free;
@@ -702,17 +702,16 @@
break;
case CX231XX_BOARD_HAUPPAUGE_EXETER:
- dev_info(dev->dev,
- "%s: looking for tuner / demod on i2c bus: %d\n",
- __func__, i2c_adapter_id(tuner_i2c));
+ printk(KERN_INFO "%s: looking for tuner / demod on i2c bus: %d\n",
+ __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
dev->dvb->frontend = dvb_attach(lgdt3305_attach,
&hcw_lgdt3305_config,
- tuner_i2c);
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap);
if (dev->dvb->frontend == NULL) {
- dev_err(dev->dev,
- "Failed to attach LG3305 front end\n");
+ printk(DRIVER_NAME
+ ": Failed to attach LG3305 front end\n");
result = -EINVAL;
goto out_free;
}
@@ -721,7 +720,7 @@
dvb->frontend->callback = cx231xx_tuner_callback;
dvb_attach(tda18271_attach, dev->dvb->frontend,
- 0x60, tuner_i2c,
+ 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
&hcw_tda18271_config);
break;
@@ -729,12 +728,12 @@
dev->dvb->frontend = dvb_attach(si2165_attach,
&hauppauge_930C_HD_1113xx_si2165_config,
- tuner_i2c
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap
);
if (dev->dvb->frontend == NULL) {
- dev_err(dev->dev,
- "Failed to attach SI2165 front end\n");
+ printk(DRIVER_NAME
+ ": Failed to attach SI2165 front end\n");
result = -EINVAL;
goto out_free;
}
@@ -746,7 +745,7 @@
dvb_attach(tda18271_attach, dev->dvb->frontend,
0x60,
- tuner_i2c,
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
&hcw_tda18271_config);
dev->cx231xx_reset_analog_tuner = NULL;
@@ -762,12 +761,12 @@
dev->dvb->frontend = dvb_attach(si2165_attach,
&pctv_quatro_stick_1114xx_si2165_config,
- tuner_i2c
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap
);
if (dev->dvb->frontend == NULL) {
- dev_err(dev->dev,
- "Failed to attach SI2165 front end\n");
+ printk(DRIVER_NAME
+ ": Failed to attach SI2165 front end\n");
result = -EINVAL;
goto out_free;
}
@@ -787,7 +786,7 @@
request_module("si2157");
client = i2c_new_device(
- tuner_i2c,
+ &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
&info);
if (client == NULL || client->dev.driver == NULL) {
dvb_frontend_detach(dev->dvb->frontend);
@@ -811,17 +810,16 @@
case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
case CX231XX_BOARD_KWORLD_UB430_USB_HYBRID:
- dev_info(dev->dev,
- "%s: looking for demod on i2c bus: %d\n",
- __func__, i2c_adapter_id(tuner_i2c));
+ printk(KERN_INFO "%s: looking for demod on i2c bus: %d\n",
+ __func__, i2c_adapter_id(&dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap));
dev->dvb->frontend = dvb_attach(mb86a20s_attach,
&pv_mb86a20s_config,
- demod_i2c);
+ &dev->i2c_bus[dev->board.demod_i2c_master].i2c_adap);
if (dev->dvb->frontend == NULL) {
- dev_err(dev->dev,
- "Failed to attach mb86a20s demod\n");
+ printk(DRIVER_NAME
+ ": Failed to attach mb86a20s demod\n");
result = -EINVAL;
goto out_free;
}
@@ -830,31 +828,30 @@
dvb->frontend->callback = cx231xx_tuner_callback;
dvb_attach(tda18271_attach, dev->dvb->frontend,
- 0x60, tuner_i2c,
+ 0x60, &dev->i2c_bus[dev->board.tuner_i2c_master].i2c_adap,
&pv_tda18271_config);
break;
default:
- dev_err(dev->dev,
- "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n",
- dev->name);
+ printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card"
+ " isn't supported yet\n", dev->name);
break;
}
if (NULL == dvb->frontend) {
- dev_err(dev->dev,
+ printk(KERN_ERR
"%s/2: frontend initialization failed\n", dev->name);
result = -EINVAL;
goto out_free;
}
/* register everything */
- result = register_dvb(dvb, THIS_MODULE, dev, dev->dev);
+ result = register_dvb(dvb, THIS_MODULE, dev, &dev->udev->dev);
if (result < 0)
goto out_free;
- dev_info(dev->dev, "Successfully loaded cx231xx-dvb\n");
+ printk(KERN_INFO "Successfully loaded cx231xx-dvb\n");
ret:
cx231xx_set_mode(dev, CX231XX_SUSPEND);
diff --git a/drivers/media/usb/cx231xx/cx231xx-i2c.c b/drivers/media/usb/cx231xx/cx231xx-i2c.c
index a29c345..7c0f797 100644
--- a/drivers/media/usb/cx231xx/cx231xx-i2c.c
+++ b/drivers/media/usb/cx231xx/cx231xx-i2c.c
@@ -20,14 +20,14 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "cx231xx.h"
#include <linux/module.h>
#include <linux/kernel.h>
+#include <linux/usb.h>
#include <linux/i2c.h>
-#include <linux/i2c-mux.h>
#include <media/v4l2-common.h>
#include <media/tuner.h>
+#include "cx231xx.h"
/* ----------------------------------------------------------- */
@@ -54,19 +54,10 @@
} \
} while (0)
-static inline int get_real_i2c_port(struct cx231xx *dev, int bus_nr)
-{
- if (bus_nr == 1)
- return dev->port_3_switch_enabled ? I2C_1_MUX_3 : I2C_1_MUX_1;
- return bus_nr;
-}
-
static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus,
const struct i2c_msg *msg, int tuner_type)
{
- int i2c_port = get_real_i2c_port(dev, bus->nr);
-
- if (i2c_port != dev->board.tuner_i2c_master)
+ if (bus->nr != dev->board.tuner_i2c_master)
return false;
if (msg->addr != dev->board.tuner_addr)
@@ -349,15 +340,14 @@
struct cx231xx *dev = bus->dev;
struct cx231xx_i2c_xfer_data req_data;
int status = 0;
- u8 buf[1];
/* prepare xfer_data struct */
req_data.dev_addr = msg->addr;
- req_data.direction = I2C_M_RD;
+ req_data.direction = msg->flags;
req_data.saddr_len = 0;
req_data.saddr_dat = 0;
- req_data.buf_size = 1;
- req_data.p_buffer = buf;
+ req_data.buf_size = 0;
+ req_data.p_buffer = NULL;
/* usb send command */
status = dev->cx231xx_send_usb_command(bus, &req_data);
@@ -465,14 +455,17 @@
.algo = &cx231xx_algo,
};
+static struct i2c_client cx231xx_client_template = {
+ .name = "cx231xx internal",
+};
+
/* ----------------------------------------------------------- */
/*
* i2c_devs
* incomplete list of known devices
*/
-static const char *i2c_devs[128] = {
- [0x20 >> 1] = "demod",
+static char *i2c_devs[128] = {
[0x60 >> 1] = "colibri",
[0x88 >> 1] = "hammerhead",
[0x8e >> 1] = "CIR",
@@ -487,34 +480,22 @@
* cx231xx_do_i2c_scan()
* check i2c address range for devices
*/
-void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port)
+void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c)
{
unsigned char buf;
int i, rc;
- struct i2c_client client;
- if (!i2c_scan)
- return;
-
- /* Don't generate I2C errors during scan */
- dev->i2c_scan_running = true;
-
- memset(&client, 0, sizeof(client));
- client.adapter = cx231xx_get_i2c_adap(dev, i2c_port);
-
+ cx231xx_info(": Checking for I2C devices ..\n");
for (i = 0; i < 128; i++) {
- client.addr = i;
- rc = i2c_master_recv(&client, &buf, 0);
+ c->addr = i;
+ rc = i2c_master_recv(c, &buf, 0);
if (rc < 0)
continue;
- dev_info(dev->dev,
- "i2c scan: found device @ port %d addr 0x%x [%s]\n",
- i2c_port,
- i << 1,
- i2c_devs[i] ? i2c_devs[i] : "???");
+ cx231xx_info("%s: i2c scan: found device @ 0x%x [%s]\n",
+ dev->name, i << 1,
+ i2c_devs[i] ? i2c_devs[i] : "???");
}
-
- dev->i2c_scan_running = false;
+ cx231xx_info(": Completed Checking for I2C devices.\n");
}
/*
@@ -528,17 +509,23 @@
BUG_ON(!dev->cx231xx_send_usb_command);
bus->i2c_adap = cx231xx_adap_template;
- bus->i2c_adap.dev.parent = dev->dev;
+ bus->i2c_client = cx231xx_client_template;
+ bus->i2c_adap.dev.parent = &dev->udev->dev;
- snprintf(bus->i2c_adap.name, sizeof(bus->i2c_adap.name), "%s-%d", bus->dev->name, bus->nr);
+ strlcpy(bus->i2c_adap.name, bus->dev->name, sizeof(bus->i2c_adap.name));
bus->i2c_adap.algo_data = bus;
i2c_set_adapdata(&bus->i2c_adap, &dev->v4l2_dev);
i2c_add_adapter(&bus->i2c_adap);
- if (0 != bus->i2c_rc)
- dev_warn(dev->dev,
- "i2c bus %d register FAILED\n", bus->nr);
+ bus->i2c_client.adapter = &bus->i2c_adap;
+
+ if (0 == bus->i2c_rc) {
+ if (i2c_scan)
+ cx231xx_do_i2c_scan(dev, &bus->i2c_client);
+ } else
+ cx231xx_warn("%s: i2c bus %d register FAILED\n",
+ dev->name, bus->nr);
return bus->i2c_rc;
}
@@ -552,62 +539,3 @@
i2c_del_adapter(&bus->i2c_adap);
return 0;
}
-
-/*
- * cx231xx_i2c_mux_select()
- * switch i2c master number 1 between port1 and port3
- */
-static int cx231xx_i2c_mux_select(struct i2c_adapter *adap,
- void *mux_priv, u32 chan_id)
-{
- struct cx231xx *dev = mux_priv;
-
- return cx231xx_enable_i2c_port_3(dev, chan_id);
-}
-
-int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no)
-{
- struct i2c_adapter *i2c_parent = &dev->i2c_bus[1].i2c_adap;
- /* what is the correct mux_dev? */
- struct device *mux_dev = dev->dev;
-
- dev->i2c_mux_adap[mux_no] = i2c_add_mux_adapter(i2c_parent,
- mux_dev,
- dev /* mux_priv */,
- 0,
- mux_no /* chan_id */,
- 0 /* class */,
- &cx231xx_i2c_mux_select,
- NULL);
-
- if (!dev->i2c_mux_adap[mux_no])
- dev_warn(dev->dev,
- "i2c mux %d register FAILED\n", mux_no);
-
- return 0;
-}
-
-void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no)
-{
- i2c_del_mux_adapter(dev->i2c_mux_adap[mux_no]);
- dev->i2c_mux_adap[mux_no] = NULL;
-}
-
-struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port)
-{
- switch (i2c_port) {
- case I2C_0:
- return &dev->i2c_bus[0].i2c_adap;
- case I2C_1:
- return &dev->i2c_bus[1].i2c_adap;
- case I2C_2:
- return &dev->i2c_bus[2].i2c_adap;
- case I2C_1_MUX_1:
- return dev->i2c_mux_adap[0];
- case I2C_1_MUX_3:
- return dev->i2c_mux_adap[1];
- default:
- return NULL;
- }
-}
-EXPORT_SYMBOL_GPL(cx231xx_get_i2c_adap);
diff --git a/drivers/media/usb/cx231xx/cx231xx-input.c b/drivers/media/usb/cx231xx/cx231xx-input.c
index 15d8d1b..05f0434 100644
--- a/drivers/media/usb/cx231xx/cx231xx-input.c
+++ b/drivers/media/usb/cx231xx/cx231xx-input.c
@@ -19,6 +19,7 @@
*/
#include "cx231xx.h"
+#include <linux/usb.h>
#include <linux/slab.h>
#include <linux/bitrev.h>
@@ -62,7 +63,7 @@
struct i2c_board_info info;
u8 ir_i2c_bus;
- dev_dbg(dev->dev, "%s\n", __func__);
+ dev_dbg(&dev->udev->dev, "%s\n", __func__);
/* Only initialize if a rc keycode map is defined */
if (!cx231xx_boards[dev->model].rc_map_name)
@@ -97,10 +98,9 @@
/* Load and bind ir-kbd-i2c */
ir_i2c_bus = cx231xx_boards[dev->model].ir_i2c_master;
- dev_dbg(dev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
+ dev_dbg(&dev->udev->dev, "Trying to bind ir at bus %d, addr 0x%02x\n",
ir_i2c_bus, info.addr);
- dev->ir_i2c_client = i2c_new_device(
- cx231xx_get_i2c_adap(dev, ir_i2c_bus), &info);
+ dev->ir_i2c_client = i2c_new_device(&dev->i2c_bus[ir_i2c_bus].i2c_adap, &info);
return 0;
}
diff --git a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
index 5bc7414..3052c4c 100644
--- a/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
+++ b/drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c
@@ -703,9 +703,9 @@
_current_scenario_idx = INDEX_BUSPOWER_DIF_ONLY;
break;
default:
- dev_err(dev->dev,
- "bad config in buspower!!!!\nconfig_info=%x\n",
- config_info & BUSPOWER_MASK);
+ cx231xx_info("bad config in buspower!!!!\n");
+ cx231xx_info("config_info=%x\n",
+ (config_info & BUSPOWER_MASK));
return 1;
}
} else { /* self-power */
@@ -768,9 +768,9 @@
_current_scenario_idx = INDEX_SELFPOWER_COMPRESSOR;
break;
default:
- dev_err(dev->dev,
- "bad senario!!!!!\nconfig_info=%x\n",
- config_info & SELFPOWER_MASK);
+ cx231xx_info("bad senario!!!!!\n");
+ cx231xx_info("config_info=%x\n",
+ (config_info & SELFPOWER_MASK));
return -ENODEV;
}
}
@@ -781,29 +781,18 @@
sizeof(struct pcb_config));
if (pcb_debug) {
- dev_info(dev->dev,
- "SC(0x00) register = 0x%x\n", config_info);
- dev_info(dev->dev,
- "scenario %d\n",
- (dev->current_pcb_config.index) + 1);
- dev_info(dev->dev,
- "type=%x\n",
- dev->current_pcb_config.type);
- dev_info(dev->dev,
- "mode=%x\n",
- dev->current_pcb_config.mode);
- dev_info(dev->dev,
- "speed=%x\n",
- dev->current_pcb_config.speed);
- dev_info(dev->dev,
- "ts1_source=%x\n",
- dev->current_pcb_config.ts1_source);
- dev_info(dev->dev,
- "ts2_source=%x\n",
- dev->current_pcb_config.ts2_source);
- dev_info(dev->dev,
- "analog_source=%x\n",
- dev->current_pcb_config.analog_source);
+ cx231xx_info("SC(0x00) register = 0x%x\n", config_info);
+ cx231xx_info("scenario %d\n",
+ (dev->current_pcb_config.index) + 1);
+ cx231xx_info("type=%x\n", dev->current_pcb_config.type);
+ cx231xx_info("mode=%x\n", dev->current_pcb_config.mode);
+ cx231xx_info("speed=%x\n", dev->current_pcb_config.speed);
+ cx231xx_info("ts1_source=%x\n",
+ dev->current_pcb_config.ts1_source);
+ cx231xx_info("ts2_source=%x\n",
+ dev->current_pcb_config.ts2_source);
+ cx231xx_info("analog_source=%x\n",
+ dev->current_pcb_config.analog_source);
}
return 0;
diff --git a/drivers/media/usb/cx231xx/cx231xx-vbi.c b/drivers/media/usb/cx231xx/cx231xx-vbi.c
index 80261ac..c027942 100644
--- a/drivers/media/usb/cx231xx/cx231xx-vbi.c
+++ b/drivers/media/usb/cx231xx/cx231xx-vbi.c
@@ -19,12 +19,12 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "cx231xx.h"
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/bitmap.h>
+#include <linux/usb.h>
#include <linux/i2c.h>
#include <linux/mm.h>
#include <linux/mutex.h>
@@ -35,6 +35,7 @@
#include <media/msp3400.h>
#include <media/tuner.h>
+#include "cx231xx.h"
#include "cx231xx-vbi.h"
static inline void print_err_status(struct cx231xx *dev, int packet, int status)
@@ -68,12 +69,11 @@
break;
}
if (packet < 0) {
- dev_err(dev->dev,
- "URB status %d [%s].\n", status, errmsg);
+ cx231xx_err("URB status %d [%s].\n", status,
+ errmsg);
} else {
- dev_err(dev->dev,
- "URB packet %d, status %d [%s].\n",
- packet, status, errmsg);
+ cx231xx_err("URB packet %d, status %d [%s].\n",
+ packet, status, errmsg);
}
}
@@ -316,8 +316,8 @@
case -ESHUTDOWN:
return;
default: /* error */
- dev_err(dev->dev,
- "urb completition error %d.\n", urb->status);
+ cx231xx_err("urb completition error %d.\n",
+ urb->status);
break;
}
@@ -331,8 +331,8 @@
urb->status = usb_submit_urb(urb, GFP_ATOMIC);
if (urb->status) {
- dev_err(dev->dev, "urb resubmit failed (error=%i)\n",
- urb->status);
+ cx231xx_err("urb resubmit failed (error=%i)\n",
+ urb->status);
}
}
@@ -344,7 +344,7 @@
struct urb *urb;
int i;
- dev_dbg(dev->dev, "called cx231xx_uninit_vbi_isoc\n");
+ cx231xx_info("called cx231xx_uninit_vbi_isoc\n");
dev->vbi_mode.bulk_ctl.nfields = -1;
for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
@@ -393,7 +393,7 @@
struct urb *urb;
int rc;
- dev_dbg(dev->dev, "called cx231xx_vbi_isoc\n");
+ cx231xx_info("called cx231xx_vbi_isoc\n");
/* De-allocates all pending stuff */
cx231xx_uninit_vbi_isoc(dev);
@@ -419,16 +419,14 @@
dev->vbi_mode.bulk_ctl.urb = kzalloc(sizeof(void *) * num_bufs,
GFP_KERNEL);
if (!dev->vbi_mode.bulk_ctl.urb) {
- dev_err(dev->dev,
- "cannot alloc memory for usb buffers\n");
+ cx231xx_errdev("cannot alloc memory for usb buffers\n");
return -ENOMEM;
}
dev->vbi_mode.bulk_ctl.transfer_buffer =
kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
if (!dev->vbi_mode.bulk_ctl.transfer_buffer) {
- dev_err(dev->dev,
- "cannot allocate memory for usbtransfer\n");
+ cx231xx_errdev("cannot allocate memory for usbtransfer\n");
kfree(dev->vbi_mode.bulk_ctl.urb);
return -ENOMEM;
}
@@ -443,8 +441,7 @@
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) {
- dev_err(dev->dev,
- "cannot alloc bulk_ctl.urb %i\n", i);
+ cx231xx_err("cannot alloc bulk_ctl.urb %i\n", i);
cx231xx_uninit_vbi_isoc(dev);
return -ENOMEM;
}
@@ -454,10 +451,9 @@
dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
kzalloc(sb_size, GFP_KERNEL);
if (!dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
- dev_err(dev->dev,
- "unable to allocate %i bytes for transfer buffer %i%s\n",
- sb_size, i,
- in_interrupt() ? " while in int" : "");
+ cx231xx_err("unable to allocate %i bytes for transfer"
+ " buffer %i%s\n", sb_size, i,
+ in_interrupt() ? " while in int" : "");
cx231xx_uninit_vbi_isoc(dev);
return -ENOMEM;
}
@@ -474,8 +470,8 @@
for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
rc = usb_submit_urb(dev->vbi_mode.bulk_ctl.urb[i], GFP_ATOMIC);
if (rc) {
- dev_err(dev->dev,
- "submit of urb %i failed (error=%i)\n", i, rc);
+ cx231xx_err("submit of urb %i failed (error=%i)\n", i,
+ rc);
cx231xx_uninit_vbi_isoc(dev);
return rc;
}
@@ -526,7 +522,7 @@
struct cx231xx_buffer *buf)
{
/* Advice that buffer was filled */
- /* dev_dbg(dev->dev, "[%p/%d] wakeup\n", buf, buf->vb.i); */
+ /* cx231xx_info("[%p/%d] wakeup\n", buf, buf->vb.i); */
buf->vb.state = VIDEOBUF_DONE;
buf->vb.field_count++;
@@ -618,7 +614,7 @@
char *outp;
if (list_empty(&dma_q->active)) {
- dev_err(dev->dev, "No active queue to serve\n");
+ cx231xx_err("No active queue to serve\n");
dev->vbi_mode.bulk_ctl.buf = NULL;
*buf = NULL;
return;
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
index d72d74e..425080b 100644
--- a/drivers/media/usb/cx231xx/cx231xx-video.c
+++ b/drivers/media/usb/cx231xx/cx231xx-video.c
@@ -22,12 +22,12 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include "cx231xx.h"
#include <linux/init.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/bitmap.h>
+#include <linux/usb.h>
#include <linux/i2c.h>
#include <linux/mm.h>
#include <linux/mutex.h>
@@ -41,9 +41,10 @@
#include "dvb_frontend.h"
+#include "cx231xx.h"
#include "cx231xx-vbi.h"
-#define CX231XX_VERSION "0.0.3"
+#define CX231XX_VERSION "0.0.2"
#define DRIVER_AUTHOR "Srinivasa Deevi <srinivasa.deevi@conexant.com>"
#define DRIVER_DESC "Conexant cx231xx based USB video device driver"
@@ -736,9 +737,8 @@
if (!dev->video_mode.bulk_ctl.num_bufs)
urb_init = 1;
}
- dev_dbg(dev->dev,
- "urb_init=%d dev->video_mode.max_pkt_size=%d\n",
- urb_init, dev->video_mode.max_pkt_size);
+ /*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
+ urb_init, dev->video_mode.max_pkt_size);*/
if (urb_init) {
dev->mode_tv = 0;
if (dev->USE_ISO)
@@ -809,7 +809,7 @@
cx231xx_set_audio_input(dev, dev->ctl_ainput);
- dev_dbg(dev->dev, "video_mux : %d\n", index);
+ cx231xx_info("video_mux : %d\n", index);
/* do mode control overrides if required */
cx231xx_do_mode_ctrl_overrides(dev);
@@ -861,7 +861,7 @@
static int check_dev(struct cx231xx *dev)
{
if (dev->state & DEV_DISCONNECTED) {
- dev_err(dev->dev, "v4l2 ioctl: device not present\n");
+ cx231xx_errdev("v4l2 ioctl: device not present\n");
return -ENODEV;
}
return 0;
@@ -953,13 +953,12 @@
return -EINVAL;
if (videobuf_queue_is_busy(&fh->vb_vidq)) {
- dev_err(dev->dev, "%s: queue busy\n", __func__);
+ cx231xx_errdev("%s queue busy\n", __func__);
return -EBUSY;
}
if (dev->stream_on && !fh->stream_on) {
- dev_err(dev->dev,
- "%s: device in use by another fh\n", __func__);
+ cx231xx_errdev("%s device in use by another fh\n", __func__);
return -EBUSY;
}
@@ -968,7 +967,7 @@
dev->height = f->fmt.pix.height;
dev->format = fmt;
- v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, MEDIA_BUS_FMT_FIXED);
+ v4l2_fill_mbus_format(&mbus_fmt, &f->fmt.pix, V4L2_MBUS_FMT_FIXED);
call_all(dev, video, s_mbus_fmt, &mbus_fmt);
v4l2_fill_pix_format(&f->fmt.pix, &mbus_fmt);
@@ -1013,7 +1012,7 @@
resolution (since a standard change effects things like the number
of lines in VACT, etc) */
memset(&mbus_fmt, 0, sizeof(mbus_fmt));
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
+ mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
mbus_fmt.width = dev->width;
mbus_fmt.height = dev->height;
call_all(dev, video, s_mbus_fmt, &mbus_fmt);
@@ -1177,9 +1176,9 @@
int rc;
u32 if_frequency = 5400000;
- dev_dbg(dev->dev,
- "Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
- f->frequency, f->type);
+ cx231xx_info("Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
+ f->frequency, f->type);
+ /*cx231xx_info("f->type: 1-radio 2-analogTV 3-digitalTV\n");*/
rc = check_dev(dev);
if (rc < 0)
@@ -1214,14 +1213,13 @@
else if (dev->norm & V4L2_STD_SECAM_LC)
if_frequency = 1250000; /*1.25MHz */
- dev_dbg(dev->dev,
- "if_frequency is set to %d\n", if_frequency);
+ cx231xx_info("if_frequency is set to %d\n", if_frequency);
cx231xx_set_Colibri_For_LowIF(dev, if_frequency, 1, 1);
update_HH_register_after_set_DIF(dev);
}
- dev_dbg(dev->dev, "Set New FREQUENCY to %d\n", f->frequency);
+ cx231xx_info("Set New FREQUENCY to %d\n", f->frequency);
return rc;
}
@@ -1525,8 +1523,7 @@
struct cx231xx *dev = fh->dev;
if (dev->vbi_stream_on && !fh->stream_on) {
- dev_err(dev->dev,
- "%s device in use by another fh\n", __func__);
+ cx231xx_errdev("%s device in use by another fh\n", __func__);
return -EBUSY;
}
return vidioc_try_fmt_vbi_cap(file, priv, f);
@@ -1645,15 +1642,17 @@
#if 0
errCode = cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
if (errCode < 0) {
- dev_err(dev->dev,
- "Device locked on digital mode. Can't open analog\n");
+ cx231xx_errdev
+ ("Device locked on digital mode. Can't open analog\n");
return -EBUSY;
}
#endif
fh = kzalloc(sizeof(struct cx231xx_fh), GFP_KERNEL);
- if (!fh)
+ if (!fh) {
+ cx231xx_errdev("cx231xx-video.c: Out of memory?!\n");
return -ENOMEM;
+ }
if (mutex_lock_interruptible(&dev->lock)) {
kfree(fh);
return -ERESTARTSYS;
@@ -1737,8 +1736,8 @@
dev->radio_dev = NULL;
}
if (dev->vbi_dev) {
- dev_info(dev->dev, "V4L2 device %s deregistered\n",
- video_device_node_name(dev->vbi_dev));
+ cx231xx_info("V4L2 device %s deregistered\n",
+ video_device_node_name(dev->vbi_dev));
if (video_is_registered(dev->vbi_dev))
video_unregister_device(dev->vbi_dev);
else
@@ -1746,8 +1745,8 @@
dev->vbi_dev = NULL;
}
if (dev->vdev) {
- dev_info(dev->dev, "V4L2 device %s deregistered\n",
- video_device_node_name(dev->vdev));
+ cx231xx_info("V4L2 device %s deregistered\n",
+ video_device_node_name(dev->vdev));
if (dev->board.has_417)
cx231xx_417_unregister(dev);
@@ -2081,7 +2080,8 @@
{
int ret;
- dev_info(dev->dev, "v4l2 driver version %s\n", CX231XX_VERSION);
+ cx231xx_info("%s: v4l2 driver version %s\n",
+ dev->name, CX231XX_VERSION);
/* set default norm */
dev->norm = V4L2_STD_PAL;
@@ -2119,7 +2119,7 @@
/* allocate and fill video video_device struct */
dev->vdev = cx231xx_vdev_init(dev, &cx231xx_video_template, "video");
if (!dev->vdev) {
- dev_err(dev->dev, "cannot allocate video_device.\n");
+ cx231xx_errdev("cannot allocate video_device.\n");
return -ENODEV;
}
@@ -2128,14 +2128,13 @@
ret = video_register_device(dev->vdev, VFL_TYPE_GRABBER,
video_nr[dev->devno]);
if (ret) {
- dev_err(dev->dev,
- "unable to register video device (error=%i).\n",
- ret);
+ cx231xx_errdev("unable to register video device (error=%i).\n",
+ ret);
return ret;
}
- dev_info(dev->dev, "Registered video device %s [v4l2]\n",
- video_device_node_name(dev->vdev));
+ cx231xx_info("%s/0: registered device %s [v4l2]\n",
+ dev->name, video_device_node_name(dev->vdev));
/* Initialize VBI template */
cx231xx_vbi_template = cx231xx_video_template;
@@ -2145,7 +2144,7 @@
dev->vbi_dev = cx231xx_vdev_init(dev, &cx231xx_vbi_template, "vbi");
if (!dev->vbi_dev) {
- dev_err(dev->dev, "cannot allocate video_device.\n");
+ cx231xx_errdev("cannot allocate video_device.\n");
return -ENODEV;
}
dev->vbi_dev->ctrl_handler = &dev->ctrl_handler;
@@ -2153,32 +2152,34 @@
ret = video_register_device(dev->vbi_dev, VFL_TYPE_VBI,
vbi_nr[dev->devno]);
if (ret < 0) {
- dev_err(dev->dev, "unable to register vbi device\n");
+ cx231xx_errdev("unable to register vbi device\n");
return ret;
}
- dev_info(dev->dev, "Registered VBI device %s\n",
- video_device_node_name(dev->vbi_dev));
+ cx231xx_info("%s/0: registered device %s\n",
+ dev->name, video_device_node_name(dev->vbi_dev));
if (cx231xx_boards[dev->model].radio.type == CX231XX_RADIO) {
dev->radio_dev = cx231xx_vdev_init(dev, &cx231xx_radio_template,
"radio");
if (!dev->radio_dev) {
- dev_err(dev->dev,
- "cannot allocate video_device.\n");
+ cx231xx_errdev("cannot allocate video_device.\n");
return -ENODEV;
}
dev->radio_dev->ctrl_handler = &dev->radio_ctrl_handler;
ret = video_register_device(dev->radio_dev, VFL_TYPE_RADIO,
radio_nr[dev->devno]);
if (ret < 0) {
- dev_err(dev->dev,
- "can't register radio device\n");
+ cx231xx_errdev("can't register radio device\n");
return ret;
}
- dev_info(dev->dev, "Registered radio device as %s\n",
- video_device_node_name(dev->radio_dev));
+ cx231xx_info("Registered radio device as %s\n",
+ video_device_node_name(dev->radio_dev));
}
+ cx231xx_info("V4L2 device registered as %s and %s\n",
+ video_device_node_name(dev->vdev),
+ video_device_node_name(dev->vbi_dev));
+
return 0;
}
diff --git a/drivers/media/usb/cx231xx/cx231xx.h b/drivers/media/usb/cx231xx/cx231xx.h
index 2ebe7c4..d607c5c 100644
--- a/drivers/media/usb/cx231xx/cx231xx.h
+++ b/drivers/media/usb/cx231xx/cx231xx.h
@@ -28,7 +28,6 @@
#include <linux/i2c.h>
#include <linux/workqueue.h>
#include <linux/mutex.h>
-#include <linux/usb.h>
#include <media/cx2341x.h>
@@ -323,11 +322,10 @@
};
enum CX231XX_I2C_MASTER_PORT {
- I2C_0 = 0, /* master 0 - internal connection */
- I2C_1 = 1, /* master 1 - used with mux */
- I2C_2 = 2, /* master 2 */
- I2C_1_MUX_1 = 3, /* master 1 - port 1 (I2C_DEMOD_EN = 0) */
- I2C_1_MUX_3 = 4 /* master 1 - port 3 (I2C_DEMOD_EN = 1) */
+ I2C_0 = 0,
+ I2C_1 = 1,
+ I2C_2 = 2,
+ I2C_3 = 3
};
struct cx231xx_board {
@@ -369,6 +367,7 @@
unsigned int valid:1;
unsigned int no_alt_vanc:1;
unsigned int external_av:1;
+ unsigned int dont_use_port_3:1;
unsigned char xclk, i2c_speed;
@@ -473,6 +472,7 @@
/* i2c i/o */
struct i2c_adapter i2c_adap;
+ struct i2c_client i2c_client;
u32 i2c_rc;
/* different settings for each bus */
@@ -597,7 +597,6 @@
char name[30]; /* name (including minor) of the device */
int model; /* index in the device_data struct */
int devno; /* marks the number of this device */
- struct device *dev; /* pointer to USB interface's dev */
struct cx231xx_board board;
@@ -610,8 +609,6 @@
unsigned int has_audio_class:1;
unsigned int has_alsa_audio:1;
- unsigned int i2c_scan_running:1; /* true only during i2c_scan */
-
struct cx231xx_fmt *format;
struct v4l2_device v4l2_dev;
@@ -631,10 +628,7 @@
/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
struct cx231xx_i2c i2c_bus[3];
- struct i2c_adapter *i2c_mux_adap[2];
-
unsigned int xc_fw_load_done:1;
- unsigned int port_3_switch_enabled:1;
/* locks */
struct mutex gpio_i2c_lock;
struct mutex i2c_lock;
@@ -757,12 +751,9 @@
int cx231xx_reset_analog_tuner(struct cx231xx *dev);
/* Provided by cx231xx-i2c.c */
-void cx231xx_do_i2c_scan(struct cx231xx *dev, int i2c_port);
+void cx231xx_do_i2c_scan(struct cx231xx *dev, struct i2c_client *c);
int cx231xx_i2c_register(struct cx231xx_i2c *bus);
int cx231xx_i2c_unregister(struct cx231xx_i2c *bus);
-int cx231xx_i2c_mux_register(struct cx231xx *dev, int mux_no);
-void cx231xx_i2c_mux_unregister(struct cx231xx *dev, int mux_no);
-struct i2c_adapter *cx231xx_get_i2c_adap(struct cx231xx *dev, int i2c_port);
/* Internal block control functions */
int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
@@ -811,6 +802,7 @@
void reset_s5h1432_demod(struct cx231xx *dev);
void cx231xx_dump_HH_reg(struct cx231xx *dev);
void update_HH_register_after_set_DIF(struct cx231xx *dev);
+void cx231xx_dump_SC_reg(struct cx231xx *dev);
@@ -984,6 +976,23 @@
#define cx231xx_ir_exit(dev) (0)
#endif
+
+/* printk macros */
+
+#define cx231xx_err(fmt, arg...) do {\
+ printk(KERN_ERR fmt , ##arg); } while (0)
+
+#define cx231xx_errdev(fmt, arg...) do {\
+ printk(KERN_ERR "%s: "fmt,\
+ dev->name , ##arg); } while (0)
+
+#define cx231xx_info(fmt, arg...) do {\
+ printk(KERN_INFO "%s: "fmt,\
+ dev->name , ##arg); } while (0)
+#define cx231xx_warn(fmt, arg...) do {\
+ printk(KERN_WARNING "%s: "fmt,\
+ dev->name , ##arg); } while (0)
+
static inline unsigned int norm_maxw(struct cx231xx *dev)
{
if (dev->board.max_range_640_480)
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index cf2482f..3d39fb7 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -31,7 +31,7 @@
Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
config DVB_USB_AF9035
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Afatech AF9035 DVB-T USB2.0 support"
depends on m
depends on DVB_USB_V2
@@ -46,7 +46,7 @@
Say Y here to support the Afatech AF9035 based DVB USB receiver.
config DVB_USB_ANYSEE
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Anysee DVB-T/C USB2.0 support"
depends on m
depends on DVB_USB_V2
@@ -138,7 +138,7 @@
Say Y here to support the MxL111SF USB2.0 DTV receiver.
config DVB_USB_RTL28XXU
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Realtek RTL28xxU DVB USB support"
depends on m
depends on DVB_USB_V2 && I2C_MUX
@@ -157,14 +157,11 @@
Say Y here to support the Realtek RTL28xxU DVB USB receiver.
config DVB_USB_DVBSKY
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "DVBSky USB support"
depends on m
depends on DVB_USB_V2
select DVB_M88DS3103 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_M88TS2022 if MEDIA_SUBDRV_AUTOSELECT
- select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
- select DVB_SP2 if MEDIA_SUBDRV_AUTOSELECT
help
Say Y here to support the USB receivers from DVBSky.
diff --git a/drivers/media/usb/dvb-usb-v2/af9035.c b/drivers/media/usb/dvb-usb-v2/af9035.c
index 5541221..badc331 100644
--- a/drivers/media/usb/dvb-usb-v2/af9035.c
+++ b/drivers/media/usb/dvb-usb-v2/af9035.c
@@ -193,8 +193,8 @@
return af9035_wr_regs(d, reg, &val, 1);
}
-static int af9035_add_i2c_dev(struct dvb_usb_device *d, const char *type,
- u8 addr, void *platform_data, struct i2c_adapter *adapter)
+static int af9035_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
+ void *platform_data, struct i2c_adapter *adapter)
{
int ret, num;
struct state *state = d_to_priv(d);
@@ -221,7 +221,7 @@
goto err;
}
- request_module("%s", board_info.type);
+ request_module(board_info.type);
/* register I2C device */
client = i2c_new_device(adapter, &board_info);
@@ -1171,7 +1171,6 @@
dev_dbg(&d->udev->dev, "adap->id=%d\n", adap->id);
- memset(&si2168_config, 0, sizeof(si2168_config));
si2168_config.i2c_adapter = &adapter;
si2168_config.fe = &adap->fe[0];
si2168_config.ts_mode = SI2168_TS_SERIAL;
diff --git a/drivers/media/usb/dvb-usb-v2/anysee.c b/drivers/media/usb/dvb-usb-v2/anysee.c
index fd5d0e6..8c5ec72 100644
--- a/drivers/media/usb/dvb-usb-v2/anysee.c
+++ b/drivers/media/usb/dvb-usb-v2/anysee.c
@@ -630,8 +630,8 @@
return ret;
}
-static int anysee_add_i2c_dev(struct dvb_usb_device *d, const char *type,
- u8 addr, void *platform_data)
+static int anysee_add_i2c_dev(struct dvb_usb_device *d, char *type, u8 addr,
+ void *platform_data)
{
int ret, num;
struct anysee_state *state = d_to_priv(d);
@@ -659,7 +659,7 @@
goto err;
}
- request_module("%s", board_info.type);
+ request_module(board_info.type);
/* register I2C device */
client = i2c_new_device(adapter, &board_info);
diff --git a/drivers/media/usb/dvb-usb-v2/dvbsky.c b/drivers/media/usb/dvb-usb-v2/dvbsky.c
index bfc85ed..0b41401 100644
--- a/drivers/media/usb/dvb-usb-v2/dvbsky.c
+++ b/drivers/media/usb/dvb-usb-v2/dvbsky.c
@@ -21,17 +21,10 @@
#include "dvb_usb.h"
#include "m88ds3103.h"
#include "m88ts2022.h"
-#include "sp2.h"
-#include "si2168.h"
-#include "si2157.h"
#define DVBSKY_MSG_DELAY 0/*2000*/
#define DVBSKY_BUF_LEN 64
-static int dvb_usb_dvbsky_disable_rc;
-module_param_named(disable_rc, dvb_usb_dvbsky_disable_rc, int, 0644);
-MODULE_PARM_DESC(disable_rc, "Disable inbuilt IR receiver.");
-
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
struct dvbsky_state {
@@ -39,9 +32,7 @@
u8 ibuf[DVBSKY_BUF_LEN];
u8 obuf[DVBSKY_BUF_LEN];
u8 last_lock;
- struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
- struct i2c_client *i2c_client_ci;
/* fe hook functions*/
int (*fe_set_voltage)(struct dvb_frontend *fe,
@@ -105,7 +96,8 @@
obuf[2] = value;
ret = dvbsky_usb_generic_rw(d, obuf, 3, ibuf, 1);
if (ret)
- dev_err(&d->udev->dev, "failed=%d\n", ret);
+ dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+ KBUILD_MODNAME, __func__, ret);
return ret;
}
@@ -122,7 +114,7 @@
if (num > 2) {
dev_err(&d->udev->dev,
- "too many i2c messages[%d], max 2.", num);
+ "dvbsky_usb: too many i2c messages[%d] than 2.", num);
ret = -EOPNOTSUPP;
goto i2c_error;
}
@@ -130,7 +122,7 @@
if (num == 1) {
if (msg[0].len > 60) {
dev_err(&d->udev->dev,
- "too many i2c bytes[%d], max 60.",
+ "dvbsky_usb: too many i2c bytes[%d] than 60.",
msg[0].len);
ret = -EOPNOTSUPP;
goto i2c_error;
@@ -144,7 +136,8 @@
ret = dvbsky_usb_generic_rw(d, obuf, 4,
ibuf, msg[0].len + 1);
if (ret)
- dev_err(&d->udev->dev, "failed=%d\n", ret);
+ dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+ KBUILD_MODNAME, __func__, ret);
if (!ret)
memcpy(msg[0].buf, &ibuf[1], msg[0].len);
} else {
@@ -156,12 +149,13 @@
ret = dvbsky_usb_generic_rw(d, obuf,
msg[0].len + 3, ibuf, 1);
if (ret)
- dev_err(&d->udev->dev, "failed=%d\n", ret);
+ dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+ KBUILD_MODNAME, __func__, ret);
}
} else {
if ((msg[0].len > 60) || (msg[1].len > 60)) {
dev_err(&d->udev->dev,
- "too many i2c bytes[w-%d][r-%d], max 60.",
+ "dvbsky_usb: too many i2c bytes[w-%d][r-%d] than 60.",
msg[0].len, msg[1].len);
ret = -EOPNOTSUPP;
goto i2c_error;
@@ -175,7 +169,8 @@
ret = dvbsky_usb_generic_rw(d, obuf,
msg[0].len + 4, ibuf, msg[1].len + 1);
if (ret)
- dev_err(&d->udev->dev, "failed=%d\n", ret);
+ dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+ KBUILD_MODNAME, __func__, ret);
if (!ret)
memcpy(msg[1].buf, &ibuf[1], msg[1].len);
@@ -206,7 +201,8 @@
obuf[0] = 0x10;
ret = dvbsky_usb_generic_rw(d, obuf, 1, ibuf, 2);
if (ret)
- dev_err(&d->udev->dev, "failed=%d\n", ret);
+ dev_err(&d->udev->dev, "%s: %s() failed=%d\n",
+ KBUILD_MODNAME, __func__, ret);
if (ret == 0)
code = (ibuf[0] << 8) | ibuf[1];
if (code != 0xffff) {
@@ -222,11 +218,6 @@
static int dvbsky_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
{
- if (dvb_usb_dvbsky_disable_rc) {
- rc->map_name = NULL;
- return 0;
- }
-
rc->allowed_protos = RC_BIT_RC5;
rc->query = dvbsky_rc_query;
rc->interval = 300;
@@ -274,6 +265,8 @@
if (i2c_transfer(&d->i2c_adap, msg, 2) == 2)
memcpy(mac, ibuf, 6);
+ dev_info(&d->udev->dev, "dvbsky_usb MAC address=%pM\n", mac);
+
return 0;
}
@@ -369,300 +362,6 @@
return ret;
}
-static int dvbsky_usb_ci_set_voltage(struct dvb_frontend *fe,
- fe_sec_voltage_t voltage)
-{
- struct dvb_usb_device *d = fe_to_d(fe);
- struct dvbsky_state *state = d_to_priv(d);
- u8 value;
-
- if (voltage == SEC_VOLTAGE_OFF)
- value = 0;
- else
- value = 1;
- dvbsky_gpio_ctrl(d, 0x00, value);
-
- return state->fe_set_voltage(fe, voltage);
-}
-
-static int dvbsky_ci_ctrl(void *priv, u8 read, int addr,
- u8 data, int *mem)
-{
- struct dvb_usb_device *d = priv;
- int ret = 0;
- u8 command[4], respond[2], command_size, respond_size;
-
- command[1] = (u8)((addr >> 8) & 0xff); /*high part of address*/
- command[2] = (u8)(addr & 0xff); /*low part of address*/
- if (read) {
- command[0] = 0x71;
- command_size = 3;
- respond_size = 2;
- } else {
- command[0] = 0x70;
- command[3] = data;
- command_size = 4;
- respond_size = 1;
- }
- ret = dvbsky_usb_generic_rw(d, command, command_size,
- respond, respond_size);
- if (ret)
- goto err;
- if (read)
- *mem = respond[1];
- return ret;
-err:
- dev_err(&d->udev->dev, "ci control failed=%d\n", ret);
- return ret;
-}
-
-static const struct m88ds3103_config dvbsky_s960c_m88ds3103_config = {
- .i2c_addr = 0x68,
- .clock = 27000000,
- .i2c_wr_max = 33,
- .clock_out = 0,
- .ts_mode = M88DS3103_TS_CI,
- .ts_clk = 10000,
- .ts_clk_pol = 1,
- .agc = 0x99,
- .lnb_hv_pol = 0,
- .lnb_en_pol = 1,
-};
-
-static int dvbsky_s960c_attach(struct dvb_usb_adapter *adap)
-{
- struct dvbsky_state *state = adap_to_priv(adap);
- struct dvb_usb_device *d = adap_to_d(adap);
- int ret = 0;
- /* demod I2C adapter */
- struct i2c_adapter *i2c_adapter;
- struct i2c_client *client_tuner, *client_ci;
- struct i2c_board_info info;
- struct sp2_config sp2_config;
- struct m88ts2022_config m88ts2022_config = {
- .clock = 27000000,
- };
- memset(&info, 0, sizeof(struct i2c_board_info));
-
- /* attach demod */
- adap->fe[0] = dvb_attach(m88ds3103_attach,
- &dvbsky_s960c_m88ds3103_config,
- &d->i2c_adap,
- &i2c_adapter);
- if (!adap->fe[0]) {
- dev_err(&d->udev->dev, "dvbsky_s960ci_attach fail.\n");
- ret = -ENODEV;
- goto fail_attach;
- }
-
- /* attach tuner */
- m88ts2022_config.fe = adap->fe[0];
- strlcpy(info.type, "m88ts2022", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &m88ts2022_config;
- request_module("m88ts2022");
- client_tuner = i2c_new_device(i2c_adapter, &info);
- if (client_tuner == NULL || client_tuner->dev.driver == NULL) {
- ret = -ENODEV;
- goto fail_tuner_device;
- }
-
- if (!try_module_get(client_tuner->dev.driver->owner)) {
- ret = -ENODEV;
- goto fail_tuner_module;
- }
-
- /* attach ci controller */
- memset(&sp2_config, 0, sizeof(sp2_config));
- sp2_config.dvb_adap = &adap->dvb_adap;
- sp2_config.priv = d;
- sp2_config.ci_control = dvbsky_ci_ctrl;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "sp2", I2C_NAME_SIZE);
- info.addr = 0x40;
- info.platform_data = &sp2_config;
- request_module("sp2");
- client_ci = i2c_new_device(&d->i2c_adap, &info);
- if (client_ci == NULL || client_ci->dev.driver == NULL) {
- ret = -ENODEV;
- goto fail_ci_device;
- }
-
- if (!try_module_get(client_ci->dev.driver->owner)) {
- ret = -ENODEV;
- goto fail_ci_module;
- }
-
- /* delegate signal strength measurement to tuner */
- adap->fe[0]->ops.read_signal_strength =
- adap->fe[0]->ops.tuner_ops.get_rf_strength;
-
- /* hook fe: need to resync the slave fifo when signal locks. */
- state->fe_read_status = adap->fe[0]->ops.read_status;
- adap->fe[0]->ops.read_status = dvbsky_usb_read_status;
-
- /* hook fe: LNB off/on is control by Cypress usb chip. */
- state->fe_set_voltage = adap->fe[0]->ops.set_voltage;
- adap->fe[0]->ops.set_voltage = dvbsky_usb_ci_set_voltage;
-
- state->i2c_client_tuner = client_tuner;
- state->i2c_client_ci = client_ci;
- return ret;
-fail_ci_module:
- i2c_unregister_device(client_ci);
-fail_ci_device:
- module_put(client_tuner->dev.driver->owner);
-fail_tuner_module:
- i2c_unregister_device(client_tuner);
-fail_tuner_device:
- dvb_frontend_detach(adap->fe[0]);
-fail_attach:
- return ret;
-}
-
-static int dvbsky_t680c_attach(struct dvb_usb_adapter *adap)
-{
- struct dvbsky_state *state = adap_to_priv(adap);
- struct dvb_usb_device *d = adap_to_d(adap);
- int ret = 0;
- struct i2c_adapter *i2c_adapter;
- struct i2c_client *client_demod, *client_tuner, *client_ci;
- struct i2c_board_info info;
- struct si2168_config si2168_config;
- struct si2157_config si2157_config;
- struct sp2_config sp2_config;
-
- /* attach demod */
- memset(&si2168_config, 0, sizeof(si2168_config));
- si2168_config.i2c_adapter = &i2c_adapter;
- si2168_config.fe = &adap->fe[0];
- si2168_config.ts_mode = SI2168_TS_PARALLEL;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
- info.addr = 0x64;
- info.platform_data = &si2168_config;
-
- request_module(info.type);
- client_demod = i2c_new_device(&d->i2c_adap, &info);
- if (client_demod == NULL ||
- client_demod->dev.driver == NULL)
- goto fail_demod_device;
- if (!try_module_get(client_demod->dev.driver->owner))
- goto fail_demod_module;
-
- /* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
- si2157_config.fe = adap->fe[0];
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2157", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &si2157_config;
-
- request_module(info.type);
- client_tuner = i2c_new_device(i2c_adapter, &info);
- if (client_tuner == NULL ||
- client_tuner->dev.driver == NULL)
- goto fail_tuner_device;
- if (!try_module_get(client_tuner->dev.driver->owner))
- goto fail_tuner_module;
-
- /* attach ci controller */
- memset(&sp2_config, 0, sizeof(sp2_config));
- sp2_config.dvb_adap = &adap->dvb_adap;
- sp2_config.priv = d;
- sp2_config.ci_control = dvbsky_ci_ctrl;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "sp2", I2C_NAME_SIZE);
- info.addr = 0x40;
- info.platform_data = &sp2_config;
-
- request_module(info.type);
- client_ci = i2c_new_device(&d->i2c_adap, &info);
-
- if (client_ci == NULL || client_ci->dev.driver == NULL)
- goto fail_ci_device;
-
- if (!try_module_get(client_ci->dev.driver->owner))
- goto fail_ci_module;
-
- state->i2c_client_demod = client_demod;
- state->i2c_client_tuner = client_tuner;
- state->i2c_client_ci = client_ci;
- return ret;
-fail_ci_module:
- i2c_unregister_device(client_ci);
-fail_ci_device:
- module_put(client_tuner->dev.driver->owner);
-fail_tuner_module:
- i2c_unregister_device(client_tuner);
-fail_tuner_device:
- module_put(client_demod->dev.driver->owner);
-fail_demod_module:
- i2c_unregister_device(client_demod);
-fail_demod_device:
- ret = -ENODEV;
- return ret;
-}
-
-static int dvbsky_t330_attach(struct dvb_usb_adapter *adap)
-{
- struct dvbsky_state *state = adap_to_priv(adap);
- struct dvb_usb_device *d = adap_to_d(adap);
- int ret = 0;
- struct i2c_adapter *i2c_adapter;
- struct i2c_client *client_demod, *client_tuner;
- struct i2c_board_info info;
- struct si2168_config si2168_config;
- struct si2157_config si2157_config;
-
- /* attach demod */
- memset(&si2168_config, 0, sizeof(si2168_config));
- si2168_config.i2c_adapter = &i2c_adapter;
- si2168_config.fe = &adap->fe[0];
- si2168_config.ts_mode = SI2168_TS_PARALLEL | 0x40;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
- info.addr = 0x64;
- info.platform_data = &si2168_config;
-
- request_module(info.type);
- client_demod = i2c_new_device(&d->i2c_adap, &info);
- if (client_demod == NULL ||
- client_demod->dev.driver == NULL)
- goto fail_demod_device;
- if (!try_module_get(client_demod->dev.driver->owner))
- goto fail_demod_module;
-
- /* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
- si2157_config.fe = adap->fe[0];
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2157", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &si2157_config;
-
- request_module(info.type);
- client_tuner = i2c_new_device(i2c_adapter, &info);
- if (client_tuner == NULL ||
- client_tuner->dev.driver == NULL)
- goto fail_tuner_device;
- if (!try_module_get(client_tuner->dev.driver->owner))
- goto fail_tuner_module;
-
- state->i2c_client_demod = client_demod;
- state->i2c_client_tuner = client_tuner;
- return ret;
-fail_tuner_module:
- i2c_unregister_device(client_tuner);
-fail_tuner_device:
- module_put(client_demod->dev.driver->owner);
-fail_demod_module:
- i2c_unregister_device(client_demod);
-fail_demod_device:
- ret = -ENODEV;
- return ret;
-}
-
static int dvbsky_identify_state(struct dvb_usb_device *d, const char **name)
{
dvbsky_gpio_ctrl(d, 0x04, 1);
@@ -705,18 +404,6 @@
module_put(client->dev.driver->owner);
i2c_unregister_device(client);
}
- client = state->i2c_client_demod;
- /* remove I2C demod */
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
- client = state->i2c_client_ci;
- /* remove I2C ci */
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
}
/* DVB USB Driver stuff */
@@ -747,104 +434,9 @@
}
};
-static struct dvb_usb_device_properties dvbsky_s960c_props = {
- .driver_name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
- .adapter_nr = adapter_nr,
- .size_of_priv = sizeof(struct dvbsky_state),
-
- .generic_bulk_ctrl_endpoint = 0x01,
- .generic_bulk_ctrl_endpoint_response = 0x81,
- .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
-
- .i2c_algo = &dvbsky_i2c_algo,
- .frontend_attach = dvbsky_s960c_attach,
- .init = dvbsky_init,
- .get_rc_config = dvbsky_get_rc_config,
- .streaming_ctrl = dvbsky_streaming_ctrl,
- .identify_state = dvbsky_identify_state,
- .exit = dvbsky_exit,
- .read_mac_address = dvbsky_read_mac_addr,
-
- .num_adapters = 1,
- .adapter = {
- {
- .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
- }
- }
-};
-
-static struct dvb_usb_device_properties dvbsky_t680c_props = {
- .driver_name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
- .adapter_nr = adapter_nr,
- .size_of_priv = sizeof(struct dvbsky_state),
-
- .generic_bulk_ctrl_endpoint = 0x01,
- .generic_bulk_ctrl_endpoint_response = 0x81,
- .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
-
- .i2c_algo = &dvbsky_i2c_algo,
- .frontend_attach = dvbsky_t680c_attach,
- .init = dvbsky_init,
- .get_rc_config = dvbsky_get_rc_config,
- .streaming_ctrl = dvbsky_streaming_ctrl,
- .identify_state = dvbsky_identify_state,
- .exit = dvbsky_exit,
- .read_mac_address = dvbsky_read_mac_addr,
-
- .num_adapters = 1,
- .adapter = {
- {
- .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
- }
- }
-};
-
-static struct dvb_usb_device_properties dvbsky_t330_props = {
- .driver_name = KBUILD_MODNAME,
- .owner = THIS_MODULE,
- .adapter_nr = adapter_nr,
- .size_of_priv = sizeof(struct dvbsky_state),
-
- .generic_bulk_ctrl_endpoint = 0x01,
- .generic_bulk_ctrl_endpoint_response = 0x81,
- .generic_bulk_ctrl_delay = DVBSKY_MSG_DELAY,
-
- .i2c_algo = &dvbsky_i2c_algo,
- .frontend_attach = dvbsky_t330_attach,
- .init = dvbsky_init,
- .get_rc_config = dvbsky_get_rc_config,
- .streaming_ctrl = dvbsky_streaming_ctrl,
- .identify_state = dvbsky_identify_state,
- .exit = dvbsky_exit,
- .read_mac_address = dvbsky_read_mac_addr,
-
- .num_adapters = 1,
- .adapter = {
- {
- .stream = DVB_USB_STREAM_BULK(0x82, 8, 4096),
- }
- }
-};
-
static const struct usb_device_id dvbsky_id_table[] = {
{ DVB_USB_DEVICE(0x0572, 0x6831,
&dvbsky_s960_props, "DVBSky S960/S860", RC_MAP_DVBSKY) },
- { DVB_USB_DEVICE(0x0572, 0x960c,
- &dvbsky_s960c_props, "DVBSky S960CI", RC_MAP_DVBSKY) },
- { DVB_USB_DEVICE(0x0572, 0x680c,
- &dvbsky_t680c_props, "DVBSky T680CI", RC_MAP_DVBSKY) },
- { DVB_USB_DEVICE(0x0572, 0x0320,
- &dvbsky_t330_props, "DVBSky T330", RC_MAP_DVBSKY) },
- { DVB_USB_DEVICE(USB_VID_TECHNOTREND,
- USB_PID_TECHNOTREND_TVSTICK_CT2_4400,
- &dvbsky_t330_props, "TechnoTrend TVStick CT2-4400",
- RC_MAP_TT_1500) },
- { DVB_USB_DEVICE(USB_VID_TECHNOTREND,
- USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI,
- &dvbsky_t680c_props, "TechnoTrend TT-connect CT2-4650 CI",
- RC_MAP_TT_1500) },
{ }
};
MODULE_DEVICE_TABLE(usb, dvbsky_id_table);
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index 994de53..9f2c545 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -817,22 +817,20 @@
case 0x1122:
switch (st->dvb_usb_lme2510_firmware) {
default:
+ st->dvb_usb_lme2510_firmware = TUNER_S0194;
case TUNER_S0194:
fw_lme = fw_s0194;
ret = request_firmware(&fw, fw_lme, &udev->dev);
if (ret == 0) {
- st->dvb_usb_lme2510_firmware = TUNER_S0194;
cold = 0;
break;
}
- /* fall through */
+ st->dvb_usb_lme2510_firmware = TUNER_LG;
case TUNER_LG:
fw_lme = fw_lg;
ret = request_firmware(&fw, fw_lme, &udev->dev);
- if (ret == 0) {
- st->dvb_usb_lme2510_firmware = TUNER_LG;
+ if (ret == 0)
break;
- }
st->dvb_usb_lme2510_firmware = TUNER_DEFAULT;
break;
}
@@ -840,30 +838,26 @@
case 0x1120:
switch (st->dvb_usb_lme2510_firmware) {
default:
+ st->dvb_usb_lme2510_firmware = TUNER_S7395;
case TUNER_S7395:
fw_lme = fw_c_s7395;
ret = request_firmware(&fw, fw_lme, &udev->dev);
if (ret == 0) {
- st->dvb_usb_lme2510_firmware = TUNER_S7395;
cold = 0;
break;
}
- /* fall through */
+ st->dvb_usb_lme2510_firmware = TUNER_LG;
case TUNER_LG:
fw_lme = fw_c_lg;
ret = request_firmware(&fw, fw_lme, &udev->dev);
- if (ret == 0) {
- st->dvb_usb_lme2510_firmware = TUNER_LG;
+ if (ret == 0)
break;
- }
- /* fall through */
+ st->dvb_usb_lme2510_firmware = TUNER_S0194;
case TUNER_S0194:
fw_lme = fw_c_s0194;
ret = request_firmware(&fw, fw_lme, &udev->dev);
- if (ret == 0) {
- st->dvb_usb_lme2510_firmware = TUNER_S0194;
+ if (ret == 0)
break;
- }
st->dvb_usb_lme2510_firmware = TUNER_DEFAULT;
cold = 0;
break;
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 026a68e..4bdb7ce 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.c
@@ -24,9 +24,6 @@
#include "rtl2830.h"
#include "rtl2832.h"
-#include "rtl2832_sdr.h"
-#include "mn88472.h"
-#include "mn88473.h"
#include "qt1010.h"
#include "mt2060.h"
@@ -38,6 +35,25 @@
#include "tua9001.h"
#include "r820t.h"
+/*
+ * RTL2832_SDR module is in staging. That logic is added in order to avoid any
+ * hard dependency to drivers/staging/ directory as we want compile mainline
+ * driver even whole staging directory is missing.
+ */
+#include <media/v4l2-subdev.h>
+
+#if IS_ENABLED(CPTCFG_DVB_RTL2832_SDR)
+struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+ struct v4l2_subdev *sd);
+#else
+static inline struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
+ struct i2c_adapter *i2c, const struct rtl2832_config *cfg,
+ struct v4l2_subdev *sd)
+{
+ return NULL;
+}
+#endif
#ifdef CPTCFG_MEDIA_ATTACH
#define dvb_attach_sdr(FUNCTION, ARGS...) ({ \
@@ -404,8 +420,6 @@
struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf};
struct rtl28xxu_req req_r820t = {0x0034, CMD_I2C_RD, 1, buf};
struct rtl28xxu_req req_r828d = {0x0074, CMD_I2C_RD, 1, buf};
- struct rtl28xxu_req req_mn88472 = {0xff38, CMD_I2C_RD, 1, buf};
- struct rtl28xxu_req req_mn88473 = {0xff38, CMD_I2C_RD, 1, buf};
dev_dbg(&d->udev->dev, "%s:\n", __func__);
@@ -435,7 +449,7 @@
if (ret == 0 && buf[0] == 0xa1) {
priv->tuner = TUNER_RTL2832_FC0012;
priv->tuner_name = "FC0012";
- goto tuner_found;
+ goto found;
}
/* check FC0013 ID register; reg=00 val=a3 */
@@ -443,7 +457,7 @@
if (ret == 0 && buf[0] == 0xa3) {
priv->tuner = TUNER_RTL2832_FC0013;
priv->tuner_name = "FC0013";
- goto tuner_found;
+ goto found;
}
/* check MT2266 ID register; reg=00 val=85 */
@@ -451,7 +465,7 @@
if (ret == 0 && buf[0] == 0x85) {
priv->tuner = TUNER_RTL2832_MT2266;
priv->tuner_name = "MT2266";
- goto tuner_found;
+ goto found;
}
/* check FC2580 ID register; reg=01 val=56 */
@@ -459,7 +473,7 @@
if (ret == 0 && buf[0] == 0x56) {
priv->tuner = TUNER_RTL2832_FC2580;
priv->tuner_name = "FC2580";
- goto tuner_found;
+ goto found;
}
/* check MT2063 ID register; reg=00 val=9e || 9c */
@@ -467,7 +481,7 @@
if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
priv->tuner = TUNER_RTL2832_MT2063;
priv->tuner_name = "MT2063";
- goto tuner_found;
+ goto found;
}
/* check MAX3543 ID register; reg=00 val=38 */
@@ -475,7 +489,7 @@
if (ret == 0 && buf[0] == 0x38) {
priv->tuner = TUNER_RTL2832_MAX3543;
priv->tuner_name = "MAX3543";
- goto tuner_found;
+ goto found;
}
/* check TUA9001 ID register; reg=7e val=2328 */
@@ -483,7 +497,7 @@
if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
priv->tuner = TUNER_RTL2832_TUA9001;
priv->tuner_name = "TUA9001";
- goto tuner_found;
+ goto found;
}
/* check MXL5007R ID register; reg=d9 val=14 */
@@ -491,7 +505,7 @@
if (ret == 0 && buf[0] == 0x14) {
priv->tuner = TUNER_RTL2832_MXL5007T;
priv->tuner_name = "MXL5007T";
- goto tuner_found;
+ goto found;
}
/* check E4000 ID register; reg=02 val=40 */
@@ -499,7 +513,7 @@
if (ret == 0 && buf[0] == 0x40) {
priv->tuner = TUNER_RTL2832_E4000;
priv->tuner_name = "E4000";
- goto tuner_found;
+ goto found;
}
/* check TDA18272 ID register; reg=00 val=c760 */
@@ -507,7 +521,7 @@
if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
priv->tuner = TUNER_RTL2832_TDA18272;
priv->tuner_name = "TDA18272";
- goto tuner_found;
+ goto found;
}
/* check R820T ID register; reg=00 val=69 */
@@ -515,7 +529,7 @@
if (ret == 0 && buf[0] == 0x69) {
priv->tuner = TUNER_RTL2832_R820T;
priv->tuner_name = "R820T";
- goto tuner_found;
+ goto found;
}
/* check R828D ID register; reg=00 val=69 */
@@ -523,44 +537,13 @@
if (ret == 0 && buf[0] == 0x69) {
priv->tuner = TUNER_RTL2832_R828D;
priv->tuner_name = "R828D";
- goto tuner_found;
+ goto found;
}
-tuner_found:
+
+found:
dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name);
- /* probe slave demod */
- if (priv->tuner == TUNER_RTL2832_R828D) {
- /* power on MN88472 demod on GPIO0 */
- ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x01, 0x01);
- if (ret)
- goto err;
-
- ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01);
- if (ret)
- goto err;
-
- ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01);
- if (ret)
- goto err;
-
- /* check MN88472 answers */
- ret = rtl28xxu_ctrl_msg(d, &req_mn88472);
- if (ret == 0 && buf[0] == 0x02) {
- dev_dbg(&d->udev->dev, "%s: MN88472 found\n", __func__);
- priv->slave_demod = SLAVE_DEMOD_MN88472;
- goto demod_found;
- }
-
- ret = rtl28xxu_ctrl_msg(d, &req_mn88473);
- if (ret == 0 && buf[0] == 0x03) {
- dev_dbg(&d->udev->dev, "%s: MN88473 found\n", __func__);
- priv->slave_demod = SLAVE_DEMOD_MN88473;
- goto demod_found;
- }
- }
-
-demod_found:
/* close demod I2C gate */
ret = rtl28xxu_ctrl_msg(d, &req_gate_close);
if (ret < 0)
@@ -835,66 +818,7 @@
/* set fe callback */
adap->fe[0]->callback = rtl2832u_frontend_callback;
- if (priv->slave_demod) {
- struct i2c_board_info info = {};
- struct i2c_client *client;
-
- /*
- * We continue on reduced mode, without DVB-T2/C, using master
- * demod, when slave demod fails.
- */
- ret = 0;
-
- /* attach slave demodulator */
- if (priv->slave_demod == SLAVE_DEMOD_MN88472) {
- struct mn88472_config mn88472_config = {};
-
- mn88472_config.fe = &adap->fe[1];
- mn88472_config.i2c_wr_max = 22,
- strlcpy(info.type, "mn88472", I2C_NAME_SIZE);
- info.addr = 0x18;
- info.platform_data = &mn88472_config;
- request_module(info.type);
- client = i2c_new_device(priv->demod_i2c_adapter, &info);
- if (client == NULL || client->dev.driver == NULL) {
- priv->slave_demod = SLAVE_DEMOD_NONE;
- goto err_slave_demod_failed;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- priv->slave_demod = SLAVE_DEMOD_NONE;
- goto err_slave_demod_failed;
- }
-
- priv->i2c_client_slave_demod = client;
- } else {
- struct mn88473_config mn88473_config = {};
-
- mn88473_config.fe = &adap->fe[1];
- mn88473_config.i2c_wr_max = 22,
- strlcpy(info.type, "mn88473", I2C_NAME_SIZE);
- info.addr = 0x18;
- info.platform_data = &mn88473_config;
- request_module(info.type);
- client = i2c_new_device(priv->demod_i2c_adapter, &info);
- if (client == NULL || client->dev.driver == NULL) {
- priv->slave_demod = SLAVE_DEMOD_NONE;
- goto err_slave_demod_failed;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- priv->slave_demod = SLAVE_DEMOD_NONE;
- goto err_slave_demod_failed;
- }
-
- priv->i2c_client_slave_demod = client;
- }
- }
-
return 0;
-err_slave_demod_failed:
err:
dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
return ret;
@@ -1060,7 +984,7 @@
break;
}
- priv->i2c_client_tuner = client;
+ priv->client = client;
sd = i2c_get_clientdata(client);
i2c_set_adapdata(i2c_adap_internal, d);
@@ -1100,30 +1024,32 @@
&rtl28xxu_rtl2832_r820t_config, NULL);
break;
case TUNER_RTL2832_R828D:
- fe = dvb_attach(r820t_attach, adap->fe[0],
- priv->demod_i2c_adapter,
+ /* power off mn88472 demod on GPIO0 */
+ ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, 0x00, 0x01);
+ if (ret)
+ goto err;
+
+ ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x01);
+ if (ret)
+ goto err;
+
+ ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x01, 0x01);
+ if (ret)
+ goto err;
+
+ fe = dvb_attach(r820t_attach, adap->fe[0], &d->i2c_adap,
&rtl2832u_r828d_config);
+
+ /* Use tuner to get the signal strength */
adap->fe[0]->ops.read_signal_strength =
adap->fe[0]->ops.tuner_ops.get_rf_strength;
-
- if (adap->fe[1]) {
- fe = dvb_attach(r820t_attach, adap->fe[1],
- priv->demod_i2c_adapter,
- &rtl2832u_r828d_config);
- adap->fe[1]->ops.read_signal_strength =
- adap->fe[1]->ops.tuner_ops.get_rf_strength;
- }
-
- /* attach SDR */
- dvb_attach_sdr(rtl2832_sdr_attach, adap->fe[0], &d->i2c_adap,
- &rtl28xxu_rtl2832_r820t_config, NULL);
break;
default:
dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
priv->tuner);
}
- if (fe == NULL && priv->i2c_client_tuner == NULL) {
+ if (fe == NULL && priv->client == NULL) {
ret = -ENODEV;
goto err;
}
@@ -1171,19 +1097,11 @@
static void rtl28xxu_exit(struct dvb_usb_device *d)
{
struct rtl28xxu_priv *priv = d->priv;
- struct i2c_client *client;
+ struct i2c_client *client = priv->client;
dev_dbg(&d->udev->dev, "%s:\n", __func__);
/* remove I2C tuner */
- client = priv->i2c_client_tuner;
- if (client) {
- module_put(client->dev.driver->owner);
- i2c_unregister_device(client);
- }
-
- /* remove I2C slave demod */
- client = priv->i2c_client_slave_demod;
if (client) {
module_put(client->dev.driver->owner);
i2c_unregister_device(client);
@@ -1283,6 +1201,13 @@
if (ret)
goto err;
+ mdelay(5);
+
+ /* enable ADC */
+ ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x48, 0x48);
+ if (ret)
+ goto err;
+
/* streaming EP: clear stall & reset */
ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2);
if (ret)
@@ -1297,6 +1222,11 @@
if (ret)
goto err;
+ /* disable ADC */
+ ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x48);
+ if (ret)
+ goto err;
+
/* disable PLL */
ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, 0x00, 0x80);
if (ret)
@@ -1314,38 +1244,6 @@
return ret;
}
-static int rtl2832u_frontend_ctrl(struct dvb_frontend *fe, int onoff)
-{
- struct dvb_usb_device *d = fe_to_d(fe);
- struct dvb_usb_adapter *adap = fe_to_adap(fe);
- int ret;
- u8 val;
-
- dev_dbg(&d->udev->dev, "%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
-
- /* control internal demod ADC */
- if (fe->id == 0 && onoff)
- val = 0x48; /* enable ADC */
- else
- val = 0x00; /* disable ADC */
-
- ret = rtl28xx_wr_reg_mask(d, SYS_DEMOD_CTL, val, 0x48);
- if (ret)
- goto err;
-
- /* bypass slave demod TS through master demod */
- if (fe->id == 1 && onoff) {
- ret = rtl2832_enable_external_ts_if(adap->fe[0]);
- if (ret)
- goto err;
- }
-
- return 0;
-err:
- dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
- return ret;
-}
-
#if IS_ENABLED(CPTCFG_RC_CORE)
static int rtl2831u_rc_query(struct dvb_usb_device *d)
{
@@ -1569,7 +1467,6 @@
.size_of_priv = sizeof(struct rtl28xxu_priv),
.power_ctrl = rtl2832u_power_ctrl,
- .frontend_ctrl = rtl2832u_frontend_ctrl,
.i2c_algo = &rtl28xxu_i2c_algo,
.read_config = rtl2832u_read_config,
.frontend_attach = rtl2832u_frontend_attach,
diff --git a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 3e3ea9d..a26cab1 100644
--- a/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
+++ b/drivers/media/usb/dvb-usb-v2/rtl28xxu.h
@@ -57,12 +57,7 @@
u8 page; /* integrated demod active register page */
struct i2c_adapter *demod_i2c_adapter;
bool rc_active;
- struct i2c_client *i2c_client_tuner;
- struct i2c_client *i2c_client_slave_demod;
- #define SLAVE_DEMOD_NONE 0
- #define SLAVE_DEMOD_MN88472 1
- #define SLAVE_DEMOD_MN88473 2
- unsigned int slave_demod:2;
+ struct i2c_client *client;
};
enum rtl28xxu_chip_id {
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
index 1378eca..25da066 100644
--- a/drivers/media/usb/dvb-usb/Kconfig
+++ b/drivers/media/usb/dvb-usb/Kconfig
@@ -137,6 +137,7 @@
Medion MD95700 hybrid USB2.0 device.
DViCO FusionHDTV (Bluebird) USB2.0 devices
+ TechnoTrend TVStick CT2-4400 and CT2-4650 CI devices
config DVB_USB_M920X
tristate "Uli m920x DVB-T USB2.0 support"
diff --git a/drivers/media/usb/dvb-usb/af9005.c b/drivers/media/usb/dvb-usb/af9005.c
index c0ab8c3..3f4361e 100644
--- a/drivers/media/usb/dvb-usb/af9005.c
+++ b/drivers/media/usb/dvb-usb/af9005.c
@@ -1081,12 +1081,9 @@
err("usb_register failed. (%d)", result);
return result;
}
-#if IS_MODULE(CPTCFG_DVB_USB_AF9005) || defined(CPTCFG_DVB_USB_AF9005_REMOTE)
- /* FIXME: convert to todays kernel IR infrastructure */
rc_decode = symbol_request(af9005_rc_decode);
rc_keys = symbol_request(rc_map_af9005_table);
rc_keys_size = symbol_request(rc_map_af9005_table_size);
-#endif
if (rc_decode == NULL || rc_keys == NULL || rc_keys_size == NULL) {
err("af9005_rc_decode function not found, disabling remote");
af9005_properties.rc.legacy.rc_query = NULL;
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index 0f345b1..356abb3 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -44,6 +44,7 @@
#include "atbm8830.h"
#include "si2168.h"
#include "si2157.h"
+#include "sp2.h"
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 80
@@ -146,6 +147,22 @@
}
}
+static int cxusb_tt_ct2_4400_gpio_tuner(struct dvb_usb_device *d, int onoff)
+{
+ u8 o[2], i;
+ int rc;
+
+ o[0] = 0x83;
+ o[1] = onoff;
+ rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+
+ if (rc) {
+ deb_info("gpio_write failed.\n");
+ return -EIO;
+ }
+ return 0;
+}
+
/* I2C */
static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
@@ -507,6 +524,30 @@
return 0;
}
+static int cxusb_tt_ct2_4400_rc_query(struct dvb_usb_device *d)
+{
+ u8 i[2];
+ int ret;
+ u32 cmd, keycode;
+ u8 rc5_cmd, rc5_addr, rc5_toggle;
+
+ ret = cxusb_ctrl_msg(d, 0x10, NULL, 0, i, 2);
+ if (ret)
+ return ret;
+
+ cmd = (i[0] << 8) | i[1];
+
+ if (cmd != 0xffff) {
+ rc5_cmd = cmd & 0x3F; /* bits 1-6 for command */
+ rc5_addr = (cmd & 0x07C0) >> 6; /* bits 7-11 for address */
+ rc5_toggle = (cmd & 0x0800) >> 11; /* bit 12 for toggle */
+ keycode = (rc5_addr << 8) | rc5_cmd;
+ rc_keydown(d->rc_dev, RC_BIT_RC5, keycode, rc5_toggle);
+ }
+
+ return 0;
+}
+
static struct rc_map_table rc_map_dvico_mce_table[] = {
{ 0xfe02, KEY_TV },
{ 0xfe0e, KEY_MP3 },
@@ -632,6 +673,70 @@
{ 0x0025, KEY_POWER },
};
+static int cxusb_tt_ct2_4400_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+ u8 wbuf[2];
+ u8 rbuf[6];
+ int ret;
+ struct i2c_msg msg[] = {
+ {
+ .addr = 0x51,
+ .flags = 0,
+ .buf = wbuf,
+ .len = 2,
+ }, {
+ .addr = 0x51,
+ .flags = I2C_M_RD,
+ .buf = rbuf,
+ .len = 6,
+ }
+ };
+
+ wbuf[0] = 0x1e;
+ wbuf[1] = 0x00;
+ ret = cxusb_i2c_xfer(&d->i2c_adap, msg, 2);
+
+ if (ret == 2) {
+ memcpy(mac, rbuf, 6);
+ return 0;
+ } else {
+ if (ret < 0)
+ return ret;
+ return -EIO;
+ }
+}
+
+static int cxusb_tt_ct2_4650_ci_ctrl(void *priv, u8 read, int addr,
+ u8 data, int *mem)
+{
+ struct dvb_usb_device *d = priv;
+ u8 wbuf[3];
+ u8 rbuf[2];
+ int ret;
+
+ wbuf[0] = (addr >> 8) & 0xff;
+ wbuf[1] = addr & 0xff;
+
+ if (read) {
+ ret = cxusb_ctrl_msg(d, CMD_SP2_CI_READ, wbuf, 2, rbuf, 2);
+ } else {
+ wbuf[2] = data;
+ ret = cxusb_ctrl_msg(d, CMD_SP2_CI_WRITE, wbuf, 3, rbuf, 1);
+ }
+
+ if (ret)
+ goto err;
+
+ if (read)
+ *mem = rbuf[1];
+
+ return 0;
+err:
+ deb_info("%s: ci usb write returned %d\n", __func__, ret);
+ return ret;
+
+}
+
static int cxusb_dee1601_demod_init(struct dvb_frontend* fe)
{
static u8 clock_config [] = { CLOCK_CTL, 0x38, 0x28 };
@@ -1303,34 +1408,36 @@
return 0;
}
-static int cxusb_mygica_t230_frontend_attach(struct dvb_usb_adapter *adap)
+static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *d = adap->dev;
struct cxusb_state *st = d->priv;
struct i2c_adapter *adapter;
struct i2c_client *client_demod;
struct i2c_client *client_tuner;
+ struct i2c_client *client_ci;
struct i2c_board_info info;
struct si2168_config si2168_config;
struct si2157_config si2157_config;
+ struct sp2_config sp2_config;
+ u8 o[2], i;
- /* Select required USB configuration */
- if (usb_set_interface(d->udev, 0, 0) < 0)
- err("set interface failed");
-
- /* Unblock all USB pipes */
- usb_clear_halt(d->udev,
- usb_sndbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
- usb_clear_halt(d->udev,
- usb_rcvbulkpipe(d->udev, d->props.generic_bulk_ctrl_endpoint));
- usb_clear_halt(d->udev,
- usb_rcvbulkpipe(d->udev, d->props.adapter[0].fe[0].stream.endpoint));
+ /* reset the tuner */
+ if (cxusb_tt_ct2_4400_gpio_tuner(d, 0) < 0) {
+ err("clear tuner gpio failed");
+ return -EIO;
+ }
+ msleep(100);
+ if (cxusb_tt_ct2_4400_gpio_tuner(d, 1) < 0) {
+ err("set tuner gpio failed");
+ return -EIO;
+ }
+ msleep(100);
/* attach frontend */
si2168_config.i2c_adapter = &adapter;
si2168_config.fe = &adap->fe_adap[0].fe;
si2168_config.ts_mode = SI2168_TS_PARALLEL;
- si2168_config.ts_clock_inv = 1;
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2168", I2C_NAME_SIZE);
info.addr = 0x64;
@@ -1370,6 +1477,48 @@
st->i2c_client_tuner = client_tuner;
+ /* initialize CI */
+ if (d->udev->descriptor.idProduct ==
+ USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI) {
+
+ memcpy(o, "\xc0\x01", 2);
+ cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+ msleep(100);
+
+ memcpy(o, "\xc0\x00", 2);
+ cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+ msleep(100);
+
+ memset(&sp2_config, 0, sizeof(sp2_config));
+ sp2_config.dvb_adap = &adap->dvb_adap;
+ sp2_config.priv = d;
+ sp2_config.ci_control = cxusb_tt_ct2_4650_ci_ctrl;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "sp2", I2C_NAME_SIZE);
+ info.addr = 0x40;
+ info.platform_data = &sp2_config;
+ request_module(info.type);
+ client_ci = i2c_new_device(&d->i2c_adap, &info);
+ if (client_ci == NULL || client_ci->dev.driver == NULL) {
+ module_put(client_tuner->dev.driver->owner);
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+ if (!try_module_get(client_ci->dev.driver->owner)) {
+ i2c_unregister_device(client_ci);
+ module_put(client_tuner->dev.driver->owner);
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+
+ st->i2c_client_ci = client_ci;
+
+ }
+
return 0;
}
@@ -1454,7 +1603,7 @@
static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
static struct dvb_usb_device_properties cxusb_mygica_d689_properties;
-static struct dvb_usb_device_properties cxusb_mygica_t230_properties;
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -1485,7 +1634,7 @@
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
THIS_MODULE, NULL, adapter_nr) ||
- 0 == dvb_usb_device_init(intf, &cxusb_mygica_t230_properties,
+ 0 == dvb_usb_device_init(intf, &cxusb_tt_ct2_4400_properties,
THIS_MODULE, NULL, adapter_nr) ||
0)
return 0;
@@ -1499,6 +1648,13 @@
struct cxusb_state *st = d->priv;
struct i2c_client *client;
+ /* remove I2C client for CI */
+ client = st->i2c_client_ci;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
/* remove I2C client for tuner */
client = st->i2c_client_tuner;
if (client) {
@@ -1537,7 +1693,8 @@
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) },
{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) },
{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) },
- { USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_T230) },
+ { USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) },
+ { USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_CONNECT_CT2_4650_CI) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -2184,7 +2341,7 @@
}
};
-static struct dvb_usb_device_properties cxusb_mygica_t230_properties = {
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = {
.caps = DVB_USB_IS_AN_I2C_ADAPTER,
.usb_ctrl = CYPRESS_FX2,
@@ -2192,21 +2349,25 @@
.size_of_priv = sizeof(struct cxusb_state),
.num_adapters = 1,
+ .read_mac_address = cxusb_tt_ct2_4400_read_mac_address,
+
.adapter = {
{
.num_frontends = 1,
.fe = {{
.streaming_ctrl = cxusb_streaming_ctrl,
- .frontend_attach = cxusb_mygica_t230_frontend_attach,
+ /* both frontend and tuner attached in the
+ same function */
+ .frontend_attach = cxusb_tt_ct2_4400_attach,
/* parameter for the MPEG2-data transfer */
.stream = {
.type = USB_BULK,
- .count = 5,
- .endpoint = 0x02,
+ .count = 8,
+ .endpoint = 0x82,
.u = {
.bulk = {
- .buffersize = 8192,
+ .buffersize = 4096,
}
}
},
@@ -2214,25 +2375,28 @@
},
},
- .power_ctrl = cxusb_d680_dmb_power_ctrl,
-
- .i2c_algo = &cxusb_i2c_algo,
-
+ .i2c_algo = &cxusb_i2c_algo,
.generic_bulk_ctrl_endpoint = 0x01,
+ .generic_bulk_ctrl_endpoint_response = 0x81,
- .rc.legacy = {
- .rc_interval = 100,
- .rc_map_table = rc_map_d680_dmb_table,
- .rc_map_size = ARRAY_SIZE(rc_map_d680_dmb_table),
- .rc_query = cxusb_d680_dmb_rc_query,
+ .rc.core = {
+ .rc_codes = RC_MAP_TT_1500,
+ .allowed_protos = RC_BIT_RC5,
+ .rc_query = cxusb_tt_ct2_4400_rc_query,
+ .rc_interval = 150,
},
- .num_device_descs = 1,
+ .num_device_descs = 2,
.devices = {
{
- "Mygica T230 DVB-T/T2/C",
+ "TechnoTrend TVStick CT2-4400",
{ NULL },
- { &cxusb_table[22], NULL },
+ { &cxusb_table[20], NULL },
+ },
+ {
+ "TechnoTrend TT-connect CT2-4650 CI",
+ { NULL },
+ { &cxusb_table[21], NULL },
},
}
};
diff --git a/drivers/media/usb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h
index 527ff79..29f3e2e 100644
--- a/drivers/media/usb/dvb-usb/cxusb.h
+++ b/drivers/media/usb/dvb-usb/cxusb.h
@@ -28,10 +28,14 @@
#define CMD_ANALOG 0x50
#define CMD_DIGITAL 0x51
+#define CMD_SP2_CI_WRITE 0x70
+#define CMD_SP2_CI_READ 0x71
+
struct cxusb_state {
u8 gpio_write_state[3];
struct i2c_client *i2c_client_demod;
struct i2c_client *i2c_client_tuner;
+ struct i2c_client *i2c_client_ci;
};
#endif
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c
index 5801ae7..6b0b8b6 100644
--- a/drivers/media/usb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/usb/dvb-usb/technisat-usb2.c
@@ -449,8 +449,6 @@
return 0;
}
-static struct stv090x_config technisat_usb2_stv090x_config;
-
/* frontend attach */
static int technisat_usb2_set_voltage(struct dvb_frontend *fe,
fe_sec_voltage_t voltage)
@@ -474,8 +472,7 @@
}
for (i = 0; i < 3; i++)
- if (technisat_usb2_stv090x_config.set_gpio(fe, i+2, 0,
- gpio[i], 0) != 0)
+ if (stv090x_set_gpio(fe, i+2, 0, gpio[i], 0) != 0)
return -EREMOTEIO;
return 0;
}
diff --git a/drivers/media/usb/em28xx/Kconfig b/drivers/media/usb/em28xx/Kconfig
index 82fbf57..ddec55a 100644
--- a/drivers/media/usb/em28xx/Kconfig
+++ b/drivers/media/usb/em28xx/Kconfig
@@ -38,7 +38,7 @@
module will be called em28xx-alsa
config VIDEO_EM28XX_DVB
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "DVB/ATSC Support for em28xx based TV cards"
depends on m
depends on VIDEO_EM28XX && DVB_CORE
diff --git a/drivers/media/usb/em28xx/em28xx-audio.c b/drivers/media/usb/em28xx/em28xx-audio.c
index 44ae1e0..957c7ae 100644
--- a/drivers/media/usb/em28xx/em28xx-audio.c
+++ b/drivers/media/usb/em28xx/em28xx-audio.c
@@ -56,7 +56,7 @@
#define dprintk(fmt, arg...) do { \
if (debug) \
printk(KERN_INFO "em28xx-audio %s: " fmt, \
- __func__, ##arg); \
+ __func__, ##arg); \
} while (0)
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
@@ -232,6 +232,7 @@
.channels_max = 2,
.buffer_bytes_max = 62720 * 8, /* just about the value in usbaudio.c */
+
/*
* The period is 12.288 bytes. Allow a 10% of variation along its
* value, in order to avoid overruns/underruns due to some clock
@@ -360,7 +361,7 @@
dprintk("Setting capture parameters\n");
ret = snd_pcm_alloc_vmalloc_buffer(substream,
- params_buffer_bytes(hw_params));
+ params_buffer_bytes(hw_params));
if (ret < 0)
return ret;
#if 0
@@ -477,7 +478,7 @@
* AC97 volume control support
*/
static int em28xx_vol_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *info)
+ struct snd_ctl_elem_info *info)
{
struct em28xx *dev = snd_kcontrol_chip(kcontrol);
@@ -493,7 +494,7 @@
}
static int em28xx_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *value)
+ struct snd_ctl_elem_value *value)
{
struct em28xx *dev = snd_kcontrol_chip(kcontrol);
struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
@@ -533,7 +534,7 @@
}
static int em28xx_vol_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *value)
+ struct snd_ctl_elem_value *value)
{
struct em28xx *dev = snd_kcontrol_chip(kcontrol);
struct snd_pcm_substream *substream = dev->adev.capture_pcm_substream;
@@ -654,7 +655,7 @@
struct snd_kcontrol *kctl;
struct snd_kcontrol_new tmp;
- memset(&tmp, 0, sizeof(tmp));
+ memset (&tmp, 0, sizeof(tmp));
tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
tmp.private_value = id,
tmp.name = ctl_name,
@@ -671,7 +672,7 @@
dprintk("Added control %s for ac97 volume control 0x%04x\n",
ctl_name, id);
- memset(&tmp, 0, sizeof(tmp));
+ memset (&tmp, 0, sizeof(tmp));
tmp.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
tmp.private_value = id,
tmp.name = ctl_name,
@@ -730,7 +731,7 @@
/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
static int em28xx_audio_ep_packet_size(struct usb_device *udev,
- struct usb_endpoint_descriptor *e)
+ struct usb_endpoint_descriptor *e)
{
int size = le16_to_cpu(e->wMaxPacketSize);
@@ -780,7 +781,7 @@
interval = 1 << (ep->bInterval - 1);
em28xx_info("Endpoint 0x%02x %s on intf %d alt %d interval = %d, size %d\n",
- EM28XX_EP_AUDIO, usb_speed_string(dev->udev->speed),
+ EM28XX_EP_AUDIO, usb_speed_string(dev->udev->speed),
dev->ifnum, alt,
interval,
ep_size);
diff --git a/drivers/media/usb/em28xx/em28xx-camera.c b/drivers/media/usb/em28xx/em28xx-camera.c
index 7be661f..6d2ea9a 100644
--- a/drivers/media/usb/em28xx/em28xx-camera.c
+++ b/drivers/media/usb/em28xx/em28xx-camera.c
@@ -27,6 +27,7 @@
#include "em28xx.h"
+
/* Possible i2c addresses of Micron sensors */
static unsigned short micron_sensor_addrs[] = {
0xb8 >> 1, /* MT9V111, MT9V403 */
@@ -42,6 +43,7 @@
I2C_CLIENT_END
};
+
static struct soc_camera_link camlink = {
.bus_id = 0,
.flags = 0,
@@ -49,6 +51,7 @@
.unbalanced_power = true,
};
+
/* FIXME: Should be replaced by a proper mt9m111 driver */
static int em28xx_initialize_mt9m111(struct em28xx *dev)
{
@@ -67,6 +70,7 @@
return 0;
}
+
/* FIXME: Should be replaced by a proper mt9m001 driver */
static int em28xx_initialize_mt9m001(struct em28xx *dev)
{
@@ -94,6 +98,7 @@
return 0;
}
+
/*
* Probes Micron sensors with 8 bit address and 16 bit register width
*/
@@ -425,7 +430,7 @@
break;
}
- fmt.code = MEDIA_BUS_FMT_YUYV8_2X8;
+ fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
fmt.width = 640;
fmt.height = 480;
v4l2_subdev_call(subdev, video, s_mbus_fmt, &fmt);
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index d9704e6..71fa51e 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -64,6 +64,7 @@
MODULE_PARM_DESC(usb_xfer_mode,
"USB transfer mode for frame data (-1 = auto, 0 = prefer isoc, 1 = prefer bulk)");
+
/* Bitmask marking allocated devices from 0 to EM28XX_MAXBOARDS - 1 */
static DECLARE_BITMAP(em28xx_devused, EM28XX_MAXBOARDS);
@@ -189,8 +190,8 @@
};
static struct em28xx_reg_seq kworld_ub435q_v3_digital[] = {
- {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100},
- {EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 100},
+ {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 100},
+ {EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0xbe, 0xff, 100},
{EM2874_R80_GPIO_P0_CTRL, 0xfe, 0xff, 100},
{ -1, -1, -1, -1},
@@ -300,6 +301,7 @@
{ -1, -1, -1, -1},
};
+
/* Reset for the most [digital] boards */
static struct em28xx_reg_seq leadership_digital[] = {
{EM2874_R80_GPIO_P0_CTRL, 0x70, 0xff, 10},
@@ -477,20 +479,6 @@
{-1, -1, -1, -1},
};
-static struct em28xx_reg_seq terratec_t2_stick_hd[] = {
- {EM2874_R80_GPIO_P0_CTRL, 0xff, 0xff, 0},
- {0x0d, 0xff, 0xff, 600},
- {EM2874_R80_GPIO_P0_CTRL, 0xfc, 0xff, 10},
- {EM2874_R80_GPIO_P0_CTRL, 0xbc, 0xff, 100},
- {EM2874_R80_GPIO_P0_CTRL, 0xfc, 0xff, 100},
- {EM2874_R80_GPIO_P0_CTRL, 0x00, 0xff, 300},
- {EM2874_R80_GPIO_P0_CTRL, 0xf8, 0xff, 100},
- {EM2874_R80_GPIO_P0_CTRL, 0xfc, 0xff, 300},
- {0x0d, 0x42, 0xff, 1000},
- {EM2874_R5F_TS_ENABLE, 0x85, 0xff, 0},
- {-1, -1, -1, -1},
-};
-
/*
* Button definitions
*/
@@ -560,6 +548,7 @@
{-1, 0, 0, 0},
};
+
/*
* Board definitions
*/
@@ -1525,7 +1514,7 @@
.type = EM28XX_VMUX_TELEVISION,
.vmux = SAA7115_COMPOSITE2,
.amux = EM28XX_AMUX_VIDEO,
- .aout = EM28XX_AOUT_MONO | /* I2S */
+ .aout = EM28XX_AOUT_MONO | /* I2S */
EM28XX_AOUT_MASTER, /* Line out pin */
}, {
.type = EM28XX_VMUX_COMPOSITE1,
@@ -1547,7 +1536,7 @@
.type = EM28XX_VMUX_TELEVISION,
.vmux = SAA7115_COMPOSITE2,
.amux = EM28XX_AMUX_VIDEO,
- .aout = EM28XX_AOUT_MONO | /* I2S */
+ .aout = EM28XX_AOUT_MONO | /* I2S */
EM28XX_AOUT_MASTER, /* Line out pin */
}, {
.type = EM28XX_VMUX_COMPOSITE1,
@@ -2254,31 +2243,6 @@
.has_dvb = 1,
.ir_codes = RC_MAP_PINNACLE_PCTV_HD,
},
- [EM2861_BOARD_LEADTEK_VC100] = {
- .name = "Leadtek VC100",
- .tuner_type = TUNER_ABSENT, /* Capture only device */
- .decoder = EM28XX_TVP5150,
- .input = { {
- .type = EM28XX_VMUX_COMPOSITE1,
- .vmux = TVP5150_COMPOSITE1,
- .amux = EM28XX_AMUX_LINE_IN,
- }, {
- .type = EM28XX_VMUX_SVIDEO,
- .vmux = TVP5150_SVIDEO,
- .amux = EM28XX_AMUX_LINE_IN,
- } },
- },
- /* eb1a:8179 Terratec Cinergy T2 Stick HD.
- * Empia EM28178, Silicon Labs Si2168, Silicon Labs Si2146 */
- [EM28178_BOARD_TERRATEC_T2_STICK_HD] = {
- .name = "Terratec Cinergy T2 Stick HD",
- .def_i2c_bus = 1,
- .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ,
- .tuner_type = TUNER_ABSENT,
- .tuner_gpio = terratec_t2_stick_hd,
- .has_dvb = 1,
- .ir_codes = RC_MAP_TERRATEC_SLIM_2,
- },
};
EXPORT_SYMBOL_GPL(em28xx_boards);
@@ -2460,10 +2424,6 @@
.driver_info = EM28178_BOARD_PCTV_461E },
{ USB_DEVICE(0x2013, 0x025f),
.driver_info = EM28178_BOARD_PCTV_292E },
- { USB_DEVICE(0x0413, 0x6f07),
- .driver_info = EM2861_BOARD_LEADTEK_VC100 },
- { USB_DEVICE(0xeb1a, 0x8179),
- .driver_info = EM28178_BOARD_TERRATEC_T2_STICK_HD },
{ },
};
MODULE_DEVICE_TABLE(usb, em28xx_id_table);
@@ -2493,7 +2453,6 @@
{0x4ba50080, EM2861_BOARD_GADMEI_UTV330PLUS, TUNER_TNF_5335MF},
{0x6b800080, EM2874_BOARD_LEADERSHIP_ISDBT, TUNER_ABSENT},
};
-
/* NOTE: introduce a separate hash table for devices with 16 bit eeproms */
int em28xx_tuner_callback(void *ptr, int component, int command, int arg)
@@ -2736,7 +2695,7 @@
" insmod option:\n");
for (i = 0; i < em28xx_bcount; i++) {
em28xx_errdev(" card=%d -> %s\n",
- i, em28xx_boards[i].name);
+ i, em28xx_boards[i].name);
}
return -1;
}
@@ -3092,7 +3051,6 @@
if (le16_to_cpu(dev->udev->descriptor.idVendor)
== 0xeb1a) {
__le16 idProd = dev->udev->descriptor.idProduct;
-
if (le16_to_cpu(idProd) == 0x2710)
chip_name = "em2710";
else if (le16_to_cpu(idProd) == 0x2820)
@@ -3181,7 +3139,7 @@
retval = em28xx_i2c_register(dev, 0, EM28XX_I2C_ALGO_EM28XX);
if (retval < 0) {
em28xx_errdev("%s: em28xx_i2c_register bus 0 - error [%d]!\n",
- __func__, retval);
+ __func__, retval);
return retval;
}
@@ -3189,13 +3147,13 @@
if (dev->def_i2c_bus) {
if (dev->is_em25xx)
retval = em28xx_i2c_register(dev, 1,
- EM28XX_I2C_ALGO_EM25XX_BUS_B);
+ EM28XX_I2C_ALGO_EM25XX_BUS_B);
else
retval = em28xx_i2c_register(dev, 1,
- EM28XX_I2C_ALGO_EM28XX);
+ EM28XX_I2C_ALGO_EM28XX);
if (retval < 0) {
em28xx_errdev("%s: em28xx_i2c_register bus 1 - error [%d]!\n",
- __func__, retval);
+ __func__, retval);
em28xx_i2c_unregister(dev, 0);
@@ -3235,7 +3193,7 @@
if (nr >= EM28XX_MAXBOARDS) {
/* No free device slots */
printk(DRIVER_NAME ": Supports only %i em28xx boards.\n",
- EM28XX_MAXBOARDS);
+ EM28XX_MAXBOARDS);
retval = -ENOMEM;
goto err_no_slot;
}
@@ -3419,7 +3377,6 @@
/* Checks if audio is provided by a USB Audio Class interface */
for (i = 0; i < udev->config->desc.bNumInterfaces; i++) {
struct usb_interface *uif = udev->config->interface[i];
-
if (uif->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO) {
if (has_vendor_audio)
em28xx_err("em28xx: device seems to have vendor AND usb audio class interfaces !\n"
@@ -3530,7 +3487,7 @@
}
static int em28xx_usb_suspend(struct usb_interface *interface,
- pm_message_t message)
+ pm_message_t message)
{
struct em28xx *dev;
diff --git a/drivers/media/usb/em28xx/em28xx-core.c b/drivers/media/usb/em28xx/em28xx-core.c
index 86461a7..b5e52fe 100644
--- a/drivers/media/usb/em28xx/em28xx-core.c
+++ b/drivers/media/usb/em28xx/em28xx-core.c
@@ -75,7 +75,7 @@
* reads data from the usb device specifying bRequest
*/
int em28xx_read_reg_req_len(struct em28xx *dev, u8 req, u16 reg,
- char *buf, int len)
+ char *buf, int len)
{
int ret;
int pipe = usb_rcvctrlpipe(dev->udev, 0);
@@ -151,7 +151,7 @@
* sends data to the usb device, specifying bRequest
*/
int em28xx_write_regs_req(struct em28xx *dev, u8 req, u16 reg, char *buf,
- int len)
+ int len)
{
int ret;
int pipe = usb_sndctrlpipe(dev->udev, 0);
@@ -213,7 +213,7 @@
* the actual value
*/
int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
- u8 bitmask)
+ u8 bitmask)
{
int oldval;
u8 newval;
@@ -222,7 +222,7 @@
if (oldval < 0)
return oldval;
- newval = (((u8)oldval) & ~bitmask) | (val & bitmask);
+ newval = (((u8) oldval) & ~bitmask) | (val & bitmask);
return em28xx_write_regs(dev, reg, &newval, 1);
}
@@ -314,7 +314,7 @@
if (ret < 0)
return ret;
- ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, (u8 *)&value, 2);
+ ret = em28xx_write_regs(dev, EM28XX_R40_AC97LSB, (u8 *) &value, 2);
if (ret < 0)
return ret;
@@ -361,7 +361,7 @@
if (ret < 0)
em28xx_warn("couldn't setup AC97 register %d\n",
- inputs[i].reg);
+ inputs[i].reg);
}
return 0;
}
@@ -445,7 +445,7 @@
ret = em28xx_write_ac97(dev, outputs[i].reg, 0x8000);
if (ret < 0)
em28xx_warn("couldn't setup AC97 register %d\n",
- outputs[i].reg);
+ outputs[i].reg);
}
}
@@ -483,7 +483,7 @@
vol);
if (ret < 0)
em28xx_warn("couldn't setup AC97 register %d\n",
- outputs[i].reg);
+ outputs[i].reg);
}
if (dev->ctl_aoutput & EM28XX_AOUT_PCM_IN) {
@@ -504,7 +504,7 @@
int em28xx_audio_setup(struct em28xx *dev)
{
int vid1, vid2, feat, cfg;
- u32 vid = 0;
+ u32 vid;
u8 i2s_samplerates;
if (dev->chip_id == CHIP_ID_EM2870 ||
@@ -531,7 +531,7 @@
} else if ((cfg & EM28XX_CHIPCFG_AUDIOMASK) != EM28XX_CHIPCFG_AC97) {
dev->int_audio_type = EM28XX_INT_AUDIO_I2S;
if (dev->chip_id < CHIP_ID_EM2860 &&
- (cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
+ (cfg & EM28XX_CHIPCFG_AUDIOMASK) ==
EM2820_CHIPCFG_I2S_1_SAMPRATE)
i2s_samplerates = 1;
else if (dev->chip_id >= CHIP_ID_EM2860 &&
@@ -541,7 +541,7 @@
else
i2s_samplerates = 3;
em28xx_info("I2S Audio (%d sample rate(s))\n",
- i2s_samplerates);
+ i2s_samplerates);
/* Skip the code that does AC97 vendor detection */
dev->audio_mode.ac97 = EM28XX_NO_AC97;
goto init_audio;
@@ -614,9 +614,8 @@
{
if (dev->board.leds) {
u8 k = 0;
-
while (dev->board.leds[k].role >= 0 &&
- dev->board.leds[k].role < EM28XX_NUM_LED_ROLES) {
+ dev->board.leds[k].role < EM28XX_NUM_LED_ROLES) {
if (dev->board.leds[k].role == role)
return &dev->board.leds[k];
k++;
@@ -659,12 +658,10 @@
if (dev->mode == EM28XX_ANALOG_MODE)
rc = em28xx_write_reg(dev,
- EM28XX_R12_VINENABLE,
- 0x67);
+ EM28XX_R12_VINENABLE, 0x67);
else
rc = em28xx_write_reg(dev,
- EM28XX_R12_VINENABLE,
- 0x37);
+ EM28XX_R12_VINENABLE, 0x37);
if (rc < 0)
return rc;
@@ -818,9 +815,9 @@
if (usb_bufs->transfer_buffer[i]) {
usb_free_coherent(dev->udev,
- urb->transfer_buffer_length,
- usb_bufs->transfer_buffer[i],
- urb->transfer_dma);
+ urb->transfer_buffer_length,
+ usb_bufs->transfer_buffer[i],
+ urb->transfer_dma);
}
usb_free_urb(urb);
usb_bufs->urb[i] = NULL;
@@ -892,7 +889,7 @@
if ((xfer_bulk && !dev->analog_ep_bulk) ||
(!xfer_bulk && !dev->analog_ep_isoc)) {
em28xx_errdev("no endpoint for analog mode and transfer type %d\n",
- xfer_bulk > 0);
+ xfer_bulk > 0);
return -EINVAL;
}
usb_bufs = &dev->usb_ctl.analog_bufs;
@@ -991,9 +988,9 @@
* Allocate URBs and start IRQ
*/
int em28xx_init_usb_xfer(struct em28xx *dev, enum em28xx_mode mode,
- int xfer_bulk, int num_bufs, int max_pkt_size,
+ int xfer_bulk, int num_bufs, int max_pkt_size,
int packet_multiplier,
- int (*urb_data_copy)(struct em28xx *dev, struct urb *urb))
+ int (*urb_data_copy) (struct em28xx *dev, struct urb *urb))
{
struct em28xx_dmaqueue *dma_q = &dev->vidq;
struct em28xx_dmaqueue *vbi_dma_q = &dev->vbiq;
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index 9877b69..9682c52 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -63,6 +63,7 @@
MODULE_DESCRIPTION(DRIVER_DESC " - digital TV interface");
MODULE_VERSION(EM28XX_VERSION);
+
static unsigned int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "enable debug messages [dvb]");
@@ -70,7 +71,7 @@
DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define dprintk(level, fmt, arg...) do { \
-if (debug >= level) \
+if (debug >= level) \
printk(KERN_DEBUG "%s/2-dvb: " fmt, dev->name, ## arg); \
} while (0)
@@ -98,8 +99,9 @@
struct i2c_client *i2c_client_tuner;
};
+
static inline void print_err_status(struct em28xx *dev,
- int packet, int status)
+ int packet, int status)
{
char *errmsg = "Unknown";
@@ -167,7 +169,7 @@
if (!urb->actual_length)
continue;
dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer,
- urb->actual_length);
+ urb->actual_length);
} else {
if (urb->iso_frame_desc[i].status < 0) {
print_err_status(dev, i,
@@ -278,6 +280,7 @@
}
+
/* ------------------------------------------------------------------ */
static int em28xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
{
@@ -737,7 +740,7 @@
return ret;
#else
dev_warn(&dev->udev->dev, "%s: LNA control is disabled (lna=%u)\n",
- KBUILD_MODNAME, c->lna);
+ KBUILD_MODNAME, c->lna);
return 0;
#endif
}
@@ -827,7 +830,6 @@
.no_tuner = 1,
.parallel_ts = 1,
};
-
static struct qt1010_config em28xx_qt1010_config = {
.i2c_address = 0x62
};
@@ -859,6 +861,7 @@
.agc = 0x99,
};
+
static struct tda18271_std_map drx_j_std_map = {
.atsc_6 = { .if_freq = 5000, .agc_mode = 3, .std = 0, .if_lvl = 1,
.rfagc_top = 0x37, },
@@ -945,7 +948,7 @@
result = dvb_register_frontend(&dvb->adapter, dvb->fe[1]);
if (result < 0) {
printk(KERN_WARNING "%s: 2nd dvb_register_frontend failed (errno = %d)\n",
- dev->name, result);
+ dev->name, result);
goto fail_frontend1;
}
}
@@ -1044,7 +1047,7 @@
static int em28xx_dvb_init(struct em28xx *dev)
{
- int result = 0;
+ int result = 0, mfe_shared = 0;
struct em28xx_dvb *dvb;
if (dev->is_audio_only) {
@@ -1179,8 +1182,7 @@
&dev->i2c_adap[dev->def_i2c_bus]);
if (dvb->fe[0] != NULL) {
if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
- &dev->i2c_adap[dev->def_i2c_bus],
- 0x61, TUNER_THOMSON_DTT761X)) {
+ &dev->i2c_adap[dev->def_i2c_bus], 0x61, TUNER_THOMSON_DTT761X)) {
result = -EINVAL;
goto out_free;
}
@@ -1202,8 +1204,7 @@
&dev->i2c_adap[dev->def_i2c_bus], 0x48);
if (dvb->fe[0]) {
if (!dvb_attach(simple_tuner_attach, dvb->fe[0],
- &dev->i2c_adap[dev->def_i2c_bus],
- 0x60, TUNER_PHILIPS_CU1216L)) {
+ &dev->i2c_adap[dev->def_i2c_bus], 0x60, TUNER_PHILIPS_CU1216L)) {
result = -EINVAL;
goto out_free;
}
@@ -1218,7 +1219,7 @@
goto out_free;
}
if (!dvb_attach(tda18271_attach, dvb->fe[0], 0x60,
- &dev->i2c_adap[dev->def_i2c_bus],
+ &dev->i2c_adap[dev->def_i2c_bus],
&kworld_a340_config)) {
dvb_frontend_detach(dvb->fe[0]);
result = -EINVAL;
@@ -1249,10 +1250,10 @@
#ifdef CONFIG_GPIOLIB
/* enable LNA for DVB-T, DVB-T2 and DVB-C */
result = gpio_request_one(dvb->lna_gpio,
- GPIOF_OUT_INIT_LOW, NULL);
+ GPIOF_OUT_INIT_LOW, NULL);
if (result)
em28xx_errdev("gpio request failed %d\n",
- result);
+ result);
else
gpio_free(dvb->lna_gpio);
@@ -1265,7 +1266,6 @@
case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
{
struct xc5000_config cfg;
-
hauppauge_hvr930c_init(dev);
dvb->fe[0] = dvb_attach(drxk_attach,
@@ -1339,7 +1339,7 @@
/* attach SEC */
if (dvb->fe[0])
dvb_attach(a8293_attach, dvb->fe[0], &dev->i2c_adap[dev->def_i2c_bus],
- &em28xx_a8293_config);
+ &em28xx_a8293_config);
break;
case EM2874_BOARD_DELOCK_61959:
case EM2874_BOARD_MAXMEDIA_UB425_TC:
@@ -1553,7 +1553,6 @@
struct si2157_config si2157_config;
/* attach demod */
- memset(&si2168_config, 0, sizeof(si2168_config));
si2168_config.i2c_adapter = &adapter;
si2168_config.fe = &dvb->fe[0];
si2168_config.ts_mode = SI2168_TS_PARALLEL;
@@ -1604,65 +1603,6 @@
dvb->fe[0]->ops.set_lna = em28xx_pctv_292e_set_lna;
}
break;
- case EM28178_BOARD_TERRATEC_T2_STICK_HD:
- {
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- struct i2c_board_info info;
- struct si2168_config si2168_config;
- struct si2157_config si2157_config;
-
- /* attach demod */
- memset(&si2168_config, 0, sizeof(si2168_config));
- si2168_config.i2c_adapter = &adapter;
- si2168_config.fe = &dvb->fe[0];
- si2168_config.ts_mode = SI2168_TS_PARALLEL;
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2168", I2C_NAME_SIZE);
- info.addr = 0x64;
- info.platform_data = &si2168_config;
- request_module(info.type);
- client = i2c_new_device(&dev->i2c_adap[dev->def_i2c_bus], &info);
- if (client == NULL || client->dev.driver == NULL) {
- result = -ENODEV;
- goto out_free;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_demod = client;
-
- /* attach tuner */
- memset(&si2157_config, 0, sizeof(si2157_config));
- si2157_config.fe = dvb->fe[0];
- memset(&info, 0, sizeof(struct i2c_board_info));
- strlcpy(info.type, "si2146", I2C_NAME_SIZE);
- info.addr = 0x60;
- info.platform_data = &si2157_config;
- request_module("si2157");
- client = i2c_new_device(adapter, &info);
- if (client == NULL || client->dev.driver == NULL) {
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
-
- if (!try_module_get(client->dev.driver->owner)) {
- i2c_unregister_device(client);
- module_put(dvb->i2c_client_demod->dev.driver->owner);
- i2c_unregister_device(dvb->i2c_client_demod);
- result = -ENODEV;
- goto out_free;
- }
-
- dvb->i2c_client_tuner = client;
- }
- break;
default:
em28xx_errdev("/2: The frontend of your DVB/ATSC card"
" isn't supported yet\n");
@@ -1684,6 +1624,9 @@
if (result < 0)
goto out_free;
+ /* MFE lock */
+ dvb->adapter.mfe_shared = mfe_shared;
+
em28xx_info("DVB extension successfully initialized\n");
kref_get(&dev->ref);
diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c
index a19b5c8..1048c1a 100644
--- a/drivers/media/usb/em28xx/em28xx-i2c.c
+++ b/drivers/media/usb/em28xx/em28xx-i2c.c
@@ -593,7 +593,6 @@
unsigned long l = 0;
int len = 0;
unsigned char c;
-
do {
if (len == length) {
c = (char)len;
@@ -878,7 +877,6 @@
* incomplete list of known devices
*/
static char *i2c_devs[128] = {
- [0x1c >> 1] = "lgdt330x",
[0x3e >> 1] = "remote IR sensor",
[0x4a >> 1] = "saa7113h",
[0x52 >> 1] = "drxk",
@@ -951,7 +949,7 @@
retval = i2c_add_adapter(&dev->i2c_adap[bus]);
if (retval < 0) {
em28xx_errdev("%s: i2c_add_adapter failed! retval [%d]\n",
- __func__, retval);
+ __func__, retval);
return retval;
}
@@ -963,7 +961,7 @@
retval = em28xx_i2c_eeprom(dev, bus, &dev->eedata, &dev->eedata_len);
if ((retval < 0) && (retval != -ENODEV)) {
em28xx_errdev("%s: em28xx_i2_eeprom failed! retval [%d]\n",
- __func__, retval);
+ __func__, retval);
return retval;
}
diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c
index d8dc03a..581f6da 100644
--- a/drivers/media/usb/em28xx/em28xx-input.c
+++ b/drivers/media/usb/em28xx/em28xx-input.c
@@ -459,7 +459,7 @@
return em2874_ir_change_protocol(rc_dev, rc_type);
default:
printk("Unrecognized em28xx chip id 0x%02x: IR not supported\n",
- dev->chip_id);
+ dev->chip_id);
return -EINVAL;
}
}
@@ -505,7 +505,7 @@
/* Check states of the buttons and act */
j = 0;
while (dev->board.buttons[j].role >= 0 &&
- dev->board.buttons[j].role < EM28XX_NUM_BUTTON_ROLES) {
+ dev->board.buttons[j].role < EM28XX_NUM_BUTTON_ROLES) {
struct em28xx_button *button = &dev->board.buttons[j];
/* Check if button uses the current address */
if (button->reg_r != dev->button_polling_addresses[i]) {
@@ -607,7 +607,7 @@
dev->button_polling_interval = EM28XX_BUTTONS_DEBOUNCED_QUERY_INTERVAL;
while (dev->board.buttons[i].role >= 0 &&
- dev->board.buttons[i].role < EM28XX_NUM_BUTTON_ROLES) {
+ dev->board.buttons[i].role < EM28XX_NUM_BUTTON_ROLES) {
struct em28xx_button *button = &dev->board.buttons[i];
/* Check if polling address is already on the list */
addr_new = true;
@@ -653,11 +653,11 @@
/* Start polling */
if (dev->num_button_polling_addresses) {
memset(dev->button_polling_last_values, 0,
- EM28XX_NUM_BUTTON_ADDRESSES_MAX);
+ EM28XX_NUM_BUTTON_ADDRESSES_MAX);
INIT_DELAYED_WORK(&dev->buttons_query_work,
- em28xx_query_buttons);
+ em28xx_query_buttons);
schedule_delayed_work(&dev->buttons_query_work,
- msecs_to_jiffies(dev->button_polling_interval));
+ msecs_to_jiffies(dev->button_polling_interval));
}
}
@@ -712,10 +712,8 @@
em28xx_info("Registering input extension\n");
ir = kzalloc(sizeof(*ir), GFP_KERNEL);
- if (!ir)
- return -ENOMEM;
rc = rc_allocate_device();
- if (!rc)
+ if (!ir || !rc)
goto error;
/* record handles to ourself */
@@ -841,7 +839,8 @@
if (!ir)
goto ref_put;
- rc_unregister_device(ir->rc);
+ if (ir->rc)
+ rc_unregister_device(ir->rc);
kfree(ir->i2c_client);
@@ -886,7 +885,7 @@
schedule_delayed_work(&ir->work, msecs_to_jiffies(ir->polling));
if (dev->num_button_polling_addresses)
schedule_delayed_work(&dev->buttons_query_work,
- msecs_to_jiffies(dev->button_polling_interval));
+ msecs_to_jiffies(dev->button_polling_interval));
return 0;
}
diff --git a/drivers/media/usb/em28xx/em28xx-reg.h b/drivers/media/usb/em28xx/em28xx-reg.h
index 13cbb7f..311fb34 100644
--- a/drivers/media/usb/em28xx/em28xx-reg.h
+++ b/drivers/media/usb/em28xx/em28xx-reg.h
@@ -49,6 +49,7 @@
#define EM28XX_CHIPCFG2_TS_PACKETSIZE_564 0x02
#define EM28XX_CHIPCFG2_TS_PACKETSIZE_752 0x03
+
/* GPIO/GPO registers */
#define EM2880_R04_GPO 0x04 /* em2880-em2883 only */
#define EM2820_R08_GPIO_CTRL 0x08 /* em2820-em2873/83 only */
@@ -67,6 +68,7 @@
#define EM28XX_I2C_FREQ_400_KHZ 0x01
#define EM28XX_I2C_FREQ_100_KHZ 0x00
+
#define EM28XX_R0A_CHIPID 0x0a
#define EM28XX_R0C_USBSUSP 0x0c
#define EM28XX_R0C_USBSUSP_SNAPSHOT 0x20 /* 1=button pressed, needs reset */
@@ -155,6 +157,7 @@
#define EM28XX_OUTFMT_YUV422_Y1UY0V 0x15
#define EM28XX_OUTFMT_YUV411 0x18
+
#define EM28XX_R28_XMIN 0x28
#define EM28XX_R29_XMAX 0x29
#define EM28XX_R2A_YMIN 0x2a
diff --git a/drivers/media/usb/em28xx/em28xx-v4l.h b/drivers/media/usb/em28xx/em28xx-v4l.h
index 8dfcb56..432862c 100644
--- a/drivers/media/usb/em28xx/em28xx-v4l.h
+++ b/drivers/media/usb/em28xx/em28xx-v4l.h
@@ -14,6 +14,7 @@
GNU General Public License for more details.
*/
+
int em28xx_start_analog_streaming(struct vb2_queue *vq, unsigned int count);
void em28xx_stop_vbi_streaming(struct vb2_queue *vq);
extern struct vb2_ops em28xx_vbi_qops;
diff --git a/drivers/media/usb/em28xx/em28xx-vbi.c b/drivers/media/usb/em28xx/em28xx-vbi.c
index 744e7ed..34ee1e0 100644
--- a/drivers/media/usb/em28xx/em28xx-vbi.c
+++ b/drivers/media/usb/em28xx/em28xx-vbi.c
@@ -92,6 +92,7 @@
spin_unlock_irqrestore(&dev->slock, flags);
}
+
struct vb2_ops em28xx_vbi_qops = {
.queue_setup = vbi_queue_setup,
.buf_prepare = vbi_buffer_prepare,
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index bf1be43..f35083c 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -81,6 +81,7 @@
MODULE_LICENSE("GPL");
MODULE_VERSION(EM28XX_VERSION);
+
#define EM25XX_FRMDATAHDR_BYTE1 0x02
#define EM25XX_FRMDATAHDR_BYTE2_STILL_IMAGE 0x20
#define EM25XX_FRMDATAHDR_BYTE2_FRAME_END 0x02
@@ -89,6 +90,7 @@
EM25XX_FRMDATAHDR_BYTE2_FRAME_END | \
EM25XX_FRMDATAHDR_BYTE2_FRAME_ID)
+
static unsigned int video_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
static unsigned int vbi_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
static unsigned int radio_nr[] = {[0 ... (EM28XX_MAXBOARDS - 1)] = -1U };
@@ -192,10 +194,9 @@
static void em28xx_wake_i2c(struct em28xx *dev)
{
struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
-
v4l2_device_call_all(v4l2_dev, 0, core, reset, 0);
v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
- INPUT(dev->ctl_input)->vmux, 0, 0);
+ INPUT(dev->ctl_input)->vmux, 0, 0);
v4l2_device_call_all(v4l2_dev, 0, video, s_stream, 0);
}
@@ -274,7 +275,7 @@
}
static void em28xx_capture_area_set(struct em28xx *dev, u8 hstart, u8 vstart,
- u16 width, u16 height)
+ u16 width, u16 height)
{
u8 cwidth = width >> 2;
u8 cheight = height >> 2;
@@ -282,7 +283,7 @@
/* NOTE: size limit: 2047x1023 = 2MPix */
em28xx_videodbg("capture area set to (%d,%d): %dx%d\n",
- hstart, vstart,
+ hstart, vstart,
((overflow & 2) << 9 | cwidth << 2),
((overflow & 1) << 10 | cheight << 2));
@@ -405,13 +406,13 @@
dev->packet_multiplier = EM28XX_BULK_PACKET_MULTIPLIER;
} else { /* isoc */
em28xx_videodbg("minimum isoc packet size: %u (alt=%d)\n",
- min_pkt_size, dev->alt);
+ min_pkt_size, dev->alt);
dev->max_pkt_size =
dev->alt_max_pkt_size_isoc[dev->alt];
dev->packet_multiplier = EM28XX_NUM_ISOC_PACKETS;
}
em28xx_videodbg("setting alternate %d with wMaxPacketSize=%u\n",
- dev->alt, dev->max_pkt_size);
+ dev->alt, dev->max_pkt_size);
errCode = usb_set_interface(dev->udev, dev->ifnum, dev->alt);
if (errCode < 0) {
em28xx_errdev("cannot change alternate number to %d (error=%i)\n",
@@ -481,7 +482,7 @@
if ((char *)startwrite + lencopy > (char *)buf->vb_buf + buf->length) {
em28xx_isocdbg("Overflow of %zu bytes past buffer end (1)\n",
- ((char *)startwrite + lencopy) -
+ ((char *)startwrite + lencopy) -
((char *)buf->vb_buf + buf->length));
remain = (char *)buf->vb_buf + buf->length -
(char *)startwrite;
@@ -547,7 +548,7 @@
}
static inline void print_err_status(struct em28xx *dev,
- int packet, int status)
+ int packet, int status)
{
char *errmsg = "Unknown";
@@ -830,6 +831,7 @@
return 1;
}
+
static int get_ressource(enum v4l2_buf_type f_type)
{
switch (f_type) {
@@ -1001,7 +1003,6 @@
}
while (!list_empty(&vidq->active)) {
struct em28xx_buffer *buf;
-
buf = list_entry(vidq->active.next, struct em28xx_buffer, list);
list_del(&buf->list);
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
@@ -1032,7 +1033,6 @@
}
while (!list_empty(&vbiq->active)) {
struct em28xx_buffer *buf;
-
buf = list_entry(vbiq->active.next, struct em28xx_buffer, list);
list_del(&buf->list);
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
@@ -1109,7 +1109,6 @@
static void video_mux(struct em28xx *dev, int index)
{
struct v4l2_device *v4l2_dev = &dev->v4l2->v4l2_dev;
-
dev->ctl_input = index;
dev->ctl_ainput = INPUT(index)->amux;
dev->ctl_aoutput = INPUT(index)->aout;
@@ -1118,22 +1117,21 @@
dev->ctl_aoutput = EM28XX_AOUT_MASTER;
v4l2_device_call_all(v4l2_dev, 0, video, s_routing,
- INPUT(index)->vmux, 0, 0);
+ INPUT(index)->vmux, 0, 0);
if (dev->board.has_msp34xx) {
if (dev->i2s_speed) {
v4l2_device_call_all(v4l2_dev, 0, audio,
- s_i2s_clock_freq, dev->i2s_speed);
+ s_i2s_clock_freq, dev->i2s_speed);
}
/* Note: this is msp3400 specific */
v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
- dev->ctl_ainput,
- MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
+ dev->ctl_ainput, MSP_OUTPUT(MSP_SC_IN_DSP_SCART1), 0);
}
if (dev->board.adecoder != EM28XX_NOADECODER) {
v4l2_device_call_all(v4l2_dev, 0, audio, s_routing,
- dev->ctl_ainput, dev->ctl_aoutput, 0);
+ dev->ctl_ainput, dev->ctl_aoutput, 0);
}
em28xx_audio_analog_set(dev);
@@ -1205,7 +1203,7 @@
};
static void size_to_scale(struct em28xx *dev,
- unsigned int width, unsigned int height,
+ unsigned int width, unsigned int height,
unsigned int *hscale, unsigned int *vscale)
{
unsigned int maxw = norm_maxw(dev);
@@ -1236,7 +1234,7 @@
------------------------------------------------------------------*/
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+ struct v4l2_format *f)
{
struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
@@ -1269,7 +1267,7 @@
}
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+ struct v4l2_format *f)
{
struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
@@ -1340,7 +1338,7 @@
/* set new image size */
size_to_scale(dev, v4l2->width, v4l2->height,
- &v4l2->hscale, &v4l2->vscale);
+ &v4l2->hscale, &v4l2->vscale);
em28xx_resolution_set(dev);
@@ -1348,7 +1346,7 @@
}
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_format *f)
+ struct v4l2_format *f)
{
struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
@@ -1403,7 +1401,7 @@
v4l2->width = f.fmt.pix.width;
v4l2->height = f.fmt.pix.height;
size_to_scale(dev, v4l2->width, v4l2->height,
- &v4l2->hscale, &v4l2->vscale);
+ &v4l2->hscale, &v4l2->vscale);
em28xx_resolution_set(dev);
v4l2_device_call_all(&v4l2->v4l2_dev, 0, video, s_std, v4l2->norm);
@@ -1424,7 +1422,7 @@
video, g_parm, p);
else
v4l2_video_std_frame_period(v4l2->norm,
- &p->parm.capture.timeperframe);
+ &p->parm.capture.timeperframe);
return rc;
}
@@ -1452,7 +1450,7 @@
};
static int vidioc_enum_input(struct file *file, void *priv,
- struct v4l2_input *i)
+ struct v4l2_input *i)
{
struct em28xx *dev = video_drvdata(file);
unsigned int n;
@@ -1469,7 +1467,7 @@
strcpy(i->name, iname[INPUT(n)->type]);
if ((EM28XX_VMUX_TELEVISION == INPUT(n)->type) ||
- (EM28XX_VMUX_CABLE == INPUT(n)->type))
+ (EM28XX_VMUX_CABLE == INPUT(n)->type))
i->type = V4L2_INPUT_TYPE_TUNER;
i->std = dev->v4l2->vdev->tvnorms;
@@ -1560,7 +1558,7 @@
}
static int vidioc_g_tuner(struct file *file, void *priv,
- struct v4l2_tuner *t)
+ struct v4l2_tuner *t)
{
struct em28xx *dev = video_drvdata(file);
@@ -1574,7 +1572,7 @@
}
static int vidioc_s_tuner(struct file *file, void *priv,
- const struct v4l2_tuner *t)
+ const struct v4l2_tuner *t)
{
struct em28xx *dev = video_drvdata(file);
@@ -1586,7 +1584,7 @@
}
static int vidioc_g_frequency(struct file *file, void *priv,
- struct v4l2_frequency *f)
+ struct v4l2_frequency *f)
{
struct em28xx *dev = video_drvdata(file);
struct em28xx_v4l2 *v4l2 = dev->v4l2;
@@ -1599,7 +1597,7 @@
}
static int vidioc_s_frequency(struct file *file, void *priv,
- const struct v4l2_frequency *f)
+ const struct v4l2_frequency *f)
{
struct v4l2_frequency new_freq = *f;
struct em28xx *dev = video_drvdata(file);
@@ -1617,7 +1615,7 @@
#ifdef CPTCFG_VIDEO_ADV_DEBUG
static int vidioc_g_chip_info(struct file *file, void *priv,
- struct v4l2_dbg_chip_info *chip)
+ struct v4l2_dbg_chip_info *chip)
{
struct em28xx *dev = video_drvdata(file);
@@ -1672,7 +1670,6 @@
reg->val = ret;
} else {
__le16 val = 0;
-
ret = dev->em28xx_read_reg_req_len(dev, USB_REQ_GET_STATUS,
reg->reg, (char *)&val, 2);
if (ret < 0)
@@ -1703,8 +1700,9 @@
}
#endif
+
static int vidioc_querycap(struct file *file, void *priv,
- struct v4l2_capability *cap)
+ struct v4l2_capability *cap)
{
struct video_device *vdev = video_devdata(file);
struct em28xx *dev = video_drvdata(file);
@@ -1738,7 +1736,7 @@
}
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
- struct v4l2_fmtdesc *f)
+ struct v4l2_fmtdesc *f)
{
if (unlikely(f->index >= ARRAY_SIZE(format)))
return -EINVAL;
@@ -2179,10 +2177,9 @@
/******************************** usb interface ******************************/
-static struct video_device
-*em28xx_vdev_init(struct em28xx *dev,
- const struct video_device *template,
- const char *type_name)
+static struct video_device *em28xx_vdev_init(struct em28xx *dev,
+ const struct video_device *template,
+ const char *type_name)
{
struct video_device *vfd;
@@ -2347,24 +2344,21 @@
if (dev->board.radio.type)
v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
- &dev->i2c_adap[dev->def_i2c_bus],
- "tuner", dev->board.radio_addr,
- NULL);
+ &dev->i2c_adap[dev->def_i2c_bus],
+ "tuner", dev->board.radio_addr, NULL);
if (has_demod)
v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
- &dev->i2c_adap[dev->def_i2c_bus],
- "tuner", 0,
- v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
+ &dev->i2c_adap[dev->def_i2c_bus], "tuner",
+ 0, v4l2_i2c_tuner_addrs(ADDRS_DEMOD));
if (tuner_addr == 0) {
enum v4l2_i2c_tuner_type type =
has_demod ? ADDRS_TV_WITH_DEMOD : ADDRS_TV;
struct v4l2_subdev *sd;
sd = v4l2_i2c_new_subdev(&v4l2->v4l2_dev,
- &dev->i2c_adap[dev->def_i2c_bus],
- "tuner", 0,
- v4l2_i2c_tuner_addrs(type));
+ &dev->i2c_adap[dev->def_i2c_bus], "tuner",
+ 0, v4l2_i2c_tuner_addrs(type));
if (sd)
tuner_addr = v4l2_i2c_subdev_addr(sd);
@@ -2384,20 +2378,20 @@
ret = em28xx_audio_setup(dev);
if (ret < 0) {
em28xx_errdev("%s: Error while setting audio - error [%d]!\n",
- __func__, ret);
+ __func__, ret);
goto unregister_dev;
}
if (dev->audio_mode.ac97 != EM28XX_NO_AC97) {
v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
- V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+ V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
v4l2_ctrl_new_std(hdl, &em28xx_ctrl_ops,
- V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
+ V4L2_CID_AUDIO_VOLUME, 0, 0x1f, 1, 0x1f);
} else {
/* install the em28xx notify callback */
v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_MUTE),
- em28xx_ctrl_notify, dev);
+ em28xx_ctrl_notify, dev);
v4l2_ctrl_notify(v4l2_ctrl_find(hdl, V4L2_CID_AUDIO_VOLUME),
- em28xx_ctrl_notify, dev);
+ em28xx_ctrl_notify, dev);
}
/* wake i2c devices */
@@ -2524,7 +2518,7 @@
/* register v4l2 video video_device */
ret = video_register_device(v4l2->vdev, VFL_TYPE_GRABBER,
- video_nr[dev->devno]);
+ video_nr[dev->devno]);
if (ret) {
em28xx_errdev("unable to register video device (error=%i).\n",
ret);
diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h
index 9c70753..a21a746 100644
--- a/drivers/media/usb/em28xx/em28xx.h
+++ b/drivers/media/usb/em28xx/em28xx.h
@@ -141,8 +141,6 @@
#define EM28178_BOARD_PCTV_461E 92
#define EM2874_BOARD_KWORLD_UB435Q_V3 93
#define EM28178_BOARD_PCTV_292E 94
-#define EM2861_BOARD_LEADTEK_VC100 95
-#define EM28178_BOARD_TERRATEC_T2_STICK_HD 96
/* Limits minimum and default number of buffers */
#define EM28XX_MIN_BUF 4
@@ -217,6 +215,7 @@
EM28XX_DIGITAL_MODE,
};
+
struct em28xx;
struct em28xx_usb_bufs {
@@ -244,11 +243,11 @@
struct em28xx_usb_bufs digital_bufs;
/* Stores already requested buffers */
- struct em28xx_buffer *vid_buf;
- struct em28xx_buffer *vbi_buf;
+ struct em28xx_buffer *vid_buf;
+ struct em28xx_buffer *vbi_buf;
/* copy data from URB */
- int (*urb_data_copy)(struct em28xx *dev, struct urb *urb);
+ int (*urb_data_copy) (struct em28xx *dev, struct urb *urb);
};
@@ -696,14 +695,14 @@
char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */
/* helper funcs that call usb_control_msg */
- int (*em28xx_write_regs)(struct em28xx *dev, u16 reg,
- char *buf, int len);
- int (*em28xx_read_reg)(struct em28xx *dev, u16 reg);
- int (*em28xx_read_reg_req_len)(struct em28xx *dev, u8 req, u16 reg,
- char *buf, int len);
- int (*em28xx_write_regs_req)(struct em28xx *dev, u8 req, u16 reg,
- char *buf, int len);
- int (*em28xx_read_reg_req)(struct em28xx *dev, u8 req, u16 reg);
+ int (*em28xx_write_regs) (struct em28xx *dev, u16 reg,
+ char *buf, int len);
+ int (*em28xx_read_reg) (struct em28xx *dev, u16 reg);
+ int (*em28xx_read_reg_req_len) (struct em28xx *dev, u8 req, u16 reg,
+ char *buf, int len);
+ int (*em28xx_write_regs_req) (struct em28xx *dev, u8 req, u16 reg,
+ char *buf, int len);
+ int (*em28xx_read_reg_req) (struct em28xx *dev, u8 req, u16 reg);
enum em28xx_mode mode;
@@ -746,7 +745,7 @@
int em28xx_write_regs(struct em28xx *dev, u16 reg, char *buf, int len);
int em28xx_write_reg(struct em28xx *dev, u16 reg, u8 val);
int em28xx_write_reg_bits(struct em28xx *dev, u16 reg, u8 val,
- u8 bitmask);
+ u8 bitmask);
int em28xx_toggle_reg_bits(struct em28xx *dev, u16 reg, u8 bitmask);
int em28xx_read_ac97(struct em28xx *dev, u8 reg);
diff --git a/drivers/media/usb/go7007/go7007-v4l2.c b/drivers/media/usb/go7007/go7007-v4l2.c
index d6bf982..ec799b4 100644
--- a/drivers/media/usb/go7007/go7007-v4l2.c
+++ b/drivers/media/usb/go7007/go7007-v4l2.c
@@ -252,7 +252,7 @@
if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
struct v4l2_mbus_framefmt mbus_fmt;
- mbus_fmt.code = MEDIA_BUS_FMT_FIXED;
+ mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
mbus_fmt.width = fmt ? fmt->fmt.pix.width : width;
mbus_fmt.height = height;
go->encoder_h_halve = 0;
diff --git a/drivers/media/usb/gspca/Kconfig b/drivers/media/usb/gspca/Kconfig
index 918af60..b016ea7 100644
--- a/drivers/media/usb/gspca/Kconfig
+++ b/drivers/media/usb/gspca/Kconfig
@@ -168,7 +168,7 @@
module will be called gspca_ov519.
config USB_GSPCA_OV534
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_5
tristate "OV534 OV772x USB Camera Driver"
depends on m
depends on VIDEO_V4L2 && USB_GSPCA
diff --git a/drivers/media/usb/hackrf/hackrf.c b/drivers/media/usb/hackrf/hackrf.c
index f7df15a..527e891 100644
--- a/drivers/media/usb/hackrf/hackrf.c
+++ b/drivers/media/usb/hackrf/hackrf.c
@@ -933,7 +933,7 @@
dev->bandwidth->val = bandwidth;
dev->bandwidth->cur.val = bandwidth;
- dev_dbg(dev->dev, "bandwidth selected=%d\n", bandwidth);
+ dev_dbg(dev->dev, "bandwidth selected=%d\n", bandwidth_lut[i].freq);
u16tmp = 0;
u16tmp |= ((bandwidth >> 0) & 0xff) << 0;
diff --git a/drivers/media/usb/msi2500/Kconfig b/drivers/media/usb/msi2500/Kconfig
index 73096d6..bcbee22 100644
--- a/drivers/media/usb/msi2500/Kconfig
+++ b/drivers/media/usb/msi2500/Kconfig
@@ -1,5 +1,5 @@
config USB_MSI2500
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Mirics MSi2500"
depends on m
depends on VIDEO_V4L2 && SPI
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-context.c b/drivers/media/usb/pvrusb2/pvrusb2-context.c
index c8761c7..7c19ff7 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-context.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-context.c
@@ -80,7 +80,7 @@
static void pvr2_context_destroy(struct pvr2_context *mp)
{
pvr2_trace(PVR2_TRACE_CTXT,"pvr2_context %p (destroy)",mp);
- pvr2_hdw_destroy(mp->hdw);
+ if (mp->hdw) pvr2_hdw_destroy(mp->hdw);
pvr2_context_set_notify(mp, 0);
mutex_lock(&pvr2_context_mutex);
if (mp->exist_next) {
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
index 2fd9b5e..9623b62 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-hdw.c
@@ -2966,7 +2966,7 @@
memset(&fmt, 0, sizeof(fmt));
fmt.width = hdw->res_hor_val;
fmt.height = hdw->res_ver_val;
- fmt.code = MEDIA_BUS_FMT_FIXED;
+ fmt.code = V4L2_MBUS_FMT_FIXED;
pvr2_trace(PVR2_TRACE_CHIPS, "subdev v4l2 set_size(%dx%d)",
fmt.width, fmt.height);
v4l2_device_call_all(&hdw->v4l2_dev, 0, video, s_mbus_fmt, &fmt);
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index de55e96..ccc0009 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -558,30 +558,27 @@
}
-static void s2255_got_frame(struct s2255_vc *vc, int jpgsize)
+static int s2255_got_frame(struct s2255_vc *vc, int jpgsize)
{
struct s2255_buffer *buf;
struct s2255_dev *dev = to_s2255_dev(vc->vdev.v4l2_dev);
unsigned long flags = 0;
-
+ int rc = 0;
spin_lock_irqsave(&vc->qlock, flags);
if (list_empty(&vc->buf_list)) {
dprintk(dev, 1, "No active queue to serve\n");
- spin_unlock_irqrestore(&vc->qlock, flags);
- return;
+ rc = -1;
+ goto unlock;
}
buf = list_entry(vc->buf_list.next,
struct s2255_buffer, list);
list_del(&buf->list);
v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
- buf->vb.v4l2_buf.field = vc->field;
- buf->vb.v4l2_buf.sequence = vc->frame_count;
- spin_unlock_irqrestore(&vc->qlock, flags);
-
s2255_fillbuff(vc, buf, jpgsize);
- /* tell v4l buffer was filled */
- vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
dprintk(dev, 2, "%s: [buf] [%p]\n", __func__, buf);
+unlock:
+ spin_unlock_irqrestore(&vc->qlock, flags);
+ return rc;
}
static const struct s2255_fmt *format_by_fourcc(int fourcc)
@@ -635,7 +632,7 @@
break;
case V4L2_PIX_FMT_JPEG:
case V4L2_PIX_FMT_MJPEG:
- vb2_set_plane_payload(&buf->vb, 0, jpgsize);
+ buf->vb.v4l2_buf.length = jpgsize;
memcpy(vbuf, tmpbuf, jpgsize);
break;
case V4L2_PIX_FMT_YUV422P:
@@ -652,6 +649,11 @@
}
dprintk(dev, 2, "s2255fill at : Buffer 0x%08lx size= %d\n",
(unsigned long)vbuf, pos);
+ /* tell v4l buffer was filled */
+ buf->vb.v4l2_buf.field = vc->field;
+ buf->vb.v4l2_buf.sequence = vc->frame_count;
+ v4l2_get_timestamp(&buf->vb.v4l2_buf.timestamp);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
}
@@ -1974,7 +1976,8 @@
{
unsigned long i;
for (i = 0; i < SYS_FRAMES; i++) {
- vfree(vc->buffer.frame[i].lpvbits);
+ if (vc->buffer.frame[i].lpvbits)
+ vfree(vc->buffer.frame[i].lpvbits);
vc->buffer.frame[i].lpvbits = NULL;
}
return 0;
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index 963eae2..547f749 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -475,7 +475,7 @@
struct stk1160 *dev = video_drvdata(file);
/* Match host */
- return stk1160_write_reg(dev, reg->reg, reg->val);
+ return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val));
}
#endif
diff --git a/drivers/media/usb/tlg2300/Kconfig b/drivers/media/usb/tlg2300/Kconfig
new file mode 100644
index 0000000..1d60d9b
--- /dev/null
+++ b/drivers/media/usb/tlg2300/Kconfig
@@ -0,0 +1,17 @@
+config VIDEO_TLG2300
+ tristate "Telegent TLG2300 USB video capture support"
+ depends on m
+ depends on VIDEO_DEV && I2C && SND && DVB_CORE
+ select VIDEO_TUNER
+ select VIDEO_TVEEPROM
+ depends on RC_CORE
+ select VIDEOBUF_VMALLOC
+ depends on SND_PCM
+ select VIDEOBUF_DVB
+
+ ---help---
+ This is a video4linux driver for Telegent tlg2300 based TV cards.
+ The driver supports V4L2, DVB-T and radio.
+
+ To compile this driver as a module, choose M here: the
+ module will be called poseidon
diff --git a/drivers/media/usb/tlg2300/Makefile b/drivers/media/usb/tlg2300/Makefile
new file mode 100644
index 0000000..643eb25
--- /dev/null
+++ b/drivers/media/usb/tlg2300/Makefile
@@ -0,0 +1,9 @@
+poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o
+
+obj-$(CPTCFG_VIDEO_TLG2300) += poseidon.o
+
+ccflags-y += -I$(backport_srctree)/drivers/media/i2c
+ccflags-y += -I$(backport_srctree)/drivers/media/tuners
+ccflags-y += -I$(backport_srctree)/drivers/media/dvb-core
+ccflags-y += -I$(backport_srctree)/drivers/media/dvb-frontends
+
diff --git a/drivers/media/usb/tlg2300/pd-alsa.c b/drivers/media/usb/tlg2300/pd-alsa.c
new file mode 100644
index 0000000..dd8fe10
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-alsa.c
@@ -0,0 +1,337 @@
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/init.h>
+#include <linux/sound.h>
+#include <linux/spinlock.h>
+#include <linux/soundcard.h>
+#include <linux/vmalloc.h>
+#include <linux/proc_fs.h>
+#include <linux/module.h>
+#include <linux/gfp.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/info.h>
+#include <sound/initval.h>
+#include <sound/control.h>
+#include <media/v4l2-common.h>
+#include "pd-common.h"
+#include "vendorcmds.h"
+
+static void complete_handler_audio(struct urb *urb);
+#define AUDIO_EP (0x83)
+#define AUDIO_BUF_SIZE (512)
+#define PERIOD_SIZE (1024 * 8)
+#define PERIOD_MIN (4)
+#define PERIOD_MAX PERIOD_MIN
+
+static struct snd_pcm_hardware snd_pd_hw_capture = {
+ .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID,
+
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .rates = SNDRV_PCM_RATE_48000,
+
+ .rate_min = 48000,
+ .rate_max = 48000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .buffer_bytes_max = PERIOD_SIZE * PERIOD_MIN,
+ .period_bytes_min = PERIOD_SIZE,
+ .period_bytes_max = PERIOD_SIZE,
+ .periods_min = PERIOD_MIN,
+ .periods_max = PERIOD_MAX,
+ /*
+ .buffer_bytes_max = 62720 * 8,
+ .period_bytes_min = 64,
+ .period_bytes_max = 12544,
+ .periods_min = 2,
+ .periods_max = 98
+ */
+};
+
+static int snd_pd_capture_open(struct snd_pcm_substream *substream)
+{
+ struct poseidon *p = snd_pcm_substream_chip(substream);
+ struct poseidon_audio *pa = &p->audio;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if (!p)
+ return -ENODEV;
+ pa->users++;
+ pa->card_close = 0;
+ pa->capture_pcm_substream = substream;
+ runtime->private_data = p;
+
+ runtime->hw = snd_pd_hw_capture;
+ snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ usb_autopm_get_interface(p->interface);
+ kref_get(&p->kref);
+ return 0;
+}
+
+static int snd_pd_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct poseidon *p = snd_pcm_substream_chip(substream);
+ struct poseidon_audio *pa = &p->audio;
+
+ pa->users--;
+ pa->card_close = 1;
+ usb_autopm_put_interface(p->interface);
+ kref_put(&p->kref, poseidon_delete);
+ return 0;
+}
+
+static int snd_pd_hw_capture_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned int size;
+
+ size = params_buffer_bytes(hw_params);
+ if (runtime->dma_area) {
+ if (runtime->dma_bytes > size)
+ return 0;
+ vfree(runtime->dma_area);
+ }
+ runtime->dma_area = vmalloc(size);
+ if (!runtime->dma_area)
+ return -ENOMEM;
+ else
+ runtime->dma_bytes = size;
+ return 0;
+}
+
+static int audio_buf_free(struct poseidon *p)
+{
+ struct poseidon_audio *pa = &p->audio;
+ int i;
+
+ for (i = 0; i < AUDIO_BUFS; i++)
+ if (pa->urb_array[i])
+ usb_kill_urb(pa->urb_array[i]);
+ free_all_urb_generic(pa->urb_array, AUDIO_BUFS);
+ logpm();
+ return 0;
+}
+
+static int snd_pd_hw_capture_free(struct snd_pcm_substream *substream)
+{
+ struct poseidon *p = snd_pcm_substream_chip(substream);
+
+ logpm();
+ audio_buf_free(p);
+ return 0;
+}
+
+static int snd_pd_prepare(struct snd_pcm_substream *substream)
+{
+ return 0;
+}
+
+#define AUDIO_TRAILER_SIZE (16)
+static inline void handle_audio_data(struct urb *urb, int *period_elapsed)
+{
+ struct poseidon_audio *pa = urb->context;
+ struct snd_pcm_runtime *runtime = pa->capture_pcm_substream->runtime;
+
+ int stride = runtime->frame_bits >> 3;
+ int len = urb->actual_length / stride;
+ unsigned char *cp = urb->transfer_buffer;
+ unsigned int oldptr = pa->rcv_position;
+
+ if (urb->actual_length == AUDIO_BUF_SIZE - 4)
+ len -= (AUDIO_TRAILER_SIZE / stride);
+
+ /* do the copy */
+ if (oldptr + len >= runtime->buffer_size) {
+ unsigned int cnt = runtime->buffer_size - oldptr;
+
+ memcpy(runtime->dma_area + oldptr * stride, cp, cnt * stride);
+ memcpy(runtime->dma_area, (cp + cnt * stride),
+ (len * stride - cnt * stride));
+ } else
+ memcpy(runtime->dma_area + oldptr * stride, cp, len * stride);
+
+ /* update the statas */
+ snd_pcm_stream_lock(pa->capture_pcm_substream);
+ pa->rcv_position += len;
+ if (pa->rcv_position >= runtime->buffer_size)
+ pa->rcv_position -= runtime->buffer_size;
+
+ pa->copied_position += (len);
+ if (pa->copied_position >= runtime->period_size) {
+ pa->copied_position -= runtime->period_size;
+ *period_elapsed = 1;
+ }
+ snd_pcm_stream_unlock(pa->capture_pcm_substream);
+}
+
+static void complete_handler_audio(struct urb *urb)
+{
+ struct poseidon_audio *pa = urb->context;
+ struct snd_pcm_substream *substream = pa->capture_pcm_substream;
+ int period_elapsed = 0;
+ int ret;
+
+ if (1 == pa->card_close || pa->capture_stream != STREAM_ON)
+ return;
+
+ if (urb->status != 0) {
+ /*if (urb->status == -ESHUTDOWN)*/
+ return;
+ }
+
+ if (substream) {
+ if (urb->actual_length) {
+ handle_audio_data(urb, &period_elapsed);
+ if (period_elapsed)
+ snd_pcm_period_elapsed(substream);
+ }
+ }
+
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret < 0)
+ log("audio urb failed (errcod = %i)", ret);
+ return;
+}
+
+static int fire_audio_urb(struct poseidon *p)
+{
+ int i, ret = 0;
+ struct poseidon_audio *pa = &p->audio;
+
+ alloc_bulk_urbs_generic(pa->urb_array, AUDIO_BUFS,
+ p->udev, AUDIO_EP,
+ AUDIO_BUF_SIZE, GFP_ATOMIC,
+ complete_handler_audio, pa);
+
+ for (i = 0; i < AUDIO_BUFS; i++) {
+ ret = usb_submit_urb(pa->urb_array[i], GFP_KERNEL);
+ if (ret)
+ log("urb err : %d", ret);
+ }
+ log();
+ return ret;
+}
+
+static int snd_pd_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct poseidon *p = snd_pcm_substream_chip(substream);
+ struct poseidon_audio *pa = &p->audio;
+
+ if (debug_mode)
+ log("cmd %d, audio stat : %d\n", cmd, pa->capture_stream);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_START:
+ if (pa->capture_stream == STREAM_ON)
+ return 0;
+
+ pa->rcv_position = pa->copied_position = 0;
+ pa->capture_stream = STREAM_ON;
+
+ if (in_hibernation(p))
+ return 0;
+ fire_audio_urb(p);
+ return 0;
+
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ pa->capture_stream = STREAM_SUSPEND;
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ pa->capture_stream = STREAM_OFF;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static snd_pcm_uframes_t
+snd_pd_capture_pointer(struct snd_pcm_substream *substream)
+{
+ struct poseidon *p = snd_pcm_substream_chip(substream);
+ struct poseidon_audio *pa = &p->audio;
+ return pa->rcv_position;
+}
+
+static struct page *snd_pcm_pd_get_page(struct snd_pcm_substream *subs,
+ unsigned long offset)
+{
+ void *pageptr = subs->runtime->dma_area + offset;
+ return vmalloc_to_page(pageptr);
+}
+
+static struct snd_pcm_ops pcm_capture_ops = {
+ .open = snd_pd_capture_open,
+ .close = snd_pd_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_pd_hw_capture_params,
+ .hw_free = snd_pd_hw_capture_free,
+ .prepare = snd_pd_prepare,
+ .trigger = snd_pd_capture_trigger,
+ .pointer = snd_pd_capture_pointer,
+ .page = snd_pcm_pd_get_page,
+};
+
+#ifdef CONFIG_PM
+int pm_alsa_suspend(struct poseidon *p)
+{
+ logpm(p);
+ audio_buf_free(p);
+ return 0;
+}
+
+int pm_alsa_resume(struct poseidon *p)
+{
+ logpm(p);
+ fire_audio_urb(p);
+ return 0;
+}
+#endif
+
+int poseidon_audio_init(struct poseidon *p)
+{
+ struct poseidon_audio *pa = &p->audio;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ int ret;
+
+ ret = snd_card_new(&p->interface->dev, -1, "Telegent",
+ THIS_MODULE, 0, &card);
+ if (ret != 0)
+ return ret;
+
+ ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm);
+ if (ret < 0) {
+ snd_card_free(card);
+ return ret;
+ }
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
+ pcm->info_flags = 0;
+ pcm->private_data = p;
+ strcpy(pcm->name, "poseidon audio capture");
+
+ strcpy(card->driver, "ALSA driver");
+ strcpy(card->shortname, "poseidon Audio");
+ strcpy(card->longname, "poseidon ALSA Audio");
+
+ if (snd_card_register(card)) {
+ snd_card_free(card);
+ return -ENOMEM;
+ }
+ pa->card = card;
+ return 0;
+}
+
+int poseidon_audio_free(struct poseidon *p)
+{
+ struct poseidon_audio *pa = &p->audio;
+
+ if (pa->card)
+ snd_card_free(pa->card);
+ return 0;
+}
diff --git a/drivers/media/usb/tlg2300/pd-common.h b/drivers/media/usb/tlg2300/pd-common.h
new file mode 100644
index 0000000..9e23ad3
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-common.h
@@ -0,0 +1,271 @@
+#ifndef PD_COMMON_H
+#define PD_COMMON_H
+
+#include <linux/fs.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/videodev2.h>
+#include <linux/semaphore.h>
+#include <linux/usb.h>
+#include <linux/poll.h>
+#include <media/videobuf-vmalloc.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#include "dvb_frontend.h"
+#include "dvbdev.h"
+#include "dvb_demux.h"
+#include "dmxdev.h"
+
+#define SBUF_NUM 8
+#define MAX_BUFFER_NUM 6
+#define PK_PER_URB 32
+#define ISO_PKT_SIZE 3072
+
+#define POSEIDON_STATE_NONE (0x0000)
+#define POSEIDON_STATE_ANALOG (0x0001)
+#define POSEIDON_STATE_FM (0x0002)
+#define POSEIDON_STATE_DVBT (0x0004)
+#define POSEIDON_STATE_DISCONNECT (0x0080)
+
+#define PM_SUSPEND_DELAY 3
+
+#define V4L_PAL_VBI_LINES 18
+#define V4L_NTSC_VBI_LINES 12
+#define V4L_PAL_VBI_FRAMESIZE (V4L_PAL_VBI_LINES * 1440 * 2)
+#define V4L_NTSC_VBI_FRAMESIZE (V4L_NTSC_VBI_LINES * 1440 * 2)
+
+#define TUNER_FREQ_MIN (45000000U)
+#define TUNER_FREQ_MAX (862000000U)
+
+struct vbi_data {
+ struct video_device v_dev;
+ struct video_data *video;
+ struct front_face *front;
+
+ unsigned int copied;
+ unsigned int vbi_size; /* the whole size of two fields */
+ int users;
+};
+
+/*
+ * This is the running context of the video, it is useful for
+ * resume()
+ */
+struct running_context {
+ u32 freq; /* VIDIOC_S_FREQUENCY */
+ int audio_idx; /* VIDIOC_S_TUNER */
+ v4l2_std_id tvnormid; /* VIDIOC_S_STD */
+ int sig_index; /* VIDIOC_S_INPUT */
+ struct v4l2_pix_format pix; /* VIDIOC_S_FMT */
+};
+
+struct video_data {
+ /* v4l2 video device */
+ struct video_device v_dev;
+ struct v4l2_ctrl_handler ctrl_handler;
+
+ /* the working context */
+ struct running_context context;
+
+ /* for data copy */
+ int field_count;
+
+ char *dst;
+ int lines_copied;
+ int prev_left;
+
+ int lines_per_field;
+ int lines_size;
+
+ /* for communication */
+ u8 endpoint_addr;
+ struct urb *urb_array[SBUF_NUM];
+ struct vbi_data *vbi;
+ struct poseidon *pd;
+ struct front_face *front;
+
+ int is_streaming;
+ int users;
+
+ /* for bubble handler */
+ struct work_struct bubble_work;
+};
+
+enum pcm_stream_state {
+ STREAM_OFF,
+ STREAM_ON,
+ STREAM_SUSPEND,
+};
+
+#define AUDIO_BUFS (3)
+#define CAPTURE_STREAM_EN 1
+struct poseidon_audio {
+ struct urb *urb_array[AUDIO_BUFS];
+ unsigned int copied_position;
+ struct snd_pcm_substream *capture_pcm_substream;
+
+ unsigned int rcv_position;
+ struct snd_card *card;
+ int card_close;
+
+ int users;
+ int pm_state;
+ enum pcm_stream_state capture_stream;
+};
+
+struct radio_data {
+ __u32 fm_freq;
+ unsigned int is_radio_streaming;
+ int pre_emphasis;
+ struct video_device fm_dev;
+ struct v4l2_ctrl_handler ctrl_handler;
+};
+
+#define DVB_SBUF_NUM 4
+#define DVB_URB_BUF_SIZE 0x2000
+struct pd_dvb_adapter {
+ struct dvb_adapter dvb_adap;
+ struct dvb_frontend dvb_fe;
+ struct dmxdev dmxdev;
+ struct dvb_demux demux;
+
+ atomic_t users;
+ atomic_t active_feed;
+
+ /* data transfer */
+ s32 is_streaming;
+ struct urb *urb_array[DVB_SBUF_NUM];
+ struct poseidon *pd_device;
+ u8 ep_addr;
+ u8 reserved[3];
+
+ /* data for power resume*/
+ struct dtv_frontend_properties fe_param;
+
+ /* for channel scanning */
+ int prev_freq;
+ int bandwidth;
+ unsigned long last_jiffies;
+};
+
+struct front_face {
+ /* use this field to distinguish VIDEO and VBI */
+ enum v4l2_buf_type type;
+
+ /* for host */
+ struct videobuf_queue q;
+
+ /* the bridge for host and device */
+ struct videobuf_buffer *curr_frame;
+
+ /* for device */
+ spinlock_t queue_lock;
+ struct list_head active;
+ struct poseidon *pd;
+};
+
+struct poseidon {
+ struct list_head device_list;
+
+ struct mutex lock;
+ struct kref kref;
+
+ /* for V4L2 */
+ struct v4l2_device v4l2_dev;
+
+ /* hardware info */
+ struct usb_device *udev;
+ struct usb_interface *interface;
+ int cur_transfer_mode;
+
+ struct video_data video_data; /* video */
+ struct vbi_data vbi_data; /* vbi */
+ struct poseidon_audio audio; /* audio (alsa) */
+ struct radio_data radio_data; /* FM */
+ struct pd_dvb_adapter dvb_data; /* DVB */
+
+ u32 state;
+ struct file *file_for_stream; /* the active stream*/
+
+#ifdef CONFIG_PM
+ int (*pm_suspend)(struct poseidon *);
+ int (*pm_resume)(struct poseidon *);
+ pm_message_t msg;
+
+ struct work_struct pm_work;
+ u8 portnum;
+#endif
+};
+
+struct poseidon_format {
+ char *name;
+ int fourcc; /* video4linux 2 */
+ int depth; /* bit/pixel */
+ int flags;
+};
+
+struct poseidon_tvnorm {
+ v4l2_std_id v4l2_id;
+ char name[12];
+ u32 tlg_tvnorm;
+};
+
+/* video */
+int pd_video_init(struct poseidon *);
+void pd_video_exit(struct poseidon *);
+int stop_all_video_stream(struct poseidon *);
+
+/* alsa audio */
+int poseidon_audio_init(struct poseidon *);
+int poseidon_audio_free(struct poseidon *);
+#ifdef CONFIG_PM
+int pm_alsa_suspend(struct poseidon *);
+int pm_alsa_resume(struct poseidon *);
+#endif
+
+/* dvb */
+int pd_dvb_usb_device_init(struct poseidon *);
+void pd_dvb_usb_device_exit(struct poseidon *);
+void pd_dvb_usb_device_cleanup(struct poseidon *);
+int pd_dvb_get_adapter_num(struct pd_dvb_adapter *);
+void dvb_stop_streaming(struct pd_dvb_adapter *);
+
+/* FM */
+int poseidon_fm_init(struct poseidon *);
+int poseidon_fm_exit(struct poseidon *);
+
+/* vendor command ops */
+int send_set_req(struct poseidon*, u8, s32, s32*);
+int send_get_req(struct poseidon*, u8, s32, void*, s32*, s32);
+s32 set_tuner_mode(struct poseidon*, unsigned char);
+
+/* bulk urb alloc/free */
+int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
+ struct usb_device *udev, u8 ep_addr,
+ int buf_size, gfp_t gfp_flags,
+ usb_complete_t complete_fn, void *context);
+void free_all_urb_generic(struct urb **urb_array, int num);
+
+/* misc */
+void poseidon_delete(struct kref *kref);
+extern int debug_mode;
+void set_debug_mode(struct video_device *vfd, int debug_mode);
+
+#ifdef CONFIG_PM
+#define in_hibernation(pd) (pd->msg.event == PM_EVENT_FREEZE)
+#else
+#define in_hibernation(pd) (0)
+#endif
+#define get_pm_count(p) (atomic_read(&(p)->interface->pm_usage_cnt))
+
+#define log(a, ...) printk(KERN_DEBUG "\t[ %s : %.3d ] "a"\n", \
+ __func__, __LINE__, ## __VA_ARGS__)
+
+/* for power management */
+#define logpm(pd) do {\
+ if (debug_mode & 0x10)\
+ log();\
+ } while (0)
+
+#endif
diff --git a/drivers/media/usb/tlg2300/pd-dvb.c b/drivers/media/usb/tlg2300/pd-dvb.c
new file mode 100644
index 0000000..ca4994a
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-dvb.c
@@ -0,0 +1,597 @@
+#include "pd-common.h"
+#include <linux/kernel.h>
+#include <linux/usb.h>
+#include <linux/time.h>
+#include <linux/dvb/dmx.h>
+#include <linux/delay.h>
+#include <linux/gfp.h>
+
+#include "vendorcmds.h"
+#include <linux/sched.h>
+#include <linux/atomic.h>
+
+static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb);
+
+static int dvb_bandwidth[][2] = {
+ { TLG_BW_8, 8000000 },
+ { TLG_BW_7, 7000000 },
+ { TLG_BW_6, 6000000 }
+};
+static int dvb_bandwidth_length = ARRAY_SIZE(dvb_bandwidth);
+
+static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb);
+static int poseidon_check_mode_dvbt(struct poseidon *pd)
+{
+ s32 ret = 0, cmd_status = 0;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/4);
+
+ ret = usb_set_interface(pd->udev, 0, BULK_ALTERNATE_IFACE);
+ if (ret != 0)
+ return ret;
+
+ ret = set_tuner_mode(pd, TLG_MODE_CAPS_DVB_T);
+ if (ret)
+ return ret;
+
+ /* signal source */
+ ret = send_set_req(pd, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &cmd_status);
+ if (ret|cmd_status)
+ return ret;
+
+ return 0;
+}
+
+/* acquire :
+ * 1 == open
+ * 0 == release
+ */
+static int poseidon_ts_bus_ctrl(struct dvb_frontend *fe, int acquire)
+{
+ struct poseidon *pd = fe->demodulator_priv;
+ struct pd_dvb_adapter *pd_dvb;
+ int ret = 0;
+
+ if (!pd)
+ return -ENODEV;
+
+ pd_dvb = container_of(fe, struct pd_dvb_adapter, dvb_fe);
+ if (acquire) {
+ mutex_lock(&pd->lock);
+ if (pd->state & POSEIDON_STATE_DISCONNECT) {
+ ret = -ENODEV;
+ goto open_out;
+ }
+
+ if (pd->state && !(pd->state & POSEIDON_STATE_DVBT)) {
+ ret = -EBUSY;
+ goto open_out;
+ }
+
+ usb_autopm_get_interface(pd->interface);
+ if (0 == pd->state) {
+ ret = poseidon_check_mode_dvbt(pd);
+ if (ret < 0) {
+ usb_autopm_put_interface(pd->interface);
+ goto open_out;
+ }
+ pd->state |= POSEIDON_STATE_DVBT;
+ pd_dvb->bandwidth = 0;
+ pd_dvb->prev_freq = 0;
+ }
+ atomic_inc(&pd_dvb->users);
+ kref_get(&pd->kref);
+open_out:
+ mutex_unlock(&pd->lock);
+ } else {
+ dvb_stop_streaming(pd_dvb);
+
+ if (atomic_dec_and_test(&pd_dvb->users)) {
+ mutex_lock(&pd->lock);
+ pd->state &= ~POSEIDON_STATE_DVBT;
+ mutex_unlock(&pd->lock);
+ }
+ kref_put(&pd->kref, poseidon_delete);
+ usb_autopm_put_interface(pd->interface);
+ }
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static void poseidon_fe_release(struct dvb_frontend *fe)
+{
+ struct poseidon *pd = fe->demodulator_priv;
+
+ pd->pm_suspend = NULL;
+ pd->pm_resume = NULL;
+}
+#else
+#define poseidon_fe_release NULL
+#endif
+
+static s32 poseidon_fe_sleep(struct dvb_frontend *fe)
+{
+ return 0;
+}
+
+/*
+ * return true if we can satisfy the conditions, else return false.
+ */
+static bool check_scan_ok(__u32 freq, int bandwidth,
+ struct pd_dvb_adapter *adapter)
+{
+ if (bandwidth < 0)
+ return false;
+
+ if (adapter->prev_freq == freq
+ && adapter->bandwidth == bandwidth) {
+ long nl = jiffies - adapter->last_jiffies;
+ unsigned int msec ;
+
+ msec = jiffies_to_msecs(abs(nl));
+ return msec > 15000 ? true : false;
+ }
+ return true;
+}
+
+/*
+ * Check if the firmware delays too long for an invalid frequency.
+ */
+static int fw_delay_overflow(struct pd_dvb_adapter *adapter)
+{
+ long nl = jiffies - adapter->last_jiffies;
+ unsigned int msec ;
+
+ msec = jiffies_to_msecs(abs(nl));
+ return msec > 800 ? true : false;
+}
+
+static int poseidon_set_fe(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+ s32 ret = 0, cmd_status = 0;
+ s32 i, bandwidth = -1;
+ struct poseidon *pd = fe->demodulator_priv;
+ struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+ if (in_hibernation(pd))
+ return -EBUSY;
+
+ mutex_lock(&pd->lock);
+ for (i = 0; i < dvb_bandwidth_length; i++)
+ if (fep->bandwidth_hz == dvb_bandwidth[i][1])
+ bandwidth = dvb_bandwidth[i][0];
+
+ if (check_scan_ok(fep->frequency, bandwidth, pd_dvb)) {
+ ret = send_set_req(pd, TUNE_FREQ_SELECT,
+ fep->frequency / 1000, &cmd_status);
+ if (ret | cmd_status) {
+ log("error line");
+ goto front_out;
+ }
+
+ ret = send_set_req(pd, DVBT_BANDW_SEL,
+ bandwidth, &cmd_status);
+ if (ret | cmd_status) {
+ log("error line");
+ goto front_out;
+ }
+
+ ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+ if (ret | cmd_status) {
+ log("error line");
+ goto front_out;
+ }
+
+ /* save the context for future */
+ memcpy(&pd_dvb->fe_param, fep, sizeof(*fep));
+ pd_dvb->bandwidth = bandwidth;
+ pd_dvb->prev_freq = fep->frequency;
+ pd_dvb->last_jiffies = jiffies;
+ }
+front_out:
+ mutex_unlock(&pd->lock);
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int pm_dvb_suspend(struct poseidon *pd)
+{
+ struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+ dvb_stop_streaming(pd_dvb);
+ dvb_urb_cleanup(pd_dvb);
+ msleep(500);
+ return 0;
+}
+
+static int pm_dvb_resume(struct poseidon *pd)
+{
+ struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+ poseidon_check_mode_dvbt(pd);
+ msleep(300);
+ poseidon_set_fe(&pd_dvb->dvb_fe);
+
+ dvb_start_streaming(pd_dvb);
+ return 0;
+}
+#endif
+
+static s32 poseidon_fe_init(struct dvb_frontend *fe)
+{
+ struct poseidon *pd = fe->demodulator_priv;
+ struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+#ifdef CONFIG_PM
+ pd->pm_suspend = pm_dvb_suspend;
+ pd->pm_resume = pm_dvb_resume;
+#endif
+ memset(&pd_dvb->fe_param, 0,
+ sizeof(struct dtv_frontend_properties));
+ return 0;
+}
+
+static int poseidon_get_fe(struct dvb_frontend *fe)
+{
+ struct dtv_frontend_properties *fep = &fe->dtv_property_cache;
+ struct poseidon *pd = fe->demodulator_priv;
+ struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+ memcpy(fep, &pd_dvb->fe_param, sizeof(*fep));
+ return 0;
+}
+
+static int poseidon_fe_get_tune_settings(struct dvb_frontend *fe,
+ struct dvb_frontend_tune_settings *tune)
+{
+ tune->min_delay_ms = 1000;
+ return 0;
+}
+
+static int poseidon_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+{
+ struct poseidon *pd = fe->demodulator_priv;
+ s32 ret = -1, cmd_status;
+ struct tuner_dtv_sig_stat_s status = {};
+
+ if (in_hibernation(pd))
+ return -EBUSY;
+ mutex_lock(&pd->lock);
+
+ ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T,
+ &status, &cmd_status, sizeof(status));
+ if (ret | cmd_status) {
+ log("get tuner status error");
+ goto out;
+ }
+
+ if (debug_mode)
+ log("P : %d, L %d, LB :%d", status.sig_present,
+ status.sig_locked, status.sig_lock_busy);
+
+ if (status.sig_lock_busy) {
+ goto out;
+ } else if (status.sig_present || status.sig_locked) {
+ *stat |= FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER
+ | FE_HAS_SYNC | FE_HAS_VITERBI;
+ } else {
+ if (fw_delay_overflow(&pd->dvb_data))
+ *stat |= FE_TIMEDOUT;
+ }
+out:
+ mutex_unlock(&pd->lock);
+ return ret;
+}
+
+static int poseidon_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+ struct poseidon *pd = fe->demodulator_priv;
+ struct tuner_ber_rate_s tlg_ber = {};
+ s32 ret = -1, cmd_status;
+
+ mutex_lock(&pd->lock);
+ ret = send_get_req(pd, TUNER_BER_RATE, 0,
+ &tlg_ber, &cmd_status, sizeof(tlg_ber));
+ if (ret | cmd_status)
+ goto out;
+ *ber = tlg_ber.ber_rate;
+out:
+ mutex_unlock(&pd->lock);
+ return ret;
+}
+
+static s32 poseidon_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+{
+ struct poseidon *pd = fe->demodulator_priv;
+ struct tuner_dtv_sig_stat_s status = {};
+ s32 ret = 0, cmd_status;
+
+ mutex_lock(&pd->lock);
+ ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_DVB_T,
+ &status, &cmd_status, sizeof(status));
+ if (ret | cmd_status)
+ goto out;
+ if ((status.sig_present || status.sig_locked) && !status.sig_strength)
+ *strength = 0xFFFF;
+ else
+ *strength = status.sig_strength;
+out:
+ mutex_unlock(&pd->lock);
+ return ret;
+}
+
+static int poseidon_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ return 0;
+}
+
+static int poseidon_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+{
+ *unc = 0;
+ return 0;
+}
+
+static struct dvb_frontend_ops poseidon_frontend_ops = {
+ .delsys = { SYS_DVBT },
+ .info = {
+ .name = "Poseidon DVB-T",
+ .frequency_min = 174000000,
+ .frequency_max = 862000000,
+ .frequency_stepsize = 62500,/* FIXME */
+ .caps = FE_CAN_INVERSION_AUTO |
+ 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_RECOVER |
+ FE_CAN_HIERARCHY_AUTO,
+ },
+
+ .release = poseidon_fe_release,
+
+ .init = poseidon_fe_init,
+ .sleep = poseidon_fe_sleep,
+
+ .set_frontend = poseidon_set_fe,
+ .get_frontend = poseidon_get_fe,
+ .get_tune_settings = poseidon_fe_get_tune_settings,
+
+ .read_status = poseidon_read_status,
+ .read_ber = poseidon_read_ber,
+ .read_signal_strength = poseidon_read_signal_strength,
+ .read_snr = poseidon_read_snr,
+ .read_ucblocks = poseidon_read_unc_blocks,
+
+ .ts_bus_ctrl = poseidon_ts_bus_ctrl,
+};
+
+static void dvb_urb_irq(struct urb *urb)
+{
+ struct pd_dvb_adapter *pd_dvb = urb->context;
+ int len = urb->transfer_buffer_length;
+ struct dvb_demux *demux = &pd_dvb->demux;
+ s32 ret;
+
+ if (!pd_dvb->is_streaming || urb->status) {
+ if (urb->status == -EPROTO)
+ goto resend;
+ return;
+ }
+
+ if (urb->actual_length == len)
+ dvb_dmx_swfilter(demux, urb->transfer_buffer, len);
+ else if (urb->actual_length == len - 4) {
+ int offset;
+ u8 *buf = urb->transfer_buffer;
+
+ /*
+ * The packet size is 512,
+ * last packet contains 456 bytes tsp data
+ */
+ for (offset = 456; offset < len; offset += 512) {
+ if (!strncmp(buf + offset, "DVHS", 4)) {
+ dvb_dmx_swfilter(demux, buf, offset);
+ if (len > offset + 52 + 4) {
+ /*16 bytes trailer + 36 bytes padding */
+ buf += offset + 52;
+ len -= offset + 52 + 4;
+ dvb_dmx_swfilter(demux, buf, len);
+ }
+ break;
+ }
+ }
+ }
+
+resend:
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ log(" usb_submit_urb failed: error %d", ret);
+}
+
+static int dvb_urb_init(struct pd_dvb_adapter *pd_dvb)
+{
+ if (pd_dvb->urb_array[0])
+ return 0;
+
+ alloc_bulk_urbs_generic(pd_dvb->urb_array, DVB_SBUF_NUM,
+ pd_dvb->pd_device->udev, pd_dvb->ep_addr,
+ DVB_URB_BUF_SIZE, GFP_KERNEL,
+ dvb_urb_irq, pd_dvb);
+ return 0;
+}
+
+static void dvb_urb_cleanup(struct pd_dvb_adapter *pd_dvb)
+{
+ free_all_urb_generic(pd_dvb->urb_array, DVB_SBUF_NUM);
+}
+
+static s32 dvb_start_streaming(struct pd_dvb_adapter *pd_dvb)
+{
+ struct poseidon *pd = pd_dvb->pd_device;
+ int ret = 0;
+
+ if (pd->state & POSEIDON_STATE_DISCONNECT)
+ return -ENODEV;
+
+ mutex_lock(&pd->lock);
+ if (!pd_dvb->is_streaming) {
+ s32 i, cmd_status = 0;
+ /*
+ * Once upon a time, there was a difficult bug lying here.
+ * ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+ */
+
+ ret = send_set_req(pd, PLAY_SERVICE, 1, &cmd_status);
+ if (ret | cmd_status)
+ goto out;
+
+ ret = dvb_urb_init(pd_dvb);
+ if (ret < 0)
+ goto out;
+
+ pd_dvb->is_streaming = 1;
+ for (i = 0; i < DVB_SBUF_NUM; i++) {
+ ret = usb_submit_urb(pd_dvb->urb_array[i],
+ GFP_KERNEL);
+ if (ret) {
+ log(" submit urb error %d", ret);
+ goto out;
+ }
+ }
+ }
+out:
+ mutex_unlock(&pd->lock);
+ return ret;
+}
+
+void dvb_stop_streaming(struct pd_dvb_adapter *pd_dvb)
+{
+ struct poseidon *pd = pd_dvb->pd_device;
+
+ mutex_lock(&pd->lock);
+ if (pd_dvb->is_streaming) {
+ s32 i, ret, cmd_status = 0;
+
+ pd_dvb->is_streaming = 0;
+
+ for (i = 0; i < DVB_SBUF_NUM; i++)
+ if (pd_dvb->urb_array[i])
+ usb_kill_urb(pd_dvb->urb_array[i]);
+
+ ret = send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
+ &cmd_status);
+ if (ret | cmd_status)
+ log("error");
+ }
+ mutex_unlock(&pd->lock);
+}
+
+static int pd_start_feed(struct dvb_demux_feed *feed)
+{
+ struct pd_dvb_adapter *pd_dvb = feed->demux->priv;
+ int ret = 0;
+
+ if (!pd_dvb)
+ return -1;
+ if (atomic_inc_return(&pd_dvb->active_feed) == 1)
+ ret = dvb_start_streaming(pd_dvb);
+ return ret;
+}
+
+static int pd_stop_feed(struct dvb_demux_feed *feed)
+{
+ struct pd_dvb_adapter *pd_dvb = feed->demux->priv;
+
+ if (!pd_dvb)
+ return -1;
+ if (atomic_dec_and_test(&pd_dvb->active_feed))
+ dvb_stop_streaming(pd_dvb);
+ return 0;
+}
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+int pd_dvb_usb_device_init(struct poseidon *pd)
+{
+ struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+ struct dvb_demux *dvbdemux;
+ int ret = 0;
+
+ pd_dvb->ep_addr = 0x82;
+ atomic_set(&pd_dvb->users, 0);
+ atomic_set(&pd_dvb->active_feed, 0);
+ pd_dvb->pd_device = pd;
+
+ ret = dvb_register_adapter(&pd_dvb->dvb_adap,
+ "Poseidon dvbt adapter",
+ THIS_MODULE,
+ NULL /* for hibernation correctly*/,
+ adapter_nr);
+ if (ret < 0)
+ goto error1;
+
+ /* register frontend */
+ pd_dvb->dvb_fe.demodulator_priv = pd;
+ memcpy(&pd_dvb->dvb_fe.ops, &poseidon_frontend_ops,
+ sizeof(struct dvb_frontend_ops));
+ ret = dvb_register_frontend(&pd_dvb->dvb_adap, &pd_dvb->dvb_fe);
+ if (ret < 0)
+ goto error2;
+
+ /* register demux device */
+ dvbdemux = &pd_dvb->demux;
+ dvbdemux->dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+ dvbdemux->priv = pd_dvb;
+ dvbdemux->feednum = dvbdemux->filternum = 64;
+ dvbdemux->start_feed = pd_start_feed;
+ dvbdemux->stop_feed = pd_stop_feed;
+ dvbdemux->write_to_decoder = NULL;
+
+ ret = dvb_dmx_init(dvbdemux);
+ if (ret < 0)
+ goto error3;
+
+ pd_dvb->dmxdev.filternum = pd_dvb->demux.filternum;
+ pd_dvb->dmxdev.demux = &pd_dvb->demux.dmx;
+ pd_dvb->dmxdev.capabilities = 0;
+
+ ret = dvb_dmxdev_init(&pd_dvb->dmxdev, &pd_dvb->dvb_adap);
+ if (ret < 0)
+ goto error3;
+ return 0;
+
+error3:
+ dvb_unregister_frontend(&pd_dvb->dvb_fe);
+error2:
+ dvb_unregister_adapter(&pd_dvb->dvb_adap);
+error1:
+ return ret;
+}
+
+void pd_dvb_usb_device_exit(struct poseidon *pd)
+{
+ struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+ while (atomic_read(&pd_dvb->users) != 0
+ || atomic_read(&pd_dvb->active_feed) != 0) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+ }
+ dvb_dmxdev_release(&pd_dvb->dmxdev);
+ dvb_unregister_frontend(&pd_dvb->dvb_fe);
+ dvb_unregister_adapter(&pd_dvb->dvb_adap);
+ pd_dvb_usb_device_cleanup(pd);
+}
+
+void pd_dvb_usb_device_cleanup(struct poseidon *pd)
+{
+ struct pd_dvb_adapter *pd_dvb = &pd->dvb_data;
+
+ dvb_urb_cleanup(pd_dvb);
+}
+
+int pd_dvb_get_adapter_num(struct pd_dvb_adapter *pd_dvb)
+{
+ return pd_dvb->dvb_adap.num;
+}
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c
new file mode 100644
index 0000000..b31f479
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-main.c
@@ -0,0 +1,553 @@
+/*
+ * device driver for Telegent tlg2300 based TV cards
+ *
+ * Author :
+ * Kang Yong <kangyong@telegent.com>
+ * Zhang Xiaobing <xbzhang@telegent.com>
+ * Huang Shijie <zyziii@telegent.com> or <shijie8@gmail.com>
+ *
+ * (c) 2009 Telegent Systems
+ * (c) 2010 Telegent 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
+ * 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 <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kref.h>
+#include <linux/suspend.h>
+#include <linux/usb/quirks.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/firmware.h>
+
+#include "vendorcmds.h"
+#include "pd-common.h"
+
+#define VENDOR_ID 0x1B24
+#define PRODUCT_ID 0x4001
+static struct usb_device_id id_table[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(VENDOR_ID, PRODUCT_ID, 255, 1, 1) },
+ { },
+};
+MODULE_DEVICE_TABLE(usb, id_table);
+
+int debug_mode;
+module_param(debug_mode, int, 0644);
+MODULE_PARM_DESC(debug_mode, "0 = disable, 1 = enable, 2 = verbose");
+
+#define TLG2300_FIRMWARE "tlg2300_firmware.bin"
+static const char *firmware_name = TLG2300_FIRMWARE;
+static LIST_HEAD(pd_device_list);
+
+/*
+ * send set request to USB firmware.
+ */
+s32 send_set_req(struct poseidon *pd, u8 cmdid, s32 param, s32 *cmd_status)
+{
+ s32 ret;
+ s8 data[32] = {};
+ u16 lower_16, upper_16;
+
+ if (pd->state & POSEIDON_STATE_DISCONNECT)
+ return -ENODEV;
+
+ mdelay(30);
+
+ if (param == 0) {
+ upper_16 = lower_16 = 0;
+ } else {
+ /* send 32 bit param as two 16 bit param,little endian */
+ lower_16 = (unsigned short)(param & 0xffff);
+ upper_16 = (unsigned short)((param >> 16) & 0xffff);
+ }
+ ret = usb_control_msg(pd->udev,
+ usb_rcvctrlpipe(pd->udev, 0),
+ REQ_SET_CMD | cmdid,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ lower_16,
+ upper_16,
+ &data,
+ sizeof(*cmd_status),
+ USB_CTRL_GET_TIMEOUT);
+
+ if (!ret) {
+ return -ENXIO;
+ } else {
+ /* 1st 4 bytes into cmd_status */
+ memcpy((char *)cmd_status, &(data[0]), sizeof(*cmd_status));
+ }
+ return 0;
+}
+
+/*
+ * send get request to Poseidon firmware.
+ */
+s32 send_get_req(struct poseidon *pd, u8 cmdid, s32 param,
+ void *buf, s32 *cmd_status, s32 datalen)
+{
+ s32 ret;
+ s8 data[128] = {};
+ u16 lower_16, upper_16;
+
+ if (pd->state & POSEIDON_STATE_DISCONNECT)
+ return -ENODEV;
+
+ mdelay(30);
+ if (param == 0) {
+ upper_16 = lower_16 = 0;
+ } else {
+ /*send 32 bit param as two 16 bit param, little endian */
+ lower_16 = (unsigned short)(param & 0xffff);
+ upper_16 = (unsigned short)((param >> 16) & 0xffff);
+ }
+ ret = usb_control_msg(pd->udev,
+ usb_rcvctrlpipe(pd->udev, 0),
+ REQ_GET_CMD | cmdid,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ lower_16,
+ upper_16,
+ &data,
+ (datalen + sizeof(*cmd_status)),
+ USB_CTRL_GET_TIMEOUT);
+
+ if (ret < 0) {
+ return -ENXIO;
+ } else {
+ /* 1st 4 bytes into cmd_status, remaining data into cmd_data */
+ memcpy((char *)cmd_status, &data[0], sizeof(*cmd_status));
+ memcpy((char *)buf, &data[sizeof(*cmd_status)], datalen);
+ }
+ return 0;
+}
+
+static int pm_notifier_block(struct notifier_block *nb,
+ unsigned long event, void *dummy)
+{
+ struct poseidon *pd = NULL;
+ struct list_head *node, *next;
+
+ switch (event) {
+ case PM_POST_HIBERNATION:
+ list_for_each_safe(node, next, &pd_device_list) {
+ struct usb_device *udev;
+ struct usb_interface *iface;
+ int rc = 0;
+
+ pd = container_of(node, struct poseidon, device_list);
+ udev = pd->udev;
+ iface = pd->interface;
+
+ /* It will cause the system to reload the firmware */
+ rc = usb_lock_device_for_reset(udev, iface);
+ if (rc >= 0) {
+ usb_reset_device(udev);
+ usb_unlock_device(udev);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ log("event :%ld\n", event);
+ return 0;
+}
+
+static struct notifier_block pm_notifer = {
+ .notifier_call = pm_notifier_block,
+};
+
+int set_tuner_mode(struct poseidon *pd, unsigned char mode)
+{
+ s32 ret, cmd_status;
+
+ if (pd->state & POSEIDON_STATE_DISCONNECT)
+ return -ENODEV;
+
+ ret = send_set_req(pd, TUNE_MODE_SELECT, mode, &cmd_status);
+ if (ret || cmd_status)
+ return -ENXIO;
+ return 0;
+}
+
+void poseidon_delete(struct kref *kref)
+{
+ struct poseidon *pd = container_of(kref, struct poseidon, kref);
+
+ if (!pd)
+ return;
+ list_del_init(&pd->device_list);
+
+ pd_dvb_usb_device_cleanup(pd);
+ /* clean_audio_data(&pd->audio_data);*/
+
+ if (pd->udev) {
+ usb_put_dev(pd->udev);
+ pd->udev = NULL;
+ }
+ if (pd->interface) {
+ usb_put_intf(pd->interface);
+ pd->interface = NULL;
+ }
+ kfree(pd);
+ log();
+}
+
+static int firmware_download(struct usb_device *udev)
+{
+ int ret = 0, actual_length;
+ const struct firmware *fw = NULL;
+ void *fwbuf = NULL;
+ size_t fwlength = 0, offset;
+ size_t max_packet_size;
+
+ ret = request_firmware(&fw, firmware_name, &udev->dev);
+ if (ret) {
+ log("download err : %d", ret);
+ return ret;
+ }
+
+ fwlength = fw->size;
+
+ fwbuf = kmemdup(fw->data, fwlength, GFP_KERNEL);
+ if (!fwbuf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ max_packet_size = le16_to_cpu(udev->ep_out[0x1]->desc.wMaxPacketSize);
+ log("\t\t download size : %d", (int)max_packet_size);
+
+ for (offset = 0; offset < fwlength; offset += max_packet_size) {
+ actual_length = 0;
+ ret = usb_bulk_msg(udev,
+ usb_sndbulkpipe(udev, 0x01), /* ep 1 */
+ fwbuf + offset,
+ min(max_packet_size, fwlength - offset),
+ &actual_length,
+ HZ * 10);
+ if (ret)
+ break;
+ }
+ kfree(fwbuf);
+out:
+ release_firmware(fw);
+ return ret;
+}
+
+static inline struct poseidon *get_pd(struct usb_interface *intf)
+{
+ return usb_get_intfdata(intf);
+}
+
+#ifdef CONFIG_PM
+/* one-to-one map : poseidon{} <----> usb_device{}'s port */
+static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
+{
+ pd->portnum = udev->portnum;
+}
+
+static inline int get_autopm_ref(struct poseidon *pd)
+{
+ return pd->video_data.users + pd->vbi_data.users + pd->audio.users
+ + atomic_read(&pd->dvb_data.users) +
+ !list_empty(&pd->radio_data.fm_dev.fh_list);
+}
+
+/* fixup something for poseidon */
+static inline struct poseidon *fixup(struct poseidon *pd)
+{
+ int count;
+
+ /* old udev and interface have gone, so put back reference . */
+ count = get_autopm_ref(pd);
+ log("count : %d, ref count : %d", count, get_pm_count(pd));
+ while (count--)
+ usb_autopm_put_interface(pd->interface);
+ /*usb_autopm_set_interface(pd->interface); */
+
+ usb_put_dev(pd->udev);
+ usb_put_intf(pd->interface);
+ log("event : %d\n", pd->msg.event);
+ return pd;
+}
+
+static struct poseidon *find_old_poseidon(struct usb_device *udev)
+{
+ struct poseidon *pd;
+
+ list_for_each_entry(pd, &pd_device_list, device_list) {
+ if (pd->portnum == udev->portnum && in_hibernation(pd))
+ return fixup(pd);
+ }
+ return NULL;
+}
+
+/* Is the card working now ? */
+static inline int is_working(struct poseidon *pd)
+{
+ return get_pm_count(pd) > 0;
+}
+
+static int poseidon_suspend(struct usb_interface *intf, pm_message_t msg)
+{
+ struct poseidon *pd = get_pd(intf);
+
+ if (!pd)
+ return 0;
+ if (!is_working(pd)) {
+ if (get_pm_count(pd) <= 0 && !in_hibernation(pd)) {
+ pd->msg.event = PM_EVENT_AUTO_SUSPEND;
+ pd->pm_resume = NULL; /* a good guard */
+ printk(KERN_DEBUG "TLG2300 auto suspend\n");
+ }
+ return 0;
+ }
+ pd->msg = msg; /* save it here */
+ logpm(pd);
+ return pd->pm_suspend ? pd->pm_suspend(pd) : 0;
+}
+
+static int poseidon_resume(struct usb_interface *intf)
+{
+ struct poseidon *pd = get_pd(intf);
+
+ if (!pd)
+ return 0;
+ printk(KERN_DEBUG "TLG2300 resume\n");
+
+ if (!is_working(pd)) {
+ if (PM_EVENT_AUTO_SUSPEND == pd->msg.event)
+ pd->msg = PMSG_ON;
+ return 0;
+ }
+ if (in_hibernation(pd)) {
+ logpm(pd);
+ return 0;
+ }
+ logpm(pd);
+ return pd->pm_resume ? pd->pm_resume(pd) : 0;
+}
+
+static void hibernation_resume(struct work_struct *w)
+{
+ struct poseidon *pd = container_of(w, struct poseidon, pm_work);
+ int count;
+
+ pd->msg.event = 0; /* clear it here */
+ pd->state &= ~POSEIDON_STATE_DISCONNECT;
+
+ /* set the new interface's reference */
+ count = get_autopm_ref(pd);
+ while (count--)
+ usb_autopm_get_interface(pd->interface);
+
+ /* resume the context */
+ logpm(pd);
+ if (pd->pm_resume)
+ pd->pm_resume(pd);
+}
+#else /* CONFIG_PM is not enabled: */
+static inline struct poseidon *find_old_poseidon(struct usb_device *udev)
+{
+ return NULL;
+}
+
+static inline void set_map_flags(struct poseidon *pd, struct usb_device *udev)
+{
+}
+#endif
+
+static int check_firmware(struct usb_device *udev)
+{
+ void *buf;
+ int ret;
+ struct cmd_firmware_vers_s *cmd_firm;
+
+ buf = kzalloc(sizeof(*cmd_firm) + sizeof(u32), GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+ ret = usb_control_msg(udev,
+ usb_rcvctrlpipe(udev, 0),
+ REQ_GET_CMD | GET_FW_ID,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0,
+ 0,
+ buf,
+ sizeof(*cmd_firm) + sizeof(u32),
+ USB_CTRL_GET_TIMEOUT);
+ kfree(buf);
+
+ if (ret < 0)
+ return firmware_download(udev);
+ return 0;
+}
+
+static int poseidon_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(interface);
+ struct poseidon *pd = NULL;
+ int ret = 0;
+ int new_one = 0;
+
+ /* download firmware */
+ ret = check_firmware(udev);
+ if (ret)
+ return ret;
+
+ /* Do I recovery from the hibernate ? */
+ pd = find_old_poseidon(udev);
+ if (!pd) {
+ pd = kzalloc(sizeof(*pd), GFP_KERNEL);
+ if (!pd)
+ return -ENOMEM;
+ kref_init(&pd->kref);
+ set_map_flags(pd, udev);
+ new_one = 1;
+ }
+
+ pd->udev = usb_get_dev(udev);
+ pd->interface = usb_get_intf(interface);
+ usb_set_intfdata(interface, pd);
+
+ if (new_one) {
+ logpm(pd);
+ mutex_init(&pd->lock);
+
+ /* register v4l2 device */
+ ret = v4l2_device_register(&interface->dev, &pd->v4l2_dev);
+ if (ret)
+ goto err_v4l2;
+
+ /* register devices in directory /dev */
+ ret = pd_video_init(pd);
+ if (ret)
+ goto err_video;
+ ret = poseidon_audio_init(pd);
+ if (ret)
+ goto err_audio;
+ ret = poseidon_fm_init(pd);
+ if (ret)
+ goto err_fm;
+ ret = pd_dvb_usb_device_init(pd);
+ if (ret)
+ goto err_dvb;
+
+ INIT_LIST_HEAD(&pd->device_list);
+ list_add_tail(&pd->device_list, &pd_device_list);
+ }
+
+ device_init_wakeup(&udev->dev, 1);
+#ifdef CONFIG_PM
+ pm_runtime_set_autosuspend_delay(&pd->udev->dev,
+ 1000 * PM_SUSPEND_DELAY);
+ usb_enable_autosuspend(pd->udev);
+
+ if (in_hibernation(pd)) {
+ INIT_WORK(&pd->pm_work, hibernation_resume);
+ schedule_work(&pd->pm_work);
+ }
+#endif
+ return 0;
+err_dvb:
+ poseidon_fm_exit(pd);
+err_fm:
+ poseidon_audio_free(pd);
+err_audio:
+ pd_video_exit(pd);
+err_video:
+ v4l2_device_unregister(&pd->v4l2_dev);
+err_v4l2:
+ usb_put_intf(pd->interface);
+ usb_put_dev(pd->udev);
+ kfree(pd);
+ return ret;
+}
+
+static void poseidon_disconnect(struct usb_interface *interface)
+{
+ struct poseidon *pd = get_pd(interface);
+
+ if (!pd)
+ return;
+ logpm(pd);
+ if (in_hibernation(pd))
+ return;
+
+ mutex_lock(&pd->lock);
+ pd->state |= POSEIDON_STATE_DISCONNECT;
+ mutex_unlock(&pd->lock);
+
+ /* stop urb transferring */
+ stop_all_video_stream(pd);
+ dvb_stop_streaming(&pd->dvb_data);
+
+ /*unregister v4l2 device */
+ v4l2_device_unregister(&pd->v4l2_dev);
+
+ pd_dvb_usb_device_exit(pd);
+ poseidon_fm_exit(pd);
+
+ poseidon_audio_free(pd);
+ pd_video_exit(pd);
+
+ usb_set_intfdata(interface, NULL);
+ kref_put(&pd->kref, poseidon_delete);
+}
+
+static struct usb_driver poseidon_driver = {
+ .name = "poseidon",
+ .probe = poseidon_probe,
+ .disconnect = poseidon_disconnect,
+ .id_table = id_table,
+#ifdef CONFIG_PM
+ .suspend = poseidon_suspend,
+ .resume = poseidon_resume,
+#endif
+ .supports_autosuspend = 1,
+};
+
+static int __init poseidon_init(void)
+{
+ int ret;
+
+ ret = usb_register(&poseidon_driver);
+ if (ret)
+ return ret;
+ register_pm_notifier(&pm_notifer);
+ return ret;
+}
+
+static void __exit poseidon_exit(void)
+{
+ log();
+ unregister_pm_notifier(&pm_notifer);
+ usb_deregister(&poseidon_driver);
+}
+
+module_init(poseidon_init);
+module_exit(poseidon_exit);
+
+MODULE_AUTHOR("Telegent Systems");
+MODULE_DESCRIPTION("For tlg2300-based USB device");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.2");
+MODULE_FIRMWARE(TLG2300_FIRMWARE);
diff --git a/drivers/media/usb/tlg2300/pd-radio.c b/drivers/media/usb/tlg2300/pd-radio.c
new file mode 100644
index 0000000..b391194
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-radio.c
@@ -0,0 +1,339 @@
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/bitmap.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+#include <media/v4l2-dev.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <linux/sched.h>
+
+#include "pd-common.h"
+#include "vendorcmds.h"
+
+static int set_frequency(struct poseidon *p, __u32 frequency);
+static int poseidon_fm_close(struct file *filp);
+static int poseidon_fm_open(struct file *filp);
+
+#define TUNER_FREQ_MIN_FM 76000000U
+#define TUNER_FREQ_MAX_FM 108000000U
+
+#define MAX_PREEMPHASIS (V4L2_PREEMPHASIS_75_uS + 1)
+static int preemphasis[MAX_PREEMPHASIS] = {
+ TLG_TUNE_ASTD_NONE, /* V4L2_PREEMPHASIS_DISABLED */
+ TLG_TUNE_ASTD_FM_EUR, /* V4L2_PREEMPHASIS_50_uS */
+ TLG_TUNE_ASTD_FM_US, /* V4L2_PREEMPHASIS_75_uS */
+};
+
+static int poseidon_check_mode_radio(struct poseidon *p)
+{
+ int ret;
+ u32 status;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/2);
+ ret = usb_set_interface(p->udev, 0, BULK_ALTERNATE_IFACE);
+ if (ret < 0)
+ goto out;
+
+ ret = set_tuner_mode(p, TLG_MODE_FM_RADIO);
+ if (ret != 0)
+ goto out;
+
+ ret = send_set_req(p, SGNL_SRC_SEL, TLG_SIG_SRC_ANTENNA, &status);
+ ret = send_set_req(p, TUNER_AUD_ANA_STD,
+ p->radio_data.pre_emphasis, &status);
+ ret |= send_set_req(p, TUNER_AUD_MODE,
+ TLG_TUNE_TVAUDIO_MODE_STEREO, &status);
+ ret |= send_set_req(p, AUDIO_SAMPLE_RATE_SEL,
+ ATV_AUDIO_RATE_48K, &status);
+ ret |= send_set_req(p, TUNE_FREQ_SELECT, TUNER_FREQ_MIN_FM, &status);
+out:
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int pm_fm_suspend(struct poseidon *p)
+{
+ logpm(p);
+ pm_alsa_suspend(p);
+ usb_set_interface(p->udev, 0, 0);
+ msleep(300);
+ return 0;
+}
+
+static int pm_fm_resume(struct poseidon *p)
+{
+ logpm(p);
+ poseidon_check_mode_radio(p);
+ set_frequency(p, p->radio_data.fm_freq);
+ pm_alsa_resume(p);
+ return 0;
+}
+#endif
+
+static int poseidon_fm_open(struct file *filp)
+{
+ struct poseidon *p = video_drvdata(filp);
+ int ret = 0;
+
+ mutex_lock(&p->lock);
+ if (p->state & POSEIDON_STATE_DISCONNECT) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ if (p->state && !(p->state & POSEIDON_STATE_FM)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ ret = v4l2_fh_open(filp);
+ if (ret)
+ goto out;
+
+ usb_autopm_get_interface(p->interface);
+ if (0 == p->state) {
+ struct video_device *vfd = &p->radio_data.fm_dev;
+
+ /* default pre-emphasis */
+ if (p->radio_data.pre_emphasis == 0)
+ p->radio_data.pre_emphasis = TLG_TUNE_ASTD_FM_EUR;
+ set_debug_mode(vfd, debug_mode);
+
+ ret = poseidon_check_mode_radio(p);
+ if (ret < 0) {
+ usb_autopm_put_interface(p->interface);
+ goto out;
+ }
+ p->state |= POSEIDON_STATE_FM;
+ }
+ kref_get(&p->kref);
+out:
+ mutex_unlock(&p->lock);
+ return ret;
+}
+
+static int poseidon_fm_close(struct file *filp)
+{
+ struct poseidon *p = video_drvdata(filp);
+ struct radio_data *fm = &p->radio_data;
+ uint32_t status;
+
+ mutex_lock(&p->lock);
+ if (v4l2_fh_is_singular_file(filp))
+ p->state &= ~POSEIDON_STATE_FM;
+
+ if (fm->is_radio_streaming && filp == p->file_for_stream) {
+ fm->is_radio_streaming = 0;
+ send_set_req(p, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP, &status);
+ }
+ usb_autopm_put_interface(p->interface);
+ mutex_unlock(&p->lock);
+
+ kref_put(&p->kref, poseidon_delete);
+ return v4l2_fh_release(filp);
+}
+
+static int vidioc_querycap(struct file *file, void *priv,
+ struct v4l2_capability *v)
+{
+ struct poseidon *p = video_drvdata(file);
+
+ strlcpy(v->driver, "tele-radio", sizeof(v->driver));
+ strlcpy(v->card, "Telegent Poseidon", sizeof(v->card));
+ usb_make_path(p->udev, v->bus_info, sizeof(v->bus_info));
+ v->device_caps = V4L2_CAP_TUNER | V4L2_CAP_RADIO;
+ /* Report all capabilities of the USB device */
+ v->capabilities = v->device_caps | V4L2_CAP_DEVICE_CAPS |
+ V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VBI_CAPTURE |
+ V4L2_CAP_AUDIO | V4L2_CAP_STREAMING |
+ V4L2_CAP_READWRITE;
+ return 0;
+}
+
+static const struct v4l2_file_operations poseidon_fm_fops = {
+ .owner = THIS_MODULE,
+ .open = poseidon_fm_open,
+ .release = poseidon_fm_close,
+ .poll = v4l2_ctrl_poll,
+ .unlocked_ioctl = video_ioctl2,
+};
+
+static int tlg_fm_vidioc_g_tuner(struct file *file, void *priv,
+ struct v4l2_tuner *vt)
+{
+ struct poseidon *p = video_drvdata(file);
+ struct tuner_fm_sig_stat_s fm_stat = {};
+ int ret, status, count = 5;
+
+ if (vt->index != 0)
+ return -EINVAL;
+
+ vt->type = V4L2_TUNER_RADIO;
+ vt->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_LOW;
+ vt->rangelow = TUNER_FREQ_MIN_FM * 2 / 125;
+ vt->rangehigh = TUNER_FREQ_MAX_FM * 2 / 125;
+ vt->rxsubchans = V4L2_TUNER_SUB_STEREO;
+ vt->audmode = V4L2_TUNER_MODE_STEREO;
+ vt->signal = 0;
+ vt->afc = 0;
+ strlcpy(vt->name, "Radio", sizeof(vt->name));
+
+ mutex_lock(&p->lock);
+ ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO,
+ &fm_stat, &status, sizeof(fm_stat));
+
+ while (fm_stat.sig_lock_busy && count-- && !ret) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+
+ ret = send_get_req(p, TUNER_STATUS, TLG_MODE_FM_RADIO,
+ &fm_stat, &status, sizeof(fm_stat));
+ }
+ mutex_unlock(&p->lock);
+
+ if (ret || status) {
+ vt->signal = 0;
+ } else if ((fm_stat.sig_present || fm_stat.sig_locked)
+ && fm_stat.sig_strength == 0) {
+ vt->signal = 0xffff;
+ } else
+ vt->signal = (fm_stat.sig_strength * 255 / 10) << 8;
+
+ return 0;
+}
+
+static int fm_get_freq(struct file *file, void *priv,
+ struct v4l2_frequency *argp)
+{
+ struct poseidon *p = video_drvdata(file);
+
+ if (argp->tuner)
+ return -EINVAL;
+ argp->frequency = p->radio_data.fm_freq;
+ return 0;
+}
+
+static int set_frequency(struct poseidon *p, __u32 frequency)
+{
+ __u32 freq ;
+ int ret, status;
+
+ mutex_lock(&p->lock);
+
+ ret = send_set_req(p, TUNER_AUD_ANA_STD,
+ p->radio_data.pre_emphasis, &status);
+
+ freq = (frequency * 125) / 2; /* Hz */
+ freq = clamp(freq, TUNER_FREQ_MIN_FM, TUNER_FREQ_MAX_FM);
+
+ ret = send_set_req(p, TUNE_FREQ_SELECT, freq, &status);
+ if (ret < 0)
+ goto error ;
+ ret = send_set_req(p, TAKE_REQUEST, 0, &status);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/4);
+ if (!p->radio_data.is_radio_streaming) {
+ ret = send_set_req(p, TAKE_REQUEST, 0, &status);
+ ret = send_set_req(p, PLAY_SERVICE,
+ TLG_TUNE_PLAY_SVC_START, &status);
+ p->radio_data.is_radio_streaming = 1;
+ }
+ p->radio_data.fm_freq = freq * 2 / 125;
+error:
+ mutex_unlock(&p->lock);
+ return ret;
+}
+
+static int fm_set_freq(struct file *file, void *priv,
+ const struct v4l2_frequency *argp)
+{
+ struct poseidon *p = video_drvdata(file);
+
+ if (argp->tuner)
+ return -EINVAL;
+ p->file_for_stream = file;
+#ifdef CONFIG_PM
+ p->pm_suspend = pm_fm_suspend;
+ p->pm_resume = pm_fm_resume;
+#endif
+ return set_frequency(p, argp->frequency);
+}
+
+static int tlg_fm_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct poseidon *p = container_of(ctrl->handler, struct poseidon,
+ radio_data.ctrl_handler);
+ int pre_emphasis;
+ u32 status;
+
+ switch (ctrl->id) {
+ case V4L2_CID_TUNE_PREEMPHASIS:
+ pre_emphasis = preemphasis[ctrl->val];
+ send_set_req(p, TUNER_AUD_ANA_STD, pre_emphasis, &status);
+ p->radio_data.pre_emphasis = pre_emphasis;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int vidioc_s_tuner(struct file *file, void *priv, const struct v4l2_tuner *vt)
+{
+ return vt->index > 0 ? -EINVAL : 0;
+}
+
+static const struct v4l2_ctrl_ops tlg_fm_ctrl_ops = {
+ .s_ctrl = tlg_fm_s_ctrl,
+};
+
+static const struct v4l2_ioctl_ops poseidon_fm_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_tuner = tlg_fm_vidioc_g_tuner,
+ .vidioc_g_frequency = fm_get_freq,
+ .vidioc_s_frequency = fm_set_freq,
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+};
+
+static struct video_device poseidon_fm_template = {
+ .name = "Telegent-Radio",
+ .fops = &poseidon_fm_fops,
+ .minor = -1,
+ .release = video_device_release_empty,
+ .ioctl_ops = &poseidon_fm_ioctl_ops,
+};
+
+int poseidon_fm_init(struct poseidon *p)
+{
+ struct video_device *vfd = &p->radio_data.fm_dev;
+ struct v4l2_ctrl_handler *hdl = &p->radio_data.ctrl_handler;
+
+ *vfd = poseidon_fm_template;
+
+ set_frequency(p, TUNER_FREQ_MIN_FM);
+ v4l2_ctrl_handler_init(hdl, 1);
+ v4l2_ctrl_new_std_menu(hdl, &tlg_fm_ctrl_ops, V4L2_CID_TUNE_PREEMPHASIS,
+ V4L2_PREEMPHASIS_75_uS, 0, V4L2_PREEMPHASIS_50_uS);
+ if (hdl->error) {
+ v4l2_ctrl_handler_free(hdl);
+ return hdl->error;
+ }
+ vfd->v4l2_dev = &p->v4l2_dev;
+ vfd->ctrl_handler = hdl;
+ video_set_drvdata(vfd, p);
+ return video_register_device(vfd, VFL_TYPE_RADIO, -1);
+}
+
+int poseidon_fm_exit(struct poseidon *p)
+{
+ video_unregister_device(&p->radio_data.fm_dev);
+ v4l2_ctrl_handler_free(&p->radio_data.ctrl_handler);
+ return 0;
+}
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c
new file mode 100644
index 0000000..8cd7f02
--- /dev/null
+++ b/drivers/media/usb/tlg2300/pd-video.c
@@ -0,0 +1,1570 @@
+#include <linux/fs.h>
+#include <linux/vmalloc.h>
+#include <linux/videodev2.h>
+#include <linux/usb.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ctrls.h>
+
+#include "pd-common.h"
+#include "vendorcmds.h"
+
+#ifdef CONFIG_PM
+static int pm_video_suspend(struct poseidon *pd);
+static int pm_video_resume(struct poseidon *pd);
+#endif
+static void iso_bubble_handler(struct work_struct *w);
+
+static int usb_transfer_mode;
+module_param(usb_transfer_mode, int, 0644);
+MODULE_PARM_DESC(usb_transfer_mode, "0 = Bulk, 1 = Isochronous");
+
+static const struct poseidon_format poseidon_formats[] = {
+ { "YUV 422", V4L2_PIX_FMT_YUYV, 16, 0},
+ { "RGB565", V4L2_PIX_FMT_RGB565, 16, 0},
+};
+
+static const struct poseidon_tvnorm poseidon_tvnorms[] = {
+ { V4L2_STD_PAL_D, "PAL-D", TLG_TUNE_VSTD_PAL_D },
+ { V4L2_STD_PAL_B, "PAL-B", TLG_TUNE_VSTD_PAL_B },
+ { V4L2_STD_PAL_G, "PAL-G", TLG_TUNE_VSTD_PAL_G },
+ { V4L2_STD_PAL_H, "PAL-H", TLG_TUNE_VSTD_PAL_H },
+ { V4L2_STD_PAL_I, "PAL-I", TLG_TUNE_VSTD_PAL_I },
+ { V4L2_STD_PAL_M, "PAL-M", TLG_TUNE_VSTD_PAL_M },
+ { V4L2_STD_PAL_N, "PAL-N", TLG_TUNE_VSTD_PAL_N_COMBO },
+ { V4L2_STD_PAL_Nc, "PAL-Nc", TLG_TUNE_VSTD_PAL_N_COMBO },
+ { V4L2_STD_NTSC_M, "NTSC-M", TLG_TUNE_VSTD_NTSC_M },
+ { V4L2_STD_NTSC_M_JP, "NTSC-JP", TLG_TUNE_VSTD_NTSC_M_J },
+ { V4L2_STD_SECAM_B, "SECAM-B", TLG_TUNE_VSTD_SECAM_B },
+ { V4L2_STD_SECAM_D, "SECAM-D", TLG_TUNE_VSTD_SECAM_D },
+ { V4L2_STD_SECAM_G, "SECAM-G", TLG_TUNE_VSTD_SECAM_G },
+ { V4L2_STD_SECAM_H, "SECAM-H", TLG_TUNE_VSTD_SECAM_H },
+ { V4L2_STD_SECAM_K, "SECAM-K", TLG_TUNE_VSTD_SECAM_K },
+ { V4L2_STD_SECAM_K1, "SECAM-K1", TLG_TUNE_VSTD_SECAM_K1 },
+ { V4L2_STD_SECAM_L, "SECAM-L", TLG_TUNE_VSTD_SECAM_L },
+ { V4L2_STD_SECAM_LC, "SECAM-LC", TLG_TUNE_VSTD_SECAM_L1 },
+};
+static const unsigned int POSEIDON_TVNORMS = ARRAY_SIZE(poseidon_tvnorms);
+
+struct pd_audio_mode {
+ u32 tlg_audio_mode;
+ u32 v4l2_audio_sub;
+ u32 v4l2_audio_mode;
+};
+
+static const struct pd_audio_mode pd_audio_modes[] = {
+ { TLG_TUNE_TVAUDIO_MODE_MONO, V4L2_TUNER_SUB_MONO,
+ V4L2_TUNER_MODE_MONO },
+ { TLG_TUNE_TVAUDIO_MODE_STEREO, V4L2_TUNER_SUB_STEREO,
+ V4L2_TUNER_MODE_STEREO },
+ { TLG_TUNE_TVAUDIO_MODE_LANG_A, V4L2_TUNER_SUB_LANG1,
+ V4L2_TUNER_MODE_LANG1 },
+ { TLG_TUNE_TVAUDIO_MODE_LANG_B, V4L2_TUNER_SUB_LANG2,
+ V4L2_TUNER_MODE_LANG2 },
+ { TLG_TUNE_TVAUDIO_MODE_LANG_C, V4L2_TUNER_SUB_LANG1,
+ V4L2_TUNER_MODE_LANG1_LANG2 }
+};
+static const unsigned int POSEIDON_AUDIOMODS = ARRAY_SIZE(pd_audio_modes);
+
+struct pd_input {
+ char *name;
+ uint32_t tlg_src;
+};
+
+static const struct pd_input pd_inputs[] = {
+ { "TV Antenna", TLG_SIG_SRC_ANTENNA },
+ { "TV Cable", TLG_SIG_SRC_CABLE },
+ { "TV SVideo", TLG_SIG_SRC_SVIDEO },
+ { "TV Composite", TLG_SIG_SRC_COMPOSITE }
+};
+static const unsigned int POSEIDON_INPUTS = ARRAY_SIZE(pd_inputs);
+
+struct video_std_to_audio_std {
+ v4l2_std_id video_std;
+ int audio_std;
+};
+
+static const struct video_std_to_audio_std video_to_audio_map[] = {
+ /* country : { 27, 32, 33, 34, 36, 44, 45, 46, 47, 48, 64,
+ 65, 86, 351, 352, 353, 354, 358, 372, 852, 972 } */
+ { (V4L2_STD_PAL_I | V4L2_STD_PAL_B | V4L2_STD_PAL_D |
+ V4L2_STD_SECAM_L | V4L2_STD_SECAM_D), TLG_TUNE_ASTD_NICAM },
+
+ /* country : { 1, 52, 54, 55, 886 } */
+ {V4L2_STD_NTSC_M | V4L2_STD_PAL_N | V4L2_STD_PAL_M, TLG_TUNE_ASTD_BTSC},
+
+ /* country : { 81 } */
+ { V4L2_STD_NTSC_M_JP, TLG_TUNE_ASTD_EIAJ },
+
+ /* other country : TLG_TUNE_ASTD_A2 */
+};
+static const unsigned int map_size = ARRAY_SIZE(video_to_audio_map);
+
+static int get_audio_std(v4l2_std_id v4l2_std)
+{
+ int i = 0;
+
+ for (; i < map_size; i++) {
+ if (v4l2_std & video_to_audio_map[i].video_std)
+ return video_to_audio_map[i].audio_std;
+ }
+ return TLG_TUNE_ASTD_A2;
+}
+
+static int vidioc_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct poseidon *p = video_get_drvdata(vdev);
+
+ strcpy(cap->driver, "tele-video");
+ strcpy(cap->card, "Telegent Poseidon");
+ usb_make_path(p->udev, cap->bus_info, sizeof(cap->bus_info));
+ cap->device_caps = V4L2_CAP_TUNER | V4L2_CAP_AUDIO |
+ V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
+ if (vdev->vfl_type == VFL_TYPE_VBI)
+ cap->device_caps |= V4L2_CAP_VBI_CAPTURE;
+ else
+ cap->device_caps |= V4L2_CAP_VIDEO_CAPTURE;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS |
+ V4L2_CAP_RADIO | V4L2_CAP_VBI_CAPTURE | V4L2_CAP_VIDEO_CAPTURE;
+ return 0;
+}
+
+/*====================================================================*/
+static void init_copy(struct video_data *video, bool index)
+{
+ struct front_face *front = video->front;
+
+ video->field_count = index;
+ video->lines_copied = 0;
+ video->prev_left = 0 ;
+ video->dst = (char *)videobuf_to_vmalloc(front->curr_frame)
+ + index * video->lines_size;
+ video->vbi->copied = 0; /* set it here */
+}
+
+static bool get_frame(struct front_face *front, int *need_init)
+{
+ struct videobuf_buffer *vb = front->curr_frame;
+
+ if (vb)
+ return true;
+
+ spin_lock(&front->queue_lock);
+ if (!list_empty(&front->active)) {
+ vb = list_entry(front->active.next,
+ struct videobuf_buffer, queue);
+ if (need_init)
+ *need_init = 1;
+ front->curr_frame = vb;
+ list_del_init(&vb->queue);
+ }
+ spin_unlock(&front->queue_lock);
+
+ return !!vb;
+}
+
+/* check if the video's buffer is ready */
+static bool get_video_frame(struct front_face *front, struct video_data *video)
+{
+ int need_init = 0;
+ bool ret = true;
+
+ ret = get_frame(front, &need_init);
+ if (ret && need_init)
+ init_copy(video, 0);
+ return ret;
+}
+
+static void submit_frame(struct front_face *front)
+{
+ struct videobuf_buffer *vb = front->curr_frame;
+
+ if (vb == NULL)
+ return;
+
+ front->curr_frame = NULL;
+ vb->state = VIDEOBUF_DONE;
+ vb->field_count++;
+ v4l2_get_timestamp(&vb->ts);
+
+ wake_up(&vb->done);
+}
+
+/*
+ * A frame is composed of two fields. If we receive all the two fields,
+ * call the submit_frame() to submit the whole frame to applications.
+ */
+static void end_field(struct video_data *video)
+{
+ if (1 == video->field_count)
+ submit_frame(video->front);
+ else
+ init_copy(video, 1);
+}
+
+static void copy_video_data(struct video_data *video, char *src,
+ unsigned int count)
+{
+#define copy_data(len) \
+ do { \
+ if (++video->lines_copied > video->lines_per_field) \
+ goto overflow; \
+ memcpy(video->dst, src, len);\
+ video->dst += len + video->lines_size; \
+ src += len; \
+ count -= len; \
+ } while (0)
+
+ while (count && count >= video->lines_size) {
+ if (video->prev_left) {
+ copy_data(video->prev_left);
+ video->prev_left = 0;
+ continue;
+ }
+ copy_data(video->lines_size);
+ }
+ if (count && count < video->lines_size) {
+ memcpy(video->dst, src, count);
+
+ video->prev_left = video->lines_size - count;
+ video->dst += count;
+ }
+ return;
+
+overflow:
+ end_field(video);
+}
+
+static void check_trailer(struct video_data *video, char *src, int count)
+{
+ struct vbi_data *vbi = video->vbi;
+ int offset; /* trailer's offset */
+ char *buf;
+
+ offset = (video->context.pix.sizeimage / 2 + vbi->vbi_size / 2)
+ - (vbi->copied + video->lines_size * video->lines_copied);
+ if (video->prev_left)
+ offset -= (video->lines_size - video->prev_left);
+
+ if (offset > count || offset <= 0)
+ goto short_package;
+
+ buf = src + offset;
+
+ /* trailer : (VFHS) + U32 + U32 + field_num */
+ if (!strncmp(buf, "VFHS", 4)) {
+ int field_num = *((u32 *)(buf + 12));
+
+ if ((field_num & 1) ^ video->field_count) {
+ init_copy(video, video->field_count);
+ return;
+ }
+ copy_video_data(video, src, offset);
+ }
+short_package:
+ end_field(video);
+}
+
+/* ========== Check this more carefully! =========== */
+static inline void copy_vbi_data(struct vbi_data *vbi,
+ char *src, unsigned int count)
+{
+ struct front_face *front = vbi->front;
+
+ if (front && get_frame(front, NULL)) {
+ char *buf = videobuf_to_vmalloc(front->curr_frame);
+
+ if (vbi->video->field_count)
+ buf += (vbi->vbi_size / 2);
+ memcpy(buf + vbi->copied, src, count);
+ }
+ vbi->copied += count;
+}
+
+/*
+ * Copy the normal data (VBI or VIDEO) without the trailer.
+ * VBI is not interlaced, while VIDEO is interlaced.
+ */
+static inline void copy_vbi_video_data(struct video_data *video,
+ char *src, unsigned int count)
+{
+ struct vbi_data *vbi = video->vbi;
+ unsigned int vbi_delta = (vbi->vbi_size / 2) - vbi->copied;
+
+ if (vbi_delta >= count) {
+ copy_vbi_data(vbi, src, count);
+ } else {
+ if (vbi_delta) {
+ copy_vbi_data(vbi, src, vbi_delta);
+
+ /* we receive the two fields of the VBI*/
+ if (vbi->front && video->field_count)
+ submit_frame(vbi->front);
+ }
+ copy_video_data(video, src + vbi_delta, count - vbi_delta);
+ }
+}
+
+static void urb_complete_bulk(struct urb *urb)
+{
+ struct front_face *front = urb->context;
+ struct video_data *video = &front->pd->video_data;
+ char *src = (char *)urb->transfer_buffer;
+ int count = urb->actual_length;
+ int ret = 0;
+
+ if (!video->is_streaming || urb->status) {
+ if (urb->status == -EPROTO)
+ goto resend_it;
+ return;
+ }
+ if (!get_video_frame(front, video))
+ goto resend_it;
+
+ if (count == urb->transfer_buffer_length)
+ copy_vbi_video_data(video, src, count);
+ else
+ check_trailer(video, src, count);
+
+resend_it:
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ log(" submit failed: error %d", ret);
+}
+
+/************************* for ISO *********************/
+#define GET_SUCCESS (0)
+#define GET_TRAILER (1)
+#define GET_TOO_MUCH_BUBBLE (2)
+#define GET_NONE (3)
+static int get_chunk(int start, struct urb *urb,
+ int *head, int *tail, int *bubble_err)
+{
+ struct usb_iso_packet_descriptor *pkt = NULL;
+ int ret = GET_SUCCESS;
+
+ for (*head = *tail = -1; start < urb->number_of_packets; start++) {
+ pkt = &urb->iso_frame_desc[start];
+
+ /* handle the bubble of the Hub */
+ if (-EOVERFLOW == pkt->status) {
+ if (++*bubble_err > urb->number_of_packets / 3)
+ return GET_TOO_MUCH_BUBBLE;
+ continue;
+ }
+
+ /* This is the gap */
+ if (pkt->status || pkt->actual_length <= 0
+ || pkt->actual_length > ISO_PKT_SIZE) {
+ if (*head != -1)
+ break;
+ continue;
+ }
+
+ /* a good isochronous packet */
+ if (pkt->actual_length == ISO_PKT_SIZE) {
+ if (*head == -1)
+ *head = start;
+ *tail = start;
+ continue;
+ }
+
+ /* trailer is here */
+ if (pkt->actual_length < ISO_PKT_SIZE) {
+ if (*head == -1) {
+ *head = start;
+ *tail = start;
+ return GET_TRAILER;
+ }
+ break;
+ }
+ }
+
+ if (*head == -1 && *tail == -1)
+ ret = GET_NONE;
+ return ret;
+}
+
+/*
+ * |__|------|___|-----|_______|
+ * ^ ^
+ * | |
+ * gap gap
+ */
+static void urb_complete_iso(struct urb *urb)
+{
+ struct front_face *front = urb->context;
+ struct video_data *video = &front->pd->video_data;
+ int bubble_err = 0, head = 0, tail = 0;
+ char *src = (char *)urb->transfer_buffer;
+ int ret = 0;
+
+ if (!video->is_streaming)
+ return;
+
+ do {
+ if (!get_video_frame(front, video))
+ goto out;
+
+ switch (get_chunk(head, urb, &head, &tail, &bubble_err)) {
+ case GET_SUCCESS:
+ copy_vbi_video_data(video, src + (head * ISO_PKT_SIZE),
+ (tail - head + 1) * ISO_PKT_SIZE);
+ break;
+ case GET_TRAILER:
+ check_trailer(video, src + (head * ISO_PKT_SIZE),
+ ISO_PKT_SIZE);
+ break;
+ case GET_NONE:
+ goto out;
+ case GET_TOO_MUCH_BUBBLE:
+ log("\t We got too much bubble");
+ schedule_work(&video->bubble_work);
+ return;
+ }
+ } while (head = tail + 1, head < urb->number_of_packets);
+
+out:
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
+ if (ret)
+ log("usb_submit_urb err : %d", ret);
+}
+/*============================= [ end ] =====================*/
+
+static int prepare_iso_urb(struct video_data *video)
+{
+ struct usb_device *udev = video->pd->udev;
+ int i;
+
+ if (video->urb_array[0])
+ return 0;
+
+ for (i = 0; i < SBUF_NUM; i++) {
+ struct urb *urb;
+ void *mem;
+ int j;
+
+ urb = usb_alloc_urb(PK_PER_URB, GFP_KERNEL);
+ if (urb == NULL)
+ goto out;
+
+ video->urb_array[i] = urb;
+ mem = usb_alloc_coherent(udev,
+ ISO_PKT_SIZE * PK_PER_URB,
+ GFP_KERNEL,
+ &urb->transfer_dma);
+
+ urb->complete = urb_complete_iso; /* handler */
+ urb->dev = udev;
+ urb->context = video->front;
+ urb->pipe = usb_rcvisocpipe(udev,
+ video->endpoint_addr);
+ urb->interval = 1;
+ urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+ urb->number_of_packets = PK_PER_URB;
+ urb->transfer_buffer = mem;
+ urb->transfer_buffer_length = PK_PER_URB * ISO_PKT_SIZE;
+
+ for (j = 0; j < PK_PER_URB; j++) {
+ urb->iso_frame_desc[j].offset = ISO_PKT_SIZE * j;
+ urb->iso_frame_desc[j].length = ISO_PKT_SIZE;
+ }
+ }
+ return 0;
+out:
+ for (; i > 0; i--)
+ ;
+ return -ENOMEM;
+}
+
+/* return the succeeded number of the allocation */
+int alloc_bulk_urbs_generic(struct urb **urb_array, int num,
+ struct usb_device *udev, u8 ep_addr,
+ int buf_size, gfp_t gfp_flags,
+ usb_complete_t complete_fn, void *context)
+{
+ int i = 0;
+
+ for (; i < num; i++) {
+ void *mem;
+ struct urb *urb = usb_alloc_urb(0, gfp_flags);
+ if (urb == NULL)
+ return i;
+
+ mem = usb_alloc_coherent(udev, buf_size, gfp_flags,
+ &urb->transfer_dma);
+ if (mem == NULL) {
+ usb_free_urb(urb);
+ return i;
+ }
+
+ usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, ep_addr),
+ mem, buf_size, complete_fn, context);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ urb_array[i] = urb;
+ }
+ return i;
+}
+
+void free_all_urb_generic(struct urb **urb_array, int num)
+{
+ int i;
+ struct urb *urb;
+
+ for (i = 0; i < num; i++) {
+ urb = urb_array[i];
+ if (urb) {
+ usb_free_coherent(urb->dev,
+ urb->transfer_buffer_length,
+ urb->transfer_buffer,
+ urb->transfer_dma);
+ usb_free_urb(urb);
+ urb_array[i] = NULL;
+ }
+ }
+}
+
+static int prepare_bulk_urb(struct video_data *video)
+{
+ if (video->urb_array[0])
+ return 0;
+
+ alloc_bulk_urbs_generic(video->urb_array, SBUF_NUM,
+ video->pd->udev, video->endpoint_addr,
+ 0x2000, GFP_KERNEL,
+ urb_complete_bulk, video->front);
+ return 0;
+}
+
+/* free the URBs */
+static void free_all_urb(struct video_data *video)
+{
+ free_all_urb_generic(video->urb_array, SBUF_NUM);
+}
+
+static void pd_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+ videobuf_vmalloc_free(vb);
+ vb->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static void pd_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
+{
+ struct front_face *front = q->priv_data;
+ vb->state = VIDEOBUF_QUEUED;
+ list_add_tail(&vb->queue, &front->active);
+}
+
+static int pd_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ struct front_face *front = q->priv_data;
+ int rc;
+
+ switch (front->type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ if (VIDEOBUF_NEEDS_INIT == vb->state) {
+ struct v4l2_pix_format *pix;
+
+ pix = &front->pd->video_data.context.pix;
+ vb->size = pix->sizeimage; /* real frame size */
+ vb->width = pix->width;
+ vb->height = pix->height;
+ rc = videobuf_iolock(q, vb, NULL);
+ if (rc < 0)
+ return rc;
+ }
+ break;
+ case V4L2_BUF_TYPE_VBI_CAPTURE:
+ if (VIDEOBUF_NEEDS_INIT == vb->state) {
+ vb->size = front->pd->vbi_data.vbi_size;
+ rc = videobuf_iolock(q, vb, NULL);
+ if (rc < 0)
+ return rc;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ vb->field = field;
+ vb->state = VIDEOBUF_PREPARED;
+ return 0;
+}
+
+static int fire_all_urb(struct video_data *video)
+{
+ int i, ret;
+
+ video->is_streaming = 1;
+
+ for (i = 0; i < SBUF_NUM; i++) {
+ ret = usb_submit_urb(video->urb_array[i], GFP_KERNEL);
+ if (ret)
+ log("(%d) failed: error %d", i, ret);
+ }
+ return ret;
+}
+
+static int start_video_stream(struct poseidon *pd)
+{
+ struct video_data *video = &pd->video_data;
+ s32 cmd_status;
+
+ send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+ send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_START, &cmd_status);
+
+ if (pd->cur_transfer_mode) {
+ prepare_iso_urb(video);
+ INIT_WORK(&video->bubble_work, iso_bubble_handler);
+ } else {
+ /* The bulk mode does not need a bubble handler */
+ prepare_bulk_urb(video);
+ }
+ fire_all_urb(video);
+ return 0;
+}
+
+static int pd_buf_setup(struct videobuf_queue *q, unsigned int *count,
+ unsigned int *size)
+{
+ struct front_face *front = q->priv_data;
+ struct poseidon *pd = front->pd;
+
+ switch (front->type) {
+ default:
+ return -EINVAL;
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE: {
+ struct video_data *video = &pd->video_data;
+ struct v4l2_pix_format *pix = &video->context.pix;
+
+ *size = PAGE_ALIGN(pix->sizeimage);/* page aligned frame size */
+ if (*count < 4)
+ *count = 4;
+ if (1) {
+ /* same in different altersetting */
+ video->endpoint_addr = 0x82;
+ video->vbi = &pd->vbi_data;
+ video->vbi->video = video;
+ video->pd = pd;
+ video->lines_per_field = pix->height / 2;
+ video->lines_size = pix->width * 2;
+ video->front = front;
+ }
+ return start_video_stream(pd);
+ }
+
+ case V4L2_BUF_TYPE_VBI_CAPTURE: {
+ struct vbi_data *vbi = &pd->vbi_data;
+
+ *size = PAGE_ALIGN(vbi->vbi_size);
+ log("size : %d", *size);
+ if (*count == 0)
+ *count = 4;
+ }
+ break;
+ }
+ return 0;
+}
+
+static struct videobuf_queue_ops pd_video_qops = {
+ .buf_setup = pd_buf_setup,
+ .buf_prepare = pd_buf_prepare,
+ .buf_queue = pd_buf_queue,
+ .buf_release = pd_buf_release,
+};
+
+static int vidioc_enum_fmt(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ if (ARRAY_SIZE(poseidon_formats) <= f->index)
+ return -EINVAL;
+ f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ f->flags = 0;
+ f->pixelformat = poseidon_formats[f->index].fourcc;
+ strcpy(f->description, poseidon_formats[f->index].name);
+ return 0;
+}
+
+static int vidioc_g_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct front_face *front = fh;
+ struct poseidon *pd = front->pd;
+
+ f->fmt.pix = pd->video_data.context.pix;
+ return 0;
+}
+
+/*
+ * VLC calls VIDIOC_S_STD before VIDIOC_S_FMT, while
+ * Mplayer calls them in the reverse order.
+ */
+static int pd_vidioc_s_fmt(struct poseidon *pd, struct v4l2_pix_format *pix)
+{
+ struct video_data *video = &pd->video_data;
+ struct running_context *context = &video->context;
+ struct v4l2_pix_format *pix_def = &context->pix;
+ s32 ret = 0, cmd_status = 0, vid_resol;
+
+ /* set the pixel format to firmware */
+ if (pix->pixelformat == V4L2_PIX_FMT_RGB565) {
+ vid_resol = TLG_TUNER_VID_FORMAT_RGB_565;
+ } else {
+ pix->pixelformat = V4L2_PIX_FMT_YUYV;
+ vid_resol = TLG_TUNER_VID_FORMAT_YUV;
+ }
+ ret = send_set_req(pd, VIDEO_STREAM_FMT_SEL,
+ vid_resol, &cmd_status);
+
+ /* set the resolution to firmware */
+ vid_resol = TLG_TUNE_VID_RES_720;
+ switch (pix->width) {
+ case 704:
+ vid_resol = TLG_TUNE_VID_RES_704;
+ break;
+ default:
+ pix->width = 720;
+ case 720:
+ break;
+ }
+ ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
+ vid_resol, &cmd_status);
+ if (ret || cmd_status)
+ return -EBUSY;
+
+ pix_def->pixelformat = pix->pixelformat; /* save it */
+ pix->height = (context->tvnormid & V4L2_STD_525_60) ? 480 : 576;
+
+ /* Compare with the default setting */
+ if ((pix_def->width != pix->width)
+ || (pix_def->height != pix->height)) {
+ pix_def->width = pix->width;
+ pix_def->height = pix->height;
+ pix_def->bytesperline = pix->width * 2;
+ pix_def->sizeimage = pix->width * pix->height * 2;
+ }
+ *pix = *pix_def;
+
+ return 0;
+}
+
+static int vidioc_s_fmt(struct file *file, void *fh, struct v4l2_format *f)
+{
+ struct front_face *front = fh;
+ struct poseidon *pd = front->pd;
+
+ /* stop VBI here */
+ if (V4L2_BUF_TYPE_VIDEO_CAPTURE != f->type)
+ return -EINVAL;
+
+ mutex_lock(&pd->lock);
+ if (pd->file_for_stream == NULL)
+ pd->file_for_stream = file;
+ else if (file != pd->file_for_stream) {
+ mutex_unlock(&pd->lock);
+ return -EINVAL;
+ }
+
+ pd_vidioc_s_fmt(pd, &f->fmt.pix);
+ mutex_unlock(&pd->lock);
+ return 0;
+}
+
+static int vidioc_g_fmt_vbi(struct file *file, void *fh,
+ struct v4l2_format *v4l2_f)
+{
+ struct front_face *front = fh;
+ struct poseidon *pd = front->pd;
+ struct v4l2_vbi_format *vbi_fmt = &v4l2_f->fmt.vbi;
+
+ vbi_fmt->samples_per_line = 720 * 2;
+ vbi_fmt->sampling_rate = 6750000 * 4;
+ vbi_fmt->sample_format = V4L2_PIX_FMT_GREY;
+ vbi_fmt->offset = 64 * 4; /*FIXME: why offset */
+ if (pd->video_data.context.tvnormid & V4L2_STD_525_60) {
+ vbi_fmt->start[0] = 10;
+ vbi_fmt->start[1] = 264;
+ vbi_fmt->count[0] = V4L_NTSC_VBI_LINES;
+ vbi_fmt->count[1] = V4L_NTSC_VBI_LINES;
+ } else {
+ vbi_fmt->start[0] = 6;
+ vbi_fmt->start[1] = 314;
+ vbi_fmt->count[0] = V4L_PAL_VBI_LINES;
+ vbi_fmt->count[1] = V4L_PAL_VBI_LINES;
+ }
+ vbi_fmt->flags = V4L2_VBI_UNSYNC;
+ return 0;
+}
+
+static int set_std(struct poseidon *pd, v4l2_std_id norm)
+{
+ struct video_data *video = &pd->video_data;
+ struct vbi_data *vbi = &pd->vbi_data;
+ struct running_context *context;
+ struct v4l2_pix_format *pix;
+ s32 i, ret = 0, cmd_status, param;
+ int height;
+
+ for (i = 0; i < POSEIDON_TVNORMS; i++) {
+ if (norm & poseidon_tvnorms[i].v4l2_id) {
+ param = poseidon_tvnorms[i].tlg_tvnorm;
+ log("name : %s", poseidon_tvnorms[i].name);
+ goto found;
+ }
+ }
+ return -EINVAL;
+found:
+ mutex_lock(&pd->lock);
+ ret = send_set_req(pd, VIDEO_STD_SEL, param, &cmd_status);
+ if (ret || cmd_status)
+ goto out;
+
+ /* Set vbi size and check the height of the frame */
+ context = &video->context;
+ context->tvnormid = poseidon_tvnorms[i].v4l2_id;
+ if (context->tvnormid & V4L2_STD_525_60) {
+ vbi->vbi_size = V4L_NTSC_VBI_FRAMESIZE;
+ height = 480;
+ } else {
+ vbi->vbi_size = V4L_PAL_VBI_FRAMESIZE;
+ height = 576;
+ }
+
+ pix = &context->pix;
+ if (pix->height != height) {
+ pix->height = height;
+ pix->sizeimage = pix->width * pix->height * 2;
+ }
+
+out:
+ mutex_unlock(&pd->lock);
+ return ret;
+}
+
+static int vidioc_s_std(struct file *file, void *fh, v4l2_std_id norm)
+{
+ struct front_face *front = fh;
+
+ return set_std(front->pd, norm);
+}
+
+static int vidioc_g_std(struct file *file, void *fh, v4l2_std_id *norm)
+{
+ struct front_face *front = fh;
+
+ *norm = front->pd->video_data.context.tvnormid;
+ return 0;
+}
+
+static int vidioc_enum_input(struct file *file, void *fh, struct v4l2_input *in)
+{
+ if (in->index >= POSEIDON_INPUTS)
+ return -EINVAL;
+ strcpy(in->name, pd_inputs[in->index].name);
+ in->type = V4L2_INPUT_TYPE_TUNER;
+
+ /*
+ * the audio input index mixed with this video input,
+ * Poseidon only have one audio/video, set to "0"
+ */
+ in->audioset = 1;
+ in->tuner = 0;
+ in->std = V4L2_STD_ALL;
+ in->status = 0;
+ return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+ struct front_face *front = fh;
+ struct poseidon *pd = front->pd;
+ struct running_context *context = &pd->video_data.context;
+
+ *i = context->sig_index;
+ return 0;
+}
+
+/* We can support several inputs */
+static int vidioc_s_input(struct file *file, void *fh, unsigned int i)
+{
+ struct front_face *front = fh;
+ struct poseidon *pd = front->pd;
+ s32 ret, cmd_status;
+
+ if (i >= POSEIDON_INPUTS)
+ return -EINVAL;
+ ret = send_set_req(pd, SGNL_SRC_SEL,
+ pd_inputs[i].tlg_src, &cmd_status);
+ if (ret)
+ return ret;
+
+ pd->video_data.context.sig_index = i;
+ return 0;
+}
+
+static int tlg_s_ctrl(struct v4l2_ctrl *c)
+{
+ struct poseidon *pd = container_of(c->handler, struct poseidon,
+ video_data.ctrl_handler);
+ struct tuner_custom_parameter_s param = {0};
+ s32 ret = 0, cmd_status, params;
+
+ switch (c->id) {
+ case V4L2_CID_BRIGHTNESS:
+ param.param_id = CUST_PARM_ID_BRIGHTNESS_CTRL;
+ break;
+ case V4L2_CID_CONTRAST:
+ param.param_id = CUST_PARM_ID_CONTRAST_CTRL;
+ break;
+ case V4L2_CID_HUE:
+ param.param_id = CUST_PARM_ID_HUE_CTRL;
+ break;
+ case V4L2_CID_SATURATION:
+ param.param_id = CUST_PARM_ID_SATURATION_CTRL;
+ break;
+ }
+ param.param_value = c->val;
+ params = *(s32 *)¶m; /* temp code */
+
+ mutex_lock(&pd->lock);
+ ret = send_set_req(pd, TUNER_CUSTOM_PARAMETER, params, &cmd_status);
+ ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+ mutex_unlock(&pd->lock);
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/4);
+ return ret;
+}
+
+/* Audio ioctls */
+static int vidioc_enumaudio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+ if (0 != a->index)
+ return -EINVAL;
+ a->capability = V4L2_AUDCAP_STEREO;
+ strcpy(a->name, "USB audio in");
+ /*Poseidon have no AVL function.*/
+ a->mode = 0;
+ return 0;
+}
+
+static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
+{
+ a->index = 0;
+ a->capability = V4L2_AUDCAP_STEREO;
+ strcpy(a->name, "USB audio in");
+ a->mode = 0;
+ return 0;
+}
+
+static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
+{
+ return (0 == a->index) ? 0 : -EINVAL;
+}
+
+/* Tuner ioctls */
+static int vidioc_g_tuner(struct file *file, void *fh, struct v4l2_tuner *tuner)
+{
+ struct front_face *front = fh;
+ struct poseidon *pd = front->pd;
+ struct tuner_atv_sig_stat_s atv_stat;
+ s32 count = 5, ret, cmd_status;
+ int index;
+
+ if (0 != tuner->index)
+ return -EINVAL;
+
+ mutex_lock(&pd->lock);
+ ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV,
+ &atv_stat, &cmd_status, sizeof(atv_stat));
+
+ while (atv_stat.sig_lock_busy && count-- && !ret) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ);
+
+ ret = send_get_req(pd, TUNER_STATUS, TLG_MODE_ANALOG_TV,
+ &atv_stat, &cmd_status, sizeof(atv_stat));
+ }
+ mutex_unlock(&pd->lock);
+
+ if (debug_mode)
+ log("P:%d,S:%d", atv_stat.sig_present, atv_stat.sig_strength);
+
+ if (ret || cmd_status)
+ tuner->signal = 0;
+ else if (atv_stat.sig_present && !atv_stat.sig_strength)
+ tuner->signal = 0xFFFF;
+ else
+ tuner->signal = (atv_stat.sig_strength * 255 / 10) << 8;
+
+ strcpy(tuner->name, "Telegent Systems");
+ tuner->type = V4L2_TUNER_ANALOG_TV;
+ tuner->rangelow = TUNER_FREQ_MIN / 62500;
+ tuner->rangehigh = TUNER_FREQ_MAX / 62500;
+ tuner->capability = V4L2_TUNER_CAP_NORM | V4L2_TUNER_CAP_STEREO |
+ V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
+ index = pd->video_data.context.audio_idx;
+ tuner->rxsubchans = pd_audio_modes[index].v4l2_audio_sub;
+ tuner->audmode = pd_audio_modes[index].v4l2_audio_mode;
+ tuner->afc = 0;
+ return 0;
+}
+
+static int pd_vidioc_s_tuner(struct poseidon *pd, int index)
+{
+ s32 ret = 0, cmd_status, param, audiomode;
+
+ mutex_lock(&pd->lock);
+ param = pd_audio_modes[index].tlg_audio_mode;
+ ret = send_set_req(pd, TUNER_AUD_MODE, param, &cmd_status);
+ audiomode = get_audio_std(pd->video_data.context.tvnormid);
+ ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode,
+ &cmd_status);
+ if (!ret)
+ pd->video_data.context.audio_idx = index;
+ mutex_unlock(&pd->lock);
+ return ret;
+}
+
+static int vidioc_s_tuner(struct file *file, void *fh, const struct v4l2_tuner *a)
+{
+ struct front_face *front = fh;
+ struct poseidon *pd = front->pd;
+ int index;
+
+ if (0 != a->index)
+ return -EINVAL;
+ for (index = 0; index < POSEIDON_AUDIOMODS; index++)
+ if (a->audmode == pd_audio_modes[index].v4l2_audio_mode)
+ return pd_vidioc_s_tuner(pd, index);
+ return -EINVAL;
+}
+
+static int vidioc_g_frequency(struct file *file, void *fh,
+ struct v4l2_frequency *freq)
+{
+ struct front_face *front = fh;
+ struct poseidon *pd = front->pd;
+ struct running_context *context = &pd->video_data.context;
+
+ if (0 != freq->tuner)
+ return -EINVAL;
+ freq->frequency = context->freq;
+ freq->type = V4L2_TUNER_ANALOG_TV;
+ return 0;
+}
+
+static int set_frequency(struct poseidon *pd, u32 *frequency)
+{
+ s32 ret = 0, param, cmd_status;
+ struct running_context *context = &pd->video_data.context;
+
+ *frequency = clamp(*frequency,
+ TUNER_FREQ_MIN / 62500, TUNER_FREQ_MAX / 62500);
+ param = (*frequency) * 62500 / 1000;
+
+ mutex_lock(&pd->lock);
+ ret = send_set_req(pd, TUNE_FREQ_SELECT, param, &cmd_status);
+ ret = send_set_req(pd, TAKE_REQUEST, 0, &cmd_status);
+
+ msleep(250); /* wait for a while until the hardware is ready. */
+ context->freq = *frequency;
+ mutex_unlock(&pd->lock);
+ return ret;
+}
+
+static int vidioc_s_frequency(struct file *file, void *fh,
+ const struct v4l2_frequency *freq)
+{
+ struct front_face *front = fh;
+ struct poseidon *pd = front->pd;
+ u32 frequency = freq->frequency;
+
+ if (freq->tuner)
+ return -EINVAL;
+#ifdef CONFIG_PM
+ pd->pm_suspend = pm_video_suspend;
+ pd->pm_resume = pm_video_resume;
+#endif
+ return set_frequency(pd, &frequency);
+}
+
+static int vidioc_reqbufs(struct file *file, void *fh,
+ struct v4l2_requestbuffers *b)
+{
+ struct front_face *front = file->private_data;
+ return videobuf_reqbufs(&front->q, b);
+}
+
+static int vidioc_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+ struct front_face *front = file->private_data;
+ return videobuf_querybuf(&front->q, b);
+}
+
+static int vidioc_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+ struct front_face *front = file->private_data;
+ return videobuf_qbuf(&front->q, b);
+}
+
+static int vidioc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+ struct front_face *front = file->private_data;
+ return videobuf_dqbuf(&front->q, b, file->f_flags & O_NONBLOCK);
+}
+
+/* Just stop the URBs, do not free the URBs */
+static int usb_transfer_stop(struct video_data *video)
+{
+ if (video->is_streaming) {
+ int i;
+ s32 cmd_status;
+ struct poseidon *pd = video->pd;
+
+ video->is_streaming = 0;
+ for (i = 0; i < SBUF_NUM; ++i) {
+ if (video->urb_array[i])
+ usb_kill_urb(video->urb_array[i]);
+ }
+
+ send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
+ &cmd_status);
+ }
+ return 0;
+}
+
+int stop_all_video_stream(struct poseidon *pd)
+{
+ struct video_data *video = &pd->video_data;
+ struct vbi_data *vbi = &pd->vbi_data;
+
+ mutex_lock(&pd->lock);
+ if (video->is_streaming) {
+ struct front_face *front = video->front;
+
+ /* stop the URBs */
+ usb_transfer_stop(video);
+ free_all_urb(video);
+
+ /* stop the host side of VIDEO */
+ videobuf_stop(&front->q);
+ videobuf_mmap_free(&front->q);
+
+ /* stop the host side of VBI */
+ front = vbi->front;
+ if (front) {
+ videobuf_stop(&front->q);
+ videobuf_mmap_free(&front->q);
+ }
+ }
+ mutex_unlock(&pd->lock);
+ return 0;
+}
+
+/*
+ * The bubbles can seriously damage the video's quality,
+ * though it occurs in very rare situation.
+ */
+static void iso_bubble_handler(struct work_struct *w)
+{
+ struct video_data *video;
+ struct poseidon *pd;
+
+ video = container_of(w, struct video_data, bubble_work);
+ pd = video->pd;
+
+ mutex_lock(&pd->lock);
+ usb_transfer_stop(video);
+ msleep(500);
+ start_video_stream(pd);
+ mutex_unlock(&pd->lock);
+}
+
+
+static int vidioc_streamon(struct file *file, void *fh,
+ enum v4l2_buf_type type)
+{
+ struct front_face *front = fh;
+
+ if (unlikely(type != front->type))
+ return -EINVAL;
+ return videobuf_streamon(&front->q);
+}
+
+static int vidioc_streamoff(struct file *file, void *fh,
+ enum v4l2_buf_type type)
+{
+ struct front_face *front = file->private_data;
+
+ if (unlikely(type != front->type))
+ return -EINVAL;
+ return videobuf_streamoff(&front->q);
+}
+
+/* Set the firmware's default values : need altersetting */
+static int pd_video_checkmode(struct poseidon *pd)
+{
+ s32 ret = 0, cmd_status, audiomode;
+
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(HZ/2);
+
+ /* choose the altersetting */
+ ret = usb_set_interface(pd->udev, 0,
+ (pd->cur_transfer_mode ?
+ ISO_3K_BULK_ALTERNATE_IFACE :
+ BULK_ALTERNATE_IFACE));
+ if (ret < 0)
+ goto error;
+
+ /* set default parameters for PAL-D , with the VBI enabled*/
+ ret = set_tuner_mode(pd, TLG_MODE_ANALOG_TV);
+ ret |= send_set_req(pd, SGNL_SRC_SEL,
+ TLG_SIG_SRC_ANTENNA, &cmd_status);
+ ret |= send_set_req(pd, VIDEO_STD_SEL,
+ TLG_TUNE_VSTD_PAL_D, &cmd_status);
+ ret |= send_set_req(pd, VIDEO_STREAM_FMT_SEL,
+ TLG_TUNER_VID_FORMAT_YUV, &cmd_status);
+ ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
+ TLG_TUNE_VID_RES_720, &cmd_status);
+ ret |= send_set_req(pd, TUNE_FREQ_SELECT, TUNER_FREQ_MIN, &cmd_status);
+ ret |= send_set_req(pd, VBI_DATA_SEL, 1, &cmd_status);/* enable vbi */
+
+ /* set the audio */
+ audiomode = get_audio_std(pd->video_data.context.tvnormid);
+ ret |= send_set_req(pd, TUNER_AUD_ANA_STD, audiomode, &cmd_status);
+ ret |= send_set_req(pd, TUNER_AUD_MODE,
+ TLG_TUNE_TVAUDIO_MODE_STEREO, &cmd_status);
+ ret |= send_set_req(pd, AUDIO_SAMPLE_RATE_SEL,
+ ATV_AUDIO_RATE_48K, &cmd_status);
+error:
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int pm_video_suspend(struct poseidon *pd)
+{
+ /* stop audio */
+ pm_alsa_suspend(pd);
+
+ /* stop and free all the URBs */
+ usb_transfer_stop(&pd->video_data);
+ free_all_urb(&pd->video_data);
+
+ /* reset the interface */
+ usb_set_interface(pd->udev, 0, 0);
+ msleep(300);
+ return 0;
+}
+
+static int restore_v4l2_context(struct poseidon *pd,
+ struct running_context *context)
+{
+ struct front_face *front = pd->video_data.front;
+
+ pd_video_checkmode(pd);
+
+ set_std(pd, context->tvnormid);
+ vidioc_s_input(NULL, front, context->sig_index);
+ pd_vidioc_s_tuner(pd, context->audio_idx);
+ pd_vidioc_s_fmt(pd, &context->pix);
+ set_frequency(pd, &context->freq);
+ return 0;
+}
+
+static int pm_video_resume(struct poseidon *pd)
+{
+ struct video_data *video = &pd->video_data;
+
+ /* resume the video */
+ /* [1] restore the origin V4L2 parameters */
+ restore_v4l2_context(pd, &video->context);
+
+ /* [2] initiate video copy variables */
+ if (video->front->curr_frame)
+ init_copy(video, 0);
+
+ /* [3] fire urbs */
+ start_video_stream(pd);
+
+ /* resume the audio */
+ pm_alsa_resume(pd);
+ return 0;
+}
+#endif
+
+void set_debug_mode(struct video_device *vfd, int debug_mode)
+{
+ vfd->debug = 0;
+ if (debug_mode & 0x1)
+ vfd->debug = V4L2_DEBUG_IOCTL;
+ if (debug_mode & 0x2)
+ vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
+}
+
+static void init_video_context(struct running_context *context)
+{
+ context->sig_index = 0;
+ context->audio_idx = 1; /* stereo */
+ context->tvnormid = V4L2_STD_PAL_D;
+ context->pix = (struct v4l2_pix_format) {
+ .width = 720,
+ .height = 576,
+ .pixelformat = V4L2_PIX_FMT_YUYV,
+ .field = V4L2_FIELD_INTERLACED,
+ .bytesperline = 720 * 2,
+ .sizeimage = 720 * 576 * 2,
+ .colorspace = V4L2_COLORSPACE_SMPTE170M,
+ };
+}
+
+static int pd_video_open(struct file *file)
+{
+ struct video_device *vfd = video_devdata(file);
+ struct poseidon *pd = video_get_drvdata(vfd);
+ struct front_face *front = NULL;
+ int ret = -ENOMEM;
+
+ mutex_lock(&pd->lock);
+ usb_autopm_get_interface(pd->interface);
+
+ if (pd->state && !(pd->state & POSEIDON_STATE_ANALOG)) {
+ ret = -EBUSY;
+ goto out;
+ }
+ front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
+ if (!front)
+ goto out;
+ if (vfd->vfl_type == VFL_TYPE_GRABBER) {
+ pd->cur_transfer_mode = usb_transfer_mode;/* bulk or iso */
+ init_video_context(&pd->video_data.context);
+
+ ret = pd_video_checkmode(pd);
+ if (ret < 0) {
+ kfree(front);
+ ret = -1;
+ goto out;
+ }
+
+ front->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ pd->video_data.users++;
+ set_debug_mode(vfd, debug_mode);
+
+ videobuf_queue_vmalloc_init(&front->q, &pd_video_qops,
+ NULL, &front->queue_lock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_INTERLACED,/* video is interlacd */
+ sizeof(struct videobuf_buffer),/*it's enough*/
+ front, NULL);
+ } else {
+ front->type = V4L2_BUF_TYPE_VBI_CAPTURE;
+ pd->vbi_data.front = front;
+ pd->vbi_data.users++;
+
+ videobuf_queue_vmalloc_init(&front->q, &pd_video_qops,
+ NULL, &front->queue_lock,
+ V4L2_BUF_TYPE_VBI_CAPTURE,
+ V4L2_FIELD_NONE, /* vbi is NONE mode */
+ sizeof(struct videobuf_buffer),
+ front, NULL);
+ }
+
+ pd->state |= POSEIDON_STATE_ANALOG;
+ front->pd = pd;
+ front->curr_frame = NULL;
+ INIT_LIST_HEAD(&front->active);
+ spin_lock_init(&front->queue_lock);
+
+ file->private_data = front;
+ kref_get(&pd->kref);
+
+ mutex_unlock(&pd->lock);
+ return 0;
+out:
+ usb_autopm_put_interface(pd->interface);
+ mutex_unlock(&pd->lock);
+ return ret;
+}
+
+static int pd_video_release(struct file *file)
+{
+ struct front_face *front = file->private_data;
+ struct poseidon *pd = front->pd;
+ s32 cmd_status = 0;
+
+ mutex_lock(&pd->lock);
+
+ if (front->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+ /* stop the device, and free the URBs */
+ usb_transfer_stop(&pd->video_data);
+ free_all_urb(&pd->video_data);
+
+ /* stop the firmware */
+ send_set_req(pd, PLAY_SERVICE, TLG_TUNE_PLAY_SVC_STOP,
+ &cmd_status);
+
+ pd->file_for_stream = NULL;
+ pd->video_data.users--;
+ } else if (front->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+ pd->vbi_data.front = NULL;
+ pd->vbi_data.users--;
+ }
+ if (!pd->vbi_data.users && !pd->video_data.users)
+ pd->state &= ~POSEIDON_STATE_ANALOG;
+ videobuf_stop(&front->q);
+ videobuf_mmap_free(&front->q);
+
+ usb_autopm_put_interface(pd->interface);
+ mutex_unlock(&pd->lock);
+
+ kfree(front);
+ file->private_data = NULL;
+ kref_put(&pd->kref, poseidon_delete);
+ return 0;
+}
+
+static int pd_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct front_face *front = file->private_data;
+ return videobuf_mmap_mapper(&front->q, vma);
+}
+
+static unsigned int pd_video_poll(struct file *file, poll_table *table)
+{
+ struct front_face *front = file->private_data;
+ return videobuf_poll_stream(file, &front->q, table);
+}
+
+static ssize_t pd_video_read(struct file *file, char __user *buffer,
+ size_t count, loff_t *ppos)
+{
+ struct front_face *front = file->private_data;
+ return videobuf_read_stream(&front->q, buffer, count, ppos,
+ 0, file->f_flags & O_NONBLOCK);
+}
+
+/* This struct works for both VIDEO and VBI */
+static const struct v4l2_file_operations pd_video_fops = {
+ .owner = THIS_MODULE,
+ .open = pd_video_open,
+ .release = pd_video_release,
+ .read = pd_video_read,
+ .poll = pd_video_poll,
+ .mmap = pd_video_mmap,
+ .ioctl = video_ioctl2, /* maybe changed in future */
+};
+
+static const struct v4l2_ioctl_ops pd_video_ioctl_ops = {
+ .vidioc_querycap = vidioc_querycap,
+
+ /* Video format */
+ .vidioc_g_fmt_vid_cap = vidioc_g_fmt,
+ .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt,
+ .vidioc_s_fmt_vid_cap = vidioc_s_fmt,
+ .vidioc_g_fmt_vbi_cap = vidioc_g_fmt_vbi, /* VBI */
+
+ /* Input */
+ .vidioc_g_input = vidioc_g_input,
+ .vidioc_s_input = vidioc_s_input,
+ .vidioc_enum_input = vidioc_enum_input,
+
+ /* Audio ioctls */
+ .vidioc_enumaudio = vidioc_enumaudio,
+ .vidioc_g_audio = vidioc_g_audio,
+ .vidioc_s_audio = vidioc_s_audio,
+
+ /* Tuner ioctls */
+ .vidioc_g_tuner = vidioc_g_tuner,
+ .vidioc_s_tuner = vidioc_s_tuner,
+ .vidioc_g_std = vidioc_g_std,
+ .vidioc_s_std = vidioc_s_std,
+ .vidioc_g_frequency = vidioc_g_frequency,
+ .vidioc_s_frequency = vidioc_s_frequency,
+
+ /* Buffer handlers */
+ .vidioc_reqbufs = vidioc_reqbufs,
+ .vidioc_querybuf = vidioc_querybuf,
+ .vidioc_qbuf = vidioc_qbuf,
+ .vidioc_dqbuf = vidioc_dqbuf,
+
+ /* Stream on/off */
+ .vidioc_streamon = vidioc_streamon,
+ .vidioc_streamoff = vidioc_streamoff,
+};
+
+static struct video_device pd_video_template = {
+ .name = "Telegent-Video",
+ .fops = &pd_video_fops,
+ .minor = -1,
+ .release = video_device_release_empty,
+ .tvnorms = V4L2_STD_ALL,
+ .ioctl_ops = &pd_video_ioctl_ops,
+};
+
+static const struct v4l2_ctrl_ops tlg_ctrl_ops = {
+ .s_ctrl = tlg_s_ctrl,
+};
+
+void pd_video_exit(struct poseidon *pd)
+{
+ struct video_data *video = &pd->video_data;
+ struct vbi_data *vbi = &pd->vbi_data;
+
+ video_unregister_device(&video->v_dev);
+ video_unregister_device(&vbi->v_dev);
+ v4l2_ctrl_handler_free(&video->ctrl_handler);
+ log();
+}
+
+int pd_video_init(struct poseidon *pd)
+{
+ struct video_data *video = &pd->video_data;
+ struct vbi_data *vbi = &pd->vbi_data;
+ struct v4l2_ctrl_handler *hdl = &video->ctrl_handler;
+ u32 freq = TUNER_FREQ_MIN / 62500;
+ int ret = -ENOMEM;
+
+ v4l2_ctrl_handler_init(hdl, 4);
+ v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_BRIGHTNESS,
+ 0, 10000, 1, 100);
+ v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_CONTRAST,
+ 0, 10000, 1, 100);
+ v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_HUE,
+ 0, 10000, 1, 100);
+ v4l2_ctrl_new_std(hdl, &tlg_ctrl_ops, V4L2_CID_SATURATION,
+ 0, 10000, 1, 100);
+ if (hdl->error) {
+ v4l2_ctrl_handler_free(hdl);
+ return hdl->error;
+ }
+ set_frequency(pd, &freq);
+ video->v_dev = pd_video_template;
+ video->v_dev.v4l2_dev = &pd->v4l2_dev;
+ video->v_dev.ctrl_handler = hdl;
+ video_set_drvdata(&video->v_dev, pd);
+
+ ret = video_register_device(&video->v_dev, VFL_TYPE_GRABBER, -1);
+ if (ret != 0)
+ goto out;
+
+ /* VBI uses the same template as video */
+ vbi->v_dev = pd_video_template;
+ vbi->v_dev.v4l2_dev = &pd->v4l2_dev;
+ vbi->v_dev.ctrl_handler = hdl;
+ video_set_drvdata(&vbi->v_dev, pd);
+ ret = video_register_device(&vbi->v_dev, VFL_TYPE_VBI, -1);
+ if (ret != 0)
+ goto out;
+ log("register VIDEO/VBI devices");
+ return 0;
+out:
+ log("VIDEO/VBI devices register failed, : %d", ret);
+ pd_video_exit(pd);
+ return ret;
+}
diff --git a/drivers/media/usb/tlg2300/vendorcmds.h b/drivers/media/usb/tlg2300/vendorcmds.h
new file mode 100644
index 0000000..ba6f4ae
--- /dev/null
+++ b/drivers/media/usb/tlg2300/vendorcmds.h
@@ -0,0 +1,243 @@
+#ifndef VENDOR_CMD_H_
+#define VENDOR_CMD_H_
+
+#define BULK_ALTERNATE_IFACE (2)
+#define ISO_3K_BULK_ALTERNATE_IFACE (1)
+#define REQ_SET_CMD (0X00)
+#define REQ_GET_CMD (0X80)
+
+enum tlg__analog_audio_standard {
+ TLG_TUNE_ASTD_NONE = 0x00000000,
+ TLG_TUNE_ASTD_A2 = 0x00000001,
+ TLG_TUNE_ASTD_NICAM = 0x00000002,
+ TLG_TUNE_ASTD_EIAJ = 0x00000004,
+ TLG_TUNE_ASTD_BTSC = 0x00000008,
+ TLG_TUNE_ASTD_FM_US = 0x00000010,
+ TLG_TUNE_ASTD_FM_EUR = 0x00000020,
+ TLG_TUNE_ASTD_ALL = 0x0000003f
+};
+
+/*
+ * identifiers for Custom Parameter messages.
+ * @typedef cmd_custom_param_id_t
+ */
+enum cmd_custom_param_id {
+ CUST_PARM_ID_NONE = 0x00,
+ CUST_PARM_ID_BRIGHTNESS_CTRL = 0x01,
+ CUST_PARM_ID_CONTRAST_CTRL = 0x02,
+ CUST_PARM_ID_HUE_CTRL = 0x03,
+ CUST_PARM_ID_SATURATION_CTRL = 0x04,
+ CUST_PARM_ID_AUDIO_SNR_THRESHOLD = 0x10,
+ CUST_PARM_ID_AUDIO_AGC_THRESHOLD = 0x11,
+ CUST_PARM_ID_MAX
+};
+
+struct tuner_custom_parameter_s {
+ uint16_t param_id; /* Parameter identifier */
+ uint16_t param_value; /* Parameter value */
+};
+
+struct tuner_ber_rate_s {
+ uint32_t ber_rate; /* BER sample rate in seconds */
+};
+
+struct tuner_atv_sig_stat_s {
+ uint32_t sig_present;
+ uint32_t sig_locked;
+ uint32_t sig_lock_busy;
+ uint32_t sig_strength; /* milliDb */
+ uint32_t tv_audio_chan; /* mono/stereo/sap*/
+ uint32_t mvision_stat; /* macrovision status */
+};
+
+struct tuner_dtv_sig_stat_s {
+ uint32_t sig_present; /* Boolean*/
+ uint32_t sig_locked; /* Boolean */
+ uint32_t sig_lock_busy; /* Boolean (Can this time-out?) */
+ uint32_t sig_strength; /* milliDb*/
+};
+
+struct tuner_fm_sig_stat_s {
+ uint32_t sig_present; /* Boolean*/
+ uint32_t sig_locked; /* Boolean */
+ uint32_t sig_lock_busy; /* Boolean */
+ uint32_t sig_stereo_mono;/* TBD*/
+ uint32_t sig_strength; /* milliDb*/
+};
+
+enum _tag_tlg_tune_srv_cmd {
+ TLG_TUNE_PLAY_SVC_START = 1,
+ TLG_TUNE_PLAY_SVC_STOP
+};
+
+enum _tag_tune_atv_audio_mode_caps {
+ TLG_TUNE_TVAUDIO_MODE_MONO = 0x00000001,
+ TLG_TUNE_TVAUDIO_MODE_STEREO = 0x00000002,
+ TLG_TUNE_TVAUDIO_MODE_LANG_A = 0x00000010,/* Primary language*/
+ TLG_TUNE_TVAUDIO_MODE_LANG_B = 0x00000020,/* 2nd avail language*/
+ TLG_TUNE_TVAUDIO_MODE_LANG_C = 0x00000040
+};
+
+
+enum _tag_tuner_atv_audio_rates {
+ ATV_AUDIO_RATE_NONE = 0x00,/* Audio not supported*/
+ ATV_AUDIO_RATE_32K = 0x01,/* Audio rate = 32 KHz*/
+ ATV_AUDIO_RATE_48K = 0x02, /* Audio rate = 48 KHz*/
+ ATV_AUDIO_RATE_31_25K = 0x04 /* Audio rate = 31.25KHz */
+};
+
+enum _tag_tune_atv_vid_res_caps {
+ TLG_TUNE_VID_RES_NONE = 0x00000000,
+ TLG_TUNE_VID_RES_720 = 0x00000001,
+ TLG_TUNE_VID_RES_704 = 0x00000002,
+ TLG_TUNE_VID_RES_360 = 0x00000004
+};
+
+enum _tag_tuner_analog_video_format {
+ TLG_TUNER_VID_FORMAT_YUV = 0x00000001,
+ TLG_TUNER_VID_FORMAT_YCRCB = 0x00000002,
+ TLG_TUNER_VID_FORMAT_RGB_565 = 0x00000004,
+};
+
+enum tlg_ext_audio_support {
+ TLG_EXT_AUDIO_NONE = 0x00,/* No external audio input supported */
+ TLG_EXT_AUDIO_LR = 0x01/* LR external audio inputs supported*/
+};
+
+enum {
+ TLG_MODE_NONE = 0x00, /* No Mode specified*/
+ TLG_MODE_ANALOG_TV = 0x01, /* Analog Television mode*/
+ TLG_MODE_ANALOG_TV_UNCOMP = 0x01, /* Analog Television mode*/
+ TLG_MODE_ANALOG_TV_COMP = 0x02, /* Analog TV mode (compressed)*/
+ TLG_MODE_FM_RADIO = 0x04, /* FM Radio mode*/
+ TLG_MODE_DVB_T = 0x08, /* Digital TV (DVB-T)*/
+};
+
+enum tlg_signal_sources_t {
+ TLG_SIG_SRC_NONE = 0x00,/* Signal source not specified */
+ TLG_SIG_SRC_ANTENNA = 0x01,/* Signal src is: Antenna */
+ TLG_SIG_SRC_CABLE = 0x02,/* Signal src is: Coax Cable*/
+ TLG_SIG_SRC_SVIDEO = 0x04,/* Signal src is: S_VIDEO */
+ TLG_SIG_SRC_COMPOSITE = 0x08 /* Signal src is: Composite Video */
+};
+
+enum tuner_analog_video_standard {
+ TLG_TUNE_VSTD_NONE = 0x00000000,
+ TLG_TUNE_VSTD_NTSC_M = 0x00000001,
+ TLG_TUNE_VSTD_NTSC_M_J = 0x00000002,/* Japan */
+ TLG_TUNE_VSTD_PAL_B = 0x00000010,
+ TLG_TUNE_VSTD_PAL_D = 0x00000020,
+ TLG_TUNE_VSTD_PAL_G = 0x00000040,
+ TLG_TUNE_VSTD_PAL_H = 0x00000080,
+ TLG_TUNE_VSTD_PAL_I = 0x00000100,
+ TLG_TUNE_VSTD_PAL_M = 0x00000200,
+ TLG_TUNE_VSTD_PAL_N = 0x00000400,
+ TLG_TUNE_VSTD_SECAM_B = 0x00001000,
+ TLG_TUNE_VSTD_SECAM_D = 0x00002000,
+ TLG_TUNE_VSTD_SECAM_G = 0x00004000,
+ TLG_TUNE_VSTD_SECAM_H = 0x00008000,
+ TLG_TUNE_VSTD_SECAM_K = 0x00010000,
+ TLG_TUNE_VSTD_SECAM_K1 = 0x00020000,
+ TLG_TUNE_VSTD_SECAM_L = 0x00040000,
+ TLG_TUNE_VSTD_SECAM_L1 = 0x00080000,
+ TLG_TUNE_VSTD_PAL_N_COMBO = 0x00100000
+};
+
+enum tlg_mode_caps {
+ TLG_MODE_CAPS_NONE = 0x00, /* No Mode specified */
+ TLG_MODE_CAPS_ANALOG_TV_UNCOMP = 0x01, /* Analog TV mode */
+ TLG_MODE_CAPS_ANALOG_TV_COMP = 0x02, /* Analog TV (compressed)*/
+ TLG_MODE_CAPS_FM_RADIO = 0x04, /* FM Radio mode */
+ TLG_MODE_CAPS_DVB_T = 0x08, /* Digital TV (DVB-T) */
+};
+
+enum poseidon_vendor_cmds {
+ LAST_CMD_STAT = 0x00,
+ GET_CHIP_ID = 0x01,
+ GET_FW_ID = 0x02,
+ PRODUCT_CAPS = 0x03,
+
+ TUNE_MODE_CAP_ATV = 0x10,
+ TUNE_MODE_CAP_ATVCOMP = 0X10,
+ TUNE_MODE_CAP_DVBT = 0x10,
+ TUNE_MODE_CAP_FM = 0x10,
+ TUNE_MODE_SELECT = 0x11,
+ TUNE_FREQ_SELECT = 0x12,
+ SGNL_SRC_SEL = 0x13,
+
+ VIDEO_STD_SEL = 0x14,
+ VIDEO_STREAM_FMT_SEL = 0x15,
+ VIDEO_ROSOLU_AVAIL = 0x16,
+ VIDEO_ROSOLU_SEL = 0x17,
+ VIDEO_CONT_PROTECT = 0x20,
+
+ VCR_TIMING_MODSEL = 0x21,
+ EXT_AUDIO_CAP = 0x22,
+ EXT_AUDIO_SEL = 0x23,
+ TEST_PATTERN_SEL = 0x24,
+ VBI_DATA_SEL = 0x25,
+ AUDIO_SAMPLE_RATE_CAP = 0x28,
+ AUDIO_SAMPLE_RATE_SEL = 0x29,
+ TUNER_AUD_MODE = 0x2a,
+ TUNER_AUD_MODE_AVAIL = 0x2b,
+ TUNER_AUD_ANA_STD = 0x2c,
+ TUNER_CUSTOM_PARAMETER = 0x2f,
+
+ DVBT_TUNE_MODE_SEL = 0x30,
+ DVBT_BANDW_CAP = 0x31,
+ DVBT_BANDW_SEL = 0x32,
+ DVBT_GUARD_INTERV_CAP = 0x33,
+ DVBT_GUARD_INTERV_SEL = 0x34,
+ DVBT_MODULATION_CAP = 0x35,
+ DVBT_MODULATION_SEL = 0x36,
+ DVBT_INNER_FEC_RATE_CAP = 0x37,
+ DVBT_INNER_FEC_RATE_SEL = 0x38,
+ DVBT_TRANS_MODE_CAP = 0x39,
+ DVBT_TRANS_MODE_SEL = 0x3a,
+ DVBT_SEARCH_RANG = 0x3c,
+
+ TUNER_SETUP_ANALOG = 0x40,
+ TUNER_SETUP_DIGITAL = 0x41,
+ TUNER_SETUP_FM_RADIO = 0x42,
+ TAKE_REQUEST = 0x43, /* Take effect of the command */
+ PLAY_SERVICE = 0x44, /* Play start or Play stop */
+ TUNER_STATUS = 0x45,
+ TUNE_PROP_DVBT = 0x46,
+ ERR_RATE_STATS = 0x47,
+ TUNER_BER_RATE = 0x48,
+
+ SCAN_CAPS = 0x50,
+ SCAN_SETUP = 0x51,
+ SCAN_SERVICE = 0x52,
+ SCAN_STATS = 0x53,
+
+ PID_SET = 0x58,
+ PID_UNSET = 0x59,
+ PID_LIST = 0x5a,
+
+ IRD_CAP = 0x60,
+ IRD_MODE_SEL = 0x61,
+ IRD_SETUP = 0x62,
+
+ PTM_MODE_CAP = 0x70,
+ PTM_MODE_SEL = 0x71,
+ PTM_SERVICE = 0x72,
+ TUNER_REG_SCRIPT = 0x73,
+ CMD_CHIP_RST = 0x74,
+};
+
+enum tlg_bw {
+ TLG_BW_5 = 5,
+ TLG_BW_6 = 6,
+ TLG_BW_7 = 7,
+ TLG_BW_8 = 8,
+ TLG_BW_12 = 12,
+ TLG_BW_15 = 15
+};
+
+struct cmd_firmware_vers_s {
+ uint8_t fw_rev_major;
+ uint8_t fw_rev_minor;
+ uint16_t fw_patch;
+};
+#endif /* VENDOR_CMD_H_ */
diff --git a/drivers/media/usb/usbvision/usbvision-video.c b/drivers/media/usb/usbvision/usbvision-video.c
index 282f11c..35ee9c3 100644
--- a/drivers/media/usb/usbvision/usbvision-video.c
+++ b/drivers/media/usb/usbvision/usbvision-video.c
@@ -446,7 +446,6 @@
if (usbvision->remove_pending) {
printk(KERN_INFO "%s: Final disconnect\n", __func__);
usbvision_release(usbvision);
- return 0;
}
mutex_unlock(&usbvision->v4l2_lock);
@@ -509,12 +508,11 @@
usbvision_device_data[usbvision->dev_model].model_string,
sizeof(vc->card));
usb_make_path(usbvision->dev, vc->bus_info, sizeof(vc->bus_info));
- vc->device_caps = V4L2_CAP_VIDEO_CAPTURE |
+ vc->capabilities = V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_AUDIO |
V4L2_CAP_READWRITE |
V4L2_CAP_STREAMING |
(usbvision->have_tuner ? V4L2_CAP_TUNER : 0);
- vc->capabilities = vc->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0;
}
@@ -1223,7 +1221,6 @@
if (usbvision->remove_pending) {
printk(KERN_INFO "%s: Final disconnect\n", __func__);
usbvision_release(usbvision);
- return err_code;
}
mutex_unlock(&usbvision->v4l2_lock);
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index 40d6c83..b578d68 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -331,7 +331,6 @@
struct uvc_format_desc *fmtdesc;
struct uvc_frame *frame;
const unsigned char *start = buffer;
- unsigned int width_multiplier = 1;
unsigned int interval;
unsigned int i, n;
__u8 ftype;
@@ -367,20 +366,6 @@
}
format->bpp = buffer[21];
-
- /* Some devices report a format that doesn't match what they
- * really send.
- */
- if (dev->quirks & UVC_QUIRK_FORCE_Y8) {
- if (format->fcc == V4L2_PIX_FMT_YUYV) {
- strlcpy(format->name, "Greyscale 8-bit (Y8 )",
- sizeof(format->name));
- format->fcc = V4L2_PIX_FMT_GREY;
- format->bpp = 8;
- width_multiplier = 2;
- }
- }
-
if (buffer[2] == UVC_VS_FORMAT_UNCOMPRESSED) {
ftype = UVC_VS_FRAME_UNCOMPRESSED;
} else {
@@ -489,8 +474,7 @@
frame->bFrameIndex = buffer[3];
frame->bmCapabilities = buffer[4];
- frame->wWidth = get_unaligned_le16(&buffer[5])
- * width_multiplier;
+ frame->wWidth = get_unaligned_le16(&buffer[5]);
frame->wHeight = get_unaligned_le16(&buffer[7]);
frame->dwMinBitRate = get_unaligned_le32(&buffer[9]);
frame->dwMaxBitRate = get_unaligned_le32(&buffer[13]);
@@ -1639,12 +1623,12 @@
{
struct list_head *p, *n;
- uvc_status_cleanup(dev);
- uvc_ctrl_cleanup_device(dev);
-
usb_put_intf(dev->intf);
usb_put_dev(dev->udev);
+ uvc_status_cleanup(dev);
+ uvc_ctrl_cleanup_device(dev);
+
if (dev->vdev.dev)
v4l2_device_unregister(&dev->vdev);
#ifdef CPTCFG_MEDIA_CONTROLLER
@@ -1734,11 +1718,6 @@
struct video_device *vdev;
int ret;
- /* Initialize the video buffers queue. */
- ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
- if (ret)
- return ret;
-
/* Initialize the streaming interface with default streaming
* parameters.
*/
@@ -1765,7 +1744,6 @@
*/
vdev->v4l2_dev = &dev->vdev;
vdev->fops = &uvc_fops;
- vdev->ioctl_ops = &uvc_ioctl_ops;
vdev->release = uvc_release;
vdev->prio = &stream->chain->prio;
if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
@@ -2013,13 +1991,14 @@
{
struct uvc_device *dev = usb_get_intfdata(intf);
struct uvc_streaming *stream;
- int ret = 0;
uvc_trace(UVC_TRACE_SUSPEND, "Resuming interface %u\n",
intf->cur_altsetting->desc.bInterfaceNumber);
if (intf->cur_altsetting->desc.bInterfaceSubClass ==
UVC_SC_VIDEOCONTROL) {
+ int ret = 0;
+
if (reset) {
ret = uvc_ctrl_restore_values(dev);
if (ret < 0)
@@ -2035,13 +2014,8 @@
}
list_for_each_entry(stream, &dev->streams, list) {
- if (stream->intf == intf) {
- ret = uvc_video_resume(stream, reset);
- if (ret < 0)
- uvc_queue_streamoff(&stream->queue,
- stream->queue.queue.type);
- return ret;
- }
+ if (stream->intf == intf)
+ return uvc_video_resume(stream, reset);
}
uvc_trace(UVC_TRACE_SUSPEND, "Resume: video streaming USB interface "
@@ -2530,15 +2504,6 @@
.bInterfaceProtocol = 0,
.driver_info = UVC_QUIRK_PROBE_MINMAX
| UVC_QUIRK_IGNORE_SELECTOR_UNIT },
- /* Oculus VR Positional Tracker DK2 */
- { .match_flags = USB_DEVICE_ID_MATCH_DEVICE
- | USB_DEVICE_ID_MATCH_INT_INFO,
- .idVendor = 0x2833,
- .idProduct = 0x0201,
- .bInterfaceClass = USB_CLASS_VIDEO,
- .bInterfaceSubClass = 1,
- .bInterfaceProtocol = 0,
- .driver_info = UVC_QUIRK_FORCE_Y8 },
/* Generic USB Video Class */
{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },
{}
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c
index cc96072..6e92d20 100644
--- a/drivers/media/usb/uvc/uvc_queue.c
+++ b/drivers/media/usb/uvc/uvc_queue.c
@@ -36,34 +36,6 @@
* the driver.
*/
-static inline struct uvc_streaming *
-uvc_queue_to_stream(struct uvc_video_queue *queue)
-{
- return container_of(queue, struct uvc_streaming, queue);
-}
-
-/*
- * Return all queued buffers to videobuf2 in the requested state.
- *
- * This function must be called with the queue spinlock held.
- */
-static void uvc_queue_return_buffers(struct uvc_video_queue *queue,
- enum uvc_buffer_state state)
-{
- enum vb2_buffer_state vb2_state = state == UVC_BUF_STATE_ERROR
- ? VB2_BUF_STATE_ERROR
- : VB2_BUF_STATE_QUEUED;
-
- while (!list_empty(&queue->irqqueue)) {
- struct uvc_buffer *buf = list_first_entry(&queue->irqqueue,
- struct uvc_buffer,
- queue);
- list_del(&buf->queue);
- buf->state = state;
- vb2_buffer_done(&buf->buf, vb2_state);
- }
-}
-
/* -----------------------------------------------------------------------------
* videobuf2 queue operations
*/
@@ -73,7 +45,8 @@
unsigned int sizes[], void *alloc_ctxs[])
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
- struct uvc_streaming *stream = uvc_queue_to_stream(queue);
+ struct uvc_streaming *stream =
+ container_of(queue, struct uvc_streaming, queue);
/* Make sure the image size is large enough. */
if (fmt && fmt->fmt.pix.sizeimage < stream->ctrl.dwMaxVideoFrameSize)
@@ -136,7 +109,8 @@
static void uvc_buffer_finish(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
- struct uvc_streaming *stream = uvc_queue_to_stream(queue);
+ struct uvc_streaming *stream =
+ container_of(queue, struct uvc_streaming, queue);
struct uvc_buffer *buf = container_of(vb, struct uvc_buffer, buf);
if (vb->state == VB2_BUF_STATE_DONE)
@@ -157,39 +131,6 @@
mutex_lock(&queue->mutex);
}
-static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count)
-{
- struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
- struct uvc_streaming *stream = uvc_queue_to_stream(queue);
- unsigned long flags;
- int ret;
-
- queue->buf_used = 0;
-
- ret = uvc_video_enable(stream, 1);
- if (ret == 0)
- return 0;
-
- spin_lock_irqsave(&queue->irqlock, flags);
- uvc_queue_return_buffers(queue, UVC_BUF_STATE_QUEUED);
- spin_unlock_irqrestore(&queue->irqlock, flags);
-
- return ret;
-}
-
-static void uvc_stop_streaming(struct vb2_queue *vq)
-{
- struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
- struct uvc_streaming *stream = uvc_queue_to_stream(queue);
- unsigned long flags;
-
- uvc_video_enable(stream, 0);
-
- spin_lock_irqsave(&queue->irqlock, flags);
- uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR);
- spin_unlock_irqrestore(&queue->irqlock, flags);
-}
-
static struct vb2_ops uvc_queue_qops = {
.queue_setup = uvc_queue_setup,
.buf_prepare = uvc_buffer_prepare,
@@ -197,8 +138,6 @@
.buf_finish = uvc_buffer_finish,
.wait_prepare = uvc_wait_prepare,
.wait_finish = uvc_wait_finish,
- .start_streaming = uvc_start_streaming,
- .stop_streaming = uvc_stop_streaming,
};
int uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type,
@@ -226,19 +165,12 @@
return 0;
}
-void uvc_queue_release(struct uvc_video_queue *queue)
-{
- mutex_lock(&queue->mutex);
- vb2_queue_release(&queue->queue);
- mutex_unlock(&queue->mutex);
-}
-
/* -----------------------------------------------------------------------------
* V4L2 queue operations
*/
-int uvc_request_buffers(struct uvc_video_queue *queue,
- struct v4l2_requestbuffers *rb)
+int uvc_alloc_buffers(struct uvc_video_queue *queue,
+ struct v4l2_requestbuffers *rb)
{
int ret;
@@ -249,6 +181,13 @@
return ret ? ret : rb->count;
}
+void uvc_free_buffers(struct uvc_video_queue *queue)
+{
+ mutex_lock(&queue->mutex);
+ vb2_queue_release(&queue->queue);
+ mutex_unlock(&queue->mutex);
+}
+
int uvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
{
int ret;
@@ -295,28 +234,6 @@
return ret;
}
-int uvc_queue_streamon(struct uvc_video_queue *queue, enum v4l2_buf_type type)
-{
- int ret;
-
- mutex_lock(&queue->mutex);
- ret = vb2_streamon(&queue->queue, type);
- mutex_unlock(&queue->mutex);
-
- return ret;
-}
-
-int uvc_queue_streamoff(struct uvc_video_queue *queue, enum v4l2_buf_type type)
-{
- int ret;
-
- mutex_lock(&queue->mutex);
- ret = vb2_streamoff(&queue->queue, type);
- mutex_unlock(&queue->mutex);
-
- return ret;
-}
-
int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
{
int ret;
@@ -372,6 +289,49 @@
}
/*
+ * Enable or disable the video buffers queue.
+ *
+ * The queue must be enabled before starting video acquisition and must be
+ * disabled after stopping it. This ensures that the video buffers queue
+ * state can be properly initialized before buffers are accessed from the
+ * interrupt handler.
+ *
+ * Enabling the video queue returns -EBUSY if the queue is already enabled.
+ *
+ * Disabling the video queue cancels the queue and removes all buffers from
+ * the main queue.
+ *
+ * This function can't be called from interrupt context. Use
+ * uvc_queue_cancel() instead.
+ */
+int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
+{
+ unsigned long flags;
+ int ret;
+
+ mutex_lock(&queue->mutex);
+ if (enable) {
+ ret = vb2_streamon(&queue->queue, queue->queue.type);
+ if (ret < 0)
+ goto done;
+
+ queue->buf_used = 0;
+ } else {
+ ret = vb2_streamoff(&queue->queue, queue->queue.type);
+ if (ret < 0)
+ goto done;
+
+ spin_lock_irqsave(&queue->irqlock, flags);
+ INIT_LIST_HEAD(&queue->irqqueue);
+ spin_unlock_irqrestore(&queue->irqlock, flags);
+ }
+
+done:
+ mutex_unlock(&queue->mutex);
+ return ret;
+}
+
+/*
* Cancel the video buffers queue.
*
* Cancelling the queue marks all buffers on the irq queue as erroneous,
@@ -385,10 +345,17 @@
*/
void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
{
+ struct uvc_buffer *buf;
unsigned long flags;
spin_lock_irqsave(&queue->irqlock, flags);
- uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR);
+ while (!list_empty(&queue->irqqueue)) {
+ buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
+ queue);
+ list_del(&buf->queue);
+ buf->state = UVC_BUF_STATE_ERROR;
+ vb2_buffer_done(&buf->buf, VB2_BUF_STATE_ERROR);
+ }
/* This must be protected by the irqlock spinlock to avoid race
* conditions between uvc_buffer_queue and the disconnection event that
* could result in an interruptible wait in uvc_dequeue_buffer. Do not
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index 9c5cbcf..60a8e2c 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -318,6 +318,7 @@
stream->ctrl = probe;
stream->cur_format = format;
stream->cur_frame = frame;
+ stream->frame_size = fmt->fmt.pix.sizeimage;
done:
mutex_unlock(&stream->mutex);
@@ -530,8 +531,10 @@
uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_release\n");
/* Only free resources if this is a privileged handle. */
- if (uvc_has_privileges(handle))
- uvc_queue_release(&stream->queue);
+ if (uvc_has_privileges(handle)) {
+ uvc_video_enable(stream, 0);
+ uvc_free_buffers(&stream->queue);
+ }
/* Release the file handle. */
uvc_dismiss_privileges(handle);
@@ -549,628 +552,553 @@
return 0;
}
-static int uvc_ioctl_querycap(struct file *file, void *fh,
- struct v4l2_capability *cap)
+static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
struct uvc_fh *handle = file->private_data;
struct uvc_video_chain *chain = handle->chain;
struct uvc_streaming *stream = handle->stream;
-
- strlcpy(cap->driver, "uvcvideo", sizeof(cap->driver));
- strlcpy(cap->card, vdev->name, sizeof(cap->card));
- usb_make_path(stream->dev->udev, cap->bus_info, sizeof(cap->bus_info));
- cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
- | chain->caps;
- if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
- cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
- else
- cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
-
- return 0;
-}
-
-static int uvc_ioctl_enum_fmt(struct uvc_streaming *stream,
- struct v4l2_fmtdesc *fmt)
-{
- struct uvc_format *format;
- enum v4l2_buf_type type = fmt->type;
- __u32 index = fmt->index;
-
- if (fmt->type != stream->type || fmt->index >= stream->nformats)
- return -EINVAL;
-
- memset(fmt, 0, sizeof(*fmt));
- fmt->index = index;
- fmt->type = type;
-
- format = &stream->format[fmt->index];
- fmt->flags = 0;
- if (format->flags & UVC_FMT_FLAG_COMPRESSED)
- fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
- strlcpy(fmt->description, format->name, sizeof(fmt->description));
- fmt->description[sizeof(fmt->description) - 1] = 0;
- fmt->pixelformat = format->fcc;
- return 0;
-}
-
-static int uvc_ioctl_enum_fmt_vid_cap(struct file *file, void *fh,
- struct v4l2_fmtdesc *fmt)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- return uvc_ioctl_enum_fmt(stream, fmt);
-}
-
-static int uvc_ioctl_enum_fmt_vid_out(struct file *file, void *fh,
- struct v4l2_fmtdesc *fmt)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- return uvc_ioctl_enum_fmt(stream, fmt);
-}
-
-static int uvc_ioctl_g_fmt_vid_cap(struct file *file, void *fh,
- struct v4l2_format *fmt)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- return uvc_v4l2_get_format(stream, fmt);
-}
-
-static int uvc_ioctl_g_fmt_vid_out(struct file *file, void *fh,
- struct v4l2_format *fmt)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- return uvc_v4l2_get_format(stream, fmt);
-}
-
-static int uvc_ioctl_s_fmt_vid_cap(struct file *file, void *fh,
- struct v4l2_format *fmt)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- int ret;
-
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
-
- return uvc_v4l2_set_format(stream, fmt);
-}
-
-static int uvc_ioctl_s_fmt_vid_out(struct file *file, void *fh,
- struct v4l2_format *fmt)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- int ret;
-
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
-
- return uvc_v4l2_set_format(stream, fmt);
-}
-
-static int uvc_ioctl_try_fmt_vid_cap(struct file *file, void *fh,
- struct v4l2_format *fmt)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- struct uvc_streaming_control probe;
-
- return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
-}
-
-static int uvc_ioctl_try_fmt_vid_out(struct file *file, void *fh,
- struct v4l2_format *fmt)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- struct uvc_streaming_control probe;
-
- return uvc_v4l2_try_format(stream, fmt, &probe, NULL, NULL);
-}
-
-static int uvc_ioctl_reqbufs(struct file *file, void *fh,
- struct v4l2_requestbuffers *rb)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- int ret;
-
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
-
- mutex_lock(&stream->mutex);
- ret = uvc_request_buffers(&stream->queue, rb);
- mutex_unlock(&stream->mutex);
- if (ret < 0)
- return ret;
-
- if (ret == 0)
- uvc_dismiss_privileges(handle);
-
- return 0;
-}
-
-static int uvc_ioctl_querybuf(struct file *file, void *fh,
- struct v4l2_buffer *buf)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- return uvc_query_buffer(&stream->queue, buf);
-}
-
-static int uvc_ioctl_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- return uvc_queue_buffer(&stream->queue, buf);
-}
-
-static int uvc_ioctl_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- return uvc_dequeue_buffer(&stream->queue, buf,
- file->f_flags & O_NONBLOCK);
-}
-
-static int uvc_ioctl_create_bufs(struct file *file, void *fh,
- struct v4l2_create_buffers *cb)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- int ret;
-
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
-
- return uvc_create_buffers(&stream->queue, cb);
-}
-
-static int uvc_ioctl_streamon(struct file *file, void *fh,
- enum v4l2_buf_type type)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- int ret;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- mutex_lock(&stream->mutex);
- ret = uvc_queue_streamon(&stream->queue, type);
- mutex_unlock(&stream->mutex);
-
- return ret;
-}
-
-static int uvc_ioctl_streamoff(struct file *file, void *fh,
- enum v4l2_buf_type type)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- if (!uvc_has_privileges(handle))
- return -EBUSY;
-
- mutex_lock(&stream->mutex);
- uvc_queue_streamoff(&stream->queue, type);
- mutex_unlock(&stream->mutex);
-
- return 0;
-}
-
-static int uvc_ioctl_enum_input(struct file *file, void *fh,
- struct v4l2_input *input)
-{
- struct uvc_fh *handle = fh;
- struct uvc_video_chain *chain = handle->chain;
- const struct uvc_entity *selector = chain->selector;
- struct uvc_entity *iterm = NULL;
- u32 index = input->index;
- int pin = 0;
-
- if (selector == NULL ||
- (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
- if (index != 0)
- return -EINVAL;
- list_for_each_entry(iterm, &chain->entities, chain) {
- if (UVC_ENTITY_IS_ITERM(iterm))
- break;
- }
- pin = iterm->id;
- } else if (index < selector->bNrInPins) {
- pin = selector->baSourceID[index];
- list_for_each_entry(iterm, &chain->entities, chain) {
- if (!UVC_ENTITY_IS_ITERM(iterm))
- continue;
- if (iterm->id == pin)
- break;
- }
- }
-
- if (iterm == NULL || iterm->id != pin)
- return -EINVAL;
-
- memset(input, 0, sizeof(*input));
- input->index = index;
- strlcpy(input->name, iterm->name, sizeof(input->name));
- if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
- input->type = V4L2_INPUT_TYPE_CAMERA;
-
- return 0;
-}
-
-static int uvc_ioctl_g_input(struct file *file, void *fh, unsigned int *input)
-{
- struct uvc_fh *handle = fh;
- struct uvc_video_chain *chain = handle->chain;
- int ret;
- u8 i;
-
- if (chain->selector == NULL ||
- (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
- *input = 0;
- return 0;
- }
-
- ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR, chain->selector->id,
- chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
- &i, 1);
- if (ret < 0)
- return ret;
-
- *input = i - 1;
- return 0;
-}
-
-static int uvc_ioctl_s_input(struct file *file, void *fh, unsigned int input)
-{
- struct uvc_fh *handle = fh;
- struct uvc_video_chain *chain = handle->chain;
- int ret;
- u32 i;
-
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
-
- if (chain->selector == NULL ||
- (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
- if (input)
- return -EINVAL;
- return 0;
- }
-
- if (input >= chain->selector->bNrInPins)
- return -EINVAL;
-
- i = input + 1;
- return uvc_query_ctrl(chain->dev, UVC_SET_CUR, chain->selector->id,
- chain->dev->intfnum, UVC_SU_INPUT_SELECT_CONTROL,
- &i, 1);
-}
-
-static int uvc_ioctl_queryctrl(struct file *file, void *fh,
- struct v4l2_queryctrl *qc)
-{
- struct uvc_fh *handle = fh;
- struct uvc_video_chain *chain = handle->chain;
-
- return uvc_query_v4l2_ctrl(chain, qc);
-}
-
-static int uvc_ioctl_g_ctrl(struct file *file, void *fh,
- struct v4l2_control *ctrl)
-{
- struct uvc_fh *handle = fh;
- struct uvc_video_chain *chain = handle->chain;
- struct v4l2_ext_control xctrl;
- int ret;
-
- memset(&xctrl, 0, sizeof(xctrl));
- xctrl.id = ctrl->id;
-
- ret = uvc_ctrl_begin(chain);
- if (ret < 0)
- return ret;
-
- ret = uvc_ctrl_get(chain, &xctrl);
- uvc_ctrl_rollback(handle);
- if (ret < 0)
- return ret;
-
- ctrl->value = xctrl.value;
- return 0;
-}
-
-static int uvc_ioctl_s_ctrl(struct file *file, void *fh,
- struct v4l2_control *ctrl)
-{
- struct uvc_fh *handle = fh;
- struct uvc_video_chain *chain = handle->chain;
- struct v4l2_ext_control xctrl;
- int ret;
-
- memset(&xctrl, 0, sizeof(xctrl));
- xctrl.id = ctrl->id;
- xctrl.value = ctrl->value;
-
- ret = uvc_ctrl_begin(chain);
- if (ret < 0)
- return ret;
-
- ret = uvc_ctrl_set(chain, &xctrl);
- if (ret < 0) {
- uvc_ctrl_rollback(handle);
- return ret;
- }
-
- ret = uvc_ctrl_commit(handle, &xctrl, 1);
- if (ret < 0)
- return ret;
-
- ctrl->value = xctrl.value;
- return 0;
-}
-
-static int uvc_ioctl_g_ext_ctrls(struct file *file, void *fh,
- struct v4l2_ext_controls *ctrls)
-{
- struct uvc_fh *handle = fh;
- struct uvc_video_chain *chain = handle->chain;
- struct v4l2_ext_control *ctrl = ctrls->controls;
- unsigned int i;
- int ret;
-
- ret = uvc_ctrl_begin(chain);
- if (ret < 0)
- return ret;
-
- for (i = 0; i < ctrls->count; ++ctrl, ++i) {
- ret = uvc_ctrl_get(chain, ctrl);
- if (ret < 0) {
- uvc_ctrl_rollback(handle);
- ctrls->error_idx = i;
- return ret;
- }
- }
-
- ctrls->error_idx = 0;
-
- return uvc_ctrl_rollback(handle);
-}
-
-static int uvc_ioctl_s_try_ext_ctrls(struct uvc_fh *handle,
- struct v4l2_ext_controls *ctrls,
- bool commit)
-{
- struct v4l2_ext_control *ctrl = ctrls->controls;
- struct uvc_video_chain *chain = handle->chain;
- unsigned int i;
- int ret;
-
- ret = uvc_ctrl_begin(chain);
- if (ret < 0)
- return ret;
-
- for (i = 0; i < ctrls->count; ++ctrl, ++i) {
- ret = uvc_ctrl_set(chain, ctrl);
- if (ret < 0) {
- uvc_ctrl_rollback(handle);
- ctrls->error_idx = commit ? ctrls->count : i;
- return ret;
- }
- }
-
- ctrls->error_idx = 0;
-
- if (commit)
- return uvc_ctrl_commit(handle, ctrls->controls, ctrls->count);
- else
- return uvc_ctrl_rollback(handle);
-}
-
-static int uvc_ioctl_s_ext_ctrls(struct file *file, void *fh,
- struct v4l2_ext_controls *ctrls)
-{
- struct uvc_fh *handle = fh;
-
- return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, true);
-}
-
-static int uvc_ioctl_try_ext_ctrls(struct file *file, void *fh,
- struct v4l2_ext_controls *ctrls)
-{
- struct uvc_fh *handle = fh;
-
- return uvc_ioctl_s_try_ext_ctrls(handle, ctrls, false);
-}
-
-static int uvc_ioctl_querymenu(struct file *file, void *fh,
- struct v4l2_querymenu *qm)
-{
- struct uvc_fh *handle = fh;
- struct uvc_video_chain *chain = handle->chain;
-
- return uvc_query_v4l2_menu(chain, qm);
-}
-
-static int uvc_ioctl_cropcap(struct file *file, void *fh,
- struct v4l2_cropcap *ccap)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- if (ccap->type != stream->type)
- return -EINVAL;
-
- ccap->bounds.left = 0;
- ccap->bounds.top = 0;
- mutex_lock(&stream->mutex);
- ccap->bounds.width = stream->cur_frame->wWidth;
- ccap->bounds.height = stream->cur_frame->wHeight;
- mutex_unlock(&stream->mutex);
-
- ccap->defrect = ccap->bounds;
-
- ccap->pixelaspect.numerator = 1;
- ccap->pixelaspect.denominator = 1;
- return 0;
-}
-
-static int uvc_ioctl_g_parm(struct file *file, void *fh,
- struct v4l2_streamparm *parm)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
-
- return uvc_v4l2_get_streamparm(stream, parm);
-}
-
-static int uvc_ioctl_s_parm(struct file *file, void *fh,
- struct v4l2_streamparm *parm)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- int ret;
-
- ret = uvc_acquire_privileges(handle);
- if (ret < 0)
- return ret;
-
- return uvc_v4l2_set_streamparm(stream, parm);
-}
-
-static int uvc_ioctl_enum_framesizes(struct file *file, void *fh,
- struct v4l2_frmsizeenum *fsize)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- struct uvc_format *format = NULL;
- struct uvc_frame *frame;
- int i;
-
- /* Look for the given pixel format */
- for (i = 0; i < stream->nformats; i++) {
- if (stream->format[i].fcc == fsize->pixel_format) {
- format = &stream->format[i];
- break;
- }
- }
- if (format == NULL)
- return -EINVAL;
-
- if (fsize->index >= format->nframes)
- return -EINVAL;
-
- frame = &format->frame[fsize->index];
- fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
- fsize->discrete.width = frame->wWidth;
- fsize->discrete.height = frame->wHeight;
- return 0;
-}
-
-static int uvc_ioctl_enum_frameintervals(struct file *file, void *fh,
- struct v4l2_frmivalenum *fival)
-{
- struct uvc_fh *handle = fh;
- struct uvc_streaming *stream = handle->stream;
- struct uvc_format *format = NULL;
- struct uvc_frame *frame = NULL;
- int i;
-
- /* Look for the given pixel format and frame size */
- for (i = 0; i < stream->nformats; i++) {
- if (stream->format[i].fcc == fival->pixel_format) {
- format = &stream->format[i];
- break;
- }
- }
- if (format == NULL)
- return -EINVAL;
-
- for (i = 0; i < format->nframes; i++) {
- if (format->frame[i].wWidth == fival->width &&
- format->frame[i].wHeight == fival->height) {
- frame = &format->frame[i];
- break;
- }
- }
- if (frame == NULL)
- return -EINVAL;
-
- if (frame->bFrameIntervalType) {
- if (fival->index >= frame->bFrameIntervalType)
- return -EINVAL;
-
- fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
- fival->discrete.numerator =
- frame->dwFrameInterval[fival->index];
- fival->discrete.denominator = 10000000;
- uvc_simplify_fraction(&fival->discrete.numerator,
- &fival->discrete.denominator, 8, 333);
- } else {
- fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
- fival->stepwise.min.numerator = frame->dwFrameInterval[0];
- fival->stepwise.min.denominator = 10000000;
- fival->stepwise.max.numerator = frame->dwFrameInterval[1];
- fival->stepwise.max.denominator = 10000000;
- fival->stepwise.step.numerator = frame->dwFrameInterval[2];
- fival->stepwise.step.denominator = 10000000;
- uvc_simplify_fraction(&fival->stepwise.min.numerator,
- &fival->stepwise.min.denominator, 8, 333);
- uvc_simplify_fraction(&fival->stepwise.max.numerator,
- &fival->stepwise.max.denominator, 8, 333);
- uvc_simplify_fraction(&fival->stepwise.step.numerator,
- &fival->stepwise.step.denominator, 8, 333);
- }
-
- return 0;
-}
-
-static int uvc_ioctl_subscribe_event(struct v4l2_fh *fh,
- const struct v4l2_event_subscription *sub)
-{
- switch (sub->type) {
- case V4L2_EVENT_CTRL:
- return v4l2_event_subscribe(fh, sub, 0, &uvc_ctrl_sub_ev_ops);
- default:
- return -EINVAL;
- }
-}
-
-static long uvc_ioctl_default(struct file *file, void *fh, bool valid_prio,
- unsigned int cmd, void *arg)
-{
- struct uvc_fh *handle = fh;
- struct uvc_video_chain *chain = handle->chain;
+ long ret = 0;
switch (cmd) {
- /* Dynamic controls. */
+ /* Query capabilities */
+ case VIDIOC_QUERYCAP:
+ {
+ struct v4l2_capability *cap = arg;
+
+ memset(cap, 0, sizeof *cap);
+ strlcpy(cap->driver, "uvcvideo", sizeof cap->driver);
+ strlcpy(cap->card, vdev->name, sizeof cap->card);
+ usb_make_path(stream->dev->udev,
+ cap->bus_info, sizeof(cap->bus_info));
+ cap->version = LINUX_VERSION_CODE;
+ cap->capabilities = V4L2_CAP_DEVICE_CAPS | V4L2_CAP_STREAMING
+ | chain->caps;
+ if (stream->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ cap->device_caps = V4L2_CAP_VIDEO_CAPTURE
+ | V4L2_CAP_STREAMING;
+ else
+ cap->device_caps = V4L2_CAP_VIDEO_OUTPUT
+ | V4L2_CAP_STREAMING;
+ break;
+ }
+
+ /* Priority */
+ case VIDIOC_G_PRIORITY:
+ *(u32 *)arg = v4l2_prio_max(vdev->prio);
+ break;
+
+ case VIDIOC_S_PRIORITY:
+ ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+ if (ret < 0)
+ return ret;
+
+ return v4l2_prio_change(vdev->prio, &handle->vfh.prio,
+ *(u32 *)arg);
+
+ /* Get, Set & Query control */
+ case VIDIOC_QUERYCTRL:
+ return uvc_query_v4l2_ctrl(chain, arg);
+
+ case VIDIOC_G_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ struct v4l2_ext_control xctrl;
+
+ memset(&xctrl, 0, sizeof xctrl);
+ xctrl.id = ctrl->id;
+
+ ret = uvc_ctrl_begin(chain);
+ if (ret < 0)
+ return ret;
+
+ ret = uvc_ctrl_get(chain, &xctrl);
+ uvc_ctrl_rollback(handle);
+ if (ret >= 0)
+ ctrl->value = xctrl.value;
+ break;
+ }
+
+ case VIDIOC_S_CTRL:
+ {
+ struct v4l2_control *ctrl = arg;
+ struct v4l2_ext_control xctrl;
+
+ ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+ if (ret < 0)
+ return ret;
+
+ memset(&xctrl, 0, sizeof xctrl);
+ xctrl.id = ctrl->id;
+ xctrl.value = ctrl->value;
+
+ ret = uvc_ctrl_begin(chain);
+ if (ret < 0)
+ return ret;
+
+ ret = uvc_ctrl_set(chain, &xctrl);
+ if (ret < 0) {
+ uvc_ctrl_rollback(handle);
+ return ret;
+ }
+ ret = uvc_ctrl_commit(handle, &xctrl, 1);
+ if (ret == 0)
+ ctrl->value = xctrl.value;
+ break;
+ }
+
+ case VIDIOC_QUERYMENU:
+ return uvc_query_v4l2_menu(chain, arg);
+
+ case VIDIOC_G_EXT_CTRLS:
+ {
+ struct v4l2_ext_controls *ctrls = arg;
+ struct v4l2_ext_control *ctrl = ctrls->controls;
+ unsigned int i;
+
+ ret = uvc_ctrl_begin(chain);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+ ret = uvc_ctrl_get(chain, ctrl);
+ if (ret < 0) {
+ uvc_ctrl_rollback(handle);
+ ctrls->error_idx = i;
+ return ret;
+ }
+ }
+ ctrls->error_idx = 0;
+ ret = uvc_ctrl_rollback(handle);
+ break;
+ }
+
+ case VIDIOC_S_EXT_CTRLS:
+ ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+ if (ret < 0)
+ return ret;
+ /* Fall through */
+ case VIDIOC_TRY_EXT_CTRLS:
+ {
+ struct v4l2_ext_controls *ctrls = arg;
+ struct v4l2_ext_control *ctrl = ctrls->controls;
+ unsigned int i;
+
+ ret = uvc_ctrl_begin(chain);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < ctrls->count; ++ctrl, ++i) {
+ ret = uvc_ctrl_set(chain, ctrl);
+ if (ret < 0) {
+ uvc_ctrl_rollback(handle);
+ ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS
+ ? ctrls->count : i;
+ return ret;
+ }
+ }
+
+ ctrls->error_idx = 0;
+
+ if (cmd == VIDIOC_S_EXT_CTRLS)
+ ret = uvc_ctrl_commit(handle,
+ ctrls->controls, ctrls->count);
+ else
+ ret = uvc_ctrl_rollback(handle);
+ break;
+ }
+
+ /* Get, Set & Enum input */
+ case VIDIOC_ENUMINPUT:
+ {
+ const struct uvc_entity *selector = chain->selector;
+ struct v4l2_input *input = arg;
+ struct uvc_entity *iterm = NULL;
+ u32 index = input->index;
+ int pin = 0;
+
+ if (selector == NULL ||
+ (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+ if (index != 0)
+ return -EINVAL;
+ list_for_each_entry(iterm, &chain->entities, chain) {
+ if (UVC_ENTITY_IS_ITERM(iterm))
+ break;
+ }
+ pin = iterm->id;
+ } else if (index < selector->bNrInPins) {
+ pin = selector->baSourceID[index];
+ list_for_each_entry(iterm, &chain->entities, chain) {
+ if (!UVC_ENTITY_IS_ITERM(iterm))
+ continue;
+ if (iterm->id == pin)
+ break;
+ }
+ }
+
+ if (iterm == NULL || iterm->id != pin)
+ return -EINVAL;
+
+ memset(input, 0, sizeof *input);
+ input->index = index;
+ strlcpy(input->name, iterm->name, sizeof input->name);
+ if (UVC_ENTITY_TYPE(iterm) == UVC_ITT_CAMERA)
+ input->type = V4L2_INPUT_TYPE_CAMERA;
+ break;
+ }
+
+ case VIDIOC_G_INPUT:
+ {
+ u8 input;
+
+ if (chain->selector == NULL ||
+ (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+ *(int *)arg = 0;
+ break;
+ }
+
+ ret = uvc_query_ctrl(chain->dev, UVC_GET_CUR,
+ chain->selector->id, chain->dev->intfnum,
+ UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
+ if (ret < 0)
+ return ret;
+
+ *(int *)arg = input - 1;
+ break;
+ }
+
+ case VIDIOC_S_INPUT:
+ {
+ u32 input = *(u32 *)arg + 1;
+
+ ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+ if (ret < 0)
+ return ret;
+
+ if ((ret = uvc_acquire_privileges(handle)) < 0)
+ return ret;
+
+ if (chain->selector == NULL ||
+ (chain->dev->quirks & UVC_QUIRK_IGNORE_SELECTOR_UNIT)) {
+ if (input != 1)
+ return -EINVAL;
+ break;
+ }
+
+ if (input == 0 || input > chain->selector->bNrInPins)
+ return -EINVAL;
+
+ return uvc_query_ctrl(chain->dev, UVC_SET_CUR,
+ chain->selector->id, chain->dev->intfnum,
+ UVC_SU_INPUT_SELECT_CONTROL, &input, 1);
+ }
+
+ /* Try, Get, Set & Enum format */
+ case VIDIOC_ENUM_FMT:
+ {
+ struct v4l2_fmtdesc *fmt = arg;
+ struct uvc_format *format;
+ enum v4l2_buf_type type = fmt->type;
+ __u32 index = fmt->index;
+
+ if (fmt->type != stream->type ||
+ fmt->index >= stream->nformats)
+ return -EINVAL;
+
+ memset(fmt, 0, sizeof(*fmt));
+ fmt->index = index;
+ fmt->type = type;
+
+ format = &stream->format[fmt->index];
+ fmt->flags = 0;
+ if (format->flags & UVC_FMT_FLAG_COMPRESSED)
+ fmt->flags |= V4L2_FMT_FLAG_COMPRESSED;
+ strlcpy(fmt->description, format->name,
+ sizeof fmt->description);
+ fmt->description[sizeof fmt->description - 1] = 0;
+ fmt->pixelformat = format->fcc;
+ break;
+ }
+
+ case VIDIOC_TRY_FMT:
+ {
+ struct uvc_streaming_control probe;
+
+ return uvc_v4l2_try_format(stream, arg, &probe, NULL, NULL);
+ }
+
+ case VIDIOC_S_FMT:
+ ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+ if (ret < 0)
+ return ret;
+
+ if ((ret = uvc_acquire_privileges(handle)) < 0)
+ return ret;
+
+ return uvc_v4l2_set_format(stream, arg);
+
+ case VIDIOC_G_FMT:
+ return uvc_v4l2_get_format(stream, arg);
+
+ /* Frame size enumeration */
+ case VIDIOC_ENUM_FRAMESIZES:
+ {
+ struct v4l2_frmsizeenum *fsize = arg;
+ struct uvc_format *format = NULL;
+ struct uvc_frame *frame;
+ int i;
+
+ /* Look for the given pixel format */
+ for (i = 0; i < stream->nformats; i++) {
+ if (stream->format[i].fcc ==
+ fsize->pixel_format) {
+ format = &stream->format[i];
+ break;
+ }
+ }
+ if (format == NULL)
+ return -EINVAL;
+
+ if (fsize->index >= format->nframes)
+ return -EINVAL;
+
+ frame = &format->frame[fsize->index];
+ fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+ fsize->discrete.width = frame->wWidth;
+ fsize->discrete.height = frame->wHeight;
+ break;
+ }
+
+ /* Frame interval enumeration */
+ case VIDIOC_ENUM_FRAMEINTERVALS:
+ {
+ struct v4l2_frmivalenum *fival = arg;
+ struct uvc_format *format = NULL;
+ struct uvc_frame *frame = NULL;
+ int i;
+
+ /* Look for the given pixel format and frame size */
+ for (i = 0; i < stream->nformats; i++) {
+ if (stream->format[i].fcc ==
+ fival->pixel_format) {
+ format = &stream->format[i];
+ break;
+ }
+ }
+ if (format == NULL)
+ return -EINVAL;
+
+ for (i = 0; i < format->nframes; i++) {
+ if (format->frame[i].wWidth == fival->width &&
+ format->frame[i].wHeight == fival->height) {
+ frame = &format->frame[i];
+ break;
+ }
+ }
+ if (frame == NULL)
+ return -EINVAL;
+
+ if (frame->bFrameIntervalType) {
+ if (fival->index >= frame->bFrameIntervalType)
+ return -EINVAL;
+
+ fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+ fival->discrete.numerator =
+ frame->dwFrameInterval[fival->index];
+ fival->discrete.denominator = 10000000;
+ uvc_simplify_fraction(&fival->discrete.numerator,
+ &fival->discrete.denominator, 8, 333);
+ } else {
+ fival->type = V4L2_FRMIVAL_TYPE_STEPWISE;
+ fival->stepwise.min.numerator =
+ frame->dwFrameInterval[0];
+ fival->stepwise.min.denominator = 10000000;
+ fival->stepwise.max.numerator =
+ frame->dwFrameInterval[1];
+ fival->stepwise.max.denominator = 10000000;
+ fival->stepwise.step.numerator =
+ frame->dwFrameInterval[2];
+ fival->stepwise.step.denominator = 10000000;
+ uvc_simplify_fraction(&fival->stepwise.min.numerator,
+ &fival->stepwise.min.denominator, 8, 333);
+ uvc_simplify_fraction(&fival->stepwise.max.numerator,
+ &fival->stepwise.max.denominator, 8, 333);
+ uvc_simplify_fraction(&fival->stepwise.step.numerator,
+ &fival->stepwise.step.denominator, 8, 333);
+ }
+ break;
+ }
+
+ /* Get & Set streaming parameters */
+ case VIDIOC_G_PARM:
+ return uvc_v4l2_get_streamparm(stream, arg);
+
+ case VIDIOC_S_PARM:
+ ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+ if (ret < 0)
+ return ret;
+
+ if ((ret = uvc_acquire_privileges(handle)) < 0)
+ return ret;
+
+ return uvc_v4l2_set_streamparm(stream, arg);
+
+ /* Cropping and scaling */
+ case VIDIOC_CROPCAP:
+ {
+ struct v4l2_cropcap *ccap = arg;
+
+ if (ccap->type != stream->type)
+ return -EINVAL;
+
+ ccap->bounds.left = 0;
+ ccap->bounds.top = 0;
+
+ mutex_lock(&stream->mutex);
+ ccap->bounds.width = stream->cur_frame->wWidth;
+ ccap->bounds.height = stream->cur_frame->wHeight;
+ mutex_unlock(&stream->mutex);
+
+ ccap->defrect = ccap->bounds;
+
+ ccap->pixelaspect.numerator = 1;
+ ccap->pixelaspect.denominator = 1;
+ break;
+ }
+
+ case VIDIOC_G_CROP:
+ case VIDIOC_S_CROP:
+ return -ENOTTY;
+
+ /* Buffers & streaming */
+ case VIDIOC_REQBUFS:
+ ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+ if (ret < 0)
+ return ret;
+
+ if ((ret = uvc_acquire_privileges(handle)) < 0)
+ return ret;
+
+ mutex_lock(&stream->mutex);
+ ret = uvc_alloc_buffers(&stream->queue, arg);
+ mutex_unlock(&stream->mutex);
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0)
+ uvc_dismiss_privileges(handle);
+
+ ret = 0;
+ break;
+
+ case VIDIOC_QUERYBUF:
+ {
+ struct v4l2_buffer *buf = arg;
+
+ if (!uvc_has_privileges(handle))
+ return -EBUSY;
+
+ return uvc_query_buffer(&stream->queue, buf);
+ }
+
+ case VIDIOC_CREATE_BUFS:
+ {
+ struct v4l2_create_buffers *cb = arg;
+
+ ret = uvc_acquire_privileges(handle);
+ if (ret < 0)
+ return ret;
+
+ return uvc_create_buffers(&stream->queue, cb);
+ }
+
+ case VIDIOC_QBUF:
+ if (!uvc_has_privileges(handle))
+ return -EBUSY;
+
+ return uvc_queue_buffer(&stream->queue, arg);
+
+ case VIDIOC_DQBUF:
+ if (!uvc_has_privileges(handle))
+ return -EBUSY;
+
+ return uvc_dequeue_buffer(&stream->queue, arg,
+ file->f_flags & O_NONBLOCK);
+
+ case VIDIOC_STREAMON:
+ {
+ int *type = arg;
+
+ if (*type != stream->type)
+ return -EINVAL;
+
+ ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+ if (ret < 0)
+ return ret;
+
+ if (!uvc_has_privileges(handle))
+ return -EBUSY;
+
+ mutex_lock(&stream->mutex);
+ ret = uvc_video_enable(stream, 1);
+ mutex_unlock(&stream->mutex);
+ if (ret < 0)
+ return ret;
+ break;
+ }
+
+ case VIDIOC_STREAMOFF:
+ {
+ int *type = arg;
+
+ if (*type != stream->type)
+ return -EINVAL;
+
+ ret = v4l2_prio_check(vdev->prio, handle->vfh.prio);
+ if (ret < 0)
+ return ret;
+
+ if (!uvc_has_privileges(handle))
+ return -EBUSY;
+
+ return uvc_video_enable(stream, 0);
+ }
+
+ case VIDIOC_SUBSCRIBE_EVENT:
+ {
+ struct v4l2_event_subscription *sub = arg;
+
+ switch (sub->type) {
+ case V4L2_EVENT_CTRL:
+ return v4l2_event_subscribe(&handle->vfh, sub, 0,
+ &uvc_ctrl_sub_ev_ops);
+ default:
+ return -EINVAL;
+ }
+ }
+
+ case VIDIOC_UNSUBSCRIBE_EVENT:
+ return v4l2_event_unsubscribe(&handle->vfh, arg);
+
+ case VIDIOC_DQEVENT:
+ return v4l2_event_dequeue(&handle->vfh, arg,
+ file->f_flags & O_NONBLOCK);
+
+ /* Analog video standards make no sense for digital cameras. */
+ case VIDIOC_ENUMSTD:
+ case VIDIOC_QUERYSTD:
+ case VIDIOC_G_STD:
+ case VIDIOC_S_STD:
+
+ case VIDIOC_OVERLAY:
+
+ case VIDIOC_ENUMAUDIO:
+ case VIDIOC_ENUMAUDOUT:
+
+ case VIDIOC_ENUMOUTPUT:
+ uvc_trace(UVC_TRACE_IOCTL, "Unsupported ioctl 0x%08x\n", cmd);
+ return -ENOTTY;
+
case UVCIOC_CTRL_MAP:
return uvc_ioctl_ctrl_map(chain, arg);
@@ -1178,8 +1106,23 @@
return uvc_xu_ctrl_query(chain, arg);
default:
+ uvc_trace(UVC_TRACE_IOCTL, "Unknown ioctl 0x%08x\n", cmd);
return -ENOTTY;
}
+
+ return ret;
+}
+
+static long uvc_v4l2_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ if (uvc_trace_param & UVC_TRACE_IOCTL) {
+ uvc_printk(KERN_DEBUG, "uvc_v4l2_ioctl(");
+ v4l_printk_ioctl(NULL, cmd);
+ printk(")\n");
+ }
+
+ return video_usercopy(file, cmd, arg, uvc_v4l2_do_ioctl);
}
#ifdef CONFIG_COMPAT
@@ -1362,7 +1305,7 @@
old_fs = get_fs();
set_fs(KERNEL_DS);
- ret = video_ioctl2(file, cmd, (unsigned long)&karg);
+ ret = uvc_v4l2_ioctl(file, cmd, (unsigned long)&karg);
set_fs(old_fs);
if (ret < 0)
@@ -1423,48 +1366,11 @@
}
#endif
-const struct v4l2_ioctl_ops uvc_ioctl_ops = {
- .vidioc_querycap = uvc_ioctl_querycap,
- .vidioc_enum_fmt_vid_cap = uvc_ioctl_enum_fmt_vid_cap,
- .vidioc_enum_fmt_vid_out = uvc_ioctl_enum_fmt_vid_out,
- .vidioc_g_fmt_vid_cap = uvc_ioctl_g_fmt_vid_cap,
- .vidioc_g_fmt_vid_out = uvc_ioctl_g_fmt_vid_out,
- .vidioc_s_fmt_vid_cap = uvc_ioctl_s_fmt_vid_cap,
- .vidioc_s_fmt_vid_out = uvc_ioctl_s_fmt_vid_out,
- .vidioc_try_fmt_vid_cap = uvc_ioctl_try_fmt_vid_cap,
- .vidioc_try_fmt_vid_out = uvc_ioctl_try_fmt_vid_out,
- .vidioc_reqbufs = uvc_ioctl_reqbufs,
- .vidioc_querybuf = uvc_ioctl_querybuf,
- .vidioc_qbuf = uvc_ioctl_qbuf,
- .vidioc_dqbuf = uvc_ioctl_dqbuf,
- .vidioc_create_bufs = uvc_ioctl_create_bufs,
- .vidioc_streamon = uvc_ioctl_streamon,
- .vidioc_streamoff = uvc_ioctl_streamoff,
- .vidioc_enum_input = uvc_ioctl_enum_input,
- .vidioc_g_input = uvc_ioctl_g_input,
- .vidioc_s_input = uvc_ioctl_s_input,
- .vidioc_queryctrl = uvc_ioctl_queryctrl,
- .vidioc_g_ctrl = uvc_ioctl_g_ctrl,
- .vidioc_s_ctrl = uvc_ioctl_s_ctrl,
- .vidioc_g_ext_ctrls = uvc_ioctl_g_ext_ctrls,
- .vidioc_s_ext_ctrls = uvc_ioctl_s_ext_ctrls,
- .vidioc_try_ext_ctrls = uvc_ioctl_try_ext_ctrls,
- .vidioc_querymenu = uvc_ioctl_querymenu,
- .vidioc_cropcap = uvc_ioctl_cropcap,
- .vidioc_g_parm = uvc_ioctl_g_parm,
- .vidioc_s_parm = uvc_ioctl_s_parm,
- .vidioc_enum_framesizes = uvc_ioctl_enum_framesizes,
- .vidioc_enum_frameintervals = uvc_ioctl_enum_frameintervals,
- .vidioc_subscribe_event = uvc_ioctl_subscribe_event,
- .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
- .vidioc_default = uvc_ioctl_default,
-};
-
const struct v4l2_file_operations uvc_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
.release = uvc_v4l2_release,
- .unlocked_ioctl = video_ioctl2,
+ .unlocked_ioctl = uvc_v4l2_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl32 = uvc_v4l2_compat_ioctl32,
#endif
diff --git a/drivers/media/usb/uvc/uvc_video.c b/drivers/media/usb/uvc/uvc_video.c
index 9637e8b..9ace520 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -1021,7 +1021,6 @@
uvc_video_get_ts(&ts);
- buf->buf.v4l2_buf.field = V4L2_FIELD_NONE;
buf->buf.v4l2_buf.sequence = stream->sequence;
buf->buf.v4l2_buf.timestamp.tv_sec = ts.tv_sec;
buf->buf.v4l2_buf.timestamp.tv_usec =
@@ -1144,7 +1143,7 @@
static void uvc_video_validate_buffer(const struct uvc_streaming *stream,
struct uvc_buffer *buf)
{
- if (stream->ctrl.dwMaxVideoFrameSize != buf->bytesused &&
+ if (stream->frame_size != buf->bytesused &&
!(stream->cur_format->flags & UVC_FMT_FLAG_COMPRESSED))
buf->error = 1;
}
@@ -1735,13 +1734,19 @@
uvc_video_clock_reset(stream);
ret = uvc_commit_video(stream, &stream->ctrl);
- if (ret < 0)
+ if (ret < 0) {
+ uvc_queue_enable(&stream->queue, 0);
return ret;
+ }
if (!uvc_queue_streaming(&stream->queue))
return 0;
- return uvc_init_video(stream, GFP_NOIO);
+ ret = uvc_init_video(stream, GFP_NOIO);
+ if (ret < 0)
+ uvc_queue_enable(&stream->queue, 0);
+
+ return ret;
}
/* ------------------------------------------------------------------------
@@ -1773,6 +1778,11 @@
atomic_set(&stream->active, 0);
+ /* Initialize the video buffers queue. */
+ ret = uvc_queue_init(&stream->queue, stream->type, !uvc_no_drop_param);
+ if (ret)
+ return ret;
+
/* Alternate setting 0 should be the default, yet the XBox Live Vision
* Cam (and possibly other devices) crash or otherwise misbehave if
* they don't receive a SET_INTERFACE request before any other video
@@ -1879,6 +1889,7 @@
usb_clear_halt(stream->dev->udev, pipe);
}
+ uvc_queue_enable(&stream->queue, 0);
uvc_video_clock_cleanup(stream);
return 0;
}
@@ -1887,6 +1898,10 @@
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)
@@ -1901,6 +1916,8 @@
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;
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h
index 1683a9c..11b6b61 100644
--- a/drivers/media/usb/uvc/uvcvideo.h
+++ b/drivers/media/usb/uvc/uvcvideo.h
@@ -148,7 +148,6 @@
#define UVC_QUIRK_PROBE_DEF 0x00000100
#define UVC_QUIRK_RESTRICT_FRAME_RATE 0x00000200
#define UVC_QUIRK_RESTORE_CTRLS_ON_INIT 0x00000400
-#define UVC_QUIRK_FORCE_Y8 0x00000800
/* Format flags */
#define UVC_FMT_FLAG_COMPRESSED 0x00000001
@@ -458,6 +457,7 @@
struct uvc_format *def_format;
struct uvc_format *cur_format;
struct uvc_frame *cur_frame;
+ size_t frame_size;
/* Protect access to ctrl, cur_format, cur_frame and hardware video
* probe control.
@@ -580,6 +580,7 @@
#define UVC_TRACE_FORMAT (1 << 3)
#define UVC_TRACE_CAPTURE (1 << 4)
#define UVC_TRACE_CALLS (1 << 5)
+#define UVC_TRACE_IOCTL (1 << 6)
#define UVC_TRACE_FRAME (1 << 7)
#define UVC_TRACE_SUSPEND (1 << 8)
#define UVC_TRACE_STATUS (1 << 9)
@@ -623,9 +624,9 @@
/* Video buffers queue management. */
extern int uvc_queue_init(struct uvc_video_queue *queue,
enum v4l2_buf_type type, int drop_corrupted);
-extern void uvc_queue_release(struct uvc_video_queue *queue);
-extern int uvc_request_buffers(struct uvc_video_queue *queue,
+extern int uvc_alloc_buffers(struct uvc_video_queue *queue,
struct v4l2_requestbuffers *rb);
+extern void uvc_free_buffers(struct uvc_video_queue *queue);
extern int uvc_query_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf);
extern int uvc_create_buffers(struct uvc_video_queue *queue,
@@ -634,10 +635,7 @@
struct v4l2_buffer *v4l2_buf);
extern int uvc_dequeue_buffer(struct uvc_video_queue *queue,
struct v4l2_buffer *v4l2_buf, int nonblocking);
-extern int uvc_queue_streamon(struct uvc_video_queue *queue,
- enum v4l2_buf_type type);
-extern int uvc_queue_streamoff(struct uvc_video_queue *queue,
- enum v4l2_buf_type type);
+extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf);
@@ -656,7 +654,6 @@
}
/* V4L2 interface */
-extern const struct v4l2_ioctl_ops uvc_ioctl_ops;
extern const struct v4l2_file_operations uvc_fops;
/* Media controller */
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
index 2276750..52d7b51 100644
--- a/drivers/media/v4l2-core/Kconfig
+++ b/drivers/media/v4l2-core/Kconfig
@@ -77,7 +77,7 @@
# Used by drivers that need Videobuf2 modules
config VIDEOBUF2_CORE
- select DMA_SHARED_BUFFER if !KERNEL_3_5
+ select DMA_SHARED_BUFFER if !BACKPORT_KERNEL_3_5
tristate
depends on m
@@ -91,14 +91,14 @@
depends on HAS_DMA
select VIDEOBUF2_CORE
select VIDEOBUF2_MEMOPS
- select DMA_SHARED_BUFFER if !KERNEL_3_5
+ select DMA_SHARED_BUFFER if !BACKPORT_KERNEL_3_5
config VIDEOBUF2_VMALLOC
tristate
depends on m
select VIDEOBUF2_CORE
select VIDEOBUF2_MEMOPS
- select DMA_SHARED_BUFFER if !KERNEL_3_5
+ select DMA_SHARED_BUFFER if !BACKPORT_KERNEL_3_5
config VIDEOBUF2_DMA_SG
tristate
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 0d6c1ec..46a938b 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -80,6 +80,36 @@
/* Helper functions for control handling */
+/* Check for correctness of the ctrl's value based on the data from
+ struct v4l2_queryctrl and the available menu items. Note that
+ menu_items may be NULL, in that case it is ignored. */
+int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
+ const char * const *menu_items)
+{
+ if (qctrl->flags & V4L2_CTRL_FLAG_DISABLED)
+ return -EINVAL;
+ if (qctrl->flags & V4L2_CTRL_FLAG_GRABBED)
+ return -EBUSY;
+ if (qctrl->type == V4L2_CTRL_TYPE_STRING)
+ return 0;
+ if (qctrl->type == V4L2_CTRL_TYPE_BUTTON ||
+ qctrl->type == V4L2_CTRL_TYPE_INTEGER64 ||
+ qctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
+ return 0;
+ if (ctrl->value < qctrl->minimum || ctrl->value > qctrl->maximum)
+ return -ERANGE;
+ if (qctrl->type == V4L2_CTRL_TYPE_MENU && menu_items != NULL) {
+ if (menu_items[ctrl->value] == NULL ||
+ menu_items[ctrl->value][0] == '\0')
+ return -EINVAL;
+ }
+ if (qctrl->type == V4L2_CTRL_TYPE_BITMASK &&
+ (ctrl->value & ~qctrl->maximum))
+ return -ERANGE;
+ return 0;
+}
+EXPORT_SYMBOL(v4l2_ctrl_check);
+
/* Fill in a struct v4l2_queryctrl */
int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
{
@@ -105,6 +135,101 @@
}
EXPORT_SYMBOL(v4l2_ctrl_query_fill);
+/* Fill in a struct v4l2_querymenu based on the struct v4l2_queryctrl and
+ the menu. The qctrl pointer may be NULL, in which case it is ignored.
+ If menu_items is NULL, then the menu items are retrieved using
+ v4l2_ctrl_get_menu. */
+int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu, struct v4l2_queryctrl *qctrl,
+ const char * const *menu_items)
+{
+ int i;
+
+ qmenu->reserved = 0;
+ if (menu_items == NULL)
+ menu_items = v4l2_ctrl_get_menu(qmenu->id);
+ if (menu_items == NULL ||
+ (qctrl && (qmenu->index < qctrl->minimum || qmenu->index > qctrl->maximum)))
+ return -EINVAL;
+ for (i = 0; i < qmenu->index && menu_items[i]; i++) ;
+ if (menu_items[i] == NULL || menu_items[i][0] == '\0')
+ return -EINVAL;
+ strlcpy(qmenu->name, menu_items[qmenu->index], sizeof(qmenu->name));
+ return 0;
+}
+EXPORT_SYMBOL(v4l2_ctrl_query_menu);
+
+/* Fill in a struct v4l2_querymenu based on the specified array of valid
+ menu items (terminated by V4L2_CTRL_MENU_IDS_END).
+ Use this if there are 'holes' in the list of valid menu items. */
+int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids)
+{
+ const char * const *menu_items = v4l2_ctrl_get_menu(qmenu->id);
+
+ qmenu->reserved = 0;
+ if (menu_items == NULL || ids == NULL)
+ return -EINVAL;
+ while (*ids != V4L2_CTRL_MENU_IDS_END) {
+ if (*ids++ == qmenu->index) {
+ strlcpy(qmenu->name, menu_items[qmenu->index],
+ sizeof(qmenu->name));
+ return 0;
+ }
+ }
+ return -EINVAL;
+}
+EXPORT_SYMBOL(v4l2_ctrl_query_menu_valid_items);
+
+/* ctrl_classes points to an array of u32 pointers, the last element is
+ a NULL pointer. Each u32 array is a 0-terminated array of control IDs.
+ Each array must be sorted low to high and belong to the same control
+ class. The array of u32 pointers must also be sorted, from low class IDs
+ to high class IDs.
+
+ This function returns the first ID that follows after the given ID.
+ When no more controls are available 0 is returned. */
+u32 v4l2_ctrl_next(const u32 * const * ctrl_classes, u32 id)
+{
+ u32 ctrl_class = V4L2_CTRL_ID2CLASS(id);
+ const u32 *pctrl;
+
+ if (ctrl_classes == NULL)
+ return 0;
+
+ /* if no query is desired, then check if the ID is part of ctrl_classes */
+ if ((id & V4L2_CTRL_FLAG_NEXT_CTRL) == 0) {
+ /* find class */
+ while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) != ctrl_class)
+ ctrl_classes++;
+ if (*ctrl_classes == NULL)
+ return 0;
+ pctrl = *ctrl_classes;
+ /* find control ID */
+ while (*pctrl && *pctrl != id) pctrl++;
+ return *pctrl ? id : 0;
+ }
+ id &= V4L2_CTRL_ID_MASK;
+ id++; /* select next control */
+ /* find first class that matches (or is greater than) the class of
+ the ID */
+ while (*ctrl_classes && V4L2_CTRL_ID2CLASS(**ctrl_classes) < ctrl_class)
+ ctrl_classes++;
+ /* no more classes */
+ if (*ctrl_classes == NULL)
+ return 0;
+ pctrl = *ctrl_classes;
+ /* find first ctrl within the class that is >= ID */
+ while (*pctrl && *pctrl < id) pctrl++;
+ if (*pctrl)
+ return *pctrl;
+ /* we are at the end of the controls of the current class. */
+ /* continue with next class if available */
+ ctrl_classes++;
+ if (*ctrl_classes == NULL)
+ return 0;
+ return **ctrl_classes;
+}
+EXPORT_SYMBOL(v4l2_ctrl_next);
+
/* I2C Helper functions */
#if IS_ENABLED(CONFIG_I2C)
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index af63543..e502a5f 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -222,9 +222,6 @@
static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
{
- if (put_user(kp->type, &up->type))
- return -EFAULT;
-
switch (kp->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
@@ -251,7 +248,8 @@
static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
{
- if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)))
+ if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
+ put_user(kp->type, &up->type))
return -EFAULT;
return __put_v4l2_format32(kp, up);
}
@@ -259,8 +257,8 @@
static int put_v4l2_create32(struct v4l2_create_buffers *kp, struct v4l2_create_buffers32 __user *up)
{
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
- copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format)))
- return -EFAULT;
+ copy_to_user(up, kp, offsetof(struct v4l2_create_buffers32, format.fmt)))
+ return -EFAULT;
return __put_v4l2_format32(&kp->format, &up->format);
}
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 45c5b47..8601214 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -1658,8 +1658,10 @@
}
/* Validate a new control */
-static int validate_new(const struct v4l2_ctrl *ctrl, union v4l2_ctrl_ptr p_new)
+static int validate_new(const struct v4l2_ctrl *ctrl,
+ struct v4l2_ext_control *c)
{
+ union v4l2_ctrl_ptr ptr;
unsigned idx;
int err = 0;
@@ -1672,14 +1674,19 @@
case V4L2_CTRL_TYPE_BOOLEAN:
case V4L2_CTRL_TYPE_BUTTON:
case V4L2_CTRL_TYPE_CTRL_CLASS:
+ ptr.p_s32 = &c->value;
+ return ctrl->type_ops->validate(ctrl, 0, ptr);
+
case V4L2_CTRL_TYPE_INTEGER64:
- return ctrl->type_ops->validate(ctrl, 0, p_new);
+ ptr.p_s64 = &c->value64;
+ return ctrl->type_ops->validate(ctrl, 0, ptr);
default:
break;
}
}
- for (idx = 0; !err && idx < ctrl->elems; idx++)
- err = ctrl->type_ops->validate(ctrl, idx, p_new);
+ ptr.p = c->ptr;
+ for (idx = 0; !err && idx < c->size / ctrl->elem_size; idx++)
+ err = ctrl->type_ops->validate(ctrl, idx, ptr);
return err;
}
@@ -3005,7 +3012,6 @@
cs->error_idx = cs->count;
for (i = 0; i < cs->count; i++) {
struct v4l2_ctrl *ctrl = helpers[i].ctrl;
- union v4l2_ctrl_ptr p_new;
cs->error_idx = i;
@@ -3019,17 +3025,7 @@
best-effort to avoid that. */
if (set && (ctrl->flags & V4L2_CTRL_FLAG_GRABBED))
return -EBUSY;
- /*
- * Skip validation for now if the payload needs to be copied
- * from userspace into kernelspace. We'll validate those later.
- */
- if (ctrl->is_ptr)
- continue;
- if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
- p_new.p_s64 = &cs->controls[i].value64;
- else
- p_new.p_s32 = &cs->controls[i].value;
- ret = validate_new(ctrl, p_new);
+ ret = validate_new(ctrl, &cs->controls[i]);
if (ret)
return ret;
}
@@ -3124,11 +3120,7 @@
/* Copy the new caller-supplied control values.
user_to_new() sets 'is_new' to 1. */
do {
- struct v4l2_ctrl *ctrl = helpers[idx].ctrl;
-
- ret = user_to_new(cs->controls + idx, ctrl);
- if (!ret && ctrl->is_ptr)
- ret = validate_new(ctrl, ctrl->p_new);
+ ret = user_to_new(cs->controls + idx, helpers[idx].ctrl);
idx = helpers[idx].next;
} while (!ret && idx);
@@ -3178,10 +3170,10 @@
EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls);
/* Helper function for VIDIOC_S_CTRL compatibility */
-static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
+static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
+ struct v4l2_ext_control *c, u32 ch_flags)
{
struct v4l2_ctrl *master = ctrl->cluster[0];
- int ret;
int i;
/* Reset the 'is_new' flags of the cluster */
@@ -3189,9 +3181,8 @@
if (master->cluster[i])
master->cluster[i]->is_new = 0;
- ret = validate_new(ctrl, ctrl->p_new);
- if (ret)
- return ret;
+ if (c)
+ user_to_new(c, ctrl);
/* For autoclusters with volatiles that are switched from auto to
manual mode we have to update the current volatile values since
@@ -3208,14 +3199,15 @@
static int set_ctrl_lock(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
struct v4l2_ext_control *c)
{
- int ret;
+ int ret = validate_new(ctrl, c);
- v4l2_ctrl_lock(ctrl);
- user_to_new(c, ctrl);
- ret = set_ctrl(fh, ctrl, 0);
- if (!ret)
- cur_to_user(c, ctrl);
- v4l2_ctrl_unlock(ctrl);
+ if (!ret) {
+ v4l2_ctrl_lock(ctrl);
+ ret = set_ctrl(fh, ctrl, c, 0);
+ if (!ret)
+ cur_to_user(c, ctrl);
+ v4l2_ctrl_unlock(ctrl);
+ }
return ret;
}
@@ -3223,7 +3215,7 @@
struct v4l2_control *control)
{
struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
- struct v4l2_ext_control c = { control->id };
+ struct v4l2_ext_control c;
int ret;
if (ctrl == NULL || !ctrl->is_int)
@@ -3252,7 +3244,7 @@
/* It's a driver bug if this happens. */
WARN_ON(!ctrl->is_int);
ctrl->val = val;
- return set_ctrl(NULL, ctrl, 0);
+ return set_ctrl(NULL, ctrl, NULL, 0);
}
EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
@@ -3263,7 +3255,7 @@
/* It's a driver bug if this happens. */
WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
*ctrl->p_new.p_s64 = val;
- return set_ctrl(NULL, ctrl, 0);
+ return set_ctrl(NULL, ctrl, NULL, 0);
}
EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
@@ -3274,7 +3266,7 @@
/* It's a driver bug if this happens. */
WARN_ON(ctrl->type != V4L2_CTRL_TYPE_STRING);
strlcpy(ctrl->p_new.p_char, s, ctrl->maximum + 1);
- return set_ctrl(NULL, ctrl, 0);
+ return set_ctrl(NULL, ctrl, NULL, 0);
}
EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_string);
@@ -3297,8 +3289,8 @@
int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
s64 min, s64 max, u64 step, s64 def)
{
- bool changed;
int ret;
+ struct v4l2_ext_control c;
lockdep_assert_held(ctrl->handler->lock);
@@ -3325,20 +3317,11 @@
ctrl->maximum = max;
ctrl->step = step;
ctrl->default_value = def;
- cur_to_new(ctrl);
- if (validate_new(ctrl, ctrl->p_new)) {
- if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
- *ctrl->p_new.p_s64 = def;
- else
- *ctrl->p_new.p_s32 = def;
- }
-
- if (ctrl->type == V4L2_CTRL_TYPE_INTEGER64)
- changed = *ctrl->p_new.p_s64 != *ctrl->p_cur.p_s64;
- else
- changed = *ctrl->p_new.p_s32 != *ctrl->p_cur.p_s32;
- if (changed)
- ret = set_ctrl(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
+ c.value = *ctrl->p_cur.p_s32;
+ if (validate_new(ctrl, &c))
+ c.value = def;
+ if (c.value != *ctrl->p_cur.p_s32)
+ ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE);
else
send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
return ret;
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 7385fc2..7953699 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -199,7 +199,7 @@
mutex_unlock(&videodev_lock);
#if defined(CPTCFG_MEDIA_CONTROLLER)
- if (v4l2_dev->mdev &&
+ if (v4l2_dev && v4l2_dev->mdev &&
vdev->vfl_type != VFL_TYPE_SUBDEV)
media_device_unregister_entity(&vdev->entity);
#endif
@@ -212,7 +212,7 @@
* TODO: In the long run all drivers that use v4l2_device should use the
* v4l2_device release callback. This check will then be unnecessary.
*/
- if (v4l2_dev->release == NULL)
+ if (v4l2_dev && v4l2_dev->release == NULL)
v4l2_dev = NULL;
/* Release video_device and perform other
@@ -369,22 +369,27 @@
* hack but it will have to do for those drivers that are not
* yet converted to use unlocked_ioctl.
*
- * All drivers implement struct v4l2_device, so we use the
- * lock defined there to serialize the ioctls.
+ * There are two options: if the driver implements struct
+ * v4l2_device, then the lock defined there is used to
+ * serialize the ioctls. Otherwise the v4l2 core lock defined
+ * below is used. This lock is really bad since it serializes
+ * completely independent devices.
*
- * However, if the driver sleeps, then it blocks all ioctls
- * since the lock is still held. This is very common for
- * VIDIOC_DQBUF since that normally waits for a frame to arrive.
- * As a result any other ioctl calls will proceed very, very
- * slowly since each call will have to wait for the VIDIOC_QBUF
- * to finish. Things that should take 0.01s may now take 10-20
- * seconds.
+ * Both variants suffer from the same problem: if the driver
+ * sleeps, then it blocks all ioctls since the lock is still
+ * held. This is very common for VIDIOC_DQBUF since that
+ * normally waits for a frame to arrive. As a result any other
+ * ioctl calls will proceed very, very slowly since each call
+ * will have to wait for the VIDIOC_QBUF to finish. Things that
+ * should take 0.01s may now take 10-20 seconds.
*
* The workaround is to *not* take the lock for VIDIOC_DQBUF.
* This actually works OK for videobuf-based drivers, since
* videobuf will take its own internal lock.
*/
- struct mutex *m = &vdev->v4l2_dev->ioctl_lock;
+ static DEFINE_MUTEX(v4l2_ioctl_mutex);
+ struct mutex *m = vdev->v4l2_dev ?
+ &vdev->v4l2_dev->ioctl_lock : &v4l2_ioctl_mutex;
if (cmd != VIDIOC_DQBUF && mutex_lock_interruptible(m))
return -ERESTARTSYS;
@@ -942,11 +947,12 @@
name_base, nr, video_device_node_name(vdev));
/* Increase v4l2_device refcount */
- v4l2_device_get(vdev->v4l2_dev);
+ if (vdev->v4l2_dev)
+ v4l2_device_get(vdev->v4l2_dev);
#if defined(CPTCFG_MEDIA_CONTROLLER)
/* Part 5: Register the entity. */
- if (vdev->v4l2_dev->mdev &&
+ if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
vdev->vfl_type != VFL_TYPE_SUBDEV) {
vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
vdev->entity.name = vdev->name;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index e20f1c9..a47079b 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -257,7 +257,7 @@
pr_cont(", width=%u, height=%u, "
"pixelformat=%c%c%c%c, field=%s, "
"bytesperline=%u, sizeimage=%u, colorspace=%d, "
- "flags %x, ycbcr_enc=%u, quantization=%u\n",
+ "flags %u\n",
pix->width, pix->height,
(pix->pixelformat & 0xff),
(pix->pixelformat >> 8) & 0xff,
@@ -265,24 +265,21 @@
(pix->pixelformat >> 24) & 0xff,
prt_names(pix->field, v4l2_field_names),
pix->bytesperline, pix->sizeimage,
- pix->colorspace, pix->flags, pix->ycbcr_enc,
- pix->quantization);
+ pix->colorspace, pix->flags);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
mp = &p->fmt.pix_mp;
pr_cont(", width=%u, height=%u, "
"format=%c%c%c%c, field=%s, "
- "colorspace=%d, num_planes=%u, flags=%x, "
- "ycbcr_enc=%u, quantization=%u\n",
+ "colorspace=%d, num_planes=%u\n",
mp->width, mp->height,
(mp->pixelformat & 0xff),
(mp->pixelformat >> 8) & 0xff,
(mp->pixelformat >> 16) & 0xff,
(mp->pixelformat >> 24) & 0xff,
prt_names(mp->field, v4l2_field_names),
- mp->colorspace, mp->num_planes, mp->flags,
- mp->ycbcr_enc, mp->quantization);
+ mp->colorspace, mp->num_planes);
for (i = 0; i < mp->num_planes; i++)
printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
mp->plane_fmt[i].bytesperline,
@@ -1017,12 +1014,6 @@
ret = ops->vidioc_querycap(file, fh, cap);
cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
- /*
- * Drivers MUST fill in device_caps, so check for this and
- * warn if it was forgotten.
- */
- WARN_ON(!(cap->capabilities & V4L2_CAP_DEVICE_CAPS) ||
- !cap->device_caps);
cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT;
return ret;
@@ -1049,7 +1040,7 @@
if (ops->vidioc_g_priority)
return ops->vidioc_g_priority(file, fh, arg);
vfd = video_devdata(file);
- *p = v4l2_prio_max(vfd->prio);
+ *p = v4l2_prio_max(&vfd->v4l2_dev->prio);
return 0;
}
@@ -1064,7 +1055,7 @@
return ops->vidioc_s_priority(file, fh, *p);
vfd = video_devdata(file);
vfh = file->private_data;
- return v4l2_prio_change(vfd->prio, &vfh->prio, *p);
+ return v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
}
static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
diff --git a/drivers/media/v4l2-core/videobuf-core.c b/drivers/media/v4l2-core/videobuf-core.c
index 926836d..b91a266 100644
--- a/drivers/media/v4l2-core/videobuf-core.c
+++ b/drivers/media/v4l2-core/videobuf-core.c
@@ -51,8 +51,6 @@
#define CALL(q, f, arg...) \
((q->int_ops->f) ? q->int_ops->f(arg) : 0)
-#define CALLPTR(q, f, arg...) \
- ((q->int_ops->f) ? q->int_ops->f(arg) : NULL)
struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q)
{
@@ -833,7 +831,7 @@
char __user *data, size_t count,
int nonblocking)
{
- void *vaddr = CALLPTR(q, vaddr, buf);
+ void *vaddr = CALL(q, vaddr, buf);
/* copy to userspace */
if (count > buf->size - q->read_off)
@@ -850,7 +848,7 @@
char __user *data, size_t count, size_t pos,
int vbihack, int nonblocking)
{
- unsigned int *fc = CALLPTR(q, vaddr, buf);
+ unsigned int *fc = CALL(q, vaddr, buf);
if (vbihack) {
/* dirty, undocumented hack -- pass the frame counter
diff --git a/drivers/media/v4l2-core/videobuf-dma-contig.c b/drivers/media/v4l2-core/videobuf-dma-contig.c
index e02353e..bf80f0f 100644
--- a/drivers/media/v4l2-core/videobuf-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf-dma-contig.c
@@ -305,15 +305,6 @@
/* Try to remap memory */
size = vma->vm_end - vma->vm_start;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
- /* the "vm_pgoff" is just used in v4l2 to find the
- * corresponding buffer data structure which is allocated
- * earlier and it does not mean the offset from the physical
- * buffer start address as usual. So set it to 0 to pass
- * the sanity check in vm_iomap_memory().
- */
- vma->vm_pgoff = 0;
-
retval = vm_iomap_memory(vma, mem->dma_handle, size);
if (retval) {
dev_err(q->dev, "mmap: remap failed with error %d. ",
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index c20bdf7..e9d733e 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -189,8 +189,6 @@
static int __vb2_buf_mem_alloc(struct vb2_buffer *vb)
{
struct vb2_queue *q = vb->vb2_queue;
- enum dma_data_direction dma_dir =
- V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
void *mem_priv;
int plane;
@@ -202,7 +200,7 @@
unsigned long size = PAGE_ALIGN(q->plane_sizes[plane]);
mem_priv = call_ptr_memop(vb, alloc, q->alloc_ctx[plane],
- size, dma_dir, q->gfp_flags);
+ size, q->gfp_flags);
if (IS_ERR_OR_NULL(mem_priv))
goto free;
@@ -1368,8 +1366,7 @@
void *mem_priv;
unsigned int plane;
int ret;
- enum dma_data_direction dma_dir =
- V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ int write = !V4L2_TYPE_IS_OUTPUT(q->type);
bool reacquired = vb->planes[0].mem_priv == NULL;
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1411,7 +1408,7 @@
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, get_userptr, q->alloc_ctx[plane],
planes[plane].m.userptr,
- planes[plane].length, dma_dir);
+ planes[plane].length, write);
if (IS_ERR_OR_NULL(mem_priv)) {
dprintk(1, "failed acquiring userspace "
"memory for plane %d\n", plane);
@@ -1473,8 +1470,7 @@
void *mem_priv;
unsigned int plane;
int ret;
- enum dma_data_direction dma_dir =
- V4L2_TYPE_IS_OUTPUT(q->type) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ int write = !V4L2_TYPE_IS_OUTPUT(q->type);
bool reacquired = vb->planes[0].mem_priv == NULL;
memset(planes, 0, sizeof(planes[0]) * vb->num_planes);
@@ -1522,7 +1518,7 @@
/* Acquire each plane's memory */
mem_priv = call_ptr_memop(vb, attach_dmabuf, q->alloc_ctx[plane],
- dbuf, planes[plane].length, dma_dir);
+ dbuf, planes[plane].length, write);
if (IS_ERR(mem_priv)) {
dprintk(1, "failed to attach dmabuf\n");
ret = PTR_ERR(mem_priv);
@@ -3409,14 +3405,14 @@
{
struct video_device *vdev = video_devdata(file);
- if (lock)
- mutex_lock(lock);
if (file->private_data == vdev->queue->owner) {
+ if (lock)
+ mutex_lock(lock);
vb2_queue_release(vdev->queue);
vdev->queue->owner = NULL;
+ if (lock)
+ mutex_unlock(lock);
}
- if (lock)
- mutex_unlock(lock);
return v4l2_fh_release(file);
}
EXPORT_SYMBOL_GPL(_vb2_fop_release);
@@ -3479,16 +3475,27 @@
struct video_device *vdev = video_devdata(file);
struct vb2_queue *q = vdev->queue;
struct mutex *lock = q->lock ? q->lock : vdev->lock;
+ unsigned long req_events = poll_requested_events(wait);
unsigned res;
void *fileio;
+ bool must_lock = false;
- /*
- * If this helper doesn't know how to lock, then you shouldn't be using
- * it but you should write your own.
- */
- WARN_ON(!lock);
+ /* Try to be smart: only lock if polling might start fileio,
+ otherwise locking will only introduce unwanted delays. */
+ if (q->num_buffers == 0 && !vb2_fileio_is_active(q)) {
+ if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ) &&
+ (req_events & (POLLIN | POLLRDNORM)))
+ must_lock = true;
+ else if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE) &&
+ (req_events & (POLLOUT | POLLWRNORM)))
+ must_lock = true;
+ }
- if (lock && mutex_lock_interruptible(lock))
+ /* If locking is needed, but this helper doesn't know how, then you
+ shouldn't be using this helper but you should write your own. */
+ WARN_ON(must_lock && !lock);
+
+ if (must_lock && lock && mutex_lock_interruptible(lock))
return POLLERR;
fileio = q->fileio;
@@ -3496,9 +3503,9 @@
res = vb2_poll(vdev->queue, file, wait);
/* If fileio was started, then we have a new queue owner. */
- if (!fileio && q->fileio)
+ if (must_lock && !fileio && q->fileio)
q->owner = file->private_data;
- if (lock)
+ if (must_lock && lock)
mutex_unlock(lock);
return res;
}
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index d5e28df..058d979 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -157,8 +157,7 @@
kfree(buf);
}
-static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size,
- enum dma_data_direction dma_dir, gfp_t gfp_flags)
+static void *vb2_dc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
{
struct vb2_dc_conf *conf = alloc_ctx;
struct device *dev = conf->dev;
@@ -179,7 +178,6 @@
/* Prevent the device from being released while the buffer is used */
buf->dev = get_device(dev);
buf->size = size;
- buf->dma_dir = dma_dir;
buf->handler.refcount = &buf->refcount;
buf->handler.put = vb2_dc_put;
@@ -281,7 +279,7 @@
struct vb2_dc_attachment {
struct sg_table sgt;
- enum dma_data_direction dma_dir;
+ enum dma_data_direction dir;
};
static int vb2_dc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
@@ -316,7 +314,7 @@
wr = sg_next(wr);
}
- attach->dma_dir = DMA_NONE;
+ attach->dir = DMA_NONE;
dbuf_attach->priv = attach;
return 0;
@@ -334,16 +332,16 @@
sgt = &attach->sgt;
/* release the scatterlist cache */
- if (attach->dma_dir != DMA_NONE)
+ if (attach->dir != DMA_NONE)
dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
- attach->dma_dir);
+ attach->dir);
sg_free_table(sgt);
kfree(attach);
db_attach->priv = NULL;
}
static struct sg_table *vb2_dc_dmabuf_ops_map(
- struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
+ struct dma_buf_attachment *db_attach, enum dma_data_direction dir)
{
struct vb2_dc_attachment *attach = db_attach->priv;
/* stealing dmabuf mutex to serialize map/unmap operations */
@@ -355,27 +353,27 @@
sgt = &attach->sgt;
/* return previously mapped sg table */
- if (attach->dma_dir == dma_dir) {
+ if (attach->dir == dir) {
mutex_unlock(lock);
return sgt;
}
/* release any previous cache */
- if (attach->dma_dir != DMA_NONE) {
+ if (attach->dir != DMA_NONE) {
dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
- attach->dma_dir);
- attach->dma_dir = DMA_NONE;
+ attach->dir);
+ attach->dir = DMA_NONE;
}
/* mapping to the client with new direction */
- ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
+ ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dir);
if (ret <= 0) {
pr_err("failed to map scatterlist\n");
mutex_unlock(lock);
return ERR_PTR(-EIO);
}
- attach->dma_dir = dma_dir;
+ attach->dir = dir;
mutex_unlock(lock);
@@ -383,7 +381,7 @@
}
static void vb2_dc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
- struct sg_table *sgt, enum dma_data_direction dma_dir)
+ struct sg_table *sgt, enum dma_data_direction dir)
{
/* nothing to be done here */
}
@@ -513,8 +511,7 @@
}
static int vb2_dc_get_user_pages(unsigned long start, struct page **pages,
- int n_pages, struct vm_area_struct *vma,
- enum dma_data_direction dma_dir)
+ int n_pages, struct vm_area_struct *vma, int write)
{
if (vma_is_io(vma)) {
unsigned int i;
@@ -536,7 +533,7 @@
int n;
n = get_user_pages(current, current->mm, start & PAGE_MASK,
- n_pages, dma_dir == DMA_FROM_DEVICE, 1, pages, NULL);
+ n_pages, write, 1, pages, NULL);
/* negative error means that no page was pinned */
n = max(n, 0);
if (n != n_pages) {
@@ -562,17 +559,7 @@
struct sg_table *sgt = buf->dma_sgt;
if (sgt) {
- DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
- /*
- * No need to sync to CPU, it's already synced to the CPU
- * since the finish() memop will have been called before this.
- */
- dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, &attrs);
+ dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
if (!vma_is_io(buf->vma))
vb2_dc_sgt_foreach_page(sgt, vb2_dc_put_dirty_page);
@@ -615,7 +602,7 @@
#endif
static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
- unsigned long size, enum dma_data_direction dma_dir)
+ unsigned long size, int write)
{
struct vb2_dc_conf *conf = alloc_ctx;
struct vb2_dc_buf *buf;
@@ -629,11 +616,6 @@
struct sg_table *sgt;
unsigned long contig_size;
unsigned long dma_align = dma_get_cache_alignment();
- DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
/* Only cache aligned DMA transfers are reliable */
if (!IS_ALIGNED(vaddr | size, dma_align)) {
@@ -651,7 +633,7 @@
return ERR_PTR(-ENOMEM);
buf->dev = conf->dev;
- buf->dma_dir = dma_dir;
+ buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
start = vaddr & PAGE_MASK;
offset = vaddr & ~PAGE_MASK;
@@ -687,8 +669,7 @@
}
/* extract page list from userspace mapping */
- ret = vb2_dc_get_user_pages(start, pages, n_pages, vma,
- dma_dir == DMA_FROM_DEVICE);
+ ret = vb2_dc_get_user_pages(start, pages, n_pages, vma, write);
if (ret) {
unsigned long pfn;
if (vb2_dc_get_user_pfn(start, n_pages, vma, &pfn) == 0) {
@@ -720,12 +701,8 @@
kfree(pages);
pages = NULL;
- /*
- * No need to sync to the device, this will happen later when the
- * prepare() memop is called.
- */
- sgt->nents = dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, &attrs);
+ sgt->nents = dma_map_sg(buf->dev, sgt->sgl, sgt->orig_nents,
+ buf->dma_dir);
if (sgt->nents <= 0) {
pr_err("failed to map scatterlist\n");
ret = -EIO;
@@ -747,8 +724,7 @@
return buf;
fail_map_sg:
- dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->orig_nents,
- buf->dma_dir, &attrs);
+ dma_unmap_sg(buf->dev, sgt->sgl, sgt->orig_nents, buf->dma_dir);
fail_sgt_init:
if (!vma_is_io(buf->vma))
@@ -858,7 +834,7 @@
}
static void *vb2_dc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
- unsigned long size, enum dma_data_direction dma_dir)
+ unsigned long size, int write)
{
struct vb2_dc_conf *conf = alloc_ctx;
struct vb2_dc_buf *buf;
@@ -880,7 +856,7 @@
return dba;
}
- buf->dma_dir = dma_dir;
+ buf->dma_dir = write ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
buf->size = size;
buf->db_attach = dba;
@@ -931,8 +907,7 @@
void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
{
- if (!IS_ERR_OR_NULL(alloc_ctx))
- kfree(alloc_ctx);
+ kfree(alloc_ctx);
}
EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx);
diff --git a/drivers/media/v4l2-core/videobuf2-dma-sg.c b/drivers/media/v4l2-core/videobuf2-dma-sg.c
index 18f9f42..9b163a4 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-sg.c
@@ -30,30 +30,17 @@
printk(KERN_DEBUG "vb2-dma-sg: " fmt, ## arg); \
} while (0)
-struct vb2_dma_sg_conf {
- struct device *dev;
-};
-
struct vb2_dma_sg_buf {
- struct device *dev;
void *vaddr;
struct page **pages;
+ int write;
int offset;
- enum dma_data_direction dma_dir;
struct sg_table sg_table;
- /*
- * This will point to sg_table when used with the MMAP or USERPTR
- * memory model, and to the dma_buf sglist when used with the
- * DMABUF memory model.
- */
- struct sg_table *dma_sgt;
size_t size;
unsigned int num_pages;
atomic_t refcount;
struct vb2_vmarea_handler handler;
struct vm_area_struct *vma;
-
- struct dma_buf_attachment *db_attach;
};
static void vb2_dma_sg_put(void *buf_priv);
@@ -99,33 +86,22 @@
return 0;
}
-static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size,
- enum dma_data_direction dma_dir, gfp_t gfp_flags)
+static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
{
- struct vb2_dma_sg_conf *conf = alloc_ctx;
struct vb2_dma_sg_buf *buf;
- struct sg_table *sgt;
int ret;
int num_pages;
- DEFINE_DMA_ATTRS(attrs);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
-
- if (WARN_ON(alloc_ctx == NULL))
- return NULL;
buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)
return NULL;
buf->vaddr = NULL;
- buf->dma_dir = dma_dir;
+ buf->write = 0;
buf->offset = 0;
buf->size = size;
/* size is already page aligned */
buf->num_pages = size >> PAGE_SHIFT;
- buf->dma_sgt = &buf->sg_table;
buf->pages = kzalloc(buf->num_pages * sizeof(struct page *),
GFP_KERNEL);
@@ -136,23 +112,11 @@
if (ret)
goto fail_pages_alloc;
- ret = sg_alloc_table_from_pages(buf->dma_sgt, buf->pages,
+ ret = sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
buf->num_pages, 0, size, GFP_KERNEL);
if (ret)
goto fail_table_alloc;
- /* Prevent the device from being released while the buffer is used */
- buf->dev = get_device(conf->dev);
-
- sgt = &buf->sg_table;
- /*
- * No need to sync to the device, this will happen later when the
- * prepare() memop is called.
- */
- if (dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->nents,
- buf->dma_dir, &attrs) == 0)
- goto fail_map;
-
buf->handler.refcount = &buf->refcount;
buf->handler.put = vb2_dma_sg_put;
buf->handler.arg = buf;
@@ -163,9 +127,6 @@
__func__, buf->num_pages);
return buf;
-fail_map:
- put_device(buf->dev);
- sg_free_table(buf->dma_sgt);
fail_table_alloc:
num_pages = buf->num_pages;
while (num_pages--)
@@ -180,85 +141,42 @@
static void vb2_dma_sg_put(void *buf_priv)
{
struct vb2_dma_sg_buf *buf = buf_priv;
- struct sg_table *sgt = &buf->sg_table;
int i = buf->num_pages;
if (atomic_dec_and_test(&buf->refcount)) {
- DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
dprintk(1, "%s: Freeing buffer of %d pages\n", __func__,
buf->num_pages);
- dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->nents,
- buf->dma_dir, &attrs);
if (buf->vaddr)
vm_unmap_ram(buf->vaddr, buf->num_pages);
- sg_free_table(buf->dma_sgt);
+ sg_free_table(&buf->sg_table);
while (--i >= 0)
__free_page(buf->pages[i]);
kfree(buf->pages);
- put_device(buf->dev);
kfree(buf);
}
}
-static void vb2_dma_sg_prepare(void *buf_priv)
-{
- struct vb2_dma_sg_buf *buf = buf_priv;
- struct sg_table *sgt = buf->dma_sgt;
-
- /* DMABUF exporter will flush the cache for us */
- if (buf->db_attach)
- return;
-
- dma_sync_sg_for_device(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
-}
-
-static void vb2_dma_sg_finish(void *buf_priv)
-{
- struct vb2_dma_sg_buf *buf = buf_priv;
- struct sg_table *sgt = buf->dma_sgt;
-
- /* DMABUF exporter will flush the cache for us */
- if (buf->db_attach)
- return;
-
- dma_sync_sg_for_cpu(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir);
-}
-
static inline int vma_is_io(struct vm_area_struct *vma)
{
return !!(vma->vm_flags & (VM_IO | VM_PFNMAP));
}
static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
- unsigned long size,
- enum dma_data_direction dma_dir)
+ unsigned long size, int write)
{
- struct vb2_dma_sg_conf *conf = alloc_ctx;
struct vb2_dma_sg_buf *buf;
unsigned long first, last;
int num_pages_from_user;
struct vm_area_struct *vma;
- struct sg_table *sgt;
- DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
buf = kzalloc(sizeof *buf, GFP_KERNEL);
if (!buf)
return NULL;
buf->vaddr = NULL;
- buf->dev = conf->dev;
- buf->dma_dir = dma_dir;
+ buf->write = write;
buf->offset = vaddr & ~PAGE_MASK;
buf->size = size;
- buf->dma_sgt = &buf->sg_table;
first = (vaddr & PAGE_MASK) >> PAGE_SHIFT;
last = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
@@ -303,7 +221,7 @@
num_pages_from_user = get_user_pages(current, current->mm,
vaddr & PAGE_MASK,
buf->num_pages,
- buf->dma_dir == DMA_FROM_DEVICE,
+ write,
1, /* force */
buf->pages,
NULL);
@@ -311,22 +229,12 @@
if (num_pages_from_user != buf->num_pages)
goto userptr_fail_get_user_pages;
- if (sg_alloc_table_from_pages(buf->dma_sgt, buf->pages,
+ if (sg_alloc_table_from_pages(&buf->sg_table, buf->pages,
buf->num_pages, buf->offset, size, 0))
goto userptr_fail_alloc_table_from_pages;
- sgt = &buf->sg_table;
- /*
- * No need to sync to the device, this will happen later when the
- * prepare() memop is called.
- */
- if (dma_map_sg_attrs(buf->dev, sgt->sgl, sgt->nents,
- buf->dma_dir, &attrs) == 0)
- goto userptr_fail_map;
return buf;
-userptr_fail_map:
- sg_free_table(&buf->sg_table);
userptr_fail_alloc_table_from_pages:
userptr_fail_get_user_pages:
dprintk(1, "get_user_pages requested/got: %d/%d]\n",
@@ -349,22 +257,15 @@
static void vb2_dma_sg_put_userptr(void *buf_priv)
{
struct vb2_dma_sg_buf *buf = buf_priv;
- struct sg_table *sgt = &buf->sg_table;
int i = buf->num_pages;
- DEFINE_DMA_ATTRS(attrs);
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
-#endif
dprintk(1, "%s: Releasing userspace buffer of %d pages\n",
__func__, buf->num_pages);
- dma_unmap_sg_attrs(buf->dev, sgt->sgl, sgt->nents, buf->dma_dir, &attrs);
if (buf->vaddr)
vm_unmap_ram(buf->vaddr, buf->num_pages);
- sg_free_table(buf->dma_sgt);
+ sg_free_table(&buf->sg_table);
while (--i >= 0) {
- if (buf->dma_dir == DMA_FROM_DEVICE)
+ if (buf->write)
set_page_dirty_lock(buf->pages[i]);
if (!vma_is_io(buf->vma))
put_page(buf->pages[i]);
@@ -380,18 +281,14 @@
BUG_ON(!buf);
- if (!buf->vaddr) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- if (buf->db_attach)
- buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
- else
-#endif
- buf->vaddr = vm_map_ram(buf->pages,
- buf->num_pages, -1, PAGE_KERNEL);
- }
+ if (!buf->vaddr)
+ buf->vaddr = vm_map_ram(buf->pages,
+ buf->num_pages,
+ -1,
+ PAGE_KERNEL);
/* add offset in case userptr is not page-aligned */
- return buf->vaddr ? buf->vaddr + buf->offset : NULL;
+ return buf->vaddr + buf->offset;
}
static unsigned int vb2_dma_sg_num_users(void *buf_priv)
@@ -438,281 +335,11 @@
return 0;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-/*********************************************/
-/* DMABUF ops for exporters */
-/*********************************************/
-
-struct vb2_dma_sg_attachment {
- struct sg_table sgt;
- enum dma_data_direction dma_dir;
-};
-
-static int vb2_dma_sg_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
- struct dma_buf_attachment *dbuf_attach)
-{
- struct vb2_dma_sg_attachment *attach;
- unsigned int i;
- struct scatterlist *rd, *wr;
- struct sg_table *sgt;
- struct vb2_dma_sg_buf *buf = dbuf->priv;
- int ret;
-
- attach = kzalloc(sizeof(*attach), GFP_KERNEL);
- if (!attach)
- return -ENOMEM;
-
- sgt = &attach->sgt;
- /* Copy the buf->base_sgt scatter list to the attachment, as we can't
- * map the same scatter list to multiple attachments at the same time.
- */
- ret = sg_alloc_table(sgt, buf->dma_sgt->orig_nents, GFP_KERNEL);
- if (ret) {
- kfree(attach);
- return -ENOMEM;
- }
-
- rd = buf->dma_sgt->sgl;
- wr = sgt->sgl;
- for (i = 0; i < sgt->orig_nents; ++i) {
- sg_set_page(wr, sg_page(rd), rd->length, rd->offset);
- rd = sg_next(rd);
- wr = sg_next(wr);
- }
-
- attach->dma_dir = DMA_NONE;
- dbuf_attach->priv = attach;
-
- return 0;
-}
-
-static void vb2_dma_sg_dmabuf_ops_detach(struct dma_buf *dbuf,
- struct dma_buf_attachment *db_attach)
-{
- struct vb2_dma_sg_attachment *attach = db_attach->priv;
- struct sg_table *sgt;
-
- if (!attach)
- return;
-
- sgt = &attach->sgt;
-
- /* release the scatterlist cache */
- if (attach->dma_dir != DMA_NONE)
- dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
- attach->dma_dir);
- sg_free_table(sgt);
- kfree(attach);
- db_attach->priv = NULL;
-}
-
-static struct sg_table *vb2_dma_sg_dmabuf_ops_map(
- struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
-{
- struct vb2_dma_sg_attachment *attach = db_attach->priv;
- /* stealing dmabuf mutex to serialize map/unmap operations */
- struct mutex *lock = &db_attach->dmabuf->lock;
- struct sg_table *sgt;
- int ret;
-
- mutex_lock(lock);
-
- sgt = &attach->sgt;
- /* return previously mapped sg table */
- if (attach->dma_dir == dma_dir) {
- mutex_unlock(lock);
- return sgt;
- }
-
- /* release any previous cache */
- if (attach->dma_dir != DMA_NONE) {
- dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
- attach->dma_dir);
- attach->dma_dir = DMA_NONE;
- }
-
- /* mapping to the client with new direction */
- ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
- if (ret <= 0) {
- pr_err("failed to map scatterlist\n");
- mutex_unlock(lock);
- return ERR_PTR(-EIO);
- }
-
- attach->dma_dir = dma_dir;
-
- mutex_unlock(lock);
-
- return sgt;
-}
-
-static void vb2_dma_sg_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
- struct sg_table *sgt, enum dma_data_direction dma_dir)
-{
- /* nothing to be done here */
-}
-
-static void vb2_dma_sg_dmabuf_ops_release(struct dma_buf *dbuf)
-{
- /* drop reference obtained in vb2_dma_sg_get_dmabuf */
- vb2_dma_sg_put(dbuf->priv);
-}
-
-static void *vb2_dma_sg_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
-{
- struct vb2_dma_sg_buf *buf = dbuf->priv;
-
- return buf->vaddr ? buf->vaddr + pgnum * PAGE_SIZE : NULL;
-}
-
-static void *vb2_dma_sg_dmabuf_ops_vmap(struct dma_buf *dbuf)
-{
- struct vb2_dma_sg_buf *buf = dbuf->priv;
-
- return vb2_dma_sg_vaddr(buf);
-}
-
-static int vb2_dma_sg_dmabuf_ops_mmap(struct dma_buf *dbuf,
- struct vm_area_struct *vma)
-{
- return vb2_dma_sg_mmap(dbuf->priv, vma);
-}
-
-static struct dma_buf_ops vb2_dma_sg_dmabuf_ops = {
- .attach = vb2_dma_sg_dmabuf_ops_attach,
- .detach = vb2_dma_sg_dmabuf_ops_detach,
- .map_dma_buf = vb2_dma_sg_dmabuf_ops_map,
- .unmap_dma_buf = vb2_dma_sg_dmabuf_ops_unmap,
- .kmap = vb2_dma_sg_dmabuf_ops_kmap,
- .kmap_atomic = vb2_dma_sg_dmabuf_ops_kmap,
- .vmap = vb2_dma_sg_dmabuf_ops_vmap,
- .mmap = vb2_dma_sg_dmabuf_ops_mmap,
- .release = vb2_dma_sg_dmabuf_ops_release,
-};
-
-static struct dma_buf *vb2_dma_sg_get_dmabuf(void *buf_priv, unsigned long flags)
-{
- struct vb2_dma_sg_buf *buf = buf_priv;
- struct dma_buf *dbuf;
-
- if (WARN_ON(!buf->dma_sgt))
- return NULL;
-
- dbuf = dma_buf_export(buf, &vb2_dma_sg_dmabuf_ops, buf->size, flags, NULL);
- if (IS_ERR(dbuf))
- return NULL;
-
- /* dmabuf keeps reference to vb2 buffer */
- atomic_inc(&buf->refcount);
-
- return dbuf;
-}
-
-/*********************************************/
-/* callbacks for DMABUF buffers */
-/*********************************************/
-
-static int vb2_dma_sg_map_dmabuf(void *mem_priv)
-{
- struct vb2_dma_sg_buf *buf = mem_priv;
- struct sg_table *sgt;
-
- if (WARN_ON(!buf->db_attach)) {
- pr_err("trying to pin a non attached buffer\n");
- return -EINVAL;
- }
-
- if (WARN_ON(buf->dma_sgt)) {
- pr_err("dmabuf buffer is already pinned\n");
- return 0;
- }
-
- /* get the associated scatterlist for this buffer */
- sgt = dma_buf_map_attachment(buf->db_attach, buf->dma_dir);
- if (IS_ERR(sgt)) {
- pr_err("Error getting dmabuf scatterlist\n");
- return -EINVAL;
- }
-
- buf->dma_sgt = sgt;
- buf->vaddr = NULL;
-
- return 0;
-}
-
-static void vb2_dma_sg_unmap_dmabuf(void *mem_priv)
-{
- struct vb2_dma_sg_buf *buf = mem_priv;
- struct sg_table *sgt = buf->dma_sgt;
-
- if (WARN_ON(!buf->db_attach)) {
- pr_err("trying to unpin a not attached buffer\n");
- return;
- }
-
- if (WARN_ON(!sgt)) {
- pr_err("dmabuf buffer is already unpinned\n");
- return;
- }
-
- if (buf->vaddr) {
- dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
- buf->vaddr = NULL;
- }
- dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
-
- buf->dma_sgt = NULL;
-}
-
-static void vb2_dma_sg_detach_dmabuf(void *mem_priv)
-{
- struct vb2_dma_sg_buf *buf = mem_priv;
-
- /* if vb2 works correctly you should never detach mapped buffer */
- if (WARN_ON(buf->dma_sgt))
- vb2_dma_sg_unmap_dmabuf(buf);
-
- /* detach this attachment */
- dma_buf_detach(buf->db_attach->dmabuf, buf->db_attach);
- kfree(buf);
-}
-
-static void *vb2_dma_sg_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
- unsigned long size, enum dma_data_direction dma_dir)
-{
- struct vb2_dma_sg_conf *conf = alloc_ctx;
- struct vb2_dma_sg_buf *buf;
- struct dma_buf_attachment *dba;
-
- if (dbuf->size < size)
- return ERR_PTR(-EFAULT);
-
- buf = kzalloc(sizeof(*buf), GFP_KERNEL);
- if (!buf)
- return ERR_PTR(-ENOMEM);
-
- buf->dev = conf->dev;
- /* create attachment for the dmabuf with the user device */
- dba = dma_buf_attach(dbuf, buf->dev);
- if (IS_ERR(dba)) {
- pr_err("failed to attach dmabuf\n");
- kfree(buf);
- return dba;
- }
-
- buf->dma_dir = dma_dir;
- buf->size = size;
- buf->db_attach = dba;
-
- return buf;
-}
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) */
-
static void *vb2_dma_sg_cookie(void *buf_priv)
{
struct vb2_dma_sg_buf *buf = buf_priv;
- return buf->dma_sgt;
+ return &buf->sg_table;
}
const struct vb2_mem_ops vb2_dma_sg_memops = {
@@ -720,43 +347,13 @@
.put = vb2_dma_sg_put,
.get_userptr = vb2_dma_sg_get_userptr,
.put_userptr = vb2_dma_sg_put_userptr,
- .prepare = vb2_dma_sg_prepare,
- .finish = vb2_dma_sg_finish,
.vaddr = vb2_dma_sg_vaddr,
.mmap = vb2_dma_sg_mmap,
.num_users = vb2_dma_sg_num_users,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- .get_dmabuf = vb2_dma_sg_get_dmabuf,
- .map_dmabuf = vb2_dma_sg_map_dmabuf,
- .unmap_dmabuf = vb2_dma_sg_unmap_dmabuf,
- .attach_dmabuf = vb2_dma_sg_attach_dmabuf,
- .detach_dmabuf = vb2_dma_sg_detach_dmabuf,
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) */
.cookie = vb2_dma_sg_cookie,
};
EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
-void *vb2_dma_sg_init_ctx(struct device *dev)
-{
- struct vb2_dma_sg_conf *conf;
-
- conf = kzalloc(sizeof(*conf), GFP_KERNEL);
- if (!conf)
- return ERR_PTR(-ENOMEM);
-
- conf->dev = dev;
-
- return conf;
-}
-EXPORT_SYMBOL_GPL(vb2_dma_sg_init_ctx);
-
-void vb2_dma_sg_cleanup_ctx(void *alloc_ctx)
-{
- if (!IS_ERR_OR_NULL(alloc_ctx))
- kfree(alloc_ctx);
-}
-EXPORT_SYMBOL_GPL(vb2_dma_sg_cleanup_ctx);
-
MODULE_DESCRIPTION("dma scatter/gather memory handling routines for videobuf2");
MODULE_AUTHOR("Andrzej Pietrasiewicz");
MODULE_LICENSE("GPL");
diff --git a/drivers/media/v4l2-core/videobuf2-vmalloc.c b/drivers/media/v4l2-core/videobuf2-vmalloc.c
index 272a83d..59ef98c 100644
--- a/drivers/media/v4l2-core/videobuf2-vmalloc.c
+++ b/drivers/media/v4l2-core/videobuf2-vmalloc.c
@@ -25,7 +25,7 @@
void *vaddr;
struct page **pages;
struct vm_area_struct *vma;
- enum dma_data_direction dma_dir;
+ int write;
unsigned long size;
unsigned int n_pages;
atomic_t refcount;
@@ -37,8 +37,7 @@
static void vb2_vmalloc_put(void *buf_priv);
-static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size,
- enum dma_data_direction dma_dir, gfp_t gfp_flags)
+static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size, gfp_t gfp_flags)
{
struct vb2_vmalloc_buf *buf;
@@ -48,7 +47,6 @@
buf->size = size;
buf->vaddr = vmalloc_user(buf->size);
- buf->dma_dir = dma_dir;
buf->handler.refcount = &buf->refcount;
buf->handler.put = vb2_vmalloc_put;
buf->handler.arg = buf;
@@ -74,8 +72,7 @@
}
static void *vb2_vmalloc_get_userptr(void *alloc_ctx, unsigned long vaddr,
- unsigned long size,
- enum dma_data_direction dma_dir)
+ unsigned long size, int write)
{
struct vb2_vmalloc_buf *buf;
unsigned long first, last;
@@ -87,7 +84,7 @@
if (!buf)
return NULL;
- buf->dma_dir = dma_dir;
+ buf->write = write;
offset = vaddr & ~PAGE_MASK;
buf->size = size;
@@ -112,8 +109,7 @@
/* current->mm->mmap_sem is taken by videobuf2 core */
n_pages = get_user_pages(current, current->mm,
vaddr & PAGE_MASK, buf->n_pages,
- dma_dir == DMA_FROM_DEVICE,
- 1, /* force */
+ write, 1, /* force */
buf->pages, NULL);
if (n_pages != buf->n_pages)
goto fail_get_user_pages;
@@ -150,13 +146,14 @@
if (vaddr)
vm_unmap_ram((void *)vaddr, buf->n_pages);
for (i = 0; i < buf->n_pages; ++i) {
- if (buf->dma_dir == DMA_FROM_DEVICE)
+ if (buf->write)
set_page_dirty_lock(buf->pages[i]);
put_page(buf->pages[i]);
}
kfree(buf->pages);
} else {
- vb2_put_vma(buf->vma);
+ if (buf->vma)
+ vb2_put_vma(buf->vma);
iounmap(buf->vaddr);
}
kfree(buf);
@@ -213,177 +210,7 @@
return 0;
}
-/*********************************************/
-/* DMABUF ops for exporters */
-/*********************************************/
-
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
-struct vb2_vmalloc_attachment {
- struct sg_table sgt;
- enum dma_data_direction dma_dir;
-};
-
-static int vb2_vmalloc_dmabuf_ops_attach(struct dma_buf *dbuf, struct device *dev,
- struct dma_buf_attachment *dbuf_attach)
-{
- struct vb2_vmalloc_attachment *attach;
- struct vb2_vmalloc_buf *buf = dbuf->priv;
- int num_pages = PAGE_ALIGN(buf->size) / PAGE_SIZE;
- struct sg_table *sgt;
- struct scatterlist *sg;
- void *vaddr = buf->vaddr;
- int ret;
- int i;
-
- attach = kzalloc(sizeof(*attach), GFP_KERNEL);
- if (!attach)
- return -ENOMEM;
-
- sgt = &attach->sgt;
- ret = sg_alloc_table(sgt, num_pages, GFP_KERNEL);
- if (ret) {
- kfree(attach);
- return ret;
- }
- for_each_sg(sgt->sgl, sg, sgt->nents, i) {
- struct page *page = vmalloc_to_page(vaddr);
-
- if (!page) {
- sg_free_table(sgt);
- kfree(attach);
- return -ENOMEM;
- }
- sg_set_page(sg, page, PAGE_SIZE, 0);
- vaddr += PAGE_SIZE;
- }
-
- attach->dma_dir = DMA_NONE;
- dbuf_attach->priv = attach;
- return 0;
-}
-
-static void vb2_vmalloc_dmabuf_ops_detach(struct dma_buf *dbuf,
- struct dma_buf_attachment *db_attach)
-{
- struct vb2_vmalloc_attachment *attach = db_attach->priv;
- struct sg_table *sgt;
-
- if (!attach)
- return;
-
- sgt = &attach->sgt;
-
- /* release the scatterlist cache */
- if (attach->dma_dir != DMA_NONE)
- dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
- attach->dma_dir);
- sg_free_table(sgt);
- kfree(attach);
- db_attach->priv = NULL;
-}
-
-static struct sg_table *vb2_vmalloc_dmabuf_ops_map(
- struct dma_buf_attachment *db_attach, enum dma_data_direction dma_dir)
-{
- struct vb2_vmalloc_attachment *attach = db_attach->priv;
- /* stealing dmabuf mutex to serialize map/unmap operations */
- struct mutex *lock = &db_attach->dmabuf->lock;
- struct sg_table *sgt;
- int ret;
-
- mutex_lock(lock);
-
- sgt = &attach->sgt;
- /* return previously mapped sg table */
- if (attach->dma_dir == dma_dir) {
- mutex_unlock(lock);
- return sgt;
- }
-
- /* release any previous cache */
- if (attach->dma_dir != DMA_NONE) {
- dma_unmap_sg(db_attach->dev, sgt->sgl, sgt->orig_nents,
- attach->dma_dir);
- attach->dma_dir = DMA_NONE;
- }
-
- /* mapping to the client with new direction */
- ret = dma_map_sg(db_attach->dev, sgt->sgl, sgt->orig_nents, dma_dir);
- if (ret <= 0) {
- pr_err("failed to map scatterlist\n");
- mutex_unlock(lock);
- return ERR_PTR(-EIO);
- }
-
- attach->dma_dir = dma_dir;
-
- mutex_unlock(lock);
-
- return sgt;
-}
-
-static void vb2_vmalloc_dmabuf_ops_unmap(struct dma_buf_attachment *db_attach,
- struct sg_table *sgt, enum dma_data_direction dma_dir)
-{
- /* nothing to be done here */
-}
-
-static void vb2_vmalloc_dmabuf_ops_release(struct dma_buf *dbuf)
-{
- /* drop reference obtained in vb2_vmalloc_get_dmabuf */
- vb2_vmalloc_put(dbuf->priv);
-}
-
-static void *vb2_vmalloc_dmabuf_ops_kmap(struct dma_buf *dbuf, unsigned long pgnum)
-{
- struct vb2_vmalloc_buf *buf = dbuf->priv;
-
- return buf->vaddr + pgnum * PAGE_SIZE;
-}
-
-static void *vb2_vmalloc_dmabuf_ops_vmap(struct dma_buf *dbuf)
-{
- struct vb2_vmalloc_buf *buf = dbuf->priv;
-
- return buf->vaddr;
-}
-
-static int vb2_vmalloc_dmabuf_ops_mmap(struct dma_buf *dbuf,
- struct vm_area_struct *vma)
-{
- return vb2_vmalloc_mmap(dbuf->priv, vma);
-}
-
-static struct dma_buf_ops vb2_vmalloc_dmabuf_ops = {
- .attach = vb2_vmalloc_dmabuf_ops_attach,
- .detach = vb2_vmalloc_dmabuf_ops_detach,
- .map_dma_buf = vb2_vmalloc_dmabuf_ops_map,
- .unmap_dma_buf = vb2_vmalloc_dmabuf_ops_unmap,
- .kmap = vb2_vmalloc_dmabuf_ops_kmap,
- .kmap_atomic = vb2_vmalloc_dmabuf_ops_kmap,
- .vmap = vb2_vmalloc_dmabuf_ops_vmap,
- .mmap = vb2_vmalloc_dmabuf_ops_mmap,
- .release = vb2_vmalloc_dmabuf_ops_release,
-};
-
-static struct dma_buf *vb2_vmalloc_get_dmabuf(void *buf_priv, unsigned long flags)
-{
- struct vb2_vmalloc_buf *buf = buf_priv;
- struct dma_buf *dbuf;
-
- if (WARN_ON(!buf->vaddr))
- return NULL;
-
- dbuf = dma_buf_export(buf, &vb2_vmalloc_dmabuf_ops, buf->size, flags, NULL);
- if (IS_ERR(dbuf))
- return NULL;
-
- /* dmabuf keeps reference to vb2 buffer */
- atomic_inc(&buf->refcount);
-
- return dbuf;
-}
-
/*********************************************/
/* callbacks for DMABUF buffers */
/*********************************************/
@@ -416,7 +243,7 @@
}
static void *vb2_vmalloc_attach_dmabuf(void *alloc_ctx, struct dma_buf *dbuf,
- unsigned long size, enum dma_data_direction dma_dir)
+ unsigned long size, int write)
{
struct vb2_vmalloc_buf *buf;
@@ -428,7 +255,7 @@
return ERR_PTR(-ENOMEM);
buf->dbuf = dbuf;
- buf->dma_dir = dma_dir;
+ buf->write = write;
buf->size = size;
return buf;
@@ -442,7 +269,6 @@
.get_userptr = vb2_vmalloc_get_userptr,
.put_userptr = vb2_vmalloc_put_userptr,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
- .get_dmabuf = vb2_vmalloc_get_dmabuf,
.map_dmabuf = vb2_vmalloc_map_dmabuf,
.unmap_dmabuf = vb2_vmalloc_unmap_dmabuf,
.attach_dmabuf = vb2_vmalloc_attach_dmabuf,
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 61deb80..0607b55 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -90,7 +90,7 @@
depends on m
depends on PCI
depends on CRC32
- select BPAUTO_MII
+ select BACKPORT_MII
---help---
This driver supports the PCI-Express gigabit ethernet adapters
based on JMicron JMC250 chipset.
@@ -128,7 +128,7 @@
depends on m
depends on PCI
depends on CRC32
- select BPAUTO_MII
+ select BACKPORT_MII
---help---
Say Y here to support the Myson MTD-800 family of PCI-based Ethernet
cards. <http://www.myson.com.tw/>
@@ -140,7 +140,7 @@
depends on n
tristate "NetX Ethernet support"
depends on m
- select BPAUTO_MII
+ select BACKPORT_MII
depends on ARCH_NETX
---help---
This is support for the Hilscher netX builtin Ethernet ports
@@ -159,7 +159,7 @@
tristate "OpenCores 10/100 Mbps Ethernet MAC support"
depends on m
depends on HAS_IOMEM && HAS_DMA
- select BPAUTO_MII
+ select BACKPORT_MII
depends on PHYLIB
depends on CRC32
depends on BITREVERSE
@@ -173,7 +173,6 @@
#source "drivers/net/ethernet/realtek/Kconfig"
#source "drivers/net/ethernet/renesas/Kconfig"
#source "drivers/net/ethernet/rdc/Kconfig"
-#source "drivers/net/ethernet/rocker/Kconfig"
config S6GMAC
depends on n
diff --git a/drivers/net/ethernet/Makefile b/drivers/net/ethernet/Makefile
index be78a41..ef26a25 100644
--- a/drivers/net/ethernet/Makefile
+++ b/drivers/net/ethernet/Makefile
@@ -65,7 +65,6 @@
#obj-$(CONFIG_NET_VENDOR_REALTEK) += realtek/
#obj-$(CONFIG_SH_ETH) += renesas/
#obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
-#obj-$(CONFIG_NET_VENDOR_ROCKER) += rocker/
#obj-$(CPTCFG_S6GMAC) += s6gmac.o
#obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/
#obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/
diff --git a/drivers/net/ethernet/atheros/Kconfig b/drivers/net/ethernet/atheros/Kconfig
index 35840c9..77f036c 100644
--- a/drivers/net/ethernet/atheros/Kconfig
+++ b/drivers/net/ethernet/atheros/Kconfig
@@ -23,7 +23,7 @@
depends on m
depends on PCI
depends on CRC32
- select BPAUTO_MII
+ select BACKPORT_MII
---help---
This driver supports the Atheros L2 fast ethernet adapter.
@@ -35,7 +35,7 @@
depends on m
depends on PCI
depends on CRC32
- select BPAUTO_MII
+ select BACKPORT_MII
---help---
This driver supports the Atheros/Attansic L1 gigabit ethernet
adapter.
@@ -48,7 +48,7 @@
depends on m
depends on PCI
depends on CRC32
- select BPAUTO_MII
+ select BACKPORT_MII
---help---
This driver supports the Atheros L1E gigabit ethernet adapter.
@@ -56,12 +56,12 @@
will be called atl1e.
config ATL1C
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_5
tristate "Atheros L1C Gigabit Ethernet support"
depends on m
depends on PCI
depends on CRC32
- select BPAUTO_MII
+ select BACKPORT_MII
---help---
This driver supports the Atheros L1C gigabit ethernet adapter.
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
index 8ca9e3e..d540d29 100644
--- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
+++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c
@@ -48,7 +48,7 @@
MODULE_AUTHOR("Jie Yang");
MODULE_AUTHOR("Qualcomm Atheros Inc., <nic-devel@qualcomm.com>");
-MODULE_DESCRIPTION("Qualcomm Atheros 100/1000M Ethernet Network Driver");
+MODULE_DESCRIPTION("Qualcom Atheros 100/1000M Ethernet Network Driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(ATL1C_DRV_VERSION);
diff --git a/drivers/net/ethernet/broadcom/Kconfig b/drivers/net/ethernet/broadcom/Kconfig
index 9d17913..276237c 100644
--- a/drivers/net/ethernet/broadcom/Kconfig
+++ b/drivers/net/ethernet/broadcom/Kconfig
@@ -23,7 +23,7 @@
depends on m
depends on SSB_POSSIBLE && HAS_DMA
select SSB
- select BPAUTO_MII
+ select BACKPORT_MII
depends on PHYLIB
---help---
If you have a network (Ethernet) controller of this type, say Y
@@ -57,7 +57,7 @@
tristate "Broadcom 63xx internal mac support"
depends on m
depends on BCM63XX
- select BPAUTO_MII
+ select BACKPORT_MII
depends on PHYLIB
help
This driver supports the ethernet MACs in the Broadcom 63xx
@@ -67,9 +67,10 @@
depends on n
tristate "Broadcom GENET internal MAC support"
depends on m
- select BPAUTO_MII
+ depends on OF
+ select BACKPORT_MII
depends on PHYLIB
- depends on FIXED_PHY
+ select FIXED_PHY if BCMGENET=y
depends on BCM7XXX_PHY
help
This driver supports the built-in Ethernet MACs found in the
@@ -172,9 +173,9 @@
tristate "Broadcom SYSTEMPORT internal MAC support"
depends on m
depends on OF
- select BPAUTO_MII
+ select BACKPORT_MII
depends on PHYLIB
- depends on FIXED_PHY
+ select FIXED_PHY if SYSTEMPORT=y
help
This driver supports the built-in Ethernet MACs found in the
Broadcom BCM7xxx Set Top Box family chipset using an internal
diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c
index 290bf08..f098a3f 100644
--- a/drivers/net/ethernet/broadcom/b44.c
+++ b/drivers/net/ethernet/broadcom/b44.c
@@ -836,7 +836,7 @@
struct sk_buff *copy_skb;
b44_recycle_rx(bp, cons, bp->rx_prod);
- copy_skb = napi_alloc_skb(&bp->napi, len);
+ copy_skb = netdev_alloc_skb_ip_align(bp->dev, len);
if (copy_skb == NULL)
goto drop_it_no_recycle;
@@ -2104,7 +2104,6 @@
bp->flags &= ~B44_FLAG_WOL_ENABLE;
spin_unlock_irq(&bp->lock);
- device_set_wakeup_enable(bp->sdev->dev, wol->wolopts & WAKE_MAGIC);
return 0;
}
@@ -2453,7 +2452,6 @@
}
}
- device_set_wakeup_capable(sdev->dev, true);
netdev_info(dev, "%s %pM\n", DRV_DESCRIPTION, dev->dev_addr);
return 0;
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 538d75f..3099c28 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -22,7 +22,7 @@
tristate "Intel(R) PRO/100+ support"
depends on m
depends on PCI
- select BPAUTO_MII
+ select BACKPORT_MII
---help---
This driver supports Intel(R) PRO/100 family of adapters.
To verify that your adapter is supported, find the board ID number
@@ -92,7 +92,6 @@
will be called e1000e.
config IGB
- depends on !KERNEL_3_5
tristate "Intel(R) 82575/82576 PCI-Express Gigabit Ethernet support"
depends on m
depends on PCI
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 813ab10..196b2bf 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -2860,10 +2860,7 @@
return IGB_RETA_SIZE;
}
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-static int igb_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key,
- u8 *hfunc)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
static int igb_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key)
#else
static int igb_get_rxfh(struct net_device *netdev, u32 *indir)
@@ -2872,12 +2869,6 @@
struct igb_adapter *adapter = netdev_priv(netdev);
int i;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
- if (hfunc)
- *hfunc = ETH_RSS_HASH_TOP;
-#endif
- if (!indir)
- return 0;
for (i = 0; i < IGB_RETA_SIZE; i++)
indir[i] = adapter->rss_indir_tbl[i];
@@ -2921,10 +2912,7 @@
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0)
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
-static int igb_set_rxfh(struct net_device *netdev, const u32 *indir,
- const u8 *key, const u8 hfunc)
-#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0)
static int igb_set_rxfh(struct net_device *netdev, const u32 *indir,
const u8 *key)
#else
@@ -2936,15 +2924,6 @@
int i;
u32 num_queues;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
- /* We do not allow change in unsupported parameters */
- if (key ||
- (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP))
- return -EOPNOTSUPP;
-#endif
- if (!indir)
- return 0;
-
num_queues = adapter->rss_queues;
switch (hw->mac.type) {
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 84f0acb..18d60a2 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -200,9 +200,11 @@
static int igb_suspend(struct device *);
#endif
static int igb_resume(struct device *);
+#ifdef CONFIG_PM_RUNTIME
static int igb_runtime_suspend(struct device *dev);
static int igb_runtime_resume(struct device *dev);
static int igb_runtime_idle(struct device *dev);
+#endif
static const struct dev_pm_ops igb_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume)
SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume,
@@ -1032,8 +1034,7 @@
/* igb_get_stats64() might access the rings on this vector,
* we must wait a grace period before freeing it.
*/
- if (q_vector)
- kfree_rcu(q_vector, rcu);
+ kfree_rcu(q_vector, rcu);
}
/**
@@ -1813,10 +1814,8 @@
adapter->flags &= ~IGB_FLAG_NEED_LINK_UPDATE;
for (i = 0; i < adapter->num_q_vectors; i++) {
- if (adapter->q_vector[i]) {
- napi_synchronize(&adapter->q_vector[i]->napi);
- napi_disable(&adapter->q_vector[i]->napi);
- }
+ napi_synchronize(&(adapter->q_vector[i]->napi));
+ napi_disable(&(adapter->q_vector[i]->napi));
}
@@ -3401,11 +3400,14 @@
struct e1000_hw *hw = &adapter->hw;
u32 mrqc, rxcsum;
u32 j, num_rx_queues;
- u32 rss_key[10];
+ static const u32 rsskey[10] = { 0xDA565A6D, 0xC20E5B25, 0x3D256741,
+ 0xB08FA343, 0xCB2BCAD0, 0xB4307BAE,
+ 0xA32DCB77, 0x0CF23080, 0x3BB7426A,
+ 0xFA01ACBE };
- netdev_rss_key_fill(rss_key, sizeof(rss_key));
+ /* Fill out hash function seeds */
for (j = 0; j < 10; j++)
- wr32(E1000_RSSRK(j), rss_key[j]);
+ wr32(E1000_RSSRK(j), rsskey[j]);
num_rx_queues = adapter->rss_queues;
@@ -3743,8 +3745,7 @@
int i;
for (i = 0; i < adapter->num_tx_queues; i++)
- if (adapter->tx_ring[i])
- igb_free_tx_resources(adapter->tx_ring[i]);
+ igb_free_tx_resources(adapter->tx_ring[i]);
}
void igb_unmap_and_free_tx_resource(struct igb_ring *ring,
@@ -3809,8 +3810,7 @@
int i;
for (i = 0; i < adapter->num_tx_queues; i++)
- if (adapter->tx_ring[i])
- igb_clean_tx_ring(adapter->tx_ring[i]);
+ igb_clean_tx_ring(adapter->tx_ring[i]);
}
/**
@@ -3847,8 +3847,7 @@
int i;
for (i = 0; i < adapter->num_rx_queues; i++)
- if (adapter->rx_ring[i])
- igb_free_rx_resources(adapter->rx_ring[i]);
+ igb_free_rx_resources(adapter->rx_ring[i]);
}
/**
@@ -3903,8 +3902,7 @@
int i;
for (i = 0; i < adapter->num_rx_queues; i++)
- if (adapter->rx_ring[i])
- igb_clean_rx_ring(adapter->rx_ring[i]);
+ igb_clean_rx_ring(adapter->rx_ring[i]);
}
/**
@@ -5121,8 +5119,12 @@
/* The minimum packet size with TCTL.PSP set is 17 so pad the skb
* in order to meet this minimum size requirement.
*/
- if (skb_put_padto(skb, 17))
- return NETDEV_TX_OK;
+ if (unlikely(skb->len < 17)) {
+ if (skb_pad(skb, 17 - skb->len))
+ return NETDEV_TX_OK;
+ skb->len = 17;
+ skb_set_tail_pointer(skb, 17);
+ }
return igb_xmit_frame_ring(skb, igb_tx_queue_mapping(adapter, skb));
}
@@ -6567,11 +6569,6 @@
if (unlikely(page_to_nid(page) != numa_node_id()))
return false;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- if (unlikely(page->pfmemalloc))
- return false;
-#endif
-
#if (PAGE_SIZE < 8192)
/* if we are only owner of page we can reuse it */
if (unlikely(page_count(page) != 1))
@@ -6638,12 +6635,7 @@
memcpy(__skb_put(skb, size), va, ALIGN(size, sizeof(long)));
/* we can reuse buffer as-is, just make sure it is local */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)
- if (likely((page_to_nid(page) == numa_node_id()) &&
- !page->pfmemalloc))
-#else
if (likely(page_to_nid(page) == numa_node_id()))
-#endif
return true;
/* this page cannot be reused so discard it */
@@ -6680,7 +6672,8 @@
#endif
/* allocate a skb to store the frags */
- skb = napi_alloc_skb(&rx_ring->q_vector->napi, IGB_RX_HDR_LEN);
+ skb = netdev_alloc_skb_ip_align(rx_ring->netdev,
+ IGB_RX_HDR_LEN);
if (unlikely(!skb)) {
rx_ring->rx_stats.alloc_failed++;
return NULL;
@@ -6881,9 +6874,14 @@
if (skb_is_nonlinear(skb))
igb_pull_tail(rx_ring, rx_desc, skb);
- /* if eth_skb_pad returns an error the skb was freed */
- if (eth_skb_pad(skb))
- return true;
+ /* if skb_pad returns an error the skb was freed */
+ if (unlikely(skb->len < 60)) {
+ int pad_len = 60 - skb->len;
+
+ if (skb_pad(skb, pad_len))
+ return true;
+ __skb_put(skb, pad_len);
+ }
return false;
}
@@ -6948,14 +6946,14 @@
rx_desc = IGB_RX_DESC(rx_ring, rx_ring->next_to_clean);
- if (!rx_desc->wb.upper.status_error)
+ if (!igb_test_staterr(rx_desc, E1000_RXD_STAT_DD))
break;
/* This memory barrier is needed to keep us from reading
* any other fields out of the rx_desc until we know the
- * descriptor has been written back
+ * RXD_STAT_DD bit is set
*/
- dma_rmb();
+ rmb();
/* retrieve a buffer from the ring */
skb = igb_fetch_rx_buffer(rx_ring, rx_desc, skb);
@@ -7018,7 +7016,7 @@
return true;
/* alloc new page for storage */
- page = dev_alloc_page();
+ page = __skb_alloc_page(GFP_ATOMIC | __GFP_COLD, NULL);
if (unlikely(!page)) {
rx_ring->rx_stats.alloc_failed++;
return false;
@@ -7454,8 +7452,6 @@
pci_restore_state(pdev);
pci_save_state(pdev);
- if (!pci_device_is_present(pdev))
- return -ENODEV;
err = pci_enable_device_mem(pdev);
if (err) {
dev_err(&pdev->dev,
@@ -7493,6 +7489,7 @@
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
static int igb_runtime_idle(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
@@ -7529,7 +7526,8 @@
{
return igb_resume(dev);
}
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_RUNTIME */
+#endif
static void igb_shutdown(struct pci_dev *pdev)
{
diff --git a/drivers/net/ieee802154/Kconfig b/drivers/net/ieee802154/Kconfig
index 271a167..47e5bf2 100644
--- a/drivers/net/ieee802154/Kconfig
+++ b/drivers/net/ieee802154/Kconfig
@@ -11,6 +11,17 @@
If you say N, all options in this submenu will be skipped and
disabled.
+config IEEE802154_FAKEHARD
+ tristate "Fake LR-WPAN driver with several interconnected devices"
+ depends on m
+ depends on IEEE802154_DRIVERS
+ ---help---
+ Say Y here to enable the fake driver that serves as an example
+ of HardMAC device driver.
+
+ This driver can also be built as a module. To do so say M here.
+ The module will be called 'fakehard'.
+
config IEEE802154_FAKELB
depends on IEEE802154_DRIVERS && MAC802154
tristate "IEEE 802.15.4 loopback driver"
@@ -23,7 +34,7 @@
The module will be called 'fakelb'.
config IEEE802154_AT86RF230
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
depends on IEEE802154_DRIVERS && MAC802154
tristate "AT86RF230/231/233/212 transceiver driver"
depends on m
@@ -37,7 +48,7 @@
the module will be called 'at86rf230'.
config IEEE802154_MRF24J40
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_5
tristate "Microchip MRF24J40 transceiver driver"
depends on m
depends on IEEE802154_DRIVERS && MAC802154
@@ -50,7 +61,7 @@
the module will be called 'mrf24j40'.
config IEEE802154_CC2520
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_5
depends on IEEE802154_DRIVERS && MAC802154
tristate "CC2520 transceiver driver"
depends on m
diff --git a/drivers/net/ieee802154/Makefile b/drivers/net/ieee802154/Makefile
index cf29a74..ee1bafc 100644
--- a/drivers/net/ieee802154/Makefile
+++ b/drivers/net/ieee802154/Makefile
@@ -1,3 +1,4 @@
+obj-$(CPTCFG_IEEE802154_FAKEHARD) += fakehard.o
obj-$(CPTCFG_IEEE802154_FAKELB) += fakelb.o
obj-$(CPTCFG_IEEE802154_AT86RF230) += at86rf230.o
obj-$(CPTCFG_IEEE802154_MRF24J40) += mrf24j40.o
diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c
index 1c01356..c9d2a75 100644
--- a/drivers/net/ieee802154/at86rf230.c
+++ b/drivers/net/ieee802154/at86rf230.c
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
@@ -29,10 +33,10 @@
#include <linux/regmap.h>
#include <linux/skbuff.h>
#include <linux/of_gpio.h>
-#include <linux/ieee802154.h>
+#include <net/ieee802154.h>
#include <net/mac802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
struct at86rf230_local;
/* at86rf2xx chip depend data.
@@ -46,11 +50,15 @@
u16 t_off_to_tx_on;
u16 t_frame;
u16 t_p_ack;
+ /* short interframe spacing time */
+ u16 t_sifs;
+ /* long interframe spacing time */
+ u16 t_lifs;
/* completion timeout for tx in msecs */
u16 t_tx_timeout;
int rssi_base_val;
- int (*set_channel)(struct at86rf230_local *, u8, u8);
+ int (*set_channel)(struct at86rf230_local *, int, int);
int (*get_desense_steps)(struct at86rf230_local *, s32);
};
@@ -66,14 +74,12 @@
void (*complete)(void *context);
u8 from_state;
u8 to_state;
-
- bool irq_enable;
};
struct at86rf230_local {
struct spi_device *spi;
- struct ieee802154_hw *hw;
+ struct ieee802154_dev *dev;
struct at86rf2xx_chip_data *data;
struct regmap *regmap;
@@ -83,10 +89,10 @@
struct at86rf230_state_change irq;
bool tx_aret;
- s8 max_frame_retries;
bool is_tx;
/* spinlock for is_tx protection */
spinlock_t lock;
+ struct completion tx_complete;
struct sk_buff *tx_skb;
struct at86rf230_state_change tx;
};
@@ -285,11 +291,10 @@
#define AT86RF2XX_NUMREGS 0x3F
-static void
+static int
at86rf230_async_state_change(struct at86rf230_local *lp,
struct at86rf230_state_change *ctx,
- const u8 state, void (*complete)(void *context),
- const bool irq_enable);
+ const u8 state, void (*complete)(void *context));
static inline int
__at86rf230_write(struct at86rf230_local *lp,
@@ -446,8 +451,7 @@
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
- at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL, false);
- ieee802154_wake_queue(lp->hw);
+ at86rf230_async_state_change(lp, ctx, STATE_RX_AACK_ON, NULL);
}
static void
@@ -457,31 +461,21 @@
dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
- at86rf230_async_error_recover, false);
+ at86rf230_async_error_recover);
}
/* Generic function to get some register value in async mode */
-static void
+static int
at86rf230_async_read_reg(struct at86rf230_local *lp, const u8 reg,
struct at86rf230_state_change *ctx,
- void (*complete)(void *context),
- const bool irq_enable)
+ void (*complete)(void *context))
{
- int rc;
-
u8 *tx_buf = ctx->buf;
tx_buf[0] = (reg & CMD_REG_MASK) | CMD_REG;
ctx->trx.len = 2;
ctx->msg.complete = complete;
- ctx->irq_enable = irq_enable;
- rc = spi_async(lp->spi, &ctx->msg);
- if (rc) {
- if (irq_enable)
- enable_irq(lp->spi->irq);
-
- at86rf230_async_error(lp, ctx, rc);
- }
+ return spi_async(lp->spi, &ctx->msg);
}
static void
@@ -518,8 +512,7 @@
if (ctx->to_state == STATE_TX_ON) {
at86rf230_async_state_change(lp, ctx,
STATE_FORCE_TX_ON,
- ctx->complete,
- ctx->irq_enable);
+ ctx->complete);
return;
}
}
@@ -542,6 +535,7 @@
struct at86rf230_local *lp = ctx->lp;
struct at86rf2xx_chip_data *c = lp->data;
bool force = false;
+ int rc;
/* The force state changes are will show as normal states in the
* state status subregister. We change the to_state to the
@@ -610,9 +604,10 @@
udelay(1);
change:
- at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
- at86rf230_async_state_assert,
- ctx->irq_enable);
+ rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+ at86rf230_async_state_assert);
+ if (rc)
+ dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
}
static void
@@ -627,9 +622,10 @@
/* Check for "possible" STATE_TRANSITION_IN_PROGRESS */
if (trx_state == STATE_TRANSITION_IN_PROGRESS) {
udelay(1);
- at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
- at86rf230_async_state_change_start,
- ctx->irq_enable);
+ rc = at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+ at86rf230_async_state_change_start);
+ if (rc)
+ dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
return;
}
@@ -651,27 +647,20 @@
ctx->trx.len = 2;
ctx->msg.complete = at86rf230_async_state_delay;
rc = spi_async(lp->spi, &ctx->msg);
- if (rc) {
- if (ctx->irq_enable)
- enable_irq(lp->spi->irq);
-
- at86rf230_async_error(lp, &lp->state, rc);
- }
+ if (rc)
+ dev_err(&lp->spi->dev, "spi_async error %d\n", rc);
}
-static void
+static int
at86rf230_async_state_change(struct at86rf230_local *lp,
struct at86rf230_state_change *ctx,
- const u8 state, void (*complete)(void *context),
- const bool irq_enable)
+ const u8 state, void (*complete)(void *context))
{
/* Initialization for the state change context */
ctx->to_state = state;
ctx->complete = complete;
- ctx->irq_enable = irq_enable;
- at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
- at86rf230_async_state_change_start,
- irq_enable);
+ return at86rf230_async_read_reg(lp, RG_TRX_STATUS, ctx,
+ at86rf230_async_state_change_start);
}
static void
@@ -692,16 +681,17 @@
{
int rc;
- at86rf230_async_state_change(lp, &lp->state, state,
- at86rf230_sync_state_change_complete,
- false);
+ rc = at86rf230_async_state_change(lp, &lp->state, state,
+ at86rf230_sync_state_change_complete);
+ if (rc) {
+ at86rf230_async_error(lp, &lp->state, rc);
+ return rc;
+ }
rc = wait_for_completion_timeout(&lp->state_complete,
msecs_to_jiffies(100));
- if (!rc) {
- at86rf230_async_error(lp, &lp->state, -ETIMEDOUT);
+ if (!rc)
return -ETIMEDOUT;
- }
return 0;
}
@@ -711,14 +701,8 @@
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
- struct sk_buff *skb = lp->tx_skb;
- enable_irq(lp->spi->irq);
-
- if (lp->max_frame_retries <= 0)
- ieee802154_xmit_complete(lp->hw, skb, true);
- else
- ieee802154_xmit_complete(lp->hw, skb, false);
+ complete(&lp->tx_complete);
}
static void
@@ -726,9 +710,12 @@
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
+ int rc;
- at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON,
- at86rf230_tx_complete, true);
+ rc = at86rf230_async_state_change(lp, &lp->irq, STATE_RX_AACK_ON,
+ at86rf230_tx_complete);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
}
static void
@@ -736,9 +723,12 @@
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
+ int rc;
- at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
- at86rf230_tx_on, true);
+ rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+ at86rf230_tx_on);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
}
static void
@@ -748,14 +738,17 @@
struct at86rf230_local *lp = ctx->lp;
const u8 *buf = ctx->buf;
const u8 trac = (buf[1] & 0xe0) >> 5;
+ int rc;
/* If trac status is different than zero we need to do a state change
* to STATE_FORCE_TRX_OFF then STATE_TX_ON to recover the transceiver
* state to TX_ON.
*/
if (trac) {
- at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
- at86rf230_tx_trac_error, true);
+ rc = at86rf230_async_state_change(lp, ctx, STATE_FORCE_TRX_OFF,
+ at86rf230_tx_trac_error);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
return;
}
@@ -768,29 +761,51 @@
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
+ int rc;
- at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
- at86rf230_tx_trac_check, true);
+ rc = at86rf230_async_read_reg(lp, RG_TRX_STATE, ctx,
+ at86rf230_tx_trac_check);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
}
static void
at86rf230_rx(struct at86rf230_local *lp,
- const u8 *data, const u8 len, const u8 lqi)
+ const u8 *data, u8 len)
{
+ u8 lqi;
struct sk_buff *skb;
u8 rx_local_buf[AT86RF2XX_MAX_BUF];
+ if (len < 2)
+ return;
+
+ /* read full frame buffer and invalid lqi value to lowest
+ * indicator if frame was is in a corrupted state.
+ */
+ if (len > IEEE802154_MTU) {
+ lqi = 0;
+ len = IEEE802154_MTU;
+ dev_vdbg(&lp->spi->dev, "corrupted frame received\n");
+ } else {
+ lqi = data[len];
+ }
+
memcpy(rx_local_buf, data, len);
enable_irq(lp->spi->irq);
- skb = dev_alloc_skb(IEEE802154_MTU);
+ skb = alloc_skb(IEEE802154_MTU, GFP_ATOMIC);
if (!skb) {
dev_vdbg(&lp->spi->dev, "failed to allocate sk_buff\n");
return;
}
memcpy(skb_put(skb, len), rx_local_buf, len);
- ieee802154_rx_irqsafe(lp->hw, skb, lqi);
+
+ /* We do not put CRC into the frame */
+ skb_trim(skb, len - 2);
+
+ ieee802154_rx_irqsafe(lp->dev, skb, lqi);
}
static void
@@ -799,31 +814,20 @@
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
const u8 *buf = lp->irq.buf;
- u8 len = buf[1];
+ const u8 len = buf[1];
- if (!ieee802154_is_valid_psdu_len(len)) {
- dev_vdbg(&lp->spi->dev, "corrupted frame received\n");
- len = IEEE802154_MTU;
- }
-
- at86rf230_rx(lp, buf + 2, len, buf[2 + len]);
+ at86rf230_rx(lp, buf + 2, len);
}
-static void
+static int
at86rf230_rx_read_frame(struct at86rf230_local *lp)
{
- int rc;
-
u8 *buf = lp->irq.buf;
buf[0] = CMD_FB;
lp->irq.trx.len = AT86RF2XX_MAX_BUF;
lp->irq.msg.complete = at86rf230_rx_read_frame_complete;
- rc = spi_async(lp->spi, &lp->irq.msg);
- if (rc) {
- enable_irq(lp->spi->irq);
- at86rf230_async_error(lp, &lp->irq, rc);
- }
+ return spi_async(lp->spi, &lp->irq.msg);
}
static void
@@ -831,6 +835,7 @@
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
+ int rc;
/* Possible check on trac status here. This could be useful to make
* some stats why receive is failed. Not used at the moment, but it's
@@ -838,31 +843,34 @@
* The programming guide say do it so.
*/
- at86rf230_rx_read_frame(lp);
+ rc = at86rf230_rx_read_frame(lp);
+ if (rc) {
+ enable_irq(lp->spi->irq);
+ at86rf230_async_error(lp, ctx, rc);
+ }
}
-static void
+static int
at86rf230_irq_trx_end(struct at86rf230_local *lp)
{
spin_lock(&lp->lock);
if (lp->is_tx) {
lp->is_tx = 0;
spin_unlock(&lp->lock);
+ enable_irq(lp->spi->irq);
if (lp->tx_aret)
- at86rf230_async_state_change(lp, &lp->irq,
- STATE_FORCE_TX_ON,
- at86rf230_tx_trac_status,
- true);
+ return at86rf230_async_state_change(lp, &lp->irq,
+ STATE_FORCE_TX_ON,
+ at86rf230_tx_trac_status);
else
- at86rf230_async_state_change(lp, &lp->irq,
- STATE_RX_AACK_ON,
- at86rf230_tx_complete,
- true);
+ return at86rf230_async_state_change(lp, &lp->irq,
+ STATE_RX_AACK_ON,
+ at86rf230_tx_complete);
} else {
spin_unlock(&lp->lock);
- at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
- at86rf230_rx_trac_check, true);
+ return at86rf230_async_read_reg(lp, RG_TRX_STATE, &lp->irq,
+ at86rf230_rx_trac_check);
}
}
@@ -873,9 +881,12 @@
struct at86rf230_local *lp = ctx->lp;
const u8 *buf = lp->irq.buf;
const u8 irq = buf[1];
+ int rc;
if (irq & IRQ_TRX_END) {
- at86rf230_irq_trx_end(lp);
+ rc = at86rf230_irq_trx_end(lp);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
} else {
enable_irq(lp->spi->irq);
dev_err(&lp->spi->dev, "not supported irq %02x received\n",
@@ -890,14 +901,13 @@
u8 *buf = ctx->buf;
int rc;
- disable_irq_nosync(irq);
+ disable_irq_nosync(lp->spi->irq);
buf[0] = (RG_IRQ_STATUS & CMD_REG_MASK) | CMD_REG;
ctx->trx.len = 2;
ctx->msg.complete = at86rf230_irq_status;
rc = spi_async(lp->spi, &ctx->msg);
if (rc) {
- enable_irq(irq);
at86rf230_async_error(lp, ctx, rc);
return IRQ_NONE;
}
@@ -950,18 +960,22 @@
{
struct at86rf230_state_change *ctx = context;
struct at86rf230_local *lp = ctx->lp;
+ int rc;
- at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
- at86rf230_write_frame, false);
+ rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ARET_ON,
+ at86rf230_write_frame);
+ if (rc)
+ at86rf230_async_error(lp, ctx, rc);
}
static int
-at86rf230_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
+at86rf230_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
{
- struct at86rf230_local *lp = hw->priv;
+ struct at86rf230_local *lp = dev->priv;
struct at86rf230_state_change *ctx = &lp->tx;
void (*tx_complete)(void *context) = at86rf230_write_frame;
+ int rc;
lp->tx_skb = skb;
@@ -972,39 +986,61 @@
if (lp->tx_aret)
tx_complete = at86rf230_xmit_tx_on;
- at86rf230_async_state_change(lp, ctx, STATE_TX_ON, tx_complete, false);
+ rc = at86rf230_async_state_change(lp, ctx, STATE_TX_ON,
+ tx_complete);
+ if (rc) {
+ at86rf230_async_error(lp, ctx, rc);
+ return rc;
+ }
+ rc = wait_for_completion_interruptible_timeout(&lp->tx_complete,
+ msecs_to_jiffies(lp->data->t_tx_timeout));
+ if (!rc) {
+ at86rf230_async_error(lp, ctx, rc);
+ return -ETIMEDOUT;
+ }
+
+ /* Interfame spacing time, which is phy depend.
+ * TODO
+ * Move this handling in MAC 802.15.4 layer.
+ * This is currently a workaround to avoid fragmenation issues.
+ */
+ if (skb->len > 18)
+ usleep_range(lp->data->t_lifs, lp->data->t_lifs + 10);
+ else
+ usleep_range(lp->data->t_sifs, lp->data->t_sifs + 10);
return 0;
}
static int
-at86rf230_ed(struct ieee802154_hw *hw, u8 *level)
+at86rf230_ed(struct ieee802154_dev *dev, u8 *level)
{
+ might_sleep();
BUG_ON(!level);
*level = 0xbe;
return 0;
}
static int
-at86rf230_start(struct ieee802154_hw *hw)
+at86rf230_start(struct ieee802154_dev *dev)
{
- return at86rf230_sync_state_change(hw->priv, STATE_RX_AACK_ON);
+ return at86rf230_sync_state_change(dev->priv, STATE_RX_AACK_ON);
}
static void
-at86rf230_stop(struct ieee802154_hw *hw)
+at86rf230_stop(struct ieee802154_dev *dev)
{
- at86rf230_sync_state_change(hw->priv, STATE_FORCE_TRX_OFF);
+ at86rf230_sync_state_change(dev->priv, STATE_FORCE_TRX_OFF);
}
static int
-at86rf23x_set_channel(struct at86rf230_local *lp, u8 page, u8 channel)
+at86rf23x_set_channel(struct at86rf230_local *lp, int page, int channel)
{
return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
}
static int
-at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel)
+at86rf212_set_channel(struct at86rf230_local *lp, int page, int channel)
{
int rc;
@@ -1025,60 +1061,44 @@
if (rc < 0)
return rc;
- /* This sets the symbol_duration according frequency on the 212.
- * TODO move this handling while set channel and page in cfg802154.
- * We can do that, this timings are according 802.15.4 standard.
- * If we do that in cfg802154, this is a more generic calculation.
- *
- * This should also protected from ifs_timer. Means cancel timer and
- * init with a new value. For now, this is okay.
- */
- if (channel == 0) {
- if (page == 0) {
- /* SUB:0 and BPSK:0 -> BPSK-20 */
- lp->hw->phy->symbol_duration = 50;
- } else {
- /* SUB:1 and BPSK:0 -> BPSK-40 */
- lp->hw->phy->symbol_duration = 25;
- }
- } else {
- if (page == 0)
- /* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */
- lp->hw->phy->symbol_duration = 40;
- else
- /* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */
- lp->hw->phy->symbol_duration = 16;
- }
-
- lp->hw->phy->lifs_period = IEEE802154_LIFS_PERIOD *
- lp->hw->phy->symbol_duration;
- lp->hw->phy->sifs_period = IEEE802154_SIFS_PERIOD *
- lp->hw->phy->symbol_duration;
-
return at86rf230_write_subreg(lp, SR_CHANNEL, channel);
}
static int
-at86rf230_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+at86rf230_channel(struct ieee802154_dev *dev, int page, int channel)
{
- struct at86rf230_local *lp = hw->priv;
+ struct at86rf230_local *lp = dev->priv;
int rc;
+ might_sleep();
+
+ if (page < 0 || page > 31 ||
+ !(lp->dev->phy->channels_supported[page] & BIT(channel))) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+
rc = lp->data->set_channel(lp, page, channel);
+ if (rc < 0)
+ return rc;
+
/* Wait for PLL */
usleep_range(lp->data->t_channel_switch,
lp->data->t_channel_switch + 10);
- return rc;
+ dev->phy->current_channel = channel;
+ dev->phy->current_page = page;
+
+ return 0;
}
static int
-at86rf230_set_hw_addr_filt(struct ieee802154_hw *hw,
+at86rf230_set_hw_addr_filt(struct ieee802154_dev *dev,
struct ieee802154_hw_addr_filt *filt,
unsigned long changed)
{
- struct at86rf230_local *lp = hw->priv;
+ struct at86rf230_local *lp = dev->priv;
- if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
+ if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
u16 addr = le16_to_cpu(filt->short_addr);
dev_vdbg(&lp->spi->dev,
@@ -1087,7 +1107,7 @@
__at86rf230_write(lp, RG_SHORT_ADDR_1, addr >> 8);
}
- if (changed & IEEE802154_AFILT_PANID_CHANGED) {
+ if (changed & IEEE802515_AFILT_PANID_CHANGED) {
u16 pan = le16_to_cpu(filt->pan_id);
dev_vdbg(&lp->spi->dev,
@@ -1096,7 +1116,7 @@
__at86rf230_write(lp, RG_PAN_ID_1, pan >> 8);
}
- if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
+ if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
u8 i, addr[8];
memcpy(addr, &filt->ieee_addr, 8);
@@ -1106,7 +1126,7 @@
__at86rf230_write(lp, RG_IEEE_ADDR_0 + i, addr[i]);
}
- if (changed & IEEE802154_AFILT_PANC_CHANGED) {
+ if (changed & IEEE802515_AFILT_PANC_CHANGED) {
dev_vdbg(&lp->spi->dev,
"at86rf230_set_hw_addr_filt called for panc change\n");
if (filt->pan_coord)
@@ -1119,9 +1139,9 @@
}
static int
-at86rf230_set_txpower(struct ieee802154_hw *hw, int db)
+at86rf230_set_txpower(struct ieee802154_dev *dev, int db)
{
- struct at86rf230_local *lp = hw->priv;
+ struct at86rf230_local *lp = dev->priv;
/* typical maximum output is 5dBm with RG_PHY_TX_PWR 0x60, lower five
* bits decrease power in 1dB steps. 0x60 represents extra PA gain of
@@ -1138,17 +1158,17 @@
}
static int
-at86rf230_set_lbt(struct ieee802154_hw *hw, bool on)
+at86rf230_set_lbt(struct ieee802154_dev *dev, bool on)
{
- struct at86rf230_local *lp = hw->priv;
+ struct at86rf230_local *lp = dev->priv;
return at86rf230_write_subreg(lp, SR_CSMA_LBT_MODE, on);
}
static int
-at86rf230_set_cca_mode(struct ieee802154_hw *hw, u8 mode)
+at86rf230_set_cca_mode(struct ieee802154_dev *dev, u8 mode)
{
- struct at86rf230_local *lp = hw->priv;
+ struct at86rf230_local *lp = dev->priv;
return at86rf230_write_subreg(lp, SR_CCA_MODE, mode);
}
@@ -1166,9 +1186,9 @@
}
static int
-at86rf230_set_cca_ed_level(struct ieee802154_hw *hw, s32 level)
+at86rf230_set_cca_ed_level(struct ieee802154_dev *dev, s32 level)
{
- struct at86rf230_local *lp = hw->priv;
+ struct at86rf230_local *lp = dev->priv;
if (level < lp->data->rssi_base_val || level > 30)
return -EINVAL;
@@ -1178,12 +1198,15 @@
}
static int
-at86rf230_set_csma_params(struct ieee802154_hw *hw, u8 min_be, u8 max_be,
+at86rf230_set_csma_params(struct ieee802154_dev *dev, u8 min_be, u8 max_be,
u8 retries)
{
- struct at86rf230_local *lp = hw->priv;
+ struct at86rf230_local *lp = dev->priv;
int rc;
+ if (min_be > max_be || max_be > 8 || retries > 5)
+ return -EINVAL;
+
rc = at86rf230_write_subreg(lp, SR_MIN_BE, min_be);
if (rc)
return rc;
@@ -1196,13 +1219,15 @@
}
static int
-at86rf230_set_frame_retries(struct ieee802154_hw *hw, s8 retries)
+at86rf230_set_frame_retries(struct ieee802154_dev *dev, s8 retries)
{
- struct at86rf230_local *lp = hw->priv;
+ struct at86rf230_local *lp = dev->priv;
int rc = 0;
+ if (retries < -1 || retries > 15)
+ return -EINVAL;
+
lp->tx_aret = retries >= 0;
- lp->max_frame_retries = retries;
if (retries >= 0)
rc = at86rf230_write_subreg(lp, SR_MAX_FRAME_RETRIES, retries);
@@ -1210,36 +1235,9 @@
return rc;
}
-static int
-at86rf230_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)
-{
- struct at86rf230_local *lp = hw->priv;
- int rc;
-
- if (on) {
- rc = at86rf230_write_subreg(lp, SR_AACK_DIS_ACK, 1);
- if (rc < 0)
- return rc;
-
- rc = at86rf230_write_subreg(lp, SR_AACK_PROM_MODE, 1);
- if (rc < 0)
- return rc;
- } else {
- rc = at86rf230_write_subreg(lp, SR_AACK_PROM_MODE, 0);
- if (rc < 0)
- return rc;
-
- rc = at86rf230_write_subreg(lp, SR_AACK_DIS_ACK, 0);
- if (rc < 0)
- return rc;
- }
-
- return 0;
-}
-
-static const struct ieee802154_ops at86rf230_ops = {
+static struct ieee802154_ops at86rf230_ops = {
.owner = THIS_MODULE,
- .xmit_async = at86rf230_xmit,
+ .xmit = at86rf230_xmit,
.ed = at86rf230_ed,
.set_channel = at86rf230_channel,
.start = at86rf230_start,
@@ -1251,7 +1249,6 @@
.set_cca_ed_level = at86rf230_set_cca_ed_level,
.set_csma_params = at86rf230_set_csma_params,
.set_frame_retries = at86rf230_set_frame_retries,
- .set_promiscuous_mode = at86rf230_set_promiscuous_mode,
};
static struct at86rf2xx_chip_data at86rf233_data = {
@@ -1262,6 +1259,8 @@
.t_off_to_tx_on = 80,
.t_frame = 4096,
.t_p_ack = 545,
+ .t_sifs = 192,
+ .t_lifs = 480,
.t_tx_timeout = 2000,
.rssi_base_val = -91,
.set_channel = at86rf23x_set_channel,
@@ -1276,6 +1275,8 @@
.t_off_to_tx_on = 110,
.t_frame = 4096,
.t_p_ack = 545,
+ .t_sifs = 192,
+ .t_lifs = 480,
.t_tx_timeout = 2000,
.rssi_base_val = -91,
.set_channel = at86rf23x_set_channel,
@@ -1290,6 +1291,8 @@
.t_off_to_tx_on = 200,
.t_frame = 4096,
.t_p_ack = 545,
+ .t_sifs = 192,
+ .t_lifs = 480,
.t_tx_timeout = 2000,
.rssi_base_val = -100,
.set_channel = at86rf212_set_channel,
@@ -1351,11 +1354,7 @@
return -EINVAL;
}
- /* Force setting slotted operation bit to 0. Sometimes the atben
- * sets this bit and I don't know why. We set this always force
- * to zero while probing.
- */
- return at86rf230_write_subreg(lp, SR_SLOTTED_OPERATION, 0);
+ return 0;
}
static struct at86rf230_platform_data *
@@ -1410,10 +1409,9 @@
return -EINVAL;
}
- lp->hw->extra_tx_headroom = 0;
- lp->hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AACK |
- IEEE802154_HW_TXPOWER | IEEE802154_HW_ARET |
- IEEE802154_HW_AFILT | IEEE802154_HW_PROMISCUOUS;
+ lp->dev->extra_tx_headroom = 0;
+ lp->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK |
+ IEEE802154_HW_TXPOWER | IEEE802154_HW_CSMA;
switch (part) {
case 2:
@@ -1423,19 +1421,15 @@
case 3:
chip = "at86rf231";
lp->data = &at86rf231_data;
- lp->hw->phy->channels_supported[0] = 0x7FFF800;
- lp->hw->phy->current_channel = 11;
- lp->hw->phy->symbol_duration = 16;
+ lp->dev->phy->channels_supported[0] = 0x7FFF800;
break;
case 7:
chip = "at86rf212";
if (version == 1) {
lp->data = &at86rf212_data;
- lp->hw->flags |= IEEE802154_HW_LBT;
- lp->hw->phy->channels_supported[0] = 0x00007FF;
- lp->hw->phy->channels_supported[2] = 0x00007FF;
- lp->hw->phy->current_channel = 5;
- lp->hw->phy->symbol_duration = 25;
+ lp->dev->flags |= IEEE802154_HW_LBT;
+ lp->dev->phy->channels_supported[0] = 0x00007FF;
+ lp->dev->phy->channels_supported[2] = 0x00007FF;
} else {
rc = -ENOTSUPP;
}
@@ -1443,9 +1437,7 @@
case 11:
chip = "at86rf233";
lp->data = &at86rf233_data;
- lp->hw->phy->channels_supported[0] = 0x7FFF800;
- lp->hw->phy->current_channel = 13;
- lp->hw->phy->symbol_duration = 16;
+ lp->dev->phy->channels_supported[0] = 0x7FFF800;
break;
default:
chip = "unkown";
@@ -1486,7 +1478,7 @@
static int at86rf230_probe(struct spi_device *spi)
{
struct at86rf230_platform_data *pdata;
- struct ieee802154_hw *hw;
+ struct ieee802154_dev *dev;
struct at86rf230_local *lp;
unsigned int status;
int rc, irq_type;
@@ -1525,16 +1517,14 @@
usleep_range(120, 240);
}
- hw = ieee802154_alloc_hw(sizeof(*lp), &at86rf230_ops);
- if (!hw)
+ dev = ieee802154_alloc_device(sizeof(*lp), &at86rf230_ops);
+ if (!dev)
return -ENOMEM;
- lp = hw->priv;
- lp->hw = hw;
+ lp = dev->priv;
+ lp->dev = dev;
lp->spi = spi;
- hw->parent = &spi->dev;
- hw->vif_data_size = sizeof(*lp);
- ieee802154_random_extended_addr(&hw->phy->perm_extended_addr);
+ dev->parent = &spi->dev;
lp->regmap = devm_regmap_init_spi(spi, &at86rf230_regmap_spi_config);
if (IS_ERR(lp->regmap)) {
@@ -1551,6 +1541,7 @@
goto free_dev;
spin_lock_init(&lp->lock);
+ init_completion(&lp->tx_complete);
init_completion(&lp->state_complete);
spi_set_drvdata(spi, lp);
@@ -1573,14 +1564,14 @@
if (rc)
goto free_dev;
- rc = ieee802154_register_hw(lp->hw);
+ rc = ieee802154_register_device(lp->dev);
if (rc)
goto free_dev;
return rc;
free_dev:
- ieee802154_free_hw(lp->hw);
+ ieee802154_free_device(lp->dev);
return rc;
}
@@ -1591,8 +1582,8 @@
/* mask all at86rf230 irq's */
at86rf230_write_subreg(lp, SR_IRQ_MASK, 0);
- ieee802154_unregister_hw(lp->hw);
- ieee802154_free_hw(lp->hw);
+ ieee802154_unregister_device(lp->dev);
+ ieee802154_free_device(lp->dev);
dev_dbg(&spi->dev, "unregistered at86rf230\n");
return 0;
diff --git a/drivers/net/ieee802154/cc2520.c b/drivers/net/ieee802154/cc2520.c
index f9df9fa..8a5ac7a 100644
--- a/drivers/net/ieee802154/cc2520.c
+++ b/drivers/net/ieee802154/cc2520.c
@@ -21,10 +21,10 @@
#include <linux/skbuff.h>
#include <linux/pinctrl/consumer.h>
#include <linux/of_gpio.h>
-#include <linux/ieee802154.h>
#include <net/mac802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
+#include <net/ieee802154.h>
#define SPI_COMMAND_BUFFER 3
#define HIGH 1
@@ -193,7 +193,7 @@
/* Driver private information */
struct cc2520_private {
struct spi_device *spi; /* SPI device structure */
- struct ieee802154_hw *hw; /* IEEE-802.15.4 device */
+ struct ieee802154_dev *dev; /* IEEE-802.15.4 device */
u8 *buf; /* SPI TX/Rx data buffer */
struct mutex buffer_mutex; /* SPI buffer mutex */
bool is_tx; /* Flag for sync b/w Tx and Rx */
@@ -453,20 +453,20 @@
return status;
}
-static int cc2520_start(struct ieee802154_hw *hw)
+static int cc2520_start(struct ieee802154_dev *dev)
{
- return cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRXON);
+ return cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRXON);
}
-static void cc2520_stop(struct ieee802154_hw *hw)
+static void cc2520_stop(struct ieee802154_dev *dev)
{
- cc2520_cmd_strobe(hw->priv, CC2520_CMD_SRFOFF);
+ cc2520_cmd_strobe(dev->priv, CC2520_CMD_SRFOFF);
}
static int
-cc2520_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
+cc2520_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
{
- struct cc2520_private *priv = hw->priv;
+ struct cc2520_private *priv = dev->priv;
unsigned long flags;
int rc;
u8 status = 0;
@@ -524,7 +524,7 @@
if (len < 2 || len > IEEE802154_MTU)
return -EINVAL;
- skb = dev_alloc_skb(len);
+ skb = alloc_skb(len, GFP_KERNEL);
if (!skb)
return -ENOMEM;
@@ -536,7 +536,7 @@
skb_trim(skb, skb->len - 2);
- ieee802154_rx_irqsafe(priv->hw, skb, lqi);
+ ieee802154_rx_irqsafe(priv->dev, skb, lqi);
dev_vdbg(&priv->spi->dev, "RXFIFO: %x %x\n", len, lqi);
@@ -544,9 +544,9 @@
}
static int
-cc2520_ed(struct ieee802154_hw *hw, u8 *level)
+cc2520_ed(struct ieee802154_dev *dev, u8 *level)
{
- struct cc2520_private *priv = hw->priv;
+ struct cc2520_private *priv = dev->priv;
u8 status = 0xff;
u8 rssi;
int ret;
@@ -569,11 +569,12 @@
}
static int
-cc2520_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+cc2520_set_channel(struct ieee802154_dev *dev, int page, int channel)
{
- struct cc2520_private *priv = hw->priv;
+ struct cc2520_private *priv = dev->priv;
int ret;
+ might_sleep();
dev_dbg(&priv->spi->dev, "trying to set channel\n");
BUG_ON(page != 0);
@@ -587,12 +588,12 @@
}
static int
-cc2520_filter(struct ieee802154_hw *hw,
+cc2520_filter(struct ieee802154_dev *dev,
struct ieee802154_hw_addr_filt *filt, unsigned long changed)
{
- struct cc2520_private *priv = hw->priv;
+ struct cc2520_private *priv = dev->priv;
- if (changed & IEEE802154_AFILT_PANID_CHANGED) {
+ if (changed & IEEE802515_AFILT_PANID_CHANGED) {
u16 panid = le16_to_cpu(filt->pan_id);
dev_vdbg(&priv->spi->dev,
@@ -601,7 +602,7 @@
sizeof(panid), (u8 *)&panid);
}
- if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
+ if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
dev_vdbg(&priv->spi->dev,
"cc2520_filter called for IEEE addr\n");
cc2520_write_ram(priv, CC2520RAM_IEEEADDR,
@@ -609,7 +610,7 @@
(u8 *)&filt->ieee_addr);
}
- if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
+ if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
u16 addr = le16_to_cpu(filt->short_addr);
dev_vdbg(&priv->spi->dev,
@@ -618,7 +619,7 @@
sizeof(addr), (u8 *)&addr);
}
- if (changed & IEEE802154_AFILT_PANC_CHANGED) {
+ if (changed & IEEE802515_AFILT_PANC_CHANGED) {
dev_vdbg(&priv->spi->dev,
"cc2520_filter called for panc change\n");
if (filt->pan_coord)
@@ -630,11 +631,11 @@
return 0;
}
-static const struct ieee802154_ops cc2520_ops = {
+static struct ieee802154_ops cc2520_ops = {
.owner = THIS_MODULE,
.start = cc2520_start,
.stop = cc2520_stop,
- .xmit_sync = cc2520_tx,
+ .xmit = cc2520_tx,
.ed = cc2520_ed,
.set_channel = cc2520_set_channel,
.set_hw_addr_filt = cc2520_filter,
@@ -644,29 +645,27 @@
{
int ret = -ENOMEM;
- priv->hw = ieee802154_alloc_hw(sizeof(*priv), &cc2520_ops);
- if (!priv->hw)
+ priv->dev = ieee802154_alloc_device(sizeof(*priv), &cc2520_ops);
+ if (!priv->dev)
goto err_ret;
- priv->hw->priv = priv;
- priv->hw->parent = &priv->spi->dev;
- priv->hw->extra_tx_headroom = 0;
- priv->hw->vif_data_size = sizeof(*priv);
+ priv->dev->priv = priv;
+ priv->dev->parent = &priv->spi->dev;
+ priv->dev->extra_tx_headroom = 0;
/* We do support only 2.4 Ghz */
- priv->hw->phy->channels_supported[0] = 0x7FFF800;
- priv->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK |
- IEEE802154_HW_AFILT;
+ priv->dev->phy->channels_supported[0] = 0x7FFF800;
+ priv->dev->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK;
dev_vdbg(&priv->spi->dev, "registered cc2520\n");
- ret = ieee802154_register_hw(priv->hw);
+ ret = ieee802154_register_device(priv->dev);
if (ret)
goto err_free_device;
return 0;
err_free_device:
- ieee802154_free_hw(priv->hw);
+ ieee802154_free_device(priv->dev);
err_ret:
return ret;
}
@@ -858,7 +857,7 @@
pinctrl = devm_pinctrl_get_select_default(&spi->dev);
if (IS_ERR(pinctrl))
dev_warn(&spi->dev,
- "pinctrl pins are not configured\n");
+ "pinctrl pins are not configured");
pdata = cc2520_get_platform_data(spi);
if (!pdata) {
@@ -1003,8 +1002,8 @@
mutex_destroy(&priv->buffer_mutex);
flush_work(&priv->fifop_irqwork);
- ieee802154_unregister_hw(priv->hw);
- ieee802154_free_hw(priv->hw);
+ ieee802154_unregister_device(priv->dev);
+ ieee802154_free_device(priv->dev);
return 0;
}
diff --git a/drivers/net/ieee802154/fakehard.c b/drivers/net/ieee802154/fakehard.c
new file mode 100644
index 0000000..9ce854f
--- /dev/null
+++ b/drivers/net/ieee802154/fakehard.c
@@ -0,0 +1,427 @@
+/*
+ * Sample driver for HardMAC IEEE 802.15.4 devices
+ *
+ * Copyright (C) 2009 Siemens AG
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dmitry.baryshkov@siemens.com>
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+
+#include <net/af_ieee802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/ieee802154.h>
+#include <net/nl802154.h>
+#include <net/wpan-phy.h>
+
+struct fakehard_priv {
+ struct wpan_phy *phy;
+};
+
+static struct wpan_phy *fake_to_phy(const struct net_device *dev)
+{
+ struct fakehard_priv *priv = netdev_priv(dev);
+ return priv->phy;
+}
+
+/**
+ * fake_get_phy - Return a phy corresponding to this device.
+ * @dev: The network device for which to return the wan-phy object
+ *
+ * This function returns a wpan-phy object corresponding to the passed
+ * network device. Reference counter for wpan-phy object is incremented,
+ * so when the wpan-phy isn't necessary, you should drop the reference
+ * via @wpan_phy_put() call.
+ */
+static struct wpan_phy *fake_get_phy(const struct net_device *dev)
+{
+ struct wpan_phy *phy = fake_to_phy(dev);
+ return to_phy(get_device(&phy->dev));
+}
+
+/**
+ * fake_get_pan_id - Retrieve the PAN ID of the device.
+ * @dev: The network device to retrieve the PAN of.
+ *
+ * Return the ID of the PAN from the PIB.
+ */
+static __le16 fake_get_pan_id(const struct net_device *dev)
+{
+ BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+ return cpu_to_le16(0xeba1);
+}
+
+/**
+ * fake_get_short_addr - Retrieve the short address of the device.
+ * @dev: The network device to retrieve the short address of.
+ *
+ * Returns the IEEE 802.15.4 short-form address cached for this
+ * device. If the device has not yet had a short address assigned
+ * then this should return 0xFFFF to indicate a lack of association.
+ */
+static __le16 fake_get_short_addr(const struct net_device *dev)
+{
+ BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+ return cpu_to_le16(0x1);
+}
+
+/**
+ * fake_get_dsn - Retrieve the DSN of the device.
+ * @dev: The network device to retrieve the DSN for.
+ *
+ * Returns the IEEE 802.15.4 DSN for the network device.
+ * The DSN is the sequence number which will be added to each
+ * packet or MAC command frame by the MAC during transmission.
+ *
+ * DSN means 'Data Sequence Number'.
+ *
+ * Note: This is in section 7.2.1.2 of the IEEE 802.15.4-2006
+ * document.
+ */
+static u8 fake_get_dsn(const struct net_device *dev)
+{
+ BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+ return 0x00; /* DSN are implemented in HW, so return just 0 */
+}
+
+/**
+ * fake_assoc_req - Make an association request to the HW.
+ * @dev: The network device which we are associating to a network.
+ * @addr: The coordinator with which we wish to associate.
+ * @channel: The channel on which to associate.
+ * @cap: The capability information field to use in the association.
+ *
+ * Start an association with a coordinator. The coordinator's address
+ * and PAN ID can be found in @addr.
+ *
+ * Note: This is in section 7.3.1 and 7.5.3.1 of the IEEE
+ * 802.15.4-2006 document.
+ */
+static int fake_assoc_req(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 channel, u8 page, u8 cap)
+{
+ struct wpan_phy *phy = fake_to_phy(dev);
+
+ mutex_lock(&phy->pib_lock);
+ phy->current_channel = channel;
+ phy->current_page = page;
+ mutex_unlock(&phy->pib_lock);
+
+ /* We simply emulate it here */
+ return ieee802154_nl_assoc_confirm(dev, fake_get_short_addr(dev),
+ IEEE802154_SUCCESS);
+}
+
+/**
+ * fake_assoc_resp - Send an association response to a device.
+ * @dev: The network device on which to send the response.
+ * @addr: The address of the device to respond to.
+ * @short_addr: The assigned short address for the device (if any).
+ * @status: The result of the association request.
+ *
+ * Queue the association response of the coordinator to another
+ * device's attempt to associate with the network which we
+ * coordinate. This is then added to the indirect-send queue to be
+ * transmitted to the end device when it polls for data.
+ *
+ * Note: This is in section 7.3.2 and 7.5.3.1 of the IEEE
+ * 802.15.4-2006 document.
+ */
+static int fake_assoc_resp(struct net_device *dev,
+ struct ieee802154_addr *addr, __le16 short_addr, u8 status)
+{
+ return 0;
+}
+
+/**
+ * fake_disassoc_req - Disassociate a device from a network.
+ * @dev: The network device on which we're disassociating a device.
+ * @addr: The device to disassociate from the network.
+ * @reason: The reason to give to the device for being disassociated.
+ *
+ * This sends a disassociation notification to the device being
+ * disassociated from the network.
+ *
+ * Note: This is in section 7.5.3.2 of the IEEE 802.15.4-2006
+ * document, with the reason described in 7.3.3.2.
+ */
+static int fake_disassoc_req(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 reason)
+{
+ return ieee802154_nl_disassoc_confirm(dev, IEEE802154_SUCCESS);
+}
+
+/**
+ * fake_start_req - Start an IEEE 802.15.4 PAN.
+ * @dev: The network device on which to start the PAN.
+ * @addr: The coordinator address to use when starting the PAN.
+ * @channel: The channel on which to start the PAN.
+ * @bcn_ord: Beacon order.
+ * @sf_ord: Superframe order.
+ * @pan_coord: Whether or not we are the PAN coordinator or just
+ * requesting a realignment perhaps?
+ * @blx: Battery Life Extension feature bitfield.
+ * @coord_realign: Something to realign something else.
+ *
+ * If pan_coord is non-zero then this starts a network with the
+ * provided parameters, otherwise it attempts a coordinator
+ * realignment of the stated network instead.
+ *
+ * Note: This is in section 7.5.2.3 of the IEEE 802.15.4-2006
+ * document, with 7.3.8 describing coordinator realignment.
+ */
+static int fake_start_req(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 channel, u8 page,
+ u8 bcn_ord, u8 sf_ord, u8 pan_coord, u8 blx,
+ u8 coord_realign)
+{
+ struct wpan_phy *phy = fake_to_phy(dev);
+
+ mutex_lock(&phy->pib_lock);
+ phy->current_channel = channel;
+ phy->current_page = page;
+ mutex_unlock(&phy->pib_lock);
+
+ /* We don't emulate beacons here at all, so START should fail */
+ ieee802154_nl_start_confirm(dev, IEEE802154_INVALID_PARAMETER);
+ return 0;
+}
+
+/**
+ * fake_scan_req - Start a channel scan.
+ * @dev: The network device on which to perform a channel scan.
+ * @type: The type of scan to perform.
+ * @channels: The channel bitmask to scan.
+ * @duration: How long to spend on each channel.
+ *
+ * This starts either a passive (energy) scan or an active (PAN) scan
+ * on the channels indicated in the @channels bitmask. The duration of
+ * the scan is measured in terms of superframe duration. Specifically,
+ * the scan will spend aBaseSuperFrameDuration * ((2^n) + 1) on each
+ * channel.
+ *
+ * Note: This is in section 7.5.2.1 of the IEEE 802.15.4-2006 document.
+ */
+static int fake_scan_req(struct net_device *dev, u8 type, u32 channels,
+ u8 page, u8 duration)
+{
+ u8 edl[27] = {};
+ return ieee802154_nl_scan_confirm(dev, IEEE802154_SUCCESS, type,
+ channels, page,
+ type == IEEE802154_MAC_SCAN_ED ? edl : NULL);
+}
+
+static struct ieee802154_mlme_ops fake_mlme = {
+ .assoc_req = fake_assoc_req,
+ .assoc_resp = fake_assoc_resp,
+ .disassoc_req = fake_disassoc_req,
+ .start_req = fake_start_req,
+ .scan_req = fake_scan_req,
+
+ .get_phy = fake_get_phy,
+
+ .get_pan_id = fake_get_pan_id,
+ .get_short_addr = fake_get_short_addr,
+ .get_dsn = fake_get_dsn,
+};
+
+static int ieee802154_fake_open(struct net_device *dev)
+{
+ netif_start_queue(dev);
+ return 0;
+}
+
+static int ieee802154_fake_close(struct net_device *dev)
+{
+ netif_stop_queue(dev);
+ return 0;
+}
+
+static netdev_tx_t ieee802154_fake_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
+ /* FIXME: do hardware work here ... */
+
+ dev_kfree_skb(skb);
+ return NETDEV_TX_OK;
+}
+
+
+static int ieee802154_fake_ioctl(struct net_device *dev, struct ifreq *ifr,
+ int cmd)
+{
+ struct sockaddr_ieee802154 *sa =
+ (struct sockaddr_ieee802154 *)&ifr->ifr_addr;
+ u16 pan_id, short_addr;
+
+ switch (cmd) {
+ case SIOCGIFADDR:
+ /* FIXME: fixed here, get from device IRL */
+ pan_id = le16_to_cpu(fake_get_pan_id(dev));
+ short_addr = le16_to_cpu(fake_get_short_addr(dev));
+ if (pan_id == IEEE802154_PANID_BROADCAST ||
+ short_addr == IEEE802154_ADDR_BROADCAST)
+ return -EADDRNOTAVAIL;
+
+ sa->family = AF_IEEE802154;
+ sa->addr.addr_type = IEEE802154_ADDR_SHORT;
+ sa->addr.pan_id = pan_id;
+ sa->addr.short_addr = short_addr;
+ return 0;
+ }
+ return -ENOIOCTLCMD;
+}
+
+static int ieee802154_fake_mac_addr(struct net_device *dev, void *p)
+{
+ return -EBUSY; /* HW address is built into the device */
+}
+
+static const struct net_device_ops fake_ops = {
+ .ndo_open = ieee802154_fake_open,
+ .ndo_stop = ieee802154_fake_close,
+ .ndo_start_xmit = ieee802154_fake_xmit,
+ .ndo_do_ioctl = ieee802154_fake_ioctl,
+ .ndo_set_mac_address = ieee802154_fake_mac_addr,
+};
+
+static void ieee802154_fake_destruct(struct net_device *dev)
+{
+ struct wpan_phy *phy = fake_to_phy(dev);
+
+ wpan_phy_unregister(phy);
+ free_netdev(dev);
+ wpan_phy_free(phy);
+}
+
+static void ieee802154_fake_setup(struct net_device *dev)
+{
+ dev->addr_len = IEEE802154_ADDR_LEN;
+ memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
+ dev->features = NETIF_F_HW_CSUM;
+ dev->needed_tailroom = 2; /* FCS */
+ dev->mtu = 127;
+ dev->tx_queue_len = 10;
+ dev->type = ARPHRD_IEEE802154;
+ dev->flags = IFF_NOARP | IFF_BROADCAST;
+ dev->watchdog_timeo = 0;
+ dev->destructor = ieee802154_fake_destruct;
+}
+
+
+static int ieee802154fake_probe(struct platform_device *pdev)
+{
+ struct net_device *dev;
+ struct fakehard_priv *priv;
+ struct wpan_phy *phy = wpan_phy_alloc(0);
+ int err;
+
+ if (!phy)
+ return -ENOMEM;
+
+ dev = alloc_netdev(sizeof(struct fakehard_priv), "hardwpan%d",
+ NET_NAME_UNKNOWN, ieee802154_fake_setup);
+ if (!dev) {
+ wpan_phy_free(phy);
+ return -ENOMEM;
+ }
+
+ memcpy(dev->dev_addr, "\xba\xbe\xca\xfe\xde\xad\xbe\xef",
+ dev->addr_len);
+
+ /*
+ * For now we'd like to emulate 2.4 GHz-only device,
+ * both O-QPSK and CSS
+ */
+ /* 2.4 GHz O-QPSK 802.15.4-2003 */
+ phy->channels_supported[0] |= 0x7FFF800;
+ /* 2.4 GHz CSS 802.15.4a-2007 */
+ phy->channels_supported[3] |= 0x3fff;
+
+ phy->transmit_power = 0xbf;
+
+ dev->netdev_ops = &fake_ops;
+ dev->ml_priv = &fake_mlme;
+
+ priv = netdev_priv(dev);
+ priv->phy = phy;
+
+ wpan_phy_set_dev(phy, &pdev->dev);
+ SET_NETDEV_DEV(dev, &phy->dev);
+
+ platform_set_drvdata(pdev, dev);
+
+ err = wpan_phy_register(phy);
+ if (err)
+ goto out;
+
+ err = register_netdev(dev);
+ if (err < 0)
+ goto out;
+
+ dev_info(&pdev->dev, "Added ieee802154 HardMAC hardware\n");
+ return 0;
+
+out:
+ unregister_netdev(dev);
+ return err;
+}
+
+static int ieee802154fake_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+ unregister_netdev(dev);
+ return 0;
+}
+
+static struct platform_device *ieee802154fake_dev;
+
+static struct platform_driver ieee802154fake_driver = {
+ .probe = ieee802154fake_probe,
+ .remove = ieee802154fake_remove,
+ .driver = {
+ .name = "ieee802154hardmac",
+ .owner = THIS_MODULE,
+ },
+};
+
+static __init int fake_init(void)
+{
+ ieee802154fake_dev = platform_device_register_simple(
+ "ieee802154hardmac", -1, NULL, 0);
+ return platform_driver_register(&ieee802154fake_driver);
+}
+
+static __exit void fake_exit(void)
+{
+ platform_driver_unregister(&ieee802154fake_driver);
+ platform_device_unregister(ieee802154fake_dev);
+}
+
+module_init(fake_init);
+module_exit(fake_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/net/ieee802154/fakelb.c b/drivers/net/ieee802154/fakelb.c
index dc2bfb6..27d8320 100644
--- a/drivers/net/ieee802154/fakelb.c
+++ b/drivers/net/ieee802154/fakelb.c
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -25,12 +29,12 @@
#include <linux/device.h>
#include <linux/spinlock.h>
#include <net/mac802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
static int numlbs = 1;
struct fakelb_dev_priv {
- struct ieee802154_hw *hw;
+ struct ieee802154_dev *dev;
struct list_head list;
struct fakelb_priv *fake;
@@ -45,8 +49,9 @@
};
static int
-fakelb_hw_ed(struct ieee802154_hw *hw, u8 *level)
+fakelb_hw_ed(struct ieee802154_dev *dev, u8 *level)
{
+ might_sleep();
BUG_ON(!level);
*level = 0xbe;
@@ -54,10 +59,14 @@
}
static int
-fakelb_hw_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+fakelb_hw_channel(struct ieee802154_dev *dev, int page, int channel)
{
pr_debug("set channel to %d\n", channel);
+ might_sleep();
+ dev->phy->current_page = page;
+ dev->phy->current_channel = channel;
+
return 0;
}
@@ -69,17 +78,19 @@
spin_lock(&priv->lock);
if (priv->working) {
newskb = pskb_copy(skb, GFP_ATOMIC);
- ieee802154_rx_irqsafe(priv->hw, newskb, 0xcc);
+ ieee802154_rx_irqsafe(priv->dev, newskb, 0xcc);
}
spin_unlock(&priv->lock);
}
static int
-fakelb_hw_xmit(struct ieee802154_hw *hw, struct sk_buff *skb)
+fakelb_hw_xmit(struct ieee802154_dev *dev, struct sk_buff *skb)
{
- struct fakelb_dev_priv *priv = hw->priv;
+ struct fakelb_dev_priv *priv = dev->priv;
struct fakelb_priv *fake = priv->fake;
+ might_sleep();
+
read_lock_bh(&fake->lock);
if (priv->list.next == priv->list.prev) {
/* we are the only one device */
@@ -88,8 +99,8 @@
struct fakelb_dev_priv *dp;
list_for_each_entry(dp, &priv->fake->list, list) {
if (dp != priv &&
- (dp->hw->phy->current_channel ==
- priv->hw->phy->current_channel))
+ (dp->dev->phy->current_channel ==
+ priv->dev->phy->current_channel))
fakelb_hw_deliver(dp, skb);
}
}
@@ -99,8 +110,8 @@
}
static int
-fakelb_hw_start(struct ieee802154_hw *hw) {
- struct fakelb_dev_priv *priv = hw->priv;
+fakelb_hw_start(struct ieee802154_dev *dev) {
+ struct fakelb_dev_priv *priv = dev->priv;
int ret = 0;
spin_lock(&priv->lock);
@@ -114,17 +125,17 @@
}
static void
-fakelb_hw_stop(struct ieee802154_hw *hw) {
- struct fakelb_dev_priv *priv = hw->priv;
+fakelb_hw_stop(struct ieee802154_dev *dev) {
+ struct fakelb_dev_priv *priv = dev->priv;
spin_lock(&priv->lock);
priv->working = 0;
spin_unlock(&priv->lock);
}
-static const struct ieee802154_ops fakelb_ops = {
+static struct ieee802154_ops fakelb_ops = {
.owner = THIS_MODULE,
- .xmit_sync = fakelb_hw_xmit,
+ .xmit = fakelb_hw_xmit,
.ed = fakelb_hw_ed,
.set_channel = fakelb_hw_channel,
.start = fakelb_hw_start,
@@ -139,54 +150,54 @@
{
struct fakelb_dev_priv *priv;
int err;
- struct ieee802154_hw *hw;
+ struct ieee802154_dev *ieee;
- hw = ieee802154_alloc_hw(sizeof(*priv), &fakelb_ops);
- if (!hw)
+ ieee = ieee802154_alloc_device(sizeof(*priv), &fakelb_ops);
+ if (!ieee)
return -ENOMEM;
- priv = hw->priv;
- priv->hw = hw;
+ priv = ieee->priv;
+ priv->dev = ieee;
/* 868 MHz BPSK 802.15.4-2003 */
- hw->phy->channels_supported[0] |= 1;
+ ieee->phy->channels_supported[0] |= 1;
/* 915 MHz BPSK 802.15.4-2003 */
- hw->phy->channels_supported[0] |= 0x7fe;
+ ieee->phy->channels_supported[0] |= 0x7fe;
/* 2.4 GHz O-QPSK 802.15.4-2003 */
- hw->phy->channels_supported[0] |= 0x7FFF800;
+ ieee->phy->channels_supported[0] |= 0x7FFF800;
/* 868 MHz ASK 802.15.4-2006 */
- hw->phy->channels_supported[1] |= 1;
+ ieee->phy->channels_supported[1] |= 1;
/* 915 MHz ASK 802.15.4-2006 */
- hw->phy->channels_supported[1] |= 0x7fe;
+ ieee->phy->channels_supported[1] |= 0x7fe;
/* 868 MHz O-QPSK 802.15.4-2006 */
- hw->phy->channels_supported[2] |= 1;
+ ieee->phy->channels_supported[2] |= 1;
/* 915 MHz O-QPSK 802.15.4-2006 */
- hw->phy->channels_supported[2] |= 0x7fe;
+ ieee->phy->channels_supported[2] |= 0x7fe;
/* 2.4 GHz CSS 802.15.4a-2007 */
- hw->phy->channels_supported[3] |= 0x3fff;
+ ieee->phy->channels_supported[3] |= 0x3fff;
/* UWB Sub-gigahertz 802.15.4a-2007 */
- hw->phy->channels_supported[4] |= 1;
+ ieee->phy->channels_supported[4] |= 1;
/* UWB Low band 802.15.4a-2007 */
- hw->phy->channels_supported[4] |= 0x1e;
+ ieee->phy->channels_supported[4] |= 0x1e;
/* UWB High band 802.15.4a-2007 */
- hw->phy->channels_supported[4] |= 0xffe0;
+ ieee->phy->channels_supported[4] |= 0xffe0;
/* 750 MHz O-QPSK 802.15.4c-2009 */
- hw->phy->channels_supported[5] |= 0xf;
+ ieee->phy->channels_supported[5] |= 0xf;
/* 750 MHz MPSK 802.15.4c-2009 */
- hw->phy->channels_supported[5] |= 0xf0;
+ ieee->phy->channels_supported[5] |= 0xf0;
/* 950 MHz BPSK 802.15.4d-2009 */
- hw->phy->channels_supported[6] |= 0x3ff;
+ ieee->phy->channels_supported[6] |= 0x3ff;
/* 950 MHz GFSK 802.15.4d-2009 */
- hw->phy->channels_supported[6] |= 0x3ffc00;
+ ieee->phy->channels_supported[6] |= 0x3ffc00;
INIT_LIST_HEAD(&priv->list);
priv->fake = fake;
spin_lock_init(&priv->lock);
- hw->parent = dev;
+ ieee->parent = dev;
- err = ieee802154_register_hw(hw);
+ err = ieee802154_register_device(ieee);
if (err)
goto err_reg;
@@ -197,7 +208,7 @@
return 0;
err_reg:
- ieee802154_free_hw(priv->hw);
+ ieee802154_free_device(priv->dev);
return err;
}
@@ -207,8 +218,8 @@
list_del(&priv->list);
write_unlock_bh(&priv->fake->lock);
- ieee802154_unregister_hw(priv->hw);
- ieee802154_free_hw(priv->hw);
+ ieee802154_unregister_device(priv->dev);
+ ieee802154_free_device(priv->dev);
}
static int fakelb_probe(struct platform_device *pdev)
@@ -261,6 +272,7 @@
.remove = fakelb_remove,
.driver = {
.name = "ieee802154fakelb",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/net/ieee802154/mrf24j40.c b/drivers/net/ieee802154/mrf24j40.c
index a200fa1..07e0b88 100644
--- a/drivers/net/ieee802154/mrf24j40.c
+++ b/drivers/net/ieee802154/mrf24j40.c
@@ -13,14 +13,18 @@
* 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 <linux/spi/spi.h>
#include <linux/interrupt.h>
#include <linux/module.h>
-#include <linux/ieee802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
#include <net/mac802154.h>
+#include <net/ieee802154.h>
/* MRF24J40 Short Address Registers */
#define REG_RXMCR 0x00 /* Receive MAC control */
@@ -39,8 +43,6 @@
#define REG_TXSTBL 0x2E /* TX Stabilization */
#define REG_INTSTAT 0x31 /* Interrupt Status */
#define REG_INTCON 0x32 /* Interrupt Control */
-#define REG_GPIO 0x33 /* GPIO */
-#define REG_TRISGPIO 0x34 /* GPIO direction */
#define REG_RFCTL 0x36 /* RF Control Mode Register */
#define REG_BBREG1 0x39 /* Baseband Registers */
#define REG_BBREG2 0x3A /* */
@@ -61,7 +63,6 @@
#define REG_SLPCON1 0x220
#define REG_WAKETIMEL 0x222 /* Wake-up Time Match Value Low */
#define REG_WAKETIMEH 0x223 /* Wake-up Time Match Value High */
-#define REG_TESTMODE 0x22F /* Test mode */
#define REG_RX_FIFO 0x300 /* Receive FIFO */
/* Device configuration: Only channels 11-26 on page 0 are supported. */
@@ -74,12 +75,10 @@
#define RX_FIFO_SIZE 144 /* From datasheet */
#define SET_CHANNEL_DELAY_US 192 /* From datasheet */
-enum mrf24j40_modules { MRF24J40, MRF24J40MA, MRF24J40MC };
-
/* Device Private Data */
struct mrf24j40 {
struct spi_device *spi;
- struct ieee802154_hw *hw;
+ struct ieee802154_dev *dev;
struct mutex buffer_mutex; /* only used to protect buf */
struct completion tx_complete;
@@ -332,9 +331,9 @@
return ret;
}
-static int mrf24j40_tx(struct ieee802154_hw *hw, struct sk_buff *skb)
+static int mrf24j40_tx(struct ieee802154_dev *dev, struct sk_buff *skb)
{
- struct mrf24j40 *devrec = hw->priv;
+ struct mrf24j40 *devrec = dev->priv;
u8 val;
int ret = 0;
@@ -383,7 +382,7 @@
return ret;
}
-static int mrf24j40_ed(struct ieee802154_hw *hw, u8 *level)
+static int mrf24j40_ed(struct ieee802154_dev *dev, u8 *level)
{
/* TODO: */
pr_warn("mrf24j40: ed not implemented\n");
@@ -391,9 +390,9 @@
return 0;
}
-static int mrf24j40_start(struct ieee802154_hw *hw)
+static int mrf24j40_start(struct ieee802154_dev *dev)
{
- struct mrf24j40 *devrec = hw->priv;
+ struct mrf24j40 *devrec = dev->priv;
u8 val;
int ret;
@@ -408,9 +407,9 @@
return 0;
}
-static void mrf24j40_stop(struct ieee802154_hw *hw)
+static void mrf24j40_stop(struct ieee802154_dev *dev)
{
- struct mrf24j40 *devrec = hw->priv;
+ struct mrf24j40 *devrec = dev->priv;
u8 val;
int ret;
@@ -423,9 +422,10 @@
write_short_reg(devrec, REG_INTCON, val);
}
-static int mrf24j40_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel)
+static int mrf24j40_set_channel(struct ieee802154_dev *dev,
+ int page, int channel)
{
- struct mrf24j40 *devrec = hw->priv;
+ struct mrf24j40 *devrec = dev->priv;
u8 val;
int ret;
@@ -453,15 +453,15 @@
return 0;
}
-static int mrf24j40_filter(struct ieee802154_hw *hw,
+static int mrf24j40_filter(struct ieee802154_dev *dev,
struct ieee802154_hw_addr_filt *filt,
unsigned long changed)
{
- struct mrf24j40 *devrec = hw->priv;
+ struct mrf24j40 *devrec = dev->priv;
dev_dbg(printdev(devrec), "filter\n");
- if (changed & IEEE802154_AFILT_SADDR_CHANGED) {
+ if (changed & IEEE802515_AFILT_SADDR_CHANGED) {
/* Short Addr */
u8 addrh, addrl;
@@ -474,7 +474,7 @@
"Set short addr to %04hx\n", filt->short_addr);
}
- if (changed & IEEE802154_AFILT_IEEEADDR_CHANGED) {
+ if (changed & IEEE802515_AFILT_IEEEADDR_CHANGED) {
/* Device Address */
u8 i, addr[8];
@@ -490,7 +490,7 @@
#endif
}
- if (changed & IEEE802154_AFILT_PANID_CHANGED) {
+ if (changed & IEEE802515_AFILT_PANID_CHANGED) {
/* PAN ID */
u8 panidl, panidh;
@@ -502,7 +502,7 @@
dev_dbg(printdev(devrec), "Set PANID to %04hx\n", filt->pan_id);
}
- if (changed & IEEE802154_AFILT_PANC_CHANGED) {
+ if (changed & IEEE802515_AFILT_PANC_CHANGED) {
/* Pan Coordinator */
u8 val;
int ret;
@@ -543,7 +543,7 @@
val |= 4; /* SET RXDECINV */
write_short_reg(devrec, REG_BBREG1, val);
- skb = dev_alloc_skb(len);
+ skb = alloc_skb(len, GFP_KERNEL);
if (!skb) {
ret = -ENOMEM;
goto out;
@@ -563,7 +563,7 @@
/* TODO: Other drivers call ieee20154_rx_irqsafe() here (eg: cc2040,
* also from a workqueue). I think irqsafe is not necessary here.
* Can someone confirm? */
- ieee802154_rx_irqsafe(devrec->hw, skb, lqi);
+ ieee802154_rx_irqsafe(devrec->dev, skb, lqi);
dev_dbg(printdev(devrec), "RX Handled\n");
@@ -578,9 +578,9 @@
return ret;
}
-static const struct ieee802154_ops mrf24j40_ops = {
+static struct ieee802154_ops mrf24j40_ops = {
.owner = THIS_MODULE,
- .xmit_sync = mrf24j40_tx,
+ .xmit = mrf24j40_tx,
.ed = mrf24j40_ed,
.start = mrf24j40_start,
.stop = mrf24j40_stop,
@@ -691,28 +691,6 @@
if (ret)
goto err_ret;
- if (spi_get_device_id(devrec->spi)->driver_data == MRF24J40MC) {
- /* Enable external amplifier.
- * From MRF24J40MC datasheet section 1.3: Operation.
- */
- read_long_reg(devrec, REG_TESTMODE, &val);
- val |= 0x7; /* Configure GPIO 0-2 to control amplifier */
- write_long_reg(devrec, REG_TESTMODE, val);
-
- read_short_reg(devrec, REG_TRISGPIO, &val);
- val |= 0x8; /* Set GPIO3 as output. */
- write_short_reg(devrec, REG_TRISGPIO, val);
-
- read_short_reg(devrec, REG_GPIO, &val);
- val |= 0x8; /* Set GPIO3 HIGH to enable U5 voltage regulator */
- write_short_reg(devrec, REG_GPIO, val);
-
- /* Reduce TX pwr to meet FCC requirements.
- * From MRF24J40MC datasheet section 3.1.1
- */
- write_long_reg(devrec, REG_RFCON3, 0x28);
- }
-
return 0;
err_ret:
@@ -744,18 +722,17 @@
/* Register with the 802154 subsystem */
- devrec->hw = ieee802154_alloc_hw(0, &mrf24j40_ops);
- if (!devrec->hw)
+ devrec->dev = ieee802154_alloc_device(0, &mrf24j40_ops);
+ if (!devrec->dev)
goto err_ret;
- devrec->hw->priv = devrec;
- devrec->hw->parent = &devrec->spi->dev;
- devrec->hw->phy->channels_supported[0] = CHANNEL_MASK;
- devrec->hw->flags = IEEE802154_HW_OMIT_CKSUM | IEEE802154_HW_AACK |
- IEEE802154_HW_AFILT;
+ devrec->dev->priv = devrec;
+ devrec->dev->parent = &devrec->spi->dev;
+ devrec->dev->phy->channels_supported[0] = CHANNEL_MASK;
+ devrec->dev->flags = IEEE802154_HW_OMIT_CKSUM|IEEE802154_HW_AACK;
dev_dbg(printdev(devrec), "registered mrf24j40\n");
- ret = ieee802154_register_hw(devrec->hw);
+ ret = ieee802154_register_device(devrec->dev);
if (ret)
goto err_register_device;
@@ -780,9 +757,9 @@
err_irq:
err_hw_init:
- ieee802154_unregister_hw(devrec->hw);
+ ieee802154_unregister_device(devrec->dev);
err_register_device:
- ieee802154_free_hw(devrec->hw);
+ ieee802154_free_device(devrec->dev);
err_ret:
return ret;
}
@@ -793,8 +770,8 @@
dev_dbg(printdev(devrec), "remove\n");
- ieee802154_unregister_hw(devrec->hw);
- ieee802154_free_hw(devrec->hw);
+ ieee802154_unregister_device(devrec->dev);
+ ieee802154_free_device(devrec->dev);
/* TODO: Will ieee802154_free_device() wait until ->xmit() is
* complete? */
@@ -802,9 +779,8 @@
}
static const struct spi_device_id mrf24j40_ids[] = {
- { "mrf24j40", MRF24J40 },
- { "mrf24j40ma", MRF24J40MA },
- { "mrf24j40mc", MRF24J40MC },
+ { "mrf24j40", 0 },
+ { "mrf24j40ma", 0 },
{ },
};
MODULE_DEVICE_TABLE(spi, mrf24j40_ids);
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
index d6683dd..c45c011 100644
--- a/drivers/net/usb/Kconfig
+++ b/drivers/net/usb/Kconfig
@@ -78,7 +78,7 @@
depends on n
tristate "USB Pegasus/Pegasus-II based ethernet device support"
depends on m
- select BPAUTO_MII
+ select BACKPORT_MII
---help---
Say Y here if you know you have Pegasus or Pegasus-II based adapter.
If in doubt then look at <file:drivers/net/usb/pegasus.h> for the
@@ -95,7 +95,7 @@
depends on n
tristate "USB RTL8150 based ethernet device support"
depends on m
- select BPAUTO_MII
+ select BACKPORT_MII
help
Say Y here if you have RTL8150 based usb-ethernet adapter.
Send me <petkan@users.sourceforge.net> any comments you may have.
@@ -108,7 +108,7 @@
depends on n
tristate "Realtek RTL8152/RTL8153 Based USB Ethernet Adapters"
depends on m
- select BPAUTO_MII
+ select BACKPORT_MII
help
This option adds support for Realtek RTL8152 based USB 2.0
10/100 Ethernet adapters and RTL8153 based USB 3.0 10/100/1000
@@ -120,7 +120,7 @@
config USB_USBNET
tristate "Multi-purpose USB Networking Framework"
depends on m
- select BPAUTO_MII
+ select BACKPORT_MII
---help---
This driver supports several kinds of network links over USB,
with "minidrivers" built around a common network driver core
diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c
index 80a714b..c582a86 100644
--- a/drivers/net/usb/cdc_ether.c
+++ b/drivers/net/usb/cdc_ether.c
@@ -67,36 +67,6 @@
0xa6, 0x07, 0xc0, 0xff, 0xcb, 0x7e, 0x39, 0x2a,
};
-static void usbnet_cdc_update_filter(struct usbnet *dev)
-{
- struct cdc_state *info = (void *) &dev->data;
- struct usb_interface *intf = info->control;
- struct net_device *net = dev->net;
-
- u16 cdc_filter = USB_CDC_PACKET_TYPE_DIRECTED
- | USB_CDC_PACKET_TYPE_BROADCAST;
-
- /* filtering on the device is an optional feature and not worth
- * the hassle so we just roughly care about snooping and if any
- * multicast is requested, we take every multicast
- */
- if (net->flags & IFF_PROMISC)
- cdc_filter |= USB_CDC_PACKET_TYPE_PROMISCUOUS;
- if (!netdev_mc_empty(net) || (net->flags & IFF_ALLMULTI))
- cdc_filter |= USB_CDC_PACKET_TYPE_ALL_MULTICAST;
-
- usb_control_msg(dev->udev,
- usb_sndctrlpipe(dev->udev, 0),
- USB_CDC_SET_ETHERNET_PACKET_FILTER,
- USB_TYPE_CLASS | USB_RECIP_INTERFACE,
- cdc_filter,
- intf->cur_altsetting->desc.bInterfaceNumber,
- NULL,
- 0,
- USB_CTRL_SET_TIMEOUT
- );
-}
-
/* probes control interface, claims data interface, collects the bulk
* endpoints, activates data interface (if needed), maybe sets MTU.
* all pure cdc, except for certain firmware workarounds, and knowing
@@ -377,8 +347,16 @@
* don't do reset all the way. So the packet filter should
* be set to a sane initial value.
*/
- usbnet_cdc_update_filter(dev);
-
+ usb_control_msg(dev->udev,
+ usb_sndctrlpipe(dev->udev, 0),
+ USB_CDC_SET_ETHERNET_PACKET_FILTER,
+ USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+ USB_CDC_PACKET_TYPE_ALL_MULTICAST | USB_CDC_PACKET_TYPE_DIRECTED | USB_CDC_PACKET_TYPE_BROADCAST,
+ intf->cur_altsetting->desc.bInterfaceNumber,
+ NULL,
+ 0,
+ USB_CTRL_SET_TIMEOUT
+ );
return 0;
bad_desc:
@@ -490,6 +468,10 @@
return status;
}
+ /* FIXME cdc-ether has some multicast code too, though it complains
+ * in routine cases. info->ether describes the multicast support.
+ * Implement that here, manipulating the cdc filter as needed.
+ */
return 0;
}
EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
@@ -500,7 +482,6 @@
.bind = usbnet_cdc_bind,
.unbind = usbnet_cdc_unbind,
.status = usbnet_cdc_status,
- .set_rx_mode = usbnet_cdc_update_filter,
.manage_power = usbnet_manage_power,
};
@@ -510,7 +491,6 @@
.bind = usbnet_cdc_bind,
.unbind = usbnet_cdc_unbind,
.status = usbnet_cdc_status,
- .set_rx_mode = usbnet_cdc_update_filter,
.manage_power = usbnet_manage_power,
};
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index e330332..6fb0384 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -422,7 +422,7 @@
/* map MBIM session to VLAN */
if (tci)
- __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tci);
+ vlan_put_tag(skb, htons(ETH_P_8021Q), tci);
err:
return skb;
}
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index c138280..80fa223 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -780,7 +780,6 @@
{QMI_FIXED_INTF(0x413c, 0x81a4, 8)}, /* Dell Wireless 5570e HSPA+ (42Mbps) Mobile Broadband Card */
{QMI_FIXED_INTF(0x413c, 0x81a8, 8)}, /* Dell Wireless 5808 Gobi(TM) 4G LTE Mobile Broadband Card */
{QMI_FIXED_INTF(0x413c, 0x81a9, 8)}, /* Dell Wireless 5808e Gobi(TM) 4G LTE Mobile Broadband Card */
- {QMI_FIXED_INTF(0x03f0, 0x581d, 4)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Module (Huawei me906e) */
/* 4. Gobi 1000 devices */
{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index a0dcb2f..d8bc646 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1054,21 +1054,6 @@
clear_bit(EVENT_LINK_CHANGE, &dev->flags);
}
-static void usbnet_set_rx_mode(struct net_device *net)
-{
- struct usbnet *dev = netdev_priv(net);
-
- usbnet_defer_kevent(dev, EVENT_SET_RX_MODE);
-}
-
-static void __handle_set_rx_mode(struct usbnet *dev)
-{
- if (dev->driver_info->set_rx_mode)
- (dev->driver_info->set_rx_mode)(dev);
-
- clear_bit(EVENT_SET_RX_MODE, &dev->flags);
-}
-
/* work that cannot be done in interrupt context uses keventd.
*
* NOTE: with 2.5 we could do more of this using completion callbacks,
@@ -1174,10 +1159,6 @@
if (test_bit (EVENT_LINK_CHANGE, &dev->flags))
__handle_link_change(dev);
- if (test_bit (EVENT_SET_RX_MODE, &dev->flags))
- __handle_set_rx_mode(dev);
-
-
if (dev->flags)
netdev_dbg(dev->net, "kevent done, flags = 0x%lx\n", dev->flags);
}
@@ -1564,7 +1545,6 @@
.ndo_stop = usbnet_stop,
.ndo_start_xmit = usbnet_start_xmit,
.ndo_tx_timeout = usbnet_tx_timeout,
- .ndo_set_rx_mode = usbnet_set_rx_mode,
.ndo_change_mtu = usbnet_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 74d4104..c937dac 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -28,7 +28,7 @@
Right now only ath9k makes use of this.
config ATH_TRACEPOINTS
- depends on !KERNEL_3_1
+ depends on !BACKPORT_KERNEL_3_1
bool "Atheros wireless tracing"
depends on ATH_DEBUG
depends on EVENT_TRACING
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h
index 6d58a3e..91c1893 100644
--- a/drivers/net/wireless/ath/ath.h
+++ b/drivers/net/wireless/ath/ath.h
@@ -80,7 +80,6 @@
struct ath_regulatory {
char alpha2[2];
- enum nl80211_dfs_regions region;
u16 country_code;
u16 max_power_level;
u16 current_rd;
@@ -135,11 +134,6 @@
struct ath_common;
struct ath_bus_ops;
-struct ath_ps_ops {
- void (*wakeup)(struct ath_common *common);
- void (*restore)(struct ath_common *common);
-};
-
struct ath_common {
void *ah;
void *priv;
@@ -153,7 +147,7 @@
u16 cachelsz;
u16 curaid;
u8 macaddr[ETH_ALEN];
- u8 curbssid[ETH_ALEN] __aligned(2);
+ u8 curbssid[ETH_ALEN];
u8 bssidmask[ETH_ALEN];
u32 rx_bufsize;
@@ -174,7 +168,6 @@
struct ath_regulatory reg_world_copy;
const struct ath_ops *ops;
const struct ath_bus_ops *bus_ops;
- const struct ath_ps_ops *ps_ops;
bool btcoex_enabled;
bool disable_ani;
@@ -184,11 +177,6 @@
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
};
-static inline const struct ath_ps_ops *ath_ps_ops(struct ath_common *common)
-{
- return common->ps_ops;
-}
-
struct sk_buff *ath_rxbuf_alloc(struct ath_common *common,
u32 len,
gfp_t gfp_mask);
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index bf01fad..eb8ecdf 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -34,7 +34,7 @@
If unsure, say Y to make it easier to debug problems.
config ATH10K_TRACING
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
bool "Atheros ath10k tracing support"
depends on ATH10K
depends on EVENT_TRACING
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 842d941..de7426a 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -445,12 +445,12 @@
* Guts of ath10k_ce_completed_recv_next.
* The caller takes responsibility for any necessary locking.
*/
-int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
- void **per_transfer_contextp,
- u32 *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp,
- unsigned int *flagsp)
+static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
+ void **per_transfer_contextp,
+ u32 *bufferp,
+ unsigned int *nbytesp,
+ unsigned int *transfer_idp,
+ unsigned int *flagsp)
{
struct ath10k_ce_ring *dest_ring = ce_state->dest_ring;
unsigned int nentries_mask = dest_ring->nentries_mask;
@@ -560,7 +560,6 @@
/* sanity */
dest_ring->per_transfer_context[sw_index] = NULL;
- desc->nbytes = 0;
/* Update sw_index */
sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index);
@@ -579,11 +578,11 @@
* Guts of ath10k_ce_completed_send_next.
* The caller takes responsibility for any necessary locking.
*/
-int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
- void **per_transfer_contextp,
- u32 *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp)
+static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
+ void **per_transfer_contextp,
+ u32 *bufferp,
+ unsigned int *nbytesp,
+ unsigned int *transfer_idp)
{
struct ath10k_ce_ring *src_ring = ce_state->src_ring;
u32 ctrl_addr = ce_state->ctrl_addr;
@@ -820,10 +819,7 @@
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int ce_id;
- /* Skip the last copy engine, CE7 the diagnostic window, as that
- * uses polling and isn't initialized for interrupts.
- */
- for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++)
+ for (ce_id = 0; ce_id < CE_COUNT; ce_id++)
ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]);
}
@@ -838,8 +834,8 @@
nentries = roundup_pow_of_two(attr->src_nentries);
- memset(src_ring->base_addr_owner_space, 0,
- nentries * sizeof(struct ce_desc));
+ memset(src_ring->per_transfer_context, 0,
+ nentries * sizeof(*src_ring->per_transfer_context));
src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr);
src_ring->sw_index &= src_ring->nentries_mask;
@@ -875,8 +871,8 @@
nentries = roundup_pow_of_two(attr->dest_nentries);
- memset(dest_ring->base_addr_owner_space, 0,
- nentries * sizeof(struct ce_desc));
+ memset(dest_ring->per_transfer_context, 0,
+ nentries * sizeof(*dest_ring->per_transfer_context));
dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr);
dest_ring->sw_index &= dest_ring->nentries_mask;
@@ -1034,10 +1030,37 @@
* initialized by software/firmware.
*/
int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
- const struct ce_attr *attr)
+ const struct ce_attr *attr,
+ void (*send_cb)(struct ath10k_ce_pipe *),
+ void (*recv_cb)(struct ath10k_ce_pipe *))
{
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
int ret;
+ /*
+ * Make sure there's enough CE ringbuffer entries for HTT TX to avoid
+ * additional TX locking checks.
+ *
+ * For the lack of a better place do the check here.
+ */
+ BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
+ (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
+ BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
+ (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
+
+ spin_lock_bh(&ar_pci->ce_lock);
+ ce_state->ar = ar;
+ ce_state->id = ce_id;
+ ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
+ ce_state->attr_flags = attr->flags;
+ ce_state->src_sz_max = attr->src_sz_max;
+ if (attr->src_nentries)
+ ce_state->send_cb = send_cb;
+ if (attr->dest_nentries)
+ ce_state->recv_cb = recv_cb;
+ spin_unlock_bh(&ar_pci->ce_lock);
+
if (attr->src_nentries) {
ret = ath10k_ce_init_src_ring(ar, ce_id, attr);
if (ret) {
@@ -1085,37 +1108,12 @@
}
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
- const struct ce_attr *attr,
- void (*send_cb)(struct ath10k_ce_pipe *),
- void (*recv_cb)(struct ath10k_ce_pipe *))
+ const struct ce_attr *attr)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id];
int ret;
- /*
- * Make sure there's enough CE ringbuffer entries for HTT TX to avoid
- * additional TX locking checks.
- *
- * For the lack of a better place do the check here.
- */
- BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC >
- (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
- BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC >
- (CE_HTT_H2T_MSG_SRC_NENTRIES - 1));
-
- ce_state->ar = ar;
- ce_state->id = ce_id;
- ce_state->ctrl_addr = ath10k_ce_base_address(ce_id);
- ce_state->attr_flags = attr->flags;
- ce_state->src_sz_max = attr->src_sz_max;
-
- if (attr->src_nentries)
- ce_state->send_cb = send_cb;
-
- if (attr->dest_nentries)
- ce_state->recv_cb = recv_cb;
-
if (attr->src_nentries) {
ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr);
if (IS_ERR(ce_state->src_ring)) {
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index 617a151..329b734 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -192,21 +192,15 @@
unsigned int *nbytesp,
unsigned int *transfer_idp);
-int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state,
- void **per_transfer_contextp,
- u32 *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp);
-
/*==================CE Engine Initialization=======================*/
int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id,
- const struct ce_attr *attr);
+ const struct ce_attr *attr,
+ void (*send_cb)(struct ath10k_ce_pipe *),
+ void (*recv_cb)(struct ath10k_ce_pipe *));
void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id);
int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id,
- const struct ce_attr *attr,
- void (*send_cb)(struct ath10k_ce_pipe *),
- void (*recv_cb)(struct ath10k_ce_pipe *));
+ const struct ce_attr *attr);
void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id);
/*==================CE Engine Shutdown=======================*/
@@ -219,13 +213,6 @@
void **per_transfer_contextp,
u32 *bufferp);
-int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state,
- void **per_transfer_contextp,
- u32 *bufferp,
- unsigned int *nbytesp,
- unsigned int *transfer_idp,
- unsigned int *flagsp);
-
/*
* Support clean shutdown by allowing the caller to cancel
* pending sends. Target DMA must be stopped before using
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 4a9bfdc..5a08f55 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -31,17 +31,12 @@
unsigned int ath10k_debug_mask;
static bool uart_print;
static unsigned int ath10k_p2p;
-static bool skip_otp;
-
module_param_named(debug_mask, ath10k_debug_mask, uint, 0644);
module_param(uart_print, bool, 0644);
module_param_named(p2p, ath10k_p2p, uint, 0644);
-module_param(skip_otp, bool, 0644);
-
MODULE_PARM_DESC(debug_mask, "Debugging mask");
MODULE_PARM_DESC(uart_print, "Uart target debugging");
MODULE_PARM_DESC(p2p, "Enable ath10k P2P support");
-MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode");
static const struct ath10k_hw_params ath10k_hw_params_list[] = {
{
@@ -143,8 +138,7 @@
return fw;
}
-static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data,
- size_t data_len)
+static int ath10k_push_board_ext_data(struct ath10k *ar)
{
u32 board_data_size = QCA988X_BOARD_DATA_SZ;
u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ;
@@ -165,14 +159,14 @@
if (board_ext_data_addr == 0)
return 0;
- if (data_len != (board_data_size + board_ext_data_size)) {
+ if (ar->board_len != (board_data_size + board_ext_data_size)) {
ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n",
- data_len, board_data_size, board_ext_data_size);
+ ar->board_len, board_data_size, board_ext_data_size);
return -EINVAL;
}
ret = ath10k_bmi_write_memory(ar, board_ext_data_addr,
- data + board_data_size,
+ ar->board_data + board_data_size,
board_ext_data_size);
if (ret) {
ath10k_err(ar, "could not write board ext data (%d)\n", ret);
@@ -190,14 +184,13 @@
return 0;
}
-static int ath10k_download_board_data(struct ath10k *ar, const void *data,
- size_t data_len)
+static int ath10k_download_board_data(struct ath10k *ar)
{
u32 board_data_size = QCA988X_BOARD_DATA_SZ;
u32 address;
int ret;
- ret = ath10k_push_board_ext_data(ar, data, data_len);
+ ret = ath10k_push_board_ext_data(ar);
if (ret) {
ath10k_err(ar, "could not push board ext data (%d)\n", ret);
goto exit;
@@ -209,9 +202,9 @@
goto exit;
}
- ret = ath10k_bmi_write_memory(ar, address, data,
+ ret = ath10k_bmi_write_memory(ar, address, ar->board_data,
min_t(u32, board_data_size,
- data_len));
+ ar->board_len));
if (ret) {
ath10k_err(ar, "could not write board data (%d)\n", ret);
goto exit;
@@ -227,39 +220,11 @@
return ret;
}
-static int ath10k_download_cal_file(struct ath10k *ar)
-{
- int ret;
-
- if (!ar->cal_file)
- return -ENOENT;
-
- if (IS_ERR(ar->cal_file))
- return PTR_ERR(ar->cal_file);
-
- ret = ath10k_download_board_data(ar, ar->cal_file->data,
- ar->cal_file->size);
- if (ret) {
- ath10k_err(ar, "failed to download cal_file data: %d\n", ret);
- return ret;
- }
-
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n");
-
- return 0;
-}
-
static int ath10k_download_and_run_otp(struct ath10k *ar)
{
u32 result, address = ar->hw_params.patch_load_addr;
int ret;
- ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len);
- if (ret) {
- ath10k_err(ar, "failed to download board data: %d\n", ret);
- return ret;
- }
-
/* OTP is optional */
if (!ar->otp_data || !ar->otp_len) {
@@ -285,7 +250,7 @@
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result);
- if (!skip_otp && result != 0) {
+ if (result != 0) {
ath10k_err(ar, "otp calibration failed: %d", result);
return -EINVAL;
}
@@ -343,9 +308,6 @@
if (ar->firmware && !IS_ERR(ar->firmware))
release_firmware(ar->firmware);
- if (ar->cal_file && !IS_ERR(ar->cal_file))
- release_firmware(ar->cal_file);
-
ar->board = NULL;
ar->board_data = NULL;
ar->board_len = 0;
@@ -357,27 +319,6 @@
ar->firmware = NULL;
ar->firmware_data = NULL;
ar->firmware_len = 0;
-
- ar->cal_file = NULL;
-}
-
-static int ath10k_fetch_cal_file(struct ath10k *ar)
-{
- char filename[100];
-
- /* cal-<bus>-<id>.bin */
- scnprintf(filename, sizeof(filename), "cal-%s-%s.bin",
- ath10k_bus_str(ar->hif.bus), dev_name(ar->dev));
-
- ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename);
- if (IS_ERR(ar->cal_file))
- /* calibration file is optional, don't print any warnings */
- return PTR_ERR(ar->cal_file);
-
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n",
- ATH10K_FW_DIR, filename);
-
- return 0;
}
static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar)
@@ -621,9 +562,6 @@
{
int ret;
- /* calibration file is optional, don't check for any errors */
- ath10k_fetch_cal_file(ar);
-
ar->fw_api = 3;
ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api);
@@ -651,32 +589,30 @@
return 0;
}
-static int ath10k_download_cal_data(struct ath10k *ar)
+static int ath10k_init_download_firmware(struct ath10k *ar,
+ enum ath10k_firmware_mode mode)
{
int ret;
- ret = ath10k_download_cal_file(ar);
- if (ret == 0) {
- ar->cal_mode = ATH10K_CAL_MODE_FILE;
- goto done;
+ ret = ath10k_download_board_data(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to download board data: %d\n", ret);
+ return ret;
}
- ath10k_dbg(ar, ATH10K_DBG_BOOT,
- "boot did not find a calibration file, try OTP next: %d\n",
- ret);
-
ret = ath10k_download_and_run_otp(ar);
if (ret) {
ath10k_err(ar, "failed to run otp: %d\n", ret);
return ret;
}
- ar->cal_mode = ATH10K_CAL_MODE_OTP;
+ ret = ath10k_download_fw(ar, mode);
+ if (ret) {
+ ath10k_err(ar, "failed to download firmware: %d\n", ret);
+ return ret;
+ }
-done:
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n",
- ath10k_cal_mode_str(ar->cal_mode));
- return 0;
+ return ret;
}
static int ath10k_init_uart(struct ath10k *ar)
@@ -759,25 +695,6 @@
ath10k_err(ar, "failed to execute ath10k-reset. trying driver-level reset.\n");
}
- set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
-
- /* Place a barrier to make sure the compiler doesn't reorder
- * CRASH_FLUSH and calling other functions.
- */
- barrier();
-
- ieee80211_stop_queues(ar->hw);
- ath10k_drain_tx(ar);
- complete_all(&ar->scan.started);
- complete_all(&ar->scan.completed);
- complete_all(&ar->scan.on_channel);
- complete_all(&ar->offchan_tx_completed);
- complete_all(&ar->install_key_done);
- complete_all(&ar->vdev_setup_done);
- wake_up(&ar->htt.empty_tx_wq);
- wake_up(&ar->wmi.tx_credits_wq);
- wake_up(&ar->peer_mapping_wq);
-
mutex_lock(&ar->conf_mutex);
switch (ar->state) {
@@ -809,25 +726,12 @@
mutex_unlock(&ar->conf_mutex);
}
-static void ath10k_core_init_max_sta_count(struct ath10k *ar)
-{
- if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
- ar->max_num_peers = TARGET_10X_NUM_PEERS;
- ar->max_num_stations = TARGET_10X_NUM_STATIONS;
- } else {
- ar->max_num_peers = TARGET_NUM_PEERS;
- ar->max_num_stations = TARGET_NUM_STATIONS;
- }
-}
-
int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode)
{
int status;
lockdep_assert_held(&ar->conf_mutex);
- clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags);
-
ath10k_bmi_start(ar);
if (ath10k_init_configure_target(ar)) {
@@ -835,11 +739,7 @@
goto err;
}
- status = ath10k_download_cal_data(ar);
- if (status)
- goto err;
-
- status = ath10k_download_fw(ar, mode);
+ status = ath10k_init_download_firmware(ar, mode);
if (status)
goto err;
@@ -956,9 +856,9 @@
goto err_hif_stop;
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
- ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1;
+ ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1;
else
- ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1;
+ ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
INIT_LIST_HEAD(&ar->arvifs);
@@ -1056,8 +956,6 @@
return ret;
}
- ath10k_core_init_max_sta_count(ar);
-
mutex_lock(&ar->conf_mutex);
ret = ath10k_core_start(ar, ATH10K_FIRMWARE_MODE_NORMAL);
@@ -1196,7 +1094,6 @@
EXPORT_SYMBOL(ath10k_core_unregister);
struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
- enum ath10k_bus bus,
const struct ath10k_hif_ops *hif_ops)
{
struct ath10k *ar;
@@ -1213,7 +1110,6 @@
ar->dev = dev;
ar->hif.ops = hif_ops;
- ar->hif.bus = bus;
init_completion(&ar->scan.started);
init_completion(&ar->scan.completed);
@@ -1234,8 +1130,6 @@
INIT_LIST_HEAD(&ar->peers);
init_waitqueue_head(&ar->peer_mapping_wq);
- init_waitqueue_head(&ar->htt.empty_tx_wq);
- init_waitqueue_head(&ar->wmi.tx_credits_wq);
init_completion(&ar->offchan_tx_completed);
INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index a20240c..8164721 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -63,28 +63,12 @@
struct ath10k;
-enum ath10k_bus {
- ATH10K_BUS_PCI,
-};
-
-static inline const char *ath10k_bus_str(enum ath10k_bus bus)
-{
- switch (bus) {
- case ATH10K_BUS_PCI:
- return "pci";
- }
-
- return "unknown";
-}
-
struct ath10k_skb_cb {
dma_addr_t paddr;
- u8 eid;
u8 vdev_id;
struct {
u8 tid;
- u16 freq;
bool is_offchan;
struct ath10k_htt_txbuf *txbuf;
u32 txbuf_paddr;
@@ -112,6 +96,8 @@
bool done_sent;
};
+#define ATH10K_MAX_MEM_REQS 16
+
struct ath10k_mem_chunk {
void *vaddr;
dma_addr_t paddr;
@@ -124,27 +110,22 @@
struct completion service_ready;
struct completion unified_ready;
wait_queue_head_t tx_credits_wq;
- DECLARE_BITMAP(svc_map, WMI_SERVICE_MAX);
struct wmi_cmd_map *cmd;
struct wmi_vdev_param_map *vdev_param;
struct wmi_pdev_param_map *pdev_param;
u32 num_mem_chunks;
- struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS];
+ struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS];
};
-struct ath10k_fw_stats_peer {
- struct list_head list;
-
+struct ath10k_peer_stat {
u8 peer_macaddr[ETH_ALEN];
u32 peer_rssi;
u32 peer_tx_rate;
u32 peer_rx_rate; /* 10x only */
};
-struct ath10k_fw_stats_pdev {
- struct list_head list;
-
+struct ath10k_target_stats {
/* PDEV stats */
s32 ch_noise_floor;
u32 tx_frame_count;
@@ -199,11 +180,15 @@
s32 phy_errs;
s32 phy_err_drop;
s32 mpdu_errs;
-};
-struct ath10k_fw_stats {
- struct list_head pdevs;
- struct list_head peers;
+ /* VDEV STATS */
+
+ /* PEER STATS */
+ u8 peers;
+ struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS];
+
+ /* TODO: Beacon filter stats */
+
};
struct ath10k_dfs_stats {
@@ -226,8 +211,6 @@
/* protected by data_lock */
DECLARE_BITMAP(peer_ids, ATH10K_MAX_NUM_PEER_IDS);
-
- /* protected by ar->data_lock */
struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];
};
@@ -256,8 +239,6 @@
struct sk_buff *beacon;
/* protected by data_lock */
bool beacon_sent;
- void *beacon_buf;
- dma_addr_t beacon_paddr;
struct ath10k *ar;
struct ieee80211_vif *vif;
@@ -297,7 +278,6 @@
u8 force_sgi;
bool use_cts_prot;
int num_legacy_stations;
- int txpower;
};
struct ath10k_vif_iter {
@@ -317,19 +297,17 @@
struct ath10k_debug {
struct dentry *debugfs_phy;
- struct ath10k_fw_stats fw_stats;
- struct completion fw_stats_complete;
- bool fw_stats_done;
+ struct ath10k_target_stats target_stats;
+ DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX);
+
+ struct completion event_stats_compl;
unsigned long htt_stats_mask;
struct delayed_work htt_stats_dwork;
struct ath10k_dfs_stats dfs_stats;
struct ath_dfs_pool_stats dfs_pool_stats;
- /* protected by conf_mutex */
u32 fw_dbglog_mask;
- u32 pktlog_filter;
- u32 reg_addr;
u8 htt_max_amsdu;
u8 htt_max_ampdu;
@@ -348,7 +326,7 @@
* stopped in ath10k_core_restart() work holding conf_mutex. The state
* RESTARTED means that the device is up and mac80211 has started hw
* reconfiguration. Once mac80211 is done with the reconfiguration we
- * set the state to STATE_ON in reconfig_complete(). */
+ * set the state to STATE_ON in restart_complete(). */
ATH10K_STATE_RESTARTING,
ATH10K_STATE_RESTARTED,
@@ -396,30 +374,8 @@
/* Indicates that ath10k device is during CAC phase of DFS */
ATH10K_CAC_RUNNING,
ATH10K_FLAG_CORE_REGISTERED,
-
- /* Device has crashed and needs to restart. This indicates any pending
- * waiters should immediately cancel instead of waiting for a time out.
- */
- ATH10K_FLAG_CRASH_FLUSH,
};
-enum ath10k_cal_mode {
- ATH10K_CAL_MODE_FILE,
- ATH10K_CAL_MODE_OTP,
-};
-
-static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode)
-{
- switch (mode) {
- case ATH10K_CAL_MODE_FILE:
- return "file";
- case ATH10K_CAL_MODE_OTP:
- return "otp";
- }
-
- return "unknown";
-}
-
enum ath10k_scan_state {
ATH10K_SCAN_IDLE,
ATH10K_SCAN_STARTING,
@@ -470,7 +426,6 @@
bool p2p;
struct {
- enum ath10k_bus bus;
const struct ath10k_hif_ops *ops;
} hif;
@@ -506,10 +461,7 @@
const void *firmware_data;
size_t firmware_len;
- const struct firmware *cal_file;
-
int fw_api;
- enum ath10k_cal_mode cal_mode;
struct {
struct completion started;
@@ -535,7 +487,7 @@
/* current operating channel definition */
struct cfg80211_chan_def chandef;
- unsigned long long free_vdev_map;
+ int free_vdev_map;
bool monitor;
int monitor_vdev_id;
bool monitor_started;
@@ -570,12 +522,8 @@
struct list_head peers;
wait_queue_head_t peer_mapping_wq;
- /* protected by conf_mutex */
+ /* number of created peers; protected by data_lock */
int num_peers;
- int num_stations;
-
- int max_num_peers;
- int max_num_stations;
struct work_struct offchan_tx_work;
struct sk_buff_head offchan_tx_queue;
@@ -621,19 +569,11 @@
bool utf_monitor;
} testmode;
- struct {
- /* protected by data_lock */
- u32 fw_crash_counter;
- u32 fw_warm_reset_counter;
- u32 fw_cold_reset_counter;
- } stats;
-
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
};
struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev,
- enum ath10k_bus bus,
const struct ath10k_hif_ops *hif_ops);
void ath10k_core_destroy(struct ath10k *ar);
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index ee7f8c1..f9a7cc3 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -17,12 +17,12 @@
#include <linux/module.h>
#include <linux/debugfs.h>
+#include <linux/version.h>
+#include <linux/vermagic.h>
#include <linux/vmalloc.h>
-#include <linux/utsname.h>
#include "core.h"
#include "debug.h"
-#include "hif.h"
/* ms */
#define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000
@@ -106,37 +106,34 @@
u8 data[0];
} __packed;
-void ath10k_info(struct ath10k *ar, const char *fmt, ...)
+int ath10k_info(struct ath10k *ar, const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
};
va_list args;
+ int ret;
va_start(args, fmt);
vaf.va = &args;
- dev_info(ar->dev, "%pV", &vaf);
+ ret = dev_info(ar->dev, "%pV", &vaf);
trace_ath10k_log_info(ar, &vaf);
va_end(args);
+
+ return ret;
}
EXPORT_SYMBOL(ath10k_info);
void ath10k_print_driver_info(struct ath10k *ar)
{
- ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d cal %s max_sta %d\n",
+ ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n",
ar->hw_params.name,
ar->target_version,
ar->chip_id,
ar->hw->wiphy->fw_version,
ar->fw_api,
ar->htt.target_version_major,
- ar->htt.target_version_minor,
- ar->fw_version_major,
- ar->fw_version_minor,
- ar->fw_version_release,
- ar->fw_version_build,
- ath10k_cal_mode_str(ar->cal_mode),
- ar->max_num_stations);
+ ar->htt.target_version_minor);
ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n",
config_enabled(CPTCFG_ATH10K_DEBUG),
config_enabled(CPTCFG_ATH10K_DEBUGFS),
@@ -146,22 +143,25 @@
}
EXPORT_SYMBOL(ath10k_print_driver_info);
-void ath10k_err(struct ath10k *ar, const char *fmt, ...)
+int ath10k_err(struct ath10k *ar, const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
};
va_list args;
+ int ret;
va_start(args, fmt);
vaf.va = &args;
- dev_err(ar->dev, "%pV", &vaf);
+ ret = dev_err(ar->dev, "%pV", &vaf);
trace_ath10k_log_err(ar, &vaf);
va_end(args);
+
+ return ret;
}
EXPORT_SYMBOL(ath10k_err);
-void ath10k_warn(struct ath10k *ar, const char *fmt, ...)
+int ath10k_warn(struct ath10k *ar, const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
@@ -174,11 +174,20 @@
trace_ath10k_log_warn(ar, &vaf);
va_end(args);
+
+ return 0;
}
EXPORT_SYMBOL(ath10k_warn);
#ifdef CPTCFG_ATH10K_DEBUGFS
+void ath10k_debug_read_service_map(struct ath10k *ar,
+ void *service_map,
+ size_t map_size)
+{
+ memcpy(ar->debug.wmi_service_bitmap, service_map, map_size);
+}
+
static ssize_t ath10k_read_wmi_services(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
@@ -200,9 +209,8 @@
if (len > buf_len)
len = buf_len;
- spin_lock_bh(&ar->data_lock);
for (i = 0; i < WMI_SERVICE_MAX; i++) {
- enabled = test_bit(i, ar->wmi.svc_map);
+ enabled = test_bit(i, ar->debug.wmi_service_bitmap);
name = wmi_service_name(i);
if (!name) {
@@ -218,7 +226,6 @@
"%-40s %s\n",
name, enabled ? "enabled" : "-");
}
- spin_unlock_bh(&ar->data_lock);
ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
@@ -235,182 +242,169 @@
.llseek = default_llseek,
};
-static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head)
+void ath10k_debug_read_target_stats(struct ath10k *ar,
+ struct wmi_stats_event *ev)
{
- struct ath10k_fw_stats_pdev *i, *tmp;
+ u8 *tmp = ev->data;
+ struct ath10k_target_stats *stats;
+ int num_pdev_stats, num_vdev_stats, num_peer_stats;
+ struct wmi_pdev_stats_10x *ps;
+ int i;
- list_for_each_entry_safe(i, tmp, head, list) {
- list_del(&i->list);
- kfree(i);
- }
-}
-
-static void ath10k_debug_fw_stats_peers_free(struct list_head *head)
-{
- struct ath10k_fw_stats_peer *i, *tmp;
-
- list_for_each_entry_safe(i, tmp, head, list) {
- list_del(&i->list);
- kfree(i);
- }
-}
-
-static void ath10k_debug_fw_stats_reset(struct ath10k *ar)
-{
spin_lock_bh(&ar->data_lock);
- ar->debug.fw_stats_done = false;
- ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs);
- ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers);
+
+ stats = &ar->debug.target_stats;
+
+ num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); /* 0 or 1 */
+ num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); /* 0 or max vdevs */
+ num_peer_stats = __le32_to_cpu(ev->num_peer_stats); /* 0 or max peers */
+
+ if (num_pdev_stats) {
+ ps = (struct wmi_pdev_stats_10x *)tmp;
+
+ stats->ch_noise_floor = __le32_to_cpu(ps->chan_nf);
+ stats->tx_frame_count = __le32_to_cpu(ps->tx_frame_count);
+ stats->rx_frame_count = __le32_to_cpu(ps->rx_frame_count);
+ stats->rx_clear_count = __le32_to_cpu(ps->rx_clear_count);
+ stats->cycle_count = __le32_to_cpu(ps->cycle_count);
+ stats->phy_err_count = __le32_to_cpu(ps->phy_err_count);
+ stats->chan_tx_power = __le32_to_cpu(ps->chan_tx_pwr);
+
+ stats->comp_queued = __le32_to_cpu(ps->wal.tx.comp_queued);
+ stats->comp_delivered =
+ __le32_to_cpu(ps->wal.tx.comp_delivered);
+ stats->msdu_enqued = __le32_to_cpu(ps->wal.tx.msdu_enqued);
+ stats->mpdu_enqued = __le32_to_cpu(ps->wal.tx.mpdu_enqued);
+ stats->wmm_drop = __le32_to_cpu(ps->wal.tx.wmm_drop);
+ stats->local_enqued = __le32_to_cpu(ps->wal.tx.local_enqued);
+ stats->local_freed = __le32_to_cpu(ps->wal.tx.local_freed);
+ stats->hw_queued = __le32_to_cpu(ps->wal.tx.hw_queued);
+ stats->hw_reaped = __le32_to_cpu(ps->wal.tx.hw_reaped);
+ stats->underrun = __le32_to_cpu(ps->wal.tx.underrun);
+ stats->tx_abort = __le32_to_cpu(ps->wal.tx.tx_abort);
+ stats->mpdus_requed = __le32_to_cpu(ps->wal.tx.mpdus_requed);
+ stats->tx_ko = __le32_to_cpu(ps->wal.tx.tx_ko);
+ stats->data_rc = __le32_to_cpu(ps->wal.tx.data_rc);
+ stats->self_triggers = __le32_to_cpu(ps->wal.tx.self_triggers);
+ stats->sw_retry_failure =
+ __le32_to_cpu(ps->wal.tx.sw_retry_failure);
+ stats->illgl_rate_phy_err =
+ __le32_to_cpu(ps->wal.tx.illgl_rate_phy_err);
+ stats->pdev_cont_xretry =
+ __le32_to_cpu(ps->wal.tx.pdev_cont_xretry);
+ stats->pdev_tx_timeout =
+ __le32_to_cpu(ps->wal.tx.pdev_tx_timeout);
+ stats->pdev_resets = __le32_to_cpu(ps->wal.tx.pdev_resets);
+ stats->phy_underrun = __le32_to_cpu(ps->wal.tx.phy_underrun);
+ stats->txop_ovf = __le32_to_cpu(ps->wal.tx.txop_ovf);
+
+ stats->mid_ppdu_route_change =
+ __le32_to_cpu(ps->wal.rx.mid_ppdu_route_change);
+ stats->status_rcvd = __le32_to_cpu(ps->wal.rx.status_rcvd);
+ stats->r0_frags = __le32_to_cpu(ps->wal.rx.r0_frags);
+ stats->r1_frags = __le32_to_cpu(ps->wal.rx.r1_frags);
+ stats->r2_frags = __le32_to_cpu(ps->wal.rx.r2_frags);
+ stats->r3_frags = __le32_to_cpu(ps->wal.rx.r3_frags);
+ stats->htt_msdus = __le32_to_cpu(ps->wal.rx.htt_msdus);
+ stats->htt_mpdus = __le32_to_cpu(ps->wal.rx.htt_mpdus);
+ stats->loc_msdus = __le32_to_cpu(ps->wal.rx.loc_msdus);
+ stats->loc_mpdus = __le32_to_cpu(ps->wal.rx.loc_mpdus);
+ stats->oversize_amsdu =
+ __le32_to_cpu(ps->wal.rx.oversize_amsdu);
+ stats->phy_errs = __le32_to_cpu(ps->wal.rx.phy_errs);
+ stats->phy_err_drop = __le32_to_cpu(ps->wal.rx.phy_err_drop);
+ stats->mpdu_errs = __le32_to_cpu(ps->wal.rx.mpdu_errs);
+
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X,
+ ar->fw_features)) {
+ stats->ack_rx_bad = __le32_to_cpu(ps->ack_rx_bad);
+ stats->rts_bad = __le32_to_cpu(ps->rts_bad);
+ stats->rts_good = __le32_to_cpu(ps->rts_good);
+ stats->fcs_bad = __le32_to_cpu(ps->fcs_bad);
+ stats->no_beacons = __le32_to_cpu(ps->no_beacons);
+ stats->mib_int_count = __le32_to_cpu(ps->mib_int_count);
+ tmp += sizeof(struct wmi_pdev_stats_10x);
+ } else {
+ tmp += sizeof(struct wmi_pdev_stats_old);
+ }
+ }
+
+ /* 0 or max vdevs */
+ /* Currently firmware does not support VDEV stats */
+ if (num_vdev_stats) {
+ struct wmi_vdev_stats *vdev_stats;
+
+ for (i = 0; i < num_vdev_stats; i++) {
+ vdev_stats = (struct wmi_vdev_stats *)tmp;
+ tmp += sizeof(struct wmi_vdev_stats);
+ }
+ }
+
+ if (num_peer_stats) {
+ struct wmi_peer_stats_10x *peer_stats;
+ struct ath10k_peer_stat *s;
+
+ stats->peers = num_peer_stats;
+
+ for (i = 0; i < num_peer_stats; i++) {
+ peer_stats = (struct wmi_peer_stats_10x *)tmp;
+ s = &stats->peer_stat[i];
+
+ memcpy(s->peer_macaddr, &peer_stats->peer_macaddr.addr,
+ ETH_ALEN);
+ s->peer_rssi = __le32_to_cpu(peer_stats->peer_rssi);
+ s->peer_tx_rate =
+ __le32_to_cpu(peer_stats->peer_tx_rate);
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X,
+ ar->fw_features)) {
+ s->peer_rx_rate =
+ __le32_to_cpu(peer_stats->peer_rx_rate);
+ tmp += sizeof(struct wmi_peer_stats_10x);
+
+ } else {
+ tmp += sizeof(struct wmi_peer_stats_old);
+ }
+ }
+ }
+
spin_unlock_bh(&ar->data_lock);
+ complete(&ar->debug.event_stats_compl);
}
-static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head)
+static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- struct ath10k_fw_stats_peer *i;
- size_t num = 0;
-
- list_for_each_entry(i, head, list)
- ++num;
-
- return num;
-}
-
-void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb)
-{
- struct ath10k_fw_stats stats = {};
- bool is_start, is_started, is_end;
- size_t num_peers;
+ struct ath10k *ar = file->private_data;
+ struct ath10k_target_stats *fw_stats;
+ char *buf = NULL;
+ unsigned int len = 0, buf_len = 8000;
+ ssize_t ret_cnt = 0;
+ long left;
+ int i;
int ret;
- INIT_LIST_HEAD(&stats.pdevs);
- INIT_LIST_HEAD(&stats.peers);
+ fw_stats = &ar->debug.target_stats;
- spin_lock_bh(&ar->data_lock);
- ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats);
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->state != ATH10K_STATE_ON)
+ goto exit;
+
+ buf = kzalloc(buf_len, GFP_KERNEL|__GFP_REPEAT|__GFP_HIGH);
+ if (!buf)
+ goto exit;
+
+ ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
if (ret) {
- ath10k_warn(ar, "failed to pull fw stats: %d\n", ret);
- goto unlock;
+ ath10k_warn(ar, "could not request stats (%d)\n", ret);
+ goto exit;
}
- /* Stat data may exceed htc-wmi buffer limit. In such case firmware
- * splits the stats data and delivers it in a ping-pong fashion of
- * request cmd-update event.
- *
- * However there is no explicit end-of-data. Instead start-of-data is
- * used as an implicit one. This works as follows:
- * a) discard stat update events until one with pdev stats is
- * delivered - this skips session started at end of (b)
- * b) consume stat update events until another one with pdev stats is
- * delivered which is treated as end-of-data and is itself discarded
- */
-
- if (ar->debug.fw_stats_done) {
- ath10k_warn(ar, "received unsolicited stats update event\n");
- goto free;
- }
-
- num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers);
- is_start = (list_empty(&ar->debug.fw_stats.pdevs) &&
- !list_empty(&stats.pdevs));
- is_end = (!list_empty(&ar->debug.fw_stats.pdevs) &&
- !list_empty(&stats.pdevs));
-
- if (is_start)
- list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs);
-
- if (is_end)
- ar->debug.fw_stats_done = true;
-
- is_started = !list_empty(&ar->debug.fw_stats.pdevs);
-
- if (is_started && !is_end) {
- if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) {
- /* Although this is unlikely impose a sane limit to
- * prevent firmware from DoS-ing the host.
- */
- ath10k_warn(ar, "dropping fw peer stats\n");
- goto free;
- }
-
- list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers);
- }
-
- complete(&ar->debug.fw_stats_complete);
-
-free:
- /* In some cases lists have been spliced and cleared. Free up
- * resources if that is not the case.
- */
- ath10k_debug_fw_stats_pdevs_free(&stats.pdevs);
- ath10k_debug_fw_stats_peers_free(&stats.peers);
-
-unlock:
- spin_unlock_bh(&ar->data_lock);
-}
-
-static int ath10k_debug_fw_stats_request(struct ath10k *ar)
-{
- unsigned long timeout;
- int ret;
-
- lockdep_assert_held(&ar->conf_mutex);
-
- timeout = jiffies + msecs_to_jiffies(1*HZ);
-
- ath10k_debug_fw_stats_reset(ar);
-
- for (;;) {
- if (time_after(jiffies, timeout))
- return -ETIMEDOUT;
-
- reinit_completion(&ar->debug.fw_stats_complete);
-
- ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT);
- if (ret) {
- ath10k_warn(ar, "could not request stats (%d)\n", ret);
- return ret;
- }
-
- ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete,
- 1*HZ);
- if (ret <= 0)
- return -ETIMEDOUT;
-
- spin_lock_bh(&ar->data_lock);
- if (ar->debug.fw_stats_done) {
- spin_unlock_bh(&ar->data_lock);
- break;
- }
- spin_unlock_bh(&ar->data_lock);
- }
-
- return 0;
-}
-
-/* FIXME: How to calculate the buffer size sanely? */
-#define ATH10K_FW_STATS_BUF_SIZE (1024*1024)
-
-static void ath10k_fw_stats_fill(struct ath10k *ar,
- struct ath10k_fw_stats *fw_stats,
- char *buf)
-{
- unsigned int len = 0;
- unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE;
- const struct ath10k_fw_stats_pdev *pdev;
- const struct ath10k_fw_stats_peer *peer;
- size_t num_peers;
+ left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ);
+ if (left <= 0)
+ goto exit;
spin_lock_bh(&ar->data_lock);
-
- pdev = list_first_entry_or_null(&fw_stats->pdevs,
- struct ath10k_fw_stats_pdev, list);
- if (!pdev) {
- ath10k_warn(ar, "failed to get pdev stats\n");
- goto unlock;
- }
-
- num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers);
-
len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s\n",
"ath10k PDEV stats");
@@ -418,29 +412,29 @@
"=================");
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Channel noise floor", pdev->ch_noise_floor);
+ "Channel noise floor", fw_stats->ch_noise_floor);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "Channel TX power", pdev->chan_tx_power);
+ "Channel TX power", fw_stats->chan_tx_power);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "TX frame count", pdev->tx_frame_count);
+ "TX frame count", fw_stats->tx_frame_count);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RX frame count", pdev->rx_frame_count);
+ "RX frame count", fw_stats->rx_frame_count);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RX clear count", pdev->rx_clear_count);
+ "RX clear count", fw_stats->rx_clear_count);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "Cycle count", pdev->cycle_count);
+ "Cycle count", fw_stats->cycle_count);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "PHY error count", pdev->phy_err_count);
+ "PHY error count", fw_stats->phy_err_count);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RTS bad count", pdev->rts_bad);
+ "RTS bad count", fw_stats->rts_bad);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "RTS good count", pdev->rts_good);
+ "RTS good count", fw_stats->rts_good);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "FCS bad count", pdev->fcs_bad);
+ "FCS bad count", fw_stats->fcs_bad);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "No beacon count", pdev->no_beacons);
+ "No beacon count", fw_stats->no_beacons);
len += scnprintf(buf + len, buf_len - len, "%30s %10u\n",
- "MIB int count", pdev->mib_int_count);
+ "MIB int count", fw_stats->mib_int_count);
len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s\n",
@@ -449,51 +443,51 @@
"=================");
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HTT cookies queued", pdev->comp_queued);
+ "HTT cookies queued", fw_stats->comp_queued);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HTT cookies disp.", pdev->comp_delivered);
+ "HTT cookies disp.", fw_stats->comp_delivered);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDU queued", pdev->msdu_enqued);
+ "MSDU queued", fw_stats->msdu_enqued);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDU queued", pdev->mpdu_enqued);
+ "MPDU queued", fw_stats->mpdu_enqued);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDUs dropped", pdev->wmm_drop);
+ "MSDUs dropped", fw_stats->wmm_drop);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Local enqued", pdev->local_enqued);
+ "Local enqued", fw_stats->local_enqued);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Local freed", pdev->local_freed);
+ "Local freed", fw_stats->local_freed);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HW queued", pdev->hw_queued);
+ "HW queued", fw_stats->hw_queued);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PPDUs reaped", pdev->hw_reaped);
+ "PPDUs reaped", fw_stats->hw_reaped);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Num underruns", pdev->underrun);
+ "Num underruns", fw_stats->underrun);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PPDUs cleaned", pdev->tx_abort);
+ "PPDUs cleaned", fw_stats->tx_abort);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDUs requed", pdev->mpdus_requed);
+ "MPDUs requed", fw_stats->mpdus_requed);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Excessive retries", pdev->tx_ko);
+ "Excessive retries", fw_stats->tx_ko);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "HW rate", pdev->data_rc);
+ "HW rate", fw_stats->data_rc);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Sched self tiggers", pdev->self_triggers);
+ "Sched self tiggers", fw_stats->self_triggers);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
"Dropped due to SW retries",
- pdev->sw_retry_failure);
+ fw_stats->sw_retry_failure);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
"Illegal rate phy errors",
- pdev->illgl_rate_phy_err);
+ fw_stats->illgl_rate_phy_err);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Pdev continous xretry", pdev->pdev_cont_xretry);
+ "Pdev continous xretry", fw_stats->pdev_cont_xretry);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "TX timeout", pdev->pdev_tx_timeout);
+ "TX timeout", fw_stats->pdev_tx_timeout);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PDEV resets", pdev->pdev_resets);
+ "PDEV resets", fw_stats->pdev_resets);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PHY underrun", pdev->phy_underrun);
+ "PHY underrun", fw_stats->phy_underrun);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDU is more than txop limit", pdev->txop_ovf);
+ "MPDU is more than txop limit", fw_stats->txop_ovf);
len += scnprintf(buf + len, buf_len - len, "\n");
len += scnprintf(buf + len, buf_len - len, "%30s\n",
@@ -503,161 +497,70 @@
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
"Mid PPDU route change",
- pdev->mid_ppdu_route_change);
+ fw_stats->mid_ppdu_route_change);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Tot. number of statuses", pdev->status_rcvd);
+ "Tot. number of statuses", fw_stats->status_rcvd);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 0", pdev->r0_frags);
+ "Extra frags on rings 0", fw_stats->r0_frags);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 1", pdev->r1_frags);
+ "Extra frags on rings 1", fw_stats->r1_frags);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 2", pdev->r2_frags);
+ "Extra frags on rings 2", fw_stats->r2_frags);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Extra frags on rings 3", pdev->r3_frags);
+ "Extra frags on rings 3", fw_stats->r3_frags);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDUs delivered to HTT", pdev->htt_msdus);
+ "MSDUs delivered to HTT", fw_stats->htt_msdus);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDUs delivered to HTT", pdev->htt_mpdus);
+ "MPDUs delivered to HTT", fw_stats->htt_mpdus);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MSDUs delivered to stack", pdev->loc_msdus);
+ "MSDUs delivered to stack", fw_stats->loc_msdus);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDUs delivered to stack", pdev->loc_mpdus);
+ "MPDUs delivered to stack", fw_stats->loc_mpdus);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "Oversized AMSUs", pdev->oversize_amsdu);
+ "Oversized AMSUs", fw_stats->oversize_amsdu);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PHY errors", pdev->phy_errs);
+ "PHY errors", fw_stats->phy_errs);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "PHY errors drops", pdev->phy_err_drop);
+ "PHY errors drops", fw_stats->phy_err_drop);
len += scnprintf(buf + len, buf_len - len, "%30s %10d\n",
- "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs);
+ "MPDU errors (FCS, MIC, ENC)", fw_stats->mpdu_errs);
len += scnprintf(buf + len, buf_len - len, "\n");
- len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n",
- "ath10k PEER stats", num_peers);
+ len += scnprintf(buf + len, buf_len - len, "%30s (%d)\n",
+ "ath10k PEER stats", fw_stats->peers);
len += scnprintf(buf + len, buf_len - len, "%30s\n\n",
"=================");
- list_for_each_entry(peer, &fw_stats->peers, list) {
+ for (i = 0; i < fw_stats->peers; i++) {
len += scnprintf(buf + len, buf_len - len, "%30s %pM\n",
- "Peer MAC address", peer->peer_macaddr);
+ "Peer MAC address",
+ fw_stats->peer_stat[i].peer_macaddr);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "Peer RSSI", peer->peer_rssi);
+ "Peer RSSI", fw_stats->peer_stat[i].peer_rssi);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "Peer TX rate", peer->peer_tx_rate);
+ "Peer TX rate",
+ fw_stats->peer_stat[i].peer_tx_rate);
len += scnprintf(buf + len, buf_len - len, "%30s %u\n",
- "Peer RX rate", peer->peer_rx_rate);
+ "Peer RX rate",
+ fw_stats->peer_stat[i].peer_rx_rate);
len += scnprintf(buf + len, buf_len - len, "\n");
}
-
-unlock:
spin_unlock_bh(&ar->data_lock);
- if (len >= buf_len)
- buf[len - 1] = 0;
- else
- buf[len] = 0;
-}
+ if (len > buf_len)
+ len = buf_len;
-static int ath10k_fw_stats_open(struct inode *inode, struct file *file)
-{
- struct ath10k *ar = inode->i_private;
- void *buf = NULL;
- int ret;
+ ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- mutex_lock(&ar->conf_mutex);
-
- if (ar->state != ATH10K_STATE_ON) {
- ret = -ENETDOWN;
- goto err_unlock;
- }
-
- buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE);
- if (!buf) {
- ret = -ENOMEM;
- goto err_unlock;
- }
-
- ret = ath10k_debug_fw_stats_request(ar);
- if (ret) {
- ath10k_warn(ar, "failed to request fw stats: %d\n", ret);
- goto err_free;
- }
-
- ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf);
- file->private_data = buf;
-
+exit:
mutex_unlock(&ar->conf_mutex);
- return 0;
-
-err_free:
- vfree(buf);
-
-err_unlock:
- mutex_unlock(&ar->conf_mutex);
- return ret;
-}
-
-static int ath10k_fw_stats_release(struct inode *inode, struct file *file)
-{
- vfree(file->private_data);
-
- return 0;
-}
-
-static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- const char *buf = file->private_data;
- unsigned int len = strlen(buf);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+ return ret_cnt;
}
static const struct file_operations fops_fw_stats = {
- .open = ath10k_fw_stats_open,
- .release = ath10k_fw_stats_release,
- .read = ath10k_fw_stats_read,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
-static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath10k *ar = file->private_data;
- int ret, len, buf_len;
- char *buf;
-
- buf_len = 500;
- buf = kmalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- spin_lock_bh(&ar->data_lock);
-
- len = 0;
- len += scnprintf(buf + len, buf_len - len,
- "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter);
- len += scnprintf(buf + len, buf_len - len,
- "fw_warm_reset_counter\t\t%d\n",
- ar->stats.fw_warm_reset_counter);
- len += scnprintf(buf + len, buf_len - len,
- "fw_cold_reset_counter\t\t%d\n",
- ar->stats.fw_cold_reset_counter);
-
- spin_unlock_bh(&ar->data_lock);
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-
- kfree(buf);
-
- return ret;
-}
-
-static const struct file_operations fops_fw_reset_stats = {
+ .read = ath10k_read_fw_stats,
.open = simple_open,
- .read = ath10k_debug_fw_reset_stats_read,
.owner = THIS_MODULE,
.llseek = default_llseek,
};
@@ -690,8 +593,7 @@
"To simulate firmware crash write one of the keywords to this file:\n"
"`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n"
"`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n"
- "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"
- "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
+ "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n";
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
}
@@ -745,10 +647,6 @@
} else if (!strcmp(buf, "assert")) {
ath10k_info(ar, "simulating firmware assert crash\n");
ret = ath10k_debug_fw_assert(ar);
- } else if (!strcmp(buf, "hw-restart")) {
- ath10k_info(ar, "user requested hw restart\n");
- queue_work(ar->workqueue, &ar->restart_work);
- ret = 0;
} else {
ret = -EINVAL;
goto exit;
@@ -862,8 +760,8 @@
strlcpy(dump_data->fw_ver, ar->hw->wiphy->fw_version,
sizeof(dump_data->fw_ver));
- dump_data->kernel_ver_code = 0;
- strlcpy(dump_data->kernel_ver, init_utsname()->release,
+ dump_data->kernel_ver_code = cpu_to_le32(LINUX_VERSION_CODE);
+ strlcpy(dump_data->kernel_ver, VERMAGIC_STRING,
sizeof(dump_data->kernel_ver));
dump_data->tv_sec = cpu_to_le64(crash_data->timestamp.tv_sec);
@@ -925,236 +823,6 @@
.llseek = default_llseek,
};
-static ssize_t ath10k_reg_addr_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath10k *ar = file->private_data;
- u8 buf[32];
- unsigned int len = 0;
- u32 reg_addr;
-
- mutex_lock(&ar->conf_mutex);
- reg_addr = ar->debug.reg_addr;
- mutex_unlock(&ar->conf_mutex);
-
- len += scnprintf(buf + len, sizeof(buf) - len, "0x%x\n", reg_addr);
-
- return simple_read_from_buffer(user_buf, count, ppos, buf, len);
-}
-
-static ssize_t ath10k_reg_addr_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath10k *ar = file->private_data;
- u32 reg_addr;
- int ret;
-
- ret = kstrtou32_from_user(user_buf, count, 0, ®_addr);
- if (ret)
- return ret;
-
- if (!IS_ALIGNED(reg_addr, 4))
- return -EFAULT;
-
- mutex_lock(&ar->conf_mutex);
- ar->debug.reg_addr = reg_addr;
- mutex_unlock(&ar->conf_mutex);
-
- return count;
-}
-
-static const struct file_operations fops_reg_addr = {
- .read = ath10k_reg_addr_read,
- .write = ath10k_reg_addr_write,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
-static ssize_t ath10k_reg_value_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath10k *ar = file->private_data;
- u8 buf[48];
- unsigned int len;
- u32 reg_addr, reg_val;
- int ret;
-
- mutex_lock(&ar->conf_mutex);
-
- if (ar->state != ATH10K_STATE_ON &&
- ar->state != ATH10K_STATE_UTF) {
- ret = -ENETDOWN;
- goto exit;
- }
-
- reg_addr = ar->debug.reg_addr;
-
- reg_val = ath10k_hif_read32(ar, reg_addr);
- len = scnprintf(buf, sizeof(buf), "0x%08x:0x%08x\n", reg_addr, reg_val);
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
-
-exit:
- mutex_unlock(&ar->conf_mutex);
-
- return ret;
-}
-
-static ssize_t ath10k_reg_value_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath10k *ar = file->private_data;
- u32 reg_addr, reg_val;
- int ret;
-
- mutex_lock(&ar->conf_mutex);
-
- if (ar->state != ATH10K_STATE_ON &&
- ar->state != ATH10K_STATE_UTF) {
- ret = -ENETDOWN;
- goto exit;
- }
-
- reg_addr = ar->debug.reg_addr;
-
- ret = kstrtou32_from_user(user_buf, count, 0, ®_val);
- if (ret)
- goto exit;
-
- ath10k_hif_write32(ar, reg_addr, reg_val);
-
- ret = count;
-
-exit:
- mutex_unlock(&ar->conf_mutex);
-
- return ret;
-}
-
-static const struct file_operations fops_reg_value = {
- .read = ath10k_reg_value_read,
- .write = ath10k_reg_value_write,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
-static ssize_t ath10k_mem_value_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath10k *ar = file->private_data;
- u8 *buf;
- int ret;
-
- if (*ppos < 0)
- return -EINVAL;
-
- if (!count)
- return 0;
-
- mutex_lock(&ar->conf_mutex);
-
- buf = vmalloc(count);
- if (!buf) {
- ret = -ENOMEM;
- goto exit;
- }
-
- if (ar->state != ATH10K_STATE_ON &&
- ar->state != ATH10K_STATE_UTF) {
- ret = -ENETDOWN;
- goto exit;
- }
-
- ret = ath10k_hif_diag_read(ar, *ppos, buf, count);
- if (ret) {
- ath10k_warn(ar, "failed to read address 0x%08x via diagnose window fnrom debugfs: %d\n",
- (u32)(*ppos), ret);
- goto exit;
- }
-
- ret = copy_to_user(user_buf, buf, count);
- if (ret) {
- ret = -EFAULT;
- goto exit;
- }
-
- count -= ret;
- *ppos += count;
- ret = count;
-
-exit:
- vfree(buf);
- mutex_unlock(&ar->conf_mutex);
-
- return ret;
-}
-
-static ssize_t ath10k_mem_value_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath10k *ar = file->private_data;
- u8 *buf;
- int ret;
-
- if (*ppos < 0)
- return -EINVAL;
-
- if (!count)
- return 0;
-
- mutex_lock(&ar->conf_mutex);
-
- buf = vmalloc(count);
- if (!buf) {
- ret = -ENOMEM;
- goto exit;
- }
-
- if (ar->state != ATH10K_STATE_ON &&
- ar->state != ATH10K_STATE_UTF) {
- ret = -ENETDOWN;
- goto exit;
- }
-
- ret = copy_from_user(buf, user_buf, count);
- if (ret) {
- ret = -EFAULT;
- goto exit;
- }
-
- ret = ath10k_hif_diag_write(ar, *ppos, buf, count);
- if (ret) {
- ath10k_warn(ar, "failed to write address 0x%08x via diagnose window from debugfs: %d\n",
- (u32)(*ppos), ret);
- goto exit;
- }
-
- *ppos += count;
- ret = count;
-
-exit:
- vfree(buf);
- mutex_unlock(&ar->conf_mutex);
-
- return ret;
-}
-
-static const struct file_operations fops_mem_value = {
- .read = ath10k_mem_value_read,
- .write = ath10k_mem_value_write,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
static int ath10k_debug_htt_stats_req(struct ath10k *ar)
{
u64 cookie;
@@ -1362,166 +1030,6 @@
return ret;
}
-/* TODO: Would be nice to always support ethtool stats, would need to
- * move the stats storage out of ath10k_debug, or always have ath10k_debug
- * struct available..
- */
-
-/* This generally cooresponds to the debugfs fw_stats file */
-static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = {
- "tx_pkts_nic",
- "tx_bytes_nic",
- "rx_pkts_nic",
- "rx_bytes_nic",
- "d_noise_floor",
- "d_cycle_count",
- "d_phy_error",
- "d_rts_bad",
- "d_rts_good",
- "d_tx_power", /* in .5 dbM I think */
- "d_rx_crc_err", /* fcs_bad */
- "d_no_beacon",
- "d_tx_mpdus_queued",
- "d_tx_msdu_queued",
- "d_tx_msdu_dropped",
- "d_local_enqued",
- "d_local_freed",
- "d_tx_ppdu_hw_queued",
- "d_tx_ppdu_reaped",
- "d_tx_fifo_underrun",
- "d_tx_ppdu_abort",
- "d_tx_mpdu_requed",
- "d_tx_excessive_retries",
- "d_tx_hw_rate",
- "d_tx_dropped_sw_retries",
- "d_tx_illegal_rate",
- "d_tx_continuous_xretries",
- "d_tx_timeout",
- "d_tx_mpdu_txop_limit",
- "d_pdev_resets",
- "d_rx_mid_ppdu_route_change",
- "d_rx_status",
- "d_rx_extra_frags_ring0",
- "d_rx_extra_frags_ring1",
- "d_rx_extra_frags_ring2",
- "d_rx_extra_frags_ring3",
- "d_rx_msdu_htt",
- "d_rx_mpdu_htt",
- "d_rx_msdu_stack",
- "d_rx_mpdu_stack",
- "d_rx_phy_err",
- "d_rx_phy_err_drops",
- "d_rx_mpdu_errors", /* FCS, MIC, ENC */
- "d_fw_crash_count",
- "d_fw_warm_reset_count",
- "d_fw_cold_reset_count",
-};
-
-#define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats)
-
-void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- u32 sset, u8 *data)
-{
- if (sset == ETH_SS_STATS)
- memcpy(data, *ath10k_gstrings_stats,
- sizeof(ath10k_gstrings_stats));
-}
-
-int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int sset)
-{
- if (sset == ETH_SS_STATS)
- return ATH10K_SSTATS_LEN;
-
- return 0;
-}
-
-void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ethtool_stats *stats, u64 *data)
-{
- struct ath10k *ar = hw->priv;
- static const struct ath10k_fw_stats_pdev zero_stats = {};
- const struct ath10k_fw_stats_pdev *pdev_stats;
- int i = 0, ret;
-
- mutex_lock(&ar->conf_mutex);
-
- if (ar->state == ATH10K_STATE_ON) {
- ret = ath10k_debug_fw_stats_request(ar);
- if (ret) {
- /* just print a warning and try to use older results */
- ath10k_warn(ar,
- "failed to get fw stats for ethtool: %d\n",
- ret);
- }
- }
-
- pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs,
- struct ath10k_fw_stats_pdev,
- list);
- if (!pdev_stats) {
- /* no results available so just return zeroes */
- pdev_stats = &zero_stats;
- }
-
- spin_lock_bh(&ar->data_lock);
-
- data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */
- data[i++] = 0; /* tx bytes */
- data[i++] = pdev_stats->htt_mpdus;
- data[i++] = 0; /* rx bytes */
- data[i++] = pdev_stats->ch_noise_floor;
- data[i++] = pdev_stats->cycle_count;
- data[i++] = pdev_stats->phy_err_count;
- data[i++] = pdev_stats->rts_bad;
- data[i++] = pdev_stats->rts_good;
- data[i++] = pdev_stats->chan_tx_power;
- data[i++] = pdev_stats->fcs_bad;
- data[i++] = pdev_stats->no_beacons;
- data[i++] = pdev_stats->mpdu_enqued;
- data[i++] = pdev_stats->msdu_enqued;
- data[i++] = pdev_stats->wmm_drop;
- data[i++] = pdev_stats->local_enqued;
- data[i++] = pdev_stats->local_freed;
- data[i++] = pdev_stats->hw_queued;
- data[i++] = pdev_stats->hw_reaped;
- data[i++] = pdev_stats->underrun;
- data[i++] = pdev_stats->tx_abort;
- data[i++] = pdev_stats->mpdus_requed;
- data[i++] = pdev_stats->tx_ko;
- data[i++] = pdev_stats->data_rc;
- data[i++] = pdev_stats->sw_retry_failure;
- data[i++] = pdev_stats->illgl_rate_phy_err;
- data[i++] = pdev_stats->pdev_cont_xretry;
- data[i++] = pdev_stats->pdev_tx_timeout;
- data[i++] = pdev_stats->txop_ovf;
- data[i++] = pdev_stats->pdev_resets;
- data[i++] = pdev_stats->mid_ppdu_route_change;
- data[i++] = pdev_stats->status_rcvd;
- data[i++] = pdev_stats->r0_frags;
- data[i++] = pdev_stats->r1_frags;
- data[i++] = pdev_stats->r2_frags;
- data[i++] = pdev_stats->r3_frags;
- data[i++] = pdev_stats->htt_msdus;
- data[i++] = pdev_stats->htt_mpdus;
- data[i++] = pdev_stats->loc_msdus;
- data[i++] = pdev_stats->loc_mpdus;
- data[i++] = pdev_stats->phy_errs;
- data[i++] = pdev_stats->phy_err_drop;
- data[i++] = pdev_stats->mpdu_errs;
- data[i++] = ar->stats.fw_crash_counter;
- data[i++] = ar->stats.fw_warm_reset_counter;
- data[i++] = ar->stats.fw_cold_reset_counter;
-
- spin_unlock_bh(&ar->data_lock);
-
- mutex_unlock(&ar->conf_mutex);
-
- WARN_ON(i != ATH10K_SSTATS_LEN);
-}
-
static const struct file_operations fops_fw_dbglog = {
.read = ath10k_read_fw_dbglog,
.write = ath10k_write_fw_dbglog,
@@ -1530,84 +1038,6 @@
.llseek = default_llseek,
};
-static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
-{
- struct ath10k *ar = inode->i_private;
- void *buf;
- u32 hi_addr;
- __le32 addr;
- int ret;
-
- mutex_lock(&ar->conf_mutex);
-
- if (ar->state != ATH10K_STATE_ON &&
- ar->state != ATH10K_STATE_UTF) {
- ret = -ENETDOWN;
- goto err;
- }
-
- buf = vmalloc(QCA988X_CAL_DATA_LEN);
- if (!buf) {
- ret = -ENOMEM;
- goto err;
- }
-
- hi_addr = host_interest_item_address(HI_ITEM(hi_board_data));
-
- ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr));
- if (ret) {
- ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret);
- goto err_vfree;
- }
-
- ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf,
- QCA988X_CAL_DATA_LEN);
- if (ret) {
- ath10k_warn(ar, "failed to read calibration data: %d\n", ret);
- goto err_vfree;
- }
-
- file->private_data = buf;
-
- mutex_unlock(&ar->conf_mutex);
-
- return 0;
-
-err_vfree:
- vfree(buf);
-
-err:
- mutex_unlock(&ar->conf_mutex);
-
- return ret;
-}
-
-static ssize_t ath10k_debug_cal_data_read(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- void *buf = file->private_data;
-
- return simple_read_from_buffer(user_buf, count, ppos,
- buf, QCA988X_CAL_DATA_LEN);
-}
-
-static int ath10k_debug_cal_data_release(struct inode *inode,
- struct file *file)
-{
- vfree(file->private_data);
-
- return 0;
-}
-
-static const struct file_operations fops_cal_data = {
- .open = ath10k_debug_cal_data_open,
- .read = ath10k_debug_cal_data_read,
- .release = ath10k_debug_cal_data_release,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
int ath10k_debug_start(struct ath10k *ar)
{
int ret;
@@ -1628,22 +1058,7 @@
ret);
}
- if (ar->debug.pktlog_filter) {
- ret = ath10k_wmi_pdev_pktlog_enable(ar,
- ar->debug.pktlog_filter);
- if (ret)
- /* not serious */
- ath10k_warn(ar,
- "failed to enable pktlog filter %x: %d\n",
- ar->debug.pktlog_filter, ret);
- } else {
- ret = ath10k_wmi_pdev_pktlog_disable(ar);
- if (ret)
- /* not serious */
- ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
- }
-
- return ret;
+ return 0;
}
void ath10k_debug_stop(struct ath10k *ar)
@@ -1658,8 +1073,6 @@
ar->debug.htt_max_amsdu = 0;
ar->debug.htt_max_ampdu = 0;
-
- ath10k_wmi_pdev_pktlog_disable(ar);
}
static ssize_t ath10k_write_simulate_radar(struct file *file,
@@ -1742,78 +1155,12 @@
.llseek = default_llseek,
};
-static ssize_t ath10k_write_pktlog_filter(struct file *file,
- const char __user *ubuf,
- size_t count, loff_t *ppos)
-{
- struct ath10k *ar = file->private_data;
- u32 filter;
- int ret;
-
- if (kstrtouint_from_user(ubuf, count, 0, &filter))
- return -EINVAL;
-
- mutex_lock(&ar->conf_mutex);
-
- if (ar->state != ATH10K_STATE_ON) {
- ar->debug.pktlog_filter = filter;
- ret = count;
- goto out;
- }
-
- if (filter && (filter != ar->debug.pktlog_filter)) {
- ret = ath10k_wmi_pdev_pktlog_enable(ar, filter);
- if (ret) {
- ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n",
- ar->debug.pktlog_filter, ret);
- goto out;
- }
- } else {
- ret = ath10k_wmi_pdev_pktlog_disable(ar);
- if (ret) {
- ath10k_warn(ar, "failed to disable pktlog: %d\n", ret);
- goto out;
- }
- }
-
- ar->debug.pktlog_filter = filter;
- ret = count;
-
-out:
- mutex_unlock(&ar->conf_mutex);
- return ret;
-}
-
-static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf,
- size_t count, loff_t *ppos)
-{
- char buf[32];
- struct ath10k *ar = file->private_data;
- int len = 0;
-
- mutex_lock(&ar->conf_mutex);
- len = scnprintf(buf, sizeof(buf) - len, "%08x\n",
- ar->debug.pktlog_filter);
- mutex_unlock(&ar->conf_mutex);
-
- return simple_read_from_buffer(ubuf, count, ppos, buf, len);
-}
-
-static const struct file_operations fops_pktlog_filter = {
- .read = ath10k_read_pktlog_filter,
- .write = ath10k_write_pktlog_filter,
- .open = simple_open
-};
-
int ath10k_debug_create(struct ath10k *ar)
{
ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
if (!ar->debug.fw_crash_data)
return -ENOMEM;
- INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
- INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
-
return 0;
}
@@ -1821,8 +1168,6 @@
{
vfree(ar->debug.fw_crash_data);
ar->debug.fw_crash_data = NULL;
-
- ath10k_debug_fw_stats_reset(ar);
}
int ath10k_debug_register(struct ath10k *ar)
@@ -1839,14 +1184,11 @@
INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork,
ath10k_debug_htt_stats_dwork);
- init_completion(&ar->debug.fw_stats_complete);
+ init_completion(&ar->debug.event_stats_compl);
debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar,
&fops_fw_stats);
- debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy,
- ar, &fops_fw_reset_stats);
-
debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar,
&fops_wmi_services);
@@ -1856,15 +1198,6 @@
debugfs_create_file("fw_crash_dump", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_crash_dump);
- debugfs_create_file("reg_addr", S_IRUSR | S_IWUSR,
- ar->debug.debugfs_phy, ar, &fops_reg_addr);
-
- debugfs_create_file("reg_value", S_IRUSR | S_IWUSR,
- ar->debug.debugfs_phy, ar, &fops_reg_value);
-
- debugfs_create_file("mem_value", S_IRUSR | S_IWUSR,
- ar->debug.debugfs_phy, ar, &fops_mem_value);
-
debugfs_create_file("chip_id", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_chip_id);
@@ -1878,9 +1211,6 @@
debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy,
ar, &fops_fw_dbglog);
- debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy,
- ar, &fops_cal_data);
-
if (config_enabled(CPTCFG_ATH10K_DFS_CERTIFIED)) {
debugfs_create_file("dfs_simulate_radar", S_IWUSR,
ar->debug.debugfs_phy, ar,
@@ -1895,9 +1225,6 @@
&fops_dfs_stats);
}
- debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR,
- ar->debug.debugfs_phy, ar, &fops_pktlog_filter);
-
return 0;
}
@@ -1934,26 +1261,11 @@
const char *msg, const char *prefix,
const void *buf, size_t len)
{
- char linebuf[256];
- unsigned int linebuflen;
- const void *ptr;
-
if (ath10k_debug_mask & mask) {
if (msg)
ath10k_dbg(ar, mask, "%s\n", msg);
- for (ptr = buf; (ptr - buf) < len; ptr += 16) {
- linebuflen = 0;
- linebuflen += scnprintf(linebuf + linebuflen,
- sizeof(linebuf) - linebuflen,
- "%s%08x: ",
- (prefix ? prefix : ""),
- (unsigned int)(ptr - buf));
- hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1,
- linebuf + linebuflen,
- sizeof(linebuf) - linebuflen, true);
- dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf);
- }
+ print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len);
}
/* tracing code doesn't like null strings :/ */
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h
index d9408e6..06923b4 100644
--- a/drivers/net/wireless/ath/ath10k/debug.h
+++ b/drivers/net/wireless/ath/ath10k/debug.h
@@ -35,27 +35,17 @@
ATH10K_DBG_BMI = 0x00000400,
ATH10K_DBG_REGULATORY = 0x00000800,
ATH10K_DBG_TESTMODE = 0x00001000,
- ATH10K_DBG_WMI_PRINT = 0x00002000,
ATH10K_DBG_ANY = 0xffffffff,
// Use high bit so conflicts are less likely with upstream updates.
ATH10K_DBG_BEACON = 0x10000000,
};
-enum ath10k_pktlog_filter {
- ATH10K_PKTLOG_RX = 0x000000001,
- ATH10K_PKTLOG_TX = 0x000000002,
- ATH10K_PKTLOG_RCFIND = 0x000000004,
- ATH10K_PKTLOG_RCUPDATE = 0x000000008,
- ATH10K_PKTLOG_DBG_PRINT = 0x000000010,
- ATH10K_PKTLOG_ANY = 0x00000001f,
-};
-
extern unsigned int ath10k_debug_mask;
-__printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...);
-__printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...);
-__printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...);
+__printf(2, 3) int ath10k_info(struct ath10k *ar, const char *fmt, ...);
+__printf(2, 3) int ath10k_err(struct ath10k *ar, const char *fmt, ...);
+__printf(2, 3) int ath10k_warn(struct ath10k *ar, const char *fmt, ...);
void ath10k_print_driver_info(struct ath10k *ar);
#ifdef CPTCFG_ATH10K_DEBUGFS
@@ -65,21 +55,17 @@
void ath10k_debug_destroy(struct ath10k *ar);
int ath10k_debug_register(struct ath10k *ar);
void ath10k_debug_unregister(struct ath10k *ar);
-void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb);
+void ath10k_debug_read_service_map(struct ath10k *ar,
+ void *service_map,
+ size_t map_size);
+void ath10k_debug_read_target_stats(struct ath10k *ar,
+ struct wmi_stats_event *ev);
struct ath10k_fw_crash_data *
ath10k_debug_get_new_fw_crash_data(struct ath10k *ar);
void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len);
-#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
-void ath10k_debug_get_et_strings(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- u32 sset, u8 *data);
-int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int sset);
-void ath10k_debug_get_et_stats(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ethtool_stats *stats, u64 *data);
+#define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++)
#else
static inline int ath10k_debug_start(struct ath10k *ar)
@@ -109,8 +95,14 @@
{
}
-static inline void ath10k_debug_fw_stats_process(struct ath10k *ar,
- struct sk_buff *skb)
+static inline void ath10k_debug_read_service_map(struct ath10k *ar,
+ void *service_map,
+ size_t map_size)
+{
+}
+
+static inline void ath10k_debug_read_target_stats(struct ath10k *ar,
+ struct wmi_stats_event *ev)
{
}
@@ -127,10 +119,6 @@
#define ATH10K_DFS_STAT_INC(ar, c) do { } while (0)
-#define ath10k_debug_get_et_strings NULL
-#define ath10k_debug_get_et_sset_count NULL
-#define ath10k_debug_get_et_stats NULL
-
#endif /* CPTCFG_ATH10K_DEBUGFS */
#ifdef CPTCFG_ATH10K_DEBUG
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h
index 0c92e02..62323fe 100644
--- a/drivers/net/wireless/ath/ath10k/hif.h
+++ b/drivers/net/wireless/ath/ath10k/hif.h
@@ -20,7 +20,6 @@
#include <linux/kernel.h>
#include "core.h"
-#include "debug.h"
struct ath10k_hif_sg_item {
u16 transfer_id;
@@ -32,9 +31,11 @@
struct ath10k_hif_cb {
int (*tx_completion)(struct ath10k *ar,
- struct sk_buff *wbuf);
+ struct sk_buff *wbuf,
+ unsigned transfer_id);
int (*rx_completion)(struct ath10k *ar,
- struct sk_buff *wbuf);
+ struct sk_buff *wbuf,
+ u8 pipe_id);
};
struct ath10k_hif_ops {
@@ -42,12 +43,6 @@
int (*tx_sg)(struct ath10k *ar, u8 pipe_id,
struct ath10k_hif_sg_item *items, int n_items);
- /* read firmware memory through the diagnose interface */
- int (*diag_read)(struct ath10k *ar, u32 address, void *buf,
- size_t buf_len);
-
- int (*diag_write)(struct ath10k *ar, u32 address, const void *data,
- int nbytes);
/*
* API to handle HIF-specific BMI message exchanges, this API is
* synchronous and only allowed to be called from a context that
@@ -85,10 +80,6 @@
u16 (*get_free_queue_number)(struct ath10k *ar, u8 pipe_id);
- u32 (*read32)(struct ath10k *ar, u32 address);
-
- void (*write32)(struct ath10k *ar, u32 address, u32 value);
-
/* Power up the device and enter BMI transfer mode for FW download */
int (*power_up)(struct ath10k *ar);
@@ -107,21 +98,6 @@
return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items);
}
-static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
- size_t buf_len)
-{
- return ar->hif.ops->diag_read(ar, address, buf, buf_len);
-}
-
-static inline int ath10k_hif_diag_write(struct ath10k *ar, u32 address,
- const void *data, int nbytes)
-{
- if (!ar->hif.ops->diag_write)
- return -EOPNOTSUPP;
-
- return ar->hif.ops->diag_write(ar, address, data, nbytes);
-}
-
static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar,
void *request, u32 request_len,
void *response, u32 *response_len)
@@ -201,25 +177,4 @@
return ar->hif.ops->resume(ar);
}
-static inline u32 ath10k_hif_read32(struct ath10k *ar, u32 address)
-{
- if (!ar->hif.ops->read32) {
- ath10k_warn(ar, "hif read32 not supported\n");
- return 0xdeaddead;
- }
-
- return ar->hif.ops->read32(ar, address);
-}
-
-static inline void ath10k_hif_write32(struct ath10k *ar,
- u32 address, u32 data)
-{
- if (!ar->hif.ops->write32) {
- ath10k_warn(ar, "hif write32 not supported\n");
- return;
- }
-
- ar->hif.ops->write32(ar, address, data);
-}
-
#endif /* _HIF_H_ */
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 580917b..769d594 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -165,7 +165,6 @@
ath10k_htc_prepare_tx_skb(ep, skb);
- skb_cb->eid = eid;
skb_cb->paddr = dma_map_single(dev, skb->data, skb->len, DMA_TO_DEVICE);
ret = dma_mapping_error(dev, skb_cb->paddr);
if (ret)
@@ -203,18 +202,15 @@
}
static int ath10k_htc_tx_completion_handler(struct ath10k *ar,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ unsigned int eid)
{
struct ath10k_htc *htc = &ar->htc;
- struct ath10k_skb_cb *skb_cb;
- struct ath10k_htc_ep *ep;
+ struct ath10k_htc_ep *ep = &htc->endpoint[eid];
if (WARN_ON_ONCE(!skb))
return 0;
- skb_cb = ATH10K_SKB_CB(skb);
- ep = &htc->endpoint[skb_cb->eid];
-
ath10k_htc_notify_tx_completion(ep, skb);
/* the skb now belongs to the completion handler */
@@ -326,7 +322,8 @@
}
static int ath10k_htc_rx_completion_handler(struct ath10k *ar,
- struct sk_buff *skb)
+ struct sk_buff *skb,
+ u8 pipe_id)
{
int status = 0;
struct ath10k_htc *htc = &ar->htc;
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 1bd0dbf..063fdeb 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -126,7 +126,6 @@
* (HL hosts manage queues on the host )
* more_in_batch: only for HL hosts. indicates if more packets are
* pending. this allows target to wait and aggregate
- * freq: 0 means home channel of given vdev. intended for offchannel
*/
struct htt_data_tx_desc {
u8 flags0; /* %HTT_DATA_TX_DESC_FLAGS0_ */
@@ -134,8 +133,7 @@
__le16 len;
__le16 id;
__le32 frags_paddr;
- __le16 peerid;
- __le16 freq;
+ __le32 peerid;
u8 prefetch[0]; /* start of frame, for FW classification engine */
} __packed;
@@ -158,9 +156,6 @@
HTT_RX_RING_FLAGS_PHY_DATA_RX = 1 << 15
};
-#define HTT_RX_RING_SIZE_MIN 128
-#define HTT_RX_RING_SIZE_MAX 2048
-
struct htt_rx_ring_setup_ring {
__le32 fw_idx_shadow_reg_paddr;
__le32 rx_ring_base_paddr;
@@ -730,7 +725,7 @@
*/
struct htt_pktlog_msg {
u8 pad[3];
- u8 payload[0];
+ __le32 payload[1 /* or more */];
} __packed;
struct htt_dbg_stats_rx_reorder_stats {
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index b999d3f..18fa269 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -25,8 +25,19 @@
#include <linux/log2.h>
-#define HTT_RX_RING_SIZE 1024
-#define HTT_RX_RING_FILL_LEVEL 1000
+/* slightly larger than one large A-MPDU */
+#define HTT_RX_RING_SIZE_MIN 128
+
+/* roughly 20 ms @ 1 Gbps of 1500B MSDUs */
+#define HTT_RX_RING_SIZE_MAX 2048
+
+#define HTT_RX_AVG_FRM_BYTES 1000
+
+/* ms, very conservative */
+#define HTT_RX_HOST_LATENCY_MAX_MS 20
+
+/* ms, conservative */
+#define HTT_RX_HOST_LATENCY_WORST_LIKELY_MS 10
/* when under memory pressure rx ring refill may fail and needs a retry */
#define HTT_RX_RING_REFILL_RETRY_MS 50
@@ -34,6 +45,68 @@
static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb);
static void ath10k_htt_txrx_compl_task(unsigned long ptr);
+static int ath10k_htt_rx_ring_size(struct ath10k_htt *htt)
+{
+ int size;
+
+ /*
+ * It is expected that the host CPU will typically be able to
+ * service the rx indication from one A-MPDU before the rx
+ * indication from the subsequent A-MPDU happens, roughly 1-2 ms
+ * later. However, the rx ring should be sized very conservatively,
+ * to accomodate the worst reasonable delay before the host CPU
+ * services a rx indication interrupt.
+ *
+ * The rx ring need not be kept full of empty buffers. In theory,
+ * the htt host SW can dynamically track the low-water mark in the
+ * rx ring, and dynamically adjust the level to which the rx ring
+ * is filled with empty buffers, to dynamically meet the desired
+ * low-water mark.
+ *
+ * In contrast, it's difficult to resize the rx ring itself, once
+ * it's in use. Thus, the ring itself should be sized very
+ * conservatively, while the degree to which the ring is filled
+ * with empty buffers should be sized moderately conservatively.
+ */
+
+ /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */
+ size =
+ htt->max_throughput_mbps *
+ 1000 /
+ (8 * HTT_RX_AVG_FRM_BYTES) * HTT_RX_HOST_LATENCY_MAX_MS;
+
+ if (size < HTT_RX_RING_SIZE_MIN)
+ size = HTT_RX_RING_SIZE_MIN;
+
+ if (size > HTT_RX_RING_SIZE_MAX)
+ size = HTT_RX_RING_SIZE_MAX;
+
+ size = roundup_pow_of_two(size);
+
+ return size;
+}
+
+static int ath10k_htt_rx_ring_fill_level(struct ath10k_htt *htt)
+{
+ int size;
+
+ /* 1e6 bps/mbps / 1e3 ms per sec = 1000 */
+ size =
+ htt->max_throughput_mbps *
+ 1000 /
+ (8 * HTT_RX_AVG_FRM_BYTES) * HTT_RX_HOST_LATENCY_WORST_LIKELY_MS;
+
+ /*
+ * Make sure the fill level is at least 1 less than the ring size.
+ * Leaving 1 element empty allows the SW to easily distinguish
+ * between a full ring vs. an empty ring.
+ */
+ if (size >= htt->rx_ring.size)
+ size = htt->rx_ring.size - 1;
+
+ return size;
+}
+
static void ath10k_htt_rx_ring_free(struct ath10k_htt *htt)
{
struct sk_buff *skb;
@@ -223,38 +296,50 @@
htt->rx_ring.sw_rd_idx.msdu_payld = idx;
htt->rx_ring.fill_cnt--;
- dma_unmap_single(htt->ar->dev,
- ATH10K_SKB_CB(msdu)->paddr,
- msdu->len + skb_tailroom(msdu),
- DMA_FROM_DEVICE);
- ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ",
- msdu->data, msdu->len + skb_tailroom(msdu));
-
return msdu;
}
+static void ath10k_htt_rx_free_msdu_chain(struct sk_buff *skb)
+{
+ struct sk_buff *next;
+
+ while (skb) {
+ next = skb->next;
+ dev_kfree_skb_any(skb);
+ skb = next;
+ }
+}
+
/* return: < 0 fatal error, 0 - non chained msdu, 1 chained msdu */
static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
u8 **fw_desc, int *fw_desc_len,
- struct sk_buff_head *amsdu)
+ struct sk_buff **head_msdu,
+ struct sk_buff **tail_msdu,
+ u32 *attention)
{
struct ath10k *ar = htt->ar;
int msdu_len, msdu_chaining = 0;
- struct sk_buff *msdu;
+ struct sk_buff *msdu, *next;
struct htt_rx_desc *rx_desc;
lockdep_assert_held(&htt->rx_ring.lock);
- for (;;) {
+ if (htt->rx_confused) {
+ ath10k_warn(ar, "htt is confused. refusing rx\n");
+ return -1;
+ }
+
+ msdu = *head_msdu = ath10k_htt_rx_netbuf_pop(htt);
+ while (msdu) {
int last_msdu, msdu_len_invalid, msdu_chained;
- msdu = ath10k_htt_rx_netbuf_pop(htt);
- if (!msdu) {
- __skb_queue_purge(amsdu);
- return -ENOENT;
- }
+ dma_unmap_single(htt->ar->dev,
+ ATH10K_SKB_CB(msdu)->paddr,
+ msdu->len + skb_tailroom(msdu),
+ DMA_FROM_DEVICE);
- __skb_queue_tail(amsdu, msdu);
+ ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ",
+ msdu->data, msdu->len + skb_tailroom(msdu));
rx_desc = (struct htt_rx_desc *)msdu->data;
@@ -273,10 +358,19 @@
*/
if (!(__le32_to_cpu(rx_desc->attention.flags)
& RX_ATTENTION_FLAGS_MSDU_DONE)) {
- __skb_queue_purge(amsdu);
- return -EIO;
+ ath10k_htt_rx_free_msdu_chain(*head_msdu);
+ *head_msdu = NULL;
+ msdu = NULL;
+ ath10k_err(ar, "htt rx stopped. cannot recover\n");
+ htt->rx_confused = true;
+ break;
}
+ *attention |= __le32_to_cpu(rx_desc->attention.flags) &
+ (RX_ATTENTION_FLAGS_TKIP_MIC_ERR |
+ RX_ATTENTION_FLAGS_DECRYPT_ERR |
+ RX_ATTENTION_FLAGS_FCS_ERR |
+ RX_ATTENTION_FLAGS_MGMT_TYPE);
/*
* Copy the FW rx descriptor for this MSDU from the rx
* indication message into the MSDU's netbuf. HL uses the
@@ -333,32 +427,43 @@
skb_put(msdu, min(msdu_len, HTT_RX_MSDU_SIZE));
msdu_len -= msdu->len;
- /* Note: Chained buffers do not contain rx descriptor */
+ /* FIXME: Do chained buffers include htt_rx_desc or not? */
while (msdu_chained--) {
- msdu = ath10k_htt_rx_netbuf_pop(htt);
- if (!msdu) {
- __skb_queue_purge(amsdu);
- return -ENOENT;
- }
+ struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt);
- __skb_queue_tail(amsdu, msdu);
- skb_trim(msdu, 0);
- skb_put(msdu, min(msdu_len, HTT_RX_BUF_SIZE));
- msdu_len -= msdu->len;
+ dma_unmap_single(htt->ar->dev,
+ ATH10K_SKB_CB(next)->paddr,
+ next->len + skb_tailroom(next),
+ DMA_FROM_DEVICE);
+
+ ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL,
+ "htt rx chained: ", next->data,
+ next->len + skb_tailroom(next));
+
+ skb_trim(next, 0);
+ skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE));
+ msdu_len -= next->len;
+
+ msdu->next = next;
+ msdu = next;
msdu_chaining = 1;
}
last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
RX_MSDU_END_INFO0_LAST_MSDU;
- trace_ath10k_htt_rx_desc(ar, &rx_desc->attention,
- sizeof(*rx_desc) - sizeof(u32));
-
- if (last_msdu)
+ if (last_msdu) {
+ msdu->next = NULL;
break;
- }
+ }
- if (skb_queue_empty(amsdu))
+ next = ath10k_htt_rx_netbuf_pop(htt);
+ msdu->next = next;
+ msdu = next;
+ }
+ *tail_msdu = msdu;
+
+ if (*head_msdu == NULL)
msdu_chaining = -1;
/*
@@ -392,20 +497,25 @@
size_t size;
struct timer_list *timer = &htt->rx_ring.refill_retry_timer;
- htt->rx_confused = false;
-
- /* XXX: The fill level could be changed during runtime in response to
- * the host processing latency. Is this really worth it?
- */
- htt->rx_ring.size = HTT_RX_RING_SIZE;
- htt->rx_ring.size_mask = htt->rx_ring.size - 1;
- htt->rx_ring.fill_level = HTT_RX_RING_FILL_LEVEL;
-
+ htt->rx_ring.size = ath10k_htt_rx_ring_size(htt);
if (!is_power_of_2(htt->rx_ring.size)) {
ath10k_warn(ar, "htt rx ring size is not power of 2\n");
return -EINVAL;
}
+ htt->rx_ring.size_mask = htt->rx_ring.size - 1;
+
+ /*
+ * Set the initial value for the level to which the rx ring
+ * should be filled, based on the max throughput and the
+ * worst likely latency for the host to fill the rx ring
+ * with new buffers. In theory, this fill level can be
+ * dynamically adjusted from the initial value set here, to
+ * reflect the actual host latency rather than a
+ * conservative assumption about the host latency.
+ */
+ htt->rx_ring.fill_level = ath10k_htt_rx_ring_fill_level(htt);
+
htt->rx_ring.netbufs_ring =
kzalloc(htt->rx_ring.size * sizeof(struct sk_buff *),
GFP_KERNEL|__GFP_REPEAT|__GFP_HIGH);
@@ -477,50 +587,73 @@
enum htt_rx_mpdu_encrypt_type type)
{
switch (type) {
- case HTT_RX_MPDU_ENCRYPT_NONE:
- return 0;
case HTT_RX_MPDU_ENCRYPT_WEP40:
case HTT_RX_MPDU_ENCRYPT_WEP104:
- return IEEE80211_WEP_IV_LEN;
+ return 4;
case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
+ case HTT_RX_MPDU_ENCRYPT_WEP128: /* not tested */
case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
- return IEEE80211_TKIP_IV_LEN;
+ case HTT_RX_MPDU_ENCRYPT_WAPI: /* not tested */
case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
- return IEEE80211_CCMP_HDR_LEN;
- case HTT_RX_MPDU_ENCRYPT_WEP128:
- case HTT_RX_MPDU_ENCRYPT_WAPI:
- break;
+ return 8;
+ case HTT_RX_MPDU_ENCRYPT_NONE:
+ return 0;
}
- ath10k_warn(ar, "unsupported encryption type %d\n", type);
+ ath10k_warn(ar, "unknown encryption type %d\n", type);
return 0;
}
-#define MICHAEL_MIC_LEN 8
-
static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar,
enum htt_rx_mpdu_encrypt_type type)
{
switch (type) {
case HTT_RX_MPDU_ENCRYPT_NONE:
- return 0;
case HTT_RX_MPDU_ENCRYPT_WEP40:
case HTT_RX_MPDU_ENCRYPT_WEP104:
- return IEEE80211_WEP_ICV_LEN;
- case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
- case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
- return IEEE80211_TKIP_ICV_LEN;
- case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
- return IEEE80211_CCMP_MIC_LEN;
case HTT_RX_MPDU_ENCRYPT_WEP128:
case HTT_RX_MPDU_ENCRYPT_WAPI:
- break;
+ return 0;
+ case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC:
+ case HTT_RX_MPDU_ENCRYPT_TKIP_WPA:
+ return 4;
+ case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
+ return 8;
}
- ath10k_warn(ar, "unsupported encryption type %d\n", type);
+ ath10k_warn(ar, "unknown encryption type %d\n", type);
return 0;
}
+/* Applies for first msdu in chain, before altering it. */
+static struct ieee80211_hdr *ath10k_htt_rx_skb_get_hdr(struct sk_buff *skb)
+{
+ struct htt_rx_desc *rxd;
+ enum rx_msdu_decap_format fmt;
+
+ rxd = (void *)skb->data - sizeof(*rxd);
+ fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
+ RX_MSDU_START_INFO1_DECAP_FORMAT);
+
+ if (fmt == RX_MSDU_DECAP_RAW)
+ return (void *)skb->data;
+
+ return (void *)skb->data - RX_HTT_HDR_STATUS_LEN;
+}
+
+/* This function only applies for first msdu in an msdu chain */
+static bool ath10k_htt_rx_hdr_is_amsdu(struct ieee80211_hdr *hdr)
+{
+ u8 *qc;
+
+ if (ieee80211_is_data_qos(hdr->frame_control)) {
+ qc = ieee80211_get_qos_ctl(hdr);
+ if (qc[0] & 0x80)
+ return true;
+ }
+ return false;
+}
+
struct rfc1042_hdr {
u8 llc_dsap;
u8 llc_ssap;
@@ -555,34 +688,23 @@
};
static void ath10k_htt_rx_h_rates(struct ath10k *ar,
- struct ieee80211_rx_status *status,
- struct htt_rx_desc *rxd)
+ enum ieee80211_band band,
+ u8 info0, u32 info1, u32 info2,
+ struct ieee80211_rx_status *status)
{
- enum ieee80211_band band;
u8 cck, rate, rate_idx, bw, sgi, mcs, nss;
u8 preamble = 0;
- u32 info1, info2, info3;
- /* Band value can't be set as undefined but freq can be 0 - use that to
- * determine whether band is provided.
- *
- * FIXME: Perhaps this can go away if CCK rate reporting is a little
- * reworked?
- */
- if (!status->freq)
+ /* Check if valid fields */
+ if (!(info0 & HTT_RX_INDICATION_INFO0_START_VALID))
return;
- band = status->band;
- info1 = __le32_to_cpu(rxd->ppdu_start.info1);
- info2 = __le32_to_cpu(rxd->ppdu_start.info2);
- info3 = __le32_to_cpu(rxd->ppdu_start.info3);
-
- preamble = MS(info1, RX_PPDU_START_INFO1_PREAMBLE_TYPE);
+ preamble = MS(info1, HTT_RX_INDICATION_INFO1_PREAMBLE_TYPE);
switch (preamble) {
case HTT_RX_LEGACY:
- cck = info1 & RX_PPDU_START_INFO1_L_SIG_RATE_SELECT;
- rate = MS(info1, RX_PPDU_START_INFO1_L_SIG_RATE);
+ cck = info0 & HTT_RX_INDICATION_INFO0_LEGACY_RATE_CCK;
+ rate = MS(info0, HTT_RX_INDICATION_INFO0_LEGACY_RATE);
rate_idx = 0;
if (rate < 0x08 || rate > 0x0F)
@@ -609,11 +731,11 @@
break;
case HTT_RX_HT:
case HTT_RX_HT_WITH_TXBF:
- /* HT-SIG - Table 20-11 in info2 and info3 */
- mcs = info2 & 0x1F;
+ /* HT-SIG - Table 20-11 in info1 and info2 */
+ mcs = info1 & 0x1F;
nss = mcs >> 3;
- bw = (info2 >> 7) & 1;
- sgi = (info3 >> 7) & 1;
+ bw = (info1 >> 7) & 1;
+ sgi = (info2 >> 7) & 1;
status->rate_idx = mcs;
status->flag |= RX_FLAG_HT;
@@ -624,12 +746,12 @@
break;
case HTT_RX_VHT:
case HTT_RX_VHT_WITH_TXBF:
- /* VHT-SIG-A1 in info2, VHT-SIG-A2 in info3
+ /* VHT-SIG-A1 in info 1, VHT-SIG-A2 in info2
TODO check this */
- mcs = (info3 >> 4) & 0x0F;
- nss = ((info2 >> 10) & 0x07) + 1;
- bw = info2 & 3;
- sgi = info3 & 1;
+ mcs = (info2 >> 4) & 0x0F;
+ nss = ((info1 >> 10) & 0x07) + 1;
+ bw = info1 & 3;
+ sgi = info2 & 1;
status->rate_idx = mcs;
status->vht_nss = nss;
@@ -657,6 +779,41 @@
}
}
+static void ath10k_htt_rx_h_protected(struct ath10k_htt *htt,
+ struct ieee80211_rx_status *rx_status,
+ struct sk_buff *skb,
+ enum htt_rx_mpdu_encrypt_type enctype,
+ enum rx_msdu_decap_format fmt,
+ bool dot11frag)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+
+ rx_status->flag &= ~(RX_FLAG_DECRYPTED |
+ RX_FLAG_IV_STRIPPED |
+ RX_FLAG_MMIC_STRIPPED);
+
+ if (enctype == HTT_RX_MPDU_ENCRYPT_NONE)
+ return;
+
+ /*
+ * There's no explicit rx descriptor flag to indicate whether a given
+ * frame has been decrypted or not. We're forced to use the decap
+ * format as an implicit indication. However fragmentation rx is always
+ * raw and it probably never reports undecrypted raws.
+ *
+ * This makes sure sniffed frames are reported as-is without stripping
+ * the protected flag.
+ */
+ if (fmt == RX_MSDU_DECAP_RAW && !dot11frag)
+ return;
+
+ rx_status->flag |= RX_FLAG_DECRYPTED |
+ RX_FLAG_IV_STRIPPED |
+ RX_FLAG_MMIC_STRIPPED;
+ hdr->frame_control = __cpu_to_le16(__le16_to_cpu(hdr->frame_control) &
+ ~IEEE80211_FCTL_PROTECTED);
+}
+
static bool ath10k_htt_rx_h_channel(struct ath10k *ar,
struct ieee80211_rx_status *status)
{
@@ -677,72 +834,6 @@
return true;
}
-static void ath10k_htt_rx_h_signal(struct ath10k *ar,
- struct ieee80211_rx_status *status,
- struct htt_rx_desc *rxd)
-{
- /* FIXME: Get real NF */
- status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
- rxd->ppdu_start.rssi_comb;
- status->flag &= ~RX_FLAG_NO_SIGNAL_VAL;
-}
-
-static void ath10k_htt_rx_h_mactime(struct ath10k *ar,
- struct ieee80211_rx_status *status,
- struct htt_rx_desc *rxd)
-{
- /* FIXME: TSF is known only at the end of PPDU, in the last MPDU. This
- * means all prior MSDUs in a PPDU are reported to mac80211 without the
- * TSF. Is it worth holding frames until end of PPDU is known?
- *
- * FIXME: Can we get/compute 64bit TSF?
- */
- status->mactime = __le32_to_cpu(rxd->ppdu_end.tsf_timestamp);
- status->flag |= RX_FLAG_MACTIME_END;
-}
-
-static void ath10k_htt_rx_h_ppdu(struct ath10k *ar,
- struct sk_buff_head *amsdu,
- struct ieee80211_rx_status *status)
-{
- struct sk_buff *first;
- struct htt_rx_desc *rxd;
- bool is_first_ppdu;
- bool is_last_ppdu;
-
- if (skb_queue_empty(amsdu))
- return;
-
- first = skb_peek(amsdu);
- rxd = (void *)first->data - sizeof(*rxd);
-
- is_first_ppdu = !!(rxd->attention.flags &
- __cpu_to_le32(RX_ATTENTION_FLAGS_FIRST_MPDU));
- is_last_ppdu = !!(rxd->attention.flags &
- __cpu_to_le32(RX_ATTENTION_FLAGS_LAST_MPDU));
-
- if (is_first_ppdu) {
- /* New PPDU starts so clear out the old per-PPDU status. */
- status->freq = 0;
- status->rate_idx = 0;
- status->vht_nss = 0;
- status->vht_flag &= ~RX_VHT_FLAG_80MHZ;
- status->flag &= ~(RX_FLAG_HT |
- RX_FLAG_VHT |
- RX_FLAG_SHORT_GI |
- RX_FLAG_40MHZ |
- RX_FLAG_MACTIME_END);
- status->flag |= RX_FLAG_NO_SIGNAL_VAL;
-
- ath10k_htt_rx_h_signal(ar, status, rxd);
- ath10k_htt_rx_h_channel(ar, status);
- ath10k_htt_rx_h_rates(ar, status, rxd);
- }
-
- if (is_last_ppdu)
- ath10k_htt_rx_h_mactime(ar, status, rxd);
-}
-
static const char * const tid_to_ac[] = {
"BE",
"BK",
@@ -807,8 +898,6 @@
!!(status->flag & RX_FLAG_AMSDU_MORE));
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ",
skb->data, skb->len);
- trace_ath10k_rx_hdr(ar, skb->data, skb->len);
- trace_ath10k_rx_payload(ar, skb->data, skb->len);
ieee80211_rx(ar->hw, skb);
}
@@ -819,263 +908,187 @@
return round_up(ieee80211_hdrlen(hdr->frame_control), 4);
}
-static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
- struct sk_buff *msdu,
- struct ieee80211_rx_status *status,
- enum htt_rx_mpdu_encrypt_type enctype,
- bool is_decrypted)
+static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
+ struct ieee80211_rx_status *rx_status,
+ struct sk_buff *skb_in)
{
- struct ieee80211_hdr *hdr;
+ struct ath10k *ar = htt->ar;
struct htt_rx_desc *rxd;
- size_t hdr_len;
- size_t crypto_len;
- bool is_first;
- bool is_last;
-
- rxd = (void *)msdu->data - sizeof(*rxd);
- is_first = !!(rxd->msdu_end.info0 &
- __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
- is_last = !!(rxd->msdu_end.info0 &
- __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
-
- /* Delivered decapped frame:
- * [802.11 header]
- * [crypto param] <-- can be trimmed if !fcs_err &&
- * !decrypt_err && !peer_idx_invalid
- * [amsdu header] <-- only if A-MSDU
- * [rfc1042/llc]
- * [payload]
- * [FCS] <-- at end, needs to be trimmed
- */
-
- /* This probably shouldn't happen but warn just in case */
- if (unlikely(WARN_ON_ONCE(!is_first)))
- return;
-
- /* This probably shouldn't happen but warn just in case */
- if (unlikely(WARN_ON_ONCE(!(is_first && is_last))))
- return;
-
- skb_trim(msdu, msdu->len - FCS_LEN);
-
- /* In most cases this will be true for sniffed frames. It makes sense
- * to deliver them as-is without stripping the crypto param. This would
- * also make sense for software based decryption (which is not
- * implemented in ath10k).
- *
- * If there's no error then the frame is decrypted. At least that is
- * the case for frames that come in via fragmented rx indication.
- */
- if (!is_decrypted)
- return;
-
- /* The payload is decrypted so strip crypto params. Start from tail
- * since hdr is used to compute some stuff.
- */
-
- hdr = (void *)msdu->data;
-
- /* Tail */
- skb_trim(msdu, msdu->len - ath10k_htt_rx_crypto_tail_len(ar, enctype));
-
- /* MMIC */
- if (!ieee80211_has_morefrags(hdr->frame_control) &&
- enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
- skb_trim(msdu, msdu->len - 8);
-
- /* Head */
- hdr_len = ieee80211_hdrlen(hdr->frame_control);
- crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
-
- memmove((void *)msdu->data + crypto_len,
- (void *)msdu->data, hdr_len);
- skb_pull(msdu, crypto_len);
-}
-
-static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
- struct sk_buff *msdu,
- struct ieee80211_rx_status *status,
- const u8 first_hdr[64])
-{
+ struct sk_buff *skb = skb_in;
+ struct sk_buff *first;
+ enum rx_msdu_decap_format fmt;
+ enum htt_rx_mpdu_encrypt_type enctype;
struct ieee80211_hdr *hdr;
- size_t hdr_len;
- u8 da[ETH_ALEN];
- u8 sa[ETH_ALEN];
+ u8 hdr_buf[64], da[ETH_ALEN], sa[ETH_ALEN], *qos;
+ unsigned int hdr_len;
- /* Delivered decapped frame:
- * [nwifi 802.11 header] <-- replaced with 802.11 hdr
- * [rfc1042/llc]
- *
- * Note: The nwifi header doesn't have QoS Control and is
- * (always?) a 3addr frame.
- *
- * Note2: There's no A-MSDU subframe header. Even if it's part
- * of an A-MSDU.
- */
+ rxd = (void *)skb->data - sizeof(*rxd);
+ enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
+ RX_MPDU_START_INFO0_ENCRYPT_TYPE);
- /* pull decapped header and copy SA & DA */
- hdr = (struct ieee80211_hdr *)msdu->data;
- hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
- ether_addr_copy(da, ieee80211_get_DA(hdr));
- ether_addr_copy(sa, ieee80211_get_SA(hdr));
- skb_pull(msdu, hdr_len);
-
- /* push original 802.11 header */
- hdr = (struct ieee80211_hdr *)first_hdr;
+ hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
hdr_len = ieee80211_hdrlen(hdr->frame_control);
- memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
+ memcpy(hdr_buf, hdr, hdr_len);
+ hdr = (struct ieee80211_hdr *)hdr_buf;
- /* original 802.11 header has a different DA and in
- * case of 4addr it may also have different SA
- */
- hdr = (struct ieee80211_hdr *)msdu->data;
- ether_addr_copy(ieee80211_get_DA(hdr), da);
- ether_addr_copy(ieee80211_get_SA(hdr), sa);
-}
+ first = skb;
+ while (skb) {
+ void *decap_hdr;
+ int len;
-static void *ath10k_htt_rx_h_find_rfc1042(struct ath10k *ar,
- struct sk_buff *msdu,
- enum htt_rx_mpdu_encrypt_type enctype)
-{
- struct ieee80211_hdr *hdr;
- struct htt_rx_desc *rxd;
- size_t hdr_len, crypto_len;
- void *rfc1042;
- bool is_first, is_last, is_amsdu;
+ rxd = (void *)skb->data - sizeof(*rxd);
+ fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
+ RX_MSDU_START_INFO1_DECAP_FORMAT);
+ decap_hdr = (void *)rxd->rx_hdr_status;
- rxd = (void *)msdu->data - sizeof(*rxd);
- hdr = (void *)rxd->rx_hdr_status;
+ skb->ip_summed = ath10k_htt_rx_get_csum_state(skb);
- is_first = !!(rxd->msdu_end.info0 &
- __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU));
- is_last = !!(rxd->msdu_end.info0 &
- __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU));
- is_amsdu = !(is_first && is_last);
+ /* First frame in an A-MSDU chain has more decapped data. */
+ if (skb == first) {
+ len = round_up(ieee80211_hdrlen(hdr->frame_control), 4);
+ len += round_up(ath10k_htt_rx_crypto_param_len(ar,
+ enctype), 4);
+ decap_hdr += len;
+ }
- rfc1042 = hdr;
+ switch (fmt) {
+ case RX_MSDU_DECAP_RAW:
+ /* remove trailing FCS */
+ skb_trim(skb, skb->len - FCS_LEN);
+ break;
+ case RX_MSDU_DECAP_NATIVE_WIFI:
+ /* pull decapped header and copy SA & DA */
+ hdr = (struct ieee80211_hdr *)skb->data;
+ hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
+ ether_addr_copy(da, ieee80211_get_DA(hdr));
+ ether_addr_copy(sa, ieee80211_get_SA(hdr));
+ skb_pull(skb, hdr_len);
- if (is_first) {
- hdr_len = ieee80211_hdrlen(hdr->frame_control);
- crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype);
+ /* push original 802.11 header */
+ hdr = (struct ieee80211_hdr *)hdr_buf;
+ hdr_len = ieee80211_hdrlen(hdr->frame_control);
+ memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
- rfc1042 += round_up(hdr_len, 4) +
- round_up(crypto_len, 4);
+ /* original A-MSDU header has the bit set but we're
+ * not including A-MSDU subframe header */
+ hdr = (struct ieee80211_hdr *)skb->data;
+ qos = ieee80211_get_qos_ctl(hdr);
+ qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+
+ /* original 802.11 header has a different DA and in
+ * case of 4addr it may also have different SA
+ */
+ ether_addr_copy(ieee80211_get_DA(hdr), da);
+ ether_addr_copy(ieee80211_get_SA(hdr), sa);
+ break;
+ case RX_MSDU_DECAP_ETHERNET2_DIX:
+ /* strip ethernet header and insert decapped 802.11
+ * header, amsdu subframe header and rfc1042 header */
+
+ len = 0;
+ len += sizeof(struct rfc1042_hdr);
+ len += sizeof(struct amsdu_subframe_hdr);
+
+ skb_pull(skb, sizeof(struct ethhdr));
+ memcpy(skb_push(skb, len), decap_hdr, len);
+ memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
+ break;
+ case RX_MSDU_DECAP_8023_SNAP_LLC:
+ /* insert decapped 802.11 header making a singly
+ * A-MSDU */
+ memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
+ break;
+ }
+
+ skb_in = skb;
+ ath10k_htt_rx_h_protected(htt, rx_status, skb_in, enctype, fmt,
+ false);
+ skb = skb->next;
+ skb_in->next = NULL;
+
+ if (skb)
+ rx_status->flag |= RX_FLAG_AMSDU_MORE;
+ else
+ rx_status->flag &= ~RX_FLAG_AMSDU_MORE;
+
+ ath10k_process_rx(htt->ar, rx_status, skb_in);
}
- if (is_amsdu)
- rfc1042 += sizeof(struct amsdu_subframe_hdr);
-
- return rfc1042;
+ /* FIXME: It might be nice to re-assemble the A-MSDU when there's a
+ * monitor interface active for sniffing purposes. */
}
-static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
- struct sk_buff *msdu,
- struct ieee80211_rx_status *status,
- const u8 first_hdr[64],
- enum htt_rx_mpdu_encrypt_type enctype)
+static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
+ struct ieee80211_rx_status *rx_status,
+ struct sk_buff *skb)
{
- struct ieee80211_hdr *hdr;
- struct ethhdr *eth;
- size_t hdr_len;
- void *rfc1042;
- u8 da[ETH_ALEN];
- u8 sa[ETH_ALEN];
-
- /* Delivered decapped frame:
- * [eth header] <-- replaced with 802.11 hdr & rfc1042/llc
- * [payload]
- */
-
- rfc1042 = ath10k_htt_rx_h_find_rfc1042(ar, msdu, enctype);
- if (WARN_ON_ONCE(!rfc1042))
- return;
-
- /* pull decapped header and copy SA & DA */
- eth = (struct ethhdr *)msdu->data;
- ether_addr_copy(da, eth->h_dest);
- ether_addr_copy(sa, eth->h_source);
- skb_pull(msdu, sizeof(struct ethhdr));
-
- /* push rfc1042/llc/snap */
- memcpy(skb_push(msdu, sizeof(struct rfc1042_hdr)), rfc1042,
- sizeof(struct rfc1042_hdr));
-
- /* push original 802.11 header */
- hdr = (struct ieee80211_hdr *)first_hdr;
- hdr_len = ieee80211_hdrlen(hdr->frame_control);
- memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
-
- /* original 802.11 header has a different DA and in
- * case of 4addr it may also have different SA
- */
- hdr = (struct ieee80211_hdr *)msdu->data;
- ether_addr_copy(ieee80211_get_DA(hdr), da);
- ether_addr_copy(ieee80211_get_SA(hdr), sa);
-}
-
-static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
- struct sk_buff *msdu,
- struct ieee80211_rx_status *status,
- const u8 first_hdr[64])
-{
- struct ieee80211_hdr *hdr;
- size_t hdr_len;
-
- /* Delivered decapped frame:
- * [amsdu header] <-- replaced with 802.11 hdr
- * [rfc1042/llc]
- * [payload]
- */
-
- skb_pull(msdu, sizeof(struct amsdu_subframe_hdr));
-
- hdr = (struct ieee80211_hdr *)first_hdr;
- hdr_len = ieee80211_hdrlen(hdr->frame_control);
- memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
-}
-
-static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
- struct sk_buff *msdu,
- struct ieee80211_rx_status *status,
- u8 first_hdr[64],
- enum htt_rx_mpdu_encrypt_type enctype,
- bool is_decrypted)
-{
+ struct ath10k *ar = htt->ar;
struct htt_rx_desc *rxd;
- enum rx_msdu_decap_format decap;
struct ieee80211_hdr *hdr;
+ enum rx_msdu_decap_format fmt;
+ enum htt_rx_mpdu_encrypt_type enctype;
+ int hdr_len;
+ void *rfc1042;
- /* First msdu's decapped header:
- * [802.11 header] <-- padded to 4 bytes long
- * [crypto param] <-- padded to 4 bytes long
- * [amsdu header] <-- only if A-MSDU
- * [rfc1042/llc]
- *
- * Other (2nd, 3rd, ..) msdu's decapped header:
- * [amsdu header] <-- only if A-MSDU
- * [rfc1042/llc]
- */
+ /* This shouldn't happen. If it does than it may be a FW bug. */
+ if (skb->next) {
+ ath10k_warn(ar, "htt rx received chained non A-MSDU frame\n");
+ ath10k_htt_rx_free_msdu_chain(skb->next);
+ skb->next = NULL;
+ }
- rxd = (void *)msdu->data - sizeof(*rxd);
- hdr = (void *)rxd->rx_hdr_status;
- decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
- RX_MSDU_START_INFO1_DECAP_FORMAT);
+ rxd = (void *)skb->data - sizeof(*rxd);
+ fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
+ RX_MSDU_START_INFO1_DECAP_FORMAT);
+ enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
+ RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+ hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
+ hdr_len = ieee80211_hdrlen(hdr->frame_control);
- switch (decap) {
+ skb->ip_summed = ath10k_htt_rx_get_csum_state(skb);
+
+ switch (fmt) {
case RX_MSDU_DECAP_RAW:
- ath10k_htt_rx_h_undecap_raw(ar, msdu, status, enctype,
- is_decrypted);
+ /* remove trailing FCS */
+ skb_trim(skb, skb->len - FCS_LEN);
break;
case RX_MSDU_DECAP_NATIVE_WIFI:
- ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr);
+ /* Pull decapped header */
+ hdr = (struct ieee80211_hdr *)skb->data;
+ hdr_len = ath10k_htt_rx_nwifi_hdrlen(hdr);
+ skb_pull(skb, hdr_len);
+
+ /* Push original header */
+ hdr = (struct ieee80211_hdr *)rxd->rx_hdr_status;
+ hdr_len = ieee80211_hdrlen(hdr->frame_control);
+ memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
break;
case RX_MSDU_DECAP_ETHERNET2_DIX:
- ath10k_htt_rx_h_undecap_eth(ar, msdu, status, first_hdr, enctype);
+ /* strip ethernet header and insert decapped 802.11 header and
+ * rfc1042 header */
+
+ rfc1042 = hdr;
+ rfc1042 += roundup(hdr_len, 4);
+ rfc1042 += roundup(ath10k_htt_rx_crypto_param_len(ar,
+ enctype), 4);
+
+ skb_pull(skb, sizeof(struct ethhdr));
+ memcpy(skb_push(skb, sizeof(struct rfc1042_hdr)),
+ rfc1042, sizeof(struct rfc1042_hdr));
+ memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
break;
case RX_MSDU_DECAP_8023_SNAP_LLC:
- ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr);
+ /* remove A-MSDU subframe header and insert
+ * decapped 802.11 header. rfc1042 header is already there */
+
+ skb_pull(skb, sizeof(struct amsdu_subframe_hdr));
+ memcpy(skb_push(skb, hdr_len), hdr, hdr_len);
break;
}
+
+ ath10k_htt_rx_h_protected(htt, rx_status, skb, enctype, fmt, false);
+
+ ath10k_process_rx(htt->ar, rx_status, skb);
}
static int ath10k_htt_rx_get_csum_state(struct sk_buff *skb)
@@ -1109,128 +1122,10 @@
return CHECKSUM_UNNECESSARY;
}
-static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu)
+static int ath10k_unchain_msdu(struct sk_buff *msdu_head)
{
- msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
-}
-
-static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
- struct sk_buff_head *amsdu,
- struct ieee80211_rx_status *status)
-{
- struct sk_buff *first;
- struct sk_buff *last;
- struct sk_buff *msdu;
- struct htt_rx_desc *rxd;
- struct ieee80211_hdr *hdr;
- enum htt_rx_mpdu_encrypt_type enctype;
- u8 first_hdr[64];
- u8 *qos;
- size_t hdr_len;
- bool has_fcs_err;
- bool has_crypto_err;
- bool has_tkip_err;
- bool has_peer_idx_invalid;
- bool is_decrypted;
- u32 attention;
-
- if (skb_queue_empty(amsdu))
- return;
-
- first = skb_peek(amsdu);
- rxd = (void *)first->data - sizeof(*rxd);
-
- enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
- RX_MPDU_START_INFO0_ENCRYPT_TYPE);
-
- /* First MSDU's Rx descriptor in an A-MSDU contains full 802.11
- * decapped header. It'll be used for undecapping of each MSDU.
- */
- hdr = (void *)rxd->rx_hdr_status;
- hdr_len = ieee80211_hdrlen(hdr->frame_control);
- memcpy(first_hdr, hdr, hdr_len);
-
- /* Each A-MSDU subframe will use the original header as the base and be
- * reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl.
- */
- hdr = (void *)first_hdr;
- qos = ieee80211_get_qos_ctl(hdr);
- qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
-
- /* Some attention flags are valid only in the last MSDU. */
- last = skb_peek_tail(amsdu);
- rxd = (void *)last->data - sizeof(*rxd);
- attention = __le32_to_cpu(rxd->attention.flags);
-
- has_fcs_err = !!(attention & RX_ATTENTION_FLAGS_FCS_ERR);
- has_crypto_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
- has_tkip_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
- has_peer_idx_invalid = !!(attention & RX_ATTENTION_FLAGS_PEER_IDX_INVALID);
-
- /* Note: If hardware captures an encrypted frame that it can't decrypt,
- * e.g. due to fcs error, missing peer or invalid key data it will
- * report the frame as raw.
- */
- is_decrypted = (enctype != HTT_RX_MPDU_ENCRYPT_NONE &&
- !has_fcs_err &&
- !has_crypto_err &&
- !has_peer_idx_invalid);
-
- /* Clear per-MPDU flags while leaving per-PPDU flags intact. */
- status->flag &= ~(RX_FLAG_FAILED_FCS_CRC |
- RX_FLAG_MMIC_ERROR |
- RX_FLAG_DECRYPTED |
- RX_FLAG_IV_STRIPPED |
- RX_FLAG_MMIC_STRIPPED);
-
- if (has_fcs_err)
- status->flag |= RX_FLAG_FAILED_FCS_CRC;
-
- if (has_tkip_err)
- status->flag |= RX_FLAG_MMIC_ERROR;
-
- if (is_decrypted)
- status->flag |= RX_FLAG_DECRYPTED |
- RX_FLAG_IV_STRIPPED |
- RX_FLAG_MMIC_STRIPPED;
-
- skb_queue_walk(amsdu, msdu) {
- ath10k_htt_rx_h_csum_offload(msdu);
- ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
- is_decrypted);
-
- /* Undecapping involves copying the original 802.11 header back
- * to sk_buff. If frame is protected and hardware has decrypted
- * it then remove the protected bit.
- */
- if (!is_decrypted)
- continue;
-
- hdr = (void *)msdu->data;
- hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
- }
-}
-
-static void ath10k_htt_rx_h_deliver(struct ath10k *ar,
- struct sk_buff_head *amsdu,
- struct ieee80211_rx_status *status)
-{
- struct sk_buff *msdu;
-
- while ((msdu = __skb_dequeue(amsdu))) {
- /* Setup per-MSDU flags */
- if (skb_queue_empty(amsdu))
- status->flag &= ~RX_FLAG_AMSDU_MORE;
- else
- status->flag |= RX_FLAG_AMSDU_MORE;
-
- ath10k_process_rx(ar, status, msdu);
- }
-}
-
-static int ath10k_unchain_msdu(struct sk_buff_head *amsdu)
-{
- struct sk_buff *skb, *first;
+ struct sk_buff *next = msdu_head->next;
+ struct sk_buff *to_free = next;
int space;
int total_len = 0;
@@ -1241,142 +1136,113 @@
* skb?
*/
- first = __skb_dequeue(amsdu);
+ msdu_head->next = NULL;
/* Allocate total length all at once. */
- skb_queue_walk(amsdu, skb)
- total_len += skb->len;
+ while (next) {
+ total_len += next->len;
+ next = next->next;
+ }
- space = total_len - skb_tailroom(first);
+ space = total_len - skb_tailroom(msdu_head);
if ((space > 0) &&
- (pskb_expand_head(first, 0, space, GFP_ATOMIC) < 0)) {
+ (pskb_expand_head(msdu_head, 0, space, GFP_ATOMIC) < 0)) {
/* TODO: bump some rx-oom error stat */
/* put it back together so we can free the
* whole list at once.
*/
- __skb_queue_head(amsdu, first);
+ msdu_head->next = to_free;
return -1;
}
/* Walk list again, copying contents into
* msdu_head
*/
- while ((skb = __skb_dequeue(amsdu))) {
- skb_copy_from_linear_data(skb, skb_put(first, skb->len),
- skb->len);
- dev_kfree_skb_any(skb);
+ next = to_free;
+ while (next) {
+ skb_copy_from_linear_data(next, skb_put(msdu_head, next->len),
+ next->len);
+ next = next->next;
}
- __skb_queue_head(amsdu, first);
+ /* If here, we have consolidated skb. Free the
+ * fragments and pass the main skb on up the
+ * stack.
+ */
+ ath10k_htt_rx_free_msdu_chain(to_free);
return 0;
}
-static void ath10k_htt_rx_h_unchain(struct ath10k *ar,
- struct sk_buff_head *amsdu,
- bool chained)
+static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt,
+ struct sk_buff *head,
+ enum htt_rx_mpdu_status status,
+ bool channel_set,
+ u32 attention)
{
- struct sk_buff *first;
- struct htt_rx_desc *rxd;
- enum rx_msdu_decap_format decap;
+ struct ath10k *ar = htt->ar;
- first = skb_peek(amsdu);
- rxd = (void *)first->data - sizeof(*rxd);
- decap = MS(__le32_to_cpu(rxd->msdu_start.info1),
- RX_MSDU_START_INFO1_DECAP_FORMAT);
-
- if (!chained)
- return;
-
- /* FIXME: Current unchaining logic can only handle simple case of raw
- * msdu chaining. If decapping is other than raw the chaining may be
- * more complex and this isn't handled by the current code. Don't even
- * try re-constructing such frames - it'll be pretty much garbage.
- */
- if (decap != RX_MSDU_DECAP_RAW ||
- skb_queue_len(amsdu) != 1 + rxd->frag_info.ring2_more_count) {
- __skb_queue_purge(amsdu);
- return;
- }
-
- ath10k_unchain_msdu(amsdu);
-}
-
-static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar,
- struct sk_buff_head *amsdu,
- struct ieee80211_rx_status *rx_status)
-{
- struct sk_buff *msdu;
- struct htt_rx_desc *rxd;
- bool is_mgmt;
- bool has_fcs_err;
-
- msdu = skb_peek(amsdu);
- rxd = (void *)msdu->data - sizeof(*rxd);
-
- /* FIXME: It might be a good idea to do some fuzzy-testing to drop
- * invalid/dangerous frames.
- */
-
- if (!rx_status->freq) {
- ath10k_warn(ar, "no channel configured; ignoring frame(s)!\n");
+ if (head->len == 0) {
+ ath10k_dbg(ar, ATH10K_DBG_HTT,
+ "htt rx dropping due to zero-len\n");
return false;
}
- is_mgmt = !!(rxd->attention.flags &
- __cpu_to_le32(RX_ATTENTION_FLAGS_MGMT_TYPE));
- has_fcs_err = !!(rxd->attention.flags &
- __cpu_to_le32(RX_ATTENTION_FLAGS_FCS_ERR));
+ if (attention & RX_ATTENTION_FLAGS_DECRYPT_ERR) {
+ ath10k_dbg(ar, ATH10K_DBG_HTT,
+ "htt rx dropping due to decrypt-err\n");
+ return false;
+ }
- /* Management frames are handled via WMI events. The pros of such
- * approach is that channel is explicitly provided in WMI events
- * whereas HTT doesn't provide channel information for Rxed frames.
- *
- * However some firmware revisions don't report corrupted frames via
- * WMI so don't drop them.
- */
- if (is_mgmt && !has_fcs_err) {
+ if (!channel_set) {
+ ath10k_warn(ar, "no channel configured; ignoring frame!\n");
+ return false;
+ }
+
+ /* Skip mgmt frames while we handle this in WMI */
+ if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL ||
+ attention & RX_ATTENTION_FLAGS_MGMT_TYPE) {
ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n");
return false;
}
- if (test_bit(ATH10K_CAC_RUNNING, &ar->dev_flags)) {
- ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx cac running\n");
+ if (status != HTT_RX_IND_MPDU_STATUS_OK &&
+ status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR &&
+ status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER &&
+ !htt->ar->monitor_started) {
+ ath10k_dbg(ar, ATH10K_DBG_HTT,
+ "htt rx ignoring frame w/ status %d\n",
+ status);
+ return false;
+ }
+
+ if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) {
+ ath10k_dbg(ar, ATH10K_DBG_HTT,
+ "htt rx CAC running\n");
return false;
}
return true;
}
-static void ath10k_htt_rx_h_filter(struct ath10k *ar,
- struct sk_buff_head *amsdu,
- struct ieee80211_rx_status *rx_status)
-{
- if (skb_queue_empty(amsdu))
- return;
-
- if (ath10k_htt_rx_amsdu_allowed(ar, amsdu, rx_status))
- return;
-
- __skb_queue_purge(amsdu);
-}
-
static void ath10k_htt_rx_handler(struct ath10k_htt *htt,
struct htt_rx_indication *rx)
{
struct ath10k *ar = htt->ar;
struct ieee80211_rx_status *rx_status = &htt->rx_status;
struct htt_rx_indication_mpdu_range *mpdu_ranges;
- struct sk_buff_head amsdu;
+ struct htt_rx_desc *rxd;
+ enum htt_rx_mpdu_status status;
+ struct ieee80211_hdr *hdr;
int num_mpdu_ranges;
+ u32 attention;
int fw_desc_len;
u8 *fw_desc;
- int i, ret, mpdu_count = 0;
+ bool channel_set;
+ int i, j;
+ int ret;
lockdep_assert_held(&htt->rx_ring.lock);
- if (htt->rx_confused)
- return;
-
fw_desc_len = __le16_to_cpu(rx->prefix.fw_rx_desc_bytes);
fw_desc = (u8 *)&rx->fw_desc;
@@ -1384,33 +1250,92 @@
HTT_RX_INDICATION_INFO1_NUM_MPDU_RANGES);
mpdu_ranges = htt_rx_ind_get_mpdu_ranges(rx);
+ /* Fill this once, while this is per-ppdu */
+ if (rx->ppdu.info0 & HTT_RX_INDICATION_INFO0_START_VALID) {
+ memset(rx_status, 0, sizeof(*rx_status));
+ rx_status->signal = ATH10K_DEFAULT_NOISE_FLOOR +
+ rx->ppdu.combined_rssi;
+ }
+
+ if (rx->ppdu.info0 & HTT_RX_INDICATION_INFO0_END_VALID) {
+ /* TSF available only in 32-bit */
+ rx_status->mactime = __le32_to_cpu(rx->ppdu.tsf) & 0xffffffff;
+ rx_status->flag |= RX_FLAG_MACTIME_END;
+ }
+
+ channel_set = ath10k_htt_rx_h_channel(htt->ar, rx_status);
+
+ if (channel_set) {
+ ath10k_htt_rx_h_rates(htt->ar, rx_status->band,
+ rx->ppdu.info0,
+ __le32_to_cpu(rx->ppdu.info1),
+ __le32_to_cpu(rx->ppdu.info2),
+ rx_status);
+ }
+
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx ind: ",
rx, sizeof(*rx) +
(sizeof(struct htt_rx_indication_mpdu_range) *
num_mpdu_ranges));
- for (i = 0; i < num_mpdu_ranges; i++)
- mpdu_count += mpdu_ranges[i].mpdu_count;
+ for (i = 0; i < num_mpdu_ranges; i++) {
+ status = mpdu_ranges[i].mpdu_range_status;
- while (mpdu_count--) {
- __skb_queue_head_init(&amsdu);
- ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc,
- &fw_desc_len, &amsdu);
- if (ret < 0) {
- ath10k_warn(ar, "rx ring became corrupted: %d\n", ret);
- __skb_queue_purge(&amsdu);
- /* FIXME: It's probably a good idea to reboot the
- * device instead of leaving it inoperable.
- */
- htt->rx_confused = true;
- break;
+ for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) {
+ struct sk_buff *msdu_head, *msdu_tail;
+
+ attention = 0;
+ msdu_head = NULL;
+ msdu_tail = NULL;
+ ret = ath10k_htt_rx_amsdu_pop(htt,
+ &fw_desc,
+ &fw_desc_len,
+ &msdu_head,
+ &msdu_tail,
+ &attention);
+
+ if (ret < 0) {
+ ath10k_warn(ar, "failed to pop amsdu from htt rx ring %d\n",
+ ret);
+ ath10k_htt_rx_free_msdu_chain(msdu_head);
+ continue;
+ }
+
+ rxd = container_of((void *)msdu_head->data,
+ struct htt_rx_desc,
+ msdu_payload);
+
+ if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head,
+ status,
+ channel_set,
+ attention)) {
+ ath10k_htt_rx_free_msdu_chain(msdu_head);
+ continue;
+ }
+
+ if (ret > 0 &&
+ ath10k_unchain_msdu(msdu_head) < 0) {
+ ath10k_htt_rx_free_msdu_chain(msdu_head);
+ continue;
+ }
+
+ if (attention & RX_ATTENTION_FLAGS_FCS_ERR)
+ rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ else
+ rx_status->flag &= ~RX_FLAG_FAILED_FCS_CRC;
+
+ if (attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR)
+ rx_status->flag |= RX_FLAG_MMIC_ERROR;
+ else
+ rx_status->flag &= ~RX_FLAG_MMIC_ERROR;
+
+ hdr = ath10k_htt_rx_skb_get_hdr(msdu_head);
+
+ if (ath10k_htt_rx_hdr_is_amsdu(hdr))
+ ath10k_htt_rx_amsdu(htt, rx_status, msdu_head);
+ else
+ ath10k_htt_rx_msdu(htt, rx_status, msdu_head);
}
-
- ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
- ath10k_htt_rx_h_unchain(ar, &amsdu, ret > 0);
- ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
- ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
- ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
}
tasklet_schedule(&htt->rx_replenish_task);
@@ -1420,44 +1345,108 @@
struct htt_rx_fragment_indication *frag)
{
struct ath10k *ar = htt->ar;
+ struct sk_buff *msdu_head, *msdu_tail;
+ enum htt_rx_mpdu_encrypt_type enctype;
+ struct htt_rx_desc *rxd;
+ enum rx_msdu_decap_format fmt;
struct ieee80211_rx_status *rx_status = &htt->rx_status;
- struct sk_buff_head amsdu;
+ struct ieee80211_hdr *hdr;
int ret;
+ bool tkip_mic_err;
+ bool decrypt_err;
u8 *fw_desc;
- int fw_desc_len;
+ int fw_desc_len, hdrlen, paramlen;
+ int trim;
+ u32 attention = 0;
fw_desc_len = __le16_to_cpu(frag->fw_rx_desc_bytes);
fw_desc = (u8 *)frag->fw_msdu_rx_desc;
- __skb_queue_head_init(&amsdu);
+ msdu_head = NULL;
+ msdu_tail = NULL;
spin_lock_bh(&htt->rx_ring.lock);
ret = ath10k_htt_rx_amsdu_pop(htt, &fw_desc, &fw_desc_len,
- &amsdu);
+ &msdu_head, &msdu_tail,
+ &attention);
spin_unlock_bh(&htt->rx_ring.lock);
- tasklet_schedule(&htt->rx_replenish_task);
-
ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n");
if (ret) {
ath10k_warn(ar, "failed to pop amsdu from httr rx ring for fragmented rx %d\n",
ret);
- __skb_queue_purge(&amsdu);
+ ath10k_htt_rx_free_msdu_chain(msdu_head);
return;
}
- if (skb_queue_len(&amsdu) != 1) {
- ath10k_warn(ar, "failed to pop frag amsdu: too many msdus\n");
- __skb_queue_purge(&amsdu);
- return;
+ /* FIXME: implement signal strength */
+ rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+
+ hdr = (struct ieee80211_hdr *)msdu_head->data;
+ rxd = (void *)msdu_head->data - sizeof(*rxd);
+ tkip_mic_err = !!(attention & RX_ATTENTION_FLAGS_TKIP_MIC_ERR);
+ decrypt_err = !!(attention & RX_ATTENTION_FLAGS_DECRYPT_ERR);
+ fmt = MS(__le32_to_cpu(rxd->msdu_start.info1),
+ RX_MSDU_START_INFO1_DECAP_FORMAT);
+
+ if (fmt != RX_MSDU_DECAP_RAW) {
+ ath10k_warn(ar, "we dont support non-raw fragmented rx yet\n");
+ dev_kfree_skb_any(msdu_head);
+ goto end;
}
- ath10k_htt_rx_h_ppdu(ar, &amsdu, rx_status);
- ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
- ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
- ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
+ enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
+ RX_MPDU_START_INFO0_ENCRYPT_TYPE);
+ ath10k_htt_rx_h_protected(htt, rx_status, msdu_head, enctype, fmt,
+ true);
+ msdu_head->ip_summed = ath10k_htt_rx_get_csum_state(msdu_head);
+ if (tkip_mic_err)
+ ath10k_warn(ar, "tkip mic error\n");
+
+ if (decrypt_err) {
+ ath10k_warn(ar, "decryption err in fragmented rx\n");
+ dev_kfree_skb_any(msdu_head);
+ goto end;
+ }
+
+ if (enctype != HTT_RX_MPDU_ENCRYPT_NONE) {
+ hdrlen = ieee80211_hdrlen(hdr->frame_control);
+ paramlen = ath10k_htt_rx_crypto_param_len(ar, enctype);
+
+ /* It is more efficient to move the header than the payload */
+ memmove((void *)msdu_head->data + paramlen,
+ (void *)msdu_head->data,
+ hdrlen);
+ skb_pull(msdu_head, paramlen);
+ hdr = (struct ieee80211_hdr *)msdu_head->data;
+ }
+
+ /* remove trailing FCS */
+ trim = 4;
+
+ /* remove crypto trailer */
+ trim += ath10k_htt_rx_crypto_tail_len(ar, enctype);
+
+ /* last fragment of TKIP frags has MIC */
+ if (!ieee80211_has_morefrags(hdr->frame_control) &&
+ enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
+ trim += 8;
+
+ if (trim > msdu_head->len) {
+ ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n");
+ dev_kfree_skb_any(msdu_head);
+ goto end;
+ }
+
+ skb_trim(msdu_head, msdu_head->len - trim);
+
+ ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx frag mpdu: ",
+ msdu_head->data, msdu_head->len);
+ ath10k_process_rx(htt->ar, rx_status, msdu_head);
+
+end:
if (fw_desc_len > 0) {
ath10k_dbg(ar, ATH10K_DBG_HTT,
"expecting more fragmented rx in one indication %d\n",
@@ -1685,15 +1674,6 @@
case HTT_T2H_MSG_TYPE_RX_DELBA:
ath10k_htt_rx_delba(ar, resp);
break;
- case HTT_T2H_MSG_TYPE_PKTLOG: {
- struct ath10k_pktlog_hdr *hdr =
- (struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload;
-
- trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload,
- sizeof(*hdr) +
- __le16_to_cpu(hdr->size));
- break;
- }
case HTT_T2H_MSG_TYPE_RX_FLUSH: {
/* Ignore this event because mac80211 takes care of Rx
* aggregation reordering.
@@ -1701,8 +1681,8 @@
break;
}
default:
- ath10k_warn(ar, "htt event (%d) not handled\n",
- resp->hdr.msg_type);
+ ath10k_dbg(ar, ATH10K_DBG_HTT, "htt event (%d) not handled\n",
+ resp->hdr.msg_type);
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ",
skb->data, skb->len);
break;
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index a0f8a0b..c6768e2 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -74,8 +74,8 @@
{
struct ath10k *ar = htt->ar;
int tx_idx;
-
spin_lock_init(&htt->tx_msdu_pool_lock);
+ init_waitqueue_head(&htt->empty_tx_wq);
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features))
htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC;
@@ -549,18 +549,14 @@
skb_cb->htt.txbuf->cmd_tx.len = __cpu_to_le16(msdu->len);
skb_cb->htt.txbuf->cmd_tx.id = __cpu_to_le16(msdu_id);
skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr);
- skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le16(HTT_INVALID_PEERID);
- skb_cb->htt.txbuf->cmd_tx.freq = __cpu_to_le16(skb_cb->htt.freq);
+ skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID);
- trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid);
ath10k_dbg(ar, ATH10K_DBG_HTT,
- "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu freq %hu\n",
+ "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n",
flags0, flags1, msdu->len, msdu_id, frags_paddr,
- (u32)skb_cb->paddr, vdev_id, tid, skb_cb->htt.freq);
+ (u32)skb_cb->paddr, vdev_id, tid);
ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ",
msdu->data, msdu->len);
- trace_ath10k_tx_hdr(ar, msdu->data, msdu->len);
- trace_ath10k_tx_payload(ar, msdu->data, msdu->len);
sg_items[0].transfer_id = 0;
sg_items[0].transfer_context = NULL;
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h
index dfedfd0..3cf5702 100644
--- a/drivers/net/wireless/ath/ath10k/hw.h
+++ b/drivers/net/wireless/ath/ath10k/hw.h
@@ -20,16 +20,15 @@
#include "targaddrs.h"
-#define ATH10K_FW_DIR "ath10k"
-
/* QCA988X 1.0 definitions (unsupported) */
#define QCA988X_HW_1_0_CHIP_ID_REV 0x0
/* QCA988X 2.0 definitions */
#define QCA988X_HW_2_0_VERSION 0x4100016c
#define QCA988X_HW_2_0_CHIP_ID_REV 0x2
-#define QCA988X_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA988X/hw2.0"
+#define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0"
#define QCA988X_HW_2_0_FW_FILE "firmware.bin"
+#define QCA988X_HW_2_0_FW_3_FILE "firmware-3.bin"
#define QCA988X_HW_2_0_OTP_FILE "otp.bin"
#define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin"
#define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234
@@ -44,8 +43,6 @@
#define REG_DUMP_COUNT_QCA988X 60
-#define QCA988X_CAL_DATA_LEN 2116
-
struct ath10k_fw_ie {
__le32 id;
__le32 len;
@@ -81,15 +78,6 @@
ATH10K_MCAST2UCAST_ENABLED = 1,
};
-struct ath10k_pktlog_hdr {
- __le16 flags;
- __le16 missed_cnt;
- __le16 log_type;
- __le16 size;
- __le32 timestamp;
- u8 payload[0];
-} __packed;
-
/* Target specific defines for MAIN firmware */
#define TARGET_NUM_VDEVS 8
#define TARGET_NUM_PEER_AST 2
@@ -97,13 +85,11 @@
#define TARGET_DMA_BURST_SIZE 0
#define TARGET_MAC_AGGR_DELIM 0
#define TARGET_AST_SKID_LIMIT 16
-#define TARGET_NUM_STATIONS 16
-#define TARGET_NUM_PEERS ((TARGET_NUM_STATIONS) + \
- (TARGET_NUM_VDEVS))
+#define TARGET_NUM_PEERS 16
#define TARGET_NUM_OFFLOAD_PEERS 0
#define TARGET_NUM_OFFLOAD_REORDER_BUFS 0
#define TARGET_NUM_PEER_KEYS 2
-#define TARGET_NUM_TIDS ((TARGET_NUM_PEERS) * 2)
+#define TARGET_NUM_TIDS (2 * ((TARGET_NUM_PEERS) + (TARGET_NUM_VDEVS)))
#define TARGET_TX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
#define TARGET_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
#define TARGET_RX_TIMEOUT_LO_PRI 100
@@ -134,15 +120,12 @@
#define TARGET_10X_DMA_BURST_SIZE 0
#define TARGET_10X_MAC_AGGR_DELIM 0
#define TARGET_10X_AST_SKID_LIMIT 16
-#define TARGET_10X_NUM_STATIONS 128
-#define TARGET_10X_NUM_PEERS ((TARGET_10X_NUM_STATIONS) + \
- (TARGET_10X_NUM_VDEVS))
+#define TARGET_10X_NUM_PEERS (128 + (TARGET_10X_NUM_VDEVS))
+#define TARGET_10X_NUM_PEERS_MAX 128
#define TARGET_10X_NUM_OFFLOAD_PEERS 0
#define TARGET_10X_NUM_OFFLOAD_REORDER_BUFS 0
#define TARGET_10X_NUM_PEER_KEYS 2
-#define TARGET_10X_NUM_TIDS_MAX 256
-#define TARGET_10X_NUM_TIDS min((TARGET_10X_NUM_TIDS_MAX), \
- (TARGET_10X_NUM_PEERS) * 2)
+#define TARGET_10X_NUM_TIDS 256
#define TARGET_10X_TX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
#define TARGET_10X_RX_CHAIN_MASK (BIT(0) | BIT(1) | BIT(2))
#define TARGET_10X_RX_TIMEOUT_LO_PRI 100
@@ -296,7 +279,6 @@
#define SI_RX_DATA1_OFFSET 0x00000014
#define CORE_CTRL_CPU_INTR_MASK 0x00002000
-#define CORE_CTRL_PCIE_REG_31_MASK 0x00000800
#define CORE_CTRL_ADDRESS 0x0000
#define PCIE_INTR_ENABLE_ADDRESS 0x0008
#define PCIE_INTR_CAUSE_ADDRESS 0x000c
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 351235e..a001051 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -136,9 +136,7 @@
if (ret)
return ret;
- spin_lock_bh(&ar->data_lock);
peer->keys[i] = arvif->wep_keys[i];
- spin_unlock_bh(&ar->data_lock);
}
return 0;
@@ -175,39 +173,12 @@
ath10k_warn(ar, "failed to remove peer wep key %d: %d\n",
i, ret);
- spin_lock_bh(&ar->data_lock);
peer->keys[i] = NULL;
- spin_unlock_bh(&ar->data_lock);
}
return first_errno;
}
-bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
- u8 keyidx)
-{
- struct ath10k_peer *peer;
- int i;
-
- lockdep_assert_held(&ar->data_lock);
-
- /* We don't know which vdev this peer belongs to,
- * since WMI doesn't give us that information.
- *
- * FIXME: multi-bss needs to be handled.
- */
- peer = ath10k_peer_find(ar, 0, addr);
- if (!peer)
- return false;
-
- for (i = 0; i < ARRAY_SIZE(peer->keys); i++) {
- if (peer->keys[i] && peer->keys[i]->keyidx == keyidx)
- return true;
- }
-
- return false;
-}
-
static int ath10k_clear_vdev_key(struct ath10k_vif *arvif,
struct ieee80211_key_conf *key)
{
@@ -351,30 +322,61 @@
static int ath10k_peer_create(struct ath10k *ar, u32 vdev_id, const u8 *addr)
{
+ struct ath10k_peer *peer;
int ret;
lockdep_assert_held(&ar->conf_mutex);
- if (ar->num_peers >= ar->max_num_peers)
- return -ENOBUFS;
+ peer = ath10k_peer_find(ar, vdev_id, addr);
+ if (peer) {
+ ath10k_warn(ar, "peer %pM on vdev %i already exists\n",
+ addr, vdev_id);
+ return -EINVAL;
+ }
+
+ peer = kzalloc(sizeof(*peer), GFP_KERNEL);
+ if (!peer) {
+ ath10k_warn(ar, "failed to allocate peer %pM on vdev %i: not enough memory\n",
+ addr, vdev_id);
+ return -ENOMEM;
+ }
+
+ peer->vdev_id = vdev_id;
+ memcpy(peer->addr, addr, ETH_ALEN);
+
+ spin_lock_bh(&ar->data_lock);
+ list_add(&peer->list, &ar->peers);
+ spin_unlock_bh(&ar->data_lock);
ret = ath10k_wmi_peer_create(ar, vdev_id, addr);
if (ret) {
ath10k_warn(ar, "failed to create wmi peer %pM on vdev %i: %i\n",
addr, vdev_id, ret);
- return ret;
+ goto err_free;
}
ret = ath10k_wait_for_peer_created(ar, vdev_id, addr);
if (ret) {
ath10k_warn(ar, "failed to wait for created wmi peer %pM on vdev %i: %i\n",
addr, vdev_id, ret);
- return ret;
+ goto err_free;
}
-
+ spin_lock_bh(&ar->data_lock);
ar->num_peers++;
+ spin_unlock_bh(&ar->data_lock);
return 0;
+
+err_free:
+ spin_lock_bh(&ar->data_lock);
+ list_del(&peer->list);
+ /* very unlikely, but check anyway */
+ if (!bitmap_empty(peer->peer_ids, ATH10K_MAX_NUM_PEER_IDS))
+ ath10k_warn(ar, "removing peer %pM on vdev %i still being mapped in firmware\n",
+ addr, vdev_id);
+ spin_unlock_bh(&ar->data_lock);
+ kfree(peer);
+ return ret;
}
static int ath10k_mac_set_kickout(struct ath10k_vif *arvif)
@@ -422,11 +424,15 @@
return 0;
}
-static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
+static int ath10k_mac_set_rts(struct ath10k_vif *arvif, u32 value)
{
struct ath10k *ar = arvif->ar;
u32 vdev_param;
+ if (value != 0xFFFFFFFF)
+ value = min_t(u32, arvif->ar->hw->wiphy->rts_threshold,
+ ATH10K_RTS_MAX);
+
vdev_param = ar->wmi.vdev_param->rts_threshold;
return ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param, value);
}
@@ -473,7 +479,9 @@
goto out;
}
+ spin_lock_bh(&ar->data_lock);
ar->num_peers--;
+ spin_unlock_bh(&ar->data_lock);
out:
spin_lock_bh(&ar->data_lock);
@@ -520,59 +528,20 @@
list_del(&peer->list);
kfree(peer);
}
- spin_unlock_bh(&ar->data_lock);
-
ar->num_peers = 0;
- ar->num_stations = 0;
+ spin_unlock_bh(&ar->data_lock);
}
/************************/
/* Interface management */
/************************/
-void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif)
-{
- struct ath10k *ar = arvif->ar;
-
- lockdep_assert_held(&ar->data_lock);
-
- if (!arvif->beacon)
- return;
-
- if (!arvif->beacon_buf)
- dma_unmap_single(ar->dev, ATH10K_SKB_CB(arvif->beacon)->paddr,
- arvif->beacon->len, DMA_TO_DEVICE);
-
- dev_kfree_skb_any(arvif->beacon);
-
- arvif->beacon = NULL;
- arvif->beacon_sent = false;
-}
-
-static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif)
-{
- struct ath10k *ar = arvif->ar;
-
- lockdep_assert_held(&ar->data_lock);
-
- ath10k_mac_vif_beacon_free(arvif);
-
- if (arvif->beacon_buf) {
- dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
- arvif->beacon_buf, arvif->beacon_paddr);
- arvif->beacon_buf = NULL;
- }
-}
-
static inline int ath10k_vdev_setup_sync(struct ath10k *ar)
{
int ret;
lockdep_assert_held(&ar->conf_mutex);
- if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
- return -ESHUTDOWN;
-
ret = wait_for_completion_timeout(&ar->vdev_setup_done,
ATH10K_VDEV_SETUP_TIMEOUT_HZ);
if (ret == 0)
@@ -605,8 +574,6 @@
arg.channel.max_reg_power = channel->max_reg_power * 2;
arg.channel.max_antenna_gain = channel->max_antenna_gain * 2;
- reinit_completion(&ar->vdev_setup_done);
-
ret = ath10k_wmi_vdev_start(ar, &arg);
if (ret) {
ath10k_warn(ar, "failed to request monitor vdev %i start: %d\n",
@@ -654,8 +621,6 @@
ath10k_warn(ar, "failed to put down monitor vdev %i: %d\n",
ar->monitor_vdev_id, ret);
- reinit_completion(&ar->vdev_setup_done);
-
ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id);
if (ret)
ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n",
@@ -682,9 +647,9 @@
return -ENOMEM;
}
- bit = __ffs64(ar->free_vdev_map);
+ bit = ffs(ar->free_vdev_map);
- ar->monitor_vdev_id = bit;
+ ar->monitor_vdev_id = bit - 1;
ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id,
WMI_VDEV_TYPE_MONITOR,
@@ -695,7 +660,7 @@
return ret;
}
- ar->free_vdev_map &= ~(1LL << ar->monitor_vdev_id);
+ ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id);
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n",
ar->monitor_vdev_id);
@@ -715,7 +680,7 @@
return ret;
}
- ar->free_vdev_map |= 1LL << ar->monitor_vdev_id;
+ ar->free_vdev_map |= 1 << ar->monitor_vdev_id;
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n",
ar->monitor_vdev_id);
@@ -1003,7 +968,15 @@
arvif->is_up = false;
spin_lock_bh(&arvif->ar->data_lock);
- ath10k_mac_vif_beacon_free(arvif);
+ if (arvif->beacon) {
+ dma_unmap_single(arvif->ar->dev,
+ ATH10K_SKB_CB(arvif->beacon)->paddr,
+ arvif->beacon->len, DMA_TO_DEVICE);
+ dev_kfree_skb_any(arvif->beacon);
+
+ arvif->beacon = NULL;
+ arvif->beacon_sent = false;
+ }
spin_unlock_bh(&arvif->ar->data_lock);
return;
@@ -1052,6 +1025,14 @@
if (is_zero_ether_addr(arvif->bssid))
return;
+ ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id,
+ arvif->bssid);
+ if (ret) {
+ ath10k_warn(ar, "failed to delete IBSS BSSID peer %pM for vdev %d: %d\n",
+ arvif->bssid, arvif->vdev_id, ret);
+ return;
+ }
+
memset(arvif->bssid, 0, ETH_ALEN);
return;
@@ -1120,45 +1101,51 @@
/* Station management */
/**********************/
-static u32 ath10k_peer_assoc_h_listen_intval(struct ath10k *ar,
- struct ieee80211_vif *vif)
-{
- /* Some firmware revisions have unstable STA powersave when listen
- * interval is set too high (e.g. 5). The symptoms are firmware doesn't
- * generate NullFunc frames properly even if buffered frames have been
- * indicated in Beacon TIM. Firmware would seldom wake up to pull
- * buffered frames. Often pinging the device from AP would simply fail.
- *
- * As a workaround set it to 1.
- */
- if (vif->type == NL80211_IFTYPE_STATION)
- return 1;
-
- return ar->hw->conf.listen_interval;
-}
-
static void ath10k_peer_assoc_h_basic(struct ath10k *ar,
- struct ieee80211_vif *vif,
+ struct ath10k_vif *arvif,
struct ieee80211_sta *sta,
+ struct ieee80211_bss_conf *bss_conf,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-
lockdep_assert_held(&ar->conf_mutex);
ether_addr_copy(arg->addr, sta->addr);
arg->vdev_id = arvif->vdev_id;
arg->peer_aid = sta->aid;
arg->peer_flags |= WMI_PEER_AUTH;
- arg->peer_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif);
+
+ if (arvif->vdev_type == WMI_VDEV_TYPE_STA)
+ /*
+ * Seems FW have problems with Power Save in STA
+ * mode when we setup this parameter to high (eg. 5).
+ * Often we see that FW don't send NULL (with clean P flags)
+ * frame even there is info about buffered frames in beacons.
+ * Sometimes we have to wait more than 10 seconds before FW
+ * will wakeup. Often sending one ping from AP to our device
+ * just fail (more than 50%).
+ *
+ * Seems setting this FW parameter to 1 couse FW
+ * will check every beacon and will wakup immediately
+ * after detection buffered data.
+ */
+ arg->peer_listen_intval = 1;
+ else
+ arg->peer_listen_intval = ar->hw->conf.listen_interval;
+
arg->peer_num_spatial_streams = 1;
- arg->peer_caps = vif->bss_conf.assoc_capability;
+
+ /*
+ * The assoc capabilities are available only in managed mode.
+ */
+ if (arvif->vdev_type == WMI_VDEV_TYPE_STA && bss_conf)
+ arg->peer_caps = bss_conf->assoc_capability;
}
static void ath10k_peer_assoc_h_crypto(struct ath10k *ar,
- struct ieee80211_vif *vif,
+ struct ath10k_vif *arvif,
struct wmi_peer_assoc_complete_arg *arg)
{
+ struct ieee80211_vif *vif = arvif->vif;
struct ieee80211_bss_conf *info = &vif->bss_conf;
struct cfg80211_bss *bss;
const u8 *rsnie = NULL;
@@ -1415,12 +1402,11 @@
}
static void ath10k_peer_assoc_h_qos(struct ath10k *ar,
- struct ieee80211_vif *vif,
+ struct ath10k_vif *arvif,
struct ieee80211_sta *sta,
+ struct ieee80211_bss_conf *bss_conf,
struct wmi_peer_assoc_complete_arg *arg)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
-
switch (arvif->vdev_type) {
case WMI_VDEV_TYPE_AP:
if (sta->wme)
@@ -1432,7 +1418,7 @@
}
break;
case WMI_VDEV_TYPE_STA:
- if (vif->bss_conf.qos)
+ if (bss_conf->qos)
arg->peer_flags |= WMI_PEER_QOS;
break;
default:
@@ -1441,7 +1427,7 @@
}
static void ath10k_peer_assoc_h_phymode(struct ath10k *ar,
- struct ieee80211_vif *vif,
+ struct ath10k_vif *arvif,
struct ieee80211_sta *sta,
struct wmi_peer_assoc_complete_arg *arg)
{
@@ -1492,21 +1478,22 @@
}
static int ath10k_peer_assoc_prepare(struct ath10k *ar,
- struct ieee80211_vif *vif,
+ struct ath10k_vif *arvif,
struct ieee80211_sta *sta,
+ struct ieee80211_bss_conf *bss_conf,
struct wmi_peer_assoc_complete_arg *arg)
{
lockdep_assert_held(&ar->conf_mutex);
memset(arg, 0, sizeof(*arg));
- ath10k_peer_assoc_h_basic(ar, vif, sta, arg);
- ath10k_peer_assoc_h_crypto(ar, vif, arg);
+ ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, arg);
+ ath10k_peer_assoc_h_crypto(ar, arvif, arg);
ath10k_peer_assoc_h_rates(ar, sta, arg);
ath10k_peer_assoc_h_ht(ar, sta, arg);
ath10k_peer_assoc_h_vht(ar, sta, arg);
- ath10k_peer_assoc_h_qos(ar, vif, sta, arg);
- ath10k_peer_assoc_h_phymode(ar, vif, sta, arg);
+ ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, arg);
+ ath10k_peer_assoc_h_phymode(ar, arvif, sta, arg);
return 0;
}
@@ -1552,9 +1539,6 @@
lockdep_assert_held(&ar->conf_mutex);
- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
- arvif->vdev_id, arvif->bssid, arvif->aid);
-
rcu_read_lock();
ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
@@ -1569,7 +1553,8 @@
* before calling ath10k_setup_peer_smps() which might sleep. */
ht_cap = ap_sta->ht_cap;
- ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg);
+ ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta,
+ bss_conf, &peer_arg);
if (ret) {
ath10k_warn(ar, "failed to prepare peer assoc for %pM vdev %i: %d\n",
bss_conf->bssid, arvif->vdev_id, ret);
@@ -1597,8 +1582,6 @@
"mac vdev %d up (associated) bssid %pM aid %d\n",
arvif->vdev_id, bss_conf->bssid, bss_conf->aid);
- WARN_ON(arvif->is_up);
-
arvif->aid = bss_conf->aid;
ether_addr_copy(arvif->bssid, bss_conf->bssid);
@@ -1612,6 +1595,9 @@
arvif->is_up = true;
}
+/*
+ * FIXME: flush TIDs
+ */
static void ath10k_bss_disassoc(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -1621,30 +1607,45 @@
lockdep_assert_held(&ar->conf_mutex);
- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n",
- arvif->vdev_id, arvif->bssid);
+ /*
+ * For some reason, calling VDEV-DOWN before VDEV-STOP
+ * makes the FW to send frames via HTT after disassociation.
+ * No idea why this happens, even though VDEV-DOWN is supposed
+ * to be analogous to link down, so just stop the VDEV.
+ */
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d stop (disassociated\n",
+ arvif->vdev_id);
+ /* FIXME: check return value */
+ ret = ath10k_vdev_stop(arvif);
+
+ /*
+ * If we don't call VDEV-DOWN after VDEV-STOP FW will remain active and
+ * report beacons from previously associated network through HTT.
+ * This in turn would spam mac80211 WARN_ON if we bring down all
+ * interfaces as it expects there is no rx when no interface is
+ * running.
+ */
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d down\n", arvif->vdev_id);
+
+ /* FIXME: why don't we print error if wmi call fails? */
ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id);
- if (ret)
- ath10k_warn(ar, "faield to down vdev %i: %d\n",
- arvif->vdev_id, ret);
arvif->def_wep_key_idx = 0;
+
+ arvif->is_started = false;
arvif->is_up = false;
}
-static int ath10k_station_assoc(struct ath10k *ar,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- bool reassoc)
+static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif,
+ struct ieee80211_sta *sta, bool reassoc)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct wmi_peer_assoc_complete_arg peer_arg;
int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
- ret = ath10k_peer_assoc_prepare(ar, vif, sta, &peer_arg);
+ ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg);
if (ret) {
ath10k_warn(ar, "failed to prepare WMI peer assoc for %pM vdev %i: %i\n",
sta->addr, arvif->vdev_id, ret);
@@ -1659,51 +1660,43 @@
return ret;
}
- /* Re-assoc is run only to update supported rates for given station. It
- * doesn't make much sense to reconfigure the peer completely.
- */
- if (!reassoc) {
- ret = ath10k_setup_peer_smps(ar, arvif, sta->addr,
- &sta->ht_cap);
- if (ret) {
- ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n",
- arvif->vdev_id, ret);
- return ret;
- }
+ ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap);
+ if (ret) {
+ ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
- ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta);
+ if (!sta->wme && !reassoc) {
+ arvif->num_legacy_stations++;
+ ret = ath10k_recalc_rtscts_prot(arvif);
if (ret) {
- ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n",
- sta->addr, arvif->vdev_id, ret);
- return ret;
- }
-
- if (!sta->wme) {
- arvif->num_legacy_stations++;
- ret = ath10k_recalc_rtscts_prot(arvif);
- if (ret) {
- ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
- arvif->vdev_id, ret);
- return ret;
- }
- }
-
- ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
- if (ret) {
- ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n",
+ ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n",
arvif->vdev_id, ret);
return ret;
}
}
+ ret = ath10k_install_peer_wep_keys(arvif, sta->addr);
+ if (ret) {
+ ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
+ ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta);
+ if (ret) {
+ ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n",
+ sta->addr, arvif->vdev_id, ret);
+ return ret;
+ }
+
return ret;
}
-static int ath10k_station_disassoc(struct ath10k *ar,
- struct ieee80211_vif *vif,
+static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif,
struct ieee80211_sta *sta)
{
- struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
int ret = 0;
lockdep_assert_held(&ar->conf_mutex);
@@ -1795,7 +1788,6 @@
ch->passive = passive;
ch->freq = channel->center_freq;
- ch->band_center_freq1 = channel->center_freq;
ch->min_power = 0;
ch->max_power = channel->max_power * 2;
ch->max_reg_power = channel->max_reg_power * 2;
@@ -2050,18 +2042,6 @@
}
}
-static bool ath10k_mac_need_offchan_tx_work(struct ath10k *ar)
-{
- /* FIXME: Not really sure since when the behaviour changed. At some
- * point new firmware stopped requiring creation of peer entries for
- * offchannel tx (and actually creating them causes issues with wmi-htc
- * tx credit replenishment and reliability). Assuming it's at least 3.4
- * because that's when the `freq` was introduced to TX_FRM HTT command.
- */
- return !(ar->htt.target_version_major >= 3 &&
- ar->htt.target_version_minor >= 4);
-}
-
static void ath10k_tx_htt(struct ath10k *ar, struct sk_buff *skb)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -2333,10 +2313,10 @@
case ATH10K_SCAN_IDLE:
break;
case ATH10K_SCAN_RUNNING:
+ case ATH10K_SCAN_ABORTING:
if (ar->scan.is_roc)
ieee80211_remain_on_channel_expired(ar->hw);
- case ATH10K_SCAN_ABORTING:
- if (!ar->scan.is_roc)
+ else
ieee80211_scan_completed(ar->hw,
(ar->scan.state ==
ATH10K_SCAN_ABORTING));
@@ -2502,28 +2482,23 @@
if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) {
spin_lock_bh(&ar->data_lock);
- ATH10K_SKB_CB(skb)->htt.freq = ar->scan.roc_freq;
+ ATH10K_SKB_CB(skb)->htt.is_offchan = true;
ATH10K_SKB_CB(skb)->vdev_id = ar->scan.vdev_id;
spin_unlock_bh(&ar->data_lock);
- if (ath10k_mac_need_offchan_tx_work(ar)) {
- ATH10K_SKB_CB(skb)->htt.freq = 0;
- ATH10K_SKB_CB(skb)->htt.is_offchan = true;
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
+ skb);
- ath10k_dbg(ar, ATH10K_DBG_MAC, "queued offchannel skb %p\n",
- skb);
-
- skb_queue_tail(&ar->offchan_tx_queue, skb);
- ieee80211_queue_work(hw, &ar->offchan_tx_work);
- return;
- }
+ skb_queue_tail(&ar->offchan_tx_queue, skb);
+ ieee80211_queue_work(hw, &ar->offchan_tx_work);
+ return;
}
ath10k_tx_htt(ar, skb);
}
/* Must not be called with conf_mutex held as workers can use that also. */
-void ath10k_drain_tx(struct ath10k *ar)
+static void ath10k_drain_tx(struct ath10k *ar)
{
/* make sure rcu-protected mac80211 tx path itself is drained */
synchronize_net();
@@ -2556,8 +2531,16 @@
ath10k_hif_power_down(ar);
spin_lock_bh(&ar->data_lock);
- list_for_each_entry(arvif, &ar->arvifs, list)
- ath10k_mac_vif_beacon_cleanup(arvif);
+ list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (!arvif->beacon)
+ continue;
+
+ dma_unmap_single(arvif->ar->dev,
+ ATH10K_SKB_CB(arvif->beacon)->paddr,
+ arvif->beacon->len, DMA_TO_DEVICE);
+ dev_kfree_skb_any(arvif->beacon);
+ arvif->beacon = NULL;
+ }
spin_unlock_bh(&ar->data_lock);
}
@@ -2580,28 +2563,12 @@
return 0;
}
-static void ath10k_check_chain_mask(struct ath10k *ar, u32 cm, const char *dbg)
-{
- /* It is not clear that allowing gaps in chainmask
- * is helpful. Probably it will not do what user
- * is hoping for, so warn in that case.
- */
- if (cm == 15 || cm == 7 || cm == 3 || cm == 1 || cm == 0)
- return;
-
- ath10k_warn(ar, "mac %s antenna chainmask may be invalid: 0x%x. Suggested values: 15, 7, 3, 1 or 0.\n",
- dbg, cm);
-}
-
static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
{
int ret;
lockdep_assert_held(&ar->conf_mutex);
- ath10k_check_chain_mask(ar, tx_ant, "tx");
- ath10k_check_chain_mask(ar, rx_ant, "rx");
-
ar->cfg_tx_chainmask = tx_ant;
ar->cfg_rx_chainmask = rx_ant;
@@ -2865,68 +2832,12 @@
ath10k_monitor_recalc(ar);
}
-static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower)
-{
- int ret;
- u32 param;
-
- lockdep_assert_held(&ar->conf_mutex);
-
- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac txpower %d\n", txpower);
-
- param = ar->wmi.pdev_param->txpower_limit2g;
- ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2);
- if (ret) {
- ath10k_warn(ar, "failed to set 2g txpower %d: %d\n",
- txpower, ret);
- return ret;
- }
-
- param = ar->wmi.pdev_param->txpower_limit5g;
- ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2);
- if (ret) {
- ath10k_warn(ar, "failed to set 5g txpower %d: %d\n",
- txpower, ret);
- return ret;
- }
-
- return 0;
-}
-
-static int ath10k_mac_txpower_recalc(struct ath10k *ar)
-{
- struct ath10k_vif *arvif;
- int ret, txpower = -1;
-
- lockdep_assert_held(&ar->conf_mutex);
-
- list_for_each_entry(arvif, &ar->arvifs, list) {
- WARN_ON(arvif->txpower < 0);
-
- if (txpower == -1)
- txpower = arvif->txpower;
- else
- txpower = min(txpower, arvif->txpower);
- }
-
- if (WARN_ON(txpower == -1))
- return -EINVAL;
-
- ret = ath10k_mac_txpower_setup(ar, txpower);
- if (ret) {
- ath10k_warn(ar, "failed to setup tx power %d: %d\n",
- txpower, ret);
- return ret;
- }
-
- return 0;
-}
-
static int ath10k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath10k *ar = hw->priv;
struct ieee80211_conf *conf = &hw->conf;
int ret = 0;
+ u32 param;
mutex_lock(&ar->conf_mutex);
@@ -2950,6 +2861,25 @@
}
}
+ if (changed & IEEE80211_CONF_CHANGE_POWER) {
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac config power %d\n",
+ hw->conf.power_level);
+
+ param = ar->wmi.pdev_param->txpower_limit2g;
+ ret = ath10k_wmi_pdev_set_param(ar, param,
+ hw->conf.power_level * 2);
+ if (ret)
+ ath10k_warn(ar, "failed to set 2g txpower %d: %d\n",
+ hw->conf.power_level, ret);
+
+ param = ar->wmi.pdev_param->txpower_limit5g;
+ ret = ath10k_wmi_pdev_set_param(ar, param,
+ hw->conf.power_level * 2);
+ if (ret)
+ ath10k_warn(ar, "failed to set 5g txpower %d: %d\n",
+ hw->conf.power_level, ret);
+ }
+
if (changed & IEEE80211_CONF_CHANGE_PS)
ath10k_config_ps(ar);
@@ -2964,17 +2894,6 @@
return ret;
}
-static u32 get_nss_from_chainmask(u16 chain_mask)
-{
- if ((chain_mask & 0x15) == 0x15)
- return 4;
- else if ((chain_mask & 0x7) == 0x7)
- return 3;
- else if ((chain_mask & 0x3) == 0x3)
- return 2;
- return 1;
-}
-
/*
* TODO:
* Figure out how to handle WMI_VDEV_SUBTYPE_P2P_DEVICE,
@@ -3008,12 +2927,9 @@
ret = -EBUSY;
goto err;
}
- bit = __ffs64(ar->free_vdev_map);
+ bit = ffs(ar->free_vdev_map);
- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac create vdev %i map %llx\n",
- bit, ar->free_vdev_map);
-
- arvif->vdev_id = bit;
+ arvif->vdev_id = bit - 1;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
if (ar->p2p)
@@ -3043,39 +2959,8 @@
break;
}
- /* Some firmware revisions don't wait for beacon tx completion before
- * sending another SWBA event. This could lead to hardware using old
- * (freed) beacon data in some cases, e.g. tx credit starvation
- * combined with missed TBTT. This is very very rare.
- *
- * On non-IOMMU-enabled hosts this could be a possible security issue
- * because hw could beacon some random data on the air. On
- * IOMMU-enabled hosts DMAR faults would occur in most cases and target
- * device would crash.
- *
- * Since there are no beacon tx completions (implicit nor explicit)
- * propagated to host the only workaround for this is to allocate a
- * DMA-coherent buffer for a lifetime of a vif and use it for all
- * beacon tx commands. Worst case for this approach is some beacons may
- * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap.
- */
- if (vif->type == NL80211_IFTYPE_ADHOC ||
- vif->type == NL80211_IFTYPE_AP) {
- arvif->beacon_buf = dma_zalloc_coherent(ar->dev,
- IEEE80211_MAX_FRAME_LEN,
- &arvif->beacon_paddr,
- GFP_ATOMIC);
- if (!arvif->beacon_buf) {
- ret = -ENOMEM;
- ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
- ret);
- goto err;
- }
- }
-
- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n",
- arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype,
- arvif->beacon_buf ? "single-buf" : "per-skb");
+ ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d\n",
+ arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype);
ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type,
arvif->vdev_subtype, vif->addr);
@@ -3085,7 +2970,7 @@
goto err;
}
- ar->free_vdev_map &= ~(1LL << arvif->vdev_id);
+ ar->free_vdev_map &= ~(1 << arvif->vdev_id);
list_add(&arvif->list, &ar->arvifs);
vdev_param = ar->wmi.vdev_param->def_keyid;
@@ -3107,20 +2992,6 @@
goto err_vdev_delete;
}
- if (ar->cfg_tx_chainmask) {
- u16 nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
-
- vdev_param = ar->wmi.vdev_param->nss;
- ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id, vdev_param,
- nss);
- if (ret) {
- ath10k_warn(ar, "failed to set vdev %i chainmask 0x%x, nss %i: %d\n",
- arvif->vdev_id, ar->cfg_tx_chainmask, nss,
- ret);
- goto err_vdev_delete;
- }
- }
-
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
ret = ath10k_peer_create(ar, arvif->vdev_id, vif->addr);
if (ret) {
@@ -3183,13 +3054,6 @@
goto err_peer_delete;
}
- arvif->txpower = vif->bss_conf.txpower;
- ret = ath10k_mac_txpower_recalc(ar);
- if (ret) {
- ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
- goto err_peer_delete;
- }
-
mutex_unlock(&ar->conf_mutex);
return 0;
@@ -3199,16 +3063,10 @@
err_vdev_delete:
ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
- ar->free_vdev_map |= 1LL << arvif->vdev_id;
+ ar->free_vdev_map |= 1 << arvif->vdev_id;
list_del(&arvif->list);
err:
- if (arvif->beacon_buf) {
- dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN,
- arvif->beacon_buf, arvif->beacon_paddr);
- arvif->beacon_buf = NULL;
- }
-
mutex_unlock(&ar->conf_mutex);
return ret;
@@ -3221,12 +3079,19 @@
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
int ret;
- cancel_work_sync(&arvif->wep_key_work);
-
mutex_lock(&ar->conf_mutex);
+ cancel_work_sync(&arvif->wep_key_work);
+
spin_lock_bh(&ar->data_lock);
- ath10k_mac_vif_beacon_cleanup(arvif);
+ if (arvif->beacon) {
+ dma_unmap_single(arvif->ar->dev,
+ ATH10K_SKB_CB(arvif->beacon)->paddr,
+ arvif->beacon->len, DMA_TO_DEVICE);
+ dev_kfree_skb_any(arvif->beacon);
+ arvif->beacon = NULL;
+ }
+
spin_unlock_bh(&ar->data_lock);
ret = ath10k_spectral_vif_stop(arvif);
@@ -3234,7 +3099,7 @@
ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n",
arvif->vdev_id, ret);
- ar->free_vdev_map |= 1LL << arvif->vdev_id;
+ ar->free_vdev_map |= 1 << arvif->vdev_id;
list_del(&arvif->list);
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
@@ -3358,8 +3223,54 @@
arvif->u.ap.hidden_ssid = info->hidden_ssid;
}
- if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid))
- ether_addr_copy(arvif->bssid, info->bssid);
+ /*
+ * Firmware manages AP self-peer internally so make sure to not create
+ * it in driver. Otherwise AP self-peer deletion may timeout later.
+ */
+ if (changed & BSS_CHANGED_BSSID &&
+ vif->type != NL80211_IFTYPE_AP) {
+ if (!is_zero_ether_addr(info->bssid)) {
+ ath10k_dbg(ar, ATH10K_DBG_MAC,
+ "mac vdev %d create peer %pM\n",
+ arvif->vdev_id, info->bssid);
+
+ ret = ath10k_peer_create(ar, arvif->vdev_id,
+ info->bssid);
+ if (ret)
+ ath10k_warn(ar, "failed to add peer %pM for vdev %d when changing bssid: %i\n",
+ info->bssid, arvif->vdev_id, ret);
+
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ /*
+ * this is never erased as we it for crypto key
+ * clearing; this is FW requirement
+ */
+ ether_addr_copy(arvif->bssid, info->bssid);
+
+ ath10k_dbg(ar, ATH10K_DBG_MAC,
+ "mac vdev %d start %pM\n",
+ arvif->vdev_id, info->bssid);
+
+ ret = ath10k_vdev_start(arvif);
+ if (ret) {
+ ath10k_warn(ar, "failed to start vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ goto exit;
+ }
+
+ arvif->is_started = true;
+ }
+
+ /*
+ * Mac80211 does not keep IBSS bssid when leaving IBSS,
+ * so driver need to store it. It is needed when leaving
+ * IBSS in order to remove BSSID peer.
+ */
+ if (vif->type == NL80211_IFTYPE_ADHOC)
+ memcpy(arvif->bssid, info->bssid,
+ ETH_ALEN);
+ }
+ }
if (changed & BSS_CHANGED_BEACON_ENABLED)
ath10k_control_beaconing(arvif, info);
@@ -3421,21 +3332,10 @@
ath10k_monitor_stop(ar);
ath10k_bss_assoc(hw, vif, info);
ath10k_monitor_recalc(ar);
- } else {
- ath10k_bss_disassoc(hw, vif);
}
}
- if (changed & BSS_CHANGED_TXPOWER) {
- ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev_id %i txpower %d\n",
- arvif->vdev_id, info->txpower);
-
- arvif->txpower = info->txpower;
- ret = ath10k_mac_txpower_recalc(ar);
- if (ret)
- ath10k_warn(ar, "failed to recalc tx power: %d\n", ret);
- }
-
+exit:
mutex_unlock(&ar->conf_mutex);
}
@@ -3521,10 +3421,9 @@
struct ath10k *ar = hw->priv;
mutex_lock(&ar->conf_mutex);
+ cancel_delayed_work_sync(&ar->scan.timeout);
ath10k_scan_abort(ar);
mutex_unlock(&ar->conf_mutex);
-
- cancel_delayed_work_sync(&ar->scan.timeout);
}
static void ath10k_set_key_h_def_keyidx(struct ath10k *ar,
@@ -3709,7 +3608,7 @@
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n",
sta->addr);
- err = ath10k_station_assoc(ar, arvif->vif, sta, true);
+ err = ath10k_station_assoc(ar, arvif, sta, true);
if (err)
ath10k_warn(ar, "failed to reassociate station: %pM\n",
sta->addr);
@@ -3718,37 +3617,6 @@
mutex_unlock(&ar->conf_mutex);
}
-static int ath10k_mac_inc_num_stations(struct ath10k_vif *arvif)
-{
- struct ath10k *ar = arvif->ar;
-
- lockdep_assert_held(&ar->conf_mutex);
-
- if (arvif->vdev_type != WMI_VDEV_TYPE_AP &&
- arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
- return 0;
-
- if (ar->num_stations >= ar->max_num_stations)
- return -ENOBUFS;
-
- ar->num_stations++;
-
- return 0;
-}
-
-static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif)
-{
- struct ath10k *ar = arvif->ar;
-
- lockdep_assert_held(&ar->conf_mutex);
-
- if (arvif->vdev_type != WMI_VDEV_TYPE_AP &&
- arvif->vdev_type != WMI_VDEV_TYPE_IBSS)
- return;
-
- ar->num_stations--;
-}
-
static int ath10k_sta_state(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -3758,6 +3626,7 @@
struct ath10k *ar = hw->priv;
struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv;
+ int max_num_peers;
int ret = 0;
if (old_state == IEEE80211_STA_NOTEXIST &&
@@ -3775,46 +3644,31 @@
mutex_lock(&ar->conf_mutex);
if (old_state == IEEE80211_STA_NOTEXIST &&
- new_state == IEEE80211_STA_NONE) {
+ new_state == IEEE80211_STA_NONE &&
+ vif->type != NL80211_IFTYPE_STATION) {
/*
* New station addition.
*/
- ath10k_dbg(ar, ATH10K_DBG_MAC,
- "mac vdev %d peer create %pM (new sta) sta %d / %d peer %d / %d\n",
- arvif->vdev_id, sta->addr,
- ar->num_stations + 1, ar->max_num_stations,
- ar->num_peers + 1, ar->max_num_peers);
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+ max_num_peers = TARGET_10X_NUM_PEERS_MAX - 1;
+ else
+ max_num_peers = TARGET_NUM_PEERS;
- ret = ath10k_mac_inc_num_stations(arvif);
- if (ret) {
- ath10k_warn(ar, "refusing to associate station: too many connected already (%d)\n",
- ar->max_num_stations);
+ if (ar->num_peers >= max_num_peers) {
+ ath10k_warn(ar, "number of peers exceeded: peers number %d (max peers %d)\n",
+ ar->num_peers, max_num_peers);
+ ret = -ENOBUFS;
goto exit;
}
+ ath10k_dbg(ar, ATH10K_DBG_MAC,
+ "mac vdev %d peer create %pM (new sta) num_peers %d\n",
+ arvif->vdev_id, sta->addr, ar->num_peers);
+
ret = ath10k_peer_create(ar, arvif->vdev_id, sta->addr);
- if (ret) {
+ if (ret)
ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n",
sta->addr, arvif->vdev_id, ret);
- ath10k_mac_dec_num_stations(arvif);
- goto exit;
- }
-
- if (vif->type == NL80211_IFTYPE_STATION) {
- WARN_ON(arvif->is_started);
-
- ret = ath10k_vdev_start(arvif);
- if (ret) {
- ath10k_warn(ar, "failed to start vdev %i: %d\n",
- arvif->vdev_id, ret);
- WARN_ON(ath10k_peer_delete(ar, arvif->vdev_id,
- sta->addr));
- ath10k_mac_dec_num_stations(arvif);
- goto exit;
- }
-
- arvif->is_started = true;
- }
} else if ((old_state == IEEE80211_STA_NONE &&
new_state == IEEE80211_STA_NOTEXIST)) {
/*
@@ -3823,24 +3677,13 @@
ath10k_dbg(ar, ATH10K_DBG_MAC,
"mac vdev %d peer delete %pM (sta gone)\n",
arvif->vdev_id, sta->addr);
-
- if (vif->type == NL80211_IFTYPE_STATION) {
- WARN_ON(!arvif->is_started);
-
- ret = ath10k_vdev_stop(arvif);
- if (ret)
- ath10k_warn(ar, "failed to stop vdev %i: %d\n",
- arvif->vdev_id, ret);
-
- arvif->is_started = false;
- }
-
ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr);
if (ret)
ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n",
sta->addr, arvif->vdev_id, ret);
- ath10k_mac_dec_num_stations(arvif);
+ if (vif->type == NL80211_IFTYPE_STATION)
+ ath10k_bss_disassoc(hw, vif);
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&
(vif->type == NL80211_IFTYPE_AP ||
@@ -3851,7 +3694,7 @@
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n",
sta->addr);
- ret = ath10k_station_assoc(ar, vif, sta, false);
+ ret = ath10k_station_assoc(ar, arvif, sta, false);
if (ret)
ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n",
sta->addr, arvif->vdev_id, ret);
@@ -3865,7 +3708,7 @@
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n",
sta->addr);
- ret = ath10k_station_disassoc(ar, vif, sta);
+ ret = ath10k_station_disassoc(ar, arvif, sta);
if (ret)
ath10k_warn(ar, "failed to disassociate station: %pM vdev %i: %i\n",
sta->addr, arvif->vdev_id, ret);
@@ -4029,8 +3872,6 @@
if (ret)
goto exit;
- duration = max(duration, WMI_SCAN_CHAN_MIN_TIME_MSEC);
-
memset(&arg, 0, sizeof(arg));
ath10k_wmi_start_scan_init(ar, &arg);
arg.vdev_id = arvif->vdev_id;
@@ -4075,11 +3916,10 @@
struct ath10k *ar = hw->priv;
mutex_lock(&ar->conf_mutex);
+ cancel_delayed_work_sync(&ar->scan.timeout);
ath10k_scan_abort(ar);
mutex_unlock(&ar->conf_mutex);
- cancel_delayed_work_sync(&ar->scan.timeout);
-
return 0;
}
@@ -4122,7 +3962,7 @@
ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n",
arvif->vdev_id, value);
- ret = ath10k_mac_set_frag(arvif, value);
+ ret = ath10k_mac_set_rts(arvif, value);
if (ret) {
ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n",
arvif->vdev_id, ret);
@@ -4170,9 +4010,7 @@
spin_unlock_irqrestore(&ar->wmi_mgmt_tx_queue.lock,
flags);
- skip = (ar->state == ATH10K_STATE_WEDGED) ||
- test_bit(ATH10K_FLAG_CRASH_FLUSH,
- &ar->dev_flags);
+ skip = (ar->state == ATH10K_STATE_WEDGED);
((htt_empty && wmi_empty) || skip);
}), ATH10K_FLUSH_TIMEOUT_HZ);
@@ -4314,14 +4152,10 @@
}
#endif
-static void ath10k_reconfig_complete(struct ieee80211_hw *hw,
- enum ieee80211_reconfig_type reconfig_type)
+static void ath10k_restart_complete(struct ieee80211_hw *hw)
{
struct ath10k *ar = hw->priv;
- if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
- return;
-
mutex_lock(&ar->conf_mutex);
/* If device failed to restart it will be in a different state, e.g.
@@ -4329,7 +4163,6 @@
if (ar->state == ATH10K_STATE_RESTARTED) {
ath10k_info(ar, "device successfully recovered\n");
ar->state = ATH10K_STATE_ON;
- ieee80211_wake_queues(ar->hw);
}
mutex_unlock(&ar->conf_mutex);
@@ -4365,9 +4198,6 @@
survey->channel = &sband->channels[idx];
- if (ar->rx_channel == survey->channel)
- survey->filled |= SURVEY_INFO_IN_USE;
-
exit:
mutex_unlock(&ar->conf_mutex);
return ret;
@@ -4415,10 +4245,6 @@
u32 legacy = 0x00ff;
u8 ht = 0xff, i;
u16 vht = 0x3ff;
- u16 nrf = ar->num_rf_chains;
-
- if (ar->cfg_tx_chainmask)
- nrf = get_nss_from_chainmask(ar->cfg_tx_chainmask);
switch (band) {
case IEEE80211_BAND_2GHZ:
@@ -4434,11 +4260,11 @@
if (mask->control[band].legacy != legacy)
return false;
- for (i = 0; i < nrf; i++)
+ for (i = 0; i < ar->num_rf_chains; i++)
if (mask->control[band].ht_mcs[i] != ht)
return false;
- for (i = 0; i < nrf; i++)
+ for (i = 0; i < ar->num_rf_chains; i++)
if (mask->control[band].vht_mcs[i] != vht)
return false;
@@ -4689,9 +4515,6 @@
u8 fixed_nss = ar->num_rf_chains;
u8 force_sgi;
- if (ar->cfg_tx_chainmask)
- fixed_nss = get_nss_from_chainmask(ar->cfg_tx_chainmask);
-
force_sgi = mask->control[band].gi;
if (force_sgi == NL80211_TXRATE_FORCE_LGI)
return -EINVAL;
@@ -4850,15 +4673,12 @@
.tx_last_beacon = ath10k_tx_last_beacon,
.set_antenna = ath10k_set_antenna,
.get_antenna = ath10k_get_antenna,
- .reconfig_complete = ath10k_reconfig_complete,
+ .restart_complete = ath10k_restart_complete,
.get_survey = ath10k_get_survey,
.set_bitrate_mask = ath10k_set_bitrate_mask,
.sta_rc_update = ath10k_sta_rc_update,
.get_tsf = ath10k_get_tsf,
.ampdu_action = ath10k_ampdu_action,
- .get_et_sset_count = ath10k_debug_get_et_sset_count,
- .get_et_stats = ath10k_debug_get_et_stats,
- .get_et_strings = ath10k_debug_get_et_strings,
CFG80211_TESTMODE_CMD(ath10k_tm_cmd)
@@ -5203,6 +5023,15 @@
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP);
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+ /* TODO: Have to deal with 2x2 chips if/when the come out. */
+ ar->supp_tx_chainmask = TARGET_10X_TX_CHAIN_MASK;
+ ar->supp_rx_chainmask = TARGET_10X_RX_CHAIN_MASK;
+ } else {
+ ar->supp_tx_chainmask = TARGET_TX_CHAIN_MASK;
+ ar->supp_rx_chainmask = TARGET_RX_CHAIN_MASK;
+ }
+
ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
@@ -5221,6 +5050,10 @@
IEEE80211_HW_AP_LINK_PS |
IEEE80211_HW_SPECTRUM_MGMT;
+ /* MSDU can have HTT TX fragment pushed in front. The additional 4
+ * bytes is used for padding/alignment if necessary. */
+ ar->hw->extra_tx_headroom += sizeof(struct htt_data_tx_desc_frag)*2 + 4;
+
ar->hw->wiphy->features |= NL80211_FEATURE_STATIC_SMPS;
if (ar->ht_cap_info & WMI_HT_CAP_DYNAMIC_SMPS)
@@ -5244,8 +5077,6 @@
ar->hw->wiphy->max_remain_on_channel_duration = 5000;
ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
- ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE;
-
/*
* on LL hardware queues are managed entirely by the FW
* so we only advertise to mac we can do the queues thing
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h
index 6829611..6c80eea 100644
--- a/drivers/net/wireless/ath/ath10k/mac.h
+++ b/drivers/net/wireless/ath/ath10k/mac.h
@@ -21,8 +21,6 @@
#include <net/mac80211.h>
#include "core.h"
-#define WEP_KEYID_SHIFT 6
-
struct ath10k_generic_iter {
struct ath10k *ar;
int ret;
@@ -41,10 +39,6 @@
void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar);
void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work);
void ath10k_halt(struct ath10k *ar);
-void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif);
-void ath10k_drain_tx(struct ath10k *ar);
-bool ath10k_mac_is_peer_wep_key_set(struct ath10k *ar, const u8 *addr,
- u8 keyidx);
static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif)
{
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index 7269de6..0d70674 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -490,8 +490,6 @@
void *data_buf = NULL;
int i;
- spin_lock_bh(&ar_pci->ce_lock);
-
ce_diag = ar_pci->ce_diag;
/*
@@ -518,7 +516,7 @@
nbytes = min_t(unsigned int, remaining_bytes,
DIAG_TRANSFER_LIMIT);
- ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
+ ret = ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data);
if (ret != 0)
goto done;
@@ -534,15 +532,15 @@
address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem,
address);
- ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0,
- 0);
+ ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0,
+ 0);
if (ret)
goto done;
i = 0;
- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
- &completed_nbytes,
- &id) != 0) {
+ while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
+ &completed_nbytes,
+ &id) != 0) {
mdelay(1);
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
ret = -EBUSY;
@@ -561,9 +559,9 @@
}
i = 0;
- while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
- &completed_nbytes,
- &id, &flags) != 0) {
+ while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
+ &completed_nbytes,
+ &id, &flags) != 0) {
mdelay(1);
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -598,8 +596,6 @@
dma_free_coherent(ar->dev, orig_nbytes, data_buf,
ce_data_base);
- spin_unlock_bh(&ar_pci->ce_lock);
-
return ret;
}
@@ -657,8 +653,6 @@
dma_addr_t ce_data_base = 0;
int i;
- spin_lock_bh(&ar_pci->ce_lock);
-
ce_diag = ar_pci->ce_diag;
/*
@@ -699,7 +693,7 @@
nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT);
/* Set up to receive directly into Target(!) address */
- ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address);
+ ret = ath10k_ce_rx_post_buf(ce_diag, NULL, address);
if (ret != 0)
goto done;
@@ -707,15 +701,15 @@
* Request CE to send caller-supplied data that
* was copied to bounce buffer to Target(!) address.
*/
- ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data,
- nbytes, 0, 0);
+ ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data,
+ nbytes, 0, 0);
if (ret != 0)
goto done;
i = 0;
- while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf,
- &completed_nbytes,
- &id) != 0) {
+ while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf,
+ &completed_nbytes,
+ &id) != 0) {
mdelay(1);
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -735,9 +729,9 @@
}
i = 0;
- while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf,
- &completed_nbytes,
- &id, &flags) != 0) {
+ while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf,
+ &completed_nbytes,
+ &id, &flags) != 0) {
mdelay(1);
if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) {
@@ -771,8 +765,6 @@
ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n",
address, ret);
- spin_unlock_bh(&ar_pci->ce_lock);
-
return ret;
}
@@ -828,24 +820,20 @@
struct ath10k *ar = ce_state->ar;
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
- struct sk_buff_head list;
- struct sk_buff *skb;
+ void *transfer_context;
u32 ce_data;
unsigned int nbytes;
unsigned int transfer_id;
- __skb_queue_head_init(&list);
- while (ath10k_ce_completed_send_next(ce_state, (void **)&skb, &ce_data,
- &nbytes, &transfer_id) == 0) {
+ while (ath10k_ce_completed_send_next(ce_state, &transfer_context,
+ &ce_data, &nbytes,
+ &transfer_id) == 0) {
/* no need to call tx completion for NULL pointers */
- if (skb == NULL)
+ if (transfer_context == NULL)
continue;
- __skb_queue_tail(&list, skb);
+ cb->tx_completion(ar, transfer_context, transfer_id);
}
-
- while ((skb = __skb_dequeue(&list)))
- cb->tx_completion(ar, skb);
}
/* Called by lower (CE) layer when data is received from the Target. */
@@ -856,14 +844,12 @@
struct ath10k_pci_pipe *pipe_info = &ar_pci->pipe_info[ce_state->id];
struct ath10k_hif_cb *cb = &ar_pci->msg_callbacks_current;
struct sk_buff *skb;
- struct sk_buff_head list;
void *transfer_context;
u32 ce_data;
unsigned int nbytes, max_nbytes;
unsigned int transfer_id;
unsigned int flags;
- __skb_queue_head_init(&list);
while (ath10k_ce_completed_recv_next(ce_state, &transfer_context,
&ce_data, &nbytes, &transfer_id,
&flags) == 0) {
@@ -880,16 +866,7 @@
}
skb_put(skb, nbytes);
- __skb_queue_tail(&list, skb);
- }
-
- while ((skb = __skb_dequeue(&list))) {
- ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n",
- ce_state->id, skb->len);
- ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ",
- skb->data, skb->len);
-
- cb->rx_completion(ar, skb);
+ cb->rx_completion(ar, skb, pipe_info->pipe_num);
}
ath10k_pci_rx_post_pipe(pipe_info);
@@ -964,12 +941,6 @@
return err;
}
-static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf,
- size_t buf_len)
-{
- return ath10k_pci_diag_read_mem(ar, address, buf, buf_len);
-}
-
static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe)
{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
@@ -1020,8 +991,6 @@
spin_lock_bh(&ar->data_lock);
- ar->stats.fw_crash_counter++;
-
crash_data = ath10k_debug_get_new_fw_crash_data(ar);
if (crash_data)
@@ -1160,38 +1129,15 @@
&dl_is_polled);
}
-static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar)
-{
- u32 val;
-
- val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
- val &= ~CORE_CTRL_PCIE_REG_31_MASK;
-
- ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
-}
-
-static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar)
-{
- u32 val;
-
- val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS);
- val |= CORE_CTRL_PCIE_REG_31_MASK;
-
- ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val);
-}
-
static void ath10k_pci_irq_disable(struct ath10k *ar)
{
- ath10k_ce_disable_interrupts(ar);
- ath10k_pci_disable_and_clear_legacy_irq(ar);
- ath10k_pci_irq_msi_fw_mask(ar);
-}
-
-static void ath10k_pci_irq_sync(struct ath10k *ar)
-{
struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
int i;
+ ath10k_ce_disable_interrupts(ar);
+ ath10k_pci_disable_and_clear_legacy_irq(ar);
+ /* FIXME: How to mask all MSI interrupts? */
+
for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++)
synchronize_irq(ar_pci->pdev->irq + i);
}
@@ -1200,7 +1146,7 @@
{
ath10k_ce_enable_interrupts(ar);
ath10k_pci_enable_legacy_irq(ar);
- ath10k_pci_irq_msi_fw_unmask(ar);
+ /* FIXME: How to unmask all MSI interrupts? */
}
static int ath10k_pci_hif_start(struct ath10k *ar)
@@ -1213,74 +1159,64 @@
return 0;
}
-static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
-{
- struct ath10k *ar;
- struct ath10k_ce_pipe *ce_pipe;
- struct ath10k_ce_ring *ce_ring;
- struct sk_buff *skb;
- int i;
-
- ar = pci_pipe->hif_ce_state;
- ce_pipe = pci_pipe->ce_hdl;
- ce_ring = ce_pipe->dest_ring;
-
- if (!ce_ring)
- return;
-
- if (!pci_pipe->buf_sz)
- return;
-
- for (i = 0; i < ce_ring->nentries; i++) {
- skb = ce_ring->per_transfer_context[i];
- if (!skb)
- continue;
-
- ce_ring->per_transfer_context[i] = NULL;
-
- dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr,
- skb->len + skb_tailroom(skb),
- DMA_FROM_DEVICE);
- dev_kfree_skb_any(skb);
- }
-}
-
-static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe)
+static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
{
struct ath10k *ar;
struct ath10k_pci *ar_pci;
- struct ath10k_ce_pipe *ce_pipe;
- struct ath10k_ce_ring *ce_ring;
- struct ce_desc *ce_desc;
- struct sk_buff *skb;
- unsigned int id;
- int i;
+ struct ath10k_ce_pipe *ce_hdl;
+ u32 buf_sz;
+ struct sk_buff *netbuf;
+ u32 ce_data;
- ar = pci_pipe->hif_ce_state;
+ buf_sz = pipe_info->buf_sz;
+
+ /* Unused Copy Engine */
+ if (buf_sz == 0)
+ return;
+
+ ar = pipe_info->hif_ce_state;
ar_pci = ath10k_pci_priv(ar);
- ce_pipe = pci_pipe->ce_hdl;
- ce_ring = ce_pipe->src_ring;
+ ce_hdl = pipe_info->ce_hdl;
- if (!ce_ring)
+ while (ath10k_ce_revoke_recv_next(ce_hdl, (void **)&netbuf,
+ &ce_data) == 0) {
+ dma_unmap_single(ar->dev, ATH10K_SKB_CB(netbuf)->paddr,
+ netbuf->len + skb_tailroom(netbuf),
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_any(netbuf);
+ }
+}
+
+static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info)
+{
+ struct ath10k *ar;
+ struct ath10k_pci *ar_pci;
+ struct ath10k_ce_pipe *ce_hdl;
+ struct sk_buff *netbuf;
+ u32 ce_data;
+ unsigned int nbytes;
+ unsigned int id;
+ u32 buf_sz;
+
+ buf_sz = pipe_info->buf_sz;
+
+ /* Unused Copy Engine */
+ if (buf_sz == 0)
return;
- if (!pci_pipe->buf_sz)
- return;
+ ar = pipe_info->hif_ce_state;
+ ar_pci = ath10k_pci_priv(ar);
+ ce_hdl = pipe_info->ce_hdl;
- ce_desc = ce_ring->shadow_base;
- if (WARN_ON(!ce_desc))
- return;
-
- for (i = 0; i < ce_ring->nentries; i++) {
- skb = ce_ring->per_transfer_context[i];
- if (!skb)
+ while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf,
+ &ce_data, &nbytes, &id) == 0) {
+ /* no need to call tx completion for NULL pointers */
+ if (!netbuf)
continue;
- ce_ring->per_transfer_context[i] = NULL;
- id = MS(__le16_to_cpu(ce_desc[i].flags),
- CE_DESC_FLAGS_META_DATA);
-
- ar_pci->msg_callbacks_current.tx_completion(ar, skb);
+ ar_pci->msg_callbacks_current.tx_completion(ar,
+ netbuf,
+ id);
}
}
@@ -1338,7 +1274,6 @@
ath10k_pci_warm_reset(ar);
ath10k_pci_irq_disable(ar);
- ath10k_pci_irq_sync(ar);
ath10k_pci_flush(ar);
}
@@ -1459,9 +1394,6 @@
&nbytes, &transfer_id, &flags))
return;
- if (WARN_ON_ONCE(!xfer))
- return;
-
if (!xfer->wait_for_resp) {
ath10k_warn(ar, "unexpected: BMI data received; ignoring\n");
return;
@@ -1645,40 +1577,23 @@
return 0;
}
-static int ath10k_pci_alloc_pipes(struct ath10k *ar)
+static int ath10k_pci_alloc_ce(struct ath10k *ar)
{
- struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
- struct ath10k_pci_pipe *pipe;
int i, ret;
for (i = 0; i < CE_COUNT; i++) {
- pipe = &ar_pci->pipe_info[i];
- pipe->ce_hdl = &ar_pci->ce_states[i];
- pipe->pipe_num = i;
- pipe->hif_ce_state = ar;
-
- ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i],
- ath10k_pci_ce_send_done,
- ath10k_pci_ce_recv_data);
+ ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]);
if (ret) {
ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n",
i, ret);
return ret;
}
-
- /* Last CE is Diagnostic Window */
- if (i == CE_COUNT - 1) {
- ar_pci->ce_diag = pipe->ce_hdl;
- continue;
- }
-
- pipe->buf_sz = (size_t)(host_ce_config_wlan[i].src_sz_max);
}
return 0;
}
-static void ath10k_pci_free_pipes(struct ath10k *ar)
+static void ath10k_pci_free_ce(struct ath10k *ar)
{
int i;
@@ -1686,17 +1601,39 @@
ath10k_ce_free_pipe(ar, i);
}
-static int ath10k_pci_init_pipes(struct ath10k *ar)
+static int ath10k_pci_ce_init(struct ath10k *ar)
{
- int i, ret;
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ struct ath10k_pci_pipe *pipe_info;
+ const struct ce_attr *attr;
+ int pipe_num, ret;
- for (i = 0; i < CE_COUNT; i++) {
- ret = ath10k_ce_init_pipe(ar, i, &host_ce_config_wlan[i]);
+ for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) {
+ pipe_info = &ar_pci->pipe_info[pipe_num];
+ pipe_info->ce_hdl = &ar_pci->ce_states[pipe_num];
+ pipe_info->pipe_num = pipe_num;
+ pipe_info->hif_ce_state = ar;
+ attr = &host_ce_config_wlan[pipe_num];
+
+ ret = ath10k_ce_init_pipe(ar, pipe_num, attr,
+ ath10k_pci_ce_send_done,
+ ath10k_pci_ce_recv_data);
if (ret) {
ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n",
- i, ret);
+ pipe_num, ret);
return ret;
}
+
+ if (pipe_num == CE_COUNT - 1) {
+ /*
+ * Reserve the ultimate CE for
+ * diagnostic Window support
+ */
+ ar_pci->ce_diag = pipe_info->ce_hdl;
+ continue;
+ }
+
+ pipe_info->buf_sz = (size_t)(attr->src_sz_max);
}
return 0;
@@ -1737,167 +1674,93 @@
msleep(10);
}
-static void ath10k_pci_warm_reset_cpu(struct ath10k *ar)
+static int ath10k_pci_warm_reset(struct ath10k *ar)
{
u32 val;
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
+
+ /* debug */
+ val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+ PCIE_INTR_CAUSE_ADDRESS);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n",
+ val);
+
+ val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+ CPU_INTR_ADDRESS);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
+ val);
+
+ /* disable pending irqs */
+ ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+ PCIE_INTR_ENABLE_ADDRESS, 0);
+
+ ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+ PCIE_INTR_CLR_ADDRESS, ~0);
+
+ msleep(100);
+
+ /* clear fw indicator */
ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0);
- val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
- SOC_RESET_CONTROL_ADDRESS);
- ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
- val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
-}
-
-static void ath10k_pci_warm_reset_ce(struct ath10k *ar)
-{
- u32 val;
-
- val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
- SOC_RESET_CONTROL_ADDRESS);
-
- ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
- val | SOC_RESET_CONTROL_CE_RST_MASK);
- msleep(10);
- ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
- val & ~SOC_RESET_CONTROL_CE_RST_MASK);
-}
-
-static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar)
-{
- u32 val;
-
+ /* clear target LF timer interrupts */
val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
SOC_LF_TIMER_CONTROL0_ADDRESS);
ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS +
SOC_LF_TIMER_CONTROL0_ADDRESS,
val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK);
-}
-static int ath10k_pci_warm_reset(struct ath10k *ar)
-{
- int ret;
+ /* reset CE */
+ val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+ SOC_RESET_CONTROL_ADDRESS);
+ ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
+ val | SOC_RESET_CONTROL_CE_RST_MASK);
+ val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+ SOC_RESET_CONTROL_ADDRESS);
+ msleep(10);
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n");
+ /* unreset CE */
+ ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
+ val & ~SOC_RESET_CONTROL_CE_RST_MASK);
+ val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+ SOC_RESET_CONTROL_ADDRESS);
+ msleep(10);
- spin_lock_bh(&ar->data_lock);
- ar->stats.fw_warm_reset_counter++;
- spin_unlock_bh(&ar->data_lock);
-
- ath10k_pci_irq_disable(ar);
-
- /* Make sure the target CPU is not doing anything dangerous, e.g. if it
- * were to access copy engine while host performs copy engine reset
- * then it is possible for the device to confuse pci-e controller to
- * the point of bringing host system to a complete stop (i.e. hang).
- */
ath10k_pci_warm_reset_si0(ar);
- ath10k_pci_warm_reset_cpu(ar);
- ath10k_pci_init_pipes(ar);
- ath10k_pci_wait_for_target_init(ar);
- ath10k_pci_warm_reset_clear_lf(ar);
- ath10k_pci_warm_reset_ce(ar);
- ath10k_pci_warm_reset_cpu(ar);
- ath10k_pci_init_pipes(ar);
+ /* debug */
+ val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+ PCIE_INTR_CAUSE_ADDRESS);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n",
+ val);
- ret = ath10k_pci_wait_for_target_init(ar);
- if (ret) {
- ath10k_warn(ar, "failed to wait for target init: %d\n", ret);
- return ret;
- }
+ val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
+ CPU_INTR_ADDRESS);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n",
+ val);
+
+ /* CPU warm reset */
+ val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+ SOC_RESET_CONTROL_ADDRESS);
+ ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS,
+ val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK);
+
+ val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS +
+ SOC_RESET_CONTROL_ADDRESS);
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target reset state: 0x%08x\n",
+ val);
+
+ msleep(100);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n");
return 0;
}
-static int ath10k_pci_chip_reset(struct ath10k *ar)
-{
- int i, ret;
- u32 val;
-
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset\n");
-
- /* Some hardware revisions (e.g. CUS223v2) has issues with cold reset.
- * It is thus preferred to use warm reset which is safer but may not be
- * able to recover the device from all possible fail scenarios.
- *
- * Warm reset doesn't always work on first try so attempt it a few
- * times before giving up.
- */
- for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) {
- ret = ath10k_pci_warm_reset(ar);
- if (ret) {
- ath10k_warn(ar, "failed to warm reset attempt %d of %d: %d\n",
- i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS,
- ret);
- continue;
- }
-
- /* FIXME: Sometimes copy engine doesn't recover after warm
- * reset. In most cases this needs cold reset. In some of these
- * cases the device is in such a state that a cold reset may
- * lock up the host.
- *
- * Reading any host interest register via copy engine is
- * sufficient to verify if device is capable of booting
- * firmware blob.
- */
- ret = ath10k_pci_init_pipes(ar);
- if (ret) {
- ath10k_warn(ar, "failed to init copy engine: %d\n",
- ret);
- continue;
- }
-
- ret = ath10k_pci_diag_read32(ar, QCA988X_HOST_INTEREST_ADDRESS,
- &val);
- if (ret) {
- ath10k_warn(ar, "failed to poke copy engine: %d\n",
- ret);
- continue;
- }
-
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (warm)\n");
- return 0;
- }
-
- if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY) {
- ath10k_warn(ar, "refusing cold reset as requested\n");
- return -EPERM;
- }
-
- ret = ath10k_pci_cold_reset(ar);
- if (ret) {
- ath10k_warn(ar, "failed to cold reset: %d\n", ret);
- return ret;
- }
-
- ret = ath10k_pci_wait_for_target_init(ar);
- if (ret) {
- ath10k_warn(ar, "failed to wait for target after cold reset: %d\n",
- ret);
- return ret;
- }
-
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (cold)\n");
-
- return 0;
-}
-
-static int ath10k_pci_hif_power_up(struct ath10k *ar)
+static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset)
{
int ret;
- ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n");
-
- ret = ath10k_pci_wake(ar);
- if (ret) {
- ath10k_err(ar, "failed to wake up target: %d\n", ret);
- return ret;
- }
-
/*
* Bring the target up cleanly.
*
@@ -1908,16 +1771,26 @@
* is in an unexpected state. We try to catch that here in order to
* reset the Target and retry the probe.
*/
- ret = ath10k_pci_chip_reset(ar);
+ if (cold_reset)
+ ret = ath10k_pci_cold_reset(ar);
+ else
+ ret = ath10k_pci_warm_reset(ar);
+
if (ret) {
- ath10k_err(ar, "failed to reset chip: %d\n", ret);
- goto err_sleep;
+ ath10k_err(ar, "failed to reset target: %d\n", ret);
+ goto err;
}
- ret = ath10k_pci_init_pipes(ar);
+ ret = ath10k_pci_ce_init(ar);
if (ret) {
ath10k_err(ar, "failed to initialize CE: %d\n", ret);
- goto err_sleep;
+ goto err;
+ }
+
+ ret = ath10k_pci_wait_for_target_init(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to wait for target to init: %d\n", ret);
+ goto err_ce;
}
ret = ath10k_pci_init_config(ar);
@@ -1936,21 +1809,73 @@
err_ce:
ath10k_pci_ce_deinit(ar);
-
-err_sleep:
- ath10k_pci_sleep(ar);
+ ath10k_pci_warm_reset(ar);
+err:
return ret;
}
+static int ath10k_pci_hif_power_up_warm(struct ath10k *ar)
+{
+ int i, ret;
+
+ /*
+ * Sometime warm reset succeeds after retries.
+ *
+ * FIXME: It might be possible to tune ath10k_pci_warm_reset() to work
+ * at first try.
+ */
+ for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) {
+ ret = __ath10k_pci_hif_power_up(ar, false);
+ if (ret == 0)
+ break;
+
+ ath10k_warn(ar, "failed to warm reset (attempt %d out of %d): %d\n",
+ i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, ret);
+ }
+
+ return ret;
+}
+
+static int ath10k_pci_hif_power_up(struct ath10k *ar)
+{
+ int ret;
+
+ ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n");
+
+ /*
+ * Hardware CUS232 version 2 has some issues with cold reset and the
+ * preferred (and safer) way to perform a device reset is through a
+ * warm reset.
+ *
+ * Warm reset doesn't always work though so fall back to cold reset may
+ * be necessary.
+ */
+ ret = ath10k_pci_hif_power_up_warm(ar);
+ if (ret) {
+ ath10k_warn(ar, "failed to power up target using warm reset: %d\n",
+ ret);
+
+ if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY)
+ return ret;
+
+ ath10k_warn(ar, "trying cold reset\n");
+
+ ret = __ath10k_pci_hif_power_up(ar, true);
+ if (ret) {
+ ath10k_err(ar, "failed to power up target using cold reset too (%d)\n",
+ ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static void ath10k_pci_hif_power_down(struct ath10k *ar)
{
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n");
- /* Currently hif_power_up performs effectively a reset and hif_stop
- * resets the chip as well so there's no point in resetting here.
- */
-
- ath10k_pci_sleep(ar);
+ ath10k_pci_warm_reset(ar);
}
#ifdef CONFIG_PM
@@ -2004,8 +1929,6 @@
static const struct ath10k_hif_ops ath10k_pci_hif_ops = {
.tx_sg = ath10k_pci_hif_tx_sg,
- .diag_read = ath10k_pci_hif_diag_read,
- .diag_write = ath10k_pci_diag_write_mem,
.exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg,
.start = ath10k_pci_hif_start,
.stop = ath10k_pci_hif_stop,
@@ -2016,8 +1939,6 @@
.get_free_queue_number = ath10k_pci_hif_get_free_queue_number,
.power_up = ath10k_pci_hif_power_up,
.power_down = ath10k_pci_hif_power_down,
- .read32 = ath10k_pci_read32,
- .write32 = ath10k_pci_write32,
#ifdef CONFIG_PM
.suspend = ath10k_pci_hif_suspend,
.resume = ath10k_pci_hif_resume,
@@ -2337,14 +2258,14 @@
if (ar_pci->num_msi_intrs == 0)
/* Fix potential race by repeating CORE_BASE writes */
- ath10k_pci_enable_legacy_irq(ar);
+ ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS +
+ PCIE_INTR_ENABLE_ADDRESS,
+ PCIE_INTR_FIRMWARE_MASK |
+ PCIE_INTR_CE_MASK_ALL);
mdelay(10);
} while (time_before(jiffies, timeout));
- ath10k_pci_disable_and_clear_legacy_irq(ar);
- ath10k_pci_irq_msi_fw_mask(ar);
-
if (val == 0xffffffff) {
ath10k_err(ar, "failed to read device register, device is gone\n");
return -EIO;
@@ -2374,12 +2295,6 @@
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n");
- spin_lock_bh(&ar->data_lock);
-
- ar->stats.fw_cold_reset_counter++;
-
- spin_unlock_bh(&ar->data_lock);
-
/* Put Target, including PCIe, into RESET. */
val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS);
val |= 1;
@@ -2493,7 +2408,6 @@
u32 chip_id;
ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev,
- ATH10K_BUS_PCI,
&ath10k_pci_hif_ops);
if (!ar) {
dev_err(&pdev->dev, "failed to allocate core\n");
@@ -2529,7 +2443,7 @@
goto err_sleep;
}
- ret = ath10k_pci_alloc_pipes(ar);
+ ret = ath10k_pci_alloc_ce(ar);
if (ret) {
ath10k_err(ar, "failed to allocate copy engine pipes: %d\n",
ret);
@@ -2537,12 +2451,25 @@
}
ath10k_pci_ce_deinit(ar);
- ath10k_pci_irq_disable(ar);
+
+ ret = ath10k_ce_disable_interrupts(ar);
+ if (ret) {
+ ath10k_err(ar, "failed to disable copy engine interrupts: %d\n",
+ ret);
+ goto err_free_ce;
+ }
+
+ /* Workaround: There's no known way to mask all possible interrupts via
+ * device CSR. The only way to make sure device doesn't assert
+ * interrupts is to reset it. Interrupts are then disabled on host
+ * after handlers are registered.
+ */
+ ath10k_pci_warm_reset(ar);
ret = ath10k_pci_init_irq(ar);
if (ret) {
ath10k_err(ar, "failed to init irqs: %d\n", ret);
- goto err_free_pipes;
+ goto err_free_ce;
}
ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n",
@@ -2555,7 +2482,8 @@
goto err_deinit_irq;
}
- ath10k_pci_sleep(ar);
+ /* This shouldn't race as the device has been reset above. */
+ ath10k_pci_irq_disable(ar);
ret = ath10k_core_register(ar, chip_id);
if (ret) {
@@ -2572,8 +2500,8 @@
err_deinit_irq:
ath10k_pci_deinit_irq(ar);
-err_free_pipes:
- ath10k_pci_free_pipes(ar);
+err_free_ce:
+ ath10k_pci_free_ce(ar);
err_sleep:
ath10k_pci_sleep(ar);
@@ -2607,7 +2535,8 @@
ath10k_pci_kill_tasklet(ar);
ath10k_pci_deinit_irq(ar);
ath10k_pci_ce_deinit(ar);
- ath10k_pci_free_pipes(ar);
+ ath10k_pci_free_ce(ar);
+ ath10k_pci_sleep(ar);
ath10k_pci_release(ar);
ath10k_core_destroy(ar);
}
@@ -2644,7 +2573,5 @@
MODULE_AUTHOR("Qualcomm Atheros");
MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE);
-MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE);
-MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE);
+MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_3_FILE);
MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
index 127c8df..f45b90f 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.c
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -56,14 +56,14 @@
}
int ath10k_spectral_process_fft(struct ath10k *ar,
- const struct wmi_phyerr *phyerr,
- const struct phyerr_fft_report *fftr,
+ struct wmi_single_phyerr_rx_event *event,
+ struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf)
{
struct fft_sample_ath10k *fft_sample;
u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS];
u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag;
- u32 reg0, reg1;
+ u32 reg0, reg1, nf_list1, nf_list2;
u8 chain_idx, *bins;
int dc_pos;
@@ -82,7 +82,7 @@
/* TODO: there might be a reason why the hardware reports 20/40/80 MHz,
* but the results/plots suggest that its actually 22/44/88 MHz.
*/
- switch (phyerr->chan_width_mhz) {
+ switch (event->hdr.chan_width_mhz) {
case 20:
fft_sample->chan_width_mhz = 22;
break;
@@ -101,7 +101,7 @@
fft_sample->chan_width_mhz = 88;
break;
default:
- fft_sample->chan_width_mhz = phyerr->chan_width_mhz;
+ fft_sample->chan_width_mhz = event->hdr.chan_width_mhz;
}
fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB);
@@ -110,22 +110,36 @@
peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG);
fft_sample->max_magnitude = __cpu_to_be16(peak_mag);
fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX);
- fft_sample->rssi = phyerr->rssi_combined;
+ fft_sample->rssi = event->hdr.rssi_combined;
total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB);
base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB);
fft_sample->total_gain_db = __cpu_to_be16(total_gain_db);
fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db);
- freq1 = __le16_to_cpu(phyerr->freq1);
- freq2 = __le16_to_cpu(phyerr->freq2);
+ freq1 = __le16_to_cpu(event->hdr.freq1);
+ freq2 = __le16_to_cpu(event->hdr.freq2);
fft_sample->freq1 = __cpu_to_be16(freq1);
fft_sample->freq2 = __cpu_to_be16(freq2);
+ nf_list1 = __le32_to_cpu(event->hdr.nf_list_1);
+ nf_list2 = __le32_to_cpu(event->hdr.nf_list_2);
chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX);
- fft_sample->noise = __cpu_to_be16(
- __le16_to_cpu(phyerr->nf_chains[chain_idx]));
+ switch (chain_idx) {
+ case 0:
+ fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu);
+ break;
+ case 1:
+ fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu);
+ break;
+ case 2:
+ fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu);
+ break;
+ case 3:
+ fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu);
+ break;
+ }
bins = (u8 *)fftr;
bins += sizeof(*fftr);
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h
index 918a1d3..ee20232 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.h
+++ b/drivers/net/wireless/ath/ath10k/spectral.h
@@ -47,8 +47,8 @@
#ifdef CPTCFG_ATH10K_DEBUGFS
int ath10k_spectral_process_fft(struct ath10k *ar,
- const struct wmi_phyerr *phyerr,
- const struct phyerr_fft_report *fftr,
+ struct wmi_single_phyerr_rx_event *event,
+ struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf);
int ath10k_spectral_start(struct ath10k *ar);
int ath10k_spectral_vif_stop(struct ath10k_vif *arvif);
@@ -59,8 +59,8 @@
static inline int
ath10k_spectral_process_fft(struct ath10k *ar,
- const struct wmi_phyerr *phyerr,
- const struct phyerr_fft_report *fftr,
+ struct wmi_single_phyerr_rx_event *event,
+ struct phyerr_fft_report *fftr,
size_t bin_len, u64 tsf)
{
return 0;
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h
index b3bba04..31fe5cd 100644
--- a/drivers/net/wireless/ath/ath10k/trace.h
+++ b/drivers/net/wireless/ath/ath10k/trace.h
@@ -20,15 +20,6 @@
#include <linux/tracepoint.h>
#include "core.h"
-#if !defined(_TRACE_H_)
-static inline u32 ath10k_frm_hdr_len(const void *buf)
-{
- const struct ieee80211_hdr *hdr = buf;
-
- return ieee80211_hdrlen(hdr->frame_control);
-}
-#endif
-
#define _TRACE_H_
/* create empty functions when tracing is disabled */
@@ -147,8 +138,7 @@
);
TRACE_EVENT(ath10k_wmi_cmd,
- TP_PROTO(struct ath10k *ar, int id, const void *buf, size_t buf_len,
- int ret),
+ TP_PROTO(struct ath10k *ar, int id, void *buf, size_t buf_len, int ret),
TP_ARGS(ar, id, buf, buf_len, ret),
@@ -181,7 +171,7 @@
);
TRACE_EVENT(ath10k_wmi_event,
- TP_PROTO(struct ath10k *ar, int id, const void *buf, size_t buf_len),
+ TP_PROTO(struct ath10k *ar, int id, void *buf, size_t buf_len),
TP_ARGS(ar, id, buf, buf_len),
@@ -211,7 +201,7 @@
);
TRACE_EVENT(ath10k_htt_stats,
- TP_PROTO(struct ath10k *ar, const void *buf, size_t buf_len),
+ TP_PROTO(struct ath10k *ar, void *buf, size_t buf_len),
TP_ARGS(ar, buf, buf_len),
@@ -238,7 +228,7 @@
);
TRACE_EVENT(ath10k_wmi_dbglog,
- TP_PROTO(struct ath10k *ar, const void *buf, size_t buf_len),
+ TP_PROTO(struct ath10k *ar, void *buf, size_t buf_len),
TP_ARGS(ar, buf, buf_len),
@@ -264,195 +254,6 @@
)
);
-TRACE_EVENT(ath10k_htt_pktlog,
- TP_PROTO(struct ath10k *ar, const void *buf, u16 buf_len),
-
- TP_ARGS(ar, buf, buf_len),
-
- TP_STRUCT__entry(
- __string(device, dev_name(ar->dev))
- __string(driver, dev_driver_string(ar->dev))
- __field(u16, buf_len)
- __dynamic_array(u8, pktlog, buf_len)
- ),
-
- TP_fast_assign(
- __assign_str(device, dev_name(ar->dev));
- __assign_str(driver, dev_driver_string(ar->dev));
- __entry->buf_len = buf_len;
- memcpy(__get_dynamic_array(pktlog), buf, buf_len);
- ),
-
- TP_printk(
- "%s %s size %hu",
- __get_str(driver),
- __get_str(device),
- __entry->buf_len
- )
-);
-
-TRACE_EVENT(ath10k_htt_tx,
- TP_PROTO(struct ath10k *ar, u16 msdu_id, u16 msdu_len,
- u8 vdev_id, u8 tid),
-
- TP_ARGS(ar, msdu_id, msdu_len, vdev_id, tid),
-
- TP_STRUCT__entry(
- __string(device, dev_name(ar->dev))
- __string(driver, dev_driver_string(ar->dev))
- __field(u16, msdu_id)
- __field(u16, msdu_len)
- __field(u8, vdev_id)
- __field(u8, tid)
- ),
-
- TP_fast_assign(
- __assign_str(device, dev_name(ar->dev));
- __assign_str(driver, dev_driver_string(ar->dev));
- __entry->msdu_id = msdu_id;
- __entry->msdu_len = msdu_len;
- __entry->vdev_id = vdev_id;
- __entry->tid = tid;
- ),
-
- TP_printk(
- "%s %s msdu_id %d msdu_len %d vdev_id %d tid %d",
- __get_str(driver),
- __get_str(device),
- __entry->msdu_id,
- __entry->msdu_len,
- __entry->vdev_id,
- __entry->tid
- )
-);
-
-TRACE_EVENT(ath10k_txrx_tx_unref,
- TP_PROTO(struct ath10k *ar, u16 msdu_id),
-
- TP_ARGS(ar, msdu_id),
-
- TP_STRUCT__entry(
- __string(device, dev_name(ar->dev))
- __string(driver, dev_driver_string(ar->dev))
- __field(u16, msdu_id)
- ),
-
- TP_fast_assign(
- __assign_str(device, dev_name(ar->dev));
- __assign_str(driver, dev_driver_string(ar->dev));
- __entry->msdu_id = msdu_id;
- ),
-
- TP_printk(
- "%s %s msdu_id %d",
- __get_str(driver),
- __get_str(device),
- __entry->msdu_id
- )
-);
-
-DECLARE_EVENT_CLASS(ath10k_hdr_event,
- TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-
- TP_ARGS(ar, data, len),
-
- TP_STRUCT__entry(
- __string(device, dev_name(ar->dev))
- __string(driver, dev_driver_string(ar->dev))
- __field(size_t, len)
- __dynamic_array(u8, data, ath10k_frm_hdr_len(data))
- ),
-
- TP_fast_assign(
- __assign_str(device, dev_name(ar->dev));
- __assign_str(driver, dev_driver_string(ar->dev));
- __entry->len = ath10k_frm_hdr_len(data);
- memcpy(__get_dynamic_array(data), data, __entry->len);
- ),
-
- TP_printk(
- "%s %s len %zu\n",
- __get_str(driver),
- __get_str(device),
- __entry->len
- )
-);
-
-DECLARE_EVENT_CLASS(ath10k_payload_event,
- TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-
- TP_ARGS(ar, data, len),
-
- TP_STRUCT__entry(
- __string(device, dev_name(ar->dev))
- __string(driver, dev_driver_string(ar->dev))
- __field(size_t, len)
- __dynamic_array(u8, payload, (len - ath10k_frm_hdr_len(data)))
- ),
-
- TP_fast_assign(
- __assign_str(device, dev_name(ar->dev));
- __assign_str(driver, dev_driver_string(ar->dev));
- __entry->len = len - ath10k_frm_hdr_len(data);
- memcpy(__get_dynamic_array(payload),
- data + ath10k_frm_hdr_len(data), __entry->len);
- ),
-
- TP_printk(
- "%s %s len %zu\n",
- __get_str(driver),
- __get_str(device),
- __entry->len
- )
-);
-
-DEFINE_EVENT(ath10k_hdr_event, ath10k_tx_hdr,
- TP_PROTO(struct ath10k *ar, const void *data, size_t len),
- TP_ARGS(ar, data, len)
-);
-
-DEFINE_EVENT(ath10k_payload_event, ath10k_tx_payload,
- TP_PROTO(struct ath10k *ar, const void *data, size_t len),
- TP_ARGS(ar, data, len)
-);
-
-DEFINE_EVENT(ath10k_hdr_event, ath10k_rx_hdr,
- TP_PROTO(struct ath10k *ar, const void *data, size_t len),
- TP_ARGS(ar, data, len)
-);
-
-DEFINE_EVENT(ath10k_payload_event, ath10k_rx_payload,
- TP_PROTO(struct ath10k *ar, const void *data, size_t len),
- TP_ARGS(ar, data, len)
-);
-
-TRACE_EVENT(ath10k_htt_rx_desc,
- TP_PROTO(struct ath10k *ar, const void *data, size_t len),
-
- TP_ARGS(ar, data, len),
-
- TP_STRUCT__entry(
- __string(device, dev_name(ar->dev))
- __string(driver, dev_driver_string(ar->dev))
- __field(u16, len)
- __dynamic_array(u8, rxdesc, len)
- ),
-
- TP_fast_assign(
- __assign_str(device, dev_name(ar->dev));
- __assign_str(driver, dev_driver_string(ar->dev));
- __entry->len = len;
- memcpy(__get_dynamic_array(rxdesc), data, len);
- ),
-
- TP_printk(
- "%s %s rxdesc len %d",
- __get_str(driver),
- __get_str(device),
- __entry->len
- )
-);
-
#endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/
/* we don't want to use include/trace/events */
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c
index 2f774c6..7c16b8b 100644
--- a/drivers/net/wireless/ath/ath10k/txrx.c
+++ b/drivers/net/wireless/ath/ath10k/txrx.c
@@ -84,7 +84,6 @@
info = IEEE80211_SKB_CB(msdu);
memset(&info->status, 0, sizeof(info->status));
- trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id);
if (tx_done->discard) {
ieee80211_free_txskb(htt->ar->hw, msdu);
@@ -149,8 +148,7 @@
ATH10K_MAX_NUM_PEER_IDS);
spin_unlock_bh(&ar->data_lock);
- (mapped == expect_mapped ||
- test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags));
+ mapped == expect_mapped;
}), 3*HZ);
if (ret <= 0)
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index a769d15..fd39c22 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -609,40 +609,6 @@
.gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID,
};
-static void
-ath10k_wmi_put_wmi_channel(struct wmi_channel *ch,
- const struct wmi_channel_arg *arg)
-{
- u32 flags = 0;
-
- memset(ch, 0, sizeof(*ch));
-
- if (arg->passive)
- flags |= WMI_CHAN_FLAG_PASSIVE;
- if (arg->allow_ibss)
- flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED;
- if (arg->allow_ht)
- flags |= WMI_CHAN_FLAG_ALLOW_HT;
- if (arg->allow_vht)
- flags |= WMI_CHAN_FLAG_ALLOW_VHT;
- if (arg->ht40plus)
- flags |= WMI_CHAN_FLAG_HT40_PLUS;
- if (arg->chan_radar)
- flags |= WMI_CHAN_FLAG_DFS;
-
- ch->mhz = __cpu_to_le32(arg->freq);
- ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1);
- ch->band_center_freq2 = 0;
- ch->min_power = arg->min_power;
- ch->max_power = arg->max_power;
- ch->reg_power = arg->max_reg_power;
- ch->antenna_max = arg->max_antenna_gain;
-
- /* mode & flags share storage */
- ch->mode = arg->mode;
- ch->flags |= __cpu_to_le32(flags);
-}
-
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar)
{
int ret;
@@ -781,10 +747,6 @@
ath10k_wmi_tx_beacons_nowait(ar);
ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id);
-
- if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags))
- ret = -ESHUTDOWN;
-
(ret != -EAGAIN);
}), 3*HZ);
@@ -839,8 +801,6 @@
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n",
wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE,
fc & IEEE80211_FCTL_STYPE);
- trace_ath10k_tx_hdr(ar, skb->data, skb->len);
- trace_ath10k_tx_payload(ar, skb->data, skb->len);
/* Send the management frame buffer to the target */
ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid);
@@ -1110,46 +1070,13 @@
return rate_idx;
}
-/* If keys are configured, HW decrypts all frames
- * with protected bit set. Mark such frames as decrypted.
- */
-static void ath10k_wmi_handle_wep_reauth(struct ath10k *ar,
- struct sk_buff *skb,
- struct ieee80211_rx_status *status)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- unsigned int hdrlen;
- bool peer_key;
- u8 *addr, keyidx;
-
- if (!ieee80211_is_auth(hdr->frame_control) ||
- !ieee80211_has_protected(hdr->frame_control))
- return;
-
- hdrlen = ieee80211_hdrlen(hdr->frame_control);
- if (skb->len < (hdrlen + IEEE80211_WEP_IV_LEN))
- return;
-
- keyidx = skb->data[hdrlen + (IEEE80211_WEP_IV_LEN - 1)] >> WEP_KEYID_SHIFT;
- addr = ieee80211_get_SA(hdr);
-
- spin_lock_bh(&ar->data_lock);
- peer_key = ath10k_mac_is_peer_wep_key_set(ar, addr, keyidx);
- spin_unlock_bh(&ar->data_lock);
-
- if (peer_key) {
- ath10k_dbg(ar, ATH10K_DBG_MAC,
- "mac wep key present for peer %pM\n", addr);
- status->flag |= RX_FLAG_DECRYPTED;
- }
-}
-
static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_mgmt_rx_event_v1 *ev_v1;
struct wmi_mgmt_rx_event_v2 *ev_v2;
struct wmi_mgmt_rx_hdr_v1 *ev_hdr;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+ struct ieee80211_channel *ch;
struct ieee80211_hdr *hdr;
u32 rx_status;
u32 channel;
@@ -1197,33 +1124,29 @@
return 0;
}
- if (rx_status & WMI_RX_STATUS_ERR_CRC) {
- dev_kfree_skb(skb);
- return 0;
- }
-
+ if (rx_status & WMI_RX_STATUS_ERR_CRC)
+ status->flag |= RX_FLAG_FAILED_FCS_CRC;
if (rx_status & WMI_RX_STATUS_ERR_MIC)
status->flag |= RX_FLAG_MMIC_ERROR;
- /* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to
+ /* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to
* MODE_11B. This means phy_mode is not a reliable source for the band
- * of mgmt rx.
- */
- if (channel >= 1 && channel <= 14) {
- status->band = IEEE80211_BAND_2GHZ;
- } else if (channel >= 36 && channel <= 165) {
- status->band = IEEE80211_BAND_5GHZ;
- } else {
- /* Shouldn't happen unless list of advertised channels to
- * mac80211 has been changed.
- */
- WARN_ON_ONCE(1);
- dev_kfree_skb(skb);
- return 0;
- }
+ * of mgmt rx. */
- if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ)
- ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n");
+ ch = ar->scan_channel;
+ if (!ch)
+ ch = ar->rx_channel;
+
+ if (ch) {
+ status->band = ch->band;
+
+ if (phy_mode == MODE_11B &&
+ status->band == IEEE80211_BAND_5GHZ)
+ ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n");
+ } else {
+ ath10k_warn(ar, "using (unreliable) phy_mode to extract band for mgmt rx\n");
+ status->band = phy_mode_to_band(phy_mode);
+ }
status->freq = ieee80211_channel_to_frequency(channel, status->band);
status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR;
@@ -1234,8 +1157,6 @@
hdr = (struct ieee80211_hdr *)skb->data;
fc = le16_to_cpu(hdr->frame_control);
- ath10k_wmi_handle_wep_reauth(ar, skb, status);
-
/* FW delivers WEP Shared Auth frame with Protected Bit set and
* encrypted payload. However in case of PMF it delivers decrypted
* frames with Protected Bit set. */
@@ -1371,196 +1292,14 @@
return 0;
}
-static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src,
- struct ath10k_fw_stats_pdev *dst)
-{
- const struct wal_dbg_tx_stats *tx = &src->wal.tx;
- const struct wal_dbg_rx_stats *rx = &src->wal.rx;
-
- dst->ch_noise_floor = __le32_to_cpu(src->chan_nf);
- dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count);
- dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count);
- dst->rx_clear_count = __le32_to_cpu(src->rx_clear_count);
- dst->cycle_count = __le32_to_cpu(src->cycle_count);
- dst->phy_err_count = __le32_to_cpu(src->phy_err_count);
- dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr);
-
- dst->comp_queued = __le32_to_cpu(tx->comp_queued);
- dst->comp_delivered = __le32_to_cpu(tx->comp_delivered);
- dst->msdu_enqued = __le32_to_cpu(tx->msdu_enqued);
- dst->mpdu_enqued = __le32_to_cpu(tx->mpdu_enqued);
- dst->wmm_drop = __le32_to_cpu(tx->wmm_drop);
- dst->local_enqued = __le32_to_cpu(tx->local_enqued);
- dst->local_freed = __le32_to_cpu(tx->local_freed);
- dst->hw_queued = __le32_to_cpu(tx->hw_queued);
- dst->hw_reaped = __le32_to_cpu(tx->hw_reaped);
- dst->underrun = __le32_to_cpu(tx->underrun);
- dst->tx_abort = __le32_to_cpu(tx->tx_abort);
- dst->mpdus_requed = __le32_to_cpu(tx->mpdus_requed);
- dst->tx_ko = __le32_to_cpu(tx->tx_ko);
- dst->data_rc = __le32_to_cpu(tx->data_rc);
- dst->self_triggers = __le32_to_cpu(tx->self_triggers);
- dst->sw_retry_failure = __le32_to_cpu(tx->sw_retry_failure);
- dst->illgl_rate_phy_err = __le32_to_cpu(tx->illgl_rate_phy_err);
- dst->pdev_cont_xretry = __le32_to_cpu(tx->pdev_cont_xretry);
- dst->pdev_tx_timeout = __le32_to_cpu(tx->pdev_tx_timeout);
- dst->pdev_resets = __le32_to_cpu(tx->pdev_resets);
- dst->phy_underrun = __le32_to_cpu(tx->phy_underrun);
- dst->txop_ovf = __le32_to_cpu(tx->txop_ovf);
-
- dst->mid_ppdu_route_change = __le32_to_cpu(rx->mid_ppdu_route_change);
- dst->status_rcvd = __le32_to_cpu(rx->status_rcvd);
- dst->r0_frags = __le32_to_cpu(rx->r0_frags);
- dst->r1_frags = __le32_to_cpu(rx->r1_frags);
- dst->r2_frags = __le32_to_cpu(rx->r2_frags);
- dst->r3_frags = __le32_to_cpu(rx->r3_frags);
- dst->htt_msdus = __le32_to_cpu(rx->htt_msdus);
- dst->htt_mpdus = __le32_to_cpu(rx->htt_mpdus);
- dst->loc_msdus = __le32_to_cpu(rx->loc_msdus);
- dst->loc_mpdus = __le32_to_cpu(rx->loc_mpdus);
- dst->oversize_amsdu = __le32_to_cpu(rx->oversize_amsdu);
- dst->phy_errs = __le32_to_cpu(rx->phy_errs);
- dst->phy_err_drop = __le32_to_cpu(rx->phy_err_drop);
- dst->mpdu_errs = __le32_to_cpu(rx->mpdu_errs);
-}
-
-static void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src,
- struct ath10k_fw_stats_peer *dst)
-{
- ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr);
- dst->peer_rssi = __le32_to_cpu(src->peer_rssi);
- dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate);
-}
-
-static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar,
- struct sk_buff *skb,
- struct ath10k_fw_stats *stats)
-{
- const struct wmi_stats_event *ev = (void *)skb->data;
- u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
- int i;
-
- if (!skb_pull(skb, sizeof(*ev)))
- return -EPROTO;
-
- num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
- num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
- num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
-
- for (i = 0; i < num_pdev_stats; i++) {
- const struct wmi_pdev_stats *src;
- struct ath10k_fw_stats_pdev *dst;
-
- src = (void *)skb->data;
- if (!skb_pull(skb, sizeof(*src)))
- return -EPROTO;
-
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
- if (!dst)
- continue;
-
- ath10k_wmi_pull_pdev_stats(src, dst);
- list_add_tail(&dst->list, &stats->pdevs);
- }
-
- /* fw doesn't implement vdev stats */
-
- for (i = 0; i < num_peer_stats; i++) {
- const struct wmi_peer_stats *src;
- struct ath10k_fw_stats_peer *dst;
-
- src = (void *)skb->data;
- if (!skb_pull(skb, sizeof(*src)))
- return -EPROTO;
-
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
- if (!dst)
- continue;
-
- ath10k_wmi_pull_peer_stats(src, dst);
- list_add_tail(&dst->list, &stats->peers);
- }
-
- return 0;
-}
-
-static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar,
- struct sk_buff *skb,
- struct ath10k_fw_stats *stats)
-{
- const struct wmi_stats_event *ev = (void *)skb->data;
- u32 num_pdev_stats, num_vdev_stats, num_peer_stats;
- int i;
-
- if (!skb_pull(skb, sizeof(*ev)))
- return -EPROTO;
-
- num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats);
- num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats);
- num_peer_stats = __le32_to_cpu(ev->num_peer_stats);
-
- for (i = 0; i < num_pdev_stats; i++) {
- const struct wmi_10x_pdev_stats *src;
- struct ath10k_fw_stats_pdev *dst;
-
- src = (void *)skb->data;
- if (!skb_pull(skb, sizeof(*src)))
- return -EPROTO;
-
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
- if (!dst)
- continue;
-
- ath10k_wmi_pull_pdev_stats(&src->old, dst);
-
- dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad);
- dst->rts_bad = __le32_to_cpu(src->rts_bad);
- dst->rts_good = __le32_to_cpu(src->rts_good);
- dst->fcs_bad = __le32_to_cpu(src->fcs_bad);
- dst->no_beacons = __le32_to_cpu(src->no_beacons);
- dst->mib_int_count = __le32_to_cpu(src->mib_int_count);
-
- list_add_tail(&dst->list, &stats->pdevs);
- }
-
- /* fw doesn't implement vdev stats */
-
- for (i = 0; i < num_peer_stats; i++) {
- const struct wmi_10x_peer_stats *src;
- struct ath10k_fw_stats_peer *dst;
-
- src = (void *)skb->data;
- if (!skb_pull(skb, sizeof(*src)))
- return -EPROTO;
-
- dst = kzalloc(sizeof(*dst), GFP_ATOMIC);
- if (!dst)
- continue;
-
- ath10k_wmi_pull_peer_stats(&src->old, dst);
-
- dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate);
-
- list_add_tail(&dst->list, &stats->peers);
- }
-
- return 0;
-}
-
-int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
- struct ath10k_fw_stats *stats)
-{
- if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
- return ath10k_wmi_10x_pull_fw_stats(ar, skb, stats);
- else
- return ath10k_wmi_main_pull_fw_stats(ar, skb, stats);
-}
-
static void ath10k_wmi_event_update_stats(struct ath10k *ar,
struct sk_buff *skb)
{
+ struct wmi_stats_event *ev = (struct wmi_stats_event *)skb->data;
+
ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n");
- ath10k_debug_fw_stats_process(ar, skb);
+
+ ath10k_debug_read_target_stats(ar, ev);
}
static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar,
@@ -1837,7 +1576,6 @@
struct wmi_bcn_info *bcn_info;
struct ath10k_vif *arvif;
struct sk_buff *bcn;
- dma_addr_t paddr;
int ret, vdev_id = 0;
int attempted_to_send_beacon = 0;
@@ -1909,36 +1647,27 @@
ath10k_warn(ar, "SWBA overrun on vdev %d\n",
arvif->vdev_id);
- ath10k_mac_vif_beacon_free(arvif);
+ dma_unmap_single(arvif->ar->dev,
+ ATH10K_SKB_CB(arvif->beacon)->paddr,
+ arvif->beacon->len, DMA_TO_DEVICE);
+ dev_kfree_skb_any(arvif->beacon);
+ arvif->beacon = NULL;
}
- if (!arvif->beacon_buf) {
- paddr = dma_map_single(arvif->ar->dev, bcn->data,
- bcn->len, DMA_TO_DEVICE);
- ret = dma_mapping_error(arvif->ar->dev, paddr);
- if (ret) {
- ath10k_warn(ar, "failed to map beacon: %d\n",
- ret);
- dev_kfree_skb_any(bcn);
- goto skip;
- }
-
- ATH10K_SKB_CB(bcn)->paddr = paddr;
- } else {
- if (bcn->len > IEEE80211_MAX_FRAME_LEN) {
- ath10k_warn(ar, "trimming beacon %d -> %d bytes!\n",
- bcn->len, IEEE80211_MAX_FRAME_LEN);
- skb_trim(bcn, IEEE80211_MAX_FRAME_LEN);
- }
- memcpy(arvif->beacon_buf, bcn->data, bcn->len);
- ATH10K_SKB_CB(bcn)->paddr = arvif->beacon_paddr;
+ ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev,
+ bcn->data, bcn->len,
+ DMA_TO_DEVICE);
+ ret = dma_mapping_error(arvif->ar->dev,
+ ATH10K_SKB_CB(bcn)->paddr);
+ if (ret) {
+ ath10k_warn(ar, "failed to map beacon: %d\n", ret);
+ dev_kfree_skb_any(bcn);
+ goto skip;
}
arvif->beacon = bcn;
arvif->beacon_sent = false;
- trace_ath10k_tx_hdr(ar, bcn->data, bcn->len);
- trace_ath10k_tx_payload(ar, bcn->data, bcn->len);
ret = ath10k_wmi_tx_beacon_nowait(arvif);
attempted_to_send_beacon = 1;
if (ret == 1) {
@@ -1967,8 +1696,8 @@
}
static void ath10k_dfs_radar_report(struct ath10k *ar,
- const struct wmi_phyerr *phyerr,
- const struct phyerr_radar_report *rr,
+ struct wmi_single_phyerr_rx_event *event,
+ struct phyerr_radar_report *rr,
u64 tsf)
{
u32 reg0, reg1, tsf32l;
@@ -2001,12 +1730,12 @@
return;
/* report event to DFS pattern detector */
- tsf32l = __le32_to_cpu(phyerr->tsf_timestamp);
+ tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp);
tsf64 = tsf & (~0xFFFFFFFFULL);
tsf64 |= tsf32l;
width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR);
- rssi = phyerr->rssi_combined;
+ rssi = event->hdr.rssi_combined;
/* hardware store this as 8 bit signed value,
* set to zero if negative number
@@ -2045,8 +1774,8 @@
}
static int ath10k_dfs_fft_report(struct ath10k *ar,
- const struct wmi_phyerr *phyerr,
- const struct phyerr_fft_report *fftr,
+ struct wmi_single_phyerr_rx_event *event,
+ struct phyerr_fft_report *fftr,
u64 tsf)
{
u32 reg0, reg1;
@@ -2054,7 +1783,7 @@
reg0 = __le32_to_cpu(fftr->reg0);
reg1 = __le32_to_cpu(fftr->reg1);
- rssi = phyerr->rssi_combined;
+ rssi = event->hdr.rssi_combined;
ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
"wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n",
@@ -2083,20 +1812,20 @@
}
static void ath10k_wmi_event_dfs(struct ath10k *ar,
- const struct wmi_phyerr *phyerr,
+ struct wmi_single_phyerr_rx_event *event,
u64 tsf)
{
int buf_len, tlv_len, res, i = 0;
- const struct phyerr_tlv *tlv;
- const struct phyerr_radar_report *rr;
- const struct phyerr_fft_report *fftr;
- const u8 *tlv_buf;
+ struct phyerr_tlv *tlv;
+ struct phyerr_radar_report *rr;
+ struct phyerr_fft_report *fftr;
+ u8 *tlv_buf;
- buf_len = __le32_to_cpu(phyerr->buf_len);
+ buf_len = __le32_to_cpu(event->hdr.buf_len);
ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
"wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n",
- phyerr->phy_err_code, phyerr->rssi_combined,
- __le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len);
+ event->hdr.phy_err_code, event->hdr.rssi_combined,
+ __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len);
/* Skip event if DFS disabled */
if (!config_enabled(CPTCFG_ATH10K_DFS_CERTIFIED))
@@ -2111,9 +1840,9 @@
return;
}
- tlv = (struct phyerr_tlv *)&phyerr->buf[i];
+ tlv = (struct phyerr_tlv *)&event->bufp[i];
tlv_len = __le16_to_cpu(tlv->len);
- tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
+ tlv_buf = &event->bufp[i + sizeof(*tlv)];
ath10k_dbg(ar, ATH10K_DBG_REGULATORY,
"wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n",
tlv_len, tlv->tag, tlv->sig);
@@ -2127,7 +1856,7 @@
}
rr = (struct phyerr_radar_report *)tlv_buf;
- ath10k_dfs_radar_report(ar, phyerr, rr, tsf);
+ ath10k_dfs_radar_report(ar, event, rr, tsf);
break;
case PHYERR_TLV_TAG_SEARCH_FFT_REPORT:
if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) {
@@ -2137,7 +1866,7 @@
}
fftr = (struct phyerr_fft_report *)tlv_buf;
- res = ath10k_dfs_fft_report(ar, phyerr, fftr, tsf);
+ res = ath10k_dfs_fft_report(ar, event, fftr, tsf);
if (res)
return;
break;
@@ -2149,16 +1878,16 @@
static void
ath10k_wmi_event_spectral_scan(struct ath10k *ar,
- const struct wmi_phyerr *phyerr,
+ struct wmi_single_phyerr_rx_event *event,
u64 tsf)
{
int buf_len, tlv_len, res, i = 0;
struct phyerr_tlv *tlv;
- const void *tlv_buf;
- const struct phyerr_fft_report *fftr;
+ u8 *tlv_buf;
+ struct phyerr_fft_report *fftr;
size_t fftr_len;
- buf_len = __le32_to_cpu(phyerr->buf_len);
+ buf_len = __le32_to_cpu(event->hdr.buf_len);
while (i < buf_len) {
if (i + sizeof(*tlv) > buf_len) {
@@ -2167,9 +1896,9 @@
return;
}
- tlv = (struct phyerr_tlv *)&phyerr->buf[i];
+ tlv = (struct phyerr_tlv *)&event->bufp[i];
tlv_len = __le16_to_cpu(tlv->len);
- tlv_buf = &phyerr->buf[i + sizeof(*tlv)];
+ tlv_buf = &event->bufp[i + sizeof(*tlv)];
if (i + sizeof(*tlv) + tlv_len > buf_len) {
ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n",
@@ -2186,8 +1915,8 @@
}
fftr_len = tlv_len - sizeof(*fftr);
- fftr = tlv_buf;
- res = ath10k_spectral_process_fft(ar, phyerr,
+ fftr = (struct phyerr_fft_report *)tlv_buf;
+ res = ath10k_spectral_process_fft(ar, event,
fftr, fftr_len,
tsf);
if (res < 0) {
@@ -2204,8 +1933,8 @@
static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb)
{
- const struct wmi_phyerr_event *ev;
- const struct wmi_phyerr *phyerr;
+ struct wmi_comb_phyerr_rx_event *comb_event;
+ struct wmi_single_phyerr_rx_event *event;
u32 count, i, buf_len, phy_err_code;
u64 tsf;
int left_len = skb->len;
@@ -2213,38 +1942,38 @@
ATH10K_DFS_STAT_INC(ar, phy_errors);
/* Check if combined event available */
- if (left_len < sizeof(*ev)) {
+ if (left_len < sizeof(*comb_event)) {
ath10k_warn(ar, "wmi phyerr combined event wrong len\n");
return;
}
- left_len -= sizeof(*ev);
+ left_len -= sizeof(*comb_event);
/* Check number of included events */
- ev = (const struct wmi_phyerr_event *)skb->data;
- count = __le32_to_cpu(ev->num_phyerrs);
+ comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data;
+ count = __le32_to_cpu(comb_event->hdr.num_phyerr_events);
- tsf = __le32_to_cpu(ev->tsf_u32);
+ tsf = __le32_to_cpu(comb_event->hdr.tsf_u32);
tsf <<= 32;
- tsf |= __le32_to_cpu(ev->tsf_l32);
+ tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32);
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi event phyerr count %d tsf64 0x%llX\n",
count, tsf);
- phyerr = ev->phyerrs;
+ event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp;
for (i = 0; i < count; i++) {
/* Check if we can read event header */
- if (left_len < sizeof(*phyerr)) {
+ if (left_len < sizeof(*event)) {
ath10k_warn(ar, "single event (%d) wrong head len\n",
i);
return;
}
- left_len -= sizeof(*phyerr);
+ left_len -= sizeof(*event);
- buf_len = __le32_to_cpu(phyerr->buf_len);
- phy_err_code = phyerr->phy_err_code;
+ buf_len = __le32_to_cpu(event->hdr.buf_len);
+ phy_err_code = event->hdr.phy_err_code;
if (left_len < buf_len) {
ath10k_warn(ar, "single event (%d) wrong buf len\n", i);
@@ -2255,20 +1984,20 @@
switch (phy_err_code) {
case PHY_ERROR_RADAR:
- ath10k_wmi_event_dfs(ar, phyerr, tsf);
+ ath10k_wmi_event_dfs(ar, event, tsf);
break;
case PHY_ERROR_SPECTRAL_SCAN:
- ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
+ ath10k_wmi_event_spectral_scan(ar, event, tsf);
break;
case PHY_ERROR_FALSE_RADAR_EXT:
- ath10k_wmi_event_dfs(ar, phyerr, tsf);
- ath10k_wmi_event_spectral_scan(ar, phyerr, tsf);
+ ath10k_wmi_event_dfs(ar, event, tsf);
+ ath10k_wmi_event_spectral_scan(ar, event, tsf);
break;
default:
break;
}
- phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len;
+ event += sizeof(*event) + buf_len;
}
}
@@ -2314,7 +2043,7 @@
/* the last byte is always reserved for the null character */
buf[i] = '\0';
- ath10k_dbg(ar, ATH10K_DBG_WMI_PRINT, "wmi print '%s'\n", buf);
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi event debug print '%s'\n", buf);
}
static void ath10k_wmi_event_pdev_qvit(struct ath10k *ar, struct sk_buff *skb)
@@ -2449,117 +2178,30 @@
return 0;
}
-static int ath10k_wmi_main_pull_svc_rdy_ev(struct sk_buff *skb,
- struct wmi_svc_rdy_ev_arg *arg)
+static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar,
+ struct sk_buff *skb)
{
- struct wmi_service_ready_event *ev;
- size_t i, n;
+ struct wmi_service_ready_event *ev = (void *)skb->data;
+ DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
- if (skb->len < sizeof(*ev))
- return -EPROTO;
-
- ev = (void *)skb->data;
- skb_pull(skb, sizeof(*ev));
- arg->min_tx_power = ev->hw_min_tx_power;
- arg->max_tx_power = ev->hw_max_tx_power;
- arg->ht_cap = ev->ht_cap_info;
- arg->vht_cap = ev->vht_cap_info;
- arg->sw_ver0 = ev->sw_version;
- arg->sw_ver1 = ev->sw_version_1;
- arg->phy_capab = ev->phy_capability;
- arg->num_rf_chains = ev->num_rf_chains;
- arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
- arg->num_mem_reqs = ev->num_mem_reqs;
- arg->service_map = ev->wmi_service_bitmap;
- arg->service_map_len = sizeof(ev->wmi_service_bitmap);
-
- n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
- ARRAY_SIZE(arg->mem_reqs));
- for (i = 0; i < n; i++)
- arg->mem_reqs[i] = &ev->mem_reqs[i];
-
- if (skb->len <
- __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
- return -EPROTO;
-
- return 0;
-}
-
-static int ath10k_wmi_10x_pull_svc_rdy_ev(struct sk_buff *skb,
- struct wmi_svc_rdy_ev_arg *arg)
-{
- struct wmi_10x_service_ready_event *ev;
- int i, n;
-
- if (skb->len < sizeof(*ev))
- return -EPROTO;
-
- ev = (void *)skb->data;
- skb_pull(skb, sizeof(*ev));
- arg->min_tx_power = ev->hw_min_tx_power;
- arg->max_tx_power = ev->hw_max_tx_power;
- arg->ht_cap = ev->ht_cap_info;
- arg->vht_cap = ev->vht_cap_info;
- arg->sw_ver0 = ev->sw_version;
- arg->phy_capab = ev->phy_capability;
- arg->num_rf_chains = ev->num_rf_chains;
- arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd;
- arg->num_mem_reqs = ev->num_mem_reqs;
- arg->service_map = ev->wmi_service_bitmap;
- arg->service_map_len = sizeof(ev->wmi_service_bitmap);
-
- n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs),
- ARRAY_SIZE(arg->mem_reqs));
- for (i = 0; i < n; i++)
- arg->mem_reqs[i] = &ev->mem_reqs[i];
-
- if (skb->len <
- __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0]))
- return -EPROTO;
-
- return 0;
-}
-
-static void ath10k_wmi_event_service_ready(struct ath10k *ar,
- struct sk_buff *skb)
-{
- struct wmi_svc_rdy_ev_arg arg = {};
- u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
- int ret;
-
- memset(&ar->wmi.svc_map, 0, sizeof(ar->wmi.svc_map));
-
- if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
- ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg);
- wmi_10x_svc_map(arg.service_map, ar->wmi.svc_map,
- arg.service_map_len);
- } else {
- ret = ath10k_wmi_main_pull_svc_rdy_ev(skb, &arg);
- wmi_main_svc_map(arg.service_map, ar->wmi.svc_map,
- arg.service_map_len);
- }
-
- if (ret) {
- ath10k_warn(ar, "failed to parse service ready: %d\n", ret);
+ if (skb->len < sizeof(*ev)) {
+ ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
+ skb->len, sizeof(*ev));
return;
}
- ar->hw_min_tx_power = __le32_to_cpu(arg.min_tx_power);
- ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power);
- ar->ht_cap_info = __le32_to_cpu(arg.ht_cap);
- ar->vht_cap_info = __le32_to_cpu(arg.vht_cap);
+ ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
+ ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
+ ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
+ ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
ar->fw_version_major =
- (__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24;
- ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff);
+ (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
+ ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
ar->fw_version_release =
- (__le32_to_cpu(arg.sw_ver1) & 0xffff0000) >> 16;
- ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff);
- ar->phy_capability = __le32_to_cpu(arg.phy_capab);
- ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains);
- ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd);
-
- ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
- arg.service_map, arg.service_map_len);
+ (__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16;
+ ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff);
+ ar->phy_capability = __le32_to_cpu(ev->phy_capability);
+ ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
/* only manually set fw features when not using FW IE format */
if (ar->fw_api == 1 && ar->fw_version_build > 636)
@@ -2571,8 +2213,13 @@
ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
}
- ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1;
- ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1;
+ ar->ath_common.regulatory.current_rd =
+ __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
+
+ wmi_main_svc_map(ev->wmi_service_bitmap, svc_bmap);
+ ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
+ ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
+ ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap));
if (strlen(ar->hw->wiphy->fw_version) == 0) {
snprintf(ar->hw->wiphy->fw_version,
@@ -2584,18 +2231,93 @@
ar->fw_version_build);
}
- num_mem_reqs = __le32_to_cpu(arg.num_mem_reqs);
- if (num_mem_reqs > WMI_MAX_MEM_REQS) {
+ /* FIXME: it probably should be better to support this */
+ if (__le32_to_cpu(ev->num_mem_reqs) > 0) {
+ ath10k_warn(ar, "target requested %d memory chunks; ignoring\n",
+ __le32_to_cpu(ev->num_mem_reqs));
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
+ __le32_to_cpu(ev->sw_version),
+ __le32_to_cpu(ev->sw_version_1),
+ __le32_to_cpu(ev->abi_version),
+ __le32_to_cpu(ev->phy_capability),
+ __le32_to_cpu(ev->ht_cap_info),
+ __le32_to_cpu(ev->vht_cap_info),
+ __le32_to_cpu(ev->vht_supp_mcs),
+ __le32_to_cpu(ev->sys_cap_info),
+ __le32_to_cpu(ev->num_mem_reqs),
+ __le32_to_cpu(ev->num_rf_chains));
+
+ complete(&ar->wmi.service_ready);
+}
+
+static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar,
+ struct sk_buff *skb)
+{
+ u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i;
+ int ret;
+ struct wmi_service_ready_event_10x *ev = (void *)skb->data;
+ DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {};
+
+ if (skb->len < sizeof(*ev)) {
+ ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n",
+ skb->len, sizeof(*ev));
+ return;
+ }
+
+ ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power);
+ ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power);
+ ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info);
+ ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info);
+ ar->fw_version_major =
+ (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24;
+ ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff);
+ ar->phy_capability = __le32_to_cpu(ev->phy_capability);
+ ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains);
+
+ if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) {
+ ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n",
+ ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM);
+ ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM;
+ }
+
+ ar->ath_common.regulatory.current_rd =
+ __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd);
+
+ wmi_10x_svc_map(ev->wmi_service_bitmap, svc_bmap);
+ ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap));
+ ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ",
+ ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap));
+
+ if (strlen(ar->hw->wiphy->fw_version) == 0) {
+ snprintf(ar->hw->wiphy->fw_version,
+ sizeof(ar->hw->wiphy->fw_version),
+ "%u.%u",
+ ar->fw_version_major,
+ ar->fw_version_minor);
+ }
+
+ num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs);
+
+ if (num_mem_reqs > ATH10K_MAX_MEM_REQS) {
ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n",
num_mem_reqs);
return;
}
+ if (!num_mem_reqs)
+ goto exit;
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n",
+ num_mem_reqs);
+
for (i = 0; i < num_mem_reqs; ++i) {
- req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id);
- num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units);
- unit_size = __le32_to_cpu(arg.mem_reqs[i]->unit_size);
- num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info);
+ req_id = __le32_to_cpu(ev->mem_reqs[i].req_id);
+ num_units = __le32_to_cpu(ev->mem_reqs[i].num_units);
+ unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size);
+ num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info);
if (num_unit_info & NUM_UNITS_IS_NUM_PEERS)
/* number of units to allocate is number of
@@ -2609,7 +2331,7 @@
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n",
req_id,
- __le32_to_cpu(arg.mem_reqs[i]->num_units),
+ __le32_to_cpu(ev->mem_reqs[i].num_units),
num_unit_info,
unit_size,
num_units);
@@ -2620,23 +2342,23 @@
return;
}
+exit:
ath10k_dbg(ar, ATH10K_DBG_WMI,
- "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n",
- __le32_to_cpu(arg.min_tx_power),
- __le32_to_cpu(arg.max_tx_power),
- __le32_to_cpu(arg.ht_cap),
- __le32_to_cpu(arg.vht_cap),
- __le32_to_cpu(arg.sw_ver0),
- __le32_to_cpu(arg.sw_ver1),
- __le32_to_cpu(arg.phy_capab),
- __le32_to_cpu(arg.num_rf_chains),
- __le32_to_cpu(arg.eeprom_rd),
- __le32_to_cpu(arg.num_mem_reqs));
+ "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n",
+ __le32_to_cpu(ev->sw_version),
+ __le32_to_cpu(ev->abi_version),
+ __le32_to_cpu(ev->phy_capability),
+ __le32_to_cpu(ev->ht_cap_info),
+ __le32_to_cpu(ev->vht_cap_info),
+ __le32_to_cpu(ev->vht_supp_mcs),
+ __le32_to_cpu(ev->sys_cap_info),
+ __le32_to_cpu(ev->num_mem_reqs),
+ __le32_to_cpu(ev->num_rf_chains));
complete(&ar->wmi.service_ready);
}
-static int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb)
+static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb)
{
struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data;
@@ -2759,10 +2481,10 @@
ath10k_wmi_event_vdev_install_key_complete(ar, skb);
break;
case WMI_SERVICE_READY_EVENTID:
- ath10k_wmi_event_service_ready(ar, skb);
+ ath10k_wmi_service_ready_event_rx(ar, skb);
break;
case WMI_READY_EVENTID:
- ath10k_wmi_event_ready(ar, skb);
+ ath10k_wmi_ready_event_rx(ar, skb);
break;
default:
ath10k_warn(ar, "Unknown eventid: %d\n", id);
@@ -2879,10 +2601,10 @@
ath10k_wmi_event_vdev_resume_req(ar, skb);
break;
case WMI_10X_SERVICE_READY_EVENTID:
- ath10k_wmi_event_service_ready(ar, skb);
+ ath10k_wmi_10x_service_ready_event_rx(ar, skb);
break;
case WMI_10X_READY_EVENTID:
- ath10k_wmi_event_ready(ar, skb);
+ ath10k_wmi_ready_event_rx(ar, skb);
break;
case WMI_10X_PDEV_UTF_EVENTID:
/* ignore utf events */
@@ -2990,10 +2712,10 @@
ath10k_wmi_event_vdev_resume_req(ar, skb);
break;
case WMI_10_2_SERVICE_READY_EVENTID:
- ath10k_wmi_event_service_ready(ar, skb);
+ ath10k_wmi_10x_service_ready_event_rx(ar, skb);
break;
case WMI_10_2_READY_EVENTID:
- ath10k_wmi_event_ready(ar, skb);
+ ath10k_wmi_ready_event_rx(ar, skb);
break;
case WMI_10_2_RTT_KEEPALIVE_EVENTID:
case WMI_10_2_GPIO_INPUT_EVENTID:
@@ -3025,6 +2747,45 @@
}
}
+/* WMI Initialization functions */
+int ath10k_wmi_attach(struct ath10k *ar)
+{
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
+ ar->wmi.cmd = &wmi_10_2_cmd_map;
+ else
+ ar->wmi.cmd = &wmi_10x_cmd_map;
+
+ ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
+ ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
+ } else {
+ ar->wmi.cmd = &wmi_cmd_map;
+ ar->wmi.vdev_param = &wmi_vdev_param_map;
+ ar->wmi.pdev_param = &wmi_pdev_param_map;
+ }
+
+ init_completion(&ar->wmi.service_ready);
+ init_completion(&ar->wmi.unified_ready);
+ init_waitqueue_head(&ar->wmi.tx_credits_wq);
+
+ return 0;
+}
+
+void ath10k_wmi_detach(struct ath10k *ar)
+{
+ int i;
+
+ /* free the host memory chunks requested by firmware */
+ for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+ dma_free_coherent(ar->dev,
+ ar->wmi.mem_chunks[i].len,
+ ar->wmi.mem_chunks[i].vaddr,
+ ar->wmi.mem_chunks[i].paddr);
+ }
+
+ ar->wmi.num_mem_chunks = 0;
+}
+
int ath10k_wmi_connect(struct ath10k *ar)
{
int status;
@@ -3119,6 +2880,42 @@
ctl2g, ctl5g);
}
+int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
+ const struct wmi_channel_arg *arg)
+{
+ struct wmi_set_channel_cmd *cmd;
+ struct sk_buff *skb;
+ u32 ch_flags = 0;
+
+ if (arg->passive)
+ return -EINVAL;
+
+ skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
+ if (!skb)
+ return -ENOMEM;
+
+ if (arg->chan_radar)
+ ch_flags |= WMI_CHAN_FLAG_DFS;
+
+ cmd = (struct wmi_set_channel_cmd *)skb->data;
+ cmd->chan.mhz = __cpu_to_le32(arg->freq);
+ cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq);
+ cmd->chan.mode = arg->mode;
+ cmd->chan.flags |= __cpu_to_le32(ch_flags);
+ cmd->chan.min_power = arg->min_power;
+ cmd->chan.max_power = arg->max_power;
+ cmd->chan.reg_power = arg->max_reg_power;
+ cmd->chan.reg_classid = arg->reg_class_id;
+ cmd->chan.antenna_max = arg->max_antenna_gain;
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi set channel mode %d freq %d\n",
+ arg->mode, arg->freq);
+
+ return ath10k_wmi_cmd_send(ar, skb,
+ ar->wmi.cmd->pdev_set_channel_cmdid);
+}
+
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt)
{
struct wmi_pdev_suspend_cmd *cmd;
@@ -3169,37 +2966,16 @@
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid);
}
-static void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar,
- struct wmi_host_mem_chunks *chunks)
-{
- struct host_memory_chunk *chunk;
- int i;
-
- chunks->count = __cpu_to_le32(ar->wmi.num_mem_chunks);
-
- for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
- chunk = &chunks->items[i];
- chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
- chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len);
- chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
-
- ath10k_dbg(ar, ATH10K_DBG_WMI,
- "wmi chunk %d len %d requested, addr 0x%llx\n",
- i,
- ar->wmi.mem_chunks[i].len,
- (unsigned long long)ar->wmi.mem_chunks[i].paddr);
- }
-}
-
static int ath10k_wmi_main_cmd_init(struct ath10k *ar)
{
struct wmi_init_cmd *cmd;
struct sk_buff *buf;
struct wmi_resource_config config = {};
u32 len, val;
+ int i;
config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS);
- config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS);
+ config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS);
config.num_offload_peers = __cpu_to_le32(TARGET_NUM_OFFLOAD_PEERS);
config.num_offload_reorder_bufs =
@@ -3260,8 +3036,32 @@
cmd = (struct wmi_init_cmd *)buf->data;
+ if (ar->wmi.num_mem_chunks == 0) {
+ cmd->num_host_mem_chunks = 0;
+ goto out;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
+ ar->wmi.num_mem_chunks);
+
+ cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
+
+ for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+ cmd->host_mem_chunks[i].ptr =
+ __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
+ cmd->host_mem_chunks[i].size =
+ __cpu_to_le32(ar->wmi.mem_chunks[i].len);
+ cmd->host_mem_chunks[i].req_id =
+ __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi chunk %d len %d requested, addr 0x%llx\n",
+ i,
+ ar->wmi.mem_chunks[i].len,
+ (unsigned long long)ar->wmi.mem_chunks[i].paddr);
+ }
+out:
memcpy(&cmd->resource_config, &config, sizeof(config));
- ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n");
return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
@@ -3273,6 +3073,7 @@
struct sk_buff *buf;
struct wmi_resource_config_10x config = {};
u32 len, val;
+ int i;
config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
@@ -3329,8 +3130,32 @@
cmd = (struct wmi_init_cmd_10x *)buf->data;
+ if (ar->wmi.num_mem_chunks == 0) {
+ cmd->num_host_mem_chunks = 0;
+ goto out;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
+ ar->wmi.num_mem_chunks);
+
+ cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
+
+ for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+ cmd->host_mem_chunks[i].ptr =
+ __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
+ cmd->host_mem_chunks[i].size =
+ __cpu_to_le32(ar->wmi.mem_chunks[i].len);
+ cmd->host_mem_chunks[i].req_id =
+ __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi chunk %d len %d requested, addr 0x%llx\n",
+ i,
+ ar->wmi.mem_chunks[i].len,
+ (unsigned long long)ar->wmi.mem_chunks[i].paddr);
+ }
+out:
memcpy(&cmd->resource_config, &config, sizeof(config));
- ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n");
return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
@@ -3342,6 +3167,7 @@
struct sk_buff *buf;
struct wmi_resource_config_10x config = {};
u32 len, val;
+ int i;
config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS);
config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS);
@@ -3395,8 +3221,32 @@
cmd = (struct wmi_init_cmd_10_2 *)buf->data;
+ if (ar->wmi.num_mem_chunks == 0) {
+ cmd->num_host_mem_chunks = 0;
+ goto out;
+ }
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n",
+ ar->wmi.num_mem_chunks);
+
+ cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks);
+
+ for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
+ cmd->host_mem_chunks[i].ptr =
+ __cpu_to_le32(ar->wmi.mem_chunks[i].paddr);
+ cmd->host_mem_chunks[i].size =
+ __cpu_to_le32(ar->wmi.mem_chunks[i].len);
+ cmd->host_mem_chunks[i].req_id =
+ __cpu_to_le32(ar->wmi.mem_chunks[i].req_id);
+
+ ath10k_dbg(ar, ATH10K_DBG_WMI,
+ "wmi chunk %d len %d requested, addr 0x%llx\n",
+ i,
+ ar->wmi.mem_chunks[i].len,
+ (unsigned long long)ar->wmi.mem_chunks[i].paddr);
+ }
+out:
memcpy(&cmd->resource_config.common, &config, sizeof(config));
- ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks);
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n");
return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid);
@@ -3418,50 +3268,52 @@
return ret;
}
-static int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg)
+static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar,
+ const struct wmi_start_scan_arg *arg)
{
- if (arg->ie_len && !arg->ie)
- return -EINVAL;
- if (arg->n_channels && !arg->channels)
- return -EINVAL;
- if (arg->n_ssids && !arg->ssids)
- return -EINVAL;
- if (arg->n_bssids && !arg->bssids)
- return -EINVAL;
+ int len;
- if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
- return -EINVAL;
- if (arg->n_channels > ARRAY_SIZE(arg->channels))
- return -EINVAL;
- if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
- return -EINVAL;
- if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
- return -EINVAL;
-
- return 0;
-}
-
-static size_t
-ath10k_wmi_start_scan_tlvs_len(const struct wmi_start_scan_arg *arg)
-{
- int len = 0;
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+ len = sizeof(struct wmi_start_scan_cmd_10x);
+ else
+ len = sizeof(struct wmi_start_scan_cmd);
if (arg->ie_len) {
+ if (!arg->ie)
+ return -EINVAL;
+ if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN)
+ return -EINVAL;
+
len += sizeof(struct wmi_ie_data);
len += roundup(arg->ie_len, 4);
}
if (arg->n_channels) {
+ if (!arg->channels)
+ return -EINVAL;
+ if (arg->n_channels > ARRAY_SIZE(arg->channels))
+ return -EINVAL;
+
len += sizeof(struct wmi_chan_list);
len += sizeof(__le32) * arg->n_channels;
}
if (arg->n_ssids) {
+ if (!arg->ssids)
+ return -EINVAL;
+ if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID)
+ return -EINVAL;
+
len += sizeof(struct wmi_ssid_list);
len += sizeof(struct wmi_ssid) * arg->n_ssids;
}
if (arg->n_bssids) {
+ if (!arg->bssids)
+ return -EINVAL;
+ if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID)
+ return -EINVAL;
+
len += sizeof(struct wmi_bssid_list);
len += sizeof(struct wmi_mac_addr) * arg->n_bssids;
}
@@ -3469,12 +3321,28 @@
return len;
}
-static void
-ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn,
- const struct wmi_start_scan_arg *arg)
+int ath10k_wmi_start_scan(struct ath10k *ar,
+ const struct wmi_start_scan_arg *arg)
{
+ struct wmi_start_scan_cmd *cmd;
+ struct sk_buff *skb;
+ struct wmi_ie_data *ie;
+ struct wmi_chan_list *channels;
+ struct wmi_ssid_list *ssids;
+ struct wmi_bssid_list *bssids;
u32 scan_id;
u32 scan_req_id;
+ int off;
+ int len = 0;
+ int i;
+
+ len = ath10k_wmi_start_scan_calc_len(ar, arg);
+ if (len < 0)
+ return len; /* len contains error code here */
+
+ skb = ath10k_wmi_alloc_skb(ar, len);
+ if (!skb)
+ return -ENOMEM;
scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX;
scan_id |= arg->scan_id;
@@ -3482,36 +3350,35 @@
scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX;
scan_req_id |= arg->scan_req_id;
- cmn->scan_id = __cpu_to_le32(scan_id);
- cmn->scan_req_id = __cpu_to_le32(scan_req_id);
- cmn->vdev_id = __cpu_to_le32(arg->vdev_id);
- cmn->scan_priority = __cpu_to_le32(arg->scan_priority);
- cmn->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
- cmn->dwell_time_active = __cpu_to_le32(arg->dwell_time_active);
- cmn->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
- cmn->min_rest_time = __cpu_to_le32(arg->min_rest_time);
- cmn->max_rest_time = __cpu_to_le32(arg->max_rest_time);
- cmn->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time);
- cmn->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
- cmn->idle_time = __cpu_to_le32(arg->idle_time);
- cmn->max_scan_time = __cpu_to_le32(arg->max_scan_time);
- cmn->probe_delay = __cpu_to_le32(arg->probe_delay);
- cmn->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags);
-}
+ cmd = (struct wmi_start_scan_cmd *)skb->data;
+ cmd->scan_id = __cpu_to_le32(scan_id);
+ cmd->scan_req_id = __cpu_to_le32(scan_req_id);
+ cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
+ cmd->scan_priority = __cpu_to_le32(arg->scan_priority);
+ cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events);
+ cmd->dwell_time_active = __cpu_to_le32(arg->dwell_time_active);
+ cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive);
+ cmd->min_rest_time = __cpu_to_le32(arg->min_rest_time);
+ cmd->max_rest_time = __cpu_to_le32(arg->max_rest_time);
+ cmd->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time);
+ cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time);
+ cmd->idle_time = __cpu_to_le32(arg->idle_time);
+ cmd->max_scan_time = __cpu_to_le32(arg->max_scan_time);
+ cmd->probe_delay = __cpu_to_le32(arg->probe_delay);
+ cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags);
-static void
-ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs,
- const struct wmi_start_scan_arg *arg)
-{
- struct wmi_ie_data *ie;
- struct wmi_chan_list *channels;
- struct wmi_ssid_list *ssids;
- struct wmi_bssid_list *bssids;
- void *ptr = tlvs->tlvs;
- int i;
+ /* TLV list starts after fields included in the struct */
+ /* There's just one filed that differes the two start_scan
+ * structures - burst_duration, which we are not using btw,
+ no point to make the split here, just shift the buffer to fit with
+ given FW */
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+ off = sizeof(struct wmi_start_scan_cmd_10x);
+ else
+ off = sizeof(struct wmi_start_scan_cmd);
if (arg->n_channels) {
- channels = ptr;
+ channels = (void *)skb->data + off;
channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG);
channels->num_chan = __cpu_to_le32(arg->n_channels);
@@ -3519,12 +3386,12 @@
channels->channel_list[i].freq =
__cpu_to_le16(arg->channels[i]);
- ptr += sizeof(*channels);
- ptr += sizeof(__le32) * arg->n_channels;
+ off += sizeof(*channels);
+ off += sizeof(__le32) * arg->n_channels;
}
if (arg->n_ssids) {
- ssids = ptr;
+ ssids = (void *)skb->data + off;
ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG);
ssids->num_ssids = __cpu_to_le32(arg->n_ssids);
@@ -3536,12 +3403,12 @@
arg->ssids[i].len);
}
- ptr += sizeof(*ssids);
- ptr += sizeof(struct wmi_ssid) * arg->n_ssids;
+ off += sizeof(*ssids);
+ off += sizeof(struct wmi_ssid) * arg->n_ssids;
}
if (arg->n_bssids) {
- bssids = ptr;
+ bssids = (void *)skb->data + off;
bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG);
bssids->num_bssid = __cpu_to_le32(arg->n_bssids);
@@ -3550,57 +3417,23 @@
arg->bssids[i].bssid,
ETH_ALEN);
- ptr += sizeof(*bssids);
- ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids;
+ off += sizeof(*bssids);
+ off += sizeof(struct wmi_mac_addr) * arg->n_bssids;
}
if (arg->ie_len) {
- ie = ptr;
+ ie = (void *)skb->data + off;
ie->tag = __cpu_to_le32(WMI_IE_TAG);
ie->ie_len = __cpu_to_le32(arg->ie_len);
memcpy(ie->ie_data, arg->ie, arg->ie_len);
- ptr += sizeof(*ie);
- ptr += roundup(arg->ie_len, 4);
+ off += sizeof(*ie);
+ off += roundup(arg->ie_len, 4);
}
-}
-int ath10k_wmi_start_scan(struct ath10k *ar,
- const struct wmi_start_scan_arg *arg)
-{
- struct sk_buff *skb;
- size_t len;
- int ret;
-
- ret = ath10k_wmi_start_scan_verify(arg);
- if (ret)
- return ret;
-
- if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
- len = sizeof(struct wmi_10x_start_scan_cmd) +
- ath10k_wmi_start_scan_tlvs_len(arg);
- else
- len = sizeof(struct wmi_start_scan_cmd) +
- ath10k_wmi_start_scan_tlvs_len(arg);
-
- skb = ath10k_wmi_alloc_skb(ar, len);
- if (!skb)
- return -ENOMEM;
-
- if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
- struct wmi_10x_start_scan_cmd *cmd;
-
- cmd = (struct wmi_10x_start_scan_cmd *)skb->data;
- ath10k_wmi_put_start_scan_common(&cmd->common, arg);
- ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
- } else {
- struct wmi_start_scan_cmd *cmd;
-
- cmd = (struct wmi_start_scan_cmd *)skb->data;
- cmd->burst_duration_ms = __cpu_to_le32(0);
-
- ath10k_wmi_put_start_scan_common(&cmd->common, arg);
- ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg);
+ if (off != skb->len) {
+ dev_kfree_skb(skb);
+ return -EINVAL;
}
ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n");
@@ -3719,6 +3552,7 @@
struct sk_buff *skb;
const char *cmdname;
u32 flags = 0;
+ u32 ch_flags = 0;
if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid &&
cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid)
@@ -3745,6 +3579,8 @@
flags |= WMI_VDEV_START_HIDDEN_SSID;
if (arg->pmf_enabled)
flags |= WMI_VDEV_START_PMF_ENABLED;
+ if (arg->channel.chan_radar)
+ ch_flags |= WMI_CHAN_FLAG_DFS;
cmd = (struct wmi_vdev_start_request_cmd *)skb->data;
cmd->vdev_id = __cpu_to_le32(arg->vdev_id);
@@ -3762,7 +3598,18 @@
memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len);
}
- ath10k_wmi_put_wmi_channel(&cmd->chan, &arg->channel);
+ cmd->chan.mhz = __cpu_to_le32(arg->channel.freq);
+
+ cmd->chan.band_center_freq1 =
+ __cpu_to_le32(arg->channel.band_center_freq1);
+
+ cmd->chan.mode = arg->channel.mode;
+ cmd->chan.flags |= __cpu_to_le32(ch_flags);
+ cmd->chan.min_power = arg->channel.min_power;
+ cmd->chan.max_power = arg->channel.max_power;
+ cmd->chan.reg_power = arg->channel.max_reg_power;
+ cmd->chan.reg_classid = arg->channel.reg_class_id;
+ cmd->chan.antenna_max = arg->channel.max_antenna_gain;
ath10k_dbg(ar, ATH10K_DBG_WMI,
"wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n",
@@ -4143,10 +3990,35 @@
cmd->num_scan_chans = __cpu_to_le32(arg->n_channels);
for (i = 0; i < arg->n_channels; i++) {
+ u32 flags = 0;
+
ch = &arg->channels[i];
ci = &cmd->chan_info[i];
- ath10k_wmi_put_wmi_channel(ci, ch);
+ if (ch->passive)
+ flags |= WMI_CHAN_FLAG_PASSIVE;
+ if (ch->allow_ibss)
+ flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED;
+ if (ch->allow_ht)
+ flags |= WMI_CHAN_FLAG_ALLOW_HT;
+ if (ch->allow_vht)
+ flags |= WMI_CHAN_FLAG_ALLOW_VHT;
+ if (ch->ht40plus)
+ flags |= WMI_CHAN_FLAG_HT40_PLUS;
+ if (ch->chan_radar)
+ flags |= WMI_CHAN_FLAG_DFS;
+
+ ci->mhz = __cpu_to_le32(ch->freq);
+ ci->band_center_freq1 = __cpu_to_le32(ch->freq);
+ ci->band_center_freq2 = 0;
+ ci->min_power = ch->min_power;
+ ci->max_power = ch->max_power;
+ ci->reg_power = ch->max_reg_power;
+ ci->antenna_max = ch->max_antenna_gain;
+
+ /* mode & flags share storage */
+ ci->mode = ch->mode;
+ ci->flags |= __cpu_to_le32(flags);
}
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid);
@@ -4258,9 +4130,9 @@
if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
- ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg);
- else
ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg);
+ else
+ ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg);
} else {
ath10k_wmi_peer_assoc_fill_main(ar, skb->data, arg);
}
@@ -4417,73 +4289,3 @@
return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid);
}
-
-int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_bitmap)
-{
- struct wmi_pdev_pktlog_enable_cmd *cmd;
- struct sk_buff *skb;
-
- skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd));
- if (!skb)
- return -ENOMEM;
-
- ev_bitmap &= ATH10K_PKTLOG_ANY;
- ath10k_dbg(ar, ATH10K_DBG_WMI,
- "wmi enable pktlog filter:%x\n", ev_bitmap);
-
- cmd = (struct wmi_pdev_pktlog_enable_cmd *)skb->data;
- cmd->ev_bitmap = __cpu_to_le32(ev_bitmap);
- return ath10k_wmi_cmd_send(ar, skb,
- ar->wmi.cmd->pdev_pktlog_enable_cmdid);
-}
-
-int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar)
-{
- struct sk_buff *skb;
-
- skb = ath10k_wmi_alloc_skb(ar, 0);
- if (!skb)
- return -ENOMEM;
-
- ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi disable pktlog\n");
-
- return ath10k_wmi_cmd_send(ar, skb,
- ar->wmi.cmd->pdev_pktlog_disable_cmdid);
-}
-
-int ath10k_wmi_attach(struct ath10k *ar)
-{
- if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
- if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features))
- ar->wmi.cmd = &wmi_10_2_cmd_map;
- else
- ar->wmi.cmd = &wmi_10x_cmd_map;
-
- ar->wmi.vdev_param = &wmi_10x_vdev_param_map;
- ar->wmi.pdev_param = &wmi_10x_pdev_param_map;
- } else {
- ar->wmi.cmd = &wmi_cmd_map;
- ar->wmi.vdev_param = &wmi_vdev_param_map;
- ar->wmi.pdev_param = &wmi_pdev_param_map;
- }
-
- init_completion(&ar->wmi.service_ready);
- init_completion(&ar->wmi.unified_ready);
-
- return 0;
-}
-
-void ath10k_wmi_detach(struct ath10k *ar)
-{
- int i;
-
- /* free the host memory chunks requested by firmware */
- for (i = 0; i < ar->wmi.num_mem_chunks; i++) {
- dma_free_coherent(ar->dev,
- ar->wmi.mem_chunks[i].len,
- ar->wmi.mem_chunks[i].vaddr,
- ar->wmi.mem_chunks[i].paddr);
- }
-
- ar->wmi.num_mem_chunks = 0;
-}
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index 09daa3e..048ba28 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -222,131 +222,128 @@
#undef SVCSTR
}
-#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id, len) \
- ((svc_id) < (len) && \
- __le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
+#define WMI_SERVICE_IS_ENABLED(wmi_svc_bmap, svc_id) \
+ (__le32_to_cpu((wmi_svc_bmap)[(svc_id)/(sizeof(u32))]) & \
BIT((svc_id)%(sizeof(u32))))
-#define SVCMAP(x, y, len) \
+#define SVCMAP(x, y) \
do { \
- if (WMI_SERVICE_IS_ENABLED((in), (x), (len))) \
+ if (WMI_SERVICE_IS_ENABLED((in), (x))) \
__set_bit(y, out); \
} while (0)
-static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out,
- size_t len)
+static inline void wmi_10x_svc_map(const __le32 *in, unsigned long *out)
{
SVCMAP(WMI_10X_SERVICE_BEACON_OFFLOAD,
- WMI_SERVICE_BEACON_OFFLOAD, len);
+ WMI_SERVICE_BEACON_OFFLOAD);
SVCMAP(WMI_10X_SERVICE_SCAN_OFFLOAD,
- WMI_SERVICE_SCAN_OFFLOAD, len);
+ WMI_SERVICE_SCAN_OFFLOAD);
SVCMAP(WMI_10X_SERVICE_ROAM_OFFLOAD,
- WMI_SERVICE_ROAM_OFFLOAD, len);
+ WMI_SERVICE_ROAM_OFFLOAD);
SVCMAP(WMI_10X_SERVICE_BCN_MISS_OFFLOAD,
- WMI_SERVICE_BCN_MISS_OFFLOAD, len);
+ WMI_SERVICE_BCN_MISS_OFFLOAD);
SVCMAP(WMI_10X_SERVICE_STA_PWRSAVE,
- WMI_SERVICE_STA_PWRSAVE, len);
+ WMI_SERVICE_STA_PWRSAVE);
SVCMAP(WMI_10X_SERVICE_STA_ADVANCED_PWRSAVE,
- WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
+ WMI_SERVICE_STA_ADVANCED_PWRSAVE);
SVCMAP(WMI_10X_SERVICE_AP_UAPSD,
- WMI_SERVICE_AP_UAPSD, len);
+ WMI_SERVICE_AP_UAPSD);
SVCMAP(WMI_10X_SERVICE_AP_DFS,
- WMI_SERVICE_AP_DFS, len);
+ WMI_SERVICE_AP_DFS);
SVCMAP(WMI_10X_SERVICE_11AC,
- WMI_SERVICE_11AC, len);
+ WMI_SERVICE_11AC);
SVCMAP(WMI_10X_SERVICE_BLOCKACK,
- WMI_SERVICE_BLOCKACK, len);
+ WMI_SERVICE_BLOCKACK);
SVCMAP(WMI_10X_SERVICE_PHYERR,
- WMI_SERVICE_PHYERR, len);
+ WMI_SERVICE_PHYERR);
SVCMAP(WMI_10X_SERVICE_BCN_FILTER,
- WMI_SERVICE_BCN_FILTER, len);
+ WMI_SERVICE_BCN_FILTER);
SVCMAP(WMI_10X_SERVICE_RTT,
- WMI_SERVICE_RTT, len);
+ WMI_SERVICE_RTT);
SVCMAP(WMI_10X_SERVICE_RATECTRL,
- WMI_SERVICE_RATECTRL, len);
+ WMI_SERVICE_RATECTRL);
SVCMAP(WMI_10X_SERVICE_WOW,
- WMI_SERVICE_WOW, len);
+ WMI_SERVICE_WOW);
SVCMAP(WMI_10X_SERVICE_RATECTRL_CACHE,
- WMI_SERVICE_RATECTRL_CACHE, len);
+ WMI_SERVICE_RATECTRL_CACHE);
SVCMAP(WMI_10X_SERVICE_IRAM_TIDS,
- WMI_SERVICE_IRAM_TIDS, len);
+ WMI_SERVICE_IRAM_TIDS);
SVCMAP(WMI_10X_SERVICE_BURST,
- WMI_SERVICE_BURST, len);
+ WMI_SERVICE_BURST);
SVCMAP(WMI_10X_SERVICE_SMART_ANTENNA_SW_SUPPORT,
- WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT, len);
+ WMI_SERVICE_SMART_ANTENNA_SW_SUPPORT);
SVCMAP(WMI_10X_SERVICE_FORCE_FW_HANG,
- WMI_SERVICE_FORCE_FW_HANG, len);
+ WMI_SERVICE_FORCE_FW_HANG);
SVCMAP(WMI_10X_SERVICE_SMART_ANTENNA_HW_SUPPORT,
- WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT, len);
+ WMI_SERVICE_SMART_ANTENNA_HW_SUPPORT);
}
-static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out,
- size_t len)
+static inline void wmi_main_svc_map(const __le32 *in, unsigned long *out)
{
SVCMAP(WMI_MAIN_SERVICE_BEACON_OFFLOAD,
- WMI_SERVICE_BEACON_OFFLOAD, len);
+ WMI_SERVICE_BEACON_OFFLOAD);
SVCMAP(WMI_MAIN_SERVICE_SCAN_OFFLOAD,
- WMI_SERVICE_SCAN_OFFLOAD, len);
+ WMI_SERVICE_SCAN_OFFLOAD);
SVCMAP(WMI_MAIN_SERVICE_ROAM_OFFLOAD,
- WMI_SERVICE_ROAM_OFFLOAD, len);
+ WMI_SERVICE_ROAM_OFFLOAD);
SVCMAP(WMI_MAIN_SERVICE_BCN_MISS_OFFLOAD,
- WMI_SERVICE_BCN_MISS_OFFLOAD, len);
+ WMI_SERVICE_BCN_MISS_OFFLOAD);
SVCMAP(WMI_MAIN_SERVICE_STA_PWRSAVE,
- WMI_SERVICE_STA_PWRSAVE, len);
+ WMI_SERVICE_STA_PWRSAVE);
SVCMAP(WMI_MAIN_SERVICE_STA_ADVANCED_PWRSAVE,
- WMI_SERVICE_STA_ADVANCED_PWRSAVE, len);
+ WMI_SERVICE_STA_ADVANCED_PWRSAVE);
SVCMAP(WMI_MAIN_SERVICE_AP_UAPSD,
- WMI_SERVICE_AP_UAPSD, len);
+ WMI_SERVICE_AP_UAPSD);
SVCMAP(WMI_MAIN_SERVICE_AP_DFS,
- WMI_SERVICE_AP_DFS, len);
+ WMI_SERVICE_AP_DFS);
SVCMAP(WMI_MAIN_SERVICE_11AC,
- WMI_SERVICE_11AC, len);
+ WMI_SERVICE_11AC);
SVCMAP(WMI_MAIN_SERVICE_BLOCKACK,
- WMI_SERVICE_BLOCKACK, len);
+ WMI_SERVICE_BLOCKACK);
SVCMAP(WMI_MAIN_SERVICE_PHYERR,
- WMI_SERVICE_PHYERR, len);
+ WMI_SERVICE_PHYERR);
SVCMAP(WMI_MAIN_SERVICE_BCN_FILTER,
- WMI_SERVICE_BCN_FILTER, len);
+ WMI_SERVICE_BCN_FILTER);
SVCMAP(WMI_MAIN_SERVICE_RTT,
- WMI_SERVICE_RTT, len);
+ WMI_SERVICE_RTT);
SVCMAP(WMI_MAIN_SERVICE_RATECTRL,
- WMI_SERVICE_RATECTRL, len);
+ WMI_SERVICE_RATECTRL);
SVCMAP(WMI_MAIN_SERVICE_WOW,
- WMI_SERVICE_WOW, len);
+ WMI_SERVICE_WOW);
SVCMAP(WMI_MAIN_SERVICE_RATECTRL_CACHE,
- WMI_SERVICE_RATECTRL_CACHE, len);
+ WMI_SERVICE_RATECTRL_CACHE);
SVCMAP(WMI_MAIN_SERVICE_IRAM_TIDS,
- WMI_SERVICE_IRAM_TIDS, len);
+ WMI_SERVICE_IRAM_TIDS);
SVCMAP(WMI_MAIN_SERVICE_ARPNS_OFFLOAD,
- WMI_SERVICE_ARPNS_OFFLOAD, len);
+ WMI_SERVICE_ARPNS_OFFLOAD);
SVCMAP(WMI_MAIN_SERVICE_NLO,
- WMI_SERVICE_NLO, len);
+ WMI_SERVICE_NLO);
SVCMAP(WMI_MAIN_SERVICE_GTK_OFFLOAD,
- WMI_SERVICE_GTK_OFFLOAD, len);
+ WMI_SERVICE_GTK_OFFLOAD);
SVCMAP(WMI_MAIN_SERVICE_SCAN_SCH,
- WMI_SERVICE_SCAN_SCH, len);
+ WMI_SERVICE_SCAN_SCH);
SVCMAP(WMI_MAIN_SERVICE_CSA_OFFLOAD,
- WMI_SERVICE_CSA_OFFLOAD, len);
+ WMI_SERVICE_CSA_OFFLOAD);
SVCMAP(WMI_MAIN_SERVICE_CHATTER,
- WMI_SERVICE_CHATTER, len);
+ WMI_SERVICE_CHATTER);
SVCMAP(WMI_MAIN_SERVICE_COEX_FREQAVOID,
- WMI_SERVICE_COEX_FREQAVOID, len);
+ WMI_SERVICE_COEX_FREQAVOID);
SVCMAP(WMI_MAIN_SERVICE_PACKET_POWER_SAVE,
- WMI_SERVICE_PACKET_POWER_SAVE, len);
+ WMI_SERVICE_PACKET_POWER_SAVE);
SVCMAP(WMI_MAIN_SERVICE_FORCE_FW_HANG,
- WMI_SERVICE_FORCE_FW_HANG, len);
+ WMI_SERVICE_FORCE_FW_HANG);
SVCMAP(WMI_MAIN_SERVICE_GPIO,
- WMI_SERVICE_GPIO, len);
+ WMI_SERVICE_GPIO);
SVCMAP(WMI_MAIN_SERVICE_STA_DTIM_PS_MODULATED_DTIM,
- WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM, len);
+ WMI_SERVICE_STA_DTIM_PS_MODULATED_DTIM);
SVCMAP(WMI_MAIN_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG,
- WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG, len);
+ WMI_SERVICE_STA_UAPSD_BASIC_AUTO_TRIG);
SVCMAP(WMI_MAIN_SERVICE_STA_UAPSD_VAR_AUTO_TRIG,
- WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG, len);
+ WMI_SERVICE_STA_UAPSD_VAR_AUTO_TRIG);
SVCMAP(WMI_MAIN_SERVICE_STA_KEEP_ALIVE,
- WMI_SERVICE_STA_KEEP_ALIVE, len);
+ WMI_SERVICE_STA_KEEP_ALIVE);
SVCMAP(WMI_MAIN_SERVICE_TX_ENCAP,
- WMI_SERVICE_TX_ENCAP, len);
+ WMI_SERVICE_TX_ENCAP);
}
#undef SVCMAP
@@ -1431,11 +1428,11 @@
* where FW can access this memory directly (or) by DMA.
*/
__le32 num_mem_reqs;
- struct wlan_host_mem_req mem_reqs[0];
+ struct wlan_host_mem_req mem_reqs[1];
} __packed;
/* This is the definition from 10.X firmware branch */
-struct wmi_10x_service_ready_event {
+struct wmi_service_ready_event_10x {
__le32 sw_version;
__le32 abi_version;
@@ -1470,7 +1467,7 @@
*/
__le32 num_mem_reqs;
- struct wlan_host_mem_req mem_reqs[0];
+ struct wlan_host_mem_req mem_reqs[1];
} __packed;
#define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ)
@@ -1886,26 +1883,38 @@
__le32 size;
} __packed;
-struct wmi_host_mem_chunks {
- __le32 count;
- /* some fw revisions require at least 1 chunk regardless of count */
- struct host_memory_chunk items[1];
-} __packed;
-
struct wmi_init_cmd {
struct wmi_resource_config resource_config;
- struct wmi_host_mem_chunks mem_chunks;
+ __le32 num_host_mem_chunks;
+
+ /*
+ * variable number of host memory chunks.
+ * This should be the last element in the structure
+ */
+ struct host_memory_chunk host_mem_chunks[1];
} __packed;
/* _10x stucture is from 10.X FW API */
struct wmi_init_cmd_10x {
struct wmi_resource_config_10x resource_config;
- struct wmi_host_mem_chunks mem_chunks;
+ __le32 num_host_mem_chunks;
+
+ /*
+ * variable number of host memory chunks.
+ * This should be the last element in the structure
+ */
+ struct host_memory_chunk host_mem_chunks[1];
} __packed;
struct wmi_init_cmd_10_2 {
struct wmi_resource_config_10_2 resource_config;
- struct wmi_host_mem_chunks mem_chunks;
+ __le32 num_host_mem_chunks;
+
+ /*
+ * variable number of host memory chunks.
+ * This should be the last element in the structure
+ */
+ struct host_memory_chunk host_mem_chunks[1];
} __packed;
struct wmi_chan_list_entry {
@@ -1955,11 +1964,6 @@
#define WLAN_SCAN_PARAMS_MAX_BSSID 4
#define WLAN_SCAN_PARAMS_MAX_IE_LEN 256
-/* Values lower than this may be refused by some firmware revisions with a scan
- * completion with a timedout reason.
- */
-#define WMI_SCAN_CHAN_MIN_TIME_MSEC 40
-
/* Scan priority numbers must be sequential, starting with 0 */
enum wmi_scan_priority {
WMI_SCAN_PRIORITY_VERY_LOW = 0,
@@ -1970,7 +1974,7 @@
WMI_SCAN_PRIORITY_COUNT /* number of priorities supported */
};
-struct wmi_start_scan_common {
+struct wmi_start_scan_cmd {
/* Scan ID */
__le32 scan_id;
/* Scan requestor ID */
@@ -2028,25 +2032,95 @@
__le32 probe_delay;
/* Scan control flags */
__le32 scan_ctrl_flags;
-} __packed;
-struct wmi_start_scan_tlvs {
- /* TLV parameters. These includes channel list, ssid list, bssid list,
- * extra ies.
+ /* Burst duration time in msecs */
+ __le32 burst_duration;
+ /*
+ * TLV (tag length value ) paramerters follow the scan_cmd structure.
+ * TLV can contain channel list, bssid list, ssid list and
+ * ie. the TLV tags are defined above;
*/
- u8 tlvs[0];
-} __packed;
-
-struct wmi_start_scan_cmd {
- struct wmi_start_scan_common common;
- __le32 burst_duration_ms;
- struct wmi_start_scan_tlvs tlvs;
} __packed;
/* This is the definition from 10.X firmware branch */
-struct wmi_10x_start_scan_cmd {
- struct wmi_start_scan_common common;
- struct wmi_start_scan_tlvs tlvs;
+struct wmi_start_scan_cmd_10x {
+ /* Scan ID */
+ __le32 scan_id;
+
+ /* Scan requestor ID */
+ __le32 scan_req_id;
+
+ /* VDEV id(interface) that is requesting scan */
+ __le32 vdev_id;
+
+ /* Scan Priority, input to scan scheduler */
+ __le32 scan_priority;
+
+ /* Scan events subscription */
+ __le32 notify_scan_events;
+
+ /* dwell time in msec on active channels */
+ __le32 dwell_time_active;
+
+ /* dwell time in msec on passive channels */
+ __le32 dwell_time_passive;
+
+ /*
+ * min time in msec on the BSS channel,only valid if atleast one
+ * VDEV is active
+ */
+ __le32 min_rest_time;
+
+ /*
+ * max rest time in msec on the BSS channel,only valid if at least
+ * one VDEV is active
+ */
+ /*
+ * the scanner will rest on the bss channel at least min_rest_time
+ * after min_rest_time the scanner will start checking for tx/rx
+ * activity on all VDEVs. if there is no activity the scanner will
+ * switch to off channel. if there is activity the scanner will let
+ * the radio on the bss channel until max_rest_time expires.at
+ * max_rest_time scanner will switch to off channel irrespective of
+ * activity. activity is determined by the idle_time parameter.
+ */
+ __le32 max_rest_time;
+
+ /*
+ * time before sending next set of probe requests.
+ * The scanner keeps repeating probe requests transmission with
+ * period specified by repeat_probe_time.
+ * The number of probe requests specified depends on the ssid_list
+ * and bssid_list
+ */
+ __le32 repeat_probe_time;
+
+ /* time in msec between 2 consequetive probe requests with in a set. */
+ __le32 probe_spacing_time;
+
+ /*
+ * data inactivity time in msec on bss channel that will be used by
+ * scanner for measuring the inactivity.
+ */
+ __le32 idle_time;
+
+ /* maximum time in msec allowed for scan */
+ __le32 max_scan_time;
+
+ /*
+ * delay in msec before sending first probe request after switching
+ * to a channel
+ */
+ __le32 probe_delay;
+
+ /* Scan control flags */
+ __le32 scan_ctrl_flags;
+
+ /*
+ * TLV (tag length value ) paramerters follow the scan_cmd structure.
+ * TLV can contain channel list, bssid list, ssid list and
+ * ie. the TLV tags are defined above;
+ */
} __packed;
struct wmi_ssid_arg {
@@ -2232,25 +2306,94 @@
#define PHY_ERROR_FALSE_RADAR_EXT 0x24
#define PHY_ERROR_RADAR 0x05
-struct wmi_phyerr {
+struct wmi_single_phyerr_rx_hdr {
+ /* TSF timestamp */
__le32 tsf_timestamp;
+
+ /*
+ * Current freq1, freq2
+ *
+ * [7:0]: freq1[lo]
+ * [15:8] : freq1[hi]
+ * [23:16]: freq2[lo]
+ * [31:24]: freq2[hi]
+ */
__le16 freq1;
__le16 freq2;
+
+ /*
+ * Combined RSSI over all chains and channel width for this PHY error
+ *
+ * [7:0]: RSSI combined
+ * [15:8]: Channel width (MHz)
+ * [23:16]: PHY error code
+ * [24:16]: reserved (future use)
+ */
u8 rssi_combined;
u8 chan_width_mhz;
u8 phy_err_code;
u8 rsvd0;
- __le32 rssi_chains[4];
- __le16 nf_chains[4];
+
+ /*
+ * RSSI on chain 0 through 3
+ *
+ * This is formatted the same as the PPDU_START RX descriptor
+ * field:
+ *
+ * [7:0]: pri20
+ * [15:8]: sec20
+ * [23:16]: sec40
+ * [31:24]: sec80
+ */
+
+ __le32 rssi_chain0;
+ __le32 rssi_chain1;
+ __le32 rssi_chain2;
+ __le32 rssi_chain3;
+
+ /*
+ * Last calibrated NF value for chain 0 through 3
+ *
+ * nf_list_1:
+ *
+ * + [15:0] - chain 0
+ * + [31:16] - chain 1
+ *
+ * nf_list_2:
+ *
+ * + [15:0] - chain 2
+ * + [31:16] - chain 3
+ */
+ __le32 nf_list_1;
+ __le32 nf_list_2;
+
+ /* Length of the frame */
__le32 buf_len;
- u8 buf[0];
} __packed;
-struct wmi_phyerr_event {
- __le32 num_phyerrs;
+struct wmi_single_phyerr_rx_event {
+ /* Phy error event header */
+ struct wmi_single_phyerr_rx_hdr hdr;
+ /* frame buffer */
+ u8 bufp[0];
+} __packed;
+
+struct wmi_comb_phyerr_rx_hdr {
+ /* Phy error phy error count */
+ __le32 num_phyerr_events;
__le32 tsf_l32;
__le32 tsf_u32;
- struct wmi_phyerr phyerrs[0];
+} __packed;
+
+struct wmi_comb_phyerr_rx_event {
+ /* Phy error phy error count */
+ struct wmi_comb_phyerr_rx_hdr hdr;
+ /*
+ * frame buffer - contains multiple payloads in the order:
+ * header - payload, header - payload...
+ * (The header is of type: wmi_single_phyerr_rx_hdr)
+ */
+ u8 bufp[0];
} __packed;
#define PHYERR_TLV_SIG 0xBB
@@ -2765,6 +2908,11 @@
WMI_TP_SCALE_SIZE = 5, /* max num of enum */
};
+struct wmi_set_channel_cmd {
+ /* channel (only frequency and mode info are used) */
+ struct wmi_channel chan;
+} __packed;
+
struct wmi_pdev_chanlist_update_event {
/* number of channels */
__le32 num_chan;
@@ -2795,10 +2943,6 @@
struct wmi_channel chan;
} __packed;
-struct wmi_pdev_pktlog_enable_cmd {
- __le32 ev_bitmap;
-} __packed;
-
/* Customize the DSCP (bit) to TID (0-7) mapping for QOS */
#define WMI_DSCP_MAP_MAX (64)
struct wmi_pdev_set_dscp_tid_map_cmd {
@@ -3033,7 +3177,7 @@
* PDEV statistics
* TODO: add all PDEV stats here
*/
-struct wmi_pdev_stats {
+struct wmi_pdev_stats_old {
__le32 chan_nf; /* Channel noise floor */
__le32 tx_frame_count; /* TX frame count */
__le32 rx_frame_count; /* RX frame count */
@@ -3044,8 +3188,15 @@
struct wal_dbg_stats wal; /* WAL dbg stats */
} __packed;
-struct wmi_10x_pdev_stats {
- struct wmi_pdev_stats old;
+struct wmi_pdev_stats_10x {
+ __le32 chan_nf; /* Channel noise floor */
+ __le32 tx_frame_count; /* TX frame count */
+ __le32 rx_frame_count; /* RX frame count */
+ __le32 rx_clear_count; /* rx clear count */
+ __le32 cycle_count; /* cycle count */
+ __le32 phy_err_count; /* Phy error count */
+ __le32 chan_tx_pwr; /* channel tx power */
+ struct wal_dbg_stats wal; /* WAL dbg stats */
__le32 ack_rx_bad;
__le32 rts_bad;
__le32 rts_good;
@@ -3066,14 +3217,16 @@
* peer statistics.
* TODO: add more stats
*/
-struct wmi_peer_stats {
+struct wmi_peer_stats_old {
struct wmi_mac_addr peer_macaddr;
__le32 peer_rssi;
__le32 peer_tx_rate;
} __packed;
-struct wmi_10x_peer_stats {
- struct wmi_peer_stats old;
+struct wmi_peer_stats_10x {
+ struct wmi_mac_addr peer_macaddr;
+ __le32 peer_rssi;
+ __le32 peer_tx_rate;
__le32 peer_rx_rate;
} __packed;
@@ -4559,6 +4712,7 @@
__le32 config_valid;
} __packed;
+#define ATH10K_RTS_MAX 2347
#define ATH10K_FRAGMT_THRESHOLD_MIN 540
#define ATH10K_FRAGMT_THRESHOLD_MAX 2346
@@ -4569,27 +4723,8 @@
/* By default disable power save for IBSS */
#define ATH10K_DEFAULT_ATIM 0
-#define WMI_MAX_MEM_REQS 16
-
-struct wmi_svc_rdy_ev_arg {
- __le32 min_tx_power;
- __le32 max_tx_power;
- __le32 ht_cap;
- __le32 vht_cap;
- __le32 sw_ver0;
- __le32 sw_ver1;
- __le32 phy_capab;
- __le32 num_rf_chains;
- __le32 eeprom_rd;
- __le32 num_mem_reqs;
- const __le32 *service_map;
- size_t service_map_len;
- const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS];
-};
-
struct ath10k;
struct ath10k_vif;
-struct ath10k_fw_stats;
int ath10k_wmi_attach(struct ath10k *ar);
void ath10k_wmi_detach(struct ath10k *ar);
@@ -4601,6 +4736,8 @@
struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len);
int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id);
+int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
+ const struct wmi_channel_arg *);
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
int ath10k_wmi_pdev_resume_target(struct ath10k *ar);
int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g,
@@ -4661,9 +4798,5 @@
enum wmi_force_fw_hang_type type, u32 delay_ms);
int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb);
int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable);
-int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb,
- struct ath10k_fw_stats *stats);
-int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_list);
-int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar);
#endif /* _WMI_H_ */
diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig
index 85fe7d4..614737b 100644
--- a/drivers/net/wireless/ath/ath5k/Kconfig
+++ b/drivers/net/wireless/ath/ath5k/Kconfig
@@ -1,14 +1,13 @@
config ATH5K
tristate "Atheros 5xxx wireless cards support"
depends on m
- depends on (PCI || ATH25) && MAC80211
+ depends on PCI && MAC80211
select ATH_COMMON
select MAC80211_LEDS
- select BPAUTO_LEDS_CLASS
- select BPAUTO_NEW_LEDS
- select BPAUTO_AVERAGE
- select ATH5K_AHB if ATH25
- select ATH5K_PCI if !ATH25
+ select BACKPORT_LEDS_CLASS
+ select BACKPORT_NEW_LEDS
+ select BACKPORT_AVERAGE
+ select ATH5K_PCI
---help---
This module adds support for wireless adapters based on
Atheros 5xxx chipset.
@@ -53,16 +52,9 @@
If unsure, say N.
-config ATH5K_AHB
- bool "Atheros 5xxx AHB bus support"
- depends on ATH25
- ---help---
- This adds support for WiSoC type chipsets of the 5xxx Atheros
- family.
-
config ATH5K_PCI
bool "Atheros 5xxx PCI bus support"
- depends on (!ATH25 && PCI)
+ depends on PCI
---help---
This adds support for PCI type chipsets of the 5xxx Atheros
family.
diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile
index 32a0f67..3c9c2ac 100644
--- a/drivers/net/wireless/ath/ath5k/Makefile
+++ b/drivers/net/wireless/ath/ath5k/Makefile
@@ -17,6 +17,5 @@
ath5k-y += sysfs.o
ath5k-y += mac80211-ops.o
ath5k-$(CPTCFG_ATH5K_DEBUG) += debug.o
-ath5k-$(CPTCFG_ATH5K_AHB) += ahb.o
ath5k-$(CPTCFG_ATH5K_PCI) += pci.o
obj-$(CPTCFG_ATH5K) += ath5k.o
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
deleted file mode 100644
index 8f387cf..0000000
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ /dev/null
@@ -1,234 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Atheros Communications Inc.
- * Copyright (c) 2009 Gabor Juhos <juhosg@openwrt.org>
- * Copyright (c) 2009 Imre Kaloz <kaloz@openwrt.org>
- *
- * 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 <linux/nl80211.h>
-#include <linux/platform_device.h>
-#include <linux/etherdevice.h>
-#include <linux/export.h>
-#include <ath25_platform.h>
-#include "ath5k.h"
-#include "debug.h"
-#include "base.h"
-#include "reg.h"
-
-/* return bus cachesize in 4B word units */
-static void ath5k_ahb_read_cachesize(struct ath_common *common, int *csz)
-{
- *csz = L1_CACHE_BYTES >> 2;
-}
-
-static bool
-ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
-{
- struct ath5k_hw *ah = common->priv;
- struct platform_device *pdev = to_platform_device(ah->dev);
- struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
- u16 *eeprom, *eeprom_end;
-
- eeprom = (u16 *) bcfg->radio;
- eeprom_end = ((void *) bcfg->config) + BOARD_CONFIG_BUFSZ;
-
- eeprom += off;
- if (eeprom > eeprom_end)
- return false;
-
- *data = *eeprom;
- return true;
-}
-
-int ath5k_hw_read_srev(struct ath5k_hw *ah)
-{
- struct platform_device *pdev = to_platform_device(ah->dev);
- struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
- ah->ah_mac_srev = bcfg->devid;
- return 0;
-}
-
-static int ath5k_ahb_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac)
-{
- struct platform_device *pdev = to_platform_device(ah->dev);
- struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
- u8 *cfg_mac;
-
- if (to_platform_device(ah->dev)->id == 0)
- cfg_mac = bcfg->config->wlan0_mac;
- else
- cfg_mac = bcfg->config->wlan1_mac;
-
- memcpy(mac, cfg_mac, ETH_ALEN);
- return 0;
-}
-
-static const struct ath_bus_ops ath_ahb_bus_ops = {
- .ath_bus_type = ATH_AHB,
- .read_cachesize = ath5k_ahb_read_cachesize,
- .eeprom_read = ath5k_ahb_eeprom_read,
- .eeprom_read_mac = ath5k_ahb_eeprom_read_mac,
-};
-
-/*Initialization*/
-static int ath_ahb_probe(struct platform_device *pdev)
-{
- struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
- struct ath5k_hw *ah;
- struct ieee80211_hw *hw;
- struct resource *res;
- void __iomem *mem;
- int irq;
- int ret = 0;
- u32 reg;
-
- if (!dev_get_platdata(&pdev->dev)) {
- dev_err(&pdev->dev, "no platform data specified\n");
- ret = -EINVAL;
- goto err_out;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "no memory resource found\n");
- ret = -ENXIO;
- goto err_out;
- }
-
- mem = ioremap_nocache(res->start, resource_size(res));
- if (mem == NULL) {
- dev_err(&pdev->dev, "ioremap failed\n");
- ret = -ENOMEM;
- goto err_out;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "no IRQ resource found\n");
- ret = -ENXIO;
- goto err_iounmap;
- }
-
- irq = res->start;
-
- hw = ieee80211_alloc_hw(sizeof(struct ath5k_hw), &ath5k_hw_ops);
- if (hw == NULL) {
- dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
- ret = -ENOMEM;
- goto err_iounmap;
- }
-
- ah = hw->priv;
- ah->hw = hw;
- ah->dev = &pdev->dev;
- ah->iobase = mem;
- ah->irq = irq;
- ah->devid = bcfg->devid;
-
- if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
- /* Enable WMAC AHB arbitration */
- reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
- reg |= AR5K_AR2315_AHB_ARB_CTL_WLAN;
- iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
-
- /* Enable global WMAC swapping */
- reg = ioread32((void __iomem *) AR5K_AR2315_BYTESWAP);
- reg |= AR5K_AR2315_BYTESWAP_WMAC;
- iowrite32(reg, (void __iomem *) AR5K_AR2315_BYTESWAP);
- } else {
- /* Enable WMAC DMA access (assuming 5312 or 231x*/
- /* TODO: check other platforms */
- reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
- if (to_platform_device(ah->dev)->id == 0)
- reg |= AR5K_AR5312_ENABLE_WLAN0;
- else
- reg |= AR5K_AR5312_ENABLE_WLAN1;
- iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
-
- /*
- * On a dual-band AR5312, the multiband radio is only
- * used as pass-through. Disable 2 GHz support in the
- * driver for it
- */
- if (to_platform_device(ah->dev)->id == 0 &&
- (bcfg->config->flags & (BD_WLAN0 | BD_WLAN1)) ==
- (BD_WLAN1 | BD_WLAN0))
- ah->ah_capabilities.cap_needs_2GHz_ovr = true;
- else
- ah->ah_capabilities.cap_needs_2GHz_ovr = false;
- }
-
- ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
- if (ret != 0) {
- dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
- ret = -ENODEV;
- goto err_free_hw;
- }
-
- platform_set_drvdata(pdev, hw);
-
- return 0;
-
- err_free_hw:
- ieee80211_free_hw(hw);
- err_iounmap:
- iounmap(mem);
- err_out:
- return ret;
-}
-
-static int ath_ahb_remove(struct platform_device *pdev)
-{
- struct ar231x_board_config *bcfg = dev_get_platdata(&pdev->dev);
- struct ieee80211_hw *hw = platform_get_drvdata(pdev);
- struct ath5k_hw *ah;
- u32 reg;
-
- if (!hw)
- return 0;
-
- ah = hw->priv;
-
- if (bcfg->devid >= AR5K_SREV_AR2315_R6) {
- /* Disable WMAC AHB arbitration */
- reg = ioread32((void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
- reg &= ~AR5K_AR2315_AHB_ARB_CTL_WLAN;
- iowrite32(reg, (void __iomem *) AR5K_AR2315_AHB_ARB_CTL);
- } else {
- /*Stop DMA access */
- reg = ioread32((void __iomem *) AR5K_AR5312_ENABLE);
- if (to_platform_device(ah->dev)->id == 0)
- reg &= ~AR5K_AR5312_ENABLE_WLAN0;
- else
- reg &= ~AR5K_AR5312_ENABLE_WLAN1;
- iowrite32(reg, (void __iomem *) AR5K_AR5312_ENABLE);
- }
-
- ath5k_deinit_ah(ah);
- iounmap(ah->iobase);
- ieee80211_free_hw(hw);
-
- return 0;
-}
-
-static struct platform_driver ath_ahb_driver = {
- .probe = ath_ahb_probe,
- .remove = ath_ahb_remove,
- .driver = {
- .name = "ar231x-wmac",
- .owner = THIS_MODULE,
- },
-};
-
-module_platform_driver(ath_ahb_driver);
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index cc701f1..e43e883 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -1647,32 +1647,6 @@
return &(ath5k_hw_common(ah)->regulatory);
}
-#ifdef CPTCFG_ATH5K_AHB
-#define AR5K_AR2315_PCI_BASE ((void __iomem *)0xb0100000)
-
-static inline void __iomem *ath5k_ahb_reg(struct ath5k_hw *ah, u16 reg)
-{
- /* On AR2315 and AR2317 the PCI clock domain registers
- * are outside of the WMAC register space */
- if (unlikely((reg >= 0x4000) && (reg < 0x5000) &&
- (ah->ah_mac_srev >= AR5K_SREV_AR2315_R6)))
- return AR5K_AR2315_PCI_BASE + reg;
-
- return ah->iobase + reg;
-}
-
-static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
-{
- return ioread32(ath5k_ahb_reg(ah, reg));
-}
-
-static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg)
-{
- iowrite32(val, ath5k_ahb_reg(ah, reg));
-}
-
-#else
-
static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg)
{
return ioread32(ah->iobase + reg);
@@ -1683,8 +1657,6 @@
iowrite32(val, ah->iobase + reg);
}
-#endif
-
static inline enum ath_bus_type ath5k_get_bus_type(struct ath5k_hw *ah)
{
return ath5k_hw_common(ah)->bus_ops->ath_bus_type;
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 65cc4b3..3f5fae0 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -99,15 +99,6 @@
/* Known SREVs */
static const struct ath5k_srev_name srev_names[] = {
-#ifdef CPTCFG_ATH5K_AHB
- { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R2 },
- { "5312", AR5K_VERSION_MAC, AR5K_SREV_AR5312_R7 },
- { "2313", AR5K_VERSION_MAC, AR5K_SREV_AR2313_R8 },
- { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R6 },
- { "2315", AR5K_VERSION_MAC, AR5K_SREV_AR2315_R7 },
- { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R1 },
- { "2317", AR5K_VERSION_MAC, AR5K_SREV_AR2317_R2 },
-#else
{ "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 },
{ "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 },
{ "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A },
@@ -126,7 +117,6 @@
{ "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 },
{ "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 },
{ "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 },
-#endif
{ "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN },
{ "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 },
{ "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 },
@@ -142,10 +132,6 @@
{ "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 },
{ "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 },
{ "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 },
-#ifdef CPTCFG_ATH5K_AHB
- { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 },
- { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 },
-#endif
{ "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN },
};
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 201d1de..0beb7e7 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -163,20 +163,14 @@
{
int ret = 0;
struct ieee80211_hw *hw = ah->hw;
-#ifndef CPTCFG_ATH5K_AHB
struct pci_dev *pdev = ah->pdev;
-#endif
char name[ATH5K_LED_MAX_NAME_LEN + 1];
const struct pci_device_id *match;
if (!ah->pdev)
return 0;
-#ifdef CPTCFG_ATH5K_AHB
- match = NULL;
-#else
match = pci_match_id(&ath5k_led_devices[0], pdev);
-#endif
if (match) {
__set_bit(ATH_STAT_LEDSOFT, ah->status);
ah->led_pin = ATH_PIN(match->driver_data);
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 19eab2a..ab2709a 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -547,9 +547,7 @@
static void
-ath5k_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+ath5k_sw_scan_start(struct ieee80211_hw *hw)
{
struct ath5k_hw *ah = hw->priv;
if (!ah->assoc)
@@ -558,7 +556,7 @@
static void
-ath5k_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+ath5k_sw_scan_complete(struct ieee80211_hw *hw)
{
struct ath5k_hw *ah = hw->priv;
ath5k_hw_set_ledstate(ah, ah->assoc ?
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index ddaad71..0583c69 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -225,7 +225,13 @@
} else {
switch (queue_type) {
case AR5K_TX_QUEUE_DATA:
- queue = queue_info->tqi_subtype;
+ for (queue = AR5K_TX_QUEUE_ID_DATA_MIN;
+ ah->ah_txq[queue].tqi_type !=
+ AR5K_TX_QUEUE_INACTIVE; queue++) {
+
+ if (queue > AR5K_TX_QUEUE_ID_DATA_MAX)
+ return -EINVAL;
+ }
break;
case AR5K_TX_QUEUE_UAPSD:
queue = AR5K_TX_QUEUE_ID_UAPSD;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 03799d2..04d3c2e 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -2976,11 +2976,11 @@
static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
- struct station_del_parameters *params)
+ const u8 *mac)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
- const u8 *addr = params->mac ? params->mac : bcast_addr;
+ const u8 *addr = mac ? mac : bcast_addr;
return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH,
addr, WLAN_REASON_PREV_AUTH_NOT_VALID);
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h
index 4f82e86..05debf7 100644
--- a/drivers/net/wireless/ath/ath6kl/common.h
+++ b/drivers/net/wireless/ath/ath6kl/common.h
@@ -22,7 +22,7 @@
#define ATH6KL_MAX_IE 256
-__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...);
+__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
/*
* Reflects the version of binary interface exposed by ATH6KL target
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
index fc2b18a..f596535 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.c
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -37,64 +37,76 @@
#define ATH6KL_FWLOG_VALID_MASK 0x1ffff
-void ath6kl_printk(const char *level, const char *fmt, ...)
+int ath6kl_printk(const char *level, const char *fmt, ...)
{
struct va_format vaf;
va_list args;
+ int rtn;
va_start(args, fmt);
vaf.fmt = fmt;
vaf.va = &args;
- printk("%sath6kl: %pV", level, &vaf);
+ rtn = printk("%sath6kl: %pV", level, &vaf);
va_end(args);
+
+ return rtn;
}
EXPORT_SYMBOL(ath6kl_printk);
-void ath6kl_info(const char *fmt, ...)
+int ath6kl_info(const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
};
va_list args;
+ int ret;
va_start(args, fmt);
vaf.va = &args;
- ath6kl_printk(KERN_INFO, "%pV", &vaf);
+ ret = ath6kl_printk(KERN_INFO, "%pV", &vaf);
trace_ath6kl_log_info(&vaf);
va_end(args);
+
+ return ret;
}
EXPORT_SYMBOL(ath6kl_info);
-void ath6kl_err(const char *fmt, ...)
+int ath6kl_err(const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
};
va_list args;
+ int ret;
va_start(args, fmt);
vaf.va = &args;
- ath6kl_printk(KERN_ERR, "%pV", &vaf);
+ ret = ath6kl_printk(KERN_ERR, "%pV", &vaf);
trace_ath6kl_log_err(&vaf);
va_end(args);
+
+ return ret;
}
EXPORT_SYMBOL(ath6kl_err);
-void ath6kl_warn(const char *fmt, ...)
+int ath6kl_warn(const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
};
va_list args;
+ int ret;
va_start(args, fmt);
vaf.va = &args;
- ath6kl_printk(KERN_WARNING, "%pV", &vaf);
+ ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf);
trace_ath6kl_log_warn(&vaf);
va_end(args);
+
+ return ret;
}
EXPORT_SYMBOL(ath6kl_warn);
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index 5356e42..01debd4 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -50,10 +50,10 @@
};
extern unsigned int debug_mask;
-__printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...);
-__printf(1, 2) void ath6kl_info(const char *fmt, ...);
-__printf(1, 2) void ath6kl_err(const char *fmt, ...);
-__printf(1, 2) void ath6kl_warn(const char *fmt, ...);
+__printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...);
+__printf(1, 2) int ath6kl_info(const char *fmt, ...);
+__printf(1, 2) int ath6kl_err(const char *fmt, ...);
+__printf(1, 2) int ath6kl_warn(const char *fmt, ...);
enum ath6kl_war {
ATH6KL_WAR_INVALID_RATE,
@@ -81,9 +81,10 @@
void ath6kl_debug_cleanup(struct ath6kl *ar);
#else
-static inline void ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
- const char *fmt, ...)
+static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
+ const char *fmt, ...)
{
+ return 0;
}
static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c
index a0b89b5..af439e7 100644
--- a/drivers/net/wireless/ath/ath6kl/usb.c
+++ b/drivers/net/wireless/ath/ath6kl/usb.c
@@ -1193,10 +1193,18 @@
return 0;
}
+static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf)
+{
+ if (usb_get_intfdata(intf))
+ ath6kl_usb_remove(intf);
+ return 0;
+}
+
#else
#define ath6kl_usb_pm_suspend NULL
#define ath6kl_usb_pm_resume NULL
+#define ath6kl_usb_pm_reset_resume NULL
#endif
@@ -1214,6 +1222,7 @@
.probe = ath6kl_usb_probe,
.suspend = ath6kl_usb_pm_suspend,
.resume = ath6kl_usb_pm_resume,
+ .reset_resume = ath6kl_usb_pm_reset_resume,
.disconnect = ath6kl_usb_remove,
.id_table = ath6kl_usb_ids,
.supports_autosuspend = true,
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 9d490f2..1acecc2 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -5,8 +5,6 @@
tristate
depends on m
select ATH_COMMON
- depends on DEBUG_FS
- depends on RELAY
config ATH9K_DFS_DEBUGFS
def_bool y
depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED
@@ -25,8 +23,8 @@
depends on MAC80211 && HAS_DMA
select ATH9K_HW
select MAC80211_LEDS
- select BPAUTO_LEDS_CLASS
- select BPAUTO_NEW_LEDS
+ select BACKPORT_LEDS_CLASS
+ select BACKPORT_NEW_LEDS
select ATH9K_COMMON
---help---
This module adds support for wireless adapters based on
@@ -153,19 +151,14 @@
for multi-channel concurrency. Enable this if P2P PowerSave support
is required.
-config ATH9K_PCOEM
- bool "Atheros ath9k support for PC OEM cards" if EXPERT
- depends on ATH9K
- default y
-
config ATH9K_HTC
tristate "Atheros HTC based wireless cards support"
depends on m
depends on USB && MAC80211
select ATH9K_HW
select MAC80211_LEDS
- select BPAUTO_LEDS_CLASS
- select BPAUTO_NEW_LEDS
+ select BACKPORT_LEDS_CLASS
+ select BACKPORT_NEW_LEDS
select ATH9K_COMMON
---help---
Support for Atheros HTC based cards.
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 18e21a8..ccee747 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -16,7 +16,8 @@
ath9k-$(CPTCFG_ATH9K_TX99) += tx99.o
ath9k-$(CPTCFG_ATH9K_WOW) += wow.o
-ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o
+ath9k-$(CPTCFG_ATH9K_DEBUGFS) += debug.o \
+ spectral.o
ath9k-$(CPTCFG_ATH9K_STATION_STATISTICS) += debug_sta.o
@@ -31,6 +32,7 @@
ar5008_phy.o \
ar9002_calib.o \
ar9003_calib.o \
+ ar9003_rtt.o \
calib.o \
eeprom.o \
eeprom_def.o \
@@ -48,8 +50,6 @@
ath9k_hw-$(CPTCFG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \
ar9003_mci.o
-ath9k_hw-$(CPTCFG_ATH9K_PCOEM) += ar9003_rtt.o
-
ath9k_hw-$(CPTCFG_ATH9K_DYNACK) += dynack.o
obj-$(CPTCFG_ATH9K_HW) += ath9k_hw.o
@@ -58,8 +58,7 @@
ath9k_common-y:= common.o \
common-init.o \
common-beacon.o \
- common-debug.o \
- common-spectral.o
+ common-debug.o
ath9k_htc-y += htc_hst.o \
hif_usb.o \
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index e000c4c..4173838 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -175,6 +175,7 @@
.remove = ath_ahb_remove,
.driver = {
.name = "ath9k",
+ .owner = THIS_MODULE,
},
.id_table = ath9k_platform_id_table,
};
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
index 5829074..b72d0be 100644
--- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c
@@ -1190,7 +1190,7 @@
static void ar5008_hw_set_radar_params(struct ath_hw *ah,
struct ath_hw_radar_conf *conf)
{
- u32 radar_0 = 0, radar_1;
+ u32 radar_0 = 0, radar_1 = 0;
if (!conf) {
REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
@@ -1204,9 +1204,6 @@
radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
- radar_1 = REG_READ(ah, AR_PHY_RADAR_1);
- radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH |
- AR_PHY_RADAR_1_RELPWR_THRESH);
radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
@@ -1228,7 +1225,7 @@
conf->fir_power = -33;
conf->radar_rssi = 20;
conf->pulse_height = 10;
- conf->pulse_rssi = 15;
+ conf->pulse_rssi = 24;
conf->pulse_inband = 15;
conf->pulse_maxlen = 255;
conf->pulse_inband_step = 12;
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 42190b6..cdc7400 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -657,29 +657,31 @@
ar9280_hw_olc_temp_compensation(ah);
}
-static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
- u8 rxchainmask, bool longcal)
+static bool ar9002_hw_calibrate(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 rxchainmask,
+ bool longcal)
{
+ bool iscaldone = true;
struct ath9k_cal_list *currCal = ah->cal_list_curr;
- bool nfcal, nfcal_pending = false, percal_pending;
- int ret;
+ bool nfcal, nfcal_pending = false;
nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
if (ah->caldata)
nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
- percal_pending = (currCal &&
- (currCal->calState == CAL_RUNNING ||
- currCal->calState == CAL_WAITING));
+ if (currCal && !nfcal &&
+ (currCal->calState == CAL_RUNNING ||
+ currCal->calState == CAL_WAITING)) {
+ iscaldone = ar9002_hw_per_calibration(ah, chan,
+ rxchainmask, currCal);
+ if (iscaldone) {
+ ah->cal_list_curr = currCal = currCal->calNext;
- if (percal_pending && !nfcal) {
- if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal))
- return 0;
-
- ah->cal_list_curr = currCal = currCal->calNext;
- if (currCal->calState == CAL_WAITING) {
- ath9k_hw_reset_calibration(ah, currCal);
- return 0;
+ if (currCal->calState == CAL_WAITING) {
+ iscaldone = false;
+ ath9k_hw_reset_calibration(ah, currCal);
+ }
}
}
@@ -696,9 +698,7 @@
* NF is slow time-variant, so it is OK to use a
* historical value.
*/
- ret = ath9k_hw_loadnf(ah, ah->curchan);
- if (ret < 0)
- return ret;
+ ath9k_hw_loadnf(ah, ah->curchan);
}
if (longcal) {
@@ -709,7 +709,7 @@
}
}
- return !percal_pending;
+ return iscaldone;
}
/* Carrier leakage Calibration fix */
@@ -856,8 +856,6 @@
/* Do PA Calibration */
ar9002_hw_pa_cal(ah, true);
- ath9k_hw_loadnf(ah, chan);
- ath9k_hw_start_nfcal(ah, true);
if (ah->caldata)
set_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
index f816909..2a93519 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c
@@ -281,7 +281,7 @@
ACCESS_ONCE(ads->ds_ctl0) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- | SM(i->txpower[0], AR_XmitPower0)
+ | SM(i->txpower, AR_XmitPower0)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
@@ -307,9 +307,9 @@
| set11nRateFlags(i->rates, 3)
| SM(i->rtscts_rate, AR_RTSCTSRate);
- ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower[1], AR_XmitPower1);
- ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower[2], AR_XmitPower2);
- ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower[3], AR_XmitPower3);
+ ACCESS_ONCE(ads->ds_ctl9) = SM(i->txpower, AR_XmitPower1);
+ ACCESS_ONCE(ads->ds_ctl10) = SM(i->txpower, AR_XmitPower2);
+ ACCESS_ONCE(ads->ds_ctl11) = SM(i->txpower, AR_XmitPower3);
}
static int ar9002_hw_proc_txdesc(struct ath_hw *ah, void *ds,
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
index 757e0e0..5d71361 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c
@@ -643,12 +643,9 @@
* and fix otherwise.
*/
count = param->count;
- if (param->endless) {
- if (AR_SREV_9271(ah))
- count = 0;
- else
- count = 0x80;
- } else if (count & 0x80)
+ if (param->endless)
+ count = 0x80;
+ else if (count & 0x80)
count = 0x7f;
REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 06ab71d..ac8301e 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -121,12 +121,13 @@
return iscaldone;
}
-static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan,
- u8 rxchainmask, bool longcal)
+static bool ar9003_hw_calibrate(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 rxchainmask,
+ bool longcal)
{
bool iscaldone = true;
struct ath9k_cal_list *currCal = ah->cal_list_curr;
- int ret;
/*
* For given calibration:
@@ -162,9 +163,7 @@
* NF is slow time-variant, so it is OK to use a historical
* value.
*/
- ret = ath9k_hw_loadnf(ah, ah->curchan);
- if (ret < 0)
- return ret;
+ ath9k_hw_loadnf(ah, ah->curchan);
/* start NF calibration, without updating BB NF register */
ath9k_hw_start_nfcal(ah, false);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index 278afac..ceafa9a 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -4079,28 +4079,27 @@
static void ar9003_hw_thermometer_apply(struct ath_hw *ah)
{
- struct ath9k_hw_capabilities *pCap = &ah->caps;
int thermometer = ar9003_hw_get_thermometer(ah);
u8 therm_on = (thermometer < 0) ? 0 : 1;
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
- if (pCap->chip_chainmask & BIT(1))
+ if (ah->caps.tx_chainmask & BIT(1))
REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
- if (pCap->chip_chainmask & BIT(2))
+ if (ah->caps.tx_chainmask & BIT(2))
REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on);
therm_on = (thermometer < 0) ? 0 : (thermometer == 0);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
- if (pCap->chip_chainmask & BIT(1)) {
+ if (ah->caps.tx_chainmask & BIT(1)) {
therm_on = (thermometer < 0) ? 0 : (thermometer == 1);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
}
- if (pCap->chip_chainmask & BIT(2)) {
+ if (ah->caps.tx_chainmask & BIT(2)) {
therm_on = (thermometer < 0) ? 0 : (thermometer == 2);
REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4,
AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on);
@@ -4377,25 +4376,6 @@
targetPowerArray, numPiers);
}
-static void ar9003_hw_selfgen_tpc_txpower(struct ath_hw *ah,
- struct ath9k_channel *chan,
- u8 *pwr_array)
-{
- u32 val;
-
- /* target power values for self generated frames (ACK,RTS/CTS) */
- if (IS_CHAN_2GHZ(chan)) {
- val = SM(pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_ACK) |
- SM(pwr_array[ALL_TARGET_LEGACY_1L_5L], AR_TPC_CTS) |
- SM(0x3f, AR_TPC_CHIRP) | SM(0x3f, AR_TPC_RPT);
- } else {
- val = SM(pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_ACK) |
- SM(pwr_array[ALL_TARGET_LEGACY_6_24], AR_TPC_CTS) |
- SM(0x3f, AR_TPC_CHIRP) | SM(0x3f, AR_TPC_RPT);
- }
- REG_WRITE(ah, AR_TPC, val);
-}
-
/* Set tx power registers to array of values passed in */
static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
{
@@ -5331,7 +5311,6 @@
struct ar9300_modal_eep_header *modal_hdr;
u8 targetPowerValT2[ar9300RateSize];
u8 target_power_val_t2_eep[ar9300RateSize];
- u8 targetPowerValT2_tpc[ar9300RateSize];
unsigned int i = 0, paprd_scale_factor = 0;
u8 pwr_idx, min_pwridx = 0;
@@ -5383,9 +5362,6 @@
twiceAntennaReduction,
powerLimit);
- memcpy(targetPowerValT2_tpc, targetPowerValT2,
- sizeof(targetPowerValT2));
-
if (ar9003_is_paprd_enabled(ah)) {
for (i = 0; i < ar9300RateSize; i++) {
if ((ah->paprd_ratemask & (1 << i)) &&
@@ -5419,30 +5395,6 @@
ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
ar9003_hw_calibration_apply(ah, chan->channel);
ar9003_paprd_set_txpower(ah, chan, targetPowerValT2);
-
- ar9003_hw_selfgen_tpc_txpower(ah, chan, targetPowerValT2);
-
- /* TPC initializations */
- if (ah->tpc_enabled) {
- u32 val;
-
- ar9003_hw_init_rate_txpower(ah, targetPowerValT2_tpc, chan);
-
- /* Enable TPC */
- REG_WRITE(ah, AR_PHY_PWRTX_MAX,
- AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE);
- /* Disable per chain power reduction */
- val = REG_READ(ah, AR_PHY_POWER_TX_SUB);
- if (AR_SREV_9340(ah))
- REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
- val & 0xFFFFFFC0);
- else
- REG_WRITE(ah, AR_PHY_POWER_TX_SUB,
- val & 0xFFFFF000);
- } else {
- /* Disable TPC */
- REG_WRITE(ah, AR_PHY_PWRTX_MAX, 0);
- }
}
static u16 ath9k_hw_ar9300_get_spur_channel(struct ath_hw *ah,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index 06ad217..ddef9ee 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -333,29 +333,12 @@
qca953x_1p0_soc_preamble);
INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST],
qca953x_1p0_soc_postamble);
-
- if (AR_SREV_9531_20(ah)) {
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- qca953x_2p0_common_wo_xlna_rx_gain_table);
- INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
- qca953x_2p0_common_wo_xlna_rx_gain_bounds);
- } else {
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- qca953x_1p0_common_wo_xlna_rx_gain_table);
- INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
- qca953x_1p0_common_wo_xlna_rx_gain_bounds);
- }
-
- if (AR_SREV_9531_20(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- qca953x_2p0_modes_no_xpa_tx_gain_table);
- else if (AR_SREV_9531_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- qca953x_1p1_modes_no_xpa_tx_gain_table);
- else
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- qca953x_1p0_modes_no_xpa_tx_gain_table);
-
+ INIT_INI_ARRAY(&ah->iniModesRxGain,
+ qca953x_1p0_common_wo_xlna_rx_gain_table);
+ INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
+ qca953x_1p0_common_wo_xlna_rx_gain_bounds);
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ qca953x_1p0_modes_no_xpa_tx_gain_table);
INIT_INI_ARRAY(&ah->iniModesFastClock,
qca953x_1p0_modes_fast_clock);
} else if (AR_SREV_9580(ah)) {
@@ -535,15 +518,9 @@
else if (AR_SREV_9550(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar955x_1p0_modes_xpa_tx_gain_table);
- else if (AR_SREV_9531_10(ah))
+ else if (AR_SREV_9531(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
- qca953x_1p0_modes_xpa_tx_gain_table);
- else if (AR_SREV_9531_11(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- qca953x_1p1_modes_xpa_tx_gain_table);
- else if (AR_SREV_9531_20(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- qca953x_2p0_modes_xpa_tx_gain_table);
+ qca953x_1p0_modes_xpa_tx_gain_table);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_lowest_ob_db_tx_gain_table);
@@ -585,10 +562,7 @@
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar955x_1p0_modes_no_xpa_tx_gain_table);
else if (AR_SREV_9531(ah)) {
- if (AR_SREV_9531_20(ah))
- INIT_INI_ARRAY(&ah->iniModesTxGain,
- qca953x_2p0_modes_no_xpa_tx_gain_table);
- else if (AR_SREV_9531_11(ah))
+ if (AR_SREV_9531_11(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
qca953x_1p1_modes_no_xpa_tx_gain_table);
else
@@ -696,6 +670,9 @@
if (AR_SREV_9485_11_OR_LATER(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9485Modes_green_ob_db_tx_gain_1_1);
+ else if (AR_SREV_9340(ah))
+ INIT_INI_ARRAY(&ah->iniModesTxGain,
+ ar9340Modes_ub124_tx_gain_table_1p0);
else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesTxGain,
ar9580_1p0_type5_tx_gain_table);
@@ -815,16 +792,11 @@
ar955x_1p0_common_wo_xlna_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
ar955x_1p0_common_wo_xlna_rx_gain_bounds);
- } else if (AR_SREV_9531_10(ah) || AR_SREV_9531_11(ah)) {
+ } else if (AR_SREV_9531(ah)) {
INIT_INI_ARRAY(&ah->iniModesRxGain,
qca953x_1p0_common_wo_xlna_rx_gain_table);
INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
qca953x_1p0_common_wo_xlna_rx_gain_bounds);
- } else if (AR_SREV_9531_20(ah)) {
- INIT_INI_ARRAY(&ah->iniModesRxGain,
- qca953x_2p0_common_wo_xlna_rx_gain_table);
- INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds,
- qca953x_2p0_common_wo_xlna_rx_gain_bounds);
} else if (AR_SREV_9580(ah))
INIT_INI_ARRAY(&ah->iniModesRxGain,
ar9580_1p0_wo_xlna_rx_gain_table);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index da84b70..057b165 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -101,7 +101,7 @@
ACCESS_ONCE(ads->ctl11) = (i->pkt_len & AR_FrameLen)
| (i->flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0)
- | SM(i->txpower[0], AR_XmitPower0)
+ | SM(i->txpower, AR_XmitPower0)
| (i->flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0)
| (i->keyix != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0)
| (i->flags & ATH9K_TXDESC_LOWRXCHAIN ? AR_LowRxChain : 0)
@@ -152,9 +152,9 @@
ACCESS_ONCE(ads->ctl19) = AR_Not_Sounding;
- ACCESS_ONCE(ads->ctl20) = SM(i->txpower[1], AR_XmitPower1);
- ACCESS_ONCE(ads->ctl21) = SM(i->txpower[2], AR_XmitPower2);
- ACCESS_ONCE(ads->ctl22) = SM(i->txpower[3], AR_XmitPower3);
+ ACCESS_ONCE(ads->ctl20) = SM(i->txpower, AR_XmitPower1);
+ ACCESS_ONCE(ads->ctl21) = SM(i->txpower, AR_XmitPower2);
+ ACCESS_ONCE(ads->ctl22) = SM(i->txpower, AR_XmitPower3);
}
static u16 ar9003_calc_ptr_chksum(struct ar9003_txc *ads)
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index d20a39e..fbe3059 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -18,21 +18,6 @@
#include "hw.h"
#include "ar9003_phy.h"
-#define AR9300_OFDM_RATES 8
-#define AR9300_HT_SS_RATES 8
-#define AR9300_HT_DS_RATES 8
-#define AR9300_HT_TS_RATES 8
-
-#define AR9300_11NA_OFDM_SHIFT 0
-#define AR9300_11NA_HT_SS_SHIFT 8
-#define AR9300_11NA_HT_DS_SHIFT 16
-#define AR9300_11NA_HT_TS_SHIFT 24
-
-#define AR9300_11NG_OFDM_SHIFT 4
-#define AR9300_11NG_HT_SS_SHIFT 12
-#define AR9300_11NG_HT_DS_SHIFT 20
-#define AR9300_11NG_HT_TS_SHIFT 28
-
static const int firstep_table[] =
/* level: 0 1 2 3 4 5 6 7 8 */
{ -4, -2, 0, 2, 4, 6, 8, 10, 12 }; /* lvl 0-8, default 2 */
@@ -55,71 +40,6 @@
static const int m1ThreshExt_off = 127;
static const int m2ThreshExt_off = 127;
-static const u8 ofdm2pwr[] = {
- ALL_TARGET_LEGACY_6_24,
- ALL_TARGET_LEGACY_6_24,
- ALL_TARGET_LEGACY_6_24,
- ALL_TARGET_LEGACY_6_24,
- ALL_TARGET_LEGACY_6_24,
- ALL_TARGET_LEGACY_36,
- ALL_TARGET_LEGACY_48,
- ALL_TARGET_LEGACY_54
-};
-
-static const u8 mcs2pwr_ht20[] = {
- ALL_TARGET_HT20_0_8_16,
- ALL_TARGET_HT20_1_3_9_11_17_19,
- ALL_TARGET_HT20_1_3_9_11_17_19,
- ALL_TARGET_HT20_1_3_9_11_17_19,
- ALL_TARGET_HT20_4,
- ALL_TARGET_HT20_5,
- ALL_TARGET_HT20_6,
- ALL_TARGET_HT20_7,
- ALL_TARGET_HT20_0_8_16,
- ALL_TARGET_HT20_1_3_9_11_17_19,
- ALL_TARGET_HT20_1_3_9_11_17_19,
- ALL_TARGET_HT20_1_3_9_11_17_19,
- ALL_TARGET_HT20_12,
- ALL_TARGET_HT20_13,
- ALL_TARGET_HT20_14,
- ALL_TARGET_HT20_15,
- ALL_TARGET_HT20_0_8_16,
- ALL_TARGET_HT20_1_3_9_11_17_19,
- ALL_TARGET_HT20_1_3_9_11_17_19,
- ALL_TARGET_HT20_1_3_9_11_17_19,
- ALL_TARGET_HT20_20,
- ALL_TARGET_HT20_21,
- ALL_TARGET_HT20_22,
- ALL_TARGET_HT20_23
-};
-
-static const u8 mcs2pwr_ht40[] = {
- ALL_TARGET_HT40_0_8_16,
- ALL_TARGET_HT40_1_3_9_11_17_19,
- ALL_TARGET_HT40_1_3_9_11_17_19,
- ALL_TARGET_HT40_1_3_9_11_17_19,
- ALL_TARGET_HT40_4,
- ALL_TARGET_HT40_5,
- ALL_TARGET_HT40_6,
- ALL_TARGET_HT40_7,
- ALL_TARGET_HT40_0_8_16,
- ALL_TARGET_HT40_1_3_9_11_17_19,
- ALL_TARGET_HT40_1_3_9_11_17_19,
- ALL_TARGET_HT40_1_3_9_11_17_19,
- ALL_TARGET_HT40_12,
- ALL_TARGET_HT40_13,
- ALL_TARGET_HT40_14,
- ALL_TARGET_HT40_15,
- ALL_TARGET_HT40_0_8_16,
- ALL_TARGET_HT40_1_3_9_11_17_19,
- ALL_TARGET_HT40_1_3_9_11_17_19,
- ALL_TARGET_HT40_1_3_9_11_17_19,
- ALL_TARGET_HT40_20,
- ALL_TARGET_HT40_21,
- ALL_TARGET_HT40_22,
- ALL_TARGET_HT40_23,
-};
-
/**
* ar9003_hw_set_channel - set channel on single-chip device
* @ah: atheros hardware structure
@@ -744,19 +664,6 @@
ah->enabled_cals |= TX_CL_CAL;
else
ah->enabled_cals &= ~TX_CL_CAL;
-
- if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) {
- if (ah->is_clk_25mhz) {
- REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
- REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
- REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae);
- } else {
- REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
- REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
- REG_WRITE(ah, AR_SLP32_INC, 0x0001e800);
- }
- udelay(100);
- }
}
static void ar9003_hw_prog_ini(struct ath_hw *ah,
@@ -1441,7 +1348,7 @@
struct ath_hw_radar_conf *conf)
{
unsigned int regWrites = 0;
- u32 radar_0 = 0, radar_1;
+ u32 radar_0 = 0, radar_1 = 0;
if (!conf) {
REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA);
@@ -1455,9 +1362,6 @@
radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI);
radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND);
- radar_1 = REG_READ(ah, AR_PHY_RADAR_1);
- radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH |
- AR_PHY_RADAR_1_RELPWR_THRESH);
radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI;
radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK;
radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN);
@@ -1484,7 +1388,7 @@
conf->fir_power = -28;
conf->radar_rssi = 0;
conf->pulse_height = 10;
- conf->pulse_rssi = 15;
+ conf->pulse_rssi = 24;
conf->pulse_inband = 8;
conf->pulse_maxlen = 255;
conf->pulse_inband_step = 12;
@@ -1879,100 +1783,6 @@
ATH9K_POW_SM(p_pwr_array[ALL_TARGET_HT40_14], 0));
}
-static void ar9003_hw_init_txpower_cck(struct ath_hw *ah, u8 *rate_array)
-{
- ah->tx_power[0] = rate_array[ALL_TARGET_LEGACY_1L_5L];
- ah->tx_power[1] = rate_array[ALL_TARGET_LEGACY_1L_5L];
- ah->tx_power[2] = min(rate_array[ALL_TARGET_LEGACY_1L_5L],
- rate_array[ALL_TARGET_LEGACY_5S]);
- ah->tx_power[3] = min(rate_array[ALL_TARGET_LEGACY_11L],
- rate_array[ALL_TARGET_LEGACY_11S]);
-}
-
-static void ar9003_hw_init_txpower_ofdm(struct ath_hw *ah, u8 *rate_array,
- int offset)
-{
- int i, j;
-
- for (i = offset; i < offset + AR9300_OFDM_RATES; i++) {
- /* OFDM rate to power table idx */
- j = ofdm2pwr[i - offset];
- ah->tx_power[i] = rate_array[j];
- }
-}
-
-static void ar9003_hw_init_txpower_ht(struct ath_hw *ah, u8 *rate_array,
- int ss_offset, int ds_offset,
- int ts_offset, bool is_40)
-{
- int i, j, mcs_idx = 0;
- const u8 *mcs2pwr = (is_40) ? mcs2pwr_ht40 : mcs2pwr_ht20;
-
- for (i = ss_offset; i < ss_offset + AR9300_HT_SS_RATES; i++) {
- j = mcs2pwr[mcs_idx];
- ah->tx_power[i] = rate_array[j];
- mcs_idx++;
- }
-
- for (i = ds_offset; i < ds_offset + AR9300_HT_DS_RATES; i++) {
- j = mcs2pwr[mcs_idx];
- ah->tx_power[i] = rate_array[j];
- mcs_idx++;
- }
-
- for (i = ts_offset; i < ts_offset + AR9300_HT_TS_RATES; i++) {
- j = mcs2pwr[mcs_idx];
- ah->tx_power[i] = rate_array[j];
- mcs_idx++;
- }
-}
-
-static void ar9003_hw_init_txpower_stbc(struct ath_hw *ah, int ss_offset,
- int ds_offset, int ts_offset)
-{
- memcpy(&ah->tx_power_stbc[ss_offset], &ah->tx_power[ss_offset],
- AR9300_HT_SS_RATES);
- memcpy(&ah->tx_power_stbc[ds_offset], &ah->tx_power[ds_offset],
- AR9300_HT_DS_RATES);
- memcpy(&ah->tx_power_stbc[ts_offset], &ah->tx_power[ts_offset],
- AR9300_HT_TS_RATES);
-}
-
-void ar9003_hw_init_rate_txpower(struct ath_hw *ah, u8 *rate_array,
- struct ath9k_channel *chan)
-{
- if (IS_CHAN_5GHZ(chan)) {
- ar9003_hw_init_txpower_ofdm(ah, rate_array,
- AR9300_11NA_OFDM_SHIFT);
- if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) {
- ar9003_hw_init_txpower_ht(ah, rate_array,
- AR9300_11NA_HT_SS_SHIFT,
- AR9300_11NA_HT_DS_SHIFT,
- AR9300_11NA_HT_TS_SHIFT,
- IS_CHAN_HT40(chan));
- ar9003_hw_init_txpower_stbc(ah,
- AR9300_11NA_HT_SS_SHIFT,
- AR9300_11NA_HT_DS_SHIFT,
- AR9300_11NA_HT_TS_SHIFT);
- }
- } else {
- ar9003_hw_init_txpower_cck(ah, rate_array);
- ar9003_hw_init_txpower_ofdm(ah, rate_array,
- AR9300_11NG_OFDM_SHIFT);
- if (IS_CHAN_HT20(chan) || IS_CHAN_HT40(chan)) {
- ar9003_hw_init_txpower_ht(ah, rate_array,
- AR9300_11NG_HT_SS_SHIFT,
- AR9300_11NG_HT_DS_SHIFT,
- AR9300_11NG_HT_TS_SHIFT,
- IS_CHAN_HT40(chan));
- ar9003_hw_init_txpower_stbc(ah,
- AR9300_11NG_HT_SS_SHIFT,
- AR9300_11NG_HT_DS_SHIFT,
- AR9300_11NG_HT_TS_SHIFT);
- }
- }
-}
-
void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
index 1efae69..a43b30d 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h
@@ -17,7 +17,6 @@
#ifndef AR9003_RTT_H
#define AR9003_RTT_H
-#ifdef CPTCFG_ATH9K_PCOEM
void ar9003_hw_rtt_enable(struct ath_hw *ah);
void ar9003_hw_rtt_disable(struct ath_hw *ah);
void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask);
@@ -26,40 +25,5 @@
void ar9003_hw_rtt_fill_hist(struct ath_hw *ah);
void ar9003_hw_rtt_clear_hist(struct ath_hw *ah);
bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan);
-#else
-static inline void ar9003_hw_rtt_enable(struct ath_hw *ah)
-{
-}
-
-static inline void ar9003_hw_rtt_disable(struct ath_hw *ah)
-{
-}
-
-static inline void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask)
-{
-}
-
-static inline bool ar9003_hw_rtt_force_restore(struct ath_hw *ah)
-{
- return false;
-}
-
-static inline void ar9003_hw_rtt_load_hist(struct ath_hw *ah)
-{
-}
-
-static inline void ar9003_hw_rtt_fill_hist(struct ath_hw *ah)
-{
-}
-
-static inline void ar9003_hw_rtt_clear_hist(struct ath_hw *ah)
-{
-}
-
-static inline bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan)
-{
- return false;
-}
-#endif
#endif
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
index 159cc6f..812a9d7 100644
--- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h
@@ -20,8 +20,6 @@
#define qca953x_1p0_mac_postamble ar9300_2p2_mac_postamble
-#define qca953x_1p0_soc_preamble ar955x_1p0_soc_preamble
-
#define qca953x_1p0_soc_postamble ar9300_2p2_soc_postamble
#define qca953x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2
@@ -30,10 +28,6 @@
#define qca953x_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2
-#define qca953x_1p0_common_wo_xlna_rx_gain_bounds ar955x_1p0_common_wo_xlna_rx_gain_bounds
-
-#define qca953x_1p0_common_rx_gain_bounds ar955x_1p0_common_rx_gain_bounds
-
static const u32 qca953x_1p0_mac_core[][2] = {
/* Addr allmodes */
{0x00000008, 0x00000000},
@@ -496,6 +490,35 @@
{0x00016540, 0x10804008, 0x10804008, 0x50804000, 0x50804000},
};
+static const u32 qca953x_1p0_soc_preamble[][2] = {
+ /* Addr allmodes */
+ {0x00007000, 0x00000000},
+ {0x00007004, 0x00000000},
+ {0x00007008, 0x00000000},
+ {0x0000700c, 0x00000000},
+ {0x0000701c, 0x00000000},
+ {0x00007020, 0x00000000},
+ {0x00007024, 0x00000000},
+ {0x00007028, 0x00000000},
+ {0x0000702c, 0x00000000},
+ {0x00007030, 0x00000000},
+ {0x00007034, 0x00000002},
+ {0x00007038, 0x000004c2},
+ {0x00007048, 0x00000000},
+};
+
+static const u32 qca953x_1p0_common_rx_gain_bounds[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018},
+};
+
+static const u32 qca953x_1p0_common_wo_xlna_rx_gain_bounds[][5] = {
+ /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
+ {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
+ {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
+};
+
static const u32 qca953x_1p0_modes_xpa_tx_gain_table[][2] = {
/* Addr allmodes */
{0x0000a2dc, 0xfffd5aaa},
@@ -692,73 +715,8 @@
{0x00016448, 0x6c927a70},
};
-static const u32 qca953x_1p1_modes_xpa_tx_gain_table[][2] = {
- /* Addr allmodes */
- {0x0000a2dc, 0xfffb52aa},
- {0x0000a2e0, 0xfffd64cc},
- {0x0000a2e4, 0xfffe80f0},
- {0x0000a2e8, 0xffffff00},
- {0x0000a410, 0x000050d5},
- {0x0000a500, 0x00000000},
- {0x0000a504, 0x04000002},
- {0x0000a508, 0x08000004},
- {0x0000a50c, 0x0c000006},
- {0x0000a510, 0x1000000a},
- {0x0000a514, 0x1400000c},
- {0x0000a518, 0x1800000e},
- {0x0000a51c, 0x1c000048},
- {0x0000a520, 0x2000004a},
- {0x0000a524, 0x2400004c},
- {0x0000a528, 0x2800004e},
- {0x0000a52c, 0x2b00024a},
- {0x0000a530, 0x2f00024c},
- {0x0000a534, 0x3300024e},
- {0x0000a538, 0x36000668},
- {0x0000a53c, 0x38000669},
- {0x0000a540, 0x3a000868},
- {0x0000a544, 0x3d00086a},
- {0x0000a548, 0x4000086c},
- {0x0000a54c, 0x4200086e},
- {0x0000a550, 0x43000a6e},
- {0x0000a554, 0x43000a6e},
- {0x0000a558, 0x43000a6e},
- {0x0000a55c, 0x43000a6e},
- {0x0000a560, 0x43000a6e},
- {0x0000a564, 0x43000a6e},
- {0x0000a568, 0x43000a6e},
- {0x0000a56c, 0x43000a6e},
- {0x0000a570, 0x43000a6e},
- {0x0000a574, 0x43000a6e},
- {0x0000a578, 0x43000a6e},
- {0x0000a57c, 0x43000a6e},
- {0x0000a600, 0x00000000},
- {0x0000a604, 0x00000000},
- {0x0000a608, 0x00000000},
- {0x0000a60c, 0x03804000},
- {0x0000a610, 0x03804e01},
- {0x0000a614, 0x03804e01},
- {0x0000a618, 0x03804e01},
- {0x0000a61c, 0x04009002},
- {0x0000a620, 0x04009002},
- {0x0000a624, 0x04009002},
- {0x0000a628, 0x04009002},
- {0x0000a62c, 0x04009002},
- {0x0000a630, 0x04009002},
- {0x0000a634, 0x04009002},
- {0x0000a638, 0x04009002},
- {0x0000a63c, 0x04009002},
- {0x0000b2dc, 0xfffb52aa},
- {0x0000b2e0, 0xfffd64cc},
- {0x0000b2e4, 0xfffe80f0},
- {0x0000b2e8, 0xffffff00},
- {0x00016044, 0x024922db},
- {0x00016048, 0x6c927a70},
- {0x00016444, 0x024922db},
- {0x00016448, 0x6c927a70},
-};
-
static const u32 qca953x_2p0_baseband_core[][2] = {
- /* Addr allmodes */
+ /* Addr allmodes */
{0x00009800, 0xafe68e30},
{0x00009804, 0xfd14e000},
{0x00009808, 0x9c0a9f6b},
@@ -956,400 +914,4 @@
{0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010},
};
-static const u32 qca953x_2p0_common_wo_xlna_rx_gain_table[][2] = {
- /* Addr allmodes */
- {0x0000a000, 0x00010000},
- {0x0000a004, 0x00030002},
- {0x0000a008, 0x00050004},
- {0x0000a00c, 0x00810080},
- {0x0000a010, 0x00830082},
- {0x0000a014, 0x01810180},
- {0x0000a018, 0x01830182},
- {0x0000a01c, 0x01850184},
- {0x0000a020, 0x01890188},
- {0x0000a024, 0x018b018a},
- {0x0000a028, 0x018d018c},
- {0x0000a02c, 0x03820190},
- {0x0000a030, 0x03840383},
- {0x0000a034, 0x03880385},
- {0x0000a038, 0x038a0389},
- {0x0000a03c, 0x038c038b},
- {0x0000a040, 0x0390038d},
- {0x0000a044, 0x03920391},
- {0x0000a048, 0x03940393},
- {0x0000a04c, 0x03960395},
- {0x0000a050, 0x00000000},
- {0x0000a054, 0x00000000},
- {0x0000a058, 0x00000000},
- {0x0000a05c, 0x00000000},
- {0x0000a060, 0x00000000},
- {0x0000a064, 0x00000000},
- {0x0000a068, 0x00000000},
- {0x0000a06c, 0x00000000},
- {0x0000a070, 0x00000000},
- {0x0000a074, 0x00000000},
- {0x0000a078, 0x00000000},
- {0x0000a07c, 0x00000000},
- {0x0000a080, 0x29292929},
- {0x0000a084, 0x29292929},
- {0x0000a088, 0x29292929},
- {0x0000a08c, 0x29292929},
- {0x0000a090, 0x22292929},
- {0x0000a094, 0x1d1d2222},
- {0x0000a098, 0x0c111117},
- {0x0000a09c, 0x00030303},
- {0x0000a0a0, 0x00000000},
- {0x0000a0a4, 0x00000000},
- {0x0000a0a8, 0x00000000},
- {0x0000a0ac, 0x00000000},
- {0x0000a0b0, 0x00000000},
- {0x0000a0b4, 0x00000000},
- {0x0000a0b8, 0x00000000},
- {0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x001f0000},
- {0x0000a0c4, 0x01000101},
- {0x0000a0c8, 0x011e011f},
- {0x0000a0cc, 0x011c011d},
- {0x0000a0d0, 0x02030204},
- {0x0000a0d4, 0x02010202},
- {0x0000a0d8, 0x021f0200},
- {0x0000a0dc, 0x0302021e},
- {0x0000a0e0, 0x03000301},
- {0x0000a0e4, 0x031e031f},
- {0x0000a0e8, 0x0402031d},
- {0x0000a0ec, 0x04000401},
- {0x0000a0f0, 0x041e041f},
- {0x0000a0f4, 0x0502041d},
- {0x0000a0f8, 0x05000501},
- {0x0000a0fc, 0x051e051f},
- {0x0000a100, 0x06010602},
- {0x0000a104, 0x061f0600},
- {0x0000a108, 0x061d061e},
- {0x0000a10c, 0x07020703},
- {0x0000a110, 0x07000701},
- {0x0000a114, 0x00000000},
- {0x0000a118, 0x00000000},
- {0x0000a11c, 0x00000000},
- {0x0000a120, 0x00000000},
- {0x0000a124, 0x00000000},
- {0x0000a128, 0x00000000},
- {0x0000a12c, 0x00000000},
- {0x0000a130, 0x00000000},
- {0x0000a134, 0x00000000},
- {0x0000a138, 0x00000000},
- {0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x01000101},
- {0x0000a148, 0x011e011f},
- {0x0000a14c, 0x011c011d},
- {0x0000a150, 0x02030204},
- {0x0000a154, 0x02010202},
- {0x0000a158, 0x021f0200},
- {0x0000a15c, 0x0302021e},
- {0x0000a160, 0x03000301},
- {0x0000a164, 0x031e031f},
- {0x0000a168, 0x0402031d},
- {0x0000a16c, 0x04000401},
- {0x0000a170, 0x041e041f},
- {0x0000a174, 0x0502041d},
- {0x0000a178, 0x05000501},
- {0x0000a17c, 0x051e051f},
- {0x0000a180, 0x06010602},
- {0x0000a184, 0x061f0600},
- {0x0000a188, 0x061d061e},
- {0x0000a18c, 0x07020703},
- {0x0000a190, 0x07000701},
- {0x0000a194, 0x00000000},
- {0x0000a198, 0x00000000},
- {0x0000a19c, 0x00000000},
- {0x0000a1a0, 0x00000000},
- {0x0000a1a4, 0x00000000},
- {0x0000a1a8, 0x00000000},
- {0x0000a1ac, 0x00000000},
- {0x0000a1b0, 0x00000000},
- {0x0000a1b4, 0x00000000},
- {0x0000a1b8, 0x00000000},
- {0x0000a1bc, 0x00000000},
- {0x0000a1c0, 0x00000000},
- {0x0000a1c4, 0x00000000},
- {0x0000a1c8, 0x00000000},
- {0x0000a1cc, 0x00000000},
- {0x0000a1d0, 0x00000000},
- {0x0000a1d4, 0x00000000},
- {0x0000a1d8, 0x00000000},
- {0x0000a1dc, 0x00000000},
- {0x0000a1e0, 0x00000000},
- {0x0000a1e4, 0x00000000},
- {0x0000a1e8, 0x00000000},
- {0x0000a1ec, 0x00000000},
- {0x0000a1f0, 0x00000396},
- {0x0000a1f4, 0x00000396},
- {0x0000a1f8, 0x00000396},
- {0x0000a1fc, 0x00000196},
- {0x0000b000, 0x00010000},
- {0x0000b004, 0x00030002},
- {0x0000b008, 0x00050004},
- {0x0000b00c, 0x00810080},
- {0x0000b010, 0x00830082},
- {0x0000b014, 0x01810180},
- {0x0000b018, 0x01830182},
- {0x0000b01c, 0x01850184},
- {0x0000b020, 0x02810280},
- {0x0000b024, 0x02830282},
- {0x0000b028, 0x02850284},
- {0x0000b02c, 0x02890288},
- {0x0000b030, 0x028b028a},
- {0x0000b034, 0x0388028c},
- {0x0000b038, 0x038a0389},
- {0x0000b03c, 0x038c038b},
- {0x0000b040, 0x0390038d},
- {0x0000b044, 0x03920391},
- {0x0000b048, 0x03940393},
- {0x0000b04c, 0x03960395},
- {0x0000b050, 0x00000000},
- {0x0000b054, 0x00000000},
- {0x0000b058, 0x00000000},
- {0x0000b05c, 0x00000000},
- {0x0000b060, 0x00000000},
- {0x0000b064, 0x00000000},
- {0x0000b068, 0x00000000},
- {0x0000b06c, 0x00000000},
- {0x0000b070, 0x00000000},
- {0x0000b074, 0x00000000},
- {0x0000b078, 0x00000000},
- {0x0000b07c, 0x00000000},
- {0x0000b080, 0x32323232},
- {0x0000b084, 0x2f2f3232},
- {0x0000b088, 0x23282a2d},
- {0x0000b08c, 0x1c1e2123},
- {0x0000b090, 0x14171919},
- {0x0000b094, 0x0e0e1214},
- {0x0000b098, 0x03050707},
- {0x0000b09c, 0x00030303},
- {0x0000b0a0, 0x00000000},
- {0x0000b0a4, 0x00000000},
- {0x0000b0a8, 0x00000000},
- {0x0000b0ac, 0x00000000},
- {0x0000b0b0, 0x00000000},
- {0x0000b0b4, 0x00000000},
- {0x0000b0b8, 0x00000000},
- {0x0000b0bc, 0x00000000},
- {0x0000b0c0, 0x003f0020},
- {0x0000b0c4, 0x00400041},
- {0x0000b0c8, 0x0140005f},
- {0x0000b0cc, 0x0160015f},
- {0x0000b0d0, 0x017e017f},
- {0x0000b0d4, 0x02410242},
- {0x0000b0d8, 0x025f0240},
- {0x0000b0dc, 0x027f0260},
- {0x0000b0e0, 0x0341027e},
- {0x0000b0e4, 0x035f0340},
- {0x0000b0e8, 0x037f0360},
- {0x0000b0ec, 0x04400441},
- {0x0000b0f0, 0x0460045f},
- {0x0000b0f4, 0x0541047f},
- {0x0000b0f8, 0x055f0540},
- {0x0000b0fc, 0x057f0560},
- {0x0000b100, 0x06400641},
- {0x0000b104, 0x0660065f},
- {0x0000b108, 0x067e067f},
- {0x0000b10c, 0x07410742},
- {0x0000b110, 0x075f0740},
- {0x0000b114, 0x077f0760},
- {0x0000b118, 0x07800781},
- {0x0000b11c, 0x07a0079f},
- {0x0000b120, 0x07c107bf},
- {0x0000b124, 0x000007c0},
- {0x0000b128, 0x00000000},
- {0x0000b12c, 0x00000000},
- {0x0000b130, 0x00000000},
- {0x0000b134, 0x00000000},
- {0x0000b138, 0x00000000},
- {0x0000b13c, 0x00000000},
- {0x0000b140, 0x003f0020},
- {0x0000b144, 0x00400041},
- {0x0000b148, 0x0140005f},
- {0x0000b14c, 0x0160015f},
- {0x0000b150, 0x017e017f},
- {0x0000b154, 0x02410242},
- {0x0000b158, 0x025f0240},
- {0x0000b15c, 0x027f0260},
- {0x0000b160, 0x0341027e},
- {0x0000b164, 0x035f0340},
- {0x0000b168, 0x037f0360},
- {0x0000b16c, 0x04400441},
- {0x0000b170, 0x0460045f},
- {0x0000b174, 0x0541047f},
- {0x0000b178, 0x055f0540},
- {0x0000b17c, 0x057f0560},
- {0x0000b180, 0x06400641},
- {0x0000b184, 0x0660065f},
- {0x0000b188, 0x067e067f},
- {0x0000b18c, 0x07410742},
- {0x0000b190, 0x075f0740},
- {0x0000b194, 0x077f0760},
- {0x0000b198, 0x07800781},
- {0x0000b19c, 0x07a0079f},
- {0x0000b1a0, 0x07c107bf},
- {0x0000b1a4, 0x000007c0},
- {0x0000b1a8, 0x00000000},
- {0x0000b1ac, 0x00000000},
- {0x0000b1b0, 0x00000000},
- {0x0000b1b4, 0x00000000},
- {0x0000b1b8, 0x00000000},
- {0x0000b1bc, 0x00000000},
- {0x0000b1c0, 0x00000000},
- {0x0000b1c4, 0x00000000},
- {0x0000b1c8, 0x00000000},
- {0x0000b1cc, 0x00000000},
- {0x0000b1d0, 0x00000000},
- {0x0000b1d4, 0x00000000},
- {0x0000b1d8, 0x00000000},
- {0x0000b1dc, 0x00000000},
- {0x0000b1e0, 0x00000000},
- {0x0000b1e4, 0x00000000},
- {0x0000b1e8, 0x00000000},
- {0x0000b1ec, 0x00000000},
- {0x0000b1f0, 0x00000396},
- {0x0000b1f4, 0x00000396},
- {0x0000b1f8, 0x00000396},
- {0x0000b1fc, 0x00000196},
-};
-
-static const u32 qca953x_2p0_common_wo_xlna_rx_gain_bounds[][5] = {
- /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27},
- {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012},
-};
-
-static const u32 qca953x_2p0_modes_xpa_tx_gain_table[][2] = {
- /* Addr allmodes */
- {0x0000a2dc, 0xfffb52aa},
- {0x0000a2e0, 0xfffd64cc},
- {0x0000a2e4, 0xfffe80f0},
- {0x0000a2e8, 0xffffff00},
- {0x0000a410, 0x000050d5},
- {0x0000a500, 0x00000000},
- {0x0000a504, 0x04000002},
- {0x0000a508, 0x08000004},
- {0x0000a50c, 0x0c000006},
- {0x0000a510, 0x1000000a},
- {0x0000a514, 0x1400000c},
- {0x0000a518, 0x1800000e},
- {0x0000a51c, 0x1c000048},
- {0x0000a520, 0x2000004a},
- {0x0000a524, 0x2400004c},
- {0x0000a528, 0x2800004e},
- {0x0000a52c, 0x2b00024a},
- {0x0000a530, 0x2f00024c},
- {0x0000a534, 0x3300024e},
- {0x0000a538, 0x36000668},
- {0x0000a53c, 0x38000669},
- {0x0000a540, 0x3a000868},
- {0x0000a544, 0x3d00086a},
- {0x0000a548, 0x4000086c},
- {0x0000a54c, 0x4200086e},
- {0x0000a550, 0x43000a6e},
- {0x0000a554, 0x43000a6e},
- {0x0000a558, 0x43000a6e},
- {0x0000a55c, 0x43000a6e},
- {0x0000a560, 0x43000a6e},
- {0x0000a564, 0x43000a6e},
- {0x0000a568, 0x43000a6e},
- {0x0000a56c, 0x43000a6e},
- {0x0000a570, 0x43000a6e},
- {0x0000a574, 0x43000a6e},
- {0x0000a578, 0x43000a6e},
- {0x0000a57c, 0x43000a6e},
- {0x0000a600, 0x00000000},
- {0x0000a604, 0x00000000},
- {0x0000a608, 0x00000000},
- {0x0000a60c, 0x03804000},
- {0x0000a610, 0x03804e01},
- {0x0000a614, 0x03804e01},
- {0x0000a618, 0x03804e01},
- {0x0000a61c, 0x04009002},
- {0x0000a620, 0x04009002},
- {0x0000a624, 0x04009002},
- {0x0000a628, 0x04009002},
- {0x0000a62c, 0x04009002},
- {0x0000a630, 0x04009002},
- {0x0000a634, 0x04009002},
- {0x0000a638, 0x04009002},
- {0x0000a63c, 0x04009002},
- {0x0000b2dc, 0xfffb52aa},
- {0x0000b2e0, 0xfffd64cc},
- {0x0000b2e4, 0xfffe80f0},
- {0x0000b2e8, 0xffffff00},
- {0x00016044, 0x024922db},
- {0x00016048, 0x6c927a70},
- {0x00016444, 0x024922db},
- {0x00016448, 0x6c927a70},
-};
-
-static const u32 qca953x_2p0_modes_no_xpa_tx_gain_table[][2] = {
- /* Addr allmodes */
- {0x0000a2dc, 0xffd5f552},
- {0x0000a2e0, 0xffe60664},
- {0x0000a2e4, 0xfff80780},
- {0x0000a2e8, 0xfffff800},
- {0x0000a410, 0x000050de},
- {0x0000a500, 0x00000061},
- {0x0000a504, 0x04000063},
- {0x0000a508, 0x08000065},
- {0x0000a50c, 0x0c000261},
- {0x0000a510, 0x10000263},
- {0x0000a514, 0x14000265},
- {0x0000a518, 0x18000482},
- {0x0000a51c, 0x1b000484},
- {0x0000a520, 0x1f000486},
- {0x0000a524, 0x240008c2},
- {0x0000a528, 0x28000cc1},
- {0x0000a52c, 0x2d000ce3},
- {0x0000a530, 0x31000ce5},
- {0x0000a534, 0x350010e5},
- {0x0000a538, 0x360012e5},
- {0x0000a53c, 0x380014e5},
- {0x0000a540, 0x3b0018e5},
- {0x0000a544, 0x3d001d04},
- {0x0000a548, 0x3e001d05},
- {0x0000a54c, 0x40001d07},
- {0x0000a550, 0x42001f27},
- {0x0000a554, 0x43001f67},
- {0x0000a558, 0x46001fe7},
- {0x0000a55c, 0x47001f2b},
- {0x0000a560, 0x49001f0d},
- {0x0000a564, 0x4b001ed2},
- {0x0000a568, 0x4c001ed4},
- {0x0000a56c, 0x4e001f15},
- {0x0000a570, 0x4f001ff6},
- {0x0000a574, 0x4f001ff6},
- {0x0000a578, 0x4f001ff6},
- {0x0000a57c, 0x4f001ff6},
- {0x0000a600, 0x00000000},
- {0x0000a604, 0x00000000},
- {0x0000a608, 0x00000000},
- {0x0000a60c, 0x00804201},
- {0x0000a610, 0x01008201},
- {0x0000a614, 0x0180c402},
- {0x0000a618, 0x0180c603},
- {0x0000a61c, 0x0180c603},
- {0x0000a620, 0x01c10603},
- {0x0000a624, 0x01c10704},
- {0x0000a628, 0x02c18b05},
- {0x0000a62c, 0x02c14c07},
- {0x0000a630, 0x01008704},
- {0x0000a634, 0x01c10402},
- {0x0000a638, 0x0301cc07},
- {0x0000a63c, 0x0301cc07},
- {0x0000b2dc, 0xffd5f552},
- {0x0000b2e0, 0xffe60664},
- {0x0000b2e4, 0xfff80780},
- {0x0000b2e8, 0xfffff800},
- {0x00016044, 0x049242db},
- {0x00016048, 0x6c927a70},
- {0x00016444, 0x049242db},
- {0x00016448, 0x6c927a70},
-};
-
#endif /* INITVALS_953X_H */
diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
index fd6a84c..74d8bc0 100644
--- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h
@@ -507,7 +507,7 @@
{0x00009d04, 0x40206c10},
{0x00009d08, 0x009c4060},
{0x00009d0c, 0x9883800a},
- {0x00009d10, 0x01884061},
+ {0x00009d10, 0x01834061},
{0x00009d14, 0x00c0040b},
{0x00009d18, 0x00000000},
{0x00009e08, 0x0038230c},
@@ -545,9 +545,9 @@
{0x0000a370, 0x00000000},
{0x0000a390, 0x00000001},
{0x0000a394, 0x00000444},
- {0x0000a398, 0x001f0e0f},
- {0x0000a39c, 0x0075393f},
- {0x0000a3a0, 0xb79f6427},
+ {0x0000a398, 0x1f020503},
+ {0x0000a39c, 0x29180c03},
+ {0x0000a3a0, 0x9a8b6844},
{0x0000a3a4, 0x00000000},
{0x0000a3a8, 0xaaaaaaaa},
{0x0000a3ac, 0x3c466478},
diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
index 5d4629f..a5ca652 100644
--- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h
@@ -24,149 +24,7 @@
#define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble
-static const u32 ar9580_1p0_radio_core[][2] = {
- /* Addr allmodes */
- {0x00016000, 0x36db2db6},
- {0x00016004, 0x6db6db40},
- {0x00016008, 0x73f00000},
- {0x0001600c, 0x00000000},
- {0x00016040, 0x7f80fff8},
- {0x0001604c, 0x76d005b5},
- {0x00016050, 0x556cf031},
- {0x00016054, 0x13449440},
- {0x00016058, 0x0c51c92c},
- {0x0001605c, 0x3db7fffc},
- {0x00016060, 0xfffffffc},
- {0x00016064, 0x000f0278},
- {0x0001606c, 0x6db60000},
- {0x00016080, 0x00000000},
- {0x00016084, 0x0e48048c},
- {0x00016088, 0x54214514},
- {0x0001608c, 0x119f481e},
- {0x00016090, 0x24926490},
- {0x00016098, 0xd2888888},
- {0x000160a0, 0x0a108ffe},
- {0x000160a4, 0x812fc370},
- {0x000160a8, 0x423c8000},
- {0x000160b4, 0x92480080},
- {0x000160c0, 0x00adb6d0},
- {0x000160c4, 0x6db6db60},
- {0x000160c8, 0x6db6db6c},
- {0x000160cc, 0x01e6c000},
- {0x00016100, 0x3fffbe01},
- {0x00016104, 0xfff80000},
- {0x00016108, 0x00080010},
- {0x00016144, 0x02084080},
- {0x00016148, 0x00000000},
- {0x00016280, 0x058a0001},
- {0x00016284, 0x3d840208},
- {0x00016288, 0x05a20408},
- {0x0001628c, 0x00038c07},
- {0x00016290, 0x00000004},
- {0x00016294, 0x458a214f},
- {0x00016380, 0x00000000},
- {0x00016384, 0x00000000},
- {0x00016388, 0x00800700},
- {0x0001638c, 0x00800700},
- {0x00016390, 0x00800700},
- {0x00016394, 0x00000000},
- {0x00016398, 0x00000000},
- {0x0001639c, 0x00000000},
- {0x000163a0, 0x00000001},
- {0x000163a4, 0x00000001},
- {0x000163a8, 0x00000000},
- {0x000163ac, 0x00000000},
- {0x000163b0, 0x00000000},
- {0x000163b4, 0x00000000},
- {0x000163b8, 0x00000000},
- {0x000163bc, 0x00000000},
- {0x000163c0, 0x000000a0},
- {0x000163c4, 0x000c0000},
- {0x000163c8, 0x14021402},
- {0x000163cc, 0x00001402},
- {0x000163d0, 0x00000000},
- {0x000163d4, 0x00000000},
- {0x00016400, 0x36db2db6},
- {0x00016404, 0x6db6db40},
- {0x00016408, 0x73f00000},
- {0x0001640c, 0x00000000},
- {0x00016440, 0x7f80fff8},
- {0x0001644c, 0x76d005b5},
- {0x00016450, 0x556cf031},
- {0x00016454, 0x13449440},
- {0x00016458, 0x0c51c92c},
- {0x0001645c, 0x3db7fffc},
- {0x00016460, 0xfffffffc},
- {0x00016464, 0x000f0278},
- {0x0001646c, 0x6db60000},
- {0x00016500, 0x3fffbe01},
- {0x00016504, 0xfff80000},
- {0x00016508, 0x00080010},
- {0x00016544, 0x02084080},
- {0x00016548, 0x00000000},
- {0x00016780, 0x00000000},
- {0x00016784, 0x00000000},
- {0x00016788, 0x00800700},
- {0x0001678c, 0x00800700},
- {0x00016790, 0x00800700},
- {0x00016794, 0x00000000},
- {0x00016798, 0x00000000},
- {0x0001679c, 0x00000000},
- {0x000167a0, 0x00000001},
- {0x000167a4, 0x00000001},
- {0x000167a8, 0x00000000},
- {0x000167ac, 0x00000000},
- {0x000167b0, 0x00000000},
- {0x000167b4, 0x00000000},
- {0x000167b8, 0x00000000},
- {0x000167bc, 0x00000000},
- {0x000167c0, 0x000000a0},
- {0x000167c4, 0x000c0000},
- {0x000167c8, 0x14021402},
- {0x000167cc, 0x00001402},
- {0x000167d0, 0x00000000},
- {0x000167d4, 0x00000000},
- {0x00016800, 0x36db2db6},
- {0x00016804, 0x6db6db40},
- {0x00016808, 0x73f00000},
- {0x0001680c, 0x00000000},
- {0x00016840, 0x7f80fff8},
- {0x0001684c, 0x76d005b5},
- {0x00016850, 0x556cf031},
- {0x00016854, 0x13449440},
- {0x00016858, 0x0c51c92c},
- {0x0001685c, 0x3db7fffc},
- {0x00016860, 0xfffffffc},
- {0x00016864, 0x000f0278},
- {0x0001686c, 0x6db60000},
- {0x00016900, 0x3fffbe01},
- {0x00016904, 0xfff80000},
- {0x00016908, 0x00080010},
- {0x00016944, 0x02084080},
- {0x00016948, 0x00000000},
- {0x00016b80, 0x00000000},
- {0x00016b84, 0x00000000},
- {0x00016b88, 0x00800700},
- {0x00016b8c, 0x00800700},
- {0x00016b90, 0x00800700},
- {0x00016b94, 0x00000000},
- {0x00016b98, 0x00000000},
- {0x00016b9c, 0x00000000},
- {0x00016ba0, 0x00000001},
- {0x00016ba4, 0x00000001},
- {0x00016ba8, 0x00000000},
- {0x00016bac, 0x00000000},
- {0x00016bb0, 0x00000000},
- {0x00016bb4, 0x00000000},
- {0x00016bb8, 0x00000000},
- {0x00016bbc, 0x00000000},
- {0x00016bc0, 0x000000a0},
- {0x00016bc4, 0x000c0000},
- {0x00016bc8, 0x14021402},
- {0x00016bcc, 0x00001402},
- {0x00016bd0, 0x00000000},
- {0x00016bd4, 0x00000000},
-};
+#define ar9580_1p0_radio_core ar9300_2p2_radio_core
#define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index e008569..4581876 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -28,6 +28,7 @@
#include "debug.h"
#include "mci.h"
#include "dfs.h"
+#include "spectral.h"
struct ath_node;
struct ath_vif;
@@ -189,7 +190,6 @@
u8 rtscts_rate;
u8 retries : 7;
u8 baw_tracked : 1;
- u8 tx_power;
};
struct ath_rxbuf {
@@ -345,9 +345,7 @@
u64 tsf_val;
u32 last_beacon;
- int flush_timeout;
u16 txpower;
- u16 cur_txpower;
bool offchannel;
bool stopped;
bool active;
@@ -364,7 +362,7 @@
ATH_CHANCTX_EVENT_BEACON_SENT,
ATH_CHANCTX_EVENT_TSF_TIMER,
ATH_CHANCTX_EVENT_BEACON_RECEIVED,
- ATH_CHANCTX_EVENT_AUTHORIZED,
+ ATH_CHANCTX_EVENT_ASSOC,
ATH_CHANCTX_EVENT_SWITCH,
ATH_CHANCTX_EVENT_ASSIGN,
ATH_CHANCTX_EVENT_UNASSIGN,
@@ -382,12 +380,10 @@
struct ath_chanctx_sched {
bool beacon_pending;
- bool beacon_adjust;
bool offchannel_pending;
bool wait_switch;
bool force_noa_update;
bool extend_absence;
- bool mgd_prepare_tx;
enum ath_chanctx_state state;
u8 beacon_miss;
@@ -472,7 +468,6 @@
void ath_offchannel_next(struct ath_softc *sc);
void ath_scan_complete(struct ath_softc *sc, bool abort);
void ath_roc_complete(struct ath_softc *sc, bool abort);
-struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc);
#else
@@ -545,6 +540,7 @@
#endif /* CPTCFG_ATH9K_CHANNEL_CONTEXT */
+int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan);
void ath_startrecv(struct ath_softc *sc);
bool ath_stoprecv(struct ath_softc *sc);
u32 ath_calcrxfilter(struct ath_softc *sc);
@@ -599,7 +595,7 @@
u16 seq_no;
/* BSS info */
- u8 bssid[ETH_ALEN] __aligned(2);
+ u8 bssid[ETH_ALEN];
u16 aid;
bool assoc;
@@ -622,7 +618,6 @@
u32 noa_start;
u32 noa_duration;
bool periodic_noa;
- bool oneshot_noa;
};
struct ath9k_vif_iter_data {
@@ -720,8 +715,7 @@
void ath_update_survey_nf(struct ath_softc *sc, int channel);
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
void ath_ps_full_sleep(unsigned long data);
-void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
- bool sw_pending, bool timeout_override);
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop);
/**********/
/* BTCOEX */
@@ -933,7 +927,6 @@
#define ATH9K_PCI_AR9565_2ANT 0x0100
#define ATH9K_PCI_NO_PLL_PWRSAVE 0x0200
#define ATH9K_PCI_KILLER 0x0400
-#define ATH9K_PCI_LED_ACT_HI 0x0800
/*
* Default cache line size, in bytes.
@@ -982,7 +975,6 @@
struct ath_chanctx_sched sched;
struct ath_offchannel offchannel;
struct ath_chanctx *next_chan;
- struct completion go_beacon;
#endif
unsigned long driver_data;
@@ -990,6 +982,7 @@
u8 gtt_cnt;
u32 intrstatus;
u16 ps_flags; /* PS_* */
+ u16 curtxpow;
bool ps_enabled;
bool ps_idle;
short nbcnvifs;
@@ -1030,8 +1023,10 @@
struct dfs_pattern_detector *dfs_detector;
u64 dfs_prev_pulse_ts;
u32 wow_enabled;
-
- struct ath_spec_scan_priv spec_priv;
+ /* relay(fs) channel for spectral scan */
+ struct rchan *rfs_chan_spec_scan;
+ enum spectral_mode spectral_mode;
+ struct ath_spec_scan spec_config;
struct ieee80211_vif *tx99_vif;
struct sk_buff *tx99_skb;
@@ -1074,7 +1069,7 @@
int ath_cabq_update(struct ath_softc *);
u8 ath9k_parse_mpdudensity(u8 mpdudensity);
irqreturn_t ath_isr(int irq, void *dev);
-int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan);
+int ath_reset(struct ath_softc *sc);
void ath_cancel_work(struct ath_softc *sc);
void ath_restart_work(struct ath_softc *sc);
int ath9k_init_device(u16 devid, struct ath_softc *sc,
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index cb366ad..ecb783b 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -78,7 +78,7 @@
struct ath_tx_info info;
struct ieee80211_supported_band *sband;
u8 chainmask = ah->txchainmask;
- u8 i, rate = 0;
+ u8 rate = 0;
sband = &common->sbands[sc->cur_chandef.chan->band];
rate = sband->bitrates[rateidx].hw_value;
@@ -88,8 +88,7 @@
memset(&info, 0, sizeof(info));
info.pkt_len = skb->len + FCS_LEN;
info.type = ATH9K_PKT_TYPE_BEACON;
- for (i = 0; i < 4; i++)
- info.txpower[i] = MAX_RATE_POWER;
+ info.txpower = MAX_RATE_POWER;
info.keyix = ATH9K_TXKEYIX_INVALID;
info.keytype = ATH9K_KEY_TYPE_CLEAR;
info.flags = ATH9K_TXDESC_NOACK | ATH9K_TXDESC_CLRDMASK;
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index e200a6e..278365b 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -234,7 +234,7 @@
REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
}
-int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
{
struct ath9k_nfcal_hist *h = NULL;
unsigned i, j;
@@ -301,7 +301,7 @@
ath_dbg(common, ANY,
"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
REG_READ(ah, AR_PHY_AGC_CONTROL));
- return -ETIMEDOUT;
+ return;
}
/*
@@ -322,8 +322,6 @@
}
}
REGWRITE_BUFFER_FLUSH(ah);
-
- return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 87badf4..b8ed95e 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -109,7 +109,7 @@
bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update);
-int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
+void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
struct ath9k_channel *chan);
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 239e8a3..696152b 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -66,7 +66,7 @@
}
hchan = &sc->sc_ah->channels[pos];
- r = ath_reset(sc, hchan);
+ r = ath_reset_internal(sc, hchan);
if (r)
return r;
@@ -92,8 +92,8 @@
} else {
/* perform spectral scan if requested. */
if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
- sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN)
- ath9k_cmn_spectral_scan_trigger(common, &sc->spec_priv);
+ sc->spectral_mode == SPECTRAL_CHANSCAN)
+ ath9k_spectral_scan_trigger(hw);
}
return 0;
@@ -117,7 +117,6 @@
cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20);
INIT_LIST_HEAD(&ctx->vifs);
ctx->txpower = ATH_TXPOWER_MAX;
- ctx->flush_timeout = HZ / 5; /* 200ms */
for (j = 0; j < ARRAY_SIZE(ctx->acq); j++)
INIT_LIST_HEAD(&ctx->acq[j]);
}
@@ -146,36 +145,6 @@
#ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT
-/*************/
-/* Utilities */
-/*************/
-
-struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc)
-{
- struct ath_chanctx *ctx;
- struct ath_vif *avp;
- struct ieee80211_vif *vif;
-
- spin_lock_bh(&sc->chan_lock);
-
- ath_for_each_chanctx(sc, ctx) {
- if (!ctx->active)
- continue;
-
- list_for_each_entry(avp, &ctx->vifs, list) {
- vif = avp->vif;
-
- if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_P2P_GO) {
- spin_unlock_bh(&sc->chan_lock);
- return ctx;
- }
- }
- }
-
- spin_unlock_bh(&sc->chan_lock);
- return NULL;
-}
-
/**********************************************************/
/* Functions to handle the channel context state machine. */
/**********************************************************/
@@ -202,7 +171,7 @@
case_rtn_string(ATH_CHANCTX_EVENT_BEACON_SENT);
case_rtn_string(ATH_CHANCTX_EVENT_TSF_TIMER);
case_rtn_string(ATH_CHANCTX_EVENT_BEACON_RECEIVED);
- case_rtn_string(ATH_CHANCTX_EVENT_AUTHORIZED);
+ case_rtn_string(ATH_CHANCTX_EVENT_ASSOC);
case_rtn_string(ATH_CHANCTX_EVENT_SWITCH);
case_rtn_string(ATH_CHANCTX_EVENT_ASSIGN);
case_rtn_string(ATH_CHANCTX_EVENT_UNASSIGN);
@@ -229,7 +198,6 @@
void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- struct ath_chanctx *ictx;
struct ath_vif *avp;
bool active = false;
u8 n_active = 0;
@@ -237,28 +205,6 @@
if (!ctx)
return;
- if (ctx == &sc->offchannel.chan) {
- spin_lock_bh(&sc->chan_lock);
-
- if (likely(sc->sched.channel_switch_time))
- ctx->flush_timeout =
- usecs_to_jiffies(sc->sched.channel_switch_time);
- else
- ctx->flush_timeout =
- msecs_to_jiffies(10);
-
- spin_unlock_bh(&sc->chan_lock);
-
- /*
- * There is no need to iterate over the
- * active/assigned channel contexts if
- * the current context is offchannel.
- */
- return;
- }
-
- ictx = ctx;
-
list_for_each_entry(avp, &ctx->vifs, list) {
struct ieee80211_vif *vif = avp->vif;
@@ -281,23 +227,12 @@
n_active++;
}
- spin_lock_bh(&sc->chan_lock);
-
if (n_active <= 1) {
- ictx->flush_timeout = HZ / 5;
clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags);
- spin_unlock_bh(&sc->chan_lock);
return;
}
-
- ictx->flush_timeout = usecs_to_jiffies(sc->sched.channel_switch_time);
-
- if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) {
- spin_unlock_bh(&sc->chan_lock);
+ if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
return;
- }
-
- spin_unlock_bh(&sc->chan_lock);
if (ath9k_is_chanctx_enabled()) {
ath_chanctx_event(sc, NULL,
@@ -366,111 +301,6 @@
"Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time));
}
-static void ath_chanctx_handle_bmiss(struct ath_softc *sc,
- struct ath_chanctx *ctx,
- struct ath_vif *avp)
-{
- /*
- * Clear the extend_absence flag if it had been
- * set during the previous beacon transmission,
- * since we need to revert to the normal NoA
- * schedule.
- */
- if (ctx->active && sc->sched.extend_absence) {
- avp->noa_duration = 0;
- sc->sched.extend_absence = false;
- }
-
- /* If at least two consecutive beacons were missed on the STA
- * chanctx, stay on the STA channel for one extra beacon period,
- * to resync the timer properly.
- */
- if (ctx->active && sc->sched.beacon_miss >= 2) {
- avp->noa_duration = 0;
- sc->sched.extend_absence = true;
- }
-}
-
-static void ath_chanctx_offchannel_noa(struct ath_softc *sc,
- struct ath_chanctx *ctx,
- struct ath_vif *avp,
- u32 tsf_time)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
- avp->noa_index++;
- avp->offchannel_start = tsf_time;
- avp->offchannel_duration = sc->sched.offchannel_duration;
-
- ath_dbg(common, CHAN_CTX,
- "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n",
- avp->offchannel_duration,
- avp->offchannel_start,
- avp->noa_index);
-
- /*
- * When multiple contexts are active, the NoA
- * has to be recalculated and advertised after
- * an offchannel operation.
- */
- if (ctx->active && avp->noa_duration)
- avp->noa_duration = 0;
-}
-
-static void ath_chanctx_set_periodic_noa(struct ath_softc *sc,
- struct ath_vif *avp,
- struct ath_beacon_config *cur_conf,
- u32 tsf_time,
- u32 beacon_int)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
- avp->noa_index++;
- avp->noa_start = tsf_time;
-
- if (sc->sched.extend_absence)
- avp->noa_duration = (3 * beacon_int / 2) +
- sc->sched.channel_switch_time;
- else
- avp->noa_duration =
- TU_TO_USEC(cur_conf->beacon_interval) / 2 +
- sc->sched.channel_switch_time;
-
- if (test_bit(ATH_OP_SCANNING, &common->op_flags) ||
- sc->sched.extend_absence)
- avp->periodic_noa = false;
- else
- avp->periodic_noa = true;
-
- ath_dbg(common, CHAN_CTX,
- "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
- avp->noa_duration,
- avp->noa_start,
- avp->noa_index,
- avp->periodic_noa);
-}
-
-static void ath_chanctx_set_oneshot_noa(struct ath_softc *sc,
- struct ath_vif *avp,
- u32 tsf_time,
- u32 duration)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
- avp->noa_index++;
- avp->noa_start = tsf_time;
- avp->periodic_noa = false;
- avp->oneshot_noa = true;
- avp->noa_duration = duration + sc->sched.channel_switch_time;
-
- ath_dbg(common, CHAN_CTX,
- "oneshot noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
- avp->noa_duration,
- avp->noa_start,
- avp->noa_index,
- avp->periodic_noa);
-}
-
void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif,
enum ath_chanctx_event ev)
{
@@ -497,14 +327,6 @@
if (avp->offchannel_duration)
avp->offchannel_duration = 0;
- if (avp->oneshot_noa) {
- avp->noa_duration = 0;
- avp->oneshot_noa = false;
-
- ath_dbg(common, CHAN_CTX,
- "Clearing oneshot NoA\n");
- }
-
if (avp->chanctx != sc->cur_chan) {
ath_dbg(common, CHAN_CTX,
"Contexts differ, not preparing beacon\n");
@@ -534,24 +356,6 @@
"Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n");
}
- if (sc->sched.mgd_prepare_tx)
- sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON;
-
- /*
- * When a context becomes inactive, for example,
- * disassociation of a station context, the NoA
- * attribute needs to be removed from subsequent
- * beacons.
- */
- if (!ctx->active && avp->noa_duration &&
- sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) {
- avp->noa_duration = 0;
- avp->periodic_noa = false;
-
- ath_dbg(common, CHAN_CTX,
- "Clearing NoA schedule\n");
- }
-
if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
break;
@@ -574,22 +378,45 @@
* values and increment the index.
*/
if (sc->next_chan == &sc->offchannel.chan) {
- ath_chanctx_offchannel_noa(sc, ctx, avp, tsf_time);
+ avp->noa_index++;
+ avp->offchannel_start = tsf_time;
+ avp->offchannel_duration = sc->sched.offchannel_duration;
+
+ ath_dbg(common, CHAN_CTX,
+ "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n",
+ avp->offchannel_duration,
+ avp->offchannel_start,
+ avp->noa_index);
+
+ /*
+ * When multiple contexts are active, the NoA
+ * has to be recalculated and advertised after
+ * an offchannel operation.
+ */
+ if (ctx->active && avp->noa_duration)
+ avp->noa_duration = 0;
+
break;
}
- ath_chanctx_handle_bmiss(sc, ctx, avp);
-
/*
- * If a mgd_prepare_tx() has been called by mac80211,
- * a one-shot NoA needs to be sent. This can happen
- * with one or more active channel contexts - in both
- * cases, a new NoA schedule has to be advertised.
+ * Clear the extend_absence flag if it had been
+ * set during the previous beacon transmission,
+ * since we need to revert to the normal NoA
+ * schedule.
*/
- if (sc->sched.mgd_prepare_tx) {
- ath_chanctx_set_oneshot_noa(sc, avp, tsf_time,
- jiffies_to_usecs(HZ / 5));
- break;
+ if (ctx->active && sc->sched.extend_absence) {
+ avp->noa_duration = 0;
+ sc->sched.extend_absence = false;
+ }
+
+ /* If at least two consecutive beacons were missed on the STA
+ * chanctx, stay on the STA channel for one extra beacon period,
+ * to resync the timer properly.
+ */
+ if (ctx->active && sc->sched.beacon_miss >= 2) {
+ avp->noa_duration = 0;
+ sc->sched.extend_absence = true;
}
/* Prevent wrap-around issues */
@@ -602,9 +429,31 @@
* announcement.
*/
if (ctx->active &&
- (!avp->noa_duration || sc->sched.force_noa_update))
- ath_chanctx_set_periodic_noa(sc, avp, cur_conf,
- tsf_time, beacon_int);
+ (!avp->noa_duration || sc->sched.force_noa_update)) {
+ avp->noa_index++;
+ avp->noa_start = tsf_time;
+
+ if (sc->sched.extend_absence)
+ avp->noa_duration = (3 * beacon_int / 2) +
+ sc->sched.channel_switch_time;
+ else
+ avp->noa_duration =
+ TU_TO_USEC(cur_conf->beacon_interval) / 2 +
+ sc->sched.channel_switch_time;
+
+ if (test_bit(ATH_OP_SCANNING, &common->op_flags) ||
+ sc->sched.extend_absence)
+ avp->periodic_noa = false;
+ else
+ avp->periodic_noa = true;
+
+ ath_dbg(common, CHAN_CTX,
+ "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n",
+ avp->noa_duration,
+ avp->noa_start,
+ avp->noa_index,
+ avp->periodic_noa);
+ }
if (ctx->active && sc->sched.force_noa_update)
sc->sched.force_noa_update = false;
@@ -618,15 +467,6 @@
}
sc->sched.beacon_pending = false;
-
- if (sc->sched.mgd_prepare_tx) {
- sc->sched.mgd_prepare_tx = false;
- complete(&sc->go_beacon);
- ath_dbg(common, CHAN_CTX,
- "Beacon sent, complete go_beacon\n");
- break;
- }
-
if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON)
break;
@@ -655,16 +495,10 @@
sc->cur_chan == &sc->offchannel.chan)
break;
+ ath_chanctx_adjust_tbtt_delta(sc);
sc->sched.beacon_pending = false;
sc->sched.beacon_miss = 0;
- if (sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE ||
- !sc->sched.beacon_adjust ||
- !sc->cur_chan->tsf_val)
- break;
-
- ath_chanctx_adjust_tbtt_delta(sc);
-
/* TSF time might have been updated by the incoming beacon,
* need update the channel switch timer to reflect the change.
*/
@@ -673,10 +507,10 @@
ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL);
tsf_time += ath9k_hw_gettsf32(ah);
- sc->sched.beacon_adjust = false;
+
ath_chanctx_setup_timer(sc, tsf_time);
break;
- case ATH_CHANCTX_EVENT_AUTHORIZED:
+ case ATH_CHANCTX_EVENT_ASSOC:
if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE ||
avp->chanctx != sc->cur_chan)
break;
@@ -718,7 +552,6 @@
ath_chanctx_setup_timer(sc, tsf_time);
sc->sched.beacon_pending = true;
- sc->sched.beacon_adjust = true;
break;
case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL:
if (sc->cur_chan == &sc->offchannel.chan ||
@@ -745,6 +578,22 @@
ieee80211_queue_work(sc->hw, &sc->chanctx_work);
break;
case ATH_CHANCTX_EVENT_ASSIGN:
+ /*
+ * When adding a new channel context, check if a scan
+ * is in progress and abort it since the addition of
+ * a new channel context is usually followed by VIF
+ * assignment, in which case we have to start multi-channel
+ * operation.
+ */
+ if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
+ ath_dbg(common, CHAN_CTX,
+ "Aborting HW scan to add new context\n");
+
+ spin_unlock_bh(&sc->chan_lock);
+ del_timer_sync(&sc->offchannel.timer);
+ ath_scan_complete(sc, true);
+ spin_lock_bh(&sc->chan_lock);
+ }
break;
case ATH_CHANCTX_EVENT_CHANGE:
break;
@@ -902,11 +751,6 @@
sc->offchannel.state = ATH_OFFCHANNEL_ROC_START;
ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan);
} else {
- spin_lock_bh(&sc->chan_lock);
- sc->sched.offchannel_pending = false;
- sc->sched.wait_switch = false;
- spin_unlock_bh(&sc->chan_lock);
-
ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false),
NULL);
sc->offchannel.state = ATH_OFFCHANNEL_IDLE;
@@ -926,7 +770,8 @@
sc->offchannel.roc_vif = NULL;
sc->offchannel.roc_chan = NULL;
- ieee80211_remain_on_channel_expired(sc->hw);
+ if (!abort)
+ ieee80211_remain_on_channel_expired(sc->hw);
ath_offchannel_next(sc);
ath9k_ps_restore(sc);
}
@@ -963,7 +808,7 @@
struct ieee80211_tx_info *info;
int band = sc->offchannel.chan.chandef.chan->band;
- skb = ieee80211_probereq_get(sc->hw, vif->addr,
+ skb = ieee80211_probereq_get(sc->hw, vif,
ssid->ssid, ssid->ssid_len, req->ie_len);
if (!skb)
return;
@@ -1057,8 +902,9 @@
break;
case ATH_OFFCHANNEL_ROC_START:
case ATH_OFFCHANNEL_ROC_WAIT:
+ ctx = ath_chanctx_get_oper_chan(sc, false);
sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE;
- ath_roc_complete(sc, false);
+ ath_chanctx_switch(sc, ctx, NULL);
break;
default:
break;
@@ -1188,6 +1034,7 @@
ieee80211_ready_on_channel(sc->hw);
break;
case ATH_OFFCHANNEL_ROC_DONE:
+ ath_roc_complete(sc, false);
break;
default:
break;
@@ -1235,11 +1082,10 @@
ath9k_chanctx_stop_queues(sc, sc->cur_chan);
queues_stopped = true;
- __ath9k_flush(sc->hw, ~0, true, false, false);
+ __ath9k_flush(sc->hw, ~0, true);
if (ath_chanctx_send_ps_frame(sc, true))
- __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO),
- false, false, false);
+ __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false);
send_ps = true;
spin_lock_bh(&sc->chan_lock);
@@ -1331,8 +1177,6 @@
(unsigned long)sc);
setup_timer(&sc->sched.timer, ath_chanctx_timer,
(unsigned long)sc);
-
- init_completion(&sc->go_beacon);
}
void ath9k_deinit_channel_context(struct ath_softc *sc)
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index e8c6994..c6dd7f1 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -159,7 +159,7 @@
if (test_bit(keyix, common->keymap))
rxs->flag |= RX_FLAG_DECRYPTED;
}
- if (ah->sw_mgmt_crypto_rx &&
+ if (ah->sw_mgmt_crypto &&
(rxs->flag & RX_FLAG_DECRYPTED) &&
ieee80211_is_mgmt(fc))
/* Use software decrypt for management frames. */
@@ -368,11 +368,11 @@
{
struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
- if (reg->power_limit != new_txpow)
+ if (reg->power_limit != new_txpow) {
ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
-
- /* read back in case value is clamped */
- *txpower = reg->max_power_level;
+ /* read back in case value is clamped */
+ *txpower = reg->max_power_level;
+ }
}
EXPORT_SYMBOL(ath9k_cmn_update_txpow);
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 2b79a56..ffc454b 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -24,7 +24,6 @@
#include "common-init.h"
#include "common-beacon.h"
#include "common-debug.h"
-#include "common-spectral.h"
/* Common header for Atheros 802.11n base driver cores */
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 99ce0db..947be9a 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -401,14 +401,22 @@
.llseek = default_llseek,
};
-static int read_file_dma(struct seq_file *file, void *data)
+static ssize_t read_file_dma(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- struct ath_softc *sc = file->private;
+ struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;
+ char *buf;
+ int retval;
+ unsigned int len = 0;
u32 val[ATH9K_NUM_DMA_DEBUG_REGS];
int i, qcuOffset = 0, dcuOffset = 0;
u32 *qcuBase = &val[0], *dcuBase = &val[4];
+ buf = kmalloc(DMA_BUF_LEN, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
ath9k_ps_wakeup(sc);
REG_WRITE_D(ah, AR_MACMISC,
@@ -416,18 +424,21 @@
(AR_MACMISC_MISC_OBS_BUS_1 <<
AR_MACMISC_MISC_OBS_BUS_MSB_S)));
- seq_puts(file, "Raw DMA Debug values:\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "Raw DMA Debug values:\n");
for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) {
if (i % 4 == 0)
- seq_puts(file, "\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n");
val[i] = REG_READ_D(ah, AR_DMADBG_0 + (i * sizeof(u32)));
- seq_printf(file, "%d: %08x ", i, val[i]);
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "%d: %08x ",
+ i, val[i]);
}
- seq_puts(file, "\n\n");
- seq_puts(file, "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n");
for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) {
if (i == 8) {
@@ -440,47 +451,55 @@
dcuBase++;
}
- seq_printf(file, "%2d %2x %1x %2x %2x\n",
- i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
- (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
- (val[2] & (0x7 << (i * 3))) >> (i * 3),
- (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "%2d %2x %1x %2x %2x\n",
+ i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset,
+ (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3),
+ val[2] & (0x7 << (i * 3)) >> (i * 3),
+ (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset);
}
- seq_puts(file, "\n");
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "\n");
- seq_printf(file, "qcu_stitch state: %2x qcu_fetch state: %2x\n",
- (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
- seq_printf(file, "qcu_complete state: %2x dcu_complete state: %2x\n",
- (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
- seq_printf(file, "dcu_arb state: %2x dcu_fp state: %2x\n",
- (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
- seq_printf(file, "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
- (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
- seq_printf(file, "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
- (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
- seq_printf(file, "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
- (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "qcu_stitch state: %2x qcu_fetch state: %2x\n",
+ (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22);
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "qcu_complete state: %2x dcu_complete state: %2x\n",
+ (val[3] & 0x1c000000) >> 26, (val[6] & 0x3));
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "dcu_arb state: %2x dcu_fp state: %2x\n",
+ (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27);
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n",
+ (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10);
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "txfifo_valid_0: %1d txfifo_valid_1: %1d\n",
+ (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12);
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n",
+ (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17);
- seq_printf(file, "pcu observe: 0x%x\n", REG_READ_D(ah, AR_OBS_BUS_1));
- seq_printf(file, "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR));
+ len += scnprintf(buf + len, DMA_BUF_LEN - len, "pcu observe: 0x%x\n",
+ REG_READ_D(ah, AR_OBS_BUS_1));
+ len += scnprintf(buf + len, DMA_BUF_LEN - len,
+ "AR_CR: 0x%x\n", REG_READ_D(ah, AR_CR));
ath9k_ps_restore(sc);
- return 0;
-}
+ if (len > DMA_BUF_LEN)
+ len = DMA_BUF_LEN;
-static int open_file_dma(struct inode *inode, struct file *f)
-{
- return single_open(f, read_file_dma, inode->i_private);
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+ return retval;
}
static const struct file_operations fops_dma = {
- .open = open_file_dma,
- .read = seq_read,
+ .read = read_file_dma,
+ .open = simple_open,
.owner = THIS_MODULE,
- .llseek = seq_lseek,
- .release = single_release,
+ .llseek = default_llseek,
};
@@ -537,14 +556,22 @@
sc->debug.stats.istats.gen_timer++;
}
-static int read_file_interrupt(struct seq_file *file, void *data)
+static ssize_t read_file_interrupt(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- struct ath_softc *sc = file->private;
+ struct ath_softc *sc = file->private_data;
+ unsigned int len = 0;
+ int rv;
+ int mxlen = 4000;
+ char *buf = kmalloc(mxlen, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
#define PR_IS(a, s) \
do { \
- seq_printf(file, "%21s: %10u\n", a, \
- sc->debug.stats.istats.s); \
+ len += scnprintf(buf + len, mxlen - len, \
+ "%21s: %10u\n", a, \
+ sc->debug.stats.istats.s); \
} while (0)
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
@@ -575,7 +602,8 @@
PR_IS("GENTIMER", gen_timer);
PR_IS("TOTAL", total);
- seq_puts(file, "SYNC_CAUSE stats:\n");
+ len += scnprintf(buf + len, mxlen - len,
+ "SYNC_CAUSE stats:\n");
PR_IS("Sync-All", sync_cause_all);
PR_IS("RTC-IRQ", sync_rtc_irq);
@@ -597,27 +625,35 @@
PR_IS("MAC-Asleep", mac_asleep);
PR_IS("MAC-Sleep-Access", mac_sleep_access);
- return 0;
-}
+ if (len > mxlen)
+ len = mxlen;
-static int open_file_interrupt(struct inode *inode, struct file *f)
-{
- return single_open(f, read_file_interrupt, inode->i_private);
+ rv = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+ return rv;
}
static const struct file_operations fops_interrupt = {
- .read = seq_read,
- .open = open_file_interrupt,
+ .read = read_file_interrupt,
+ .open = simple_open,
.owner = THIS_MODULE,
- .llseek = seq_lseek,
- .release = single_release,
+ .llseek = default_llseek,
};
-static int read_file_xmit(struct seq_file *file, void *data)
+static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- struct ath_softc *sc = file->private;
+ struct ath_softc *sc = file->private_data;
+ char *buf;
+ unsigned int len = 0, size = 2048;
+ ssize_t retval = 0;
- seq_printf(file, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ len += sprintf(buf, "%30s %10s%10s%10s\n\n",
+ "BE", "BK", "VI", "VO");
PR("MPDUs Queued: ", queued);
PR("MPDUs Completed: ", completed);
@@ -642,162 +678,215 @@
PR("HW-tx-proc-desc: ", txprocdesc);
PR("TX-Failed: ", txfailed);
- return 0;
+ if (len > size)
+ len = size;
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
}
-static void print_queue(struct ath_softc *sc, struct ath_txq *txq,
- struct seq_file *file)
+static ssize_t print_queue(struct ath_softc *sc, struct ath_txq *txq,
+ char *buf, ssize_t size)
{
+ ssize_t len = 0;
+
ath_txq_lock(sc, txq);
- seq_printf(file, "%s: %d ", "qnum", txq->axq_qnum);
- seq_printf(file, "%s: %2d ", "qdepth", txq->axq_depth);
- seq_printf(file, "%s: %2d ", "ampdu-depth", txq->axq_ampdu_depth);
- seq_printf(file, "%s: %3d ", "pending", txq->pending_frames);
- seq_printf(file, "%s: %d\n", "stopped", txq->stopped);
+ len += scnprintf(buf + len, size - len, "%s: %d ",
+ "qnum", txq->axq_qnum);
+ len += scnprintf(buf + len, size - len, "%s: %2d ",
+ "qdepth", txq->axq_depth);
+ len += scnprintf(buf + len, size - len, "%s: %2d ",
+ "ampdu-depth", txq->axq_ampdu_depth);
+ len += scnprintf(buf + len, size - len, "%s: %3d ",
+ "pending", txq->pending_frames);
+ len += scnprintf(buf + len, size - len, "%s: %d\n",
+ "stopped", txq->stopped);
ath_txq_unlock(sc, txq);
+ return len;
}
-static int read_file_queues(struct seq_file *file, void *data)
+static ssize_t read_file_queues(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- struct ath_softc *sc = file->private;
+ struct ath_softc *sc = file->private_data;
struct ath_txq *txq;
+ char *buf;
+ unsigned int len = 0;
+ const unsigned int size = 1024;
+ ssize_t retval = 0;
int i;
static const char *qname[4] = {
"VO", "VI", "BE", "BK"
};
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
for (i = 0; i < IEEE80211_NUM_ACS; i++) {
txq = sc->tx.txq_map[i];
- seq_printf(file, "(%s): ", qname[i]);
- print_queue(sc, txq, file);
+ len += scnprintf(buf + len, size - len, "(%s): ", qname[i]);
+ len += print_queue(sc, txq, buf + len, size - len);
}
- seq_puts(file, "(CAB): ");
- print_queue(sc, sc->beacon.cabq, file);
+ len += scnprintf(buf + len, size - len, "(CAB): ");
+ len += print_queue(sc, sc->beacon.cabq, buf + len, size - len);
- return 0;
+ if (len > size)
+ len = size;
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
}
-static int read_file_misc(struct seq_file *file, void *data)
+static ssize_t read_file_misc(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- struct ath_softc *sc = file->private;
+ struct ath_softc *sc = file->private_data;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath9k_vif_iter_data iter_data;
struct ath_chanctx *ctx;
+ char buf[512];
+ unsigned int len = 0;
+ ssize_t retval = 0;
unsigned int reg;
u32 rxfilter, i;
- seq_printf(file, "BSSID: %pM\n", common->curbssid);
- seq_printf(file, "BSSID-MASK: %pM\n", common->bssidmask);
- seq_printf(file, "OPMODE: %s\n",
- ath_opmode_to_string(sc->sc_ah->opmode));
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "BSSID: %pM\n", common->curbssid);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "BSSID-MASK: %pM\n", common->bssidmask);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "OPMODE: %s\n",
+ ath_opmode_to_string(sc->sc_ah->opmode));
ath9k_ps_wakeup(sc);
rxfilter = ath9k_hw_getrxfilter(sc->sc_ah);
ath9k_ps_restore(sc);
- seq_printf(file, "RXFILTER: 0x%x", rxfilter);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "RXFILTER: 0x%x", rxfilter);
if (rxfilter & ATH9K_RX_FILTER_UCAST)
- seq_puts(file, " UCAST");
+ len += scnprintf(buf + len, sizeof(buf) - len, " UCAST");
if (rxfilter & ATH9K_RX_FILTER_MCAST)
- seq_puts(file, " MCAST");
+ len += scnprintf(buf + len, sizeof(buf) - len, " MCAST");
if (rxfilter & ATH9K_RX_FILTER_BCAST)
- seq_puts(file, " BCAST");
+ len += scnprintf(buf + len, sizeof(buf) - len, " BCAST");
if (rxfilter & ATH9K_RX_FILTER_CONTROL)
- seq_puts(file, " CONTROL");
+ len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL");
if (rxfilter & ATH9K_RX_FILTER_BEACON)
- seq_puts(file, " BEACON");
+ len += scnprintf(buf + len, sizeof(buf) - len, " BEACON");
if (rxfilter & ATH9K_RX_FILTER_PROM)
- seq_puts(file, " PROM");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PROM");
if (rxfilter & ATH9K_RX_FILTER_PROBEREQ)
- seq_puts(file, " PROBEREQ");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PROBEREQ");
if (rxfilter & ATH9K_RX_FILTER_PHYERR)
- seq_puts(file, " PHYERR");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PHYERR");
if (rxfilter & ATH9K_RX_FILTER_MYBEACON)
- seq_puts(file, " MYBEACON");
+ len += scnprintf(buf + len, sizeof(buf) - len, " MYBEACON");
if (rxfilter & ATH9K_RX_FILTER_COMP_BAR)
- seq_puts(file, " COMP_BAR");
+ len += scnprintf(buf + len, sizeof(buf) - len, " COMP_BAR");
if (rxfilter & ATH9K_RX_FILTER_PSPOLL)
- seq_puts(file, " PSPOLL");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PSPOLL");
if (rxfilter & ATH9K_RX_FILTER_PHYRADAR)
- seq_puts(file, " PHYRADAR");
+ len += scnprintf(buf + len, sizeof(buf) - len, " PHYRADAR");
if (rxfilter & ATH9K_RX_FILTER_MCAST_BCAST_ALL)
- seq_puts(file, " MCAST_BCAST_ALL");
+ len += scnprintf(buf + len, sizeof(buf) - len, " MCAST_BCAST_ALL");
if (rxfilter & ATH9K_RX_FILTER_CONTROL_WRAPPER)
- seq_puts(file, " CONTROL_WRAPPER");
+ len += scnprintf(buf + len, sizeof(buf) - len, " CONTROL_WRAPPER");
- seq_puts(file, "\n");
+ len += scnprintf(buf + len, sizeof(buf) - len, "\n");
reg = sc->sc_ah->imask;
- seq_printf(file, "INTERRUPT-MASK: 0x%x", reg);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "INTERRUPT-MASK: 0x%x", reg);
if (reg & ATH9K_INT_SWBA)
- seq_puts(file, " SWBA");
+ len += scnprintf(buf + len, sizeof(buf) - len, " SWBA");
if (reg & ATH9K_INT_BMISS)
- seq_puts(file, " BMISS");
+ len += scnprintf(buf + len, sizeof(buf) - len, " BMISS");
if (reg & ATH9K_INT_CST)
- seq_puts(file, " CST");
+ len += scnprintf(buf + len, sizeof(buf) - len, " CST");
if (reg & ATH9K_INT_RX)
- seq_puts(file, " RX");
+ len += scnprintf(buf + len, sizeof(buf) - len, " RX");
if (reg & ATH9K_INT_RXHP)
- seq_puts(file, " RXHP");
+ len += scnprintf(buf + len, sizeof(buf) - len, " RXHP");
if (reg & ATH9K_INT_RXLP)
- seq_puts(file, " RXLP");
+ len += scnprintf(buf + len, sizeof(buf) - len, " RXLP");
if (reg & ATH9K_INT_BB_WATCHDOG)
- seq_puts(file, " BB_WATCHDOG");
+ len += scnprintf(buf + len, sizeof(buf) - len, " BB_WATCHDOG");
- seq_puts(file, "\n");
+ len += scnprintf(buf + len, sizeof(buf) - len, "\n");
i = 0;
ath_for_each_chanctx(sc, ctx) {
- if (list_empty(&ctx->vifs))
+ if (!ctx->assigned || list_empty(&ctx->vifs))
continue;
ath9k_calculate_iter_data(sc, ctx, &iter_data);
- seq_printf(file,
- "VIFS: CTX %i(%i) AP: %i STA: %i MESH: %i WDS: %i",
- i++, (int)(ctx->assigned), iter_data.naps,
- iter_data.nstations,
- iter_data.nmeshes, iter_data.nwds);
- seq_printf(file, " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
- iter_data.nadhocs, sc->cur_chan->nvifs,
- sc->nbcnvifs);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "VIF-COUNTS: CTX %i AP: %i STA: %i MESH: %i WDS: %i",
+ i++, iter_data.naps, iter_data.nstations,
+ iter_data.nmeshes, iter_data.nwds);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n",
+ iter_data.nadhocs, sc->cur_chan->nvifs, sc->nbcnvifs);
}
- return 0;
+ if (len > sizeof(buf))
+ len = sizeof(buf);
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ return retval;
}
-static int read_file_reset(struct seq_file *file, void *data)
+static ssize_t read_file_reset(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- struct ath_softc *sc = file->private;
- static const char * const reset_cause[__RESET_TYPE_MAX] = {
- [RESET_TYPE_BB_HANG] = "Baseband Hang",
- [RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog",
- [RESET_TYPE_FATAL_INT] = "Fatal HW Error",
- [RESET_TYPE_TX_ERROR] = "TX HW error",
- [RESET_TYPE_TX_GTT] = "Transmit timeout",
- [RESET_TYPE_TX_HANG] = "TX Path Hang",
- [RESET_TYPE_PLL_HANG] = "PLL RX Hang",
- [RESET_TYPE_MAC_HANG] = "MAC Hang",
- [RESET_TYPE_BEACON_STUCK] = "Stuck Beacon",
- [RESET_TYPE_MCI] = "MCI Reset",
- [RESET_TYPE_CALIBRATION] = "Calibration error",
- };
- int i;
+ struct ath_softc *sc = file->private_data;
+ char buf[512];
+ unsigned int len = 0;
- for (i = 0; i < ARRAY_SIZE(reset_cause); i++) {
- if (!reset_cause[i])
- continue;
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "Baseband Hang",
+ sc->debug.stats.reset[RESET_TYPE_BB_HANG]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "Baseband Watchdog",
+ sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "Fatal HW Error",
+ sc->debug.stats.reset[RESET_TYPE_FATAL_INT]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "TX HW error",
+ sc->debug.stats.reset[RESET_TYPE_TX_ERROR]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "TX Path Hang",
+ sc->debug.stats.reset[RESET_TYPE_TX_HANG]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "PLL RX Hang",
+ sc->debug.stats.reset[RESET_TYPE_PLL_HANG]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "MAC Hang",
+ sc->debug.stats.reset[RESET_TYPE_MAC_HANG]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "Stuck Beacon",
+ sc->debug.stats.reset[RESET_TYPE_BEACON_STUCK]);
+ len += scnprintf(buf + len, sizeof(buf) - len,
+ "%17s: %2d\n", "MCI Reset",
+ sc->debug.stats.reset[RESET_TYPE_MCI]);
- seq_printf(file, "%17s: %2d\n", reset_cause[i],
- sc->debug.stats.reset[i]);
- }
+ if (len > sizeof(buf))
+ len = sizeof(buf);
- return 0;
+ return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
@@ -837,56 +926,32 @@
TX_STAT_INC(qnum, delim_underrun);
}
-static int open_file_xmit(struct inode *inode, struct file *f)
-{
- return single_open(f, read_file_xmit, inode->i_private);
-}
-
static const struct file_operations fops_xmit = {
- .read = seq_read,
- .open = open_file_xmit,
+ .read = read_file_xmit,
+ .open = simple_open,
.owner = THIS_MODULE,
- .llseek = seq_lseek,
- .release = single_release,
+ .llseek = default_llseek,
};
-static int open_file_queues(struct inode *inode, struct file *f)
-{
- return single_open(f, read_file_queues, inode->i_private);
-}
-
static const struct file_operations fops_queues = {
- .read = seq_read,
- .open = open_file_queues,
+ .read = read_file_queues,
+ .open = simple_open,
.owner = THIS_MODULE,
- .llseek = seq_lseek,
- .release = single_release,
+ .llseek = default_llseek,
};
-static int open_file_misc(struct inode *inode, struct file *f)
-{
- return single_open(f, read_file_misc, inode->i_private);
-}
-
static const struct file_operations fops_misc = {
- .read = seq_read,
- .open = open_file_misc,
+ .read = read_file_misc,
+ .open = simple_open,
.owner = THIS_MODULE,
- .llseek = seq_lseek,
- .release = single_release,
+ .llseek = default_llseek,
};
-static int open_file_reset(struct inode *inode, struct file *f)
-{
- return single_open(f, read_file_reset, inode->i_private);
-}
-
static const struct file_operations fops_reset = {
- .read = seq_read,
- .open = open_file_reset,
+ .read = read_file_reset,
+ .open = simple_open,
.owner = THIS_MODULE,
- .llseek = seq_lseek,
- .release = single_release,
+ .llseek = default_llseek,
};
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
@@ -895,7 +960,7 @@
}
static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
char buf[32];
@@ -906,7 +971,7 @@
}
static ssize_t write_file_regidx(struct file *file, const char __user *user_buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
unsigned long regidx;
@@ -934,7 +999,7 @@
};
static ssize_t read_file_regval(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;
@@ -950,7 +1015,7 @@
}
static ssize_t write_file_regval(struct file *file, const char __user *user_buf,
- size_t count, loff_t *ppos)
+ size_t count, loff_t *ppos)
{
struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;
@@ -1016,45 +1081,57 @@
.llseek = default_llseek,/* read accesses f_pos */
};
-static int read_file_dump_nfcal(struct seq_file *file, void *data)
+static ssize_t read_file_dump_nfcal(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- struct ath_softc *sc = file->private;
+ struct ath_softc *sc = file->private_data;
struct ath_hw *ah = sc->sc_ah;
struct ath9k_nfcal_hist *h = sc->cur_chan->caldata.nfCalHist;
struct ath_common *common = ath9k_hw_common(ah);
struct ieee80211_conf *conf = &common->hw->conf;
+ u32 len = 0, size = 1500;
u32 i, j;
+ ssize_t retval = 0;
+ char *buf;
u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
u8 nread;
- seq_printf(file, "Channel Noise Floor : %d\n", ah->noise);
- seq_puts(file, "Chain | privNF | # Readings | NF Readings\n");
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len += scnprintf(buf + len, size - len,
+ "Channel Noise Floor : %d\n", ah->noise);
+ len += scnprintf(buf + len, size - len,
+ "Chain | privNF | # Readings | NF Readings\n");
for (i = 0; i < NUM_NF_READINGS; i++) {
if (!(chainmask & (1 << i)) ||
((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)))
continue;
nread = AR_PHY_CCA_FILTERWINDOW_LENGTH - h[i].invalidNFcount;
- seq_printf(file, " %d\t %d\t %d\t\t", i, h[i].privNF, nread);
+ len += scnprintf(buf + len, size - len, " %d\t %d\t %d\t\t",
+ i, h[i].privNF, nread);
for (j = 0; j < nread; j++)
- seq_printf(file, " %d", h[i].nfCalBuffer[j]);
- seq_puts(file, "\n");
+ len += scnprintf(buf + len, size - len,
+ " %d", h[i].nfCalBuffer[j]);
+ len += scnprintf(buf + len, size - len, "\n");
}
- return 0;
-}
+ if (len > size)
+ len = size;
-static int open_file_dump_nfcal(struct inode *inode, struct file *f)
-{
- return single_open(f, read_file_dump_nfcal, inode->i_private);
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
}
static const struct file_operations fops_dump_nfcal = {
- .read = seq_read,
- .open = open_file_dump_nfcal,
+ .read = read_file_dump_nfcal,
+ .open = simple_open,
.owner = THIS_MODULE,
- .llseek = seq_lseek,
- .release = single_release,
+ .llseek = default_llseek,
};
#ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
@@ -1238,7 +1315,7 @@
void ath9k_deinit_debug(struct ath_softc *sc)
{
- ath9k_cmn_spectral_deinit_debug(&sc->spec_priv);
+ ath9k_spectral_deinit_debug(sc);
}
int ath9k_init_debug(struct ath_hw *ah)
@@ -1258,7 +1335,7 @@
ath9k_dfs_init_debug(sc);
ath9k_tx99_init_debug(sc);
- ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy);
+ ath9k_spectral_init_debug(sc);
debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_dma);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 30340f1..82847c0 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -49,7 +49,6 @@
RESET_TYPE_MAC_HANG,
RESET_TYPE_BEACON_STUCK,
RESET_TYPE_MCI,
- RESET_TYPE_CALIBRATION,
__RESET_TYPE_MAX
};
@@ -196,11 +195,12 @@
#define TXSTATS sc->debug.stats.txstats
#define PR(str, elem) \
do { \
- seq_printf(file, "%s%13u%11u%10u%10u\n", str, \
- TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem,\
- TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem,\
- TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem,\
- TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
+ len += scnprintf(buf + len, size - len, \
+ "%s%13u%11u%10u%10u\n", str, \
+ TXSTATS[PR_QNUM(IEEE80211_AC_BE)].elem,\
+ TXSTATS[PR_QNUM(IEEE80211_AC_BK)].elem,\
+ TXSTATS[PR_QNUM(IEEE80211_AC_VI)].elem,\
+ TXSTATS[PR_QNUM(IEEE80211_AC_VO)].elem); \
} while(0)
struct ath_rx_rate_stats {
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index 303aa35..3516bbd 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -262,7 +262,7 @@
{
struct ar5416_eeprom_def *eep = &ah->eeprom.def;
struct ath_common *common = ath9k_hw_common(ah);
- u16 *eepdata, temp, magic;
+ u16 *eepdata, temp, magic, magic2;
u32 sum = 0, el;
bool need_swap = false;
int i, addr, size;
@@ -272,16 +272,27 @@
return false;
}
- if (swab16(magic) == AR5416_EEPROM_MAGIC &&
- !(ah->ah_flags & AH_NO_EEP_SWAP)) {
- size = sizeof(struct ar5416_eeprom_def);
- need_swap = true;
- eepdata = (u16 *) (&ah->eeprom);
+ if (!ath9k_hw_use_flash(ah)) {
+ ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic);
- for (addr = 0; addr < size / sizeof(u16); addr++) {
- temp = swab16(*eepdata);
- *eepdata = temp;
- eepdata++;
+ if (magic != AR5416_EEPROM_MAGIC) {
+ magic2 = swab16(magic);
+
+ if (magic2 == AR5416_EEPROM_MAGIC) {
+ size = sizeof(struct ar5416_eeprom_def);
+ need_swap = true;
+ eepdata = (u16 *) (&ah->eeprom);
+
+ for (addr = 0; addr < size / sizeof(u16); addr++) {
+ temp = swab16(*eepdata);
+ *eepdata = temp;
+ eepdata++;
+ }
+ } else {
+ ath_err(common,
+ "Invalid EEPROM Magic. Endianness mismatch.\n");
+ return -EINVAL;
+ }
}
}
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index 48ee417..3d9e8e4 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -25,12 +25,7 @@
enum led_brightness brightness)
{
struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
- u32 val = (brightness == LED_OFF);
-
- if (sc->sc_ah->config.led_active_high)
- val = !val;
-
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF));
}
void ath_deinit_leds(struct ath_softc *sc)
@@ -87,7 +82,7 @@
ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
/* LED off, active low */
- ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1);
+ ath9k_hw_set_gpio(ah, ah->led_pin, 1);
}
#endif
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index de6d475..e9278bc 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -481,7 +481,6 @@
unsigned long op_flags;
struct ath9k_hw_cal_data caldata;
- struct ath_spec_scan_priv spec_priv;
spinlock_t beacon_lock;
struct ath_beacon_config cur_beacon_conf;
@@ -626,12 +625,8 @@
#endif
#ifdef CPTCFG_ATH9K_HTC_DEBUGFS
int ath9k_htc_init_debug(struct ath_hw *ah);
-void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv);
#else
static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; };
-static inline void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv)
-{
-}
#endif /* CPTCFG_ATH9K_HTC_DEBUGFS */
#endif /* HTC_H */
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index 8cef1ed..8b529e4 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -490,10 +490,6 @@
WARN_ON(i != ATH9K_HTC_SSTATS_LEN);
}
-void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv)
-{
- ath9k_cmn_spectral_deinit_debug(&priv->spec_priv);
-}
int ath9k_htc_init_debug(struct ath_hw *ah)
{
@@ -505,8 +501,6 @@
if (!priv->debug.debugfs_phy)
return -ENOMEM;
- ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy);
-
debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_tgt_int_stats);
debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy,
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 33d9103..b153389 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -53,21 +53,6 @@
};
#endif
-static void ath9k_htc_op_ps_wakeup(struct ath_common *common)
-{
- ath9k_htc_ps_wakeup((struct ath9k_htc_priv *) common->priv);
-}
-
-static void ath9k_htc_op_ps_restore(struct ath_common *common)
-{
- ath9k_htc_ps_restore((struct ath9k_htc_priv *) common->priv);
-}
-
-static struct ath_ps_ops ath9k_htc_ps_ops = {
- .wakeup = ath9k_htc_op_ps_wakeup,
- .restore = ath9k_htc_op_ps_restore,
-};
-
static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv)
{
int time_left;
@@ -102,7 +87,6 @@
wiphy_rfkill_stop_polling(hw->wiphy);
ath9k_deinit_leds(priv);
- ath9k_htc_deinit_debug(priv);
ieee80211_unregister_hw(hw);
ath9k_rx_cleanup(priv);
ath9k_tx_cleanup(priv);
@@ -465,14 +449,6 @@
common->last_rssi = ATH_RSSI_DUMMY_MARKER;
priv->ah->opmode = NL80211_IFTYPE_STATION;
-
- priv->spec_priv.ah = priv->ah;
- priv->spec_priv.spec_config.enabled = 0;
- priv->spec_priv.spec_config.short_repeat = false;
- priv->spec_priv.spec_config.count = 8;
- priv->spec_priv.spec_config.endless = false;
- priv->spec_priv.spec_config.period = 0x12;
- priv->spec_priv.spec_config.fft_period = 0x02;
}
static int ath9k_init_priv(struct ath9k_htc_priv *priv,
@@ -502,7 +478,6 @@
common = ath9k_hw_common(ah);
common->ops = &ah->reg_ops;
- common->ps_ops = &ath9k_htc_ps_ops;
common->bus_ops = &ath9k_usb_bus_ops;
common->ah = ah;
common->hw = priv->hw;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index ac9563e..c03b3fa 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -314,10 +314,6 @@
mod_timer(&priv->tx.cleanup_timer,
jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));
- /* perform spectral scan if requested. */
- if (test_bit(ATH_OP_SCANNING, &common->op_flags) &&
- priv->spec_priv.spectral_mode == SPECTRAL_CHANSCAN)
- ath9k_cmn_spectral_scan_trigger(common, &priv->spec_priv);
err:
ath9k_htc_ps_restore(priv);
return ret;
@@ -1447,7 +1443,7 @@
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- if (priv->ah->sw_mgmt_crypto_tx &&
+ if (priv->ah->sw_mgmt_crypto &&
key->cipher == WLAN_CIPHER_SUITE_CCMP)
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
ret = 0;
@@ -1691,9 +1687,7 @@
return ret;
}
-static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -1707,8 +1701,7 @@
mutex_unlock(&priv->mutex);
}
-static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_common *common = ath9k_hw_common(priv->ah);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index a0f58e2..f0484b1 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -946,7 +946,7 @@
static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats,
struct ath_htc_rx_status *rxstatus)
{
- rx_stats->rs_datalen = be16_to_cpu(rxstatus->rs_datalen);
+ rx_stats->rs_datalen = rxstatus->rs_datalen;
rx_stats->rs_status = rxstatus->rs_status;
rx_stats->rs_phyerr = rxstatus->rs_phyerr;
rx_stats->rs_rssi = rxstatus->rs_rssi;
@@ -1012,20 +1012,6 @@
* separately to avoid doing two lookups for a rate for each frame.
*/
hdr = (struct ieee80211_hdr *)skb->data;
-
- /*
- * Process PHY errors and return so that the packet
- * can be dropped.
- */
- if (rx_stats.rs_status & ATH9K_RXERR_PHY) {
- /* TODO: Not using DFS processing now. */
- if (ath_cmn_process_fft(&priv->spec_priv, hdr,
- &rx_stats, rx_status->mactime)) {
- /* TODO: Code to collect spectral scan statistics */
- }
- goto rx_next;
- }
-
if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats,
&decrypt_error, priv->rxfilter))
goto rx_next;
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index 6dd44d4..134862c 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h
@@ -41,9 +41,10 @@
ath9k_hw_ops(ah)->set_desc_link(ds, link);
}
-static inline int ath9k_hw_calibrate(struct ath_hw *ah,
- struct ath9k_channel *chan,
- u8 rxchainmask, bool longcal)
+static inline bool ath9k_hw_calibrate(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 rxchainmask,
+ bool longcal)
{
return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal);
}
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 82c7afa..3e83eec 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -19,7 +19,6 @@
#include <linux/module.h>
#include <linux/time.h>
#include <linux/bitops.h>
-#include <linux/etherdevice.h>
#include <asm/unaligned.h>
#include "hw.h"
@@ -447,16 +446,8 @@
common->macaddr[2 * i] = eeval >> 8;
common->macaddr[2 * i + 1] = eeval & 0xff;
}
- if (!is_valid_ether_addr(common->macaddr)) {
- ath_err(common,
- "eeprom contains invalid mac address: %pM\n",
- common->macaddr);
-
- random_ether_addr(common->macaddr);
- ath_err(common,
- "random mac address will be used: %pM\n",
- common->macaddr);
- }
+ if (sum == 0 || sum == 0xffff * 3)
+ return -EADDRNOTAVAIL;
return 0;
}
@@ -870,6 +861,19 @@
udelay(RTC_PLL_SETTLE_DELAY);
REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK);
+
+ if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) {
+ if (ah->is_clk_25mhz) {
+ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1);
+ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7);
+ REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae);
+ } else {
+ REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1);
+ REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400);
+ REG_WRITE(ah, AR_SLP32_INC, 0x0001e800);
+ }
+ udelay(100);
+ }
}
static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
@@ -1585,22 +1589,16 @@
* frames when constructing CCMP AAD. */
REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT,
0xc7ff);
- if (AR_SREV_9271(ah) || AR_DEVID_7010(ah))
- ah->sw_mgmt_crypto_tx = true;
- else
- ah->sw_mgmt_crypto_tx = false;
- ah->sw_mgmt_crypto_rx = false;
+ ah->sw_mgmt_crypto = false;
} else if (AR_SREV_9160_10_OR_LATER(ah)) {
/* Disable hardware crypto for management frames */
REG_CLR_BIT(ah, AR_PCU_MISC_MODE2,
AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE);
REG_SET_BIT(ah, AR_PCU_MISC_MODE2,
AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT);
- ah->sw_mgmt_crypto_tx = true;
- ah->sw_mgmt_crypto_rx = true;
+ ah->sw_mgmt_crypto = true;
} else {
- ah->sw_mgmt_crypto_tx = true;
- ah->sw_mgmt_crypto_rx = true;
+ ah->sw_mgmt_crypto = true;
}
}
@@ -1947,8 +1945,6 @@
REGWRITE_BUFFER_FLUSH(ah);
- ath9k_hw_gen_timer_start_tsf2(ah);
-
ath9k_hw_init_desc(ah);
if (ath9k_hw_btcoex_is_enabled(ah))
@@ -1957,10 +1953,8 @@
if (ath9k_hw_mci_is_enabled(ah))
ar9003_mci_check_bt(ah);
- if (AR_SREV_9300_20_OR_LATER(ah)) {
- ath9k_hw_loadnf(ah, chan);
- ath9k_hw_start_nfcal(ah, true);
- }
+ ath9k_hw_loadnf(ah, chan);
+ ath9k_hw_start_nfcal(ah, true);
if (AR_SREV_9300_20_OR_LATER(ah))
ar9003_hw_bb_watchdog_config(ah);
@@ -2328,6 +2322,7 @@
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
struct ath_common *common = ath9k_hw_common(ah);
+ unsigned int chip_chainmask;
u16 eeval;
u8 ant_div_ctl1, tx_chainmask, rx_chainmask;
@@ -2347,40 +2342,31 @@
}
eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
-
- if (eeval & AR5416_OPFLAGS_11A) {
- if (ah->disable_5ghz)
- ath_warn(common, "disabling 5GHz band\n");
- else
- pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
- }
-
- if (eeval & AR5416_OPFLAGS_11G) {
- if (ah->disable_2ghz)
- ath_warn(common, "disabling 2GHz band\n");
- else
- pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
- }
-
- if ((pCap->hw_caps & (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) {
- ath_err(common, "both bands are disabled\n");
+ if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
+ ath_err(common,
+ "no band has been marked as supported in EEPROM\n");
return -EINVAL;
}
+ if (eeval & AR5416_OPFLAGS_11A)
+ pCap->hw_caps |= ATH9K_HW_CAP_5GHZ;
+
+ if (eeval & AR5416_OPFLAGS_11G)
+ pCap->hw_caps |= ATH9K_HW_CAP_2GHZ;
+
if (AR_SREV_9485(ah) ||
AR_SREV_9285(ah) ||
AR_SREV_9330(ah) ||
AR_SREV_9565(ah))
- pCap->chip_chainmask = 1;
+ chip_chainmask = 1;
+ else if (AR_SREV_9462(ah))
+ chip_chainmask = 3;
else if (!AR_SREV_9280_20_OR_LATER(ah))
- pCap->chip_chainmask = 7;
- else if (!AR_SREV_9300_20_OR_LATER(ah) ||
- AR_SREV_9340(ah) ||
- AR_SREV_9462(ah) ||
- AR_SREV_9531(ah))
- pCap->chip_chainmask = 3;
+ chip_chainmask = 7;
+ else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah))
+ chip_chainmask = 3;
else
- pCap->chip_chainmask = 7;
+ chip_chainmask = 7;
pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
/*
@@ -2398,8 +2384,8 @@
/* Use rx_chainmask from EEPROM. */
pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK);
- pCap->tx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->tx_chainmask);
- pCap->rx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->rx_chainmask);
+ pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask);
+ pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask);
ah->txchainmask = pCap->tx_chainmask;
ah->rxchainmask = pCap->rx_chainmask;
@@ -2913,16 +2899,6 @@
}
EXPORT_SYMBOL(ath9k_hw_gettsf32);
-void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah)
-{
- struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
-
- if (timer_table->tsf2_enabled) {
- REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN);
- REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE);
- }
-}
-
struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah,
void (*trigger)(void *),
void (*overflow)(void *),
@@ -2933,11 +2909,7 @@
struct ath_gen_timer *timer;
if ((timer_index < AR_FIRST_NDP_TIMER) ||
- (timer_index >= ATH_MAX_GEN_TIMER))
- return NULL;
-
- if ((timer_index > AR_FIRST_NDP_TIMER) &&
- !AR_SREV_9300_20_OR_LATER(ah))
+ (timer_index >= ATH_MAX_GEN_TIMER))
return NULL;
timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL);
@@ -2951,11 +2923,6 @@
timer->overflow = overflow;
timer->arg = arg;
- if ((timer_index > AR_FIRST_NDP_TIMER) && !timer_table->tsf2_enabled) {
- timer_table->tsf2_enabled = true;
- ath9k_hw_gen_timer_start_tsf2(ah);
- }
-
return timer;
}
EXPORT_SYMBOL(ath_gen_timer_alloc);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index fda6cb5..a578e51 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -217,8 +217,8 @@
#define AH_WOW_BEACON_MISS BIT(3)
enum ath_hw_txq_subtype {
- ATH_TXQ_AC_BK = 0,
- ATH_TXQ_AC_BE = 1,
+ ATH_TXQ_AC_BE = 0,
+ ATH_TXQ_AC_BK = 1,
ATH_TXQ_AC_VI = 2,
ATH_TXQ_AC_VO = 3,
};
@@ -244,20 +244,13 @@
ATH9K_HW_CAP_2GHZ = BIT(11),
ATH9K_HW_CAP_5GHZ = BIT(12),
ATH9K_HW_CAP_APM = BIT(13),
-#ifdef CPTCFG_ATH9K_PCOEM
ATH9K_HW_CAP_RTT = BIT(14),
ATH9K_HW_CAP_MCI = BIT(15),
- ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(16),
- ATH9K_HW_CAP_BT_ANT_DIV = BIT(17),
-#else
- ATH9K_HW_CAP_RTT = 0,
- ATH9K_HW_CAP_MCI = 0,
- ATH9K_HW_WOW_DEVICE_CAPABLE = 0,
- ATH9K_HW_CAP_BT_ANT_DIV = 0,
-#endif
- ATH9K_HW_CAP_DFS = BIT(18),
- ATH9K_HW_CAP_PAPRD = BIT(19),
- ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(20),
+ ATH9K_HW_CAP_DFS = BIT(16),
+ ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17),
+ ATH9K_HW_CAP_PAPRD = BIT(18),
+ ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(19),
+ ATH9K_HW_CAP_BT_ANT_DIV = BIT(20),
};
/*
@@ -276,7 +269,6 @@
u16 rts_aggr_limit;
u8 tx_chainmask;
u8 rx_chainmask;
- u8 chip_chainmask;
u8 max_txchains;
u8 max_rxchains;
u8 num_gpio_pins;
@@ -330,7 +322,6 @@
bool alt_mingainidx;
bool no_pll_pwrsave;
bool tx_gain_buffalo;
- bool led_active_high;
};
enum ath9k_int {
@@ -526,7 +517,6 @@
struct ath_gen_timer_table {
struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER];
u16 timer_mask;
- bool tsf2_enabled;
};
struct ath_hw_antcomb_conf {
@@ -691,8 +681,10 @@
bool power_off);
void (*rx_enable)(struct ath_hw *ah);
void (*set_desc_link)(void *ds, u32 link);
- int (*calibrate)(struct ath_hw *ah, struct ath9k_channel *chan,
- u8 rxchainmask, bool longcal);
+ bool (*calibrate)(struct ath_hw *ah,
+ struct ath9k_channel *chan,
+ u8 rxchainmask,
+ bool longcal);
bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked,
u32 *sync_cause_p);
void (*set_txdesc)(struct ath_hw *ah, void *ds,
@@ -734,7 +726,6 @@
#define AH_USE_EEPROM 0x1
#define AH_UNPLUGGED 0x2 /* The card has been physically removed. */
#define AH_FASTCC 0x4
-#define AH_NO_EEP_SWAP 0x8 /* Do not swap EEPROM data */
struct ath_hw {
struct ath_ops reg_ops;
@@ -756,8 +747,7 @@
} eeprom;
const struct eeprom_ops *eep_ops;
- bool sw_mgmt_crypto_tx;
- bool sw_mgmt_crypto_rx;
+ bool sw_mgmt_crypto;
bool is_pciexpress;
bool aspm_enabled;
bool is_monitoring;
@@ -934,16 +924,10 @@
bool is_clk_25mhz;
int (*get_mac_revision)(void);
int (*external_reset)(void);
- bool disable_2ghz;
- bool disable_5ghz;
const struct firmware *eeprom_blob;
struct ath_dynack dynack;
-
- bool tpc_enabled;
- u8 tx_power[Ar5416RateSize];
- u8 tx_power_stbc[Ar5416RateSize];
};
struct ath_bus_ops {
@@ -1043,7 +1027,6 @@
struct ath_gen_timer *timer,
u32 timer_next,
u32 timer_period);
-void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah);
void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer);
void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer);
@@ -1084,8 +1067,6 @@
bool ar9003_paprd_is_done(struct ath_hw *ah);
bool ar9003_is_paprd_enabled(struct ath_hw *ah);
void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
-void ar9003_hw_init_rate_txpower(struct ath_hw *ah, u8 *rate_array,
- struct ath9k_channel *chan);
/* Hardware family op attach helpers */
int ar5008_hw_attach_phy_ops(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 7764675..4df734e 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -104,21 +104,6 @@
static void ath9k_deinit_softc(struct ath_softc *sc);
-static void ath9k_op_ps_wakeup(struct ath_common *common)
-{
- ath9k_ps_wakeup((struct ath_softc *) common->priv);
-}
-
-static void ath9k_op_ps_restore(struct ath_common *common)
-{
- ath9k_ps_restore((struct ath_softc *) common->priv);
-}
-
-static struct ath_ps_ops ath9k_ps_ops = {
- .wakeup = ath9k_op_ps_wakeup,
- .restore = ath9k_op_ps_restore,
-};
-
/*
* Read and write, they both share the same lock. We do this to serialize
* reads and writes on Atheros 802.11n PCI devices only. This is required
@@ -203,20 +188,17 @@
ath_reg_notifier_apply(wiphy, request, reg);
/* Set tx power */
- if (!ah->curchan)
- return;
-
- sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power;
- ath9k_ps_wakeup(sc);
- ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
- ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
- sc->cur_chan->txpower,
- &sc->cur_chan->cur_txpower);
- /* synchronize DFS detector if regulatory domain changed */
- if (sc->dfs_detector != NULL)
- sc->dfs_detector->set_dfs_domain(sc->dfs_detector,
- request->dfs_region);
- ath9k_ps_restore(sc);
+ if (ah->curchan) {
+ sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power;
+ ath9k_ps_wakeup(sc);
+ ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false);
+ sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
+ /* synchronize DFS detector if regulatory domain changed */
+ if (sc->dfs_detector != NULL)
+ sc->dfs_detector->set_dfs_domain(sc->dfs_detector,
+ request->dfs_region);
+ ath9k_ps_restore(sc);
+ }
}
/*
@@ -382,13 +364,12 @@
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
- sc->spec_priv.ah = sc->sc_ah;
- sc->spec_priv.spec_config.enabled = 0;
- sc->spec_priv.spec_config.short_repeat = true;
- sc->spec_priv.spec_config.count = 8;
- sc->spec_priv.spec_config.endless = false;
- sc->spec_priv.spec_config.period = 0xFF;
- sc->spec_priv.spec_config.fft_period = 0xF;
+ sc->spec_config.enabled = 0;
+ sc->spec_config.short_repeat = true;
+ sc->spec_config.count = 8;
+ sc->spec_config.endless = false;
+ sc->spec_config.period = 0xFF;
+ sc->spec_config.fft_period = 0xF;
}
static void ath9k_init_pcoem_platform(struct ath_softc *sc)
@@ -397,9 +378,6 @@
struct ath9k_hw_capabilities *pCap = &ah->caps;
struct ath_common *common = ath9k_hw_common(ah);
- if (!IS_ENABLED(CPTCFG_ATH9K_PCOEM))
- return;
-
if (common->bus_ops->ath_bus_type != ATH_PCI)
return;
@@ -457,9 +435,6 @@
ah->config.no_pll_pwrsave = true;
ath_info(common, "Disable PLL PowerSave\n");
}
-
- if (sc->driver_data & ATH9K_PCI_LED_ACT_HI)
- ah->config.led_active_high = true;
}
static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob,
@@ -548,14 +523,10 @@
ah->reg_ops.read = ath9k_ioread32;
ah->reg_ops.write = ath9k_iowrite32;
ah->reg_ops.rmw = ath9k_reg_rmw;
+ sc->sc_ah = ah;
pCap = &ah->caps;
common = ath9k_hw_common(ah);
-
- /* Will be cleared in ath9k_start() */
- set_bit(ATH_OP_INVALID, &common->op_flags);
-
- sc->sc_ah = ah;
sc->dfs_detector = dfs_pattern_detector_init(common, NL80211_DFS_UNSET);
sc->tx99_power = MAX_RATE_POWER + 1;
init_waitqueue_head(&sc->tx_wait);
@@ -573,15 +544,10 @@
ah->is_clk_25mhz = pdata->is_clk_25mhz;
ah->get_mac_revision = pdata->get_mac_revision;
ah->external_reset = pdata->external_reset;
- ah->disable_2ghz = pdata->disable_2ghz;
- ah->disable_5ghz = pdata->disable_5ghz;
- if (!pdata->endian_check)
- ah->ah_flags |= AH_NO_EEP_SWAP;
}
common->ops = &ah->reg_ops;
common->bus_ops = bus_ops;
- common->ps_ops = &ath9k_ps_ops;
common->ah = ah;
common->hw = sc->hw;
common->priv = sc;
@@ -920,6 +886,9 @@
common = ath9k_hw_common(ah);
ath9k_set_hw_capab(sc, hw);
+ /* Will be cleared in ath9k_start() */
+ set_bit(ATH_OP_INVALID, &common->op_flags);
+
/* Initialize regulatory */
error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
ath9k_reg_notifier);
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index b829263..2343f56 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -371,15 +371,9 @@
/* Perform calibration if necessary */
if (longcal || shortcal) {
- int ret = ath9k_hw_calibrate(ah, ah->curchan, ah->rxchainmask,
- longcal);
- if (ret < 0) {
- common->ani.caldone = 0;
- ath9k_queue_reset(sc, RESET_TYPE_CALIBRATION);
- return;
- }
-
- common->ani.caldone = ret;
+ common->ani.caldone =
+ ath9k_hw_calibrate(ah, ah->curchan,
+ ah->rxchainmask, longcal);
}
ath_dbg(common, ANI,
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 3e58bfa..275205a 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -311,7 +311,14 @@
q = ATH9K_NUM_TX_QUEUES - 3;
break;
case ATH9K_TX_QUEUE_DATA:
- q = qinfo->tqi_subtype;
+ for (q = 0; q < ATH9K_NUM_TX_QUEUES; q++)
+ if (ah->txq[q].tqi_type ==
+ ATH9K_TX_QUEUE_INACTIVE)
+ break;
+ if (q == ATH9K_NUM_TX_QUEUES) {
+ ath_err(common, "No available TX queue\n");
+ return -1;
+ }
break;
default:
ath_err(common, "Invalid TX queue type: %u\n", type);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index e55fa11..aa69cea 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -704,7 +704,7 @@
enum ath9k_pkt_type type;
enum ath9k_key_type keytype;
u8 keyix;
- u8 txpower[4];
+ u8 txpower;
};
struct ath_hw;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 38efe20..35bf3e7 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -54,8 +54,7 @@
}
}
-static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq,
- bool sw_pending)
+static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
{
bool pending = false;
@@ -66,9 +65,6 @@
goto out;
}
- if (!sw_pending)
- goto out;
-
if (txq->mac80211_qnum >= 0) {
struct list_head *list;
@@ -233,9 +229,8 @@
ath9k_calculate_summary_state(sc, sc->cur_chan);
ath_startrecv(sc);
- ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
- sc->cur_chan->txpower,
- &sc->cur_chan->cur_txpower);
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->cur_chan->txpower, &sc->curtxpow);
clear_bit(ATH_OP_HW_RESET, &common->op_flags);
if (!sc->cur_chan->offchannel && start) {
@@ -275,7 +270,7 @@
return true;
}
-static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
+int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -286,7 +281,6 @@
__ath_cancel_work(sc);
tasklet_disable(&sc->intr_tq);
- tasklet_disable(&sc->bcon_tasklet);
spin_lock_bh(&sc->sc_pcu_lock);
if (!sc->cur_chan->offchannel) {
@@ -332,7 +326,6 @@
out:
spin_unlock_bh(&sc->sc_pcu_lock);
- tasklet_enable(&sc->bcon_tasklet);
tasklet_enable(&sc->intr_tq);
return r;
@@ -546,10 +539,11 @@
sched = true;
/*
- * If a FATAL interrupt is received, we have to reset the chip
- * immediately.
+ * If a FATAL or RXORN interrupt is received, we have to reset the
+ * chip immediately.
*/
- if (status & ATH9K_INT_FATAL)
+ if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) &&
+ !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)))
goto chip_reset;
if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) &&
@@ -604,11 +598,7 @@
#undef SCHED_INTR
}
-/*
- * This function is called when a HW reset cannot be deferred
- * and has to be immediate.
- */
-int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan)
+int ath_reset(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int r;
@@ -616,17 +606,12 @@
set_bit(ATH_OP_HW_RESET, &common->op_flags);
ath9k_ps_wakeup(sc);
- r = ath_reset_internal(sc, hchan);
+ r = ath_reset_internal(sc, NULL);
ath9k_ps_restore(sc);
return r;
}
-/*
- * When a HW reset can be deferred, it is added to the
- * hw_reset_work workqueue, but we set ATH_OP_HW_RESET before
- * queueing.
- */
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -641,9 +626,7 @@
{
struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work);
- ath9k_ps_wakeup(sc);
- ath_reset_internal(sc, NULL);
- ath9k_ps_restore(sc);
+ ath_reset(sc);
}
/**********************/
@@ -727,8 +710,7 @@
if (ah->led_pin >= 0) {
ath9k_hw_cfg_output(ah, ah->led_pin,
AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
- ath9k_hw_set_gpio(ah, ah->led_pin,
- (ah->config.led_active_high) ? 1 : 0);
+ ath9k_hw_set_gpio(ah, ah->led_pin, 0);
}
/*
@@ -870,8 +852,7 @@
spin_lock_bh(&sc->sc_pcu_lock);
if (ah->led_pin >= 0) {
- ath9k_hw_set_gpio(ah, ah->led_pin,
- (ah->config.led_active_high) ? 0 : 1);
+ ath9k_hw_set_gpio(ah, ah->led_pin, 1);
ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
}
@@ -887,9 +868,6 @@
&sc->cur_chan->chandef);
ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
-
- set_bit(ATH_OP_INVALID, &common->op_flags);
-
ath9k_hw_phy_disable(ah);
ath9k_hw_configpcipowersave(ah, true);
@@ -898,6 +876,7 @@
ath9k_ps_restore(sc);
+ set_bit(ATH_OP_INVALID, &common->op_flags);
sc->ps_idle = prev_idle;
mutex_unlock(&sc->mutex);
@@ -998,8 +977,9 @@
struct ath_vif *avp;
/*
- * The hardware will use primary station addr together with the
- * BSSID mask when matching addresses.
+ * Pick the MAC address of the first interface as the new hardware
+ * MAC address. The hardware will use it together with the BSSID mask
+ * when matching addresses.
*/
memset(iter_data, 0, sizeof(*iter_data));
memset(&iter_data->mask, 0xff, ETH_ALEN);
@@ -1060,7 +1040,7 @@
eth_zero_addr(common->curbssid);
eth_broadcast_addr(common->bssidmask);
- memcpy(common->macaddr, vif->addr, ETH_ALEN);
+ ether_addr_copy(common->macaddr, vif->addr);
common->curaid = 0;
ah->opmode = vif->type;
ah->imask &= ~ATH9K_INT_SWBA;
@@ -1101,7 +1081,7 @@
ath9k_calculate_iter_data(sc, ctx, &iter_data);
if (iter_data.has_hw_macaddr)
- memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN);
+ ether_addr_copy(common->macaddr, iter_data.hw_macaddr);
memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
ath_hw_setbssidmask(common);
@@ -1191,8 +1171,7 @@
for (i = 0; i < IEEE80211_NUM_ACS; i++)
vif->hw_queue[i] = i;
- if (vif->type == NL80211_IFTYPE_AP ||
- vif->type == NL80211_IFTYPE_MESH_POINT)
+ if (vif->type == NL80211_IFTYPE_AP)
vif->cab_queue = hw->queues - 2;
else
vif->cab_queue = IEEE80211_INVAL_HW_QUEUE;
@@ -1229,8 +1208,6 @@
list_add_tail(&avp->list, &avp->chanctx->vifs);
}
- ath9k_calculate_summary_state(sc, avp->chanctx);
-
ath9k_assign_hw_queues(hw, vif);
an->sc = sc;
@@ -1300,8 +1277,6 @@
ath_tx_node_cleanup(sc, &avp->mcast_node);
- ath9k_calculate_summary_state(sc, avp->chanctx);
-
mutex_unlock(&sc->mutex);
}
@@ -1348,6 +1323,78 @@
ath_dbg(common, PS, "PowerSave disabled\n");
}
+void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+ u32 rxfilter;
+
+ if (config_enabled(CPTCFG_ATH9K_TX99))
+ return;
+
+ if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
+ ath_err(common, "spectrum analyzer not implemented on this hardware\n");
+ return;
+ }
+
+ ath9k_ps_wakeup(sc);
+ rxfilter = ath9k_hw_getrxfilter(ah);
+ ath9k_hw_setrxfilter(ah, rxfilter |
+ ATH9K_RX_FILTER_PHYRADAR |
+ ATH9K_RX_FILTER_PHYERR);
+
+ /* TODO: usually this should not be neccesary, but for some reason
+ * (or in some mode?) the trigger must be called after the
+ * configuration, otherwise the register will have its values reset
+ * (on my ar9220 to value 0x01002310)
+ */
+ ath9k_spectral_scan_config(hw, sc->spectral_mode);
+ ath9k_hw_ops(ah)->spectral_scan_trigger(ah);
+ ath9k_ps_restore(sc);
+}
+
+int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
+ enum spectral_mode spectral_mode)
+{
+ struct ath_softc *sc = hw->priv;
+ struct ath_hw *ah = sc->sc_ah;
+ struct ath_common *common = ath9k_hw_common(ah);
+
+ if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
+ ath_err(common, "spectrum analyzer not implemented on this hardware\n");
+ return -1;
+ }
+
+ switch (spectral_mode) {
+ case SPECTRAL_DISABLED:
+ sc->spec_config.enabled = 0;
+ break;
+ case SPECTRAL_BACKGROUND:
+ /* send endless samples.
+ * TODO: is this really useful for "background"?
+ */
+ sc->spec_config.endless = 1;
+ sc->spec_config.enabled = 1;
+ break;
+ case SPECTRAL_CHANSCAN:
+ case SPECTRAL_MANUAL:
+ sc->spec_config.endless = 0;
+ sc->spec_config.enabled = 1;
+ break;
+ default:
+ return -1;
+ }
+
+ ath9k_ps_wakeup(sc);
+ ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config);
+ ath9k_ps_restore(sc);
+
+ sc->spectral_mode = spectral_mode;
+
+ return 0;
+}
+
static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
{
struct ath_softc *sc = hw->priv;
@@ -1408,9 +1455,8 @@
if (changed & IEEE80211_CONF_CHANGE_POWER) {
ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level);
sc->cur_chan->txpower = 2 * conf->power_level;
- ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower,
- sc->cur_chan->txpower,
- &sc->cur_chan->cur_txpower);
+ ath9k_cmn_update_txpow(ah, sc->curtxpow,
+ sc->cur_chan->txpower, &sc->curtxpow);
}
mutex_unlock(&sc->mutex);
@@ -1507,40 +1553,6 @@
return 0;
}
-static int ath9k_sta_state(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- enum ieee80211_sta_state old_state,
- enum ieee80211_sta_state new_state)
-{
- struct ath_softc *sc = hw->priv;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- int ret = 0;
-
- if (old_state == IEEE80211_STA_AUTH &&
- new_state == IEEE80211_STA_ASSOC) {
- ret = ath9k_sta_add(hw, vif, sta);
- ath_dbg(common, CONFIG,
- "Add station: %pM\n", sta->addr);
- } else if (old_state == IEEE80211_STA_ASSOC &&
- new_state == IEEE80211_STA_AUTH) {
- ret = ath9k_sta_remove(hw, vif, sta);
- ath_dbg(common, CONFIG,
- "Remove station: %pM\n", sta->addr);
- }
-
- if (ath9k_is_chanctx_enabled()) {
- if (vif->type == NL80211_IFTYPE_STATION) {
- if (old_state == IEEE80211_STA_ASSOC &&
- new_state == IEEE80211_STA_AUTHORIZED)
- ath_chanctx_event(sc, vif,
- ATH_CHANCTX_EVENT_AUTHORIZED);
- }
- }
-
- return ret;
-}
-
static void ath9k_sta_set_tx_filter(struct ath_hw *ah,
struct ath_node *an,
bool set)
@@ -1665,7 +1677,7 @@
key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
if (key->cipher == WLAN_CIPHER_SUITE_TKIP)
key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- if (sc->sc_ah->sw_mgmt_crypto_tx &&
+ if (sc->sc_ah->sw_mgmt_crypto &&
key->cipher == WLAN_CIPHER_SUITE_CCMP)
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
ret = 0;
@@ -1725,11 +1737,17 @@
ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n",
bss_conf->bssid, bss_conf->assoc);
- memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN);
+ ether_addr_copy(avp->bssid, bss_conf->bssid);
avp->aid = bss_conf->aid;
avp->assoc = bss_conf->assoc;
ath9k_calculate_summary_state(sc, avp->chanctx);
+
+ if (ath9k_is_chanctx_enabled()) {
+ if (bss_conf->assoc)
+ ath_chanctx_event(sc, vif,
+ ATH_CHANCTX_EVENT_ASSOC);
+ }
}
if (changed & BSS_CHANGED_IBSS) {
@@ -1825,7 +1843,6 @@
u16 tid, u16 *ssn, u8 buf_size)
{
struct ath_softc *sc = hw->priv;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
bool flush = false;
int ret = 0;
@@ -1837,12 +1854,6 @@
case IEEE80211_AMPDU_RX_STOP:
break;
case IEEE80211_AMPDU_TX_START:
- if (ath9k_is_chanctx_enabled()) {
- if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
- ret = -EBUSY;
- break;
- }
- }
ath9k_ps_wakeup(sc);
ret = ath_tx_aggr_start(sc, sta, tid, ssn);
if (!ret)
@@ -1956,8 +1967,7 @@
mutex_unlock(&sc->mutex);
}
-static bool ath9k_has_tx_pending(struct ath_softc *sc,
- bool sw_pending)
+static bool ath9k_has_tx_pending(struct ath_softc *sc)
{
int i, npend = 0;
@@ -1965,8 +1975,7 @@
if (!ATH_TXQ_SETUP(sc, i))
continue;
- npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i],
- sw_pending);
+ npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
if (npend)
break;
}
@@ -1978,38 +1987,18 @@
u32 queues, bool drop)
{
struct ath_softc *sc = hw->priv;
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- if (ath9k_is_chanctx_enabled()) {
- if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
- goto flush;
-
- /*
- * If MCC is active, extend the flush timeout
- * and wait for the HW/SW queues to become
- * empty. This needs to be done outside the
- * sc->mutex lock to allow the channel scheduler
- * to switch channel contexts.
- *
- * The vif queues have been stopped in mac80211,
- * so there won't be any incoming frames.
- */
- __ath9k_flush(hw, queues, drop, true, true);
- return;
- }
-flush:
mutex_lock(&sc->mutex);
- __ath9k_flush(hw, queues, drop, true, false);
+ __ath9k_flush(hw, queues, drop);
mutex_unlock(&sc->mutex);
}
-void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop,
- bool sw_pending, bool timeout_override)
+void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- int timeout;
+ int timeout = HZ / 5; /* 200 ms */
bool drain_txq;
cancel_delayed_work_sync(&sc->tx_complete_work);
@@ -2024,17 +2013,7 @@
return;
}
- spin_lock_bh(&sc->chan_lock);
- if (timeout_override)
- timeout = HZ / 5;
- else
- timeout = sc->cur_chan->flush_timeout;
- spin_unlock_bh(&sc->chan_lock);
-
- ath_dbg(common, CHAN_CTX,
- "Flush timeout: %d\n", jiffies_to_msecs(timeout));
-
- if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc, sw_pending),
+ if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc),
timeout) > 0)
drop = false;
@@ -2045,7 +2024,7 @@
spin_unlock_bh(&sc->sc_pcu_lock);
if (!drain_txq)
- ath_reset(sc, NULL);
+ ath_reset(sc);
ath9k_ps_restore(sc);
}
@@ -2057,7 +2036,7 @@
{
struct ath_softc *sc = hw->priv;
- return ath9k_has_tx_pending(sc, true);
+ return ath9k_has_tx_pending(sc);
}
static int ath9k_tx_last_beacon(struct ieee80211_hw *hw)
@@ -2188,17 +2167,14 @@
return 0;
}
-static void ath9k_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
set_bit(ATH_OP_SCANNING, &common->op_flags);
}
-static void ath9k_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
{
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -2207,28 +2183,6 @@
#ifdef CPTCFG_ATH9K_CHANNEL_CONTEXT
-static void ath9k_cancel_pending_offchannel(struct ath_softc *sc)
-{
- struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-
- if (sc->offchannel.roc_vif) {
- ath_dbg(common, CHAN_CTX,
- "%s: Aborting RoC\n", __func__);
-
- del_timer_sync(&sc->offchannel.timer);
- if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START)
- ath_roc_complete(sc, true);
- }
-
- if (test_bit(ATH_OP_SCANNING, &common->op_flags)) {
- ath_dbg(common, CHAN_CTX,
- "%s: Aborting HW scan\n", __func__);
-
- del_timer_sync(&sc->offchannel.timer);
- ath_scan_complete(sc, true);
- }
-}
-
static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_scan_request *hw_req)
{
@@ -2359,6 +2313,7 @@
conf->def.chan->center_freq);
ath_chanctx_set_channel(sc, ctx, &conf->def);
+ ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ASSIGN);
mutex_unlock(&sc->mutex);
return 0;
@@ -2415,8 +2370,6 @@
struct ath_chanctx *ctx = ath_chanctx_get(conf);
int i;
- ath9k_cancel_pending_offchannel(sc);
-
mutex_lock(&sc->mutex);
ath_dbg(common, CHAN_CTX,
@@ -2446,8 +2399,6 @@
struct ath_chanctx *ctx = ath_chanctx_get(conf);
int ac;
- ath9k_cancel_pending_offchannel(sc);
-
mutex_lock(&sc->mutex);
ath_dbg(common, CHAN_CTX,
@@ -2471,11 +2422,7 @@
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_vif *avp = (struct ath_vif *) vif->drv_priv;
- struct ath_beacon_config *cur_conf;
- struct ath_chanctx *go_ctx;
- unsigned long timeout;
bool changed = false;
- u32 beacon_int;
if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags))
return;
@@ -2486,57 +2433,19 @@
mutex_lock(&sc->mutex);
spin_lock_bh(&sc->chan_lock);
- if (sc->next_chan || (sc->cur_chan != avp->chanctx))
+ if (sc->next_chan || (sc->cur_chan != avp->chanctx)) {
+ sc->next_chan = avp->chanctx;
changed = true;
- spin_unlock_bh(&sc->chan_lock);
-
- if (!changed)
- goto out;
-
- ath9k_cancel_pending_offchannel(sc);
-
- go_ctx = ath_is_go_chanctx_present(sc);
-
- if (go_ctx) {
- /*
- * Wait till the GO interface gets a chance
- * to send out an NoA.
- */
- spin_lock_bh(&sc->chan_lock);
- sc->sched.mgd_prepare_tx = true;
- cur_conf = &go_ctx->beacon;
- beacon_int = TU_TO_USEC(cur_conf->beacon_interval);
- spin_unlock_bh(&sc->chan_lock);
-
- timeout = usecs_to_jiffies(beacon_int * 2);
- init_completion(&sc->go_beacon);
-
- mutex_unlock(&sc->mutex);
-
- if (wait_for_completion_timeout(&sc->go_beacon,
- timeout) == 0) {
- ath_dbg(common, CHAN_CTX,
- "Failed to send new NoA\n");
-
- spin_lock_bh(&sc->chan_lock);
- sc->sched.mgd_prepare_tx = false;
- spin_unlock_bh(&sc->chan_lock);
- }
-
- mutex_lock(&sc->mutex);
}
-
ath_dbg(common, CHAN_CTX,
- "%s: Set chanctx state to FORCE_ACTIVE for vif: %pM\n",
- __func__, vif->addr);
-
- spin_lock_bh(&sc->chan_lock);
- sc->next_chan = avp->chanctx;
+ "%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n",
+ __func__, changed);
sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE;
spin_unlock_bh(&sc->chan_lock);
- ath_chanctx_set_next(sc, true);
-out:
+ if (changed)
+ ath_chanctx_set_next(sc, true);
+
mutex_unlock(&sc->mutex);
}
@@ -2559,24 +2468,6 @@
#endif
-static int ath9k_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- int *dbm)
-{
- struct ath_softc *sc = hw->priv;
- struct ath_vif *avp = (void *)vif->drv_priv;
-
- mutex_lock(&sc->mutex);
- if (avp->chanctx)
- *dbm = avp->chanctx->cur_txpower;
- else
- *dbm = sc->cur_chan->cur_txpower;
- mutex_unlock(&sc->mutex);
-
- *dbm /= 2;
-
- return 0;
-}
-
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@@ -2586,7 +2477,8 @@
.remove_interface = ath9k_remove_interface,
.config = ath9k_config,
.configure_filter = ath9k_configure_filter,
- .sta_state = ath9k_sta_state,
+ .sta_add = ath9k_sta_add,
+ .sta_remove = ath9k_sta_remove,
.sta_notify = ath9k_sta_notify,
.conf_tx = ath9k_conf_tx,
.bss_info_changed = ath9k_bss_info_changed,
@@ -2623,5 +2515,4 @@
#endif
.sw_scan_start = ath9k_sw_scan_start,
.sw_scan_complete = ath9k_sw_scan_complete,
- .get_txpower = ath9k_get_txpower,
};
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 6bc24fb..c018dea 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -30,7 +30,6 @@
{ PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */
{ PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */
-#ifdef CPTCFG_ATH9K_PCOEM
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x002A,
PCI_VENDOR_ID_AZWAVE,
@@ -83,7 +82,6 @@
PCI_VENDOR_ID_AZWAVE,
0x2C37),
.driver_data = ATH9K_PCI_BT_ANT_DIV },
-#endif
{ PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */
{ PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */
@@ -104,7 +102,6 @@
{ PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */
-#ifdef CPTCFG_ATH9K_PCOEM
/* PCI-E CUS198 */
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0032,
@@ -297,12 +294,10 @@
PCI_VENDOR_ID_ASUSTEK,
0x850D),
.driver_data = ATH9K_PCI_NO_PLL_PWRSAVE },
-#endif
{ PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */
{ PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */
-#ifdef CPTCFG_ATH9K_PCOEM
/* PCI-E CUS217 */
{ PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS,
0x0034,
@@ -657,14 +652,11 @@
0x0036,
PCI_VENDOR_ID_DELL,
0x020E),
- .driver_data = ATH9K_PCI_AR9565_2ANT |
- ATH9K_PCI_BT_ANT_DIV |
- ATH9K_PCI_LED_ACT_HI},
+ .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV },
/* PCI-E AR9565 (WB335) */
{ PCI_VDEVICE(ATHEROS, 0x0036),
.driver_data = ATH9K_PCI_BT_ANT_DIV },
-#endif
{ 0 }
};
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 04da61b..b231f21 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -870,7 +870,7 @@
*/
if (rx_stats->rs_status & ATH9K_RXERR_PHY) {
ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime);
- if (ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime))
+ if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime))
RX_STAT_INC(rx_spectral);
return -EINVAL;
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 7743b38..2a938f4 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -892,21 +892,10 @@
(AR_SREV_9330((_ah)) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12))
-#ifdef CPTCFG_ATH9K_PCOEM
-#define AR_SREV_9462(_ah) \
- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
#define AR_SREV_9485(_ah) \
(((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485))
-#define AR_SREV_9565(_ah) \
- (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
-#else
-#define AR_SREV_9462(_ah) 0
-#define AR_SREV_9485(_ah) 0
-#define AR_SREV_9565(_ah) 0
-#endif
-
#define AR_SREV_9485_11_OR_LATER(_ah) \
- (AR_SREV_9485(_ah) && \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9485_11))
#define AR_SREV_9485_OR_LATER(_ah) \
(((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485))
@@ -926,30 +915,34 @@
(AR_SREV_9285_12_OR_LATER(_ah) && \
((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1))
+#define AR_SREV_9462(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462))
#define AR_SREV_9462_20(_ah) \
- (AR_SREV_9462(_ah) && \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20))
#define AR_SREV_9462_21(_ah) \
- (AR_SREV_9462(_ah) && \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_21))
#define AR_SREV_9462_20_OR_LATER(_ah) \
- (AR_SREV_9462(_ah) && \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20))
#define AR_SREV_9462_21_OR_LATER(_ah) \
- (AR_SREV_9462(_ah) && \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_21))
+#define AR_SREV_9565(_ah) \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565))
#define AR_SREV_9565_10(_ah) \
- (AR_SREV_9565(_ah) && \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10))
#define AR_SREV_9565_101(_ah) \
- (AR_SREV_9565(_ah) && \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101))
#define AR_SREV_9565_11(_ah) \
- (AR_SREV_9565(_ah) && \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11))
#define AR_SREV_9565_11_OR_LATER(_ah) \
- (AR_SREV_9565(_ah) && \
+ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \
((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11))
#define AR_SREV_9550(_ah) \
@@ -1605,7 +1598,6 @@
#define AR_RESET_TSF 0x8020
#define AR_RESET_TSF_ONCE 0x01000000
-#define AR_RESET_TSF2_ONCE 0x02000000
#define AR_MAX_CFP_DUR 0x8038
#define AR_CFP_VAL 0x0000FFFF
@@ -1724,8 +1716,6 @@
#define AR_TPC_CTS_S 8
#define AR_TPC_CHIRP 0x003f0000
#define AR_TPC_CHIRP_S 16
-#define AR_TPC_RPT 0x3f000000
-#define AR_TPC_RPT_S 24
#define AR_QUIET1 0x80fc
#define AR_QUIET1_NEXT_QUIET_S 0
@@ -1969,8 +1959,6 @@
#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000
#define AR_MAC_PCU_GEN_TIMER_TSF_SEL 0x83d8
-#define AR_DIRECT_CONNECT 0x83a0
-#define AR_DC_AP_STA_EN 0x00000001
#define AR_AES_MUTE_MASK0 0x805c
#define AR_AES_MUTE_MASK0_FC 0x0000FFFF
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/spectral.c
similarity index 74%
rename from drivers/net/wireless/ath/ath9k/common-spectral.c
rename to drivers/net/wireless/ath/ath9k/spectral.c
index 5253136..fad0c14 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/spectral.c
@@ -24,24 +24,23 @@
return (s8) rssi_val;
}
-static void ath_debug_send_fft_sample(struct ath_spec_scan_priv *spec_priv,
+static void ath_debug_send_fft_sample(struct ath_softc *sc,
struct fft_sample_tlv *fft_sample_tlv)
{
int length;
- if (!spec_priv->rfs_chan_spec_scan)
+ if (!sc->rfs_chan_spec_scan)
return;
length = __be16_to_cpu(fft_sample_tlv->length) +
sizeof(*fft_sample_tlv);
- relay_write(spec_priv->rfs_chan_spec_scan, fft_sample_tlv, length);
+ relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length);
}
/* returns 1 if this was a spectral frame, even if not handled. */
-int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr,
+int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
struct ath_rx_status *rs, u64 tsf)
{
- struct ath_hw *ah = spec_priv->ah;
- struct ath_common *common = ath9k_hw_common(spec_priv->ah);
+ struct ath_hw *ah = sc->sc_ah;
u8 num_bins, *bins, *vdata = (u8 *)hdr;
struct fft_sample_ht20 fft_sample_20;
struct fft_sample_ht20_40 fft_sample_40;
@@ -68,7 +67,7 @@
if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK))
return 0;
- chan_type = cfg80211_get_chandef_type(&common->hw->conf.chandef);
+ chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef);
if ((chan_type == NL80211_CHAN_HT40MINUS) ||
(chan_type == NL80211_CHAN_HT40PLUS)) {
fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN;
@@ -200,11 +199,10 @@
tlv = (struct fft_sample_tlv *)&fft_sample_20;
}
- ath_debug_send_fft_sample(spec_priv, tlv);
+ ath_debug_send_fft_sample(sc, tlv);
return 1;
}
-EXPORT_SYMBOL(ath_cmn_process_fft);
/*********************/
/* spectral_scan_ctl */
@@ -213,11 +211,11 @@
static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
+ struct ath_softc *sc = file->private_data;
char *mode = "";
unsigned int len;
- switch (spec_priv->spectral_mode) {
+ switch (sc->spectral_mode) {
case SPECTRAL_DISABLED:
mode = "disable";
break;
@@ -235,84 +233,12 @@
return simple_read_from_buffer(user_buf, count, ppos, mode, len);
}
-void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
- struct ath_spec_scan_priv *spec_priv)
-{
- struct ath_hw *ah = spec_priv->ah;
- u32 rxfilter;
-
- if (config_enabled(CPTCFG_ATH9K_TX99))
- return;
-
- if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
- ath_err(common, "spectrum analyzer not implemented on this hardware\n");
- return;
- }
-
- ath_ps_ops(common)->wakeup(common);
- rxfilter = ath9k_hw_getrxfilter(ah);
- ath9k_hw_setrxfilter(ah, rxfilter |
- ATH9K_RX_FILTER_PHYRADAR |
- ATH9K_RX_FILTER_PHYERR);
-
- /* TODO: usually this should not be neccesary, but for some reason
- * (or in some mode?) the trigger must be called after the
- * configuration, otherwise the register will have its values reset
- * (on my ar9220 to value 0x01002310)
- */
- ath9k_cmn_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode);
- ath9k_hw_ops(ah)->spectral_scan_trigger(ah);
- ath_ps_ops(common)->restore(common);
-}
-EXPORT_SYMBOL(ath9k_cmn_spectral_scan_trigger);
-
-int ath9k_cmn_spectral_scan_config(struct ath_common *common,
- struct ath_spec_scan_priv *spec_priv,
- enum spectral_mode spectral_mode)
-{
- struct ath_hw *ah = spec_priv->ah;
-
- if (!ath9k_hw_ops(ah)->spectral_scan_trigger) {
- ath_err(common, "spectrum analyzer not implemented on this hardware\n");
- return -1;
- }
-
- switch (spectral_mode) {
- case SPECTRAL_DISABLED:
- spec_priv->spec_config.enabled = 0;
- break;
- case SPECTRAL_BACKGROUND:
- /* send endless samples.
- * TODO: is this really useful for "background"?
- */
- spec_priv->spec_config.endless = 1;
- spec_priv->spec_config.enabled = 1;
- break;
- case SPECTRAL_CHANSCAN:
- case SPECTRAL_MANUAL:
- spec_priv->spec_config.endless = 0;
- spec_priv->spec_config.enabled = 1;
- break;
- default:
- return -1;
- }
-
- ath_ps_ops(common)->wakeup(common);
- ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config);
- ath_ps_ops(common)->restore(common);
-
- spec_priv->spectral_mode = spectral_mode;
-
- return 0;
-}
-EXPORT_SYMBOL(ath9k_cmn_spectral_scan_config);
-
static ssize_t write_file_spec_scan_ctl(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
- struct ath_common *common = ath9k_hw_common(spec_priv->ah);
+ struct ath_softc *sc = file->private_data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
char buf[32];
ssize_t len;
@@ -326,18 +252,18 @@
buf[len] = '\0';
if (strncmp("trigger", buf, 7) == 0) {
- ath9k_cmn_spectral_scan_trigger(common, spec_priv);
+ ath9k_spectral_scan_trigger(sc->hw);
} else if (strncmp("background", buf, 10) == 0) {
- ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_BACKGROUND);
+ ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND);
ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n");
} else if (strncmp("chanscan", buf, 8) == 0) {
- ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_CHANSCAN);
+ ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN);
ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n");
} else if (strncmp("manual", buf, 6) == 0) {
- ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_MANUAL);
+ ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL);
ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n");
} else if (strncmp("disable", buf, 7) == 0) {
- ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_DISABLED);
+ ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED);
ath_dbg(common, CONFIG, "spectral scan: disabled\n");
} else {
return -EINVAL;
@@ -362,11 +288,11 @@
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
+ struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
- len = sprintf(buf, "%d\n", spec_priv->spec_config.short_repeat);
+ len = sprintf(buf, "%d\n", sc->spec_config.short_repeat);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -374,7 +300,7 @@
const char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
+ struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
@@ -390,7 +316,7 @@
if (val > 1)
return -EINVAL;
- spec_priv->spec_config.short_repeat = val;
+ sc->spec_config.short_repeat = val;
return count;
}
@@ -410,11 +336,11 @@
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
+ struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
- len = sprintf(buf, "%d\n", spec_priv->spec_config.count);
+ len = sprintf(buf, "%d\n", sc->spec_config.count);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -422,7 +348,7 @@
const char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
+ struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
@@ -438,7 +364,7 @@
if (val > 255)
return -EINVAL;
- spec_priv->spec_config.count = val;
+ sc->spec_config.count = val;
return count;
}
@@ -458,11 +384,11 @@
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
+ struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
- len = sprintf(buf, "%d\n", spec_priv->spec_config.period);
+ len = sprintf(buf, "%d\n", sc->spec_config.period);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -470,7 +396,7 @@
const char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
+ struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
@@ -486,7 +412,7 @@
if (val > 255)
return -EINVAL;
- spec_priv->spec_config.period = val;
+ sc->spec_config.period = val;
return count;
}
@@ -506,11 +432,11 @@
char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
+ struct ath_softc *sc = file->private_data;
char buf[32];
unsigned int len;
- len = sprintf(buf, "%d\n", spec_priv->spec_config.fft_period);
+ len = sprintf(buf, "%d\n", sc->spec_config.fft_period);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -518,7 +444,7 @@
const char __user *user_buf,
size_t count, loff_t *ppos)
{
- struct ath_spec_scan_priv *spec_priv = file->private_data;
+ struct ath_softc *sc = file->private_data;
unsigned long val;
char buf[32];
ssize_t len;
@@ -534,7 +460,7 @@
if (val > 15)
return -EINVAL;
- spec_priv->spec_config.fft_period = val;
+ sc->spec_config.fft_period = val;
return count;
}
@@ -584,41 +510,38 @@
/* Debug Init/Deinit */
/*********************/
-void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv)
+void ath9k_spectral_deinit_debug(struct ath_softc *sc)
{
- if (config_enabled(CPTCFG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) {
- relay_close(spec_priv->rfs_chan_spec_scan);
- spec_priv->rfs_chan_spec_scan = NULL;
+ if (config_enabled(CPTCFG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
+ relay_close(sc->rfs_chan_spec_scan);
+ sc->rfs_chan_spec_scan = NULL;
}
}
-EXPORT_SYMBOL(ath9k_cmn_spectral_deinit_debug);
-void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv,
- struct dentry *debugfs_phy)
+void ath9k_spectral_init_debug(struct ath_softc *sc)
{
- spec_priv->rfs_chan_spec_scan = relay_open("spectral_scan",
- debugfs_phy,
+ sc->rfs_chan_spec_scan = relay_open("spectral_scan",
+ sc->debug.debugfs_phy,
1024, 256, &rfs_spec_scan_cb,
NULL);
debugfs_create_file("spectral_scan_ctl",
S_IRUSR | S_IWUSR,
- debugfs_phy, spec_priv,
+ sc->debug.debugfs_phy, sc,
&fops_spec_scan_ctl);
debugfs_create_file("spectral_short_repeat",
S_IRUSR | S_IWUSR,
- debugfs_phy, spec_priv,
+ sc->debug.debugfs_phy, sc,
&fops_spectral_short_repeat);
debugfs_create_file("spectral_count",
S_IRUSR | S_IWUSR,
- debugfs_phy, spec_priv,
+ sc->debug.debugfs_phy, sc,
&fops_spectral_count);
debugfs_create_file("spectral_period",
S_IRUSR | S_IWUSR,
- debugfs_phy, spec_priv,
+ sc->debug.debugfs_phy, sc,
&fops_spectral_period);
debugfs_create_file("spectral_fft_period",
S_IRUSR | S_IWUSR,
- debugfs_phy, spec_priv,
+ sc->debug.debugfs_phy, sc,
&fops_spectral_fft_period);
}
-EXPORT_SYMBOL(ath9k_cmn_spectral_init_debug);
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.h b/drivers/net/wireless/ath/ath9k/spectral.h
similarity index 84%
rename from drivers/net/wireless/ath/ath9k/common-spectral.h
rename to drivers/net/wireless/ath/ath9k/spectral.h
index 82d9dd2..0b9465e 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.h
+++ b/drivers/net/wireless/ath/ath9k/spectral.h
@@ -92,13 +92,6 @@
struct ath_radar_info radar_info;
} __packed;
-struct ath_spec_scan_priv {
- struct ath_hw *ah;
- /* relay(fs) channel for spectral scan */
- struct rchan *rfs_chan_spec_scan;
- enum spectral_mode spectral_mode;
- struct ath_spec_scan spec_config;
-};
#define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet))
@@ -130,15 +123,23 @@
return bins[0] & 0x3f;
}
-void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy);
-void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv);
+void ath9k_spectral_init_debug(struct ath_softc *sc);
+void ath9k_spectral_deinit_debug(struct ath_softc *sc);
-void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
- struct ath_spec_scan_priv *spec_priv);
-int ath9k_cmn_spectral_scan_config(struct ath_common *common,
- struct ath_spec_scan_priv *spec_priv,
+void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw);
+int ath9k_spectral_scan_config(struct ieee80211_hw *hw,
enum spectral_mode spectral_mode);
-int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr,
+
+#ifdef CPTCFG_ATH9K_DEBUGFS
+int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr,
struct ath_rx_status *rs, u64 tsf);
+#else
+static inline int ath_process_fft(struct ath_softc *sc,
+ struct ieee80211_hdr *hdr,
+ struct ath_rx_status *rs, u64 tsf)
+{
+ return 0;
+}
+#endif /* CPTCFG_ATH9K_DEBUGFS */
#endif /* SPECTRAL_H */
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c
index ac4781f..40ab65e 100644
--- a/drivers/net/wireless/ath/ath9k/tx99.c
+++ b/drivers/net/wireless/ath/ath9k/tx99.c
@@ -99,7 +99,7 @@
static void ath9k_tx99_deinit(struct ath_softc *sc)
{
- ath_reset(sc, NULL);
+ ath_reset(sc);
ath9k_ps_wakeup(sc);
ath9k_tx99_stop(sc);
@@ -127,7 +127,7 @@
memset(&txctl, 0, sizeof(txctl));
txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
- ath_reset(sc, NULL);
+ ath_reset(sc);
ath9k_ps_wakeup(sc);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 6bf7bc7..f00fbc9 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1096,37 +1096,6 @@
}
}
-static u8 ath_get_rate_txpower(struct ath_softc *sc, struct ath_buf *bf,
- u8 rateidx)
-{
- u8 max_power;
- struct ath_hw *ah = sc->sc_ah;
-
- if (sc->tx99_state)
- return MAX_RATE_POWER;
-
- if (!AR_SREV_9300_20_OR_LATER(ah)) {
- /* ar9002 is not sipported for the moment */
- return MAX_RATE_POWER;
- }
-
- if (!bf->bf_state.bfs_paprd) {
- struct sk_buff *skb = bf->bf_mpdu;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ath_frame_info *fi = get_frame_info(skb);
-
- if (rateidx < 8 && (info->flags & IEEE80211_TX_CTL_STBC))
- max_power = min(ah->tx_power_stbc[rateidx],
- fi->tx_power);
- else
- max_power = min(ah->tx_power[rateidx], fi->tx_power);
- } else {
- max_power = ah->paprd_training_power;
- }
-
- return max_power;
-}
-
static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ath_tx_info *info, int len, bool rts)
{
@@ -1197,8 +1166,6 @@
is_40, is_sgi, is_sp);
if (rix < 8 && (tx_info->flags & IEEE80211_TX_CTL_STBC))
info->rates[i].RateFlags |= ATH9K_RATESERIES_STBC;
-
- info->txpower[i] = ath_get_rate_txpower(sc, bf, rix);
continue;
}
@@ -1226,8 +1193,6 @@
info->rates[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
phy, rate->bitrate * 100, len, rix, is_sp);
-
- info->txpower[i] = ath_get_rate_txpower(sc, bf, rix);
}
/* For AR5416 - RTS cannot be followed by a frame larger than 8K */
@@ -1274,6 +1239,7 @@
memset(&info, 0, sizeof(info));
info.is_first = true;
info.is_last = true;
+ info.txpower = MAX_RATE_POWER;
info.qcu = txq->axq_qnum;
while (bf) {
@@ -2097,7 +2063,6 @@
fi->keyix = ATH9K_TXKEYIX_INVALID;
fi->keytype = keytype;
fi->framelen = framelen;
- fi->tx_power = MAX_RATE_POWER;
if (!rate)
return;
diff --git a/drivers/net/wireless/ath/carl9170/Kconfig b/drivers/net/wireless/ath/carl9170/Kconfig
index 2a510ba..a75b5c6 100644
--- a/drivers/net/wireless/ath/carl9170/Kconfig
+++ b/drivers/net/wireless/ath/carl9170/Kconfig
@@ -20,8 +20,8 @@
bool "SoftLED Support"
depends on CARL9170
select MAC80211_LEDS
- select BPAUTO_LEDS_CLASS
- select BPAUTO_NEW_LEDS
+ select BACKPORT_LEDS_CLASS
+ select BACKPORT_NEW_LEDS
default y
help
This option is necessary, if you want your device' LEDs to blink
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c
index dca6df1..b80b213 100644
--- a/drivers/net/wireless/ath/carl9170/phy.c
+++ b/drivers/net/wireless/ath/carl9170/phy.c
@@ -994,7 +994,7 @@
refsel0 = 0;
refsel1 = 1;
}
- chansel = bitrev8(chansel);
+ chansel = byte_rev_table[chansel];
} else {
if (freq == 2484) {
chansel = 10 + (freq - 2274) / 5;
@@ -1002,7 +1002,7 @@
} else
chansel = 16 + (freq - 2272) / 5;
chansel *= 4;
- chansel = bitrev8(chansel);
+ chansel = byte_rev_table[chansel];
}
d1 = chansel;
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c
index 0e383ef..7a16686 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -86,7 +86,7 @@
FCC_PATTERN(1, 0, 5, 150, 230, 1, 23),
FCC_PATTERN(2, 6, 10, 200, 500, 1, 16),
FCC_PATTERN(3, 11, 20, 200, 500, 1, 12),
- FCC_PATTERN(4, 50, 100, 1000, 2000, 1, 20),
+ FCC_PATTERN(4, 50, 100, 1000, 2000, 20, 1),
FCC_PATTERN(5, 0, 1, 333, 333, 1, 9),
};
@@ -105,7 +105,7 @@
JP_PATTERN(4, 0, 5, 150, 230, 1, 23),
JP_PATTERN(5, 6, 10, 200, 500, 1, 16),
JP_PATTERN(6, 11, 20, 200, 500, 1, 12),
- JP_PATTERN(7, 50, 100, 1000, 2000, 1, 20),
+ JP_PATTERN(7, 50, 100, 1000, 2000, 20, 1),
JP_PATTERN(5, 0, 1, 333, 333, 1, 9),
};
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c
index 0cd964f..6253db8 100644
--- a/drivers/net/wireless/ath/regd.c
+++ b/drivers/net/wireless/ath/regd.c
@@ -515,7 +515,6 @@
if (!request)
return;
- reg->region = request->dfs_region;
switch (request->initiator) {
case NL80211_REGDOM_SET_BY_CORE:
/*
@@ -780,19 +779,6 @@
return SD_NO_CTL;
}
- if (ath_regd_get_eepromRD(reg) == CTRY_DEFAULT) {
- switch (reg->region) {
- case NL80211_DFS_FCC:
- return CTL_FCC;
- case NL80211_DFS_ETSI:
- return CTL_ETSI;
- case NL80211_DFS_JP:
- return CTL_MKK;
- default:
- break;
- }
- }
-
switch (band) {
case IEEE80211_BAND_2GHZ:
return reg->regpair->reg_2ghz_ctl;
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 7dd8873..b71d2b3 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -494,9 +494,7 @@
return ret;
}
-static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw)
{
struct wcn36xx *wcn = hw->priv;
@@ -504,8 +502,7 @@
wcn36xx_smd_start_scan(wcn);
}
-static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw)
{
struct wcn36xx *wcn = hw->priv;
@@ -1078,6 +1075,7 @@
.remove = wcn36xx_remove,
.driver = {
.name = "wcn36xx",
+ .owner = THIS_MODULE,
},
.id_table = wcn36xx_platform_id_table,
};
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 38332a6..d9f4b30 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -792,13 +792,12 @@
}
static int wil_cfg80211_del_station(struct wiphy *wiphy,
- struct net_device *dev,
- struct station_del_parameters *params)
+ struct net_device *dev, const u8 *mac)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
mutex_lock(&wil->mutex);
- wil6210_disconnect(wil, params->mac, params->reason_code, false);
+ wil6210_disconnect(wil, mac);
mutex_unlock(&wil->mutex);
return 0;
diff --git a/drivers/net/wireless/ath/wil6210/debug.c b/drivers/net/wireless/ath/wil6210/debug.c
index 3249562..8d99021 100644
--- a/drivers/net/wireless/ath/wil6210/debug.c
+++ b/drivers/net/wireless/ath/wil6210/debug.c
@@ -32,23 +32,6 @@
va_end(args);
}
-void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...)
-{
- if (net_ratelimit()) {
- struct net_device *ndev = wil_to_ndev(wil);
- struct va_format vaf = {
- .fmt = fmt,
- };
- va_list args;
-
- va_start(args, fmt);
- vaf.va = &args;
- netdev_err(ndev, "%pV", &vaf);
- trace_wil6210_log_err(&vaf);
- va_end(args);
- }
-}
-
void wil_info(struct wil6210_priv *wil, const char *fmt, ...)
{
struct net_device *ndev = wil_to_ndev(wil);
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index 4e6e145..54a6ddc 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -573,10 +573,8 @@
if (!frame)
return -ENOMEM;
- if (copy_from_user(frame, buf, len)) {
- kfree(frame);
+ if (copy_from_user(frame, buf, len))
return -EIO;
- }
params.buf = frame;
params.len = len;
@@ -616,10 +614,8 @@
return -ENOMEM;
rc = simple_write_to_buffer(wmi, len, ppos, buf, len);
- if (rc < 0) {
- kfree(wmi);
+ if (rc < 0)
return rc;
- }
cmd = &wmi[1];
cmdid = le16_to_cpu(wmi->id);
diff --git a/drivers/net/wireless/ath/wil6210/fw.c b/drivers/net/wireless/ath/wil6210/fw.c
index 93c5cc1..8c6f3b0 100644
--- a/drivers/net/wireless/ath/wil6210/fw.c
+++ b/drivers/net/wireless/ath/wil6210/fw.c
@@ -15,6 +15,7 @@
*/
#include <linux/firmware.h>
#include <linux/module.h>
+#include <linux/pci.h>
#include <linux/crc32.h>
#include "wil6210.h"
#include "fw.h"
diff --git a/drivers/net/wireless/ath/wil6210/fw_inc.c b/drivers/net/wireless/ath/wil6210/fw_inc.c
index d4acf93..44cb71f 100644
--- a/drivers/net/wireless/ath/wil6210/fw_inc.c
+++ b/drivers/net/wireless/ath/wil6210/fw_inc.c
@@ -446,7 +446,7 @@
if (size >= sizeof(*hdr)) {
wil_err_fw(wil, "Stop at offset %ld"
" record type %d [%zd bytes]\n",
- (long)((const void *)hdr - data),
+ (const void *)hdr - data,
le16_to_cpu(hdr->type), hdr_sz);
}
return -EINVAL;
@@ -471,7 +471,7 @@
size_t sz;
const void *d;
- rc = request_firmware(&fw, name, wil_to_dev(wil));
+ rc = request_firmware(&fw, name, wil_to_pcie_dev(wil));
if (rc) {
wil_err_fw(wil, "Failed to load firmware %s\n", name);
return rc;
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
index 0b6ac97..b7a0f6f 100644
--- a/drivers/net/wireless/ath/wil6210/interrupt.c
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -36,8 +36,7 @@
*/
#define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL)
-#define WIL6210_IMC_RX (BIT_DMA_EP_RX_ICR_RX_DONE | \
- BIT_DMA_EP_RX_ICR_RX_HTRSH)
+#define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE
#define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \
BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
#define WIL6210_IMC_MISC (ISR_MISC_FW_READY | \
@@ -172,7 +171,6 @@
u32 isr = wil_ioread32_and_clear(wil->csr +
HOSTADDR(RGF_DMA_EP_RX_ICR) +
offsetof(struct RGF_ICR, ICR));
- bool need_unmask = true;
trace_wil6210_irq_rx(isr);
wil_dbg_irq(wil, "ISR RX 0x%08x\n", isr);
@@ -184,24 +182,12 @@
wil6210_mask_irq_rx(wil);
- /* RX_DONE and RX_HTRSH interrupts are the same if interrupt
- * moderation is not used. Interrupt moderation may cause RX
- * buffer overflow while RX_DONE is delayed. The required
- * action is always the same - should empty the accumulated
- * packets from the RX ring.
- */
- if (isr & (BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH)) {
+ if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) {
wil_dbg_irq(wil, "RX done\n");
-
- if (isr & BIT_DMA_EP_RX_ICR_RX_HTRSH)
- wil_err_ratelimited(wil, "Received \"Rx buffer is in risk "
- "of overflow\" interrupt\n");
-
- isr &= ~(BIT_DMA_EP_RX_ICR_RX_DONE | BIT_DMA_EP_RX_ICR_RX_HTRSH);
+ isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE;
if (test_bit(wil_status_reset_done, &wil->status)) {
if (test_bit(wil_status_napi_en, &wil->status)) {
wil_dbg_txrx(wil, "NAPI(Rx) schedule\n");
- need_unmask = false;
napi_schedule(&wil->napi_rx);
} else {
wil_err(wil, "Got Rx interrupt while "
@@ -218,10 +204,6 @@
/* Rx IRQ will be enabled when NAPI processing finished */
atomic_inc(&wil->isr_count_rx);
-
- if (unlikely(need_unmask))
- wil6210_unmask_irq_rx(wil);
-
return IRQ_HANDLED;
}
@@ -231,7 +213,6 @@
u32 isr = wil_ioread32_and_clear(wil->csr +
HOSTADDR(RGF_DMA_EP_TX_ICR) +
offsetof(struct RGF_ICR, ICR));
- bool need_unmask = true;
trace_wil6210_irq_tx(isr);
wil_dbg_irq(wil, "ISR TX 0x%08x\n", isr);
@@ -250,7 +231,6 @@
isr &= ~(BIT(25) - 1UL);
if (test_bit(wil_status_reset_done, &wil->status)) {
wil_dbg_txrx(wil, "NAPI(Tx) schedule\n");
- need_unmask = false;
napi_schedule(&wil->napi_tx);
} else {
wil_err(wil, "Got Tx interrupt while in reset\n");
@@ -263,10 +243,6 @@
/* Tx IRQ will be enabled when NAPI processing finished */
atomic_inc(&wil->isr_count_tx);
-
- if (unlikely(need_unmask))
- wil6210_unmask_irq_tx(wil);
-
return IRQ_HANDLED;
}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 8ff3fe3..6500caf 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -38,65 +38,6 @@
module_param(itr_trsh, uint, S_IRUGO);
MODULE_PARM_DESC(itr_trsh, " Interrupt moderation threshold, usecs.");
-/* We allow allocation of more than 1 page buffers to support large packets.
- * It is suboptimal behavior performance wise in case MTU above page size.
- */
-unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - ETH_HLEN;
-static int mtu_max_set(const char *val, const struct kernel_param *kp)
-{
- int ret;
-
- /* sets mtu_max directly. no need to restore it in case of
- * illegal value since we assume this will fail insmod
- */
- ret = param_set_uint(val, kp);
- if (ret)
- return ret;
-
- if (mtu_max < 68 || mtu_max > IEEE80211_MAX_DATA_LEN_DMG)
- ret = -EINVAL;
-
- return ret;
-}
-
-static struct kernel_param_ops mtu_max_ops = {
- .set = mtu_max_set,
- .get = param_get_uint,
-};
-
-module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO);
-MODULE_PARM_DESC(mtu_max, " Max MTU value.");
-
-static uint rx_ring_order = WIL_RX_RING_SIZE_ORDER_DEFAULT;
-static uint tx_ring_order = WIL_TX_RING_SIZE_ORDER_DEFAULT;
-
-static int ring_order_set(const char *val, const struct kernel_param *kp)
-{
- int ret;
- uint x;
-
- ret = kstrtouint(val, 0, &x);
- if (ret)
- return ret;
-
- if ((x < WIL_RING_SIZE_ORDER_MIN) || (x > WIL_RING_SIZE_ORDER_MAX))
- return -EINVAL;
-
- *((uint *)kp->arg) = x;
-
- return 0;
-}
-
-static struct kernel_param_ops ring_order_ops = {
- .set = ring_order_set,
- .get = param_get_uint,
-};
-
-module_param_cb(rx_ring_order, &ring_order_ops, &rx_ring_order, S_IRUGO);
-MODULE_PARM_DESC(rx_ring_order, " Rx ring order; size = 1 << order");
-module_param_cb(tx_ring_order, &ring_order_ops, &tx_ring_order, S_IRUGO);
-MODULE_PARM_DESC(tx_ring_order, " Tx ring order; size = 1 << order");
-
#define RST_DELAY (20) /* msec, for loop in @wil_target_reset */
#define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */
@@ -133,8 +74,7 @@
__raw_writel(*s++, d++);
}
-static void wil_disconnect_cid(struct wil6210_priv *wil, int cid,
- u16 reason_code, bool from_event)
+static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
{
uint i;
struct net_device *ndev = wil_to_ndev(wil);
@@ -146,9 +86,7 @@
sta->data_port_open = false;
if (sta->status != wil_sta_unused) {
- if (!from_event)
- wmi_disconnect_sta(wil, sta->addr, reason_code);
-
+ wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING);
switch (wdev->iftype) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
@@ -180,8 +118,7 @@
memset(&sta->stats, 0, sizeof(sta->stats));
}
-static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
- u16 reason_code, bool from_event)
+static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
{
int cid = -ENOENT;
struct net_device *ndev = wil_to_ndev(wil);
@@ -196,10 +133,10 @@
}
if (cid >= 0) /* disconnect 1 peer */
- wil_disconnect_cid(wil, cid, reason_code, from_event);
+ wil_disconnect_cid(wil, cid);
else /* disconnect all */
for (cid = 0; cid < WIL6210_MAX_CID; cid++)
- wil_disconnect_cid(wil, cid, reason_code, from_event);
+ wil_disconnect_cid(wil, cid);
/* link state */
switch (wdev->iftype) {
@@ -208,7 +145,8 @@
wil_link_off(wil);
if (test_bit(wil_status_fwconnected, &wil->status)) {
clear_bit(wil_status_fwconnected, &wil->status);
- cfg80211_disconnected(ndev, reason_code,
+ cfg80211_disconnected(ndev,
+ WLAN_STATUS_UNSPECIFIED_FAILURE,
NULL, 0, GFP_KERNEL);
} else if (test_bit(wil_status_fwconnecting, &wil->status)) {
cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
@@ -228,7 +166,7 @@
struct wil6210_priv, disconnect_worker);
mutex_lock(&wil->mutex);
- _wil6210_disconnect(wil, NULL, WLAN_REASON_UNSPECIFIED, false);
+ _wil6210_disconnect(wil, NULL);
mutex_unlock(&wil->mutex);
}
@@ -250,7 +188,6 @@
clear_bit(wil_status_fwready, &wil->status);
wil_err(wil, "Scan timeout detected, start fw error recovery\n");
- wil->recovery_state = fw_recovery_pending;
schedule_work(&wil->fw_error_worker);
}
@@ -286,11 +223,6 @@
wil_dbg_misc(wil, "fw error worker\n");
- if (!netif_running(wil_to_ndev(wil))) {
- wil_info(wil, "No recovery - interface is down\n");
- return;
- }
-
/* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO
* passed since last recovery attempt
*/
@@ -325,12 +257,9 @@
break;
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
- wil_info(wil, "No recovery for AP-like interface\n");
/* recovery in these modes is done by upper layers */
break;
default:
- wil_err(wil, "No recovery - unknown interface type %d\n",
- wdev->iftype);
break;
}
mutex_unlock(&wil->mutex);
@@ -362,7 +291,7 @@
wil_dbg_wmi(wil, "Configure for connection CID %d\n", cid);
- rc = wil_vring_init_tx(wil, ringid, 1 << tx_ring_order, cid, 0);
+ rc = wil_vring_init_tx(wil, ringid, WIL6210_TX_RING_SIZE, cid, 0);
wil->pending_connect_cid = -1;
if (rc == 0) {
wil->sta[cid].status = wil_sta_connected;
@@ -417,23 +346,12 @@
return 0;
}
-/**
- * wil6210_disconnect - disconnect one connection
- * @wil: driver context
- * @bssid: peer to disconnect, NULL to disconnect all
- * @reason_code: Reason code for the Disassociation frame
- * @from_event: whether is invoked from FW event handler
- *
- * Disconnect and release associated resources. If invoked not from the
- * FW event handler, issue WMI command(s) to trigger MAC disconnect.
- */
-void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
- u16 reason_code, bool from_event)
+void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
{
wil_dbg_misc(wil, "%s()\n", __func__);
del_timer_sync(&wil->connect_timer);
- _wil6210_disconnect(wil, bssid, reason_code, from_event);
+ _wil6210_disconnect(wil, bssid);
}
void wil_priv_deinit(struct wil6210_priv *wil)
@@ -445,7 +363,7 @@
cancel_work_sync(&wil->disconnect_worker);
cancel_work_sync(&wil->fw_error_worker);
mutex_lock(&wil->mutex);
- wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
+ wil6210_disconnect(wil, NULL);
mutex_unlock(&wil->mutex);
wmi_event_flush(wil);
destroy_workqueue(wil->wmi_wq_conn);
@@ -477,7 +395,7 @@
static int wil_target_reset(struct wil6210_priv *wil)
{
int delay = 0;
- u32 x;
+ u32 hw_state;
u32 rev_id;
bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW);
@@ -492,25 +410,9 @@
S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST);
wil_halt_cpu(wil);
-
- /* Clear Fw Download notification */
- C(RGF_USER_USAGE_6, BIT(0));
+ C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL); /* 40 MHz */
if (is_sparrow) {
- S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN);
- /* XTAL stabilization should take about 3ms */
- usleep_range(5000, 7000);
- x = R(RGF_CAF_PLL_LOCK_STATUS);
- if (!(x & BIT_CAF_OSC_DIG_XTAL_STABLE)) {
- wil_err(wil, "Xtal stabilization timeout\n"
- "RGF_CAF_PLL_LOCK_STATUS = 0x%08x\n", x);
- return -ETIME;
- }
- /* switch 10k to XTAL*/
- C(RGF_USER_SPARROW_M_4, BIT_SPARROW_M_4_SEL_SLEEP_OR_REF);
- /* 40 MHz */
- C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL);
-
W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f);
W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf);
}
@@ -551,13 +453,13 @@
/* wait until device ready. typical time is 200..250 msec */
do {
msleep(RST_DELAY);
- x = R(RGF_USER_HW_MACHINE_STATE);
+ hw_state = R(RGF_USER_HW_MACHINE_STATE);
if (delay++ > RST_COUNT) {
wil_err(wil, "Reset not completed, hw_state 0x%08x\n",
- x);
+ hw_state);
return -ETIME;
}
- } while (x != HW_MACHINE_BOOT_DONE);
+ } while (hw_state != HW_MACHINE_BOOT_DONE);
/* TODO: Erez check rev_id != 1 */
if (!is_sparrow && (rev_id != 1))
@@ -633,7 +535,7 @@
WARN_ON(test_bit(wil_status_napi_en, &wil->status));
cancel_work_sync(&wil->disconnect_worker);
- wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false);
+ wil6210_disconnect(wil, NULL);
wil->status = 0; /* prevent NAPI from being scheduled */
@@ -738,7 +640,7 @@
return rc;
/* Rx VRING. After MAC and beacon */
- rc = wil_rx_init(wil, 1 << rx_ring_order);
+ rc = wil_rx_init(wil);
if (rc)
return rc;
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index e81703c..2399651 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -41,7 +41,7 @@
{
struct wil6210_priv *wil = ndev_to_wil(ndev);
- if (new_mtu < 68 || new_mtu > mtu_max) {
+ if (new_mtu < 68 || new_mtu > (TX_BUF_LEN - ETH_HLEN)) {
wil_err(wil, "invalid MTU %d\n", new_mtu);
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index e3f8bdc..2936ef0 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -206,10 +206,12 @@
u32 i, int headroom)
{
struct device *dev = wil_to_dev(wil);
- unsigned int sz = mtu_max + ETH_HLEN;
+ unsigned int sz = RX_BUF_LEN;
struct vring_rx_desc dd, *d = ⅆ
volatile struct vring_rx_desc *_d = &vring->va[i].rx;
dma_addr_t pa;
+
+ /* TODO align */
struct sk_buff *skb = dev_alloc_skb(sz + headroom);
if (unlikely(!skb))
@@ -383,7 +385,7 @@
struct vring_rx_desc *d;
struct sk_buff *skb;
dma_addr_t pa;
- unsigned int sz = mtu_max + ETH_HLEN;
+ unsigned int sz = RX_BUF_LEN;
u16 dmalen;
u8 ftype;
u8 ds_bits;
@@ -594,7 +596,7 @@
wil_rx_refill(wil, v->size);
}
-int wil_rx_init(struct wil6210_priv *wil, u16 size)
+int wil_rx_init(struct wil6210_priv *wil)
{
struct vring *vring = &wil->vring_rx;
int rc;
@@ -606,7 +608,7 @@
return -EINVAL;
}
- vring->size = size;
+ vring->size = WIL6210_RX_RING_SIZE;
rc = wil_vring_alloc(wil, vring);
if (rc)
return rc;
@@ -644,8 +646,7 @@
.action = cpu_to_le32(WMI_VRING_CMD_ADD),
.vring_cfg = {
.tx_sw_ring = {
- .max_mpdu_size =
- cpu_to_le16(mtu_max + ETH_HLEN),
+ .max_mpdu_size = cpu_to_le16(TX_BUF_LEN),
.ring_size = cpu_to_le16(size),
},
.ringid = id,
@@ -926,9 +927,8 @@
wil_dbg_txrx(wil, "%s()\n", __func__);
if (avail < 1 + nr_frags) {
- wil_err_ratelimited(wil,
- "Tx ring full. No space for %d fragments\n",
- 1 + nr_frags);
+ wil_err(wil, "Tx ring full. No space for %d fragments\n",
+ 1 + nr_frags);
return -ENOMEM;
}
_d = &vring->va[i].tx;
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
index 630aeb5..de04671 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.h
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -21,8 +21,8 @@
#define BUF_HW_OWNED (0)
/* size of max. Tx/Rx buffers, as supported by FW */
-#define TXRX_BUF_LEN_DEFAULT (2242)
-
+#define RX_BUF_LEN (2242)
+#define TX_BUF_LEN (2242)
/* how many bytes to reserve for rtap header? */
#define WIL6210_RTAP_SIZE (128)
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index c6ec5b9..ce6488e 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -24,7 +24,6 @@
#include "wil_platform.h"
extern bool no_fw_recovery;
-extern unsigned int mtu_max;
#define WIL_NAME "wil6210"
#define WIL_FW_NAME "wil6210.fw"
@@ -49,11 +48,8 @@
#define WIL6210_MEM_SIZE (2*1024*1024UL)
-#define WIL_RX_RING_SIZE_ORDER_DEFAULT (9)
-#define WIL_TX_RING_SIZE_ORDER_DEFAULT (9)
-/* limit ring size in range [32..32k] */
-#define WIL_RING_SIZE_ORDER_MIN (5)
-#define WIL_RING_SIZE_ORDER_MAX (15)
+#define WIL6210_RX_RING_SIZE (128)
+#define WIL6210_TX_RING_SIZE (512)
#define WIL6210_MAX_TX_RINGS (24) /* HW limit */
#define WIL6210_MAX_CID (8) /* HW limit */
#define WIL6210_NAPI_BUDGET (16) /* arbitrary */
@@ -121,15 +117,12 @@
#define BIT_USER_USER_ICR_SW_INT_2 BIT(18)
#define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0 (0x880c18)
#define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1 (0x880c2c)
-#define RGF_USER_SPARROW_M_4 (0x880c50) /* Sparrow */
- #define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF BIT(2)
#define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */
#define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0)
#define BIT_DMA_EP_TX_ICR_TX_DONE_N(n) BIT(n+1) /* n = [0..23] */
#define RGF_DMA_EP_RX_ICR (0x881bd0) /* struct RGF_ICR */
#define BIT_DMA_EP_RX_ICR_RX_DONE BIT(0)
- #define BIT_DMA_EP_RX_ICR_RX_HTRSH BIT(1)
#define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */
#define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0)
#define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1)
@@ -159,10 +152,6 @@
#define RGF_MAC_MTRL_COUNTER_0 (0x886aa8)
#define RGF_CAF_ICR (0x88946c) /* struct RGF_ICR */
-#define RGF_CAF_OSC_CONTROL (0x88afa4)
- #define BIT_CAF_OSC_XTAL_EN BIT(0)
-#define RGF_CAF_PLL_LOCK_STATUS (0x88afec)
- #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0)
/* popular locations */
#define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD)
@@ -472,14 +461,10 @@
#define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w))
#define wil_to_ndev(i) (wil_to_wdev(i)->netdev)
#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
+#define wil_to_pcie_dev(i) (&i->pdev->dev)
-__printf(2, 3)
void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...);
-__printf(2, 3)
void wil_err(struct wil6210_priv *wil, const char *fmt, ...);
-__printf(2, 3)
-void wil_err_ratelimited(struct wil6210_priv *wil, const char *fmt, ...);
-__printf(2, 3)
void wil_info(struct wil6210_priv *wil, const char *fmt, ...);
#define wil_dbg(wil, fmt, arg...) do { \
netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \
@@ -590,10 +575,9 @@
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
int wmi_pcp_stop(struct wil6210_priv *wil);
-void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid,
- u16 reason_code, bool from_event);
+void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid);
-int wil_rx_init(struct wil6210_priv *wil, u16 size);
+int wil_rx_init(struct wil6210_priv *wil);
void wil_rx_fini(struct wil6210_priv *wil);
/* TX API */
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index 63476c8..4311df9 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -478,15 +478,15 @@
void *d, int len)
{
struct wmi_disconnect_event *evt = d;
- u16 reason_code = le16_to_cpu(evt->protocol_reason_status);
- wil_dbg_wmi(wil, "Disconnect %pM reason [proto %d wmi %d]\n",
- evt->bssid, reason_code, evt->disconnect_reason);
+ wil_dbg_wmi(wil, "Disconnect %pM reason %d proto %d wmi\n",
+ evt->bssid,
+ evt->protocol_reason_status, evt->disconnect_reason);
wil->sinfo_gen++;
mutex_lock(&wil->mutex);
- wil6210_disconnect(wil, evt->bssid, reason_code, true);
+ wil6210_disconnect(wil, evt->bssid);
mutex_unlock(&wil->mutex);
}
@@ -1025,7 +1025,7 @@
struct wmi_cfg_rx_chain_cmd cmd = {
.action = WMI_RX_CHAIN_ADD,
.rx_sw_ring = {
- .max_mpdu_size = cpu_to_le16(mtu_max + ETH_HLEN),
+ .max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
.ring_mem_base = cpu_to_le64(vring->pa),
.ring_size = cpu_to_le16(vring->size),
},
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 809f01c..d726f6c 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -5110,9 +5110,7 @@
B43_WARN_ON(!vif || wl->vif != vif);
}
-static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
@@ -5126,8 +5124,7 @@
mutex_unlock(&wl->mutex);
}
-static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw)
{
struct b43_wl *wl = hw_to_b43_wl(hw);
struct b43_wldev *dev;
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 9e59f8b..94da49c 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -300,7 +300,9 @@
void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg)
{
- b43_phy_write(dev, destreg, b43_phy_read(dev, srcreg));
+ assert_mac_suspended(dev);
+ dev->phy.ops->phy_write(dev, destreg,
+ dev->phy.ops->phy_read(dev, srcreg));
}
void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask)
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index a2f096f..0443fa7 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -12,7 +12,7 @@
select LEDS_CLASS if BCMA_DRIVER_GPIO
select BRCMUTIL
depends on FW_LOADER
- select BPAUTO_CORDIC
+ select BACKPORT_CORDIC
---help---
This module adds support for PCIe wireless adapters based on Broadcom
IEEE802.11n SoftMAC chipsets. It also has WLAN led support, which will
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index d496643..3d168e8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -23,15 +23,15 @@
obj-$(CPTCFG_BRCMFMAC) += brcmfmac.o
brcmfmac-objs += \
- cfg80211.o \
+ wl_cfg80211.o \
chip.o \
fwil.o \
fweh.o \
fwsignal.o \
p2p.o \
proto.o \
- common.o \
- core.o \
+ dhd_common.o \
+ dhd_linux.o \
firmware.o \
feature.o \
btcoex.o \
@@ -43,14 +43,14 @@
flowring.o \
msgbuf.o
brcmfmac-$(CPTCFG_BRCMFMAC_SDIO) += \
- sdio.o \
+ dhd_sdio.o \
bcmsdh.o
brcmfmac-$(CPTCFG_BRCMFMAC_USB) += \
usb.o
brcmfmac-$(CPTCFG_BRCMFMAC_PCIE) += \
pcie.o
brcmfmac-$(CPTCFG_BRCMDBG) += \
- debug.o
+ dhd_dbg.o
brcmfmac-$(CPTCFG_BRCM_TRACING) += \
tracepoint.o
brcmfmac-$(CONFIG_OF) += \
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
index 8e0e91c..a159ff3 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c
@@ -25,10 +25,10 @@
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
-#include "core.h"
-#include "bus.h"
+#include "dhd.h"
+#include "dhd_bus.h"
#include "fwsignal.h"
-#include "debug.h"
+#include "dhd_dbg.h"
#include "tracepoint.h"
#include "proto.h"
#include "bcdc.h"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
index 3c06e93..8dbd5db 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c
@@ -41,9 +41,9 @@
#include <chipcommon.h>
#include <soc.h>
#include "chip.h"
-#include "bus.h"
-#include "debug.h"
-#include "sdio.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+#include "sdio_host.h"
#include "of.h"
#define SDIOH_API_ACCESS_RETRY_LIMIT 2
@@ -1064,16 +1064,6 @@
if (!sdiodev->pdata)
brcmf_of_probe(sdiodev);
-#ifdef CONFIG_PM_SLEEP
- /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ
- * is true or when platform data OOB irq is true).
- */
- if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) &&
- ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) ||
- (sdiodev->pdata->oob_irq_supported)))
- bus_if->wowl_supported = true;
-#endif
-
atomic_set(&sdiodev->suspend, false);
init_waitqueue_head(&sdiodev->request_word_wait);
init_waitqueue_head(&sdiodev->request_buffer_wait);
@@ -1126,39 +1116,34 @@
brcmf_dbg(SDIO, "Exit\n");
}
-void brcmf_sdio_wowl_config(struct device *dev, bool enabled)
-{
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
-
- brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled);
- sdiodev->wowl_enabled = enabled;
-}
-
#ifdef CONFIG_PM_SLEEP
static int brcmf_ops_sdio_suspend(struct device *dev)
{
+ mmc_pm_flag_t sdio_flags;
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- mmc_pm_flag_t sdio_flags;
+ int ret = 0;
brcmf_dbg(SDIO, "Enter\n");
+ sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]);
+ if (!(sdio_flags & MMC_PM_KEEP_POWER)) {
+ brcmf_err("Host can't keep power while suspended\n");
+ return -EINVAL;
+ }
+
atomic_set(&sdiodev->suspend, true);
- if (sdiodev->wowl_enabled) {
- sdio_flags = MMC_PM_KEEP_POWER;
- if (sdiodev->pdata->oob_irq_supported)
- enable_irq_wake(sdiodev->pdata->oob_irq_nr);
- else
- sdio_flags = MMC_PM_WAKE_SDIO_IRQ;
- if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags))
- brcmf_err("Failed to set pm_flags %x\n", sdio_flags);
+ ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER);
+ if (ret) {
+ brcmf_err("Failed to set pm_flags\n");
+ atomic_set(&sdiodev->suspend, false);
+ return ret;
}
brcmf_sdio_wd_timer(sdiodev->bus, 0);
- return 0;
+ return ret;
}
static int brcmf_ops_sdio_resume(struct device *dev)
@@ -1167,8 +1152,6 @@
struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
brcmf_dbg(SDIO, "Enter\n");
- if (sdiodev->pdata->oob_irq_supported)
- disable_irq_wake(sdiodev->pdata->oob_irq_nr);
brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS);
atomic_set(&sdiodev->suspend, false);
return 0;
@@ -1221,6 +1204,7 @@
.remove = brcmf_sdio_pd_remove,
.driver = {
.name = BRCMFMAC_SDIO_PDATA_NAME,
+ .owner = THIS_MODULE,
}
};
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
index 0445163..a29ac49 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c
@@ -20,13 +20,13 @@
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include <defs.h>
-#include "core.h"
-#include "debug.h"
+#include <dhd.h>
+#include <dhd_dbg.h>
#include "fwil.h"
#include "fwil_types.h"
#include "btcoex.h"
#include "p2p.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
/* T1 start SCO/eSCO priority suppression */
#define BRCMF_BTCOEX_OPPR_WIN_TIME 2000
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
index ddae0b5..95efde8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
@@ -25,7 +25,7 @@
#include <brcm_hw_ids.h>
#include <brcmu_utils.h>
#include <chipcommon.h>
-#include "debug.h"
+#include "dhd_dbg.h"
#include "chip.h"
/* SOC Interconnect types (aka chip types) */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.c b/drivers/net/wireless/brcm80211/brcmfmac/common.c
deleted file mode 100644
index ed8356d..0000000
--- a/drivers/net/wireless/brcm80211/brcmfmac/common.c
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * 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 <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/netdevice.h>
-#include <brcmu_wifi.h>
-#include <brcmu_utils.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
-#include "fwil.h"
-#include "fwil_types.h"
-#include "tracepoint.h"
-
-#define BRCMF_DEFAULT_BCN_TIMEOUT 3
-#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
-#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
-
-/* boost value for RSSI_DELTA in preferred join selection */
-#define BRCMF_JOIN_PREF_RSSI_BOOST 8
-
-int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
-{
- s8 eventmask[BRCMF_EVENTING_MASK_LEN];
- u8 buf[BRCMF_DCMD_SMLEN];
- struct brcmf_join_pref_params join_pref_params[2];
- char *ptr;
- s32 err;
-
- /* retreive mac address */
- err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
- sizeof(ifp->mac_addr));
- if (err < 0) {
- brcmf_err("Retreiving cur_etheraddr failed, %d\n",
- err);
- goto done;
- }
- memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
-
- /* query for 'ver' to get version info from firmware */
- memset(buf, 0, sizeof(buf));
- strcpy(buf, "ver");
- err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
- if (err < 0) {
- brcmf_err("Retreiving version information failed, %d\n",
- err);
- goto done;
- }
- ptr = (char *)buf;
- strsep(&ptr, "\n");
-
- /* Print fw version info */
- brcmf_err("Firmware version = %s\n", buf);
-
- /* locate firmware version number for ethtool */
- ptr = strrchr(buf, ' ') + 1;
- strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
-
- /* set mpc */
- err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
- if (err) {
- brcmf_err("failed setting mpc\n");
- goto done;
- }
-
- /*
- * Setup timeout if Beacons are lost and roam is off to report
- * link down
- */
- err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
- BRCMF_DEFAULT_BCN_TIMEOUT);
- if (err) {
- brcmf_err("bcn_timeout error (%d)\n", err);
- goto done;
- }
-
- /* Enable/Disable build-in roaming to allowed ext supplicant to take
- * of romaing
- */
- err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
- if (err) {
- brcmf_err("roam_off error (%d)\n", err);
- goto done;
- }
-
- /* Setup join_pref to select target by RSSI(with boost on 5GHz) */
- join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
- join_pref_params[0].len = 2;
- join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
- join_pref_params[0].band = WLC_BAND_5G;
- join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
- join_pref_params[1].len = 2;
- join_pref_params[1].rssi_gain = 0;
- join_pref_params[1].band = 0;
- err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
- sizeof(join_pref_params));
- if (err)
- brcmf_err("Set join_pref error (%d)\n", err);
-
- /* Setup event_msgs, enable E_IF */
- err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
- BRCMF_EVENTING_MASK_LEN);
- if (err) {
- brcmf_err("Get event_msgs error (%d)\n", err);
- goto done;
- }
- setbit(eventmask, BRCMF_E_IF);
- err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
- BRCMF_EVENTING_MASK_LEN);
- if (err) {
- brcmf_err("Set event_msgs error (%d)\n", err);
- goto done;
- }
-
- /* Setup default scan channel time */
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
- BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
- if (err) {
- brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
- err);
- goto done;
- }
-
- /* Setup default scan unassoc time */
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
- BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
- if (err) {
- brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
- err);
- goto done;
- }
-
- /* do bus specific preinit here */
- err = brcmf_bus_preinit(ifp->drvr->bus_if);
-done:
- return err;
-}
-
-#if defined(CPTCFG_BRCM_TRACING) || defined(CPTCFG_BRCMDBG)
-void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
-{
- struct va_format vaf = {
- .fmt = fmt,
- };
- va_list args;
-
- va_start(args, fmt);
- vaf.va = &args;
- if (brcmf_msg_level & level)
- pr_debug("%s %pV", func, &vaf);
- trace_brcmf_dbg(level, func, &vaf);
- va_end(args);
-}
-#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
index 77656c7..c6d65b8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c
@@ -19,7 +19,7 @@
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
-#include "core.h"
+#include "dhd.h"
#include "commonring.h"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
similarity index 96%
rename from drivers/net/wireless/brcm80211/brcmfmac/core.h
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 23f74b1..5e4317d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -18,8 +18,8 @@
* Common types *
*/
-#ifndef BRCMFMAC_CORE_H
-#define BRCMFMAC_CORE_H
+#ifndef _BRCMF_H_
+#define _BRCMF_H_
#include "fweh.h"
@@ -83,6 +83,7 @@
/* Internal brcmf items */
uint hdrlen; /* Total BRCMF header length (proto + bus) */
uint rxsz; /* Rx buffer size bus module should use */
+ u8 wme_dp; /* wme discard priority */
/* Dongle media info */
char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN];
@@ -175,8 +176,7 @@
int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked);
struct brcmf_if *brcmf_add_if(struct brcmf_pub *drvr, s32 bssidx, s32 ifidx,
char *name, u8 *mac_addr);
-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx);
-int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr);
+void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
@@ -186,4 +186,4 @@
/* Sets dongle media info (drv_version, mac address). */
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp);
-#endif /* BRCMFMAC_CORE_H */
+#endif /* _BRCMF_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
similarity index 98%
rename from drivers/net/wireless/brcm80211/brcmfmac/bus.h
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index ba6eb69..027ff83 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -14,10 +14,10 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef BRCMFMAC_BUS_H
-#define BRCMFMAC_BUS_H
+#ifndef _BRCMF_BUS_H_
+#define _BRCMF_BUS_H_
-#include "debug.h"
+#include "dhd_dbg.h"
/* IDs of the 6 default common rings of msgbuf protocol */
#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0
@@ -227,7 +227,8 @@
void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success);
int brcmf_bus_start(struct device *dev);
-s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len);
+s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data,
+ u32 len);
void brcmf_bus_add_txhdrlen(struct device *dev, uint len);
#ifdef CPTCFG_BRCMFMAC_SDIO
@@ -240,4 +241,4 @@
void brcmf_usb_register(void);
#endif
-#endif /* BRCMFMAC_BUS_H */
+#endif /* _BRCMF_BUS_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
new file mode 100644
index 0000000..67503e2
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -0,0 +1,400 @@
+/*
+ * 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 <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/netdevice.h>
+#include <brcmu_wifi.h>
+#include <brcmu_utils.h>
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
+#include "fwil.h"
+#include "fwil_types.h"
+#include "tracepoint.h"
+
+#define PKTFILTER_BUF_SIZE 128
+#define BRCMF_DEFAULT_BCN_TIMEOUT 3
+#define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40
+#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
+#define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00"
+
+/* boost value for RSSI_DELTA in preferred join selection */
+#define BRCMF_JOIN_PREF_RSSI_BOOST 8
+
+
+bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
+ struct sk_buff *pkt, int prec)
+{
+ struct sk_buff *p;
+ int eprec = -1; /* precedence to evict from */
+ bool discard_oldest;
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_pub *drvr = bus_if->drvr;
+
+ /* 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_err("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_err("brcmu_pktq_penq() failed\n");
+
+ return p != NULL;
+}
+
+/* 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_err("Mask invalid format. Needs to start with 0x\n");
+ return -EINVAL;
+ }
+ src = src + 2; /* Skip past 0x */
+ if (strlen(src) % 2 != 0) {
+ brcmf_err("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;
+}
+
+static void
+brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable,
+ int master_mode)
+{
+ unsigned long res;
+ char *argv;
+ char *arg_save = NULL, *arg_org = NULL;
+ s32 err;
+ struct brcmf_pkt_filter_enable_le enable_parm;
+
+ arg_save = kstrdup(arg, GFP_ATOMIC);
+ if (!arg_save)
+ goto fail;
+
+ arg_org = arg_save;
+
+ argv = strsep(&arg_save, " ");
+
+ if (argv == NULL) {
+ brcmf_err("No args provided\n");
+ goto fail;
+ }
+
+ /* Parse packet filter id. */
+ enable_parm.id = 0;
+ if (!kstrtoul(argv, 0, &res))
+ enable_parm.id = cpu_to_le32((u32)res);
+
+ /* Enable/disable the specified filter. */
+ enable_parm.enable = cpu_to_le32(enable);
+
+ err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm,
+ sizeof(enable_parm));
+ if (err)
+ brcmf_err("Set pkt_filter_enable error (%d)\n", err);
+
+ /* Control the master mode */
+ err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode);
+ if (err)
+ brcmf_err("Set pkt_filter_mode error (%d)\n", err);
+
+fail:
+ kfree(arg_org);
+}
+
+static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg)
+{
+ struct brcmf_pkt_filter_le *pkt_filter;
+ unsigned long res;
+ int buf_len;
+ s32 err;
+ 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]) {
+ i++;
+ if (i >= 8) {
+ brcmf_err("Too many parameters\n");
+ goto fail;
+ }
+ argv[i] = strsep(&arg_save, " ");
+ }
+
+ if (i != 6) {
+ brcmf_err("Not enough args provided %d\n", i);
+ goto fail;
+ }
+
+ pkt_filter = (struct brcmf_pkt_filter_le *)buf;
+
+ /* Parse packet filter id. */
+ pkt_filter->id = 0;
+ if (!kstrtoul(argv[0], 0, &res))
+ pkt_filter->id = cpu_to_le32((u32)res);
+
+ /* Parse filter polarity. */
+ pkt_filter->negate_match = 0;
+ if (!kstrtoul(argv[1], 0, &res))
+ pkt_filter->negate_match = cpu_to_le32((u32)res);
+
+ /* Parse filter type. */
+ pkt_filter->type = 0;
+ if (!kstrtoul(argv[2], 0, &res))
+ pkt_filter->type = cpu_to_le32((u32)res);
+
+ /* Parse pattern filter offset. */
+ pkt_filter->u.pattern.offset = 0;
+ if (!kstrtoul(argv[3], 0, &res))
+ pkt_filter->u.pattern.offset = cpu_to_le32((u32)res);
+
+ /* Parse pattern filter mask. */
+ mask_size = brcmf_c_pattern_atoh(argv[4],
+ (char *)pkt_filter->u.pattern.mask_and_pattern);
+
+ /* Parse pattern filter pattern. */
+ pattern_size = brcmf_c_pattern_atoh(argv[5],
+ (char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]);
+
+ if (mask_size != pattern_size) {
+ brcmf_err("Mask and pattern not the same size\n");
+ goto fail;
+ }
+
+ pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size);
+ buf_len = offsetof(struct brcmf_pkt_filter_le,
+ u.pattern.mask_and_pattern);
+ buf_len += mask_size + pattern_size;
+
+ err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter,
+ buf_len);
+ if (err)
+ brcmf_err("Set pkt_filter_add error (%d)\n", err);
+
+fail:
+ kfree(arg_org);
+
+ kfree(buf);
+}
+
+int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
+{
+ s8 eventmask[BRCMF_EVENTING_MASK_LEN];
+ u8 buf[BRCMF_DCMD_SMLEN];
+ struct brcmf_join_pref_params join_pref_params[2];
+ char *ptr;
+ s32 err;
+
+ /* retreive mac address */
+ err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr,
+ sizeof(ifp->mac_addr));
+ if (err < 0) {
+ brcmf_err("Retreiving cur_etheraddr failed, %d\n",
+ err);
+ goto done;
+ }
+ memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac));
+
+ /* query for 'ver' to get version info from firmware */
+ memset(buf, 0, sizeof(buf));
+ strcpy(buf, "ver");
+ err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf));
+ if (err < 0) {
+ brcmf_err("Retreiving version information failed, %d\n",
+ err);
+ goto done;
+ }
+ ptr = (char *)buf;
+ strsep(&ptr, "\n");
+
+ /* Print fw version info */
+ brcmf_err("Firmware version = %s\n", buf);
+
+ /* locate firmware version number for ethtool */
+ ptr = strrchr(buf, ' ') + 1;
+ strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver));
+
+ /* set mpc */
+ err = brcmf_fil_iovar_int_set(ifp, "mpc", 1);
+ if (err) {
+ brcmf_err("failed setting mpc\n");
+ goto done;
+ }
+
+ /*
+ * Setup timeout if Beacons are lost and roam is off to report
+ * link down
+ */
+ err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout",
+ BRCMF_DEFAULT_BCN_TIMEOUT);
+ if (err) {
+ brcmf_err("bcn_timeout error (%d)\n", err);
+ goto done;
+ }
+
+ /* Enable/Disable build-in roaming to allowed ext supplicant to take
+ * of romaing
+ */
+ err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1);
+ if (err) {
+ brcmf_err("roam_off error (%d)\n", err);
+ goto done;
+ }
+
+ /* Setup join_pref to select target by RSSI(with boost on 5GHz) */
+ join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
+ join_pref_params[0].len = 2;
+ join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
+ join_pref_params[0].band = WLC_BAND_5G;
+ join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
+ join_pref_params[1].len = 2;
+ join_pref_params[1].rssi_gain = 0;
+ join_pref_params[1].band = 0;
+ err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
+ sizeof(join_pref_params));
+ if (err)
+ brcmf_err("Set join_pref error (%d)\n", err);
+
+ /* Setup event_msgs, enable E_IF */
+ err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
+ BRCMF_EVENTING_MASK_LEN);
+ if (err) {
+ brcmf_err("Get event_msgs error (%d)\n", err);
+ goto done;
+ }
+ setbit(eventmask, BRCMF_E_IF);
+ err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask,
+ BRCMF_EVENTING_MASK_LEN);
+ if (err) {
+ brcmf_err("Set event_msgs error (%d)\n", err);
+ goto done;
+ }
+
+ /* Setup default scan channel time */
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
+ BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
+ if (err) {
+ brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n",
+ err);
+ goto done;
+ }
+
+ /* Setup default scan unassoc time */
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME,
+ BRCMF_DEFAULT_SCAN_UNASSOC_TIME);
+ if (err) {
+ brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n",
+ err);
+ goto done;
+ }
+
+ /* Setup packet filter */
+ brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER);
+ brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER,
+ 0, true);
+
+ /* do bus specific preinit here */
+ err = brcmf_bus_preinit(ifp->drvr->bus_if);
+done:
+ return err;
+}
+
+#ifdef CPTCFG_BRCM_TRACING
+void __brcmf_err(const char *func, const char *fmt, ...)
+{
+ struct va_format vaf = {
+ .fmt = fmt,
+ };
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.va = &args;
+ pr_err("%s: %pV", func, &vaf);
+ trace_brcmf_err(func, &vaf);
+ va_end(args);
+}
+#endif
+#if defined(CPTCFG_BRCM_TRACING) || defined(CPTCFG_BRCMDBG)
+void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...)
+{
+ struct va_format vaf = {
+ .fmt = fmt,
+ };
+ va_list args;
+
+ va_start(args, fmt);
+ vaf.va = &args;
+ if (brcmf_msg_level & level)
+ pr_debug("%s %pV", func, &vaf);
+ trace_brcmf_dbg(level, func, &vaf);
+ va_end(args);
+}
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
similarity index 97%
rename from drivers/net/wireless/brcm80211/brcmfmac/debug.c
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
index 9b473d5..be9f4f8 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
@@ -19,9 +19,9 @@
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
static struct dentry *root_folder;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/debug.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
similarity index 97%
rename from drivers/net/wireless/brcm80211/brcmfmac/debug.h
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
index a1a9bf4..b811d59 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/debug.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h
@@ -14,8 +14,8 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef BRCMFMAC_DEBUG_H
-#define BRCMFMAC_DEBUG_H
+#ifndef _BRCMF_DBG_H_
+#define _BRCMF_DBG_H_
/* message levels */
#define BRCMF_TRACE_VAL 0x00000002
@@ -133,4 +133,4 @@
}
#endif
-#endif /* BRCMFMAC_DEBUG_H */
+#endif /* _BRCMF_DBG_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/core.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
similarity index 96%
rename from drivers/net/wireless/brcm80211/brcmfmac/core.c
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index f8785da..c1a16b1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -22,12 +22,12 @@
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
#include "fwil_types.h"
#include "p2p.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
#include "fwil.h"
#include "fwsignal.h"
#include "feature.h"
@@ -836,7 +836,7 @@
return ifp;
}
-static void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
+void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx)
{
struct brcmf_if *ifp;
@@ -869,38 +869,6 @@
}
}
-void brcmf_remove_interface(struct brcmf_pub *drvr, u32 bssidx)
-{
- if (drvr->iflist[bssidx]) {
- brcmf_fws_del_interface(drvr->iflist[bssidx]);
- brcmf_del_if(drvr, bssidx);
- }
-}
-
-int brcmf_get_next_free_bsscfgidx(struct brcmf_pub *drvr)
-{
- int ifidx;
- int bsscfgidx;
- bool available;
- int highest;
-
- available = false;
- bsscfgidx = 2;
- highest = 2;
- for (ifidx = 0; ifidx < BRCMF_MAX_IFS; ifidx++) {
- if (drvr->iflist[ifidx]) {
- if (drvr->iflist[ifidx]->bssidx == bsscfgidx)
- bsscfgidx = highest + 1;
- else if (drvr->iflist[ifidx]->bssidx > highest)
- highest = drvr->iflist[ifidx]->bssidx;
- } else {
- available = true;
- }
- }
-
- return available ? bsscfgidx : -ENOMEM;
-}
-
int brcmf_attach(struct device *dev)
{
struct brcmf_pub *drvr = NULL;
@@ -1065,7 +1033,10 @@
/* make sure primary interface removed last */
for (i = BRCMF_MAX_IFS-1; i > -1; i--)
- brcmf_remove_interface(drvr, i);
+ if (drvr->iflist[i]) {
+ brcmf_fws_del_interface(drvr->iflist[i]);
+ brcmf_del_if(drvr, i);
+ }
brcmf_cfg80211_detach(drvr->config);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
similarity index 98%
rename from drivers/net/wireless/brcm80211/brcmfmac/sdio.c
rename to drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 0b0d51a..f55f625 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -40,7 +40,7 @@
#include <brcmu_utils.h>
#include <brcm_hw_ids.h>
#include <soc.h>
-#include "sdio.h"
+#include "sdio_host.h"
#include "chip.h"
#include "firmware.h"
@@ -96,8 +96,8 @@
#endif /* DEBUG */
#include <chipcommon.h>
-#include "bus.h"
-#include "debug.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
#include "tracepoint.h"
#define TXQLEN 2048 /* bulk tx queue length */
@@ -670,6 +670,7 @@
struct brcmf_sdio_dev *sdiodev)
{
int i;
+ uint fw_len, nv_len;
char end;
for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
@@ -683,25 +684,25 @@
return -ENODEV;
}
+ fw_len = sizeof(sdiodev->fw_name) - 1;
+ nv_len = sizeof(sdiodev->nvram_name) - 1;
/* check if firmware path is provided by module parameter */
if (brcmf_firmware_path[0] != '\0') {
- strlcpy(sdiodev->fw_name, brcmf_firmware_path,
- sizeof(sdiodev->fw_name));
- strlcpy(sdiodev->nvram_name, brcmf_firmware_path,
- sizeof(sdiodev->nvram_name));
+ strncpy(sdiodev->fw_name, brcmf_firmware_path, fw_len);
+ strncpy(sdiodev->nvram_name, brcmf_firmware_path, nv_len);
+ fw_len -= strlen(sdiodev->fw_name);
+ nv_len -= strlen(sdiodev->nvram_name);
end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1];
if (end != '/') {
- strlcat(sdiodev->fw_name, "/",
- sizeof(sdiodev->fw_name));
- strlcat(sdiodev->nvram_name, "/",
- sizeof(sdiodev->nvram_name));
+ strncat(sdiodev->fw_name, "/", fw_len);
+ strncat(sdiodev->nvram_name, "/", nv_len);
+ fw_len--;
+ nv_len--;
}
}
- strlcat(sdiodev->fw_name, brcmf_fwname_data[i].bin,
- sizeof(sdiodev->fw_name));
- strlcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv,
- sizeof(sdiodev->nvram_name));
+ strncat(sdiodev->fw_name, brcmf_fwname_data[i].bin, fw_len);
+ strncat(sdiodev->nvram_name, brcmf_fwname_data[i].nv, nv_len);
return 0;
}
@@ -2762,48 +2763,6 @@
return &bus->txq;
}
-static bool brcmf_sdio_prec_enq(struct pktq *q, struct sk_buff *pkt, int prec)
-{
- struct sk_buff *p;
- int eprec = -1; /* precedence to evict from */
-
- /* 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 */
- if (eprec == prec)
- return false; /* refuse newer (incoming) packet */
- /* Evict packet according to discard policy */
- p = brcmu_pktq_pdeq_tail(q, eprec);
- if (p == NULL)
- brcmf_err("brcmu_pktq_pdeq_tail() failed\n");
- brcmu_pkt_buf_free_skb(p);
- }
-
- /* Enqueue */
- p = brcmu_pktq_penq(q, prec, pkt);
- if (p == NULL)
- brcmf_err("brcmu_pktq_penq() failed\n");
-
- return p != NULL;
-}
-
static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt)
{
int ret = -EBADE;
@@ -2829,7 +2788,7 @@
spin_lock_bh(&bus->txq_lock);
/* reset bus_flags in packet cb */
*(u16 *)(pkt->cb) = 0;
- if (!brcmf_sdio_prec_enq(&bus->txq, pkt, prec)) {
+ if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) {
skb_pull(pkt, bus->tx_hdrlen);
brcmf_err("out of bus->txq !!!\n");
ret = -ENOSR;
@@ -2839,7 +2798,7 @@
if (pktq_len(&bus->txq) >= TXHI) {
bus->txoff = true;
- brcmf_txflowblock(dev, true);
+ brcmf_txflowblock(bus->sdiodev->dev, true);
}
spin_unlock_bh(&bus->txq_lock);
@@ -3990,7 +3949,6 @@
.txctl = brcmf_sdio_bus_txctl,
.rxctl = brcmf_sdio_bus_rxctl,
.gettxq = brcmf_sdio_bus_gettxq,
- .wowl_config = brcmf_sdio_wowl_config
};
static void brcmf_sdio_firmware_callback(struct device *dev,
@@ -4117,7 +4075,7 @@
/* platform specific configuration:
* alignments must be at least 4 bytes for ADMA
- */
+ */
bus->head_align = ALIGNMENT;
bus->sgentry_align = ALIGNMENT;
if (sdiodev->pdata) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
index defb7a4..aed53ac 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c
@@ -17,13 +17,18 @@
#include <linux/netdevice.h>
#include <brcm_hw_ids.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
#include "fwil.h"
#include "feature.h"
/*
+ * firmware error code received if iovar is unsupported.
+ */
+#define EBRCMF_FEAT_UNSUPPORTED 23
+
+/*
* expand feature list to array of feature strings.
*/
#define BRCMF_FEAT_DEF(_f) \
@@ -97,28 +102,6 @@
}
}
-/**
- * brcmf_feat_iovar_int_set() - determine feature through iovar set.
- *
- * @ifp: interface to query.
- * @id: feature id.
- * @name: iovar name.
- */
-static void brcmf_feat_iovar_int_set(struct brcmf_if *ifp,
- enum brcmf_feat_id id, char *name, u32 val)
-{
- int err;
-
- err = brcmf_fil_iovar_int_set(ifp, name, val);
- if (err == 0) {
- brcmf_dbg(INFO, "enabling feature: %s\n", brcmf_feat_names[id]);
- ifp->drvr->feat_flags |= BIT(id);
- } else {
- brcmf_dbg(TRACE, "%s feature check failed: %d\n",
- brcmf_feat_names[id], err);
- }
-}
-
void brcmf_feat_attach(struct brcmf_pub *drvr)
{
struct brcmf_if *ifp = drvr->iflist[0];
@@ -126,7 +109,6 @@
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_MCHAN, "mchan");
if (drvr->bus_if->wowl_supported)
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_WOWL, "wowl");
- brcmf_feat_iovar_int_set(ifp, BRCMF_FEAT_MBSS, "mbss", 0);
/* set chip related quirks */
switch (drvr->bus_if->chip) {
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
index f5832e0..b9a796d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.h
@@ -22,7 +22,6 @@
* MCHAN: multi-channel for concurrent P2P.
*/
#define BRCMF_FEAT_LIST \
- BRCMF_FEAT_DEF(MBSS) \
BRCMF_FEAT_DEF(MCHAN) \
BRCMF_FEAT_DEF(WOWL)
/*
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
index 1ff787d..8ea9f28 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
@@ -20,7 +20,7 @@
#include <linux/firmware.h>
#include <linux/module.h>
-#include "debug.h"
+#include "dhd_dbg.h"
#include "firmware.h"
char brcmf_firmware_path[BRCMF_FW_PATH_LEN];
@@ -262,7 +262,8 @@
fail:
brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
- release_firmware(fwctx->code);
+ if (fwctx->code)
+ release_firmware(fwctx->code);
device_release_driver(fwctx->dev);
kfree(fwctx);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
index 44f3a84..1faa929 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c
@@ -19,9 +19,9 @@
#include <linux/etherdevice.h>
#include <brcmu_utils.h>
-#include "core.h"
-#include "debug.h"
-#include "bus.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
#include "proto.h"
#include "flowring.h"
#include "msgbuf.h"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
index ec62492..44fc85f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c
@@ -18,8 +18,8 @@
#include "brcmu_wifi.h"
#include "brcmu_utils.h"
-#include "core.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
#include "tracepoint.h"
#include "fwsignal.h"
#include "fweh.h"
@@ -221,8 +221,10 @@
err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data);
- if (ifp && ifevent->action == BRCMF_E_IF_DEL)
- brcmf_remove_interface(drvr, ifevent->bssidx);
+ if (ifp && ifevent->action == BRCMF_E_IF_DEL) {
+ brcmf_fws_del_interface(ifp);
+ brcmf_del_if(drvr, ifevent->bssidx);
+ }
}
/**
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
index 03f2c40..ded328f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c
@@ -22,9 +22,9 @@
#include <linux/netdevice.h>
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
#include "tracepoint.h"
#include "fwil.h"
#include "proto.h"
@@ -32,76 +32,6 @@
#define MAX_HEX_DUMP_LEN 64
-#ifdef DEBUG
-static const char * const brcmf_fil_errstr[] = {
- "BCME_OK",
- "BCME_ERROR",
- "BCME_BADARG",
- "BCME_BADOPTION",
- "BCME_NOTUP",
- "BCME_NOTDOWN",
- "BCME_NOTAP",
- "BCME_NOTSTA",
- "BCME_BADKEYIDX",
- "BCME_RADIOOFF",
- "BCME_NOTBANDLOCKED",
- "BCME_NOCLK",
- "BCME_BADRATESET",
- "BCME_BADBAND",
- "BCME_BUFTOOSHORT",
- "BCME_BUFTOOLONG",
- "BCME_BUSY",
- "BCME_NOTASSOCIATED",
- "BCME_BADSSIDLEN",
- "BCME_OUTOFRANGECHAN",
- "BCME_BADCHAN",
- "BCME_BADADDR",
- "BCME_NORESOURCE",
- "BCME_UNSUPPORTED",
- "BCME_BADLEN",
- "BCME_NOTREADY",
- "BCME_EPERM",
- "BCME_NOMEM",
- "BCME_ASSOCIATED",
- "BCME_RANGE",
- "BCME_NOTFOUND",
- "BCME_WME_NOT_ENABLED",
- "BCME_TSPEC_NOTFOUND",
- "BCME_ACM_NOTSUPPORTED",
- "BCME_NOT_WME_ASSOCIATION",
- "BCME_SDIO_ERROR",
- "BCME_DONGLE_DOWN",
- "BCME_VERSION",
- "BCME_TXFAIL",
- "BCME_RXFAIL",
- "BCME_NODEVICE",
- "BCME_NMODE_DISABLED",
- "BCME_NONRESIDENT",
- "BCME_SCANREJECT",
- "BCME_USAGE_ERROR",
- "BCME_IOCTL_ERROR",
- "BCME_SERIAL_PORT_ERR",
- "BCME_DISABLED",
- "BCME_DECERR",
- "BCME_ENCERR",
- "BCME_MICERR",
- "BCME_REPLAY",
- "BCME_IE_NOTFOUND",
-};
-
-static const char *brcmf_fil_get_errstr(u32 err)
-{
- if (err >= ARRAY_SIZE(brcmf_fil_errstr))
- return "(unknown)";
-
- return brcmf_fil_errstr[err];
-}
-#else
-static const char *brcmf_fil_get_errstr(u32 err)
-{
- return "";
-}
-#endif /* DEBUG */
static s32
brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set)
@@ -122,11 +52,11 @@
err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len);
if (err >= 0)
- return 0;
+ err = 0;
+ else
+ brcmf_dbg(FIL, "Failed err=%d\n", err);
- brcmf_dbg(FIL, "Failed: %s (%d)\n",
- brcmf_fil_get_errstr((u32)(-err)), err);
- return -EBADE;
+ return err;
}
s32
@@ -136,7 +66,7 @@
mutex_lock(&ifp->drvr->proto_block);
- brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len);
+ brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
@@ -154,7 +84,7 @@
mutex_lock(&ifp->drvr->proto_block);
err = brcmf_fil_cmd_data(ifp, cmd, data, len, false);
- brcmf_dbg(FIL, "ifidx=%d, cmd=%d, len=%d\n", ifp->ifidx, cmd, len);
+ brcmf_dbg(FIL, "cmd=%d, len=%d\n", cmd, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
@@ -171,7 +101,7 @@
__le32 data_le = cpu_to_le32(data);
mutex_lock(&ifp->drvr->proto_block);
- brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, data);
+ brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, data);
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), true);
mutex_unlock(&ifp->drvr->proto_block);
@@ -188,7 +118,7 @@
err = brcmf_fil_cmd_data(ifp, cmd, &data_le, sizeof(data_le), false);
mutex_unlock(&ifp->drvr->proto_block);
*data = le32_to_cpu(data_le);
- brcmf_dbg(FIL, "ifidx=%d, cmd=%d, value=%d\n", ifp->ifidx, cmd, *data);
+ brcmf_dbg(FIL, "cmd=%d, value=%d\n", cmd, *data);
return err;
}
@@ -224,7 +154,7 @@
mutex_lock(&drvr->proto_block);
- brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
+ brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
@@ -264,7 +194,7 @@
brcmf_err("Creating iovar failed\n");
}
- brcmf_dbg(FIL, "ifidx=%d, name=%s, len=%d\n", ifp->ifidx, name, len);
+ brcmf_dbg(FIL, "name=%s, len=%d\n", name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
@@ -347,8 +277,7 @@
mutex_lock(&drvr->proto_block);
- brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx,
- ifp->bssidx, name, len);
+ brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
@@ -387,8 +316,7 @@
err = -EPERM;
brcmf_err("Creating bsscfg failed\n");
}
- brcmf_dbg(FIL, "ifidx=%d, bssidx=%d, name=%s, len=%d\n", ifp->ifidx,
- ifp->bssidx, name, len);
+ brcmf_dbg(FIL, "bssidx=%d, name=%s, len=%d\n", ifp->bssidx, name, len);
brcmf_dbg_hex_dump(BRCMF_FIL_ON(), data,
min_t(uint, len, MAX_HEX_DUMP_LEN), "data\n");
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
index 50891c0..5ff5cd0 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
@@ -55,63 +55,59 @@
/* WOWL bits */
/* Wakeup on Magic packet: */
-#define BRCMF_WOWL_MAGIC (1 << 0)
+#define WL_WOWL_MAGIC (1 << 0)
/* Wakeup on Netpattern */
-#define BRCMF_WOWL_NET (1 << 1)
+#define WL_WOWL_NET (1 << 1)
/* Wakeup on loss-of-link due to Disassoc/Deauth: */
-#define BRCMF_WOWL_DIS (1 << 2)
+#define WL_WOWL_DIS (1 << 2)
/* Wakeup on retrograde TSF: */
-#define BRCMF_WOWL_RETR (1 << 3)
+#define WL_WOWL_RETR (1 << 3)
/* Wakeup on loss of beacon: */
-#define BRCMF_WOWL_BCN (1 << 4)
+#define WL_WOWL_BCN (1 << 4)
/* Wakeup after test: */
-#define BRCMF_WOWL_TST (1 << 5)
+#define WL_WOWL_TST (1 << 5)
/* Wakeup after PTK refresh: */
-#define BRCMF_WOWL_M1 (1 << 6)
+#define WL_WOWL_M1 (1 << 6)
/* Wakeup after receipt of EAP-Identity Req: */
-#define BRCMF_WOWL_EAPID (1 << 7)
+#define WL_WOWL_EAPID (1 << 7)
/* Wakeind via PME(0) or GPIO(1): */
-#define BRCMF_WOWL_PME_GPIO (1 << 8)
+#define WL_WOWL_PME_GPIO (1 << 8)
/* need tkip phase 1 key to be updated by the driver: */
-#define BRCMF_WOWL_NEEDTKIP1 (1 << 9)
+#define WL_WOWL_NEEDTKIP1 (1 << 9)
/* enable wakeup if GTK fails: */
-#define BRCMF_WOWL_GTK_FAILURE (1 << 10)
+#define WL_WOWL_GTK_FAILURE (1 << 10)
/* support extended magic packets: */
-#define BRCMF_WOWL_EXTMAGPAT (1 << 11)
+#define WL_WOWL_EXTMAGPAT (1 << 11)
/* support ARP/NS/keepalive offloading: */
-#define BRCMF_WOWL_ARPOFFLOAD (1 << 12)
+#define WL_WOWL_ARPOFFLOAD (1 << 12)
/* read protocol version for EAPOL frames: */
-#define BRCMF_WOWL_WPA2 (1 << 13)
+#define WL_WOWL_WPA2 (1 << 13)
/* If the bit is set, use key rotaton: */
-#define BRCMF_WOWL_KEYROT (1 << 14)
+#define WL_WOWL_KEYROT (1 << 14)
/* If the bit is set, frm received was bcast frame: */
-#define BRCMF_WOWL_BCAST (1 << 15)
+#define WL_WOWL_BCAST (1 << 15)
/* If the bit is set, scan offload is enabled: */
-#define BRCMF_WOWL_SCANOL (1 << 16)
+#define WL_WOWL_SCANOL (1 << 16)
/* Wakeup on tcpkeep alive timeout: */
-#define BRCMF_WOWL_TCPKEEP_TIME (1 << 17)
+#define WL_WOWL_TCPKEEP_TIME (1 << 17)
/* Wakeup on mDNS Conflict Resolution: */
-#define BRCMF_WOWL_MDNS_CONFLICT (1 << 18)
+#define WL_WOWL_MDNS_CONFLICT (1 << 18)
/* Wakeup on mDNS Service Connect: */
-#define BRCMF_WOWL_MDNS_SERVICE (1 << 19)
+#define WL_WOWL_MDNS_SERVICE (1 << 19)
/* tcp keepalive got data: */
-#define BRCMF_WOWL_TCPKEEP_DATA (1 << 20)
+#define WL_WOWL_TCPKEEP_DATA (1 << 20)
/* Firmware died in wowl mode: */
-#define BRCMF_WOWL_FW_HALT (1 << 21)
+#define WL_WOWL_FW_HALT (1 << 21)
/* Enable detection of radio button changes: */
-#define BRCMF_WOWL_ENAB_HWRADIO (1 << 22)
+#define WL_WOWL_ENAB_HWRADIO (1 << 22)
/* Offloads detected MIC failure(s): */
-#define BRCMF_WOWL_MIC_FAIL (1 << 23)
+#define WL_WOWL_MIC_FAIL (1 << 23)
/* Wakeup in Unassociated state (Net/Magic Pattern): */
-#define BRCMF_WOWL_UNASSOC (1 << 24)
+#define WL_WOWL_UNASSOC (1 << 24)
/* Wakeup if received matched secured pattern: */
-#define BRCMF_WOWL_SECURE (1 << 25)
+#define WL_WOWL_SECURE (1 << 25)
/* Link Down indication in WoWL mode: */
-#define BRCMF_WOWL_LINKDOWN (1 << 31)
-
-#define BRCMF_WOWL_MAXPATTERNS 8
-#define BRCMF_WOWL_MAXPATTERNSIZE 128
-
+#define WL_WOWL_LINKDOWN (1 << 31)
/* join preference types for join_pref iovar */
enum brcmf_join_pref_types {
@@ -128,12 +124,6 @@
BRCMF_FIL_P2P_IF_DEV,
};
-enum brcmf_wowl_pattern_type {
- BRCMF_WOWL_PATTERN_TYPE_BITMAP = 0,
- BRCMF_WOWL_PATTERN_TYPE_ARP,
- BRCMF_WOWL_PATTERN_TYPE_NA
-};
-
struct brcmf_fil_p2p_if_le {
u8 addr[ETH_ALEN];
__le16 type;
@@ -494,35 +484,4 @@
__be32 rate;
};
-/**
- * struct brcmf_fil_wowl_pattern_le - wowl pattern configuration struct.
- *
- * @cmd: "add", "del" or "clr".
- * @masksize: Size of the mask in #of bytes
- * @offset: Pattern byte offset in packet
- * @patternoffset: Offset of start of pattern. Starting from field masksize.
- * @patternsize: Size of the pattern itself in #of bytes
- * @id: id
- * @reasonsize: Size of the wakeup reason code
- * @type: Type of pattern (enum brcmf_wowl_pattern_type)
- */
-struct brcmf_fil_wowl_pattern_le {
- u8 cmd[4];
- __le32 masksize;
- __le32 offset;
- __le32 patternoffset;
- __le32 patternsize;
- __le32 id;
- __le32 reasonsize;
- __le32 type;
- /* u8 mask[] - Mask follows the structure above */
- /* u8 pattern[] - Pattern follows the mask is at 'patternoffset' */
-};
-
-struct brcmf_mbss_ssid_le {
- __le32 bsscfgidx;
- __le32 SSID_len;
- unsigned char SSID[32];
-};
-
#endif /* FWIL_TYPES_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index f0dda0e..183f08d 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -26,15 +26,15 @@
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
-#include "core.h"
-#include "debug.h"
-#include "bus.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
#include "fwil.h"
#include "fwil_types.h"
#include "fweh.h"
#include "fwsignal.h"
#include "p2p.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
#include "proto.h"
/**
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
index 456944a..11cc051 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c
@@ -24,13 +24,13 @@
#include <brcmu_utils.h>
#include <brcmu_wifi.h>
-#include "core.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
#include "proto.h"
#include "msgbuf.h"
#include "commonring.h"
#include "flowring.h"
-#include "bus.h"
+#include "dhd_bus.h"
#include "tracepoint.h"
@@ -518,7 +518,8 @@
memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ?
len : msgbuf->ioctl_resp_ret_len);
}
- brcmu_pkt_buf_free_skb(skb);
+ if (skb)
+ brcmu_pkt_buf_free_skb(skb);
return msgbuf->ioctl_resp_status;
}
@@ -1080,17 +1081,8 @@
{
struct brcmf_if *ifp;
- /* The ifidx is the idx to map to matching netdev/ifp. When receiving
- * events this is easy because it contains the bssidx which maps
- * 1-on-1 to the netdev/ifp. But for data frames the ifidx is rcvd.
- * bssidx 1 is used for p2p0 and no data can be received or
- * transmitted on it. Therefor bssidx is ifidx + 1 if ifidx > 0
- */
- if (ifidx)
- (ifidx)++;
ifp = msgbuf->drvr->iflist[ifidx];
if (!ifp || !ifp->ndev) {
- brcmf_err("Received pkt for invalid ifidx %d\n", ifidx);
brcmu_pkt_buf_free_skb(skb);
return;
}
@@ -1363,7 +1355,6 @@
}
INIT_WORK(&msgbuf->txflow_work, brcmf_msgbuf_txflow_worker);
count = BITS_TO_LONGS(if_msgbuf->nrof_flowrings);
- count = count * sizeof(unsigned long);
msgbuf->flow_map = kzalloc(count, GFP_KERNEL);
if (!msgbuf->flow_map)
goto fail;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/of.c b/drivers/net/wireless/brcm80211/brcmfmac/of.c
index c824570..f05f527 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/of.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/of.c
@@ -21,8 +21,8 @@
#include <linux/mmc/sdio_func.h>
#include <defs.h>
-#include "debug.h"
-#include "sdio.h"
+#include "dhd_dbg.h"
+#include "sdio_host.h"
void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev)
{
@@ -40,8 +40,8 @@
return;
irq = irq_of_parse_and_map(np, 0);
- if (!irq) {
- brcmf_err("interrupt could not be mapped\n");
+ if (irq < 0) {
+ brcmf_err("interrupt could not be mapped: err=%d\n", irq);
devm_kfree(dev, sdiodev->pdata);
return;
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
index effb48e..d54c58a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c
@@ -21,12 +21,12 @@
#include <brcmu_wifi.h>
#include <brcmu_utils.h>
#include <defs.h>
-#include "core.h"
-#include "debug.h"
+#include <dhd.h>
+#include <dhd_dbg.h>
#include "fwil.h"
#include "fwil_types.h"
#include "p2p.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
/* parameters used for p2p escan */
#define P2PAPI_SCAN_NPROBES 1
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
index 905991f..8c0632e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c
@@ -19,10 +19,10 @@
#include <linux/pci.h>
#include <linux/vmalloc.h>
#include <linux/delay.h>
+#include <linux/unaligned/access_ok.h>
#include <linux/interrupt.h>
#include <linux/bcma/bcma.h>
#include <linux/sched.h>
-#include <asm/unaligned.h>
#include <soc.h>
#include <chipcommon.h>
@@ -30,8 +30,8 @@
#include <brcmu_wifi.h>
#include <brcm_hw_ids.h>
-#include "debug.h"
-#include "bus.h"
+#include "dhd_dbg.h"
+#include "dhd_bus.h"
#include "commonring.h"
#include "msgbuf.h"
#include "pcie.h"
@@ -798,14 +798,12 @@
brcmf_dbg(PCIE, "Enter\n");
/* is it a v1 or v2 implementation */
devinfo->irq_requested = false;
- pci_enable_msi(pdev);
if (devinfo->generic_corerev == BRCMF_PCIE_GENREV1) {
if (request_threaded_irq(pdev->irq,
brcmf_pcie_quick_check_isr_v1,
brcmf_pcie_isr_thread_v1,
IRQF_SHARED, "brcmf_pcie_intr",
devinfo)) {
- pci_disable_msi(pdev);
brcmf_err("Failed to request IRQ %d\n", pdev->irq);
return -EIO;
}
@@ -815,7 +813,6 @@
brcmf_pcie_isr_thread_v2,
IRQF_SHARED, "brcmf_pcie_intr",
devinfo)) {
- pci_disable_msi(pdev);
brcmf_err("Failed to request IRQ %d\n", pdev->irq);
return -EIO;
}
@@ -842,7 +839,6 @@
return;
devinfo->irq_requested = false;
free_irq(pdev->irq, devinfo);
- pci_disable_msi(pdev);
msleep(50);
count = 0;
@@ -1861,8 +1857,6 @@
BRCMF_PCIE_DEVICE(BRCM_PCIE_43567_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43570_DEVICE_ID),
BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_DEVICE_ID),
- BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_2G_DEVICE_ID),
- BRCMF_PCIE_DEVICE(BRCM_PCIE_43602_5G_DEVICE_ID),
{ /* end: all zeroes */ }
};
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/brcm80211/brcmfmac/proto.c
index 26b68c3..62b9407 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/proto.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.c
@@ -20,9 +20,9 @@
#include <linux/netdevice.h>
#include <brcmu_wifi.h>
-#include "core.h"
-#include "bus.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_bus.h"
+#include "dhd_dbg.h"
#include "proto.h"
#include "bcdc.h"
#include "msgbuf.h"
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
similarity index 98%
rename from drivers/net/wireless/brcm80211/brcmfmac/sdio.h
rename to drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
index 8eb4262..f2d06ca 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/sdio.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h
@@ -14,8 +14,8 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef BRCMFMAC_SDIO_H
-#define BRCMFMAC_SDIO_H
+#ifndef _BRCM_SDH_H_
+#define _BRCM_SDH_H_
#include <linux/skbuff.h>
#include <linux/firmware.h>
@@ -186,7 +186,6 @@
struct sg_table sgtable;
char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN];
- bool wowl_enabled;
};
/* sdio core registers */
@@ -335,6 +334,5 @@
void brcmf_sdio_isr(struct brcmf_sdio *bus);
void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick);
-void brcmf_sdio_wowl_config(struct device *dev, bool enabled);
-#endif /* BRCMFMAC_SDIO_H */
+#endif /* _BRCM_SDH_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
index a10f35c..b505db4 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c
@@ -19,19 +19,4 @@
#ifndef __CHECKER__
#define CREATE_TRACE_POINTS
#include "tracepoint.h"
-
-void __brcmf_err(const char *func, const char *fmt, ...)
-{
- struct va_format vaf = {
- .fmt = fmt,
- };
- va_list args;
-
- va_start(args, fmt);
- vaf.va = &args;
- pr_err("%s: %pV", func, &vaf);
- trace_brcmf_err(func, &vaf);
- va_end(args);
-}
-
#endif
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index a662707..99b03a1 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -23,11 +23,12 @@
#include <brcmu_utils.h>
#include <brcm_hw_ids.h>
#include <brcmu_wifi.h>
-#include "bus.h"
-#include "debug.h"
-#include "firmware.h"
-#include "usb.h"
+#include <dhd_bus.h>
+#include <dhd_dbg.h>
+#include "firmware.h"
+#include "usb_rdl.h"
+#include "usb.h"
#define IOCTL_RESP_TIMEOUT 2000
@@ -48,71 +49,6 @@
#define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin"
#define BRCMF_USB_43569_FW_NAME "brcm/brcmfmac43569.bin"
-#define TRX_MAGIC 0x30524448 /* "HDR0" */
-#define TRX_MAX_OFFSET 3 /* Max number of file offsets */
-#define TRX_UNCOMP_IMAGE 0x20 /* Trx holds uncompressed img */
-#define TRX_RDL_CHUNK 1500 /* size of each dl transfer */
-#define TRX_OFFSETS_DLFWLEN_IDX 0
-
-/* Control messages: bRequest values */
-#define DL_GETSTATE 0 /* returns the rdl_state_t struct */
-#define DL_CHECK_CRC 1 /* currently unused */
-#define DL_GO 2 /* execute downloaded image */
-#define DL_START 3 /* initialize dl state */
-#define DL_REBOOT 4 /* reboot the device in 2 seconds */
-#define DL_GETVER 5 /* returns the bootrom_id_t struct */
-#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset
- * event to occur in 2 seconds. It is the
- * responsibility of the downloaded code to
- * clear this event
- */
-#define DL_EXEC 7 /* jump to a supplied address */
-#define DL_RESETCFG 8 /* To support single enum on dongle
- * - Not used by bootloader
- */
-#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup
- * if resp unavailable
- */
-
-/* states */
-#define DL_WAITING 0 /* waiting to rx first pkt */
-#define DL_READY 1 /* hdr was good, waiting for more of the
- * compressed image
- */
-#define DL_BAD_HDR 2 /* hdr was corrupted */
-#define DL_BAD_CRC 3 /* compressed image was corrupted */
-#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */
-#define DL_START_FAIL 5 /* failed to initialize correctly */
-#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM
- * value
- */
-#define DL_IMAGE_TOOBIG 7 /* firmware image too big */
-
-
-struct trx_header_le {
- __le32 magic; /* "HDR0" */
- __le32 len; /* Length of file including header */
- __le32 crc32; /* CRC from flag_version to end of file */
- __le32 flag_version; /* 0:15 flags, 16:31 version */
- __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of
- * header
- */
-};
-
-struct rdl_state_le {
- __le32 state;
- __le32 bytes;
-};
-
-struct bootrom_id_le {
- __le32 chip; /* Chip id */
- __le32 chiprev; /* Chip rev */
- __le32 ramsize; /* Size of RAM */
- __le32 remapbase; /* Current remap base address */
- __le32 boardtype; /* Type of board */
- __le32 boardrev; /* Board revision */
-};
-
struct brcmf_usb_image {
struct list_head list;
s8 *fwname;
@@ -157,8 +93,6 @@
u8 ifnum;
struct urb *bulk_urb; /* used for FW download */
-
- bool wowl_enabled;
};
static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
@@ -666,16 +600,6 @@
return 0;
}
-static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo)
-{
- if (devinfo->ctl_urb)
- usb_kill_urb(devinfo->ctl_urb);
- if (devinfo->bulk_urb)
- usb_kill_urb(devinfo->bulk_urb);
- brcmf_usb_free_q(&devinfo->tx_postq, true);
- brcmf_usb_free_q(&devinfo->rx_postq, true);
-}
-
static void brcmf_usb_down(struct device *dev)
{
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
@@ -689,7 +613,14 @@
brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);
- brcmf_cancel_all_urbs(devinfo);
+ if (devinfo->ctl_urb)
+ usb_kill_urb(devinfo->ctl_urb);
+
+ if (devinfo->bulk_urb)
+ usb_kill_urb(devinfo->bulk_urb);
+ brcmf_usb_free_q(&devinfo->tx_postq, true);
+
+ brcmf_usb_free_q(&devinfo->rx_postq, true);
}
static void
@@ -738,12 +669,10 @@
goto finalize;
}
- if (!brcmf_usb_ioctl_resp_wait(devinfo)) {
- usb_kill_urb(devinfo->ctl_urb);
+ if (!brcmf_usb_ioctl_resp_wait(devinfo))
ret = -ETIMEDOUT;
- } else {
+ else
memcpy(buffer, tmpbuf, buflen);
- }
finalize:
kfree(tmpbuf);
@@ -854,7 +783,7 @@
brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen);
- bulkchunk = kmalloc(TRX_RDL_CHUNK, GFP_ATOMIC);
+ bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC);
if (bulkchunk == NULL) {
err = -ENOMEM;
goto fail;
@@ -881,10 +810,10 @@
/* Wait until the usb device reports it received all
* the bytes we sent */
if ((rdlbytes == sent) && (rdlbytes != dllen)) {
- if ((dllen-sent) < TRX_RDL_CHUNK)
+ if ((dllen-sent) < RDL_CHUNK)
sendlen = dllen-sent;
else
- sendlen = TRX_RDL_CHUNK;
+ sendlen = RDL_CHUNK;
/* simply avoid having to send a ZLP by ensuring we
* never have an even
@@ -1049,6 +978,21 @@
kfree(devinfo->rx_reqs);
}
+#define TRX_MAGIC 0x30524448 /* "HDR0" */
+#define TRX_VERSION 1 /* Version 1 */
+#define TRX_MAX_LEN 0x3B0000 /* Max length */
+#define TRX_NO_HEADER 1 /* Do not write TRX header */
+#define TRX_MAX_OFFSET 3 /* Max number of individual files */
+#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed image */
+
+struct trx_header_le {
+ __le32 magic; /* "HDR0" */
+ __le32 len; /* Length of file including header */
+ __le32 crc32; /* CRC from flag_version to end of file */
+ __le32 flag_version; /* 0:15 flags, 16:31 version */
+ __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of
+ * header */
+};
static int check_file(const u8 *headers)
{
@@ -1150,24 +1094,11 @@
return NULL;
}
-static void brcmf_usb_wowl_config(struct device *dev, bool enabled)
-{
- struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
-
- brcmf_dbg(USB, "Configuring WOWL, enabled=%d\n", enabled);
- devinfo->wowl_enabled = enabled;
- if (enabled)
- device_set_wakeup_enable(devinfo->dev, true);
- else
- device_set_wakeup_enable(devinfo->dev, false);
-}
-
static struct brcmf_bus_ops brcmf_usb_bus_ops = {
.txdata = brcmf_usb_tx,
.stop = brcmf_usb_down,
.txctl = brcmf_usb_tx_ctlpkt,
.rxctl = brcmf_usb_rx_ctlpkt,
- .wowl_config = brcmf_usb_wowl_config,
};
static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
@@ -1255,9 +1186,6 @@
bus->ops = &brcmf_usb_bus_ops;
bus->proto_type = BRCMF_PROTO_BCDC;
bus->always_use_fws_queue = true;
-#ifdef CONFIG_PM
- bus->wowl_supported = true;
-#endif
if (!brcmf_usb_dlneeded(devinfo)) {
ret = brcmf_usb_bus_setup(devinfo);
@@ -1411,10 +1339,7 @@
brcmf_dbg(USB, "Enter\n");
devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP;
- if (devinfo->wowl_enabled)
- brcmf_cancel_all_urbs(devinfo);
- else
- brcmf_detach(&usb->dev);
+ brcmf_detach(&usb->dev);
return 0;
}
@@ -1427,12 +1352,7 @@
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
brcmf_dbg(USB, "Enter\n");
- if (!devinfo->wowl_enabled)
- return brcmf_usb_bus_setup(devinfo);
-
- devinfo->bus_pub.state = BRCMFMAC_USB_STATE_UP;
- brcmf_usb_rx_fill_all(devinfo);
- return 0;
+ return brcmf_usb_bus_setup(devinfo);
}
static int brcmf_usb_reset_resume(struct usb_interface *intf)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
new file mode 100644
index 0000000..0a35c51
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h
@@ -0,0 +1,75 @@
+/*
+ * 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 _USB_RDL_H
+#define _USB_RDL_H
+
+/* Control messages: bRequest values */
+#define DL_GETSTATE 0 /* returns the rdl_state_t struct */
+#define DL_CHECK_CRC 1 /* currently unused */
+#define DL_GO 2 /* execute downloaded image */
+#define DL_START 3 /* initialize dl state */
+#define DL_REBOOT 4 /* reboot the device in 2 seconds */
+#define DL_GETVER 5 /* returns the bootrom_id_t struct */
+#define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset
+ * event to occur in 2 seconds. It is the
+ * responsibility of the downloaded code to
+ * clear this event
+ */
+#define DL_EXEC 7 /* jump to a supplied address */
+#define DL_RESETCFG 8 /* To support single enum on dongle
+ * - Not used by bootloader
+ */
+#define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup
+ * if resp unavailable
+ */
+
+/* states */
+#define DL_WAITING 0 /* waiting to rx first pkt */
+#define DL_READY 1 /* hdr was good, waiting for more of the
+ * compressed image */
+#define DL_BAD_HDR 2 /* hdr was corrupted */
+#define DL_BAD_CRC 3 /* compressed image was corrupted */
+#define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */
+#define DL_START_FAIL 5 /* failed to initialize correctly */
+#define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM
+ * value */
+#define DL_IMAGE_TOOBIG 7 /* download image too big (exceeds DATA_START
+ * for rdl) */
+
+struct rdl_state_le {
+ __le32 state;
+ __le32 bytes;
+};
+
+struct bootrom_id_le {
+ __le32 chip; /* Chip id */
+ __le32 chiprev; /* Chip rev */
+ __le32 ramsize; /* Size of RAM */
+ __le32 remapbase; /* Current remap base address */
+ __le32 boardtype; /* Type of board */
+ __le32 boardrev; /* Board revision */
+};
+
+#define RDL_CHUNK 1500 /* size of each dl transfer */
+
+#define TRX_OFFSETS_DLFWLEN_IDX 0
+#define TRX_OFFSETS_JUMPTO_IDX 1
+#define TRX_OFFSETS_NVM_LEN_IDX 2
+
+#define TRX_OFFSETS_DLBASE_IDX 0
+
+#endif /* _USB_RDL_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c
index 50cdf70..5960d82 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/vendor.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c
@@ -20,10 +20,10 @@
#include <brcmu_wifi.h>
#include "fwil_types.h"
-#include "core.h"
+#include "dhd.h"
#include "p2p.h"
-#include "debug.h"
-#include "cfg80211.h"
+#include "dhd_dbg.h"
+#include "wl_cfg80211.h"
#include "vendor.h"
#include "fwil.h"
@@ -31,8 +31,8 @@
struct wireless_dev *wdev,
const void *data, int len)
{
- struct brcmf_cfg80211_vif *vif;
- struct brcmf_if *ifp;
+ struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+ struct net_device *ndev = cfg_to_ndev(cfg);
const struct brcmf_vndr_dcmd_hdr *cmdhdr = data;
struct sk_buff *reply;
int ret, payload, ret_len;
@@ -42,9 +42,6 @@
brcmf_dbg(TRACE, "cmd %x set %d len %d\n", cmdhdr->cmd, cmdhdr->set,
cmdhdr->len);
- vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
- ifp = vif->ifp;
-
len -= sizeof(struct brcmf_vndr_dcmd_hdr);
ret_len = cmdhdr->len;
if (ret_len > 0 || len > 0) {
@@ -66,11 +63,11 @@
}
if (cmdhdr->set)
- ret = brcmf_fil_cmd_data_set(ifp, cmdhdr->cmd, dcmd_buf,
- ret_len);
+ ret = brcmf_fil_cmd_data_set(netdev_priv(ndev), cmdhdr->cmd,
+ dcmd_buf, ret_len);
else
- ret = brcmf_fil_cmd_data_get(ifp, cmdhdr->cmd, dcmd_buf,
- ret_len);
+ ret = brcmf_fil_cmd_data_get(netdev_priv(ndev), cmdhdr->cmd,
+ dcmd_buf, ret_len);
if (ret != 0)
goto exit;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
similarity index 95%
rename from drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
rename to drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index 3aecc5f..28fa25b 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -26,18 +26,18 @@
#include <brcmu_utils.h>
#include <defs.h>
#include <brcmu_wifi.h>
-#include "core.h"
-#include "debug.h"
+#include "dhd.h"
+#include "dhd_dbg.h"
#include "tracepoint.h"
#include "fwil_types.h"
#include "p2p.h"
#include "btcoex.h"
-#include "cfg80211.h"
+#include "wl_cfg80211.h"
#include "feature.h"
#include "fwil.h"
#include "proto.h"
#include "vendor.h"
-#include "bus.h"
+#include "dhd_bus.h"
#define BRCMF_SCAN_IE_LEN_MAX 2048
#define BRCMF_PNO_VERSION 2
@@ -299,7 +299,6 @@
primary_offset = ch->center_freq1 - ch->chan->center_freq;
switch (ch->width) {
case NL80211_CHAN_WIDTH_20:
- case NL80211_CHAN_WIDTH_20_NOHT:
ch_inf.bw = BRCMU_CHAN_BW_20;
WARN_ON(primary_offset != 0);
break;
@@ -324,10 +323,6 @@
ch_inf.sb = BRCMU_CHAN_SB_LU;
}
break;
- case NL80211_CHAN_WIDTH_80P80:
- case NL80211_CHAN_WIDTH_160:
- case NL80211_CHAN_WIDTH_5:
- case NL80211_CHAN_WIDTH_10:
default:
WARN_ON_ONCE(1);
}
@@ -338,7 +333,6 @@
case IEEE80211_BAND_5GHZ:
ch_inf.band = BRCMU_CHAN_BAND_5G;
break;
- case IEEE80211_BAND_60GHZ:
default:
WARN_ON_ONCE(1);
}
@@ -520,95 +514,6 @@
ADDR_INDIRECT);
}
-static int brcmf_cfg80211_request_ap_if(struct brcmf_if *ifp)
-{
- struct brcmf_mbss_ssid_le mbss_ssid_le;
- int bsscfgidx;
- int err;
-
- memset(&mbss_ssid_le, 0, sizeof(mbss_ssid_le));
- bsscfgidx = brcmf_get_next_free_bsscfgidx(ifp->drvr);
- if (bsscfgidx < 0)
- return bsscfgidx;
-
- mbss_ssid_le.bsscfgidx = cpu_to_le32(bsscfgidx);
- mbss_ssid_le.SSID_len = cpu_to_le32(5);
- sprintf(mbss_ssid_le.SSID, "ssid%d" , bsscfgidx);
-
- err = brcmf_fil_bsscfg_data_set(ifp, "bsscfg:ssid", &mbss_ssid_le,
- sizeof(mbss_ssid_le));
- if (err < 0)
- brcmf_err("setting ssid failed %d\n", err);
-
- return err;
-}
-
-/**
- * brcmf_ap_add_vif() - create a new AP virtual interface for multiple BSS
- *
- * @wiphy: wiphy device of new interface.
- * @name: name of the new interface.
- * @flags: not used.
- * @params: contains mac address for AP device.
- */
-static
-struct wireless_dev *brcmf_ap_add_vif(struct wiphy *wiphy, const char *name,
- u32 *flags, struct vif_params *params)
-{
- struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
- struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
- struct brcmf_cfg80211_vif *vif;
- int err;
-
- if (brcmf_cfg80211_vif_event_armed(cfg))
- return ERR_PTR(-EBUSY);
-
- brcmf_dbg(INFO, "Adding vif \"%s\"\n", name);
-
- vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_AP, false);
- if (IS_ERR(vif))
- return (struct wireless_dev *)vif;
-
- brcmf_cfg80211_arm_vif_event(cfg, vif);
-
- err = brcmf_cfg80211_request_ap_if(ifp);
- if (err) {
- brcmf_cfg80211_arm_vif_event(cfg, NULL);
- goto fail;
- }
-
- /* wait for firmware event */
- err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_ADD,
- msecs_to_jiffies(1500));
- brcmf_cfg80211_arm_vif_event(cfg, NULL);
- if (!err) {
- brcmf_err("timeout occurred\n");
- err = -EIO;
- goto fail;
- }
-
- /* interface created in firmware */
- ifp = vif->ifp;
- if (!ifp) {
- brcmf_err("no if pointer provided\n");
- err = -ENOENT;
- goto fail;
- }
-
- strncpy(ifp->ndev->name, name, sizeof(ifp->ndev->name) - 1);
- err = brcmf_net_attach(ifp, true);
- if (err) {
- brcmf_err("Registering netdevice failed\n");
- goto fail;
- }
-
- return &ifp->vif->wdev;
-
-fail:
- brcmf_free_vif(vif);
- return ERR_PTR(err);
-}
-
static bool brcmf_is_apmode(struct brcmf_cfg80211_vif *vif)
{
enum nl80211_iftype iftype;
@@ -634,16 +539,12 @@
switch (type) {
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_STATION:
+ case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_MESH_POINT:
return ERR_PTR(-EOPNOTSUPP);
- case NL80211_IFTYPE_AP:
- wdev = brcmf_ap_add_vif(wiphy, name, flags, params);
- if (!IS_ERR(wdev))
- brcmf_cfg80211_update_proto_addr_mode(wdev);
- return wdev;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
case NL80211_IFTYPE_P2P_DEVICE:
@@ -1908,7 +1809,6 @@
return -EIO;
clear_bit(BRCMF_VIF_STATUS_CONNECTED, &ifp->vif->sme_state);
- clear_bit(BRCMF_VIF_STATUS_CONNECTING, &ifp->vif->sme_state);
cfg80211_disconnected(ndev, reason_code, NULL, 0, GFP_KERNEL);
memcpy(&scbval.ea, &profile->bssid, ETH_ALEN);
@@ -2879,44 +2779,6 @@
}
}
-static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
- u8 *pattern, u32 patternsize, u8 *mask,
- u32 packet_offset)
-{
- struct brcmf_fil_wowl_pattern_le *filter;
- u32 masksize;
- u32 patternoffset;
- u8 *buf;
- u32 bufsize;
- s32 ret;
-
- masksize = (patternsize + 7) / 8;
- patternoffset = sizeof(*filter) - sizeof(filter->cmd) + masksize;
-
- bufsize = sizeof(*filter) + patternsize + masksize;
- buf = kzalloc(bufsize, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- filter = (struct brcmf_fil_wowl_pattern_le *)buf;
-
- memcpy(filter->cmd, cmd, 4);
- filter->masksize = cpu_to_le32(masksize);
- filter->offset = cpu_to_le32(packet_offset);
- filter->patternoffset = cpu_to_le32(patternoffset);
- filter->patternsize = cpu_to_le32(patternsize);
- filter->type = cpu_to_le32(BRCMF_WOWL_PATTERN_TYPE_BITMAP);
-
- if ((mask) && (masksize))
- memcpy(buf + sizeof(*filter), mask, masksize);
- if ((pattern) && (patternsize))
- memcpy(buf + sizeof(*filter) + masksize, pattern, patternsize);
-
- ret = brcmf_fil_iovar_data_set(ifp, "wowl_pattern", buf, bufsize);
-
- kfree(buf);
- return ret;
-}
-
static s32 brcmf_cfg80211_resume(struct wiphy *wiphy)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
@@ -2926,11 +2788,10 @@
brcmf_dbg(TRACE, "Enter\n");
if (cfg->wowl_enabled) {
- brcmf_configure_arp_offload(ifp, true);
brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM,
cfg->pre_wowl_pmmode);
+ brcmf_fil_iovar_data_set(ifp, "wowl_pattern", "clr", 4);
brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0);
- brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0);
cfg->wowl_enabled = false;
}
return 0;
@@ -2941,29 +2802,21 @@
struct cfg80211_wowlan *wowl)
{
u32 wowl_config;
- u32 i;
brcmf_dbg(TRACE, "Suspend, wowl config.\n");
- brcmf_configure_arp_offload(ifp, false);
brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->pre_wowl_pmmode);
brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX);
wowl_config = 0;
if (wowl->disconnect)
- wowl_config = BRCMF_WOWL_DIS | BRCMF_WOWL_BCN | BRCMF_WOWL_RETR;
+ wowl_config |= WL_WOWL_DIS | WL_WOWL_BCN | WL_WOWL_RETR;
+ /* Note: if "wowl" target and not "wowlpf" then wowl_bcn_loss
+ * should be configured. This paramater is not supported by
+ * wowlpf.
+ */
if (wowl->magic_pkt)
- wowl_config |= BRCMF_WOWL_MAGIC;
- if ((wowl->patterns) && (wowl->n_patterns)) {
- wowl_config |= BRCMF_WOWL_NET;
- for (i = 0; i < wowl->n_patterns; i++) {
- brcmf_config_wowl_pattern(ifp, "add",
- (u8 *)wowl->patterns[i].pattern,
- wowl->patterns[i].pattern_len,
- (u8 *)wowl->patterns[i].mask,
- wowl->patterns[i].pkt_offset);
- }
- }
+ wowl_config |= WL_WOWL_MAGIC;
brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config);
brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1);
brcmf_bus_wowl_config(cfg->pub->bus_if, true);
@@ -3026,7 +2879,7 @@
struct brcmf_cfg80211_pmk_list *pmk_list, s32 err)
{
int i, j;
- u32 pmkid_len;
+ int pmkid_len;
pmkid_len = le32_to_cpu(pmk_list->pmkids.npmkid);
@@ -3054,7 +2907,8 @@
struct brcmf_if *ifp = netdev_priv(ndev);
struct pmkid_list *pmkids = &cfg->pmk_list->pmkids;
s32 err = 0;
- u32 pmkid_len, i;
+ int i;
+ int pmkid_len;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
@@ -3093,7 +2947,7 @@
struct brcmf_if *ifp = netdev_priv(ndev);
struct pmkid_list pmkid;
s32 err = 0;
- u32 pmkid_len, i;
+ int i, pmkid_len;
brcmf_dbg(TRACE, "Enter\n");
if (!check_vif_up(ifp->vif))
@@ -3454,10 +3308,11 @@
}
static s32
-brcmf_configure_wpaie(struct brcmf_if *ifp,
+brcmf_configure_wpaie(struct net_device *ndev,
const struct brcmf_vs_tlv *wpa_ie,
bool is_rsn_ie)
{
+ struct brcmf_if *ifp = netdev_priv(ndev);
u32 auth = 0; /* d11 open authentication */
u16 count;
s32 err = 0;
@@ -3932,7 +3787,6 @@
enum nl80211_iftype dev_role;
struct brcmf_fil_bss_enable_le bss_enable;
u16 chanspec;
- bool mbss;
brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
settings->chandef.chan->hw_value,
@@ -3943,7 +3797,6 @@
settings->inactivity_timeout);
dev_role = ifp->vif->wdev.iftype;
- mbss = ifp->vif->mbss;
memset(&ssid_le, 0, sizeof(ssid_le));
if (settings->ssid == NULL || settings->ssid_len == 0) {
@@ -3963,10 +3816,8 @@
ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len);
}
- if (!mbss) {
- brcmf_set_mpc(ifp, 0);
- brcmf_configure_arp_offload(ifp, false);
- }
+ brcmf_set_mpc(ifp, 0);
+ brcmf_configure_arp_offload(ifp, false);
/* find the RSN_IE */
rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail,
@@ -3980,16 +3831,13 @@
brcmf_dbg(TRACE, "WPA(2) IE is found\n");
if (wpa_ie != NULL) {
/* WPA IE */
- err = brcmf_configure_wpaie(ifp, wpa_ie, false);
+ err = brcmf_configure_wpaie(ndev, wpa_ie, false);
if (err < 0)
goto exit;
} else {
- struct brcmf_vs_tlv *tmp_ie;
-
- tmp_ie = (struct brcmf_vs_tlv *)rsn_ie;
-
/* RSN IE */
- err = brcmf_configure_wpaie(ifp, tmp_ie, true);
+ err = brcmf_configure_wpaie(ndev,
+ (struct brcmf_vs_tlv *)rsn_ie, true);
if (err < 0)
goto exit;
}
@@ -4000,53 +3848,45 @@
brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
- if (!mbss) {
- chanspec = chandef_to_chanspec(&cfg->d11inf,
- &settings->chandef);
- err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
+ chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);
+ err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
+ if (err < 0) {
+ brcmf_err("Set Channel failed: chspec=%d, %d\n", chanspec, err);
+ goto exit;
+ }
+
+ if (settings->beacon_interval) {
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
+ settings->beacon_interval);
if (err < 0) {
- brcmf_err("Set Channel failed: chspec=%d, %d\n",
- chanspec, err);
- goto exit;
- }
-
- if (settings->beacon_interval) {
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_BCNPRD,
- settings->beacon_interval);
- if (err < 0) {
- brcmf_err("Beacon Interval Set Error, %d\n",
- err);
- goto exit;
- }
- }
- if (settings->dtim_period) {
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
- settings->dtim_period);
- if (err < 0) {
- brcmf_err("DTIM Interval Set Error, %d\n", err);
- goto exit;
- }
- }
-
- if (dev_role == NL80211_IFTYPE_AP) {
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
- if (err < 0) {
- brcmf_err("BRCMF_C_DOWN error %d\n", err);
- goto exit;
- }
- brcmf_fil_iovar_int_set(ifp, "apsta", 0);
- }
-
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
- if (err < 0) {
- brcmf_err("SET INFRA error %d\n", err);
+ brcmf_err("Beacon Interval Set Error, %d\n", err);
goto exit;
}
}
- if (dev_role == NL80211_IFTYPE_AP) {
- if ((brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) && (!mbss))
- brcmf_fil_iovar_int_set(ifp, "mbss", 1);
+ if (settings->dtim_period) {
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_DTIMPRD,
+ settings->dtim_period);
+ if (err < 0) {
+ brcmf_err("DTIM Interval Set Error, %d\n", err);
+ goto exit;
+ }
+ }
+ if (dev_role == NL80211_IFTYPE_AP) {
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
+ if (err < 0) {
+ brcmf_err("BRCMF_C_DOWN error %d\n", err);
+ goto exit;
+ }
+ brcmf_fil_iovar_int_set(ifp, "apsta", 0);
+ }
+
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 1);
+ if (err < 0) {
+ brcmf_err("SET INFRA error %d\n", err);
+ goto exit;
+ }
+ if (dev_role == NL80211_IFTYPE_AP) {
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 1);
if (err < 0) {
brcmf_err("setting AP mode failed %d\n", err);
@@ -4091,7 +3931,7 @@
set_bit(BRCMF_VIF_STATUS_AP_CREATED, &ifp->vif->sme_state);
exit:
- if ((err) && (!mbss)) {
+ if (err) {
brcmf_set_mpc(ifp, 1);
brcmf_configure_arp_offload(ifp, true);
}
@@ -4112,31 +3952,20 @@
/* first to make sure they get processed by fw. */
msleep(400);
- if (ifp->vif->mbss) {
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
- return err;
- }
-
memset(&join_params, 0, sizeof(join_params));
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SET_SSID,
&join_params, sizeof(join_params));
if (err < 0)
brcmf_err("SET SSID error (%d)\n", err);
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_DOWN, 1);
+ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 0);
if (err < 0)
- brcmf_err("BRCMF_C_DOWN error %d\n", err);
+ brcmf_err("BRCMF_C_UP error %d\n", err);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_AP, 0);
if (err < 0)
brcmf_err("setting AP mode failed %d\n", err);
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_INFRA, 0);
if (err < 0)
brcmf_err("setting INFRA mode failed %d\n", err);
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS))
- brcmf_fil_iovar_int_set(ifp, "mbss", 0);
- /* Bring device back up so it can be used again */
- err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_UP, 1);
- if (err < 0)
- brcmf_err("BRCMF_C_UP error %d\n", err);
} else {
bss_enable.bsscfg_idx = cpu_to_le32(ifp->bssidx);
bss_enable.enable = cpu_to_le32(0);
@@ -4169,24 +3998,24 @@
static int
brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
- struct station_del_parameters *params)
+ const u8 *mac)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_scb_val_le scbval;
struct brcmf_if *ifp = netdev_priv(ndev);
s32 err;
- if (!params->mac)
+ if (!mac)
return -EFAULT;
- brcmf_dbg(TRACE, "Enter %pM\n", params->mac);
+ brcmf_dbg(TRACE, "Enter %pM\n", mac);
if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif)
ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp;
if (!check_vif_up(ifp->vif))
return -EIO;
- memcpy(&scbval.ea, params->mac, ETH_ALEN);
+ memcpy(&scbval.ea, mac, ETH_ALEN);
scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING);
err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON,
&scbval, sizeof(scbval));
@@ -4488,9 +4317,7 @@
enum nl80211_iftype type,
bool pm_block)
{
- struct brcmf_cfg80211_vif *vif_walk;
struct brcmf_cfg80211_vif *vif;
- bool mbss;
brcmf_dbg(TRACE, "allocating virtual interface (size=%zu)\n",
sizeof(*vif));
@@ -4506,17 +4333,6 @@
brcmf_init_prof(&vif->profile);
- if (type == NL80211_IFTYPE_AP) {
- mbss = false;
- list_for_each_entry(vif_walk, &cfg->vif_list, list) {
- if (vif_walk->wdev.iftype == NL80211_IFTYPE_AP) {
- mbss = true;
- break;
- }
- }
- vif->mbss = mbss;
- }
-
list_add_tail(&vif->list, &cfg->vif_list);
return vif;
}
@@ -4759,7 +4575,6 @@
struct net_device *ndev,
const struct brcmf_event_msg *e, void *data)
{
- struct brcmf_if *ifp = netdev_priv(ndev);
static int generation;
u32 event = e->event_code;
u32 reason = e->reason;
@@ -4770,8 +4585,6 @@
ndev != cfg_to_ndev(cfg)) {
brcmf_dbg(CONN, "AP mode link down\n");
complete(&cfg->vif_disabled);
- if (ifp->vif->mbss)
- brcmf_remove_interface(ifp->drvr, ifp->bssidx);
return 0;
}
@@ -5563,28 +5376,7 @@
return 0;
}
-static const struct ieee80211_iface_limit brcmf_iface_limits_mbss[] = {
- {
- .max = 1,
- .types = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC)
- },
- {
- .max = 4,
- .types = BIT(NL80211_IFTYPE_AP)
- },
- {
- .max = 1,
- .types = BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_P2P_GO)
- },
- {
- .max = 1,
- .types = BIT(NL80211_IFTYPE_P2P_DEVICE)
- }
-};
-
-static const struct ieee80211_iface_limit brcmf_iface_limits_sbss[] = {
+static const struct ieee80211_iface_limit brcmf_iface_limits[] = {
{
.max = 2,
.types = BIT(NL80211_IFTYPE_STATION) |
@@ -5605,8 +5397,8 @@
{
.max_interfaces = BRCMF_IFACE_MAX_CNT,
.num_different_channels = 1,
- .n_limits = ARRAY_SIZE(brcmf_iface_limits_sbss),
- .limits = brcmf_iface_limits_sbss,
+ .n_limits = ARRAY_SIZE(brcmf_iface_limits),
+ .limits = brcmf_iface_limits
}
};
@@ -5648,13 +5440,10 @@
wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
}
+
#ifdef CONFIG_PM
static const struct wiphy_wowlan_support brcmf_wowlan_support = {
.flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT,
- .n_patterns = BRCMF_WOWL_MAXPATTERNS,
- .pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE,
- .pattern_min_len = 1,
- .max_pkt_offset = 1500,
};
#endif
@@ -5682,10 +5471,6 @@
ifc_combo = brcmf_iface_combos[0];
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN))
ifc_combo.num_different_channels = 2;
- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS)) {
- ifc_combo.n_limits = ARRAY_SIZE(brcmf_iface_limits_mbss),
- ifc_combo.limits = brcmf_iface_limits_mbss;
- }
wiphy->iface_combinations = kmemdup(&ifc_combo,
sizeof(ifc_combo),
GFP_KERNEL);
@@ -5822,8 +5607,7 @@
return wdev->iftype;
}
-bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg,
- unsigned long state)
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state)
{
struct brcmf_cfg80211_vif *vif;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
similarity index 98%
rename from drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
rename to drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
index 9e98b8d..6abf94e 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h
@@ -14,8 +14,8 @@
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef BRCMFMAC_CFG80211_H
-#define BRCMFMAC_CFG80211_H
+#ifndef _wl_cfg80211_h_
+#define _wl_cfg80211_h_
/* for brcmu_d11inf */
#include <brcmu_d11.h>
@@ -183,7 +183,6 @@
* @pm_block: power-management blocked.
* @list: linked list.
* @mgmt_rx_reg: registered rx mgmt frame types.
- * @mbss: Multiple BSS type, set if not first AP (not relevant for P2P).
*/
struct brcmf_cfg80211_vif {
struct brcmf_if *ifp;
@@ -195,7 +194,6 @@
struct vif_saved_ie saved_ie;
struct list_head list;
u16 mgmt_rx_reg;
- bool mbss;
};
/* association inform */
@@ -482,8 +480,7 @@
brcmf_parse_tlvs(const void *buf, int buflen, uint key);
u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
struct ieee80211_channel *ch);
-bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg,
- unsigned long state);
+bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state);
void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg,
struct brcmf_cfg80211_vif *vif);
bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg);
@@ -496,4 +493,4 @@
void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg);
void brcmf_cfg80211_free_netdev(struct net_device *ndev);
-#endif /* BRCMFMAC_CFG80211_H */
+#endif /* _wl_cfg80211_h_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
index d382d94..323c9de 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
@@ -30,7 +30,6 @@
#include "main.h"
#include "debug.h"
#include "brcms_trace_events.h"
-#include "phy/phy_int.h"
static struct dentry *root_folder;
@@ -72,161 +71,48 @@
}
static
-int brcms_debugfs_hardware_read(struct seq_file *s, void *data)
+ssize_t brcms_debugfs_hardware_read(struct file *f, char __user *data,
+ size_t count, loff_t *ppos)
{
- struct brcms_pub *drvr = s->private;
- struct brcms_hardware *hw = drvr->wlc->hw;
- struct bcma_device *core = hw->d11core;
- struct bcma_bus *bus = core->bus;
- char boardrev[10];
+ char buf[128];
+ int res;
+ struct brcms_pub *drvr = f->private_data;
- seq_printf(s, "chipnum 0x%x\n"
- "chiprev 0x%x\n"
- "chippackage 0x%x\n"
- "corerev 0x%x\n"
- "boardid 0x%x\n"
- "boardvendor 0x%x\n"
- "boardrev %s\n"
- "boardflags 0x%x\n"
- "boardflags2 0x%x\n"
- "ucoderev 0x%x\n"
- "radiorev 0x%x\n"
- "phytype 0x%x\n"
- "phyrev 0x%x\n"
- "anarev 0x%x\n"
- "nvramrev %d\n",
- bus->chipinfo.id, bus->chipinfo.rev, bus->chipinfo.pkg,
- core->id.rev, bus->boardinfo.type, bus->boardinfo.vendor,
- brcmu_boardrev_str(hw->boardrev, boardrev),
- drvr->wlc->hw->boardflags, drvr->wlc->hw->boardflags2,
- drvr->wlc->ucode_rev, hw->band->radiorev,
- hw->band->phytype, hw->band->phyrev, hw->band->pi->ana_rev,
- hw->sromrev);
- return 0;
+ /* only allow read from start */
+ if (*ppos > 0)
+ return 0;
+
+ res = scnprintf(buf, sizeof(buf),
+ "board vendor: %x\n"
+ "board type: %x\n"
+ "board revision: %x\n"
+ "board flags: %x\n"
+ "board flags2: %x\n"
+ "firmware revision: %x\n",
+ drvr->wlc->hw->d11core->bus->boardinfo.vendor,
+ drvr->wlc->hw->d11core->bus->boardinfo.type,
+ drvr->wlc->hw->boardrev,
+ drvr->wlc->hw->boardflags,
+ drvr->wlc->hw->boardflags2,
+ drvr->wlc->ucode_rev
+ );
+
+ return simple_read_from_buffer(data, count, ppos, buf, res);
}
-static int brcms_debugfs_macstat_read(struct seq_file *s, void *data)
-{
- struct brcms_pub *drvr = s->private;
- struct brcms_info *wl = drvr->ieee_hw->priv;
- struct macstat stats;
- int i;
-
- spin_lock_bh(&wl->lock);
- stats = *(drvr->wlc->core->macstat_snapshot);
- spin_unlock_bh(&wl->lock);
-
- seq_printf(s, "txallfrm: %d\n", stats.txallfrm);
- seq_printf(s, "txrtsfrm: %d\n", stats.txrtsfrm);
- seq_printf(s, "txctsfrm: %d\n", stats.txctsfrm);
- seq_printf(s, "txackfrm: %d\n", stats.txackfrm);
- seq_printf(s, "txdnlfrm: %d\n", stats.txdnlfrm);
- seq_printf(s, "txbcnfrm: %d\n", stats.txbcnfrm);
- seq_printf(s, "txfunfl[8]:");
- for (i = 0; i < ARRAY_SIZE(stats.txfunfl); i++)
- seq_printf(s, " %d", stats.txfunfl[i]);
- seq_printf(s, "\ntxtplunfl: %d\n", stats.txtplunfl);
- seq_printf(s, "txphyerr: %d\n", stats.txphyerr);
- seq_printf(s, "pktengrxducast: %d\n", stats.pktengrxducast);
- seq_printf(s, "pktengrxdmcast: %d\n", stats.pktengrxdmcast);
- seq_printf(s, "rxfrmtoolong: %d\n", stats.rxfrmtoolong);
- seq_printf(s, "rxfrmtooshrt: %d\n", stats.rxfrmtooshrt);
- seq_printf(s, "rxinvmachdr: %d\n", stats.rxinvmachdr);
- seq_printf(s, "rxbadfcs: %d\n", stats.rxbadfcs);
- seq_printf(s, "rxbadplcp: %d\n", stats.rxbadplcp);
- seq_printf(s, "rxcrsglitch: %d\n", stats.rxcrsglitch);
- seq_printf(s, "rxstrt: %d\n", stats.rxstrt);
- seq_printf(s, "rxdfrmucastmbss: %d\n", stats.rxdfrmucastmbss);
- seq_printf(s, "rxmfrmucastmbss: %d\n", stats.rxmfrmucastmbss);
- seq_printf(s, "rxcfrmucast: %d\n", stats.rxcfrmucast);
- seq_printf(s, "rxrtsucast: %d\n", stats.rxrtsucast);
- seq_printf(s, "rxctsucast: %d\n", stats.rxctsucast);
- seq_printf(s, "rxackucast: %d\n", stats.rxackucast);
- seq_printf(s, "rxdfrmocast: %d\n", stats.rxdfrmocast);
- seq_printf(s, "rxmfrmocast: %d\n", stats.rxmfrmocast);
- seq_printf(s, "rxcfrmocast: %d\n", stats.rxcfrmocast);
- seq_printf(s, "rxrtsocast: %d\n", stats.rxrtsocast);
- seq_printf(s, "rxctsocast: %d\n", stats.rxctsocast);
- seq_printf(s, "rxdfrmmcast: %d\n", stats.rxdfrmmcast);
- seq_printf(s, "rxmfrmmcast: %d\n", stats.rxmfrmmcast);
- seq_printf(s, "rxcfrmmcast: %d\n", stats.rxcfrmmcast);
- seq_printf(s, "rxbeaconmbss: %d\n", stats.rxbeaconmbss);
- seq_printf(s, "rxdfrmucastobss: %d\n", stats.rxdfrmucastobss);
- seq_printf(s, "rxbeaconobss: %d\n", stats.rxbeaconobss);
- seq_printf(s, "rxrsptmout: %d\n", stats.rxrsptmout);
- seq_printf(s, "bcntxcancl: %d\n", stats.bcntxcancl);
- seq_printf(s, "rxf0ovfl: %d\n", stats.rxf0ovfl);
- seq_printf(s, "rxf1ovfl: %d\n", stats.rxf1ovfl);
- seq_printf(s, "rxf2ovfl: %d\n", stats.rxf2ovfl);
- seq_printf(s, "txsfovfl: %d\n", stats.txsfovfl);
- seq_printf(s, "pmqovfl: %d\n", stats.pmqovfl);
- seq_printf(s, "rxcgprqfrm: %d\n", stats.rxcgprqfrm);
- seq_printf(s, "rxcgprsqovfl: %d\n", stats.rxcgprsqovfl);
- seq_printf(s, "txcgprsfail: %d\n", stats.txcgprsfail);
- seq_printf(s, "txcgprssuc: %d\n", stats.txcgprssuc);
- seq_printf(s, "prs_timeout: %d\n", stats.prs_timeout);
- seq_printf(s, "rxnack: %d\n", stats.rxnack);
- seq_printf(s, "frmscons: %d\n", stats.frmscons);
- seq_printf(s, "txnack: %d\n", stats.txnack);
- seq_printf(s, "txglitch_nack: %d\n", stats.txglitch_nack);
- seq_printf(s, "txburst: %d\n", stats.txburst);
- seq_printf(s, "bphy_rxcrsglitch: %d\n", stats.bphy_rxcrsglitch);
- seq_printf(s, "phywatchdog: %d\n", stats.phywatchdog);
- seq_printf(s, "bphy_badplcp: %d\n", stats.bphy_badplcp);
- return 0;
-}
-
-struct brcms_debugfs_entry {
- int (*read)(struct seq_file *seq, void *data);
- struct brcms_pub *drvr;
-};
-
-static int brcms_debugfs_entry_open(struct inode *inode, struct file *f)
-{
- struct brcms_debugfs_entry *entry = inode->i_private;
-
- return single_open(f, entry->read, entry->drvr);
-}
-
-static const struct file_operations brcms_debugfs_def_ops = {
+static const struct file_operations brcms_debugfs_hardware_ops = {
.owner = THIS_MODULE,
- .open = brcms_debugfs_entry_open,
- .release = single_release,
- .read = seq_read,
- .llseek = seq_lseek
+ .open = simple_open,
+ .read = brcms_debugfs_hardware_read
};
-static int
-brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn,
- int (*read_fn)(struct seq_file *seq, void *data))
-{
- struct device *dev = &drvr->wlc->hw->d11core->dev;
- struct dentry *dentry = drvr->dbgfs_dir;
- struct brcms_debugfs_entry *entry;
-
- if (IS_ERR_OR_NULL(dentry))
- return -ENOENT;
-
- entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL);
- if (!entry)
- return -ENOMEM;
-
- entry->read = read_fn;
- entry->drvr = drvr;
-
- dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry,
- &brcms_debugfs_def_ops);
-
- return PTR_ERR_OR_ZERO(dentry);
-}
-
void brcms_debugfs_create_files(struct brcms_pub *drvr)
{
- if (IS_ERR_OR_NULL(drvr->dbgfs_dir))
- return;
+ struct dentry *dentry = drvr->dbgfs_dir;
- brcms_debugfs_add_entry(drvr, "hardware", brcms_debugfs_hardware_read);
- brcms_debugfs_add_entry(drvr, "macstat", brcms_debugfs_macstat_read);
+ if (!IS_ERR_OR_NULL(dentry))
+ debugfs_create_file("hardware", S_IRUGO, dentry,
+ drvr, &brcms_debugfs_hardware_ops);
}
#define __brcms_fn(fn) \
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index ac50a21..b6f5f95 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -764,9 +764,7 @@
return;
}
-static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw)
{
struct brcms_info *wl = hw->priv;
spin_lock_bh(&wl->lock);
@@ -775,8 +773,7 @@
return;
}
-static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw)
{
struct brcms_info *wl = hw->priv;
spin_lock_bh(&wl->lock);
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index eb8584a..1b47482 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -316,7 +316,7 @@
static const char * const fifo_names[] = {
"AC_BK", "AC_BE", "AC_VI", "AC_VO", "BCMC", "ATIM" };
#else
-static const char fifo_names[6][1];
+static const char fifo_names[6][0];
#endif
#ifdef DEBUG
@@ -445,18 +445,18 @@
kfree(wlc->protection);
kfree(wlc->stf);
kfree(wlc->bandstate[0]);
- if (wlc->corestate)
- kfree(wlc->corestate->macstat_snapshot);
+ kfree(wlc->corestate->macstat_snapshot);
kfree(wlc->corestate);
- if (wlc->hw)
- kfree(wlc->hw->bandstate[0]);
+ kfree(wlc->hw->bandstate[0]);
kfree(wlc->hw);
if (wlc->beacon)
dev_kfree_skb_any(wlc->beacon);
if (wlc->probe_resp)
dev_kfree_skb_any(wlc->probe_resp);
+ /* free the wlc */
kfree(wlc);
+ wlc = NULL;
}
static struct brcms_bss_cfg *brcms_c_bsscfg_malloc(uint unit)
@@ -1009,7 +1009,8 @@
if (txh)
trace_brcms_txdesc(&wlc->hw->d11core->dev, txh,
sizeof(*txh));
- brcmu_pkt_buf_free_skb(p);
+ if (p)
+ brcmu_pkt_buf_free_skb(p);
}
if (dma && queue < NFIFO) {
@@ -3080,7 +3081,7 @@
static void brcms_c_statsupd(struct brcms_c_info *wlc)
{
int i;
- struct macstat *macstats;
+ struct macstat macstats;
#ifdef DEBUG
u16 delta;
u16 rxf0ovfl;
@@ -3091,31 +3092,31 @@
if (!wlc->pub->up)
return;
- macstats = wlc->core->macstat_snapshot;
-
#ifdef DEBUG
/* save last rx fifo 0 overflow count */
- rxf0ovfl = macstats->rxf0ovfl;
+ rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl;
/* save last tx fifo underflow count */
for (i = 0; i < NFIFO; i++)
- txfunfl[i] = macstats->txfunfl[i];
+ txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i];
#endif /* DEBUG */
/* Read mac stats from contiguous shared memory */
- brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, macstats,
- sizeof(*macstats), OBJADDR_SHM_SEL);
+ brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats,
+ sizeof(struct macstat), OBJADDR_SHM_SEL);
#ifdef DEBUG
/* check for rx fifo 0 overflow */
- delta = (u16)(macstats->rxf0ovfl - rxf0ovfl);
+ delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl);
if (delta)
brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n",
wlc->pub->unit, delta);
/* check for tx fifo underflows */
for (i = 0; i < NFIFO; i++) {
- delta = macstats->txfunfl[i] - txfunfl[i];
+ delta =
+ (u16) (wlc->core->macstat_snapshot->txfunfl[i] -
+ txfunfl[i]);
if (delta)
brcms_err(wlc->hw->d11core,
"wl%d: %u tx fifo %d underflows!\n",
diff --git a/drivers/net/wireless/brcm80211/brcmutil/utils.c b/drivers/net/wireless/brcm80211/brcmutil/utils.c
index 906e89d..0f7e1c7 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/utils.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/utils.c
@@ -261,21 +261,6 @@
}
EXPORT_SYMBOL(brcmu_pktq_mdeq);
-/* Produce a human-readable string for boardrev */
-char *brcmu_boardrev_str(u32 brev, char *buf)
-{
- char c;
-
- if (brev < 0x100) {
- snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf);
- } else {
- c = (brev & 0xf000) == 0x1000 ? 'P' : 'A';
- snprintf(buf, 8, "%c%03x", c, brev & 0xfff);
- }
- return buf;
-}
-EXPORT_SYMBOL(brcmu_boardrev_str);
-
#if defined(DEBUG)
/* pretty hex print a pkt buffer chain */
void brcmu_prpkt(const char *msg, struct sk_buff *p0)
@@ -307,5 +292,4 @@
print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, data, size);
}
EXPORT_SYMBOL(brcmu_dbg_hex_dump);
-
#endif /* defined(DEBUG) */
diff --git a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
index 6996fcc..af26e0d 100644
--- a/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
+++ b/drivers/net/wireless/brcm80211/include/brcm_hw_ids.h
@@ -68,8 +68,6 @@
#define BRCM_PCIE_43567_DEVICE_ID 0x43d3
#define BRCM_PCIE_43570_DEVICE_ID 0x43d9
#define BRCM_PCIE_43602_DEVICE_ID 0x43ba
-#define BRCM_PCIE_43602_2G_DEVICE_ID 0x43bb
-#define BRCM_PCIE_43602_5G_DEVICE_ID 0x43bc
/* brcmsmac IDs */
#define BCM4313_D11N2G_ID 0x4727 /* 4313 802.11n 2.4G device */
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_utils.h b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
index a043e29..8ba445b 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_utils.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_utils.h
@@ -218,6 +218,4 @@
}
#endif
-char *brcmu_boardrev_str(u32 brev, char *buf);
-
#endif /* _BRCMU_UTILS_H_ */
diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c
index f2e276f..b2fb6c6 100644
--- a/drivers/net/wireless/cw1200/scan.c
+++ b/drivers/net/wireless/cw1200/scan.c
@@ -78,7 +78,7 @@
if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS)
return -EINVAL;
- frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0,
+ frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0,
req->ie_len);
if (!frame.skb)
return -ENOMEM;
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index d46df94..c2b7368 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -1363,7 +1363,7 @@
if (!priv->cmdlog)
return 0;
for (i = (priv->cmdlog_pos + 1) % priv->cmdlog_len;
- (i != priv->cmdlog_pos) && (len < PAGE_SIZE);
+ (i != priv->cmdlog_pos) && (PAGE_SIZE - len);
i = (i + 1) % priv->cmdlog_len) {
len +=
snprintf(buf + len, PAGE_SIZE - len,
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h
index fe9e438..e1fccda 100644
--- a/drivers/net/wireless/ipw2x00/libipw.h
+++ b/drivers/net/wireless/ipw2x00/libipw.h
@@ -654,6 +654,10 @@
/* TPC Report - mandatory if spctrm mgmt required */
struct libipw_tpc_report tpc_report;
+ /* IBSS DFS - mandatory if spctrm mgmt required and IBSS
+ * NOTE: This is variable length and so must be allocated dynamically */
+ struct libipw_ibss_dfs *ibss_dfs;
+
/* Channel Switch Announcement - optional if spctrm mgmt required */
struct libipw_csa csa;
@@ -966,6 +970,7 @@
/* make sure to set stats->len */
void libipw_rx_mgt(struct libipw_device *ieee, struct libipw_hdr_4addr *header,
struct libipw_rx_stats *stats);
+void libipw_network_reset(struct libipw_network *network);
/* libipw_geo.c */
const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee);
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c
index 1d1a28a..92a935f 100644
--- a/drivers/net/wireless/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/ipw2x00/libipw_module.c
@@ -84,12 +84,25 @@
return 0;
}
+void libipw_network_reset(struct libipw_network *network)
+{
+ if (!network)
+ return;
+
+ if (network->ibss_dfs) {
+ kfree(network->ibss_dfs);
+ network->ibss_dfs = NULL;
+ }
+}
+
static inline void libipw_networks_free(struct libipw_device *ieee)
{
int i;
- for (i = 0; i < MAX_NETWORK_COUNT; i++)
+ for (i = 0; i < MAX_NETWORK_COUNT; i++) {
+ kfree(ieee->networks[i]->ibss_dfs);
kfree(ieee->networks[i]);
+ }
}
void libipw_networks_age(struct libipw_device *ieee,
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c
index 3e4d83c..651a1ee 100644
--- a/drivers/net/wireless/ipw2x00/libipw_rx.c
+++ b/drivers/net/wireless/ipw2x00/libipw_rx.c
@@ -1298,6 +1298,13 @@
break;
case WLAN_EID_IBSS_DFS:
+ if (network->ibss_dfs)
+ break;
+ network->ibss_dfs = kmemdup(info_element->data,
+ info_element->len,
+ GFP_ATOMIC);
+ if (!network->ibss_dfs)
+ return 1;
network->flags |= NETWORK_HAS_IBSS_DFS;
break;
@@ -1328,7 +1335,9 @@
static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_assoc_response
*frame, struct libipw_rx_stats *stats)
{
- struct libipw_network network_resp = { };
+ struct libipw_network network_resp = {
+ .ibss_dfs = NULL,
+ };
struct libipw_network *network = &network_resp;
struct net_device *dev = ieee->dev;
@@ -1463,6 +1472,9 @@
int qos_active;
u8 old_param;
+ libipw_network_reset(dst);
+ dst->ibss_dfs = src->ibss_dfs;
+
/* We only update the statistics if they were created by receiving
* the network information on the actual channel the network is on.
*
@@ -1536,7 +1548,9 @@
*stats)
{
struct net_device *dev = ieee->dev;
- struct libipw_network network = { };
+ struct libipw_network network = {
+ .ibss_dfs = NULL,
+ };
struct libipw_network *target;
struct libipw_network *oldest = NULL;
#ifdef CPTCFG_LIBIPW_DEBUG
@@ -1604,6 +1618,7 @@
LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n",
target->ssid_len, target->ssid,
target->bssid);
+ libipw_network_reset(target);
} else {
/* Otherwise just pull from the free list */
target = list_entry(ieee->network_free_list.next,
@@ -1619,6 +1634,7 @@
"BEACON" : "PROBE RESPONSE");
#endif
memcpy(target, &network, sizeof(*target));
+ network.ibss_dfs = NULL;
list_add_tail(&target->list, &ieee->network_list);
} else {
LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n",
@@ -1627,6 +1643,7 @@
is_beacon(beacon->header.frame_ctl) ?
"BEACON" : "PROBE RESPONSE");
update_network(target, &network);
+ network.ibss_dfs = NULL;
}
spin_unlock_irqrestore(&ieee->lock, flags);
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index cb90853..6c9cbb8 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -6063,7 +6063,7 @@
}
void
-il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+il4965_mac_channel_switch(struct ieee80211_hw *hw,
struct ieee80211_channel_switch *ch_switch)
{
struct il_priv *il = hw->priv;
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h
index db04ecf..a96696e 100644
--- a/drivers/net/wireless/iwlegacy/4965.h
+++ b/drivers/net/wireless/iwlegacy/4965.h
@@ -187,9 +187,8 @@
u8 buf_size);
int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
-void
-il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *ch_switch);
+void il4965_mac_channel_switch(struct ieee80211_hw *hw,
+ struct ieee80211_channel_switch *ch_switch);
void il4965_led_enable(struct il_priv *il);
diff --git a/drivers/net/wireless/iwlegacy/Kconfig b/drivers/net/wireless/iwlegacy/Kconfig
index cdc6baf..05d8fc7 100644
--- a/drivers/net/wireless/iwlegacy/Kconfig
+++ b/drivers/net/wireless/iwlegacy/Kconfig
@@ -2,9 +2,9 @@
tristate
depends on m
depends on FW_LOADER
- select BPAUTO_NEW_LEDS
- select BPAUTO_LEDS_CLASS
- select BPAUTO_LEDS_TRIGGERS
+ select BACKPORT_NEW_LEDS
+ select BACKPORT_LEDS_CLASS
+ select BACKPORT_LEDS_TRIGGERS
select MAC80211_LEDS
config IWL4965
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 63f153b..3721c07 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -46,7 +46,7 @@
config IWLWIFI_LEDS
bool
depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
- select BPAUTO_LEDS_TRIGGERS
+ select BACKPORT_LEDS_TRIGGERS
select MAC80211_LEDS
default y
@@ -62,7 +62,6 @@
config IWLMVM
tristate "Intel Wireless WiFi MVM Firmware support"
depends on m
- select BPAUTO_WANT_DEV_COREDUMP
help
This is the driver that supports the MVM firmware which is
currently only available for 7260 and 3160 devices.
diff --git a/drivers/net/wireless/iwlwifi/dvm/commands.h b/drivers/net/wireless/iwlwifi/dvm/commands.h
index 7a34e4d..751ae1d 100644
--- a/drivers/net/wireless/iwlwifi/dvm/commands.h
+++ b/drivers/net/wireless/iwlwifi/dvm/commands.h
@@ -966,21 +966,21 @@
/* WiFi queues mask */
-#define IWL_SCD_BK_MSK BIT(0)
-#define IWL_SCD_BE_MSK BIT(1)
-#define IWL_SCD_VI_MSK BIT(2)
-#define IWL_SCD_VO_MSK BIT(3)
-#define IWL_SCD_MGMT_MSK BIT(3)
+#define IWL_SCD_BK_MSK cpu_to_le32(BIT(0))
+#define IWL_SCD_BE_MSK cpu_to_le32(BIT(1))
+#define IWL_SCD_VI_MSK cpu_to_le32(BIT(2))
+#define IWL_SCD_VO_MSK cpu_to_le32(BIT(3))
+#define IWL_SCD_MGMT_MSK cpu_to_le32(BIT(3))
/* PAN queues mask */
-#define IWL_PAN_SCD_BK_MSK BIT(4)
-#define IWL_PAN_SCD_BE_MSK BIT(5)
-#define IWL_PAN_SCD_VI_MSK BIT(6)
-#define IWL_PAN_SCD_VO_MSK BIT(7)
-#define IWL_PAN_SCD_MGMT_MSK BIT(7)
-#define IWL_PAN_SCD_MULTICAST_MSK BIT(8)
+#define IWL_PAN_SCD_BK_MSK cpu_to_le32(BIT(4))
+#define IWL_PAN_SCD_BE_MSK cpu_to_le32(BIT(5))
+#define IWL_PAN_SCD_VI_MSK cpu_to_le32(BIT(6))
+#define IWL_PAN_SCD_VO_MSK cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MGMT_MSK cpu_to_le32(BIT(7))
+#define IWL_PAN_SCD_MULTICAST_MSK cpu_to_le32(BIT(8))
-#define IWL_AGG_TX_QUEUE_MSK 0xffc00
+#define IWL_AGG_TX_QUEUE_MSK cpu_to_le32(0xffc00)
#define IWL_DROP_ALL BIT(1)
@@ -1005,17 +1005,12 @@
* 1: Dump multiple MSDU according to PS, INVALID STA, TTL, TID disable.
* 2: Dump all FIFO
*/
-struct iwl_txfifo_flush_cmd_v3 {
+struct iwl_txfifo_flush_cmd {
__le32 queue_control;
__le16 flush_control;
__le16 reserved;
} __packed;
-struct iwl_txfifo_flush_cmd_v2 {
- __le16 queue_control;
- __le16 flush_control;
-} __packed;
-
/*
* REPLY_WEP_KEY = 0x20
*/
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index 1d2223d..2191621 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -137,38 +137,37 @@
*/
int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk)
{
- struct iwl_txfifo_flush_cmd_v3 flush_cmd_v3 = {
- .flush_control = cpu_to_le16(IWL_DROP_ALL),
- };
- struct iwl_txfifo_flush_cmd_v2 flush_cmd_v2 = {
- .flush_control = cpu_to_le16(IWL_DROP_ALL),
+ struct iwl_txfifo_flush_cmd flush_cmd;
+ struct iwl_host_cmd cmd = {
+ .id = REPLY_TXFIFO_FLUSH,
+ .len = { sizeof(struct iwl_txfifo_flush_cmd), },
+ .data = { &flush_cmd, },
};
- u32 queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
- IWL_SCD_BE_MSK | IWL_SCD_BK_MSK | IWL_SCD_MGMT_MSK;
+ memset(&flush_cmd, 0, sizeof(flush_cmd));
+ flush_cmd.queue_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
+ IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
+ IWL_SCD_MGMT_MSK;
if ((priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
- queue_control |= IWL_PAN_SCD_VO_MSK | IWL_PAN_SCD_VI_MSK |
- IWL_PAN_SCD_BE_MSK | IWL_PAN_SCD_BK_MSK |
- IWL_PAN_SCD_MGMT_MSK |
- IWL_PAN_SCD_MULTICAST_MSK;
+ flush_cmd.queue_control |= IWL_PAN_SCD_VO_MSK |
+ IWL_PAN_SCD_VI_MSK |
+ IWL_PAN_SCD_BE_MSK |
+ IWL_PAN_SCD_BK_MSK |
+ IWL_PAN_SCD_MGMT_MSK |
+ IWL_PAN_SCD_MULTICAST_MSK;
if (priv->nvm_data->sku_cap_11n_enable)
- queue_control |= IWL_AGG_TX_QUEUE_MSK;
+ flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK;
if (scd_q_msk)
- queue_control = scd_q_msk;
+ flush_cmd.queue_control = cpu_to_le32(scd_q_msk);
- IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", queue_control);
- flush_cmd_v3.queue_control = cpu_to_le32(queue_control);
- flush_cmd_v2.queue_control = cpu_to_le16((u16)queue_control);
+ IWL_DEBUG_INFO(priv, "queue control: 0x%x\n",
+ flush_cmd.queue_control);
+ flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL);
- if (IWL_UCODE_API(priv->fw->ucode_ver) > 2)
- return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
- sizeof(flush_cmd_v3),
- &flush_cmd_v3);
- return iwl_dvm_send_cmd_pdu(priv, REPLY_TXFIFO_FLUSH, 0,
- sizeof(flush_cmd_v2), &flush_cmd_v2);
+ return iwl_dvm_send_cmd(priv, &cmd);
}
void iwlagn_dev_txfifo_flush(struct iwl_priv *priv)
@@ -419,8 +418,8 @@
static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg)
{
- return (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
- BT_UART_MSG_FRAME3SCOESCO_POS;
+ return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >>
+ BT_UART_MSG_FRAME3SCOESCO_POS;
}
static void iwlagn_bt_traffic_change_work(struct work_struct *work)
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index dfa0626..d8ebc7e 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -941,7 +941,6 @@
}
static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
struct ieee80211_channel_switch *ch_switch)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
@@ -1096,7 +1095,6 @@
u32 queues, bool drop)
{
struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw);
- u32 scd_queues;
mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "enter\n");
@@ -1110,19 +1108,18 @@
goto done;
}
- scd_queues = BIT(priv->cfg->base_params->num_of_queues) - 1;
- scd_queues &= ~(BIT(IWL_IPAN_CMD_QUEUE_NUM) |
- BIT(IWL_DEFAULT_CMD_QUEUE_NUM));
-
- if (vif)
- scd_queues &= ~BIT(vif->hw_queue[IEEE80211_AC_VO]);
-
- IWL_DEBUG_TX_QUEUES(priv, "Flushing SCD queues: 0x%x\n", scd_queues);
- if (iwlagn_txfifo_flush(priv, scd_queues)) {
- IWL_ERR(priv, "flush request fail\n");
- goto done;
+ /*
+ * mac80211 will not push any more frames for transmit
+ * until the flush is completed
+ */
+ if (drop) {
+ IWL_DEBUG_MAC80211(priv, "send flush command\n");
+ if (iwlagn_txfifo_flush(priv, 0)) {
+ IWL_ERR(priv, "flush request fail\n");
+ goto done;
+ }
}
- IWL_DEBUG_TX_QUEUES(priv, "wait transmit/flush all frames\n");
+ IWL_DEBUG_MAC80211(priv, "wait transmit/flush all frames\n");
iwl_trans_wait_tx_queue_empty(priv->trans, 0xffffffff);
done:
mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index e5be2d2..b04b885 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -73,12 +73,12 @@
#define IWL3160_UCODE_API_MAX 10
/* Oldest version we won't warn about */
-#define IWL7260_UCODE_API_OK 10
-#define IWL3160_UCODE_API_OK 10
+#define IWL7260_UCODE_API_OK 9
+#define IWL3160_UCODE_API_OK 9
/* Lowest firmware API version supported */
-#define IWL7260_UCODE_API_MIN 9
-#define IWL3160_UCODE_API_MIN 9
+#define IWL7260_UCODE_API_MIN 8
+#define IWL3160_UCODE_API_MIN 8
/* NVM versions */
#define IWL7260_NVM_VERSION 0x0a1d
@@ -89,8 +89,6 @@
#define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL7265_NVM_VERSION 0x0a1d
#define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */
-#define IWL7265D_NVM_VERSION 0x0c11
-#define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL7260_FW_PRE "iwlwifi-7260-"
#define IWL7260_MODULE_FIRMWARE(api) IWL7260_FW_PRE __stringify(api) ".ucode"
@@ -104,9 +102,6 @@
#define IWL7265_FW_PRE "iwlwifi-7265-"
#define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
-#define IWL7265D_FW_PRE "iwlwifi-7265D-"
-#define IWL7265D_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode"
-
#define NVM_HW_SECTION_NUM_FAMILY_7000 0
static const struct iwl_base_params iwl7000_base_params = {
@@ -137,8 +132,8 @@
.base_params = &iwl7000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_7000, \
- .non_shared_ant = ANT_A, \
- .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K
+ .non_shared_ant = ANT_A
+
const struct iwl_cfg iwl7260_2ac_cfg = {
.name = "Intel(R) Dual Band Wireless AC 7260",
@@ -272,38 +267,7 @@
.pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
};
-const struct iwl_cfg iwl7265d_2ac_cfg = {
- .name = "Intel(R) Dual Band Wireless AC 7265",
- .fw_name_pre = IWL7265D_FW_PRE,
- IWL_DEVICE_7000,
- .ht_params = &iwl7265_ht_params,
- .nvm_ver = IWL7265D_NVM_VERSION,
- .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
- .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
-};
-
-const struct iwl_cfg iwl7265d_2n_cfg = {
- .name = "Intel(R) Dual Band Wireless N 7265",
- .fw_name_pre = IWL7265D_FW_PRE,
- IWL_DEVICE_7000,
- .ht_params = &iwl7265_ht_params,
- .nvm_ver = IWL7265D_NVM_VERSION,
- .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
- .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
-};
-
-const struct iwl_cfg iwl7265d_n_cfg = {
- .name = "Intel(R) Wireless N 7265",
- .fw_name_pre = IWL7265D_FW_PRE,
- IWL_DEVICE_7000,
- .ht_params = &iwl7265_ht_params,
- .nvm_ver = IWL7265D_NVM_VERSION,
- .nvm_calib_ver = IWL7265_TX_POWER_VERSION,
- .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs,
-};
-
MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
MODULE_FIRMWARE(IWL3165_MODULE_FIRMWARE(IWL3160_UCODE_API_OK));
MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
-MODULE_FIRMWARE(IWL7265D_MODULE_FIRMWARE(IWL7260_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
index bf0a95c..e435148 100644
--- a/drivers/net/wireless/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -72,18 +72,17 @@
#define IWL8000_UCODE_API_MAX 10
/* Oldest version we won't warn about */
-#define IWL8000_UCODE_API_OK 10
+#define IWL8000_UCODE_API_OK 8
/* Lowest firmware API version supported */
-#define IWL8000_UCODE_API_MIN 9
+#define IWL8000_UCODE_API_MIN 8
/* NVM versions */
#define IWL8000_NVM_VERSION 0x0a1d
#define IWL8000_TX_POWER_VERSION 0xffff /* meaningless */
#define IWL8000_FW_PRE "iwlwifi-8000"
-#define IWL8000_MODULE_FIRMWARE(api) \
- IWL8000_FW_PRE "-" __stringify(api) ".ucode"
+#define IWL8000_MODULE_FIRMWARE(api) IWL8000_FW_PRE __stringify(api) ".ucode"
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
@@ -91,10 +90,6 @@
/* Max SDIO RX aggregation size of the ADDBA request/response */
#define MAX_RX_AGG_SIZE_8260_SDIO 28
-/* Max A-MPDU exponent for HT and VHT */
-#define MAX_HT_AMPDU_EXPONENT_8260_SDIO IEEE80211_HT_MAX_AMPDU_32K
-#define MAX_VHT_AMPDU_EXPONENT_8260_SDIO IEEE80211_VHT_MAX_AMPDU_32K
-
static const struct iwl_base_params iwl8000_base_params = {
.eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
.num_of_queues = IWLAGN_NUM_QUEUES,
@@ -108,7 +103,6 @@
};
static const struct iwl_ht_params iwl8000_ht_params = {
- .stbc = true,
.ldpc = true,
.ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ),
};
@@ -123,7 +117,6 @@
.base_params = &iwl8000_base_params, \
.led_mode = IWL_LED_RF_STATE, \
.nvm_hw_section_num = NVM_HW_SECTION_NUM_FAMILY_8000, \
- .d0i3 = true, \
.non_shared_ant = ANT_A
const struct iwl_cfg iwl8260_2n_cfg = {
@@ -142,7 +135,6 @@
.ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
- .max_ht_ampdu_exponent = IEEE80211_HT_MAX_AMPDU_64K,
};
const struct iwl_cfg iwl8260_2ac_sdio_cfg = {
@@ -155,23 +147,6 @@
.default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
.max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
.disable_dummy_notification = true,
- .max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
- .max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO,
-};
-
-const struct iwl_cfg iwl4165_2ac_sdio_cfg = {
- .name = "Intel(R) Dual Band Wireless-AC 4165",
- .fw_name_pre = IWL8000_FW_PRE,
- IWL_DEVICE_8000,
- .ht_params = &iwl8000_ht_params,
- .nvm_ver = IWL8000_NVM_VERSION,
- .nvm_calib_ver = IWL8000_TX_POWER_VERSION,
- .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
- .max_rx_agg_size = MAX_RX_AGG_SIZE_8260_SDIO,
- .bt_shared_single_ant = true,
- .disable_dummy_notification = true,
- .max_ht_ampdu_exponent = MAX_HT_AMPDU_EXPONENT_8260_SDIO,
- .max_vht_ampdu_exponent = MAX_VHT_AMPDU_EXPONENT_8260_SDIO,
};
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index ab079ff..6926711 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -87,16 +87,6 @@
IWL_DEVICE_FAMILY_8000,
};
-static inline bool iwl_has_secure_boot(u32 hw_rev,
- enum iwl_device_family family)
-{
- /* return 1 only for family 8000 B0 */
- if ((family == IWL_DEVICE_FAMILY_8000) && (hw_rev & 0xC))
- return 1;
-
- return 0;
-}
-
/*
* LED mode
* IWL_LED_DEFAULT: use device default
@@ -256,11 +246,6 @@
* @nvm_hw_section_num: the ID of the HW NVM section
* @pwr_tx_backoffs: translation table between power limits and backoffs
* @max_rx_agg_size: max RX aggregation size of the ADDBA request/response
- * @max_tx_agg_size: max TX aggregation size of the ADDBA request/response
- * @max_ht_ampdu_factor: the exponent of the max length of A-MPDU that the
- * station can receive in HT
- * @max_vht_ampdu_exponent: the exponent of the max length of A-MPDU that the
- * station can receive in VHT
*
* We enable the driver to be backward compatible wrt. hardware features.
* API differences in uCode shouldn't be handled here but through TLVs
@@ -300,9 +285,6 @@
const char *default_nvm_file;
unsigned int max_rx_agg_size;
bool disable_dummy_notification;
- unsigned int max_tx_agg_size;
- unsigned int max_ht_ampdu_exponent;
- unsigned int max_vht_ampdu_exponent;
};
/*
@@ -364,14 +346,9 @@
extern const struct iwl_cfg iwl7265_2ac_cfg;
extern const struct iwl_cfg iwl7265_2n_cfg;
extern const struct iwl_cfg iwl7265_n_cfg;
-extern const struct iwl_cfg iwl7265d_2ac_cfg;
-extern const struct iwl_cfg iwl7265d_2n_cfg;
-extern const struct iwl_cfg iwl7265d_n_cfg;
extern const struct iwl_cfg iwl8260_2n_cfg;
extern const struct iwl_cfg iwl8260_2ac_cfg;
extern const struct iwl_cfg iwl8260_2ac_sdio_cfg;
-extern const struct iwl_cfg iwl4265_2ac_sdio_cfg;
-extern const struct iwl_cfg iwl4165_2ac_sdio_cfg;
#endif /* CPTCFG_IWLMVM */
#endif /* __IWL_CONFIG_H__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h
index aff63c3..3f6f015 100644
--- a/drivers/net/wireless/iwlwifi/iwl-csr.h
+++ b/drivers/net/wireless/iwlwifi/iwl-csr.h
@@ -129,8 +129,6 @@
#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c)
#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060)
-#define CSR_MBOX_SET_REG (CSR_BASE + 0x88)
-
#define CSR_LED_REG (CSR_BASE+0x094)
#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0)
#define CSR_MAC_SHADOW_REG_CTRL (CSR_BASE+0x0A8) /* 6000 and up */
@@ -186,8 +184,6 @@
#define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) /* WAKE_ME */
#define CSR_HW_IF_CONFIG_REG_PERSIST_MODE (0x40000000) /* PERSISTENCE */
-#define CSR_MBOX_SET_REG_OS_ALIVE BIT(5)
-
#define CSR_INT_PERIODIC_DIS (0x00) /* disable periodic int*/
#define CSR_INT_PERIODIC_ENA (0xFF) /* 255*32 usec ~ 8 msec*/
@@ -309,24 +305,23 @@
};
-#define CSR_HW_REV_TYPE_MSK (0x000FFF0)
-#define CSR_HW_REV_TYPE_5300 (0x0000020)
-#define CSR_HW_REV_TYPE_5350 (0x0000030)
-#define CSR_HW_REV_TYPE_5100 (0x0000050)
-#define CSR_HW_REV_TYPE_5150 (0x0000040)
-#define CSR_HW_REV_TYPE_1000 (0x0000060)
-#define CSR_HW_REV_TYPE_6x00 (0x0000070)
-#define CSR_HW_REV_TYPE_6x50 (0x0000080)
-#define CSR_HW_REV_TYPE_6150 (0x0000084)
-#define CSR_HW_REV_TYPE_6x05 (0x00000B0)
-#define CSR_HW_REV_TYPE_6x30 CSR_HW_REV_TYPE_6x05
-#define CSR_HW_REV_TYPE_6x35 CSR_HW_REV_TYPE_6x05
-#define CSR_HW_REV_TYPE_2x30 (0x00000C0)
-#define CSR_HW_REV_TYPE_2x00 (0x0000100)
-#define CSR_HW_REV_TYPE_105 (0x0000110)
-#define CSR_HW_REV_TYPE_135 (0x0000120)
-#define CSR_HW_REV_TYPE_7265D (0x0000210)
-#define CSR_HW_REV_TYPE_NONE (0x00001F0)
+#define CSR_HW_REV_TYPE_MSK (0x000FFF0)
+#define CSR_HW_REV_TYPE_5300 (0x0000020)
+#define CSR_HW_REV_TYPE_5350 (0x0000030)
+#define CSR_HW_REV_TYPE_5100 (0x0000050)
+#define CSR_HW_REV_TYPE_5150 (0x0000040)
+#define CSR_HW_REV_TYPE_1000 (0x0000060)
+#define CSR_HW_REV_TYPE_6x00 (0x0000070)
+#define CSR_HW_REV_TYPE_6x50 (0x0000080)
+#define CSR_HW_REV_TYPE_6150 (0x0000084)
+#define CSR_HW_REV_TYPE_6x05 (0x00000B0)
+#define CSR_HW_REV_TYPE_6x30 CSR_HW_REV_TYPE_6x05
+#define CSR_HW_REV_TYPE_6x35 CSR_HW_REV_TYPE_6x05
+#define CSR_HW_REV_TYPE_2x30 (0x00000C0)
+#define CSR_HW_REV_TYPE_2x00 (0x0000100)
+#define CSR_HW_REV_TYPE_105 (0x0000110)
+#define CSR_HW_REV_TYPE_135 (0x0000120)
+#define CSR_HW_REV_TYPE_NONE (0x00001F0)
/* EEPROM REG */
#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001)
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 68b126b..2eb2346 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -143,7 +143,7 @@
#define IWL_DL_INFO 0x00000001
#define IWL_DL_MAC80211 0x00000002
#define IWL_DL_HCMD 0x00000004
-#define IWL_DL_TDLS 0x00000008
+#define IWL_DL_STATE 0x00000008
/* 0x000000F0 - 0x00000010 */
#define IWL_DL_QUOTA 0x00000010
#define IWL_DL_TE 0x00000020
@@ -180,7 +180,6 @@
#define IWL_DL_TX_QUEUES 0x80000000
#define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a)
-#define IWL_DEBUG_TDLS(p, f, a...) IWL_DEBUG(p, IWL_DL_TDLS, f, ## a)
#define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a)
#define IWL_DEBUG_EXTERNAL(p, f, a...) IWL_DEBUG(p, IWL_DL_EXTERNAL, f, ## a)
#define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a)
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 4322c55..5e8d279 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -78,6 +78,9 @@
#include "iwl-config.h"
#include "iwl-modparams.h"
+/* private includes */
+#include "iwl-fw-file.h"
+
/******************************************************************************
*
* module boiler plate
@@ -184,11 +187,6 @@
static void iwl_dealloc_ucode(struct iwl_drv *drv)
{
int i;
-
- kfree(drv->fw.dbg_dest_tlv);
- for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++)
- kfree(drv->fw.dbg_conf_tlv[i]);
-
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
iwl_free_fw_img(drv, drv->fw.img + i);
}
@@ -250,9 +248,6 @@
/*
* Starting 8000B - FW name format has changed. This overwrites the
* previous name and uses the new format.
- *
- * TODO:
- * Once there is only one supported step for 8000 family - delete this!
*/
if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) {
char rev_step[2] = {
@@ -263,13 +258,6 @@
if (CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP)
rev_step[0] = 0;
- /*
- * If hw_rev wasn't set yet - default as B-step. If it IS A-step
- * we'll reload that FW later instead.
- */
- if (drv->trans->hw_rev == 0)
- rev_step[0] = 'B';
-
snprintf(drv->firmware_name, sizeof(drv->firmware_name),
"%s%s-%s.ucode", name_pre, rev_step, tag);
}
@@ -313,11 +301,6 @@
u32 init_evtlog_ptr, init_evtlog_size, init_errlog_ptr;
u32 inst_evtlog_ptr, inst_evtlog_size, inst_errlog_ptr;
-
- /* FW debug data parsed for driver usage */
- struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
- struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
- size_t dbg_conf_tlv_len[FW_DBG_MAX];
};
/*
@@ -591,8 +574,6 @@
char buildstr[25];
u32 build;
int num_of_cpus;
- bool usniffer_images = false;
- bool usniffer_req = false;
if (len < sizeof(*ucode)) {
IWL_ERR(drv, "uCode has invalid length: %zd\n", len);
@@ -826,16 +807,19 @@
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR,
tlv_len);
drv->fw.mvm_fw = true;
+ drv->fw.img[IWL_UCODE_REGULAR].is_secure = true;
break;
case IWL_UCODE_TLV_SECURE_SEC_INIT:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT,
tlv_len);
drv->fw.mvm_fw = true;
+ drv->fw.img[IWL_UCODE_INIT].is_secure = true;
break;
case IWL_UCODE_TLV_SECURE_SEC_WOWLAN:
iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN,
tlv_len);
drv->fw.mvm_fw = true;
+ drv->fw.img[IWL_UCODE_WOWLAN].is_secure = true;
break;
case IWL_UCODE_TLV_NUM_OF_CPU:
if (tlv_len != sizeof(u32))
@@ -865,79 +849,12 @@
capa->n_scan_channels =
le32_to_cpup((__le32 *)tlv_data);
break;
- case IWL_UCODE_TLV_FW_DBG_DEST: {
- struct iwl_fw_dbg_dest_tlv *dest = (void *)tlv_data;
-
- if (pieces->dbg_dest_tlv) {
- IWL_ERR(drv,
- "dbg destination ignored, already exists\n");
- break;
- }
-
- pieces->dbg_dest_tlv = dest;
- IWL_INFO(drv, "Found debug destination: %s\n",
- get_fw_dbg_mode_string(dest->monitor_mode));
-
- drv->fw.dbg_dest_reg_num =
- tlv_len - offsetof(struct iwl_fw_dbg_dest_tlv,
- reg_ops);
- drv->fw.dbg_dest_reg_num /=
- sizeof(drv->fw.dbg_dest_tlv->reg_ops[0]);
-
- break;
- }
- case IWL_UCODE_TLV_FW_DBG_CONF: {
- struct iwl_fw_dbg_conf_tlv *conf = (void *)tlv_data;
-
- if (!pieces->dbg_dest_tlv) {
- IWL_ERR(drv,
- "Ignore dbg config %d - no destination configured\n",
- conf->id);
- break;
- }
-
- if (conf->id >= ARRAY_SIZE(drv->fw.dbg_conf_tlv)) {
- IWL_ERR(drv,
- "Skip unknown configuration: %d\n",
- conf->id);
- break;
- }
-
- if (pieces->dbg_conf_tlv[conf->id]) {
- IWL_ERR(drv,
- "Ignore duplicate dbg config %d\n",
- conf->id);
- break;
- }
-
- if (conf->usniffer)
- usniffer_req = true;
-
- IWL_INFO(drv, "Found debug configuration: %d\n",
- conf->id);
-
- pieces->dbg_conf_tlv[conf->id] = conf;
- pieces->dbg_conf_tlv_len[conf->id] = tlv_len;
- break;
- }
- case IWL_UCODE_TLV_SEC_RT_USNIFFER:
- usniffer_images = true;
- iwl_store_ucode_sec(pieces, tlv_data,
- IWL_UCODE_REGULAR_USNIFFER,
- tlv_len);
- break;
default:
IWL_DEBUG_INFO(drv, "unknown TLV: %d\n", tlv_type);
break;
}
}
- if (usniffer_req && !usniffer_images) {
- IWL_ERR(drv,
- "user selected to work with usniffer but usniffer image isn't available in ucode package\n");
- return -EINVAL;
- }
-
if (len) {
IWL_ERR(drv, "invalid TLV after parsing: %zd\n", len);
iwl_print_hex_dump(drv, IWL_DL_FW, (u8 *)data, len);
@@ -1075,14 +992,13 @@
struct iwl_ucode_header *ucode;
struct iwlwifi_opmode_table *op;
int err;
- struct iwl_firmware_pieces *pieces;
+ struct iwl_firmware_pieces pieces;
const unsigned int api_max = drv->cfg->ucode_api_max;
unsigned int api_ok = drv->cfg->ucode_api_ok;
const unsigned int api_min = drv->cfg->ucode_api_min;
u32 api_ver;
int i;
bool load_module = false;
- u32 hw_rev = drv->trans->hw_rev;
fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
fw->ucode_capa.standard_phy_calibration_size =
@@ -1092,9 +1008,7 @@
if (!api_ok)
api_ok = api_max;
- pieces = kzalloc(sizeof(*pieces), GFP_KERNEL);
- if (!pieces)
- return;
+ memset(&pieces, 0, sizeof(pieces));
if (!ucode_raw) {
if (drv->fw_index <= api_ok)
@@ -1117,10 +1031,10 @@
ucode = (struct iwl_ucode_header *)ucode_raw->data;
if (ucode->ver)
- err = iwl_parse_v1_v2_firmware(drv, ucode_raw, pieces);
+ err = iwl_parse_v1_v2_firmware(drv, ucode_raw, &pieces);
else
- err = iwl_parse_tlv_firmware(drv, ucode_raw, pieces,
- &fw->ucode_capa);
+ err = iwl_parse_tlv_firmware(drv, ucode_raw, &pieces,
+ &fw->ucode_capa);
if (err)
goto try_again;
@@ -1160,7 +1074,7 @@
* In mvm uCode there is no difference between data and instructions
* sections.
*/
- if (!fw->mvm_fw && validate_sec_sizes(drv, pieces, drv->cfg))
+ if (!fw->mvm_fw && validate_sec_sizes(drv, &pieces, drv->cfg))
goto try_again;
/* Allocate ucode buffers for card's bus-master loading ... */
@@ -1169,33 +1083,9 @@
* 1) unmodified from disk
* 2) backup cache for save/restore during power-downs */
for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
- if (iwl_alloc_ucode(drv, pieces, i))
+ if (iwl_alloc_ucode(drv, &pieces, i))
goto out_free_fw;
- if (pieces->dbg_dest_tlv) {
- drv->fw.dbg_dest_tlv =
- kmemdup(pieces->dbg_dest_tlv,
- sizeof(*pieces->dbg_dest_tlv) +
- sizeof(pieces->dbg_dest_tlv->reg_ops[0]) *
- drv->fw.dbg_dest_reg_num, GFP_KERNEL);
-
- if (!drv->fw.dbg_dest_tlv)
- goto out_free_fw;
- }
-
- for (i = 0; i < ARRAY_SIZE(drv->fw.dbg_conf_tlv); i++) {
- if (pieces->dbg_conf_tlv[i]) {
- drv->fw.dbg_conf_tlv_len[i] =
- pieces->dbg_conf_tlv_len[i];
- drv->fw.dbg_conf_tlv[i] =
- kmemdup(pieces->dbg_conf_tlv[i],
- drv->fw.dbg_conf_tlv_len[i],
- GFP_KERNEL);
- if (!drv->fw.dbg_conf_tlv[i])
- goto out_free_fw;
- }
- }
-
/* Now that we can no longer fail, copy information */
/*
@@ -1203,20 +1093,20 @@
* for each event, which is of mode 1 (including timestamp) for all
* new microcodes that include this information.
*/
- fw->init_evtlog_ptr = pieces->init_evtlog_ptr;
- if (pieces->init_evtlog_size)
- fw->init_evtlog_size = (pieces->init_evtlog_size - 16)/12;
+ fw->init_evtlog_ptr = pieces.init_evtlog_ptr;
+ if (pieces.init_evtlog_size)
+ fw->init_evtlog_size = (pieces.init_evtlog_size - 16)/12;
else
fw->init_evtlog_size =
drv->cfg->base_params->max_event_log_size;
- fw->init_errlog_ptr = pieces->init_errlog_ptr;
- fw->inst_evtlog_ptr = pieces->inst_evtlog_ptr;
- if (pieces->inst_evtlog_size)
- fw->inst_evtlog_size = (pieces->inst_evtlog_size - 16)/12;
+ fw->init_errlog_ptr = pieces.init_errlog_ptr;
+ fw->inst_evtlog_ptr = pieces.inst_evtlog_ptr;
+ if (pieces.inst_evtlog_size)
+ fw->inst_evtlog_size = (pieces.inst_evtlog_size - 16)/12;
else
fw->inst_evtlog_size =
drv->cfg->base_params->max_event_log_size;
- fw->inst_errlog_ptr = pieces->inst_errlog_ptr;
+ fw->inst_errlog_ptr = pieces.inst_errlog_ptr;
/*
* figure out the offset of chain noise reset and gain commands
@@ -1275,55 +1165,10 @@
op->name, err);
#endif
}
-
- /*
- * We may have loaded the wrong FW file in 8000 HW family if it is an
- * A-step card, and if drv->trans->hw_rev wasn't properly read when
- * the FW file had been loaded. (This might happen in SDIO.) In such a
- * case - unload and reload the correct file.
- *
- * TODO:
- * Once there is only one supported step for 8000 family - delete this!
- */
- if (drv->trans->cfg->device_family == IWL_DEVICE_FAMILY_8000 &&
- CSR_HW_REV_STEP(drv->trans->hw_rev) == SILICON_A_STEP &&
- drv->trans->hw_rev != hw_rev) {
- char firmware_name[32];
-
- /* Free previous FW resources */
- if (drv->op_mode)
- _iwl_op_mode_stop(drv);
- iwl_dealloc_ucode(drv);
-
- /* Build name of correct-step FW */
- snprintf(firmware_name, sizeof(firmware_name),
- strrchr(drv->firmware_name, '-'));
- snprintf(drv->firmware_name, sizeof(drv->firmware_name),
- "%s%s", drv->cfg->fw_name_pre, firmware_name);
-
- /* Clear data before loading correct FW */
- list_del(&drv->list);
-
- /* Request correct FW file this time */
- IWL_DEBUG_INFO(drv, "attempting to load A-step FW %s\n",
- drv->firmware_name);
- err = request_firmware(&ucode_raw, drv->firmware_name,
- drv->trans->dev);
- if (err) {
- IWL_ERR(drv, "Failed swapping FW!\n");
- goto out_unbind;
- }
-
- /* Redo callback function - this time with right FW */
- iwl_req_fw_callback(ucode_raw, context);
- }
-
- kfree(pieces);
return;
try_again:
/* try next, if any */
- kfree(pieces);
release_firmware(ucode_raw);
if (iwl_request_firmware(drv, false))
goto out_unbind;
@@ -1334,7 +1179,6 @@
iwl_dealloc_ucode(drv);
release_firmware(ucode_raw);
out_unbind:
- kfree(pieces);
complete(&drv->request_firmware_complete);
device_release_driver(drv->trans->dev);
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
index 41ff85d..74b796d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-eeprom-parse.c
@@ -764,7 +764,7 @@
if (iwlwifi_mod_params.amsdu_size_8K)
ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
- ht_info->ampdu_factor = cfg->max_ht_ampdu_exponent;
+ ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_4;
ht_info->mcs.rx_mask[0] = 0xFF;
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
index 20a8a64..e30a41d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
@@ -81,7 +81,6 @@
* @IWL_FW_ERROR_DUMP_FW_MONITOR: firmware monitor
* @IWL_FW_ERROR_DUMP_PRPH: range of periphery registers - there can be several
* sections like this in a single file.
- * @IWL_FW_ERROR_DUMP_FH_REGS: range of FH registers
*/
enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_SRAM = 0,
@@ -91,8 +90,6 @@
IWL_FW_ERROR_DUMP_DEV_FW_INFO = 4,
IWL_FW_ERROR_DUMP_FW_MONITOR = 5,
IWL_FW_ERROR_DUMP_PRPH = 6,
- IWL_FW_ERROR_DUMP_TXF = 7,
- IWL_FW_ERROR_DUMP_FH_REGS = 8,
IWL_FW_ERROR_DUMP_MAX,
};
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw-file.h b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
index f2a047f..401f7be 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw-file.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-file.h
@@ -131,9 +131,6 @@
IWL_UCODE_TLV_API_CHANGES_SET = 29,
IWL_UCODE_TLV_ENABLED_CAPABILITIES = 30,
IWL_UCODE_TLV_N_SCAN_CHANNELS = 31,
- IWL_UCODE_TLV_SEC_RT_USNIFFER = 34,
- IWL_UCODE_TLV_FW_DBG_DEST = 38,
- IWL_UCODE_TLV_FW_DBG_CONF = 39,
};
struct iwl_ucode_tlv {
@@ -182,309 +179,4 @@
__le32 api_capa;
} __packed;
-/**
- * enum iwl_ucode_tlv_flag - ucode API flags
- * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
- * was a separate TLV but moved here to save space.
- * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
- * treats good CRC threshold as a boolean
- * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
- * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
- * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
- * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: This uCode image supports uAPSD
- * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
- * offload profile config command.
- * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
- * (rather than two) IPv6 addresses
- * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
- * from the probe request template.
- * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
- * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
- * @IWL_UCODE_TLV_FLAGS_P2P_PM: P2P client supports PM as a stand alone MAC
- * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and
- * P2P client interfaces simultaneously if they are in different bindings.
- * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_SCM: support power save on BSS station and
- * P2P client interfaces simultaneously if they are in same bindings.
- * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: General support for uAPSD
- * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
- * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
- * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
- * @IWL_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS.
- */
-enum iwl_ucode_tlv_flag {
- IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
- IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
- IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
- IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
- IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4),
- IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7),
- IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10),
- IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12),
- IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = BIT(15),
- IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = BIT(16),
- IWL_UCODE_TLV_FLAGS_P2P_PM = BIT(21),
- IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22),
- IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM = BIT(23),
- IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24),
- IWL_UCODE_TLV_FLAGS_EBS_SUPPORT = BIT(25),
- IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26),
- IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29),
- IWL_UCODE_TLV_FLAGS_GO_UAPSD = BIT(30),
-};
-
-/**
- * enum iwl_ucode_tlv_api - ucode api
- * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.
- * @IWL_UCODE_TLV_CAPA_EXTENDED_BEACON: Support Extended beacon notification
- * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex
- * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
- * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit.
- * @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API.
- * @IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF: ucode supports disabling dummy notif.
- * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time
- * longer than the passive one, which is essential for fragmented scan.
- */
-enum iwl_ucode_tlv_api {
- IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0),
- IWL_UCODE_TLV_CAPA_EXTENDED_BEACON = BIT(1),
- IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3),
- IWL_UCODE_TLV_API_CSA_FLOW = BIT(4),
- IWL_UCODE_TLV_API_DISABLE_STA_TX = BIT(5),
- IWL_UCODE_TLV_API_LMAC_SCAN = BIT(6),
- IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF = BIT(7),
- IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8),
-};
-
-/**
- * enum iwl_ucode_tlv_capa - ucode capabilities
- * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3
- * @IWL_UCODE_TLV_CAPA_LAR_SUPPORT: supports Location Aware Regulatory
- * @IWL_UCODE_TLV_CAPA_UMAC_SCAN: supports UMAC scan.
- * @IWL_UCODE_TLV_CAPA_TDLS_SUPPORT: support basic TDLS functionality
- * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current
- * tx power value into TPC Report action frame and Link Measurement Report
- * action frame
- * @IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports updating current
- * channel in DS parameter set element in probe requests.
- * @IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT: supports adding TPC Report IE in
- * probe requests.
- * @IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests
- * @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA),
- * which also implies support for the scheduler configuration command
- * @IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH: supports TDLS channel switching
- * @IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT: supports Hot Spot Command
- */
-enum iwl_ucode_tlv_capa {
- IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0),
- IWL_UCODE_TLV_CAPA_LAR_SUPPORT = BIT(1),
- IWL_UCODE_TLV_CAPA_UMAC_SCAN = BIT(2),
- IWL_UCODE_TLV_CAPA_TDLS_SUPPORT = BIT(6),
- IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = BIT(8),
- IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = BIT(9),
- IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT = BIT(10),
- IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT = BIT(11),
- IWL_UCODE_TLV_CAPA_DQA_SUPPORT = BIT(12),
- IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH = BIT(13),
- IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT = BIT(18),
-};
-
-/* The default calibrate table size if not specified by firmware file */
-#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
-#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19
-#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253
-
-/* The default max probe length if not specified by the firmware file */
-#define IWL_DEFAULT_MAX_PROBE_LENGTH 200
-
-/*
- * For 16.0 uCode and above, there is no differentiation between sections,
- * just an offset to the HW address.
- */
-#define IWL_UCODE_SECTION_MAX 12
-#define IWL_API_ARRAY_SIZE 1
-#define IWL_CAPABILITIES_ARRAY_SIZE 1
-#define CPU1_CPU2_SEPARATOR_SECTION 0xFFFFCCCC
-
-/* uCode version contains 4 values: Major/Minor/API/Serial */
-#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
-#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
-#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
-#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
-
-/*
- * Calibration control struct.
- * Sent as part of the phy configuration command.
- * @flow_trigger: bitmap for which calibrations to perform according to
- * flow triggers.
- * @event_trigger: bitmap for which calibrations to perform according to
- * event triggers.
- */
-struct iwl_tlv_calib_ctrl {
- __le32 flow_trigger;
- __le32 event_trigger;
-} __packed;
-
-enum iwl_fw_phy_cfg {
- FW_PHY_CFG_RADIO_TYPE_POS = 0,
- FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS,
- FW_PHY_CFG_RADIO_STEP_POS = 2,
- FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS,
- FW_PHY_CFG_RADIO_DASH_POS = 4,
- FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS,
- FW_PHY_CFG_TX_CHAIN_POS = 16,
- FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
- FW_PHY_CFG_RX_CHAIN_POS = 20,
- FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
-};
-
-#define IWL_UCODE_MAX_CS 1
-
-/**
- * struct iwl_fw_cipher_scheme - a cipher scheme supported by FW.
- * @cipher: a cipher suite selector
- * @flags: cipher scheme flags (currently reserved for a future use)
- * @hdr_len: a size of MPDU security header
- * @pn_len: a size of PN
- * @pn_off: an offset of pn from the beginning of the security header
- * @key_idx_off: an offset of key index byte in the security header
- * @key_idx_mask: a bit mask of key_idx bits
- * @key_idx_shift: bit shift needed to get key_idx
- * @mic_len: mic length in bytes
- * @hw_cipher: a HW cipher index used in host commands
- */
-struct iwl_fw_cipher_scheme {
- __le32 cipher;
- u8 flags;
- u8 hdr_len;
- u8 pn_len;
- u8 pn_off;
- u8 key_idx_off;
- u8 key_idx_mask;
- u8 key_idx_shift;
- u8 mic_len;
- u8 hw_cipher;
-} __packed;
-
-enum iwl_fw_dbg_reg_operator {
- CSR_ASSIGN,
- CSR_SETBIT,
- CSR_CLEARBIT,
-
- PRPH_ASSIGN,
- PRPH_SETBIT,
- PRPH_CLEARBIT,
-};
-
-/**
- * struct iwl_fw_dbg_reg_op - an operation on a register
- *
- * @op: %enum iwl_fw_dbg_reg_operator
- * @addr: offset of the register
- * @val: value
- */
-struct iwl_fw_dbg_reg_op {
- u8 op;
- u8 reserved[3];
- __le32 addr;
- __le32 val;
-} __packed;
-
-/**
- * enum iwl_fw_dbg_monitor_mode - available monitor recording modes
- *
- * @SMEM_MODE: monitor stores the data in SMEM
- * @EXTERNAL_MODE: monitor stores the data in allocated DRAM
- * @MARBH_MODE: monitor stores the data in MARBH buffer
- */
-enum iwl_fw_dbg_monitor_mode {
- SMEM_MODE = 0,
- EXTERNAL_MODE = 1,
- MARBH_MODE = 2,
-};
-
-/**
- * struct iwl_fw_dbg_dest_tlv - configures the destination of the debug data
- *
- * @version: version of the TLV - currently 0
- * @monitor_mode: %enum iwl_fw_dbg_monitor_mode
- * @base_reg: addr of the base addr register (PRPH)
- * @end_reg: addr of the end addr register (PRPH)
- * @write_ptr_reg: the addr of the reg of the write pointer
- * @wrap_count: the addr of the reg of the wrap_count
- * @base_shift: shift right of the base addr reg
- * @end_shift: shift right of the end addr reg
- * @reg_ops: array of registers operations
- *
- * This parses IWL_UCODE_TLV_FW_DBG_DEST
- */
-struct iwl_fw_dbg_dest_tlv {
- u8 version;
- u8 monitor_mode;
- u8 reserved[2];
- __le32 base_reg;
- __le32 end_reg;
- __le32 write_ptr_reg;
- __le32 wrap_count;
- u8 base_shift;
- u8 end_shift;
- struct iwl_fw_dbg_reg_op reg_ops[0];
-} __packed;
-
-struct iwl_fw_dbg_conf_hcmd {
- u8 id;
- u8 reserved;
- __le16 len;
- u8 data[0];
-} __packed;
-
-/**
- * struct iwl_fw_dbg_trigger - a TLV that describes a debug configuration
- *
- * @enabled: is this trigger enabled
- * @reserved:
- * @len: length, in bytes, of the %trigger field
- * @trigger: pointer to a trigger struct
- */
-struct iwl_fw_dbg_trigger {
- u8 enabled;
- u8 reserved;
- u8 len;
- u8 trigger[0];
-} __packed;
-
-/**
- * enum iwl_fw_dbg_conf - configurations available
- *
- * @FW_DBG_CUSTOM: take this configuration from alive
- * Note that the trigger is NO-OP for this configuration
- */
-enum iwl_fw_dbg_conf {
- FW_DBG_CUSTOM = 0,
-
- /* must be last */
- FW_DBG_MAX,
- FW_DBG_INVALID = 0xff,
-};
-
-/**
- * struct iwl_fw_dbg_conf_tlv - a TLV that describes a debug configuration
- *
- * @id: %enum iwl_fw_dbg_conf
- * @usniffer: should the uSniffer image be used
- * @num_of_hcmds: how many HCMDs to send are present here
- * @hcmd: a variable length host command to be sent to apply the configuration.
- * If there is more than one HCMD to send, they will appear one after the
- * other and be sent in the order that they appear in.
- * This parses IWL_UCODE_TLV_FW_DBG_CONF
- */
-struct iwl_fw_dbg_conf_tlv {
- u8 id;
- u8 usniffer;
- u8 reserved;
- u8 num_of_hcmds;
- struct iwl_fw_dbg_conf_hcmd hcmd;
-
- /* struct iwl_fw_dbg_trigger sits after all variable length hcmds */
-} __packed;
-
#endif /* __iwl_fw_file_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index e6dc3b8..4f6e668 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -70,6 +70,110 @@
#include "iwl-fw-file.h"
/**
+ * enum iwl_ucode_tlv_flag - ucode API flags
+ * @IWL_UCODE_TLV_FLAGS_PAN: This is PAN capable microcode; this previously
+ * was a separate TLV but moved here to save space.
+ * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
+ * treats good CRC threshold as a boolean
+ * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
+ * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
+ * @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
+ * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: This uCode image supports uAPSD
+ * @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
+ * offload profile config command.
+ * @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
+ * (rather than two) IPv6 addresses
+ * @IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID: not sending a probe with the SSID element
+ * from the probe request template.
+ * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL: new NS offload (small version)
+ * @IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE: new NS offload (large version)
+ * @IWL_UCODE_TLV_FLAGS_P2P_PM: P2P client supports PM as a stand alone MAC
+ * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_DCM: support power save on BSS station and
+ * P2P client interfaces simultaneously if they are in different bindings.
+ * @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_SCM: support power save on BSS station and
+ * P2P client interfaces simultaneously if they are in same bindings.
+ * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: General support for uAPSD
+ * @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
+ * @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
+ * @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
+ * @IWL_UCODE_TLV_FLAGS_EBS_SUPPORT: this uCode image supports EBS.
+ */
+enum iwl_ucode_tlv_flag {
+ IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
+ IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
+ IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
+ IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
+ IWL_UCODE_TLV_FLAGS_DW_BC_TABLE = BIT(4),
+ IWL_UCODE_TLV_FLAGS_SHORT_BL = BIT(7),
+ IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS = BIT(10),
+ IWL_UCODE_TLV_FLAGS_NO_BASIC_SSID = BIT(12),
+ IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_SMALL = BIT(15),
+ IWL_UCODE_TLV_FLAGS_NEW_NSOFFL_LARGE = BIT(16),
+ IWL_UCODE_TLV_FLAGS_P2P_PM = BIT(21),
+ IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22),
+ IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM = BIT(23),
+ IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24),
+ IWL_UCODE_TLV_FLAGS_EBS_SUPPORT = BIT(25),
+ IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26),
+ IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29),
+ IWL_UCODE_TLV_FLAGS_GO_UAPSD = BIT(30),
+};
+
+/**
+ * enum iwl_ucode_tlv_api - ucode api
+ * @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.
+ * @IWL_UCODE_TLV_CAPA_EXTENDED_BEACON: Support Extended beacon notification
+ * @IWL_UCODE_TLV_API_BT_COEX_SPLIT: new API for BT Coex
+ * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
+ * @IWL_UCODE_TLV_API_DISABLE_STA_TX: ucode supports tx_disable bit.
+ * @IWL_UCODE_TLV_API_LMAC_SCAN: This ucode uses LMAC unified scan API.
+ * @IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF: ucode supports disabling dummy notif.
+ * @IWL_UCODE_TLV_API_FRAGMENTED_SCAN: This ucode supports active dwell time
+ * longer than the passive one, which is essential for fragmented scan.
+ */
+enum iwl_ucode_tlv_api {
+ IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0),
+ IWL_UCODE_TLV_CAPA_EXTENDED_BEACON = BIT(1),
+ IWL_UCODE_TLV_API_BT_COEX_SPLIT = BIT(3),
+ IWL_UCODE_TLV_API_CSA_FLOW = BIT(4),
+ IWL_UCODE_TLV_API_DISABLE_STA_TX = BIT(5),
+ IWL_UCODE_TLV_API_LMAC_SCAN = BIT(6),
+ IWL_UCODE_TLV_API_SF_NO_DUMMY_NOTIF = BIT(7),
+ IWL_UCODE_TLV_API_FRAGMENTED_SCAN = BIT(8),
+};
+
+/**
+ * enum iwl_ucode_tlv_capa - ucode capabilities
+ * @IWL_UCODE_TLV_CAPA_D0I3_SUPPORT: supports D0i3
+ * @IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT: supports insertion of current
+ * tx power value into TPC Report action frame and Link Measurement Report
+ * action frame
+ * @IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT: supports adding DS params
+ * element in probe requests.
+ * @IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT: supports adding TPC Report IE in
+ * probe requests.
+ * @IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT: supports Quiet Period requests
+ * @IWL_UCODE_TLV_CAPA_DQA_SUPPORT: supports dynamic queue allocation (DQA),
+ * which also implies support for the scheduler configuration command
+ */
+enum iwl_ucode_tlv_capa {
+ IWL_UCODE_TLV_CAPA_D0I3_SUPPORT = BIT(0),
+ IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT = BIT(8),
+ IWL_UCODE_TLV_CAPA_DS_PARAM_SET_IE_SUPPORT = BIT(9),
+ IWL_UCODE_TLV_CAPA_WFA_TPC_REP_IE_SUPPORT = BIT(10),
+ IWL_UCODE_TLV_CAPA_QUIET_PERIOD_SUPPORT = BIT(11),
+ IWL_UCODE_TLV_CAPA_DQA_SUPPORT = BIT(12),
+};
+
+/* The default calibrate table size if not specified by firmware file */
+#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE 18
+#define IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE 19
+#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE 253
+
+/* The default max probe length if not specified by the firmware file */
+#define IWL_DEFAULT_MAX_PROBE_LENGTH 200
+
+/**
* enum iwl_ucode_type
*
* The type of ucode.
@@ -77,13 +181,11 @@
* @IWL_UCODE_REGULAR: Normal runtime ucode
* @IWL_UCODE_INIT: Initial ucode
* @IWL_UCODE_WOWLAN: Wake on Wireless enabled ucode
- * @IWL_UCODE_REGULAR_USNIFFER: Normal runtime ucode when using usniffer image
*/
enum iwl_ucode_type {
IWL_UCODE_REGULAR,
IWL_UCODE_INIT,
IWL_UCODE_WOWLAN,
- IWL_UCODE_REGULAR_USNIFFER,
IWL_UCODE_TYPE_MAX,
};
@@ -98,6 +200,14 @@
IWL_UCODE_SECTION_DATA,
IWL_UCODE_SECTION_INST,
};
+/*
+ * For 16.0 uCode and above, there is no differentiation between sections,
+ * just an offset to the HW address.
+ */
+#define IWL_UCODE_SECTION_MAX 12
+#define IWL_API_ARRAY_SIZE 1
+#define IWL_CAPABILITIES_ARRAY_SIZE 1
+#define CPU1_CPU2_SEPARATOR_SECTION 0xFFFFCCCC
struct iwl_ucode_capabilities {
u32 max_probe_length;
@@ -117,6 +227,7 @@
struct fw_img {
struct fw_desc sec[IWL_UCODE_SECTION_MAX];
+ bool is_secure;
bool is_dual_cpus;
};
@@ -125,6 +236,66 @@
u32 size;
};
+/* uCode version contains 4 values: Major/Minor/API/Serial */
+#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
+#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
+#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8)
+#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF)
+
+/*
+ * Calibration control struct.
+ * Sent as part of the phy configuration command.
+ * @flow_trigger: bitmap for which calibrations to perform according to
+ * flow triggers.
+ * @event_trigger: bitmap for which calibrations to perform according to
+ * event triggers.
+ */
+struct iwl_tlv_calib_ctrl {
+ __le32 flow_trigger;
+ __le32 event_trigger;
+} __packed;
+
+enum iwl_fw_phy_cfg {
+ FW_PHY_CFG_RADIO_TYPE_POS = 0,
+ FW_PHY_CFG_RADIO_TYPE = 0x3 << FW_PHY_CFG_RADIO_TYPE_POS,
+ FW_PHY_CFG_RADIO_STEP_POS = 2,
+ FW_PHY_CFG_RADIO_STEP = 0x3 << FW_PHY_CFG_RADIO_STEP_POS,
+ FW_PHY_CFG_RADIO_DASH_POS = 4,
+ FW_PHY_CFG_RADIO_DASH = 0x3 << FW_PHY_CFG_RADIO_DASH_POS,
+ FW_PHY_CFG_TX_CHAIN_POS = 16,
+ FW_PHY_CFG_TX_CHAIN = 0xf << FW_PHY_CFG_TX_CHAIN_POS,
+ FW_PHY_CFG_RX_CHAIN_POS = 20,
+ FW_PHY_CFG_RX_CHAIN = 0xf << FW_PHY_CFG_RX_CHAIN_POS,
+};
+
+#define IWL_UCODE_MAX_CS 1
+
+/**
+ * struct iwl_fw_cipher_scheme - a cipher scheme supported by FW.
+ * @cipher: a cipher suite selector
+ * @flags: cipher scheme flags (currently reserved for a future use)
+ * @hdr_len: a size of MPDU security header
+ * @pn_len: a size of PN
+ * @pn_off: an offset of pn from the beginning of the security header
+ * @key_idx_off: an offset of key index byte in the security header
+ * @key_idx_mask: a bit mask of key_idx bits
+ * @key_idx_shift: bit shift needed to get key_idx
+ * @mic_len: mic length in bytes
+ * @hw_cipher: a HW cipher index used in host commands
+ */
+struct iwl_fw_cipher_scheme {
+ __le32 cipher;
+ u8 flags;
+ u8 hdr_len;
+ u8 pn_len;
+ u8 pn_off;
+ u8 key_idx_off;
+ u8 key_idx_mask;
+ u8 key_idx_shift;
+ u8 mic_len;
+ u8 hw_cipher;
+} __packed;
+
/**
* struct iwl_fw_cscheme_list - a cipher scheme list
* @size: a number of entries
@@ -151,11 +322,6 @@
* @inst_errlog_ptr: error log offfset for runtime ucode.
* @mvm_fw: indicates this is MVM firmware
* @cipher_scheme: optional external cipher scheme.
- * @human_readable: human readable version
- * @dbg_dest_tlv: points to the destination TLV for debug
- * @dbg_conf_tlv: array of pointers to configuration TLVs for debug
- * @dbg_conf_tlv_len: lengths of the @dbg_conf_tlv entries
- * @dbg_dest_reg_num: num of reg_ops in %dbg_dest_tlv
*/
struct iwl_fw {
u32 ucode_ver;
@@ -180,68 +346,6 @@
struct ieee80211_cipher_scheme cs[IWL_UCODE_MAX_CS];
u8 human_readable[FW_VER_HUMAN_READABLE_SZ];
-
- struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
- struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
- size_t dbg_conf_tlv_len[FW_DBG_MAX];
-
- u8 dbg_dest_reg_num;
};
-static inline const char *get_fw_dbg_mode_string(int mode)
-{
- switch (mode) {
- case SMEM_MODE:
- return "SMEM";
- case EXTERNAL_MODE:
- return "EXTERNAL_DRAM";
- case MARBH_MODE:
- return "MARBH";
- default:
- return "UNKNOWN";
- }
-}
-
-static inline const struct iwl_fw_dbg_trigger *
-iwl_fw_dbg_conf_get_trigger(const struct iwl_fw *fw, u8 id)
-{
- const struct iwl_fw_dbg_conf_tlv *conf_tlv = fw->dbg_conf_tlv[id];
- u8 *ptr;
- int i;
-
- if (!conf_tlv)
- return NULL;
-
- ptr = (void *)&conf_tlv->hcmd;
- for (i = 0; i < conf_tlv->num_of_hcmds; i++) {
- ptr += sizeof(conf_tlv->hcmd);
- ptr += le16_to_cpu(conf_tlv->hcmd.len);
- }
-
- return (const struct iwl_fw_dbg_trigger *)ptr;
-}
-
-static inline bool
-iwl_fw_dbg_conf_enabled(const struct iwl_fw *fw, u8 id)
-{
- const struct iwl_fw_dbg_trigger *trigger =
- iwl_fw_dbg_conf_get_trigger(fw, id);
-
- if (!trigger)
- return false;
-
- return trigger->enabled;
-}
-
-static inline bool
-iwl_fw_dbg_conf_usniffer(const struct iwl_fw *fw, u8 id)
-{
- const struct iwl_fw_dbg_conf_tlv *conf_tlv = fw->dbg_conf_tlv[id];
-
- if (!conf_tlv)
- return false;
-
- return conf_tlv->usniffer;
-}
-
#endif /* __iwl_fw_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 06e02fc..c302e74 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -325,8 +325,6 @@
{
int num_rx_ants = num_of_ant(rx_chains);
int num_tx_ants = num_of_ant(tx_chains);
- unsigned int max_ampdu_exponent = (cfg->max_vht_ampdu_exponent ?:
- IEEE80211_VHT_MAX_AMPDU_1024K);
vht_cap->vht_supported = true;
@@ -334,8 +332,7 @@
IEEE80211_VHT_CAP_RXSTBC_1 |
IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE |
3 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT |
- max_ampdu_exponent <<
- IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
+ 7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT;
if (cfg->ht_params->ldpc)
vht_cap->cap |= IEEE80211_VHT_CAP_RXLDPC;
diff --git a/drivers/net/wireless/iwlwifi/iwl-op-mode.h b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
index 17de6d4..b6d666e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-op-mode.h
+++ b/drivers/net/wireless/iwlwifi/iwl-op-mode.h
@@ -138,8 +138,7 @@
* @nic_config: configure NIC, called before firmware is started.
* May sleep
* @wimax_active: invoked when WiMax becomes active. May sleep
- * @enter_d0i3: configure the fw to enter d0i3. return 1 to indicate d0i3
- * entrance is aborted (e.g. due to held reference). May sleep.
+ * @enter_d0i3: configure the fw to enter d0i3. May sleep.
* @exit_d0i3: configure the fw to exit d0i3. May sleep.
*/
struct iwl_op_mode_ops {
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 2df51ea..1560f45 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -322,7 +322,6 @@
LMPM_SECURE_BOOT_CONFIG_INSPECTOR_NOT_REQ = 0x00000002,
};
-#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0 (0xA01E30)
#define LMPM_SECURE_BOOT_CPU1_STATUS_ADDR (0x1E30)
#define LMPM_SECURE_BOOT_CPU2_STATUS_ADDR (0x1E34)
enum secure_boot_status_reg {
@@ -334,7 +333,6 @@
LMPM_SECURE_BOOT_STATUS_SUCCESS = 0x00000003,
};
-#define FH_UCODE_LOAD_STATUS (0x1AF0)
#define CSR_UCODE_LOAD_STATUS_ADDR (0x1E70)
enum secure_load_status_reg {
LMPM_CPU_UCODE_LOADING_STARTED = 0x00000001,
@@ -354,7 +352,7 @@
#define LMPM_SECURE_CPU1_HDR_MEM_SPACE (0x420000)
#define LMPM_SECURE_CPU2_HDR_MEM_SPACE (0x420400)
-#define LMPM_SECURE_TIME_OUT (100) /* 10 micro */
+#define LMPM_SECURE_TIME_OUT (100)
/* Rx FIFO */
#define RXF_SIZE_ADDR (0xa00c88)
@@ -370,10 +368,4 @@
#define MON_BUFF_WRPTR (0xa03c44)
#define MON_BUFF_CYCLE_CNT (0xa03c48)
-/* FW chicken bits */
-#define LMPM_CHICK 0xA01FF8
-enum {
- LMPM_CHICK_EXTENDED_ADDR_SPACE = BIT(0),
-};
-
#endif /* __iwl_prph_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 028408a..98b4c95 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -534,10 +534,10 @@
u32 value);
void (*ref)(struct iwl_trans *trans);
void (*unref)(struct iwl_trans *trans);
- void (*suspend)(struct iwl_trans *trans);
- void (*resume)(struct iwl_trans *trans);
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans);
+#endif
};
/**
@@ -563,7 +563,6 @@
* Set during transport allocation.
* @hw_id_str: a string with info about HW ID. Set during transport allocation.
* @pm_support: set to true in start_hw if link pm is supported
- * @ltr_enabled: set to true if the LTR is enabled
* @dev_cmd_pool: pool for Tx cmd allocation - for internal use only.
* The user should use iwl_trans_{alloc,free}_tx_cmd.
* @dev_cmd_headroom: room needed for the transport's private use before the
@@ -574,9 +573,6 @@
* @rx_mpdu_cmd_hdr_size: used for tracing, amount of data before the
* start of the 802.11 header in the @rx_mpdu_cmd
* @dflt_pwr_limit: default power limit fetched from the platform (ACPI)
- * @dbg_dest_tlv: points to the destination TLV for debug
- * @dbg_conf_tlv: array of pointers to configuration TLVs for debug
- * @dbg_dest_reg_num: num of reg_ops in %dbg_dest_tlv
*/
struct iwl_trans {
const struct iwl_trans_ops *ops;
@@ -593,7 +589,6 @@
u8 rx_mpdu_cmd, rx_mpdu_cmd_hdr_size;
bool pm_support;
- bool ltr_enabled;
/* The following fields are internal only */
struct kmem_cache *dev_cmd_pool;
@@ -608,10 +603,6 @@
u64 dflt_pwr_limit;
- const struct iwl_fw_dbg_dest_tlv *dbg_dest_tlv;
- const struct iwl_fw_dbg_conf_tlv *dbg_conf_tlv[FW_DBG_MAX];
- u8 dbg_dest_reg_num;
-
/* pointer to trans specific struct */
/*Ensure that this pointer will always be aligned to sizeof pointer */
char trans_specific[0] __aligned(sizeof(void *));
@@ -711,18 +702,7 @@
trans->ops->unref(trans);
}
-static inline void iwl_trans_suspend(struct iwl_trans *trans)
-{
- if (trans->ops->suspend)
- trans->ops->suspend(trans);
-}
-
-static inline void iwl_trans_resume(struct iwl_trans *trans)
-{
- if (trans->ops->resume)
- trans->ops->resume(trans);
-}
-
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
static inline struct iwl_trans_dump_data *
iwl_trans_dump_data(struct iwl_trans *trans)
{
@@ -730,6 +710,7 @@
return NULL;
return trans->ops->dump_data(trans);
}
+#endif
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index a3bfda4..8df2021 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -72,6 +72,8 @@
#include "mvm.h"
#include "iwl-debug.h"
+#define BT_ANTENNA_COUPLING_THRESHOLD (30)
+
const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = {
[BT_KILL_MSK_DEFAULT] = 0xfffffc00,
[BT_KILL_MSK_NEVER] = 0xffffffff,
@@ -300,6 +302,11 @@
},
};
+static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
+ cpu_to_le32(0x28412201),
+ cpu_to_le32(0x11118451),
+};
+
struct corunning_block_luts {
u8 range;
__le32 lut20[BT_COEX_CORUN_LUT_SIZE];
@@ -598,7 +605,7 @@
bt_cmd->max_kill = cpu_to_le32(5);
bt_cmd->bt4_antenna_isolation_thr =
- cpu_to_le32(IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS);
+ cpu_to_le32(BT_ANTENNA_COUPLING_THRESHOLD);
bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15);
bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15);
bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
@@ -631,8 +638,8 @@
memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost,
sizeof(iwl_bt_prio_boost));
- bt_cmd->multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0);
- bt_cmd->multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1);
+ memcpy(&bt_cmd->multiprio_lut, iwl_bt_mprio_lut,
+ sizeof(iwl_bt_mprio_lut));
send_cmd:
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
@@ -1137,22 +1144,6 @@
return lut_type != BT_COEX_LOOSE_LUT;
}
-bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant)
-{
- /* there is no other antenna, shared antenna is always available */
- if (mvm->cfg->bt_shared_single_ant)
- return true;
-
- if (ant & mvm->cfg->non_shared_ant)
- return true;
-
- if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
- return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm);
-
- return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
- BT_HIGH_TRAFFIC;
-}
-
bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
{
/* there is no other antenna, shared antenna is always available */
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
index b3210cf..585c0ab 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c
@@ -102,6 +102,8 @@
#undef EVENT_PRIO_ANT
+#define BT_ANTENNA_COUPLING_THRESHOLD (30)
+
static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
{
if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
@@ -288,6 +290,11 @@
},
};
+static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
+ cpu_to_le32(0x28412201),
+ cpu_to_le32(0x11118451),
+};
+
struct corunning_block_luts {
u8 range;
__le32 lut20[BT_COEX_CORUN_LUT_SIZE];
@@ -586,8 +593,7 @@
}
bt_cmd->max_kill = 5;
- bt_cmd->bt4_antenna_isolation_thr =
- IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS;
+ bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD;
bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
bt_cmd->bt4_tx_rx_max_freq0 = 15;
@@ -612,9 +618,7 @@
BT_VALID_ANT_ISOLATION_THRS |
BT_VALID_TXTX_DELTA_FREQ_THRS |
BT_VALID_TXRX_MAX_FREQ_0 |
- BT_VALID_SYNC_TO_SCO |
- BT_VALID_TTC |
- BT_VALID_RRC);
+ BT_VALID_SYNC_TO_SCO);
if (IWL_MVM_BT_COEX_SYNC2SCO)
bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
@@ -630,12 +634,6 @@
bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
}
- if (IWL_MVM_BT_COEX_TTC)
- bt_cmd->flags |= cpu_to_le32(BT_COEX_TTC);
-
- if (IWL_MVM_BT_COEX_RRC)
- bt_cmd->flags |= cpu_to_le32(BT_COEX_RRC);
-
if (mvm->cfg->bt_shared_single_ant)
memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
sizeof(iwl_single_shared_ant));
@@ -651,8 +649,8 @@
memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
sizeof(iwl_bt_prio_boost));
- bt_cmd->bt4_multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0);
- bt_cmd->bt4_multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1);
+ memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
+ sizeof(iwl_bt_mprio_lut));
send_cmd:
memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
@@ -832,9 +830,6 @@
if (!vif->bss_conf.assoc)
smps_mode = IEEE80211_SMPS_AUTOMATIC;
- if (data->notif->rrc_enabled & BIT(mvmvif->phy_ctxt->id))
- smps_mode = IEEE80211_SMPS_AUTOMATIC;
-
IWL_DEBUG_COEX(data->mvm,
"mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
mvmvif->id, data->notif->bt_status, bt_activity_grading,
@@ -1167,12 +1162,6 @@
return lut_type != BT_COEX_LOOSE_LUT;
}
-bool iwl_mvm_bt_coex_is_ant_avail_old(struct iwl_mvm *mvm, u8 ant)
-{
- u32 ag = le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
- return ag < BT_HIGH_TRAFFIC;
-}
-
bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm)
{
u32 ag = le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h
index 3bd9347..d4dfbe4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/constants.h
+++ b/drivers/net/wireless/iwlwifi/mvm/constants.h
@@ -92,15 +92,8 @@
#define IWL_MVM_BT_COEX_SYNC2SCO 1
#define IWL_MVM_BT_COEX_CORUNNING 0
#define IWL_MVM_BT_COEX_MPLUT 1
-#define IWL_MVM_BT_COEX_RRC 1
-#define IWL_MVM_BT_COEX_TTC 1
-#define IWL_MVM_BT_COEX_MPLUT_REG0 0x28412201
-#define IWL_MVM_BT_COEX_MPLUT_REG1 0x11118451
-#define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30
#define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0
-#define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0
#define IWL_MVM_QUOTA_THRESHOLD 8
#define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0
-#define IWL_MVM_RS_DISABLE_MIMO 0
#endif /* __MVM_CONSTANTS_H */
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index db454c8..d45d6df 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -601,6 +601,33 @@
return ret;
}
+struct iwl_d3_iter_data {
+ struct iwl_mvm *mvm;
+ struct ieee80211_vif *vif;
+ bool error;
+};
+
+static void iwl_mvm_d3_iface_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_d3_iter_data *data = _data;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
+ return;
+
+ if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
+ return;
+
+ if (data->vif) {
+ IWL_ERR(data->mvm, "More than one managed interface active!\n");
+ data->error = true;
+ return;
+ }
+
+ data->vif = vif;
+}
+
static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_sta *ap_sta)
{
@@ -756,8 +783,144 @@
IWL_ERR(mvm, "failed to set non-QoS seqno\n");
}
-static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
+static int
+iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm,
+ const struct iwl_wowlan_config_cmd_v3 *cmd)
{
+ /* start only with the v2 part of the command */
+ u16 cmd_len = sizeof(cmd->common);
+
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID)
+ cmd_len = sizeof(*cmd);
+
+ return iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
+ cmd_len, cmd);
+}
+
+static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
+ struct cfg80211_wowlan *wowlan,
+ bool test)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_d3_iter_data suspend_iter_data = {
+ .mvm = mvm,
+ };
+ struct ieee80211_vif *vif;
+ struct iwl_mvm_vif *mvmvif;
+ struct ieee80211_sta *ap_sta;
+ struct iwl_mvm_sta *mvm_ap_sta;
+ struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {};
+ struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
+ struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
+ struct iwl_d3_manager_config d3_cfg_cmd_data = {
+ /*
+ * Program the minimum sleep time to 10 seconds, as many
+ * platforms have issues processing a wakeup signal while
+ * still being in the process of suspending.
+ */
+ .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
+ };
+ struct iwl_host_cmd d3_cfg_cmd = {
+ .id = D3_CONFIG_CMD,
+ .flags = CMD_WANT_SKB,
+ .data[0] = &d3_cfg_cmd_data,
+ .len[0] = sizeof(d3_cfg_cmd_data),
+ };
+ struct wowlan_key_data key_data = {
+ .use_rsc_tsc = false,
+ .tkip = &tkip_cmd,
+ .use_tkip = false,
+ };
+ int ret;
+ int len __maybe_unused;
+
+ if (!wowlan) {
+ /*
+ * mac80211 shouldn't get here, but for D3 test
+ * it doesn't warrant a warning
+ */
+ WARN_ON(!test);
+ return -EINVAL;
+ }
+
+ key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
+ if (!key_data.rsc_tsc)
+ return -ENOMEM;
+
+ mutex_lock(&mvm->mutex);
+
+ /* see if there's only a single BSS vif and it's associated */
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_d3_iface_iterator, &suspend_iter_data);
+
+ if (suspend_iter_data.error || !suspend_iter_data.vif) {
+ ret = 1;
+ goto out_noreset;
+ }
+
+ vif = suspend_iter_data.vif;
+ mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ ap_sta = rcu_dereference_protected(
+ mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
+ lockdep_is_held(&mvm->mutex));
+ if (IS_ERR_OR_NULL(ap_sta)) {
+ ret = -EINVAL;
+ goto out_noreset;
+ }
+
+ mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv;
+
+ /* TODO: wowlan_config_cmd.common.wowlan_ba_teardown_tids */
+
+ wowlan_config_cmd.common.is_11n_connection =
+ ap_sta->ht_cap.ht_supported;
+
+ /* Query the last used seqno and set it */
+ ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);
+ if (ret < 0)
+ goto out_noreset;
+ wowlan_config_cmd.common.non_qos_seq = cpu_to_le16(ret);
+
+ iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &wowlan_config_cmd.common);
+
+ if (wowlan->disconnect)
+ wowlan_config_cmd.common.wakeup_filter |=
+ cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |
+ IWL_WOWLAN_WAKEUP_LINK_CHANGE);
+ if (wowlan->magic_pkt)
+ wowlan_config_cmd.common.wakeup_filter |=
+ cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET);
+ if (wowlan->gtk_rekey_failure)
+ wowlan_config_cmd.common.wakeup_filter |=
+ cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
+ if (wowlan->eap_identity_req)
+ wowlan_config_cmd.common.wakeup_filter |=
+ cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ);
+ if (wowlan->four_way_handshake)
+ wowlan_config_cmd.common.wakeup_filter |=
+ cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
+ if (wowlan->n_patterns)
+ wowlan_config_cmd.common.wakeup_filter |=
+ cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
+
+ if (wowlan->rfkill_release)
+ wowlan_config_cmd.common.wakeup_filter |=
+ cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
+
+ if (wowlan->tcp) {
+ /*
+ * Set the "link change" (really "link lost") flag as well
+ * since that implies losing the TCP connection.
+ */
+ wowlan_config_cmd.common.wakeup_filter |=
+ cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
+ IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE |
+ IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET |
+ IWL_WOWLAN_WAKEUP_LINK_CHANGE);
+ }
+
iwl_mvm_cancel_scan(mvm);
iwl_trans_stop_device(mvm->trans);
@@ -782,99 +945,13 @@
mvm->ptk_ivlen = 0;
mvm->ptk_icvlen = 0;
- return iwl_mvm_load_d3_fw(mvm);
-}
-
-static int
-iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm,
- struct cfg80211_wowlan *wowlan,
- struct iwl_wowlan_config_cmd *wowlan_config_cmd,
- struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
- struct ieee80211_sta *ap_sta)
-{
- int ret;
- struct iwl_mvm_sta *mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv;
-
- /* TODO: wowlan_config_cmd->wowlan_ba_teardown_tids */
-
- wowlan_config_cmd->is_11n_connection =
- ap_sta->ht_cap.ht_supported;
-
- /* Query the last used seqno and set it */
- ret = iwl_mvm_get_last_nonqos_seq(mvm, vif);
- if (ret < 0)
- return ret;
-
- wowlan_config_cmd->non_qos_seq = cpu_to_le16(ret);
-
- iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, wowlan_config_cmd);
-
- if (wowlan->disconnect)
- wowlan_config_cmd->wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS |
- IWL_WOWLAN_WAKEUP_LINK_CHANGE);
- if (wowlan->magic_pkt)
- wowlan_config_cmd->wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET);
- if (wowlan->gtk_rekey_failure)
- wowlan_config_cmd->wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL);
- if (wowlan->eap_identity_req)
- wowlan_config_cmd->wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ);
- if (wowlan->four_way_handshake)
- wowlan_config_cmd->wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE);
- if (wowlan->n_patterns)
- wowlan_config_cmd->wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH);
-
- if (wowlan->rfkill_release)
- wowlan_config_cmd->wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
-
- if (wowlan->tcp) {
- /*
- * Set the "link change" (really "link lost") flag as well
- * since that implies losing the TCP connection.
- */
- wowlan_config_cmd->wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS |
- IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE |
- IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET |
- IWL_WOWLAN_WAKEUP_LINK_CHANGE);
- }
-
- return 0;
-}
-
-static int
-iwl_mvm_wowlan_config(struct iwl_mvm *mvm,
- struct cfg80211_wowlan *wowlan,
- struct iwl_wowlan_config_cmd *wowlan_config_cmd,
- struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif,
- struct ieee80211_sta *ap_sta)
-{
- struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {};
- struct iwl_wowlan_tkip_params_cmd tkip_cmd = {};
- struct wowlan_key_data key_data = {
- .use_rsc_tsc = false,
- .tkip = &tkip_cmd,
- .use_tkip = false,
- };
- int ret;
-
- ret = iwl_mvm_switch_to_d3(mvm);
+ ret = iwl_mvm_load_d3_fw(mvm);
if (ret)
- return ret;
+ goto out;
ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta);
if (ret)
- return ret;
-
- key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL);
- if (!key_data.rsc_tsc)
- return -ENOMEM;
+ goto out;
if (!iwlwifi_mod_params.sw_crypto) {
/*
@@ -933,9 +1010,7 @@
}
}
- ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
- sizeof(*wowlan_config_cmd),
- wowlan_config_cmd);
+ ret = iwl_mvm_send_wowlan_config_cmd(mvm, &wowlan_config_cmd);
if (ret)
goto out;
@@ -948,153 +1023,8 @@
goto out;
ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp);
-
-out:
- kfree(key_data.rsc_tsc);
- return ret;
-}
-
-static int
-iwl_mvm_netdetect_config(struct iwl_mvm *mvm,
- struct cfg80211_wowlan *wowlan,
- struct cfg80211_sched_scan_request *nd_config,
- struct ieee80211_vif *vif)
-{
- struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
- int ret;
-
- ret = iwl_mvm_switch_to_d3(mvm);
if (ret)
- return ret;
-
- /* rfkill release can be either for wowlan or netdetect */
- if (wowlan->rfkill_release)
- wowlan_config_cmd.wakeup_filter |=
- cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT);
-
- ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
- sizeof(wowlan_config_cmd),
- &wowlan_config_cmd);
- if (ret)
- return ret;
-
- ret = iwl_mvm_scan_offload_start(mvm, vif, nd_config, &mvm->nd_ies);
- if (ret)
- return ret;
-
- if (WARN_ON(mvm->nd_match_sets || mvm->nd_channels))
- return -EBUSY;
-
- /* save the sched scan matchsets... */
- if (nd_config->n_match_sets) {
- mvm->nd_match_sets = kmemdup(nd_config->match_sets,
- sizeof(*nd_config->match_sets) *
- nd_config->n_match_sets,
- GFP_KERNEL);
- if (mvm->nd_match_sets)
- mvm->n_nd_match_sets = nd_config->n_match_sets;
- }
-
- /* ...and the sched scan channels for later reporting */
- mvm->nd_channels = kmemdup(nd_config->channels,
- sizeof(*nd_config->channels) *
- nd_config->n_channels,
- GFP_KERNEL);
- if (mvm->nd_channels)
- mvm->n_nd_channels = nd_config->n_channels;
-
- return 0;
-}
-
-static void iwl_mvm_free_nd(struct iwl_mvm *mvm)
-{
- kfree(mvm->nd_match_sets);
- mvm->nd_match_sets = NULL;
- mvm->n_nd_match_sets = 0;
- kfree(mvm->nd_channels);
- mvm->nd_channels = NULL;
- mvm->n_nd_channels = 0;
-}
-
-static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
- struct cfg80211_wowlan *wowlan,
- bool test)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct ieee80211_vif *vif = NULL;
- struct iwl_mvm_vif *mvmvif = NULL;
- struct ieee80211_sta *ap_sta = NULL;
- struct iwl_d3_manager_config d3_cfg_cmd_data = {
- /*
- * Program the minimum sleep time to 10 seconds, as many
- * platforms have issues processing a wakeup signal while
- * still being in the process of suspending.
- */
- .min_sleep_time = cpu_to_le32(10 * 1000 * 1000),
- };
- struct iwl_host_cmd d3_cfg_cmd = {
- .id = D3_CONFIG_CMD,
- .flags = CMD_WANT_SKB,
- .data[0] = &d3_cfg_cmd_data,
- .len[0] = sizeof(d3_cfg_cmd_data),
- };
- int ret;
- int len __maybe_unused;
-
- if (!wowlan) {
- /*
- * mac80211 shouldn't get here, but for D3 test
- * it doesn't warrant a warning
- */
- WARN_ON(!test);
- return -EINVAL;
- }
-
- mutex_lock(&mvm->mutex);
-
- vif = iwl_mvm_get_bss_vif(mvm);
- if (IS_ERR_OR_NULL(vif)) {
- ret = 1;
- goto out_noreset;
- }
-
- mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) {
- /* if we're not associated, this must be netdetect */
- if (!wowlan->nd_config && !mvm->nd_config) {
- ret = 1;
- goto out_noreset;
- }
-
- ret = iwl_mvm_netdetect_config(
- mvm, wowlan, wowlan->nd_config ?: mvm->nd_config, vif);
- if (ret)
- goto out;
-
- mvm->net_detect = true;
- } else {
- struct iwl_wowlan_config_cmd wowlan_config_cmd = {};
-
- ap_sta = rcu_dereference_protected(
- mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
- lockdep_is_held(&mvm->mutex));
- if (IS_ERR_OR_NULL(ap_sta)) {
- ret = -EINVAL;
- goto out_noreset;
- }
-
- ret = iwl_mvm_get_wowlan_config(mvm, wowlan, &wowlan_config_cmd,
- vif, mvmvif, ap_sta);
- if (ret)
- goto out_noreset;
- ret = iwl_mvm_wowlan_config(mvm, wowlan, &wowlan_config_cmd,
- vif, mvmvif, ap_sta);
- if (ret)
- goto out;
-
- mvm->net_detect = false;
- }
+ goto out;
ret = iwl_mvm_power_update_device(mvm);
if (ret)
@@ -1127,11 +1057,11 @@
iwl_trans_d3_suspend(mvm->trans, test);
out:
- if (ret < 0) {
+ if (ret < 0)
ieee80211_restart_hw(mvm->hw);
- iwl_mvm_free_nd(mvm);
- }
out_noreset:
+ kfree(key_data.rsc_tsc);
+
mutex_unlock(&mvm->mutex);
return ret;
@@ -1141,7 +1071,6 @@
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- iwl_trans_suspend(mvm->trans);
if (iwl_mvm_is_d0i3_supported(mvm)) {
mutex_lock(&mvm->d0i3_suspend_mutex);
__set_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
@@ -1520,8 +1449,9 @@
return true;
}
-static struct iwl_wowlan_status *
-iwl_mvm_get_wakeup_status(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+/* releases the MVM mutex */
+static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
u32 base = mvm->error_event_table;
struct error_table_start {
@@ -1533,15 +1463,19 @@
.id = WOWLAN_GET_STATUSES,
.flags = CMD_WANT_SKB,
};
- struct iwl_wowlan_status *status, *fw_status;
- int ret, len, status_size;
+ struct iwl_wowlan_status_data status;
+ struct iwl_wowlan_status *fw_status;
+ int ret, len, status_size, i;
+ bool keep;
+ struct ieee80211_sta *ap_sta;
+ struct iwl_mvm_sta *mvm_ap_sta;
iwl_trans_read_mem_bytes(mvm->trans, base,
&err_info, sizeof(err_info));
if (err_info.valid) {
- IWL_INFO(mvm, "error table is valid (%d) with error (%d)\n",
- err_info.valid, err_info.error_id);
+ IWL_INFO(mvm, "error table is valid (%d)\n",
+ err_info.valid);
if (err_info.error_id == RF_KILL_INDICATOR_FOR_WOWLAN) {
struct cfg80211_wowlan_wakeup wakeup = {
.rfkill_release = true,
@@ -1549,7 +1483,7 @@
ieee80211_report_wowlan_wakeup(vif, &wakeup,
GFP_KERNEL);
}
- return ERR_PTR(-EIO);
+ goto out_unlock;
}
/* only for tracing for now */
@@ -1560,53 +1494,22 @@
ret = iwl_mvm_send_cmd(mvm, &cmd);
if (ret) {
IWL_ERR(mvm, "failed to query status (%d)\n", ret);
- return ERR_PTR(ret);
+ goto out_unlock;
}
/* RF-kill already asserted again... */
- if (!cmd.resp_pkt) {
- ret = -ERFKILL;
- goto out_free_resp;
- }
+ if (!cmd.resp_pkt)
+ goto out_unlock;
status_size = sizeof(*fw_status);
len = iwl_rx_packet_payload_len(cmd.resp_pkt);
if (len < status_size) {
IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
- ret = -EIO;
goto out_free_resp;
}
- status = (void *)cmd.resp_pkt->data;
- if (len != (status_size +
- ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4))) {
- IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
- ret = -EIO;
- goto out_free_resp;
- }
-
- fw_status = kmemdup(status, len, GFP_KERNEL);
-
-out_free_resp:
- iwl_free_resp(&cmd);
- return ret ? ERR_PTR(ret) : fw_status;
-}
-
-/* releases the MVM mutex */
-static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct iwl_wowlan_status_data status;
- struct iwl_wowlan_status *fw_status;
- int i;
- bool keep;
- struct ieee80211_sta *ap_sta;
- struct iwl_mvm_sta *mvm_ap_sta;
-
- fw_status = iwl_mvm_get_wakeup_status(mvm, vif);
- if (IS_ERR_OR_NULL(fw_status))
- goto out_unlock;
+ fw_status = (void *)cmd.resp_pkt->data;
status.pattern_number = le16_to_cpu(fw_status->pattern_number);
for (i = 0; i < 8; i++)
@@ -1619,12 +1522,17 @@
le32_to_cpu(fw_status->wake_packet_bufsize);
status.wake_packet = fw_status->wake_packet;
+ if (len != status_size + ALIGN(status.wake_packet_bufsize, 4)) {
+ IWL_ERR(mvm, "Invalid WoWLAN status response!\n");
+ goto out_free_resp;
+ }
+
/* still at hard-coded place 0 for D3 image */
ap_sta = rcu_dereference_protected(
mvm->fw_id_to_mac_id[0],
lockdep_is_held(&mvm->mutex));
if (IS_ERR_OR_NULL(ap_sta))
- goto out_free;
+ goto out_free_resp;
mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv;
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
@@ -1641,151 +1549,16 @@
keep = iwl_mvm_setup_connection_keep(mvm, vif, fw_status);
- kfree(fw_status);
+ iwl_free_resp(&cmd);
return keep;
-out_free:
- kfree(fw_status);
-out_unlock:
+ out_free_resp:
+ iwl_free_resp(&cmd);
+ out_unlock:
mutex_unlock(&mvm->mutex);
return false;
}
-struct iwl_mvm_nd_query_results {
- u32 matched_profiles;
- struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
-};
-
-static int
-iwl_mvm_netdetect_query_results(struct iwl_mvm *mvm,
- struct iwl_mvm_nd_query_results *results)
-{
- struct iwl_scan_offload_profiles_query *query;
- struct iwl_host_cmd cmd = {
- .id = SCAN_OFFLOAD_PROFILES_QUERY_CMD,
- .flags = CMD_WANT_SKB,
- };
- int ret, len;
-
- ret = iwl_mvm_send_cmd(mvm, &cmd);
- if (ret) {
- IWL_ERR(mvm, "failed to query matched profiles (%d)\n", ret);
- return ret;
- }
-
- /* RF-kill already asserted again... */
- if (!cmd.resp_pkt) {
- ret = -ERFKILL;
- goto out_free_resp;
- }
-
- len = iwl_rx_packet_payload_len(cmd.resp_pkt);
- if (len < sizeof(*query)) {
- IWL_ERR(mvm, "Invalid scan offload profiles query response!\n");
- ret = -EIO;
- goto out_free_resp;
- }
-
- query = (void *)cmd.resp_pkt->data;
-
- results->matched_profiles = le32_to_cpu(query->matched_profiles);
- memcpy(results->matches, query->matches, sizeof(results->matches));
-
-out_free_resp:
- iwl_free_resp(&cmd);
- return ret;
-}
-
-static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif)
-{
- struct cfg80211_wowlan_nd_info *net_detect = NULL;
- struct cfg80211_wowlan_wakeup wakeup = {
- .pattern_idx = -1,
- };
- struct cfg80211_wowlan_wakeup *wakeup_report = &wakeup;
- struct iwl_mvm_nd_query_results query;
- struct iwl_wowlan_status *fw_status;
- unsigned long matched_profiles;
- u32 reasons = 0;
- int i, j, n_matches, ret;
-
- fw_status = iwl_mvm_get_wakeup_status(mvm, vif);
- if (!IS_ERR_OR_NULL(fw_status))
- reasons = le32_to_cpu(fw_status->wakeup_reasons);
-
- if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED)
- wakeup.rfkill_release = true;
-
- if (reasons != IWL_WOWLAN_WAKEUP_BY_NON_WIRELESS)
- goto out;
-
- ret = iwl_mvm_netdetect_query_results(mvm, &query);
- if (ret || !query.matched_profiles) {
- wakeup_report = NULL;
- goto out;
- }
-
- matched_profiles = query.matched_profiles;
- if (mvm->n_nd_match_sets) {
- n_matches = hweight_long(matched_profiles);
- } else {
- IWL_ERR(mvm, "no net detect match information available\n");
- n_matches = 0;
- }
-
- net_detect = kzalloc(sizeof(*net_detect) +
- (n_matches * sizeof(net_detect->matches[0])),
- GFP_KERNEL);
- if (!net_detect || !n_matches)
- goto out_report_nd;
-
- for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) {
- struct iwl_scan_offload_profile_match *fw_match;
- struct cfg80211_wowlan_nd_match *match;
- int n_channels = 0;
-
- fw_match = &query.matches[i];
-
- for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN; j++)
- n_channels += hweight8(fw_match->matching_channels[j]);
-
- match = kzalloc(sizeof(*match) +
- (n_channels * sizeof(*match->channels)),
- GFP_KERNEL);
- if (!match)
- goto out_report_nd;
-
- net_detect->matches[net_detect->n_matches++] = match;
-
- match->ssid.ssid_len = mvm->nd_match_sets[i].ssid.ssid_len;
- memcpy(match->ssid.ssid, mvm->nd_match_sets[i].ssid.ssid,
- match->ssid.ssid_len);
-
- if (mvm->n_nd_channels < n_channels)
- continue;
-
- for (j = 0; j < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; j++)
- if (fw_match->matching_channels[j / 8] & (BIT(j % 8)))
- match->channels[match->n_channels++] =
- mvm->nd_channels[j]->center_freq;
- }
-
-out_report_nd:
- wakeup.net_detect = net_detect;
-out:
- iwl_mvm_free_nd(mvm);
-
- mutex_unlock(&mvm->mutex);
- ieee80211_report_wowlan_wakeup(vif, wakeup_report, GFP_KERNEL);
-
- if (net_detect) {
- for (i = 0; i < net_detect->n_matches; i++)
- kfree(net_detect->matches[i]);
- kfree(net_detect);
- }
-}
-
static void iwl_mvm_read_d3_sram(struct iwl_mvm *mvm)
{
#ifdef CPTCFG_IWLWIFI_DEBUGFS
@@ -1819,6 +1592,9 @@
static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test)
{
+ struct iwl_d3_iter_data resume_iter_data = {
+ .mvm = mvm,
+ };
struct ieee80211_vif *vif = NULL;
int ret;
enum iwl_d3_status d3_status;
@@ -1827,10 +1603,15 @@
mutex_lock(&mvm->mutex);
/* get the BSS vif pointer again */
- vif = iwl_mvm_get_bss_vif(mvm);
- if (IS_ERR_OR_NULL(vif))
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_d3_iface_iterator, &resume_iter_data);
+
+ if (WARN_ON(resume_iter_data.error || !resume_iter_data.vif))
goto out_unlock;
+ vif = resume_iter_data.vif;
+
ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test);
if (ret)
goto out_unlock;
@@ -1843,15 +1624,11 @@
/* query SRAM first in case we want event logging */
iwl_mvm_read_d3_sram(mvm);
- if (mvm->net_detect) {
- iwl_mvm_query_netdetect_reasons(mvm, vif);
- } else {
- keep = iwl_mvm_query_wakeup_reasons(mvm, vif);
+ keep = iwl_mvm_query_wakeup_reasons(mvm, vif);
#ifdef CPTCFG_IWLWIFI_DEBUGFS
- if (keep)
- mvm->keep_vif = vif;
+ if (keep)
+ mvm->keep_vif = vif;
#endif
- }
/* has unlocked the mutex, so skip that */
goto out;
@@ -1866,7 +1643,6 @@
/* return 1 to reconfigure the device */
set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);
- set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status);
return 1;
}
@@ -1874,10 +1650,18 @@
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- iwl_trans_resume(mvm->trans);
+ if (iwl_mvm_is_d0i3_supported(mvm)) {
+ bool exit_now;
- if (iwl_mvm_is_d0i3_supported(mvm))
+ mutex_lock(&mvm->d0i3_suspend_mutex);
+ __clear_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
+ exit_now = __test_and_clear_bit(D0I3_PENDING_WAKEUP,
+ &mvm->d0i3_suspend_flags);
+ mutex_unlock(&mvm->d0i3_suspend_mutex);
+ if (exit_now)
+ _iwl_mvm_exit_d0i3(mvm);
return 0;
+ }
return __iwl_mvm_resume(mvm, false);
}
@@ -1957,9 +1741,7 @@
int remaining_time = 10;
mvm->d3_test_active = false;
- rtnl_lock();
__iwl_mvm_resume(mvm, true);
- rtnl_unlock();
iwl_abort_notification_waits(&mvm->notif_wait);
ieee80211_restart_hw(mvm->hw);
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index 2c87e2d..7765c2b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -121,6 +121,78 @@
return ret;
}
+static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file)
+{
+ struct iwl_mvm *mvm = inode->i_private;
+ int ret;
+
+ if (!mvm)
+ return -EINVAL;
+
+ mutex_lock(&mvm->mutex);
+ if (!mvm->fw_error_dump) {
+ ret = -ENODATA;
+ goto out;
+ }
+
+ file->private_data = mvm->fw_error_dump;
+ mvm->fw_error_dump = NULL;
+ ret = 0;
+
+out:
+ mutex_unlock(&mvm->mutex);
+ return ret;
+}
+
+static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file,
+ char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
+ ssize_t bytes_read = 0;
+ ssize_t bytes_read_trans = 0;
+
+ if (*ppos < dump_ptrs->op_mode_len)
+ bytes_read +=
+ simple_read_from_buffer(user_buf, count, ppos,
+ dump_ptrs->op_mode_ptr,
+ dump_ptrs->op_mode_len);
+
+ if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len)
+ return bytes_read;
+
+ if (dump_ptrs->trans_ptr) {
+ *ppos -= dump_ptrs->op_mode_len;
+ bytes_read_trans =
+ simple_read_from_buffer(user_buf + bytes_read,
+ count - bytes_read, ppos,
+ dump_ptrs->trans_ptr->data,
+ dump_ptrs->trans_ptr->len);
+ *ppos += dump_ptrs->op_mode_len;
+
+ if (bytes_read_trans >= 0)
+ bytes_read += bytes_read_trans;
+ else if (!bytes_read)
+ /* propagate the failure */
+ return bytes_read_trans;
+ }
+
+ return bytes_read;
+
+}
+
+static int iwl_dbgfs_fw_error_dump_release(struct inode *inode,
+ struct file *file)
+{
+ struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data;
+
+ vfree(dump_ptrs->op_mode_ptr);
+ vfree(dump_ptrs->trans_ptr);
+ kfree(dump_ptrs);
+
+ return 0;
+}
+
static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -936,11 +1008,7 @@
if (scan_rx_ant & ~mvm->fw->valid_rx_ant)
return -EINVAL;
- if (mvm->scan_rx_ant != scan_rx_ant) {
- mvm->scan_rx_ant = scan_rx_ant;
- if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
- iwl_mvm_config_scan(mvm);
- }
+ mvm->scan_rx_ant = scan_rx_ant;
return count;
}
@@ -1182,118 +1250,6 @@
return ret;
}
-
-#define MAX_NUM_ND_MATCHSETS 10
-
-static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf,
- size_t count, loff_t *ppos)
-{
- const char *seps = ",\n";
- char *buf_ptr = buf;
- char *value_str = NULL;
- int ret, i;
-
- /* TODO: don't free if write is being called several times in one go */
- if (mvm->nd_config) {
- kfree(mvm->nd_config->match_sets);
- kfree(mvm->nd_config);
- mvm->nd_config = NULL;
- }
-
- mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) +
- (11 * sizeof(struct ieee80211_channel *)),
- GFP_KERNEL);
- if (!mvm->nd_config) {
- ret = -ENOMEM;
- goto out_free;
- }
-
- mvm->nd_config->n_channels = 11;
- mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20;
- mvm->nd_config->interval = 5;
- mvm->nd_config->min_rssi_thold = -80;
- for (i = 0; i < mvm->nd_config->n_channels; i++)
- mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i];
-
- mvm->nd_config->match_sets =
- kcalloc(MAX_NUM_ND_MATCHSETS,
- sizeof(*mvm->nd_config->match_sets),
- GFP_KERNEL);
- if (!mvm->nd_config->match_sets) {
- ret = -ENOMEM;
- goto out_free;
- }
-
- while ((value_str = strsep(&buf_ptr, seps)) &&
- strlen(value_str)) {
- struct cfg80211_match_set *set;
-
- if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) {
- ret = -EINVAL;
- goto out_free;
- }
-
- set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets];
- set->ssid.ssid_len = strlen(value_str);
-
- if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) {
- ret = -EINVAL;
- goto out_free;
- }
-
- memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len);
-
- mvm->nd_config->n_match_sets++;
- }
-
- ret = count;
-
- if (mvm->nd_config->n_match_sets)
- goto out;
-
-out_free:
- if (mvm->nd_config)
- kfree(mvm->nd_config->match_sets);
- kfree(mvm->nd_config);
- mvm->nd_config = NULL;
-out:
- return ret;
-}
-
-static ssize_t
-iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct iwl_mvm *mvm = file->private_data;
- size_t bufsz, ret;
- char *buf;
- int i, n_match_sets, pos = 0;
-
- n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0;
-
- bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1;
- buf = kzalloc(bufsz, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- for (i = 0; i < n_match_sets; i++) {
- if (pos +
- mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) {
- ret = -EIO;
- goto out;
- }
-
- memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid,
- mvm->nd_config->match_sets[i].ssid.ssid_len);
- pos += mvm->nd_config->match_sets[i].ssid.ssid_len;
- buf[pos++] = '\n';
- }
-
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-out:
- kfree(buf);
- return ret;
-}
#endif
#define PRINT_MVM_REF(ref) do { \
@@ -1339,7 +1295,6 @@
PRINT_MVM_REF(IWL_MVM_REF_NMI);
PRINT_MVM_REF(IWL_MVM_REF_TM_CMD);
PRINT_MVM_REF(IWL_MVM_REF_EXIT_WORK);
- PRINT_MVM_REF(IWL_MVM_REF_PROTECT_CSA);
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
@@ -1460,6 +1415,12 @@
MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8);
+static const struct file_operations iwl_dbgfs_fw_error_dump_ops = {
+ .open = iwl_dbgfs_fw_error_dump_open,
+ .read = iwl_dbgfs_fw_error_dump_read,
+ .release = iwl_dbgfs_fw_error_dump_release,
+};
+
#ifdef CPTCFG_IWLWIFI_BCAST_FILTERING
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256);
@@ -1467,7 +1428,6 @@
#ifdef CONFIG_PM_SLEEP
MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8);
-MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384);
#endif
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir)
@@ -1486,6 +1446,7 @@
S_IWUSR | S_IRUSR);
MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR);
+ MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR);
MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir,
@@ -1526,7 +1487,6 @@
if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR,
mvm->debugfs_dir, &mvm->d3_wake_sysassert))
goto err;
- MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR);
#endif
if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR,
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
index f3b1189..816883f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-coex.h
@@ -84,8 +84,6 @@
* @BT_COEX_SYNC2SCO:
* @BT_COEX_CORUNNING:
* @BT_COEX_MPLUT:
- * @BT_COEX_TTC:
- * @BT_COEX_RRC:
*
* The COEX_MODE must be set for each command. Even if it is not changed.
*/
@@ -102,8 +100,6 @@
BT_COEX_SYNC2SCO = BIT(7),
BT_COEX_CORUNNING = BIT(8),
BT_COEX_MPLUT = BIT(9),
- BT_COEX_TTC = BIT(20),
- BT_COEX_RRC = BIT(21),
};
/*
@@ -131,8 +127,6 @@
BT_VALID_TXTX_DELTA_FREQ_THRS = BIT(16),
BT_VALID_TXRX_MAX_FREQ_0 = BIT(17),
BT_VALID_SYNC_TO_SCO = BIT(18),
- BT_VALID_TTC = BIT(20),
- BT_VALID_RRC = BIT(21),
};
/**
@@ -512,8 +506,7 @@
u8 bt_agg_traffic_load;
u8 bt_ci_compliance;
u8 ttc_enabled;
- u8 rrc_enabled;
- u8 reserved;
+ __le16 reserved;
__le32 primary_ch_lut;
__le32 secondary_ch_lut;
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
index 6d3bea5..e74cdf2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-d3.h
@@ -241,12 +241,16 @@
IWL_WOWLAN_WAKEUP_BCN_FILTERING = BIT(16),
}; /* WOWLAN_WAKEUP_FILTER_API_E_VER_4 */
-struct iwl_wowlan_config_cmd {
+struct iwl_wowlan_config_cmd_v2 {
__le32 wakeup_filter;
__le16 non_qos_seq;
__le16 qos_seq[8];
u8 wowlan_ba_teardown_tids;
u8 is_11n_connection;
+} __packed; /* WOWLAN_CONFIG_API_S_VER_2 */
+
+struct iwl_wowlan_config_cmd_v3 {
+ struct iwl_wowlan_config_cmd_v2 common;
u8 offloading_tid;
u8 reserved[3];
} __packed; /* WOWLAN_CONFIG_API_S_VER_3 */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
index 4300200..27dd863 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-power.h
@@ -68,46 +68,13 @@
/* Power Management Commands, Responses, Notifications */
-/**
- * enum iwl_ltr_config_flags - masks for LTR config command flags
- * @LTR_CFG_FLAG_FEATURE_ENABLE: Feature operational status
- * @LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS: allow LTR change on shadow
- * memory access
- * @LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH: allow LTR msg send on ANY LTR
- * reg change
- * @LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3: allow LTR msg send on transition from
- * D0 to D3
- * @LTR_CFG_FLAG_SW_SET_SHORT: fixed static short LTR register
- * @LTR_CFG_FLAG_SW_SET_LONG: fixed static short LONG register
- * @LTR_CFG_FLAG_DENIE_C10_ON_PD: allow going into C10 on PD
- */
-enum iwl_ltr_config_flags {
- LTR_CFG_FLAG_FEATURE_ENABLE = BIT(0),
- LTR_CFG_FLAG_HW_DIS_ON_SHADOW_REG_ACCESS = BIT(1),
- LTR_CFG_FLAG_HW_EN_SHRT_WR_THROUGH = BIT(2),
- LTR_CFG_FLAG_HW_DIS_ON_D0_2_D3 = BIT(3),
- LTR_CFG_FLAG_SW_SET_SHORT = BIT(4),
- LTR_CFG_FLAG_SW_SET_LONG = BIT(5),
- LTR_CFG_FLAG_DENIE_C10_ON_PD = BIT(6),
-};
-
-/**
- * struct iwl_ltr_config_cmd - configures the LTR
- * @flags: See %enum iwl_ltr_config_flags
- */
-struct iwl_ltr_config_cmd {
- __le32 flags;
- __le32 static_long;
- __le32 static_short;
-} __packed;
-
/* Radio LP RX Energy Threshold measured in dBm */
#define POWER_LPRX_RSSI_THRESHOLD 75
#define POWER_LPRX_RSSI_THRESHOLD_MAX 94
#define POWER_LPRX_RSSI_THRESHOLD_MIN 30
/**
- * enum iwl_power_flags - masks for power table command flags
+ * enum iwl_scan_flags - masks for power table command flags
* @POWER_FLAGS_POWER_SAVE_ENA_MSK: '1' Allow to save power by turning off
* receiver and transmitter. '0' - does not allow.
* @POWER_FLAGS_POWER_MANAGEMENT_ENA_MSK: '0' Driver disables power management,
@@ -370,7 +337,7 @@
#define IWL_BF_DEBUG_FLAG_DEFAULT 0
#define IWL_BF_DEBUG_FLAG_D0I3 0
-#define IWL_BF_ESCAPE_TIMER_DEFAULT 0
+#define IWL_BF_ESCAPE_TIMER_DEFAULT 50
#define IWL_BF_ESCAPE_TIMER_D0I3 0
#define IWL_BF_ESCAPE_TIMER_MAX 1024
#define IWL_BF_ESCAPE_TIMER_MIN 0
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 1f2acf4..1354c68 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -794,301 +794,4 @@
__le32 reserved;
} __packed;
-/* UMAC Scan API */
-
-/**
- * struct iwl_mvm_umac_cmd_hdr - Command header for UMAC commands
- * @size: size of the command (not including header)
- * @reserved0: for future use and alignment
- * @ver: API version number
- */
-struct iwl_mvm_umac_cmd_hdr {
- __le16 size;
- u8 reserved0;
- u8 ver;
-} __packed;
-
-#define IWL_MVM_MAX_SIMULTANEOUS_SCANS 8
-
-enum scan_config_flags {
- SCAN_CONFIG_FLAG_ACTIVATE = BIT(0),
- SCAN_CONFIG_FLAG_DEACTIVATE = BIT(1),
- SCAN_CONFIG_FLAG_FORBID_CHUB_REQS = BIT(2),
- SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS = BIT(3),
- SCAN_CONFIG_FLAG_SET_TX_CHAINS = BIT(8),
- SCAN_CONFIG_FLAG_SET_RX_CHAINS = BIT(9),
- SCAN_CONFIG_FLAG_SET_AUX_STA_ID = BIT(10),
- SCAN_CONFIG_FLAG_SET_ALL_TIMES = BIT(11),
- SCAN_CONFIG_FLAG_SET_EFFECTIVE_TIMES = BIT(12),
- SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS = BIT(13),
- SCAN_CONFIG_FLAG_SET_LEGACY_RATES = BIT(14),
- SCAN_CONFIG_FLAG_SET_MAC_ADDR = BIT(15),
- SCAN_CONFIG_FLAG_SET_FRAGMENTED = BIT(16),
- SCAN_CONFIG_FLAG_CLEAR_FRAGMENTED = BIT(17),
- SCAN_CONFIG_FLAG_SET_CAM_MODE = BIT(18),
- SCAN_CONFIG_FLAG_CLEAR_CAM_MODE = BIT(19),
- SCAN_CONFIG_FLAG_SET_PROMISC_MODE = BIT(20),
- SCAN_CONFIG_FLAG_CLEAR_PROMISC_MODE = BIT(21),
-
- /* Bits 26-31 are for num of channels in channel_array */
-#define SCAN_CONFIG_N_CHANNELS(n) ((n) << 26)
-};
-
-enum scan_config_rates {
- /* OFDM basic rates */
- SCAN_CONFIG_RATE_6M = BIT(0),
- SCAN_CONFIG_RATE_9M = BIT(1),
- SCAN_CONFIG_RATE_12M = BIT(2),
- SCAN_CONFIG_RATE_18M = BIT(3),
- SCAN_CONFIG_RATE_24M = BIT(4),
- SCAN_CONFIG_RATE_36M = BIT(5),
- SCAN_CONFIG_RATE_48M = BIT(6),
- SCAN_CONFIG_RATE_54M = BIT(7),
- /* CCK basic rates */
- SCAN_CONFIG_RATE_1M = BIT(8),
- SCAN_CONFIG_RATE_2M = BIT(9),
- SCAN_CONFIG_RATE_5M = BIT(10),
- SCAN_CONFIG_RATE_11M = BIT(11),
-
- /* Bits 16-27 are for supported rates */
-#define SCAN_CONFIG_SUPPORTED_RATE(rate) ((rate) << 16)
-};
-
-enum iwl_channel_flags {
- IWL_CHANNEL_FLAG_EBS = BIT(0),
- IWL_CHANNEL_FLAG_ACCURATE_EBS = BIT(1),
- IWL_CHANNEL_FLAG_EBS_ADD = BIT(2),
- IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE = BIT(3),
-};
-
-/**
- * struct iwl_scan_config
- * @hdr: umac command header
- * @flags: enum scan_config_flags
- * @tx_chains: valid_tx antenna - ANT_* definitions
- * @rx_chains: valid_rx antenna - ANT_* definitions
- * @legacy_rates: default legacy rates - enum scan_config_rates
- * @out_of_channel_time: default max out of serving channel time
- * @suspend_time: default max suspend time
- * @dwell_active: default dwell time for active scan
- * @dwell_passive: default dwell time for passive scan
- * @dwell_fragmented: default dwell time for fragmented scan
- * @reserved: for future use and alignment
- * @mac_addr: default mac address to be used in probes
- * @bcast_sta_id: the index of the station in the fw
- * @channel_flags: default channel flags - enum iwl_channel_flags
- * scan_config_channel_flag
- * @channel_array: default supported channels
- */
-struct iwl_scan_config {
- struct iwl_mvm_umac_cmd_hdr hdr;
- __le32 flags;
- __le32 tx_chains;
- __le32 rx_chains;
- __le32 legacy_rates;
- __le32 out_of_channel_time;
- __le32 suspend_time;
- u8 dwell_active;
- u8 dwell_passive;
- u8 dwell_fragmented;
- u8 reserved;
- u8 mac_addr[ETH_ALEN];
- u8 bcast_sta_id;
- u8 channel_flags;
- u8 channel_array[];
-} __packed; /* SCAN_CONFIG_DB_CMD_API_S */
-
-/**
- * iwl_umac_scan_flags
- *@IWL_UMAC_SCAN_FLAG_PREEMPTIVE: scan process triggered by this scan request
- * can be preempted by other scan requests with higher priority.
- * The low priority scan is aborted.
- *@IWL_UMAC_SCAN_FLAG_START_NOTIF: notification will be sent to the driver
- * when scan starts.
- */
-enum iwl_umac_scan_flags {
- IWL_UMAC_SCAN_FLAG_PREEMPTIVE = BIT(0),
- IWL_UMAC_SCAN_FLAG_START_NOTIF = BIT(1),
-};
-
-enum iwl_umac_scan_uid_offsets {
- IWL_UMAC_SCAN_UID_TYPE_OFFSET = 0,
- IWL_UMAC_SCAN_UID_SEQ_OFFSET = 8,
-};
-
-enum iwl_umac_scan_general_flags {
- IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC = BIT(0),
- IWL_UMAC_SCAN_GEN_FLAGS_OVER_BT = BIT(1),
- IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL = BIT(2),
- IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE = BIT(3),
- IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT = BIT(4),
- IWL_UMAC_SCAN_GEN_FLAGS_ITER_COMPLETE = BIT(5),
- IWL_UMAC_SCAN_GEN_FLAGS_MULTIPLE_SSID = BIT(6),
- IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED = BIT(7),
- IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED = BIT(8),
- IWL_UMAC_SCAN_GEN_FLAGS_MATCH = BIT(9)
-};
-
-/**
- * struct iwl_scan_channel_cfg_umac
- * @flags: bitmap - 0-19: directed scan to i'th ssid.
- * @channel_num: channel number 1-13 etc.
- * @iter_count: repetition count for the channel.
- * @iter_interval: interval between two scan interations on one channel.
- */
-struct iwl_scan_channel_cfg_umac {
- __le32 flags;
- u8 channel_num;
- u8 iter_count;
- __le16 iter_interval;
-} __packed; /* SCAN_CHANNEL_CFG_S_VER2 */
-
-/**
- * struct iwl_scan_umac_schedule
- * @interval: interval in seconds between scan iterations
- * @iter_count: num of scan iterations for schedule plan, 0xff for infinite loop
- * @reserved: for alignment and future use
- */
-struct iwl_scan_umac_schedule {
- __le16 interval;
- u8 iter_count;
- u8 reserved;
-} __packed; /* SCAN_SCHED_PARAM_API_S_VER_1 */
-
-/**
- * struct iwl_scan_req_umac_tail - the rest of the UMAC scan request command
- * parameters following channels configuration array.
- * @schedule: two scheduling plans.
- * @delay: delay in TUs before starting the first scan iteration
- * @reserved: for future use and alignment
- * @preq: probe request with IEs blocks
- * @direct_scan: list of SSIDs for directed active scan
- */
-struct iwl_scan_req_umac_tail {
- /* SCAN_PERIODIC_PARAMS_API_S_VER_1 */
- struct iwl_scan_umac_schedule schedule[2];
- __le16 delay;
- __le16 reserved;
- /* SCAN_PROBE_PARAMS_API_S_VER_1 */
- struct iwl_scan_probe_req preq;
- struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
-} __packed;
-
-/**
- * struct iwl_scan_req_umac
- * @hdr: umac command header
- * @flags: &enum iwl_umac_scan_flags
- * @uid: scan id, &enum iwl_umac_scan_uid_offsets
- * @ooc_priority: out of channel priority - &enum iwl_scan_priority
- * @general_flags: &enum iwl_umac_scan_general_flags
- * @reserved1: for future use and alignment
- * @active_dwell: dwell time for active scan
- * @passive_dwell: dwell time for passive scan
- * @fragmented_dwell: dwell time for fragmented passive scan
- * @max_out_time: max out of serving channel time
- * @suspend_time: max suspend time
- * @scan_priority: scan internal prioritization &enum iwl_scan_priority
- * @channel_flags: &enum iwl_scan_channel_flags
- * @n_channels: num of channels in scan request
- * @reserved2: for future use and alignment
- * @data: &struct iwl_scan_channel_cfg_umac and
- * &struct iwl_scan_req_umac_tail
- */
-struct iwl_scan_req_umac {
- struct iwl_mvm_umac_cmd_hdr hdr;
- __le32 flags;
- __le32 uid;
- __le32 ooc_priority;
- /* SCAN_GENERAL_PARAMS_API_S_VER_1 */
- __le32 general_flags;
- u8 reserved1;
- u8 active_dwell;
- u8 passive_dwell;
- u8 fragmented_dwell;
- __le32 max_out_time;
- __le32 suspend_time;
- __le32 scan_priority;
- /* SCAN_CHANNEL_PARAMS_API_S_VER_1 */
- u8 channel_flags;
- u8 n_channels;
- __le16 reserved2;
- u8 data[];
-} __packed; /* SCAN_REQUEST_CMD_UMAC_API_S_VER_1 */
-
-/**
- * struct iwl_umac_scan_abort
- * @hdr: umac command header
- * @uid: scan id, &enum iwl_umac_scan_uid_offsets
- * @flags: reserved
- */
-struct iwl_umac_scan_abort {
- struct iwl_mvm_umac_cmd_hdr hdr;
- __le32 uid;
- __le32 flags;
-} __packed; /* SCAN_ABORT_CMD_UMAC_API_S_VER_1 */
-
-/**
- * struct iwl_umac_scan_complete
- * @uid: scan id, &enum iwl_umac_scan_uid_offsets
- * @last_schedule: last scheduling line
- * @last_iter: last scan iteration number
- * @scan status: &enum iwl_scan_offload_complete_status
- * @ebs_status: &enum iwl_scan_ebs_status
- * @time_from_last_iter: time elapsed from last iteration
- * @reserved: for future use
- */
-struct iwl_umac_scan_complete {
- __le32 uid;
- u8 last_schedule;
- u8 last_iter;
- u8 status;
- u8 ebs_status;
- __le32 time_from_last_iter;
- __le32 reserved;
-} __packed; /* SCAN_COMPLETE_NTF_UMAC_API_S_VER_1 */
-
-#define SCAN_OFFLOAD_MATCHING_CHANNELS_LEN 5
-/**
- * struct iwl_scan_offload_profile_match - match information
- * @bssid: matched bssid
- * @channel: channel where the match occurred
- * @energy:
- * @matching_feature:
- * @matching_channels: bitmap of channels that matched, referencing
- * the channels passed in tue scan offload request
- */
-struct iwl_scan_offload_profile_match {
- u8 bssid[ETH_ALEN];
- __le16 reserved;
- u8 channel;
- u8 energy;
- u8 matching_feature;
- u8 matching_channels[SCAN_OFFLOAD_MATCHING_CHANNELS_LEN];
-} __packed; /* SCAN_OFFLOAD_PROFILE_MATCH_RESULTS_S_VER_1 */
-
-/**
- * struct iwl_scan_offload_profiles_query - match results query response
- * @matched_profiles: bitmap of matched profiles, referencing the
- * matches passed in the scan offload request
- * @last_scan_age: age of the last offloaded scan
- * @n_scans_done: number of offloaded scans done
- * @gp2_d0u: GP2 when D0U occurred
- * @gp2_invoked: GP2 when scan offload was invoked
- * @resume_while_scanning: not used
- * @self_recovery: obsolete
- * @reserved: reserved
- * @matches: array of match information, one for each match
- */
-struct iwl_scan_offload_profiles_query {
- __le32 matched_profiles;
- __le32 last_scan_age;
- __le32 n_scans_done;
- __le32 gp2_d0u;
- __le32 gp2_invoked;
- u8 resume_while_scanning;
- u8 self_recovery;
- __le16 reserved;
- struct iwl_scan_offload_profile_match matches[IWL_SCAN_MAX_PROFILES];
-} __packed; /* SCAN_OFFLOAD_PROFILES_QUERY_RSP_S_VER_2 */
-
#endif
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
index 88af6dd..667a922 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h
@@ -106,12 +106,6 @@
DBG_CFG = 0x9,
ANTENNA_COUPLING_NOTIFICATION = 0xa,
- /* UMAC scan commands */
- SCAN_CFG_CMD = 0xc,
- SCAN_REQ_UMAC = 0xd,
- SCAN_ABORT_UMAC = 0xe,
- SCAN_COMPLETE_UMAC = 0xf,
-
/* station table */
ADD_STA_KEY = 0x17,
ADD_STA = 0x18,
@@ -128,11 +122,6 @@
/* global key */
WEP_KEY = 0x20,
- /* TDLS */
- TDLS_CHANNEL_SWITCH_CMD = 0x27,
- TDLS_CHANNEL_SWITCH_NOTIFICATION = 0xaa,
- TDLS_CONFIG_CMD = 0xa7,
-
/* MAC and Binding commands */
MAC_CONTEXT_CMD = 0x28,
TIME_EVENT_CMD = 0x29, /* both CMD and response */
@@ -168,7 +157,6 @@
/* Power - legacy power table command */
POWER_TABLE_CMD = 0x77,
PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION = 0x78,
- LTR_CONFIG = 0xee,
/* Thermal Throttling*/
REPLY_THERMAL_MNG_BACKOFF = 0x7e,
@@ -201,8 +189,6 @@
/* Power - new power table command */
MAC_PM_POWER_TABLE = 0xa9,
- MFUART_LOAD_NOTIFICATION = 0xb1,
-
REPLY_RX_PHY_CMD = 0xc0,
REPLY_RX_MPDU_CMD = 0xc1,
BA_NOTIF = 0xc5,
@@ -249,9 +235,11 @@
WOWLAN_TX_POWER_PER_DB = 0xe6,
/* and for NetDetect */
- SCAN_OFFLOAD_PROFILES_QUERY_CMD = 0x56,
- SCAN_OFFLOAD_HOTSPOTS_CONFIG_CMD = 0x58,
- SCAN_OFFLOAD_HOTSPOTS_QUERY_CMD = 0x59,
+ NET_DETECT_CONFIG_CMD = 0x54,
+ NET_DETECT_PROFILES_QUERY_CMD = 0x56,
+ NET_DETECT_PROFILES_CMD = 0x57,
+ NET_DETECT_HOTSPOTS_CMD = 0x58,
+ NET_DETECT_HOTSPOTS_QUERY_CMD = 0x59,
REPLY_MAX = 0xff,
};
@@ -1212,21 +1200,6 @@
} __packed; /* MISSED_BEACON_NTFY_API_S_VER_3 */
/**
- * struct iwl_mfuart_load_notif - mfuart image version & status
- * ( MFUART_LOAD_NOTIFICATION = 0xb1 )
- * @installed_ver: installed image version
- * @external_ver: external image version
- * @status: MFUART loading status
- * @duration: MFUART loading time
-*/
-struct iwl_mfuart_load_notif {
- __le32 installed_ver;
- __le32 external_ver;
- __le32 status;
- __le32 duration;
-} __packed; /*MFU_LOADER_NTFY_API_S_VER_1*/
-
-/**
* struct iwl_set_calib_default_cmd - set default value for calibration.
* ( SET_CALIB_DEFAULT_CMD = 0x8e )
* @calib_index: the calibration to set value for
@@ -1615,7 +1588,7 @@
#define SF_NUM_TIMEOUT_TYPES 2 /* Aging timer and Idle timer */
/* smart FIFO default values */
-#define SF_W_MARK_SISO 6144
+#define SF_W_MARK_SISO 4096
#define SF_W_MARK_MIMO2 8192
#define SF_W_MARK_MIMO3 6144
#define SF_W_MARK_LEGACY 4096
@@ -1737,145 +1710,4 @@
u8 flags;
} __packed;
-/***********************************
- * TDLS API
- ***********************************/
-
-/* Type of TDLS request */
-enum iwl_tdls_channel_switch_type {
- TDLS_SEND_CHAN_SW_REQ = 0,
- TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH,
- TDLS_MOVE_CH,
-}; /* TDLS_STA_CHANNEL_SWITCH_CMD_TYPE_API_E_VER_1 */
-
-/**
- * Switch timing sub-element in a TDLS channel-switch command
- * @frame_timestamp: GP2 timestamp of channel-switch request/response packet
- * received from peer
- * @max_offchan_duration: What amount of microseconds out of a DTIM is given
- * to the TDLS off-channel communication. For instance if the DTIM is
- * 200TU and the TDLS peer is to be given 25% of the time, the value
- * given will be 50TU, or 50 * 1024 if translated into microseconds.
- * @switch_time: switch time the peer sent in its channel switch timing IE
- * @switch_timout: switch timeout the peer sent in its channel switch timing IE
- */
-struct iwl_tdls_channel_switch_timing {
- __le32 frame_timestamp; /* GP2 time of peer packet Rx */
- __le32 max_offchan_duration; /* given in micro-seconds */
- __le32 switch_time; /* given in micro-seconds */
- __le32 switch_timeout; /* given in micro-seconds */
-} __packed; /* TDLS_STA_CHANNEL_SWITCH_TIMING_DATA_API_S_VER_1 */
-
-#define IWL_TDLS_CH_SW_FRAME_MAX_SIZE 200
-
-/**
- * TDLS channel switch frame template
- *
- * A template representing a TDLS channel-switch request or response frame
- *
- * @switch_time_offset: offset to the channel switch timing IE in the template
- * @tx_cmd: Tx parameters for the frame
- * @data: frame data
- */
-struct iwl_tdls_channel_switch_frame {
- __le32 switch_time_offset;
- struct iwl_tx_cmd tx_cmd;
- u8 data[IWL_TDLS_CH_SW_FRAME_MAX_SIZE];
-} __packed; /* TDLS_STA_CHANNEL_SWITCH_FRAME_API_S_VER_1 */
-
-/**
- * TDLS channel switch command
- *
- * The command is sent to initiate a channel switch and also in response to
- * incoming TDLS channel-switch request/response packets from remote peers.
- *
- * @switch_type: see &enum iwl_tdls_channel_switch_type
- * @peer_sta_id: station id of TDLS peer
- * @ci: channel we switch to
- * @timing: timing related data for command
- * @frame: channel-switch request/response template, depending to switch_type
- */
-struct iwl_tdls_channel_switch_cmd {
- u8 switch_type;
- __le32 peer_sta_id;
- struct iwl_fw_channel_info ci;
- struct iwl_tdls_channel_switch_timing timing;
- struct iwl_tdls_channel_switch_frame frame;
-} __packed; /* TDLS_STA_CHANNEL_SWITCH_CMD_API_S_VER_1 */
-
-/**
- * TDLS channel switch start notification
- *
- * @status: non-zero on success
- * @offchannel_duration: duration given in microseconds
- * @sta_id: peer currently performing the channel-switch with
- */
-struct iwl_tdls_channel_switch_notif {
- __le32 status;
- __le32 offchannel_duration;
- __le32 sta_id;
-} __packed; /* TDLS_STA_CHANNEL_SWITCH_NTFY_API_S_VER_1 */
-
-/**
- * TDLS station info
- *
- * @sta_id: station id of the TDLS peer
- * @tx_to_peer_tid: TID reserved vs. the peer for FW based Tx
- * @tx_to_peer_ssn: initial SSN the FW should use for Tx on its TID vs the peer
- * @is_initiator: 1 if the peer is the TDLS link initiator, 0 otherwise
- */
-struct iwl_tdls_sta_info {
- u8 sta_id;
- u8 tx_to_peer_tid;
- __le16 tx_to_peer_ssn;
- __le32 is_initiator;
-} __packed; /* TDLS_STA_INFO_VER_1 */
-
-/**
- * TDLS basic config command
- *
- * @id_and_color: MAC id and color being configured
- * @tdls_peer_count: amount of currently connected TDLS peers
- * @tx_to_ap_tid: TID reverved vs. the AP for FW based Tx
- * @tx_to_ap_ssn: initial SSN the FW should use for Tx on its TID vs. the AP
- * @sta_info: per-station info. Only the first tdls_peer_count entries are set
- * @pti_req_data_offset: offset of network-level data for the PTI template
- * @pti_req_tx_cmd: Tx parameters for PTI request template
- * @pti_req_template: PTI request template data
- */
-struct iwl_tdls_config_cmd {
- __le32 id_and_color; /* mac id and color */
- u8 tdls_peer_count;
- u8 tx_to_ap_tid;
- __le16 tx_to_ap_ssn;
- struct iwl_tdls_sta_info sta_info[IWL_MVM_TDLS_STA_COUNT];
-
- __le32 pti_req_data_offset;
- struct iwl_tx_cmd pti_req_tx_cmd;
- u8 pti_req_template[0];
-} __packed; /* TDLS_CONFIG_CMD_API_S_VER_1 */
-
-/**
- * TDLS per-station config information from FW
- *
- * @sta_id: station id of the TDLS peer
- * @tx_to_peer_last_seq: last sequence number used by FW during FW-based Tx to
- * the peer
- */
-struct iwl_tdls_config_sta_info_res {
- __le16 sta_id;
- __le16 tx_to_peer_last_seq;
-} __packed; /* TDLS_STA_INFO_RSP_VER_1 */
-
-/**
- * TDLS config information from FW
- *
- * @tx_to_ap_last_seq: last sequence number used by FW during FW-based Tx to AP
- * @sta_info: per-station TDLS config information
- */
-struct iwl_tdls_config_res {
- __le32 tx_to_ap_last_seq;
- struct iwl_tdls_config_sta_info_res sta_info[IWL_MVM_TDLS_STA_COUNT];
-} __packed; /* TDLS_CONFIG_RSP_API_S_VER_1 */
-
#endif /* __fw_api_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index d0fa6e9..23fd711 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -186,12 +186,7 @@
static const u8 alive_cmd[] = { MVM_ALIVE };
struct iwl_sf_region st_fwrd_space;
- if (ucode_type == IWL_UCODE_REGULAR &&
- iwl_fw_dbg_conf_usniffer(mvm->fw, FW_DBG_CUSTOM) &&
- iwl_fw_dbg_conf_enabled(mvm->fw, FW_DBG_CUSTOM))
- fw = iwl_get_ucode_image(mvm, IWL_UCODE_REGULAR_USNIFFER);
- else
- fw = iwl_get_ucode_image(mvm, ucode_type);
+ fw = iwl_get_ucode_image(mvm, ucode_type);
if (WARN_ON(!fw))
return -EINVAL;
mvm->cur_ucode = ucode_type;
@@ -232,10 +227,6 @@
st_fwrd_space.addr = mvm->sf_space.addr;
st_fwrd_space.size = mvm->sf_space.size;
ret = iwl_trans_update_sf(mvm->trans, &st_fwrd_space);
- if (ret) {
- IWL_ERR(mvm, "Failed to update SF size. ret %d\n", ret);
- return ret;
- }
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
@@ -293,7 +284,7 @@
lockdep_assert_held(&mvm->mutex);
- if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating))
+ if (WARN_ON_ONCE(mvm->init_ucode_complete))
return 0;
iwl_init_notification_wait(&mvm->notif_wait,
@@ -343,8 +334,6 @@
goto out;
}
- mvm->calibrating = true;
-
/* Send TX valid antennas before triggering calibrations */
ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret)
@@ -369,17 +358,11 @@
MVM_UCODE_CALIB_TIMEOUT);
if (!ret)
mvm->init_ucode_complete = true;
-
- if (ret && iwl_mvm_is_radio_killed(mvm)) {
- IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n");
- ret = 1;
- }
goto out;
error:
iwl_remove_notification(&mvm->notif_wait, &calib_wait);
out:
- mvm->calibrating = false;
if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) {
/* we want to debug INIT and we have no NVM - fake */
mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) +
@@ -399,42 +382,6 @@
return ret;
}
-static int iwl_mvm_start_fw_dbg_conf(struct iwl_mvm *mvm,
- enum iwl_fw_dbg_conf conf_id)
-{
- u8 *ptr;
- int ret;
- int i;
-
- if (WARN_ONCE(conf_id >= ARRAY_SIZE(mvm->fw->dbg_conf_tlv),
- "Invalid configuration %d\n", conf_id))
- return -EINVAL;
-
- if (!mvm->fw->dbg_conf_tlv[conf_id])
- return -EINVAL;
-
- if (mvm->fw_dbg_conf != FW_DBG_INVALID)
- IWL_WARN(mvm, "FW already configured (%d) - re-configuring\n",
- mvm->fw_dbg_conf);
-
- /* Send all HCMDs for configuring the FW debug */
- ptr = (void *)&mvm->fw->dbg_conf_tlv[conf_id]->hcmd;
- for (i = 0; i < mvm->fw->dbg_conf_tlv[conf_id]->num_of_hcmds; i++) {
- struct iwl_fw_dbg_conf_hcmd *cmd = (void *)ptr;
-
- ret = iwl_mvm_send_cmd_pdu(mvm, cmd->id, 0,
- le16_to_cpu(cmd->len), cmd->data);
- if (ret)
- return ret;
-
- ptr += sizeof(*cmd);
- ptr += le16_to_cpu(cmd->len);
- }
-
- mvm->fw_dbg_conf = conf_id;
- return ret;
-}
-
int iwl_mvm_up(struct iwl_mvm *mvm)
{
int ret, i;
@@ -486,9 +433,6 @@
if (ret)
IWL_ERR(mvm, "Failed to initialize Smart Fifo\n");
- mvm->fw_dbg_conf = FW_DBG_INVALID;
- iwl_mvm_start_fw_dbg_conf(mvm, FW_DBG_CUSTOM);
-
ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant);
if (ret)
goto error;
@@ -510,8 +454,6 @@
for (i = 0; i < IWL_MVM_STATION_COUNT; i++)
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[i], NULL);
- mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT;
-
/* reset quota debouncing buffer - 0xff will yield invalid data */
memset(&mvm->last_quota_cmd, 0xff, sizeof(mvm->last_quota_cmd));
@@ -538,25 +480,10 @@
/* Initialize tx backoffs to the minimal possible */
iwl_mvm_tt_tx_backoff(mvm, 0);
- if (mvm->trans->ltr_enabled) {
- struct iwl_ltr_config_cmd cmd = {
- .flags = cpu_to_le32(LTR_CFG_FLAG_FEATURE_ENABLE),
- };
-
- WARN_ON(iwl_mvm_send_cmd_pdu(mvm, LTR_CONFIG, 0,
- sizeof(cmd), &cmd));
- }
-
ret = iwl_mvm_power_update_device(mvm);
if (ret)
goto error;
- if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
- ret = iwl_mvm_config_scan(mvm);
- if (ret)
- goto error;
- }
-
/* allow FW/transport low power modes if not during restart */
if (!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
@@ -643,19 +570,3 @@
le32_to_cpu(radio_version->radio_dash));
return 0;
}
-
-int iwl_mvm_rx_mfuart_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_mfuart_load_notif *mfuart_notif = (void *)pkt->data;
-
- IWL_DEBUG_INFO(mvm,
- "MFUART: installed ver: 0x%08x, external ver: 0x%08x, status: 0x%08x, duration: 0x%08x\n",
- le32_to_cpu(mfuart_notif->installed_ver),
- le32_to_cpu(mfuart_notif->external_ver),
- le32_to_cpu(mfuart_notif->status),
- le32_to_cpu(mfuart_notif->duration));
- return 0;
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index f6d86cc..0c5c0b0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -83,15 +83,11 @@
struct ieee80211_vif *vif;
unsigned long available_mac_ids[BITS_TO_LONGS(NUM_MAC_INDEX_DRIVER)];
unsigned long available_tsf_ids[BITS_TO_LONGS(NUM_TSF_IDS)];
+ u32 used_hw_queues;
enum iwl_tsf_id preferred_tsf;
bool found_vif;
};
-struct iwl_mvm_hw_queues_iface_iterator_data {
- struct ieee80211_vif *exclude_vif;
- unsigned long used_hw_queues;
-};
-
static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
@@ -201,7 +197,8 @@
/*
* Get the mask of the queues used by the vif
*/
-u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif)
+u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif)
{
u32 qmask = 0, ac;
@@ -217,54 +214,6 @@
return qmask;
}
-static void iwl_mvm_iface_hw_queues_iter(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_hw_queues_iface_iterator_data *data = _data;
-
- /* exclude the given vif */
- if (vif == data->exclude_vif)
- return;
-
- data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif);
-}
-
-static void iwl_mvm_mac_sta_hw_queues_iter(void *_data,
- struct ieee80211_sta *sta)
-{
- struct iwl_mvm_hw_queues_iface_iterator_data *data = _data;
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
-
- /* Mark the queues used by the sta */
- data->used_hw_queues |= mvmsta->tfd_queue_msk;
-}
-
-unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
- struct ieee80211_vif *exclude_vif)
-{
- struct iwl_mvm_hw_queues_iface_iterator_data data = {
- .exclude_vif = exclude_vif,
- .used_hw_queues =
- BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
- BIT(mvm->aux_queue) |
- BIT(IWL_MVM_CMD_QUEUE),
- };
-
- lockdep_assert_held(&mvm->mutex);
-
- /* mark all VIF used hw queues */
- ieee80211_iterate_active_interfaces_atomic(
- mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
- iwl_mvm_iface_hw_queues_iter, &data);
-
- /* don't assign the same hw queues as TDLS stations */
- ieee80211_iterate_stations_atomic(mvm->hw,
- iwl_mvm_mac_sta_hw_queues_iter,
- &data);
-
- return data.used_hw_queues;
-}
-
static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac,
struct ieee80211_vif *vif)
{
@@ -277,6 +226,9 @@
return;
}
+ /* Mark the queues used by the vif */
+ data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(data->mvm, vif);
+
/* Mark MAC IDs as used by clearing the available bit, and
* (below) mark TSFs as used if their existing use is not
* compatible with the new interface type.
@@ -323,6 +275,10 @@
.available_tsf_ids = { (1 << NUM_TSF_IDS) - 1 },
/* no preference yet */
.preferred_tsf = NUM_TSF_IDS,
+ .used_hw_queues =
+ BIT(IWL_MVM_OFFCHANNEL_QUEUE) |
+ BIT(mvm->aux_queue) |
+ BIT(IWL_MVM_CMD_QUEUE),
.found_vif = false,
};
u32 ac;
@@ -361,8 +317,6 @@
mvm->hw, IEEE80211_IFACE_ITER_RESUME_ALL,
iwl_mvm_mac_iface_iterator, &data);
- used_hw_queues = iwl_mvm_get_used_hw_queues(mvm, vif);
-
/*
* In the case we're getting here during resume, it's similar to
* firmware restart, and with RESUME_ALL the iterator will find
@@ -412,6 +366,8 @@
return 0;
}
+ used_hw_queues = data.used_hw_queues;
+
/* Find available queues, and allocate them to the ACs */
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
u8 queue = find_first_zero_bit(&used_hw_queues,
@@ -1263,25 +1219,17 @@
}
static void iwl_mvm_csa_count_down(struct iwl_mvm *mvm,
- struct ieee80211_vif *csa_vif, u32 gp2,
- bool tx_success)
+ struct ieee80211_vif *csa_vif, u32 gp2)
{
struct iwl_mvm_vif *mvmvif =
iwl_mvm_vif_from_mac80211(csa_vif);
- /* Don't start to countdown from a failed beacon */
- if (!tx_success && !mvmvif->csa_countdown)
- return;
-
- mvmvif->csa_countdown = true;
-
if (!ieee80211_csa_is_complete(csa_vif)) {
int c = ieee80211_csa_update_counter(csa_vif);
iwl_mvm_mac_ctxt_beacon_changed(mvm, csa_vif);
if (csa_vif->p2p &&
- !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2 &&
- tx_success) {
+ !iwl_mvm_te_scheduled(&mvmvif->time_event_data) && gp2) {
u32 rel_time = (c + 1) *
csa_vif->bss_conf.beacon_int -
IWL_MVM_CHANNEL_SWITCH_TIME_GO;
@@ -1304,30 +1252,38 @@
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
struct iwl_mvm_tx_resp *beacon_notify_hdr;
struct ieee80211_vif *csa_vif;
struct ieee80211_vif *tx_blocked_vif;
- u16 status;
+ u64 tsf;
lockdep_assert_held(&mvm->mutex);
- beacon_notify_hdr = &beacon->beacon_notify_hdr;
- mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_CAPA_EXTENDED_BEACON) {
+ struct iwl_extended_beacon_notif *beacon = (void *)pkt->data;
- status = le16_to_cpu(beacon_notify_hdr->status.status) & TX_STATUS_MSK;
+ beacon_notify_hdr = &beacon->beacon_notify_hdr;
+ tsf = le64_to_cpu(beacon->tsf);
+ mvm->ap_last_beacon_gp2 = le32_to_cpu(beacon->gp2);
+ } else {
+ struct iwl_beacon_notif *beacon = (void *)pkt->data;
+
+ beacon_notify_hdr = &beacon->beacon_notify_hdr;
+ tsf = le64_to_cpu(beacon->tsf);
+ }
+
IWL_DEBUG_RX(mvm,
"beacon status %#x retries:%d tsf:0x%16llX gp2:0x%X rate:%d\n",
- status, beacon_notify_hdr->failure_frame,
- le64_to_cpu(beacon->tsf),
+ le16_to_cpu(beacon_notify_hdr->status.status) &
+ TX_STATUS_MSK,
+ beacon_notify_hdr->failure_frame, tsf,
mvm->ap_last_beacon_gp2,
le32_to_cpu(beacon_notify_hdr->initial_rate));
csa_vif = rcu_dereference_protected(mvm->csa_vif,
lockdep_is_held(&mvm->mutex));
if (unlikely(csa_vif && csa_vif->csa_active))
- iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2,
- (status == TX_STATUS_SUCCESS));
+ iwl_mvm_csa_count_down(mvm, csa_vif, mvm->ap_last_beacon_gp2);
tx_blocked_vif = rcu_dereference_protected(mvm->csa_tx_blocked_vif,
lockdep_is_held(&mvm->mutex));
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 137f3da..fec128f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -69,7 +69,6 @@
#include <linux/etherdevice.h>
#include <linux/ip.h>
#include <linux/if_arp.h>
-#include <linux/devcoredump.h>
#include <net/mac80211.h>
#include <net/ieee80211_radiotap.h>
#include <net/tcp.h>
@@ -254,26 +253,6 @@
spin_unlock_bh(&mvm->refs_lock);
}
-bool iwl_mvm_ref_taken(struct iwl_mvm *mvm)
-{
- int i;
- bool taken = false;
-
- if (!iwl_mvm_is_d0i3_supported(mvm))
- return true;
-
- spin_lock_bh(&mvm->refs_lock);
- for (i = 0; i < IWL_MVM_REF_COUNT; i++) {
- if (mvm->refs[i]) {
- taken = true;
- break;
- }
- }
- spin_unlock_bh(&mvm->refs_lock);
-
- return taken;
-}
-
int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type)
{
iwl_mvm_ref(mvm, ref_type);
@@ -323,8 +302,7 @@
hw->offchannel_tx_hw_queue = IWL_MVM_OFFCHANNEL_QUEUE;
hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
IEEE80211_RADIOTAP_MCS_HAVE_STBC;
- hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
- IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED;
+ hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC;
hw->rate_control_algorithm = "iwl-mvm-rs";
/*
@@ -337,19 +315,15 @@
hw->flags |= IEEE80211_HW_MFP_CAPABLE;
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
+ IWL_UCODE_API(mvm->fw->ucode_ver) >= 9 &&
!iwlwifi_mod_params.uapsd_disable) {
hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
hw->uapsd_queues = IWL_MVM_UAPSD_QUEUES;
hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
}
- if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN ||
- mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
- hw->wiphy->features |=
- NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
- NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
- }
hw->sta_data_size = sizeof(struct iwl_mvm_sta);
hw->vif_data_size = sizeof(struct iwl_mvm_vif);
@@ -369,7 +343,8 @@
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD)
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
- hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_CSA_FLOW)
+ hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
hw->wiphy->n_iface_combinations =
@@ -427,8 +402,7 @@
NL80211_FEATURE_LOW_PRIORITY_SCAN |
NL80211_FEATURE_P2P_GO_OPPPS |
NL80211_FEATURE_DYNAMIC_SMPS |
- NL80211_FEATURE_STATIC_SMPS |
- NL80211_FEATURE_SUPPORTS_WMM_ADMISSION;
+ NL80211_FEATURE_STATIC_SMPS;
if (mvm->fw->ucode_capa.capa[0] &
IWL_UCODE_TLV_CAPA_TXPOWER_INSERTION_SUPPORT)
@@ -466,8 +440,7 @@
mvm->wowlan.flags = WIPHY_WOWLAN_MAGIC_PKT |
WIPHY_WOWLAN_DISCONNECT |
WIPHY_WOWLAN_EAP_IDENTITY_REQ |
- WIPHY_WOWLAN_RFKILL_RELEASE |
- WIPHY_WOWLAN_NET_DETECT;
+ WIPHY_WOWLAN_RFKILL_RELEASE;
if (!iwlwifi_mod_params.sw_crypto)
mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
WIPHY_WOWLAN_GTK_REKEY_FAILURE |
@@ -476,7 +449,6 @@
mvm->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS;
mvm->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN;
mvm->wowlan.pattern_max_len = IWL_WOWLAN_MAX_PATTERN_LEN;
- mvm->wowlan.max_nd_match_sets = IWL_SCAN_MAX_PROFILES;
mvm->wowlan.tcp = &iwl_mvm_wowlan_tcp_support;
hw->wiphy->wowlan = &mvm->wowlan;
}
@@ -491,17 +463,6 @@
if (ret)
return ret;
- if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_TDLS_SUPPORT) {
- IWL_DEBUG_TDLS(mvm, "TDLS supported\n");
- hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS;
- }
-
- if (mvm->fw->ucode_capa.capa[0] &
- IWL_UCODE_TLV_CAPA_TDLS_CHANNEL_SWITCH) {
- IWL_DEBUG_TDLS(mvm, "TDLS channel switch supported\n");
- hw->wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
- }
-
ret = ieee80211_register_hw(mvm->hw);
if (ret)
iwl_mvm_leds_exit(mvm);
@@ -565,8 +526,7 @@
}
if (IEEE80211_SKB_CB(skb)->hw_queue == IWL_MVM_OFFCHANNEL_QUEUE &&
- !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status) &&
- !test_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status))
+ !test_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status))
goto drop;
/* treat non-bufferable MMPDUs as broadcast if sta is sleeping */
@@ -718,51 +678,10 @@
memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data));
}
-static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count,
- const void *data, size_t datalen)
-{
- const struct iwl_mvm_dump_ptrs *dump_ptrs = data;
- ssize_t bytes_read;
- ssize_t bytes_read_trans;
-
- if (offset < dump_ptrs->op_mode_len) {
- bytes_read = min_t(ssize_t, count,
- dump_ptrs->op_mode_len - offset);
- memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset,
- bytes_read);
- offset += bytes_read;
- count -= bytes_read;
-
- if (count == 0)
- return bytes_read;
- } else {
- bytes_read = 0;
- }
-
- if (!dump_ptrs->trans_ptr)
- return bytes_read;
-
- offset -= dump_ptrs->op_mode_len;
- bytes_read_trans = min_t(ssize_t, count,
- dump_ptrs->trans_ptr->len - offset);
- memcpy(buffer + bytes_read,
- (u8 *)dump_ptrs->trans_ptr->data + offset,
- bytes_read_trans);
-
- return bytes_read + bytes_read_trans;
-}
-
-static void iwl_mvm_free_coredump(const void *data)
-{
- const struct iwl_mvm_dump_ptrs *fw_error_dump = data;
-
- vfree(fw_error_dump->op_mode_ptr);
- vfree(fw_error_dump->trans_ptr);
- kfree(fw_error_dump);
-}
-
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
{
+ static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL };
struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data;
struct iwl_fw_error_dump_info *dump_info;
@@ -775,7 +694,10 @@
lockdep_assert_held(&mvm->mutex);
- fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL);
+ if (mvm->fw_error_dump)
+ return;
+
+ fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL);
if (!fw_error_dump)
return;
@@ -850,25 +772,21 @@
if (fw_error_dump->trans_ptr)
file_len += fw_error_dump->trans_ptr->len;
dump_file->file_len = cpu_to_le32(file_len);
+ mvm->fw_error_dump = fw_error_dump;
- dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0,
- GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump);
+ /* notify the userspace about the error we had */
+ kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env);
}
+#endif
static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm)
{
- /* clear the D3 reconfig, we only need it to avoid dumping a
- * firmware coredump on reconfiguration, we shouldn't do that
- * on D3->D0 transition
- */
- if (!test_and_clear_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status))
- iwl_mvm_fw_error_dump(mvm);
+ iwl_mvm_fw_error_dump(mvm);
iwl_trans_stop_device(mvm->trans);
mvm->scan_status = IWL_MVM_SCAN_NONE;
mvm->ps_disabled = false;
- mvm->calibrating = false;
/* just in case one was running */
ieee80211_remain_on_channel_expired(mvm->hw);
@@ -883,7 +801,6 @@
iwl_mvm_reset_phy_ctxts(mvm);
memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));
memset(mvm->sta_drained, 0, sizeof(mvm->sta_drained));
- memset(mvm->tfd_drained, 0, sizeof(mvm->tfd_drained));
memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
@@ -940,8 +857,9 @@
return ret;
}
-static void iwl_mvm_restart_complete(struct iwl_mvm *mvm)
+static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw)
{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
mutex_lock(&mvm->mutex);
@@ -956,50 +874,9 @@
/* allow transport/FW low power modes */
iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);
- /*
- * If we have TDLS peers, remove them. We don't know the last seqno/PN
- * of packets the FW sent out, so we must reconnect.
- */
- iwl_mvm_teardown_tdls_peers(mvm);
-
mutex_unlock(&mvm->mutex);
}
-static void iwl_mvm_resume_complete(struct iwl_mvm *mvm)
-{
- bool exit_now;
-
- if (!iwl_mvm_is_d0i3_supported(mvm))
- return;
-
- mutex_lock(&mvm->d0i3_suspend_mutex);
- __clear_bit(D0I3_DEFER_WAKEUP, &mvm->d0i3_suspend_flags);
- exit_now = __test_and_clear_bit(D0I3_PENDING_WAKEUP,
- &mvm->d0i3_suspend_flags);
- mutex_unlock(&mvm->d0i3_suspend_mutex);
-
- if (exit_now) {
- IWL_DEBUG_RPM(mvm, "Run deferred d0i3 exit\n");
- _iwl_mvm_exit_d0i3(mvm);
- }
-}
-
-static void
-iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw,
- enum ieee80211_reconfig_type reconfig_type)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
-
- switch (reconfig_type) {
- case IEEE80211_RECONFIG_TYPE_RESTART:
- iwl_mvm_restart_complete(mvm);
- break;
- case IEEE80211_RECONFIG_TYPE_SUSPEND:
- iwl_mvm_resume_complete(mvm);
- break;
- }
-}
-
void __iwl_mvm_mac_stop(struct iwl_mvm *mvm)
{
lockdep_assert_held(&mvm->mutex);
@@ -1208,7 +1085,7 @@
static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
- u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif);
+ u32 tfd_msk = iwl_mvm_mac_get_queues_mask(mvm, vif);
if (tfd_msk) {
mutex_lock(&mvm->mutex);
@@ -1504,9 +1381,6 @@
.cmd = cmd,
};
- if (IWL_MVM_FW_BCAST_FILTER_PASS_ALL)
- return false;
-
memset(cmd, 0, sizeof(*cmd));
cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters);
cmd->max_macs = ARRAY_SIZE(cmd->macs);
@@ -1860,13 +1734,6 @@
if (changes & BSS_CHANGED_BEACON &&
iwl_mvm_mac_ctxt_beacon_changed(mvm, vif))
IWL_WARN(mvm, "Failed updating beacon data\n");
-
- if (changes & BSS_CHANGED_TXPOWER) {
- IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n",
- bss_conf->txpower);
- iwl_mvm_set_tx_power(mvm, vif, bss_conf->txpower);
- }
-
}
static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
@@ -1959,11 +1826,9 @@
req->n_channels > mvm->fw->ucode_capa.n_scan_channels)
return -EINVAL;
- if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
- ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
- if (ret)
- return ret;
- }
+ ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_SCHED);
+ if (ret)
+ return ret;
mutex_lock(&mvm->mutex);
@@ -1974,9 +1839,7 @@
iwl_mvm_ref(mvm, IWL_MVM_REF_SCAN);
- if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
- ret = iwl_mvm_scan_umac(mvm, vif, hw_req);
- else if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
ret = iwl_mvm_unified_scan_lmac(mvm, vif, hw_req);
else
ret = iwl_mvm_scan_request(mvm, vif, req);
@@ -2193,15 +2056,6 @@
out_unlock:
mutex_unlock(&mvm->mutex);
- if (sta->tdls && ret == 0) {
- if (old_state == IEEE80211_STA_NOTEXIST &&
- new_state == IEEE80211_STA_NONE)
- ieee80211_reserve_tid(sta, IWL_MVM_TDLS_FW_TID);
- else if (old_state == IEEE80211_STA_NONE &&
- new_state == IEEE80211_STA_NOTEXIST)
- ieee80211_unreserve_tid(sta, IWL_MVM_TDLS_FW_TID);
- }
-
return ret;
}
@@ -2284,11 +2138,9 @@
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
- if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)) {
- ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
- if (ret)
- return ret;
- }
+ ret = iwl_mvm_cancel_scan_wait_notif(mvm, IWL_MVM_SCAN_OS);
+ if (ret)
+ return ret;
mutex_lock(&mvm->mutex);
@@ -2308,10 +2160,27 @@
goto out;
}
- ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies);
- if (ret)
- mvm->scan_status = IWL_MVM_SCAN_NONE;
+ mvm->scan_status = IWL_MVM_SCAN_SCHED;
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
+ ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
+ if (ret)
+ goto err;
+ }
+
+ ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
+ if (ret)
+ goto err;
+
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+ ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
+ else
+ ret = iwl_mvm_sched_scan_start(mvm, req);
+
+ if (!ret)
+ goto out;
+err:
+ mvm->scan_status = IWL_MVM_SCAN_NONE;
out:
mutex_unlock(&mvm->mutex);
return ret;
@@ -2329,7 +2198,6 @@
iwl_mvm_wait_for_async_handlers(mvm);
return ret;
-
}
static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
@@ -2358,16 +2226,12 @@
break;
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
- /* For non-client mode, only use WEP keys for TX as we probably
- * don't have a station yet anyway and would then have to keep
- * track of the keys, linking them to each of the clients/peers
- * as they appear. For now, don't do that, for performance WEP
- * offload doesn't really matter much, but we need it for some
- * other offload features in client mode.
+ /*
+ * Support for TX only, at least for now, so accept
+ * the key and do nothing else. Then mac80211 will
+ * pass it for TX but we don't have to use it for RX.
*/
- if (vif->type != NL80211_IFTYPE_STATION)
- return 0;
- break;
+ return 0;
default:
/* currently FW supports only one optional cipher scheme */
if (hw->n_cipher_schemes &&
@@ -2503,19 +2367,14 @@
/* Set the node address */
memcpy(aux_roc_req.node_addr, vif->addr, ETH_ALEN);
- lockdep_assert_held(&mvm->mutex);
-
- spin_lock_bh(&mvm->time_event_lock);
-
- if (WARN_ON(te_data->id == HOT_SPOT_CMD)) {
- spin_unlock_bh(&mvm->time_event_lock);
- return -EIO;
- }
-
te_data->vif = vif;
te_data->duration = duration;
te_data->id = HOT_SPOT_CMD;
+ lockdep_assert_held(&mvm->mutex);
+
+ spin_lock_bh(&mvm->time_event_lock);
+ list_add_tail(&te_data->list, &mvm->time_event_list);
spin_unlock_bh(&mvm->time_event_lock);
/*
@@ -2571,29 +2430,22 @@
IWL_DEBUG_MAC80211(mvm, "enter (%d, %d, %d)\n", channel->hw_value,
duration, type);
- mutex_lock(&mvm->mutex);
-
switch (vif->type) {
case NL80211_IFTYPE_STATION:
- if (mvm->fw->ucode_capa.capa[0] &
- IWL_UCODE_TLV_CAPA_HOTSPOT_SUPPORT) {
- /* Use aux roc framework (HS20) */
- ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
- vif, duration);
- goto out_unlock;
- }
- IWL_ERR(mvm, "hotspot not supported\n");
- ret = -EINVAL;
- goto out_unlock;
+ /* Use aux roc framework (HS20) */
+ ret = iwl_mvm_send_aux_roc_cmd(mvm, channel,
+ vif, duration);
+ return ret;
case NL80211_IFTYPE_P2P_DEVICE:
/* handle below */
break;
default:
IWL_ERR(mvm, "vif isn't P2P_DEVICE: %d\n", vif->type);
- ret = -EINVAL;
- goto out_unlock;
+ return -EINVAL;
}
+ mutex_lock(&mvm->mutex);
+
for (i = 0; i < NUM_PHY_CTX; i++) {
phy_ctxt = &mvm->phy_ctxts[i];
if (phy_ctxt->ref == 0 || mvmvif->phy_ctxt == phy_ctxt)
@@ -2690,7 +2542,7 @@
IWL_DEBUG_MAC80211(mvm, "enter\n");
mutex_lock(&mvm->mutex);
- iwl_mvm_stop_roc(mvm);
+ iwl_mvm_stop_p2p_roc(mvm);
mutex_unlock(&mvm->mutex);
IWL_DEBUG_MAC80211(mvm, "leave\n");
@@ -2803,8 +2655,8 @@
switch (vif->type) {
case NL80211_IFTYPE_AP:
- /* only needed if we're switching chanctx (i.e. during CSA) */
- if (switching_chanctx) {
+ /* Unless it's a CSA flow we have nothing to do here */
+ if (vif->csa_active) {
mvmvif->ap_ibss_active = true;
break;
}
@@ -2848,32 +2700,23 @@
}
/* Handle binding during CSA */
- if (vif->type == NL80211_IFTYPE_AP) {
+ if ((vif->type == NL80211_IFTYPE_AP) ||
+ (switching_chanctx && (vif->type == NL80211_IFTYPE_STATION))) {
iwl_mvm_update_quotas(mvm, NULL);
iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
}
- if (switching_chanctx && vif->type == NL80211_IFTYPE_STATION) {
- u32 duration = 2 * vif->bss_conf.beacon_int;
+ if (vif->csa_active && vif->type == NL80211_IFTYPE_STATION) {
+ struct iwl_mvm_sta *mvmsta;
- /* iwl_mvm_protect_session() reads directly from the
- * device (the system time), so make sure it is
- * available.
- */
- ret = iwl_mvm_ref_sync(mvm, IWL_MVM_REF_PROTECT_CSA);
- if (ret)
- goto out_remove_binding;
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
+ mvmvif->ap_sta_id);
- /* Protect the session to make sure we hear the first
- * beacon on the new channel.
- */
- iwl_mvm_protect_session(mvm, vif, duration, duration,
- vif->bss_conf.beacon_int / 2,
- true);
+ if (WARN_ON(!mvmsta))
+ goto out;
- iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_CSA);
-
- iwl_mvm_update_quotas(mvm, NULL);
+ /* TODO: only re-enable after the first beacon */
+ iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
}
goto out;
@@ -2907,6 +2750,7 @@
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
struct ieee80211_vif *disabled_vif = NULL;
+ struct iwl_mvm_sta *mvmsta;
lockdep_assert_held(&mvm->mutex);
@@ -2921,11 +2765,9 @@
break;
case NL80211_IFTYPE_AP:
/* This part is triggered only during CSA */
- if (!switching_chanctx || !mvmvif->ap_ibss_active)
+ if (!vif->csa_active || !mvmvif->ap_ibss_active)
goto out;
- mvmvif->csa_countdown = false;
-
/* Set CS bit on all the stations */
iwl_mvm_modify_all_sta_disable_tx(mvm, mvmvif, true);
@@ -2940,6 +2782,12 @@
disabled_vif = vif;
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
+ mvmvif->ap_sta_id);
+
+ if (!WARN_ON(!mvmsta))
+ iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, true);
+
iwl_mvm_mac_ctxt_changed(mvm, vif, true, NULL);
break;
default:
@@ -2965,12 +2813,18 @@
mutex_unlock(&mvm->mutex);
}
-static int
-iwl_mvm_switch_vif_chanctx_swap(struct iwl_mvm *mvm,
- struct ieee80211_vif_chanctx_switch *vifs)
+static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
+ struct ieee80211_vif_chanctx_switch *vifs,
+ int n_vifs,
+ enum ieee80211_chanctx_switch_mode mode)
{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
int ret;
+ /* we only support SWAP_CONTEXTS and with a single-vif right now */
+ if (mode != CHANCTX_SWMODE_SWAP_CONTEXTS || n_vifs > 1)
+ return -EOPNOTSUPP;
+
mutex_lock(&mvm->mutex);
__iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
__iwl_mvm_remove_chanctx(mvm, vifs[0].old_ctx);
@@ -2999,51 +2853,15 @@
__iwl_mvm_remove_chanctx(mvm, vifs[0].new_ctx);
out_reassign:
- if (__iwl_mvm_add_chanctx(mvm, vifs[0].old_ctx)) {
+ ret = __iwl_mvm_add_chanctx(mvm, vifs[0].old_ctx);
+ if (ret) {
IWL_ERR(mvm, "failed to add old_ctx back after failure.\n");
goto out_restart;
}
- if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
- true)) {
- IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
- goto out_restart;
- }
-
- goto out;
-
-out_restart:
- /* things keep failing, better restart the hw */
- iwl_mvm_nic_restart(mvm, false);
-
-out:
- mutex_unlock(&mvm->mutex);
-
- return ret;
-}
-
-static int
-iwl_mvm_switch_vif_chanctx_reassign(struct iwl_mvm *mvm,
- struct ieee80211_vif_chanctx_switch *vifs)
-{
- int ret;
-
- mutex_lock(&mvm->mutex);
- __iwl_mvm_unassign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx, true);
-
- ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].new_ctx,
+ ret = __iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
true);
if (ret) {
- IWL_ERR(mvm,
- "failed to assign new_ctx during channel switch\n");
- goto out_reassign;
- }
-
- goto out;
-
-out_reassign:
- if (__iwl_mvm_assign_vif_chanctx(mvm, vifs[0].vif, vifs[0].old_ctx,
- true)) {
IWL_ERR(mvm, "failed to reassign old_ctx after failure.\n");
goto out_restart;
}
@@ -3056,34 +2874,6 @@
out:
mutex_unlock(&mvm->mutex);
-
- return ret;
-}
-
-static int iwl_mvm_switch_vif_chanctx(struct ieee80211_hw *hw,
- struct ieee80211_vif_chanctx_switch *vifs,
- int n_vifs,
- enum ieee80211_chanctx_switch_mode mode)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- int ret;
-
- /* we only support a single-vif right now */
- if (n_vifs > 1)
- return -EOPNOTSUPP;
-
- switch (mode) {
- case CHANCTX_SWMODE_SWAP_CONTEXTS:
- ret = iwl_mvm_switch_vif_chanctx_swap(mvm, vifs);
- break;
- case CHANCTX_SWMODE_REASSIGN_VIF:
- ret = iwl_mvm_switch_vif_chanctx_reassign(mvm, vifs);
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
-
return ret;
}
@@ -3169,134 +2959,27 @@
}
#endif
-static void iwl_mvm_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *chsw)
-{
- /* By implementing this operation, we prevent mac80211 from
- * starting its own channel switch timer, so that we can call
- * ieee80211_chswitch_done() ourselves at the right time
- * (which is when the absence time event starts).
- */
-
- IWL_DEBUG_MAC80211(IWL_MAC80211_GET_MVM(hw),
- "dummy channel switch op\n");
-}
-
-static int iwl_mvm_pre_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *chsw)
+static void iwl_mvm_channel_switch_beacon(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_chan_def *chandef)
{
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct ieee80211_vif *csa_vif;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- u32 apply_time;
- int ret;
mutex_lock(&mvm->mutex);
- IWL_DEBUG_MAC80211(mvm, "pre CSA to freq %d\n",
- chsw->chandef.center_freq1);
-
- switch (vif->type) {
- case NL80211_IFTYPE_AP:
- csa_vif =
- rcu_dereference_protected(mvm->csa_vif,
- lockdep_is_held(&mvm->mutex));
- if (WARN_ONCE(csa_vif && csa_vif->csa_active,
- "Another CSA is already in progress")) {
- ret = -EBUSY;
- goto out_unlock;
- }
-
- rcu_assign_pointer(mvm->csa_vif, vif);
-
- if (WARN_ONCE(mvmvif->csa_countdown,
- "Previous CSA countdown didn't complete")) {
- ret = -EBUSY;
- goto out_unlock;
- }
-
- break;
- case NL80211_IFTYPE_STATION:
- /* Schedule the time event to a bit before beacon 1,
- * to make sure we're in the new channel when the
- * GO/AP arrives.
- */
- apply_time = chsw->device_timestamp +
- ((vif->bss_conf.beacon_int * (chsw->count - 1) -
- IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT) * 1024);
-
- if (chsw->block_tx)
- iwl_mvm_csa_client_absent(mvm, vif);
-
- iwl_mvm_schedule_csa_period(mvm, vif, vif->bss_conf.beacon_int,
- apply_time);
- if (mvmvif->bf_data.bf_enabled) {
- ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
- if (ret)
- goto out_unlock;
- }
-
- break;
- default:
- break;
- }
-
- mvmvif->ps_disabled = true;
-
- ret = iwl_mvm_power_update_ps(mvm);
- if (ret)
+ csa_vif = rcu_dereference_protected(mvm->csa_vif,
+ lockdep_is_held(&mvm->mutex));
+ if (WARN(csa_vif && csa_vif->csa_active,
+ "Another CSA is already in progress"))
goto out_unlock;
- /* we won't be on this channel any longer */
- iwl_mvm_teardown_tdls_peers(mvm);
+ IWL_DEBUG_MAC80211(mvm, "CSA started to freq %d\n",
+ chandef->center_freq1);
+ rcu_assign_pointer(mvm->csa_vif, vif);
out_unlock:
mutex_unlock(&mvm->mutex);
-
- return ret;
-}
-
-static int iwl_mvm_post_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- int ret;
-
- mutex_lock(&mvm->mutex);
-
- if (vif->type == NL80211_IFTYPE_STATION) {
- struct iwl_mvm_sta *mvmsta;
-
- mvmsta = iwl_mvm_sta_from_staid_protected(mvm,
- mvmvif->ap_sta_id);
-
- if (WARN_ON(!mvmsta)) {
- ret = -EIO;
- goto out_unlock;
- }
-
- iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, false);
-
- iwl_mvm_mac_ctxt_changed(mvm, vif, false, NULL);
-
- ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
- if (ret)
- goto out_unlock;
-
- iwl_mvm_stop_session_protection(mvm, vif);
- }
-
- mvmvif->ps_disabled = false;
-
- ret = iwl_mvm_power_update_ps(mvm);
-
-out_unlock:
- mutex_unlock(&mvm->mutex);
-
- return ret;
}
static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
@@ -3305,52 +2988,33 @@
struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
struct iwl_mvm_vif *mvmvif;
struct iwl_mvm_sta *mvmsta;
- struct ieee80211_sta *sta;
- int i;
- u32 msk = 0;
if (!vif || vif->type != NL80211_IFTYPE_STATION)
return;
mutex_lock(&mvm->mutex);
mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
- /* flush the AP-station and all TDLS peers */
- for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
- sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
- lockdep_is_held(&mvm->mutex));
- if (IS_ERR_OR_NULL(sta))
- continue;
-
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
- if (mvmsta->vif != vif)
- continue;
-
- /* make sure only TDLS peers or the AP are flushed */
- WARN_ON(i != mvmvif->ap_sta_id && !sta->tdls);
-
- msk |= mvmsta->tfd_queue_msk;
- }
+ if (WARN_ON_ONCE(!mvmsta))
+ goto done;
if (drop) {
- if (iwl_mvm_flush_tx_path(mvm, msk, true))
+ if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true))
IWL_ERR(mvm, "flush request fail\n");
- mutex_unlock(&mvm->mutex);
} else {
- mutex_unlock(&mvm->mutex);
-
- /* this can take a while, and we may need/want other operations
- * to succeed while doing this, so do it without the mutex held
- */
- iwl_trans_wait_tx_queue_empty(mvm->trans, msk);
+ iwl_trans_wait_tx_queue_empty(mvm->trans,
+ mvmsta->tfd_queue_msk);
}
+done:
+ mutex_unlock(&mvm->mutex);
}
const struct ieee80211_ops iwl_mvm_hw_ops = {
.tx = iwl_mvm_mac_tx,
.ampdu_action = iwl_mvm_mac_ampdu_action,
.start = iwl_mvm_mac_start,
- .reconfig_complete = iwl_mvm_mac_reconfig_complete,
+ .restart_complete = iwl_mvm_mac_restart_complete,
.stop = iwl_mvm_mac_stop,
.add_interface = iwl_mvm_mac_add_interface,
.remove_interface = iwl_mvm_mac_remove_interface,
@@ -3391,13 +3055,7 @@
.set_tim = iwl_mvm_set_tim,
- .channel_switch = iwl_mvm_channel_switch,
- .pre_channel_switch = iwl_mvm_pre_channel_switch,
- .post_channel_switch = iwl_mvm_post_channel_switch,
-
- .tdls_channel_switch = iwl_mvm_tdls_channel_switch,
- .tdls_cancel_channel_switch = iwl_mvm_tdls_cancel_channel_switch,
- .tdls_recv_channel_switch = iwl_mvm_tdls_recv_channel_switch,
+ .channel_switch_beacon = iwl_mvm_channel_switch_beacon,
CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index d4d4d72..a1d1fc2 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -87,18 +87,12 @@
/* A TimeUnit is 1024 microsecond */
#define MSEC_TO_TU(_msec) (_msec*1000/1024)
-/* For GO, this value represents the number of TUs before CSA "beacon
- * 0" TBTT when the CSA time-event needs to be scheduled to start. It
- * must be big enough to ensure that we switch in time.
+/* This value represents the number of TUs before CSA "beacon 0" TBTT
+ * when the CSA time-event needs to be scheduled to start. It must be
+ * big enough to ensure that we switch in time.
*/
#define IWL_MVM_CHANNEL_SWITCH_TIME_GO 40
-/* For client, this value represents the number of TUs before CSA
- * "beacon 1" TBTT, instead. This is because we don't know when the
- * GO/AP will be in the new channel, so we switch early enough.
- */
-#define IWL_MVM_CHANNEL_SWITCH_TIME_CLIENT 10
-
/*
* This value (in TUs) is used to fine tune the CSA NoA end time which should
* be just before "beacon 0" TBTT.
@@ -275,7 +269,6 @@
IWL_MVM_REF_NMI,
IWL_MVM_REF_TM_CMD,
IWL_MVM_REF_EXIT_WORK,
- IWL_MVM_REF_PROTECT_CSA,
/* update debugfs.c when changing this */
@@ -295,6 +288,7 @@
* struct iwl_mvm_vif_bf_data - beacon filtering related data
* @bf_enabled: indicates if beacon filtering is enabled
* @ba_enabled: indicated if beacon abort is enabled
+* @last_beacon_signal: last beacon rssi signal in dbm
* @ave_beacon_signal: average beacon signal
* @last_cqm_event: rssi of the last cqm event
* @bt_coex_min_thold: minimum threshold for BT coex
@@ -405,9 +399,6 @@
/* FW identified misbehaving AP */
u8 uapsd_misbehaving_bssid[ETH_ALEN];
-
- /* Indicates that CSA countdown may be started */
- bool csa_countdown;
};
static inline struct iwl_mvm_vif *
@@ -528,13 +519,6 @@
#define IWL_MVM_DEBUG_SET_TEMPERATURE_MIN -100
#define IWL_MVM_DEBUG_SET_TEMPERATURE_MAX 200
-enum iwl_mvm_tdls_cs_state {
- IWL_MVM_TDLS_SW_IDLE = 0,
- IWL_MVM_TDLS_SW_REQ_SENT,
- IWL_MVM_TDLS_SW_REQ_RCVD,
- IWL_MVM_TDLS_SW_ACTIVE,
-};
-
struct iwl_mvm {
/* for logger access */
struct device *dev;
@@ -564,7 +548,6 @@
enum iwl_ucode_type cur_ucode;
bool ucode_loaded;
bool init_ucode_complete;
- bool calibrating;
u32 error_event_table;
u32 log_event_table;
u32 umac_error_event_table;
@@ -594,7 +577,6 @@
struct work_struct sta_drained_wk;
unsigned long sta_drained[BITS_TO_LONGS(IWL_MVM_STATION_COUNT)];
atomic_t pending_frames[IWL_MVM_STATION_COUNT];
- u32 tfd_drained[IWL_MVM_STATION_COUNT];
u8 rx_ba_sessions;
/* configured by mac80211 */
@@ -605,10 +587,6 @@
void *scan_cmd;
struct iwl_mcast_filter_cmd *mcast_filter_cmd;
- /* UMAC scan tracking */
- u32 scan_uid[IWL_MVM_MAX_SIMULTANEOUS_SCANS];
- u8 scan_seq_num, sched_scan_seq_num;
-
/* rx chain antennas set through debugfs for the scan command */
u8 scan_rx_ant;
@@ -670,7 +648,7 @@
/* -1 for always, 0 for never, >0 for that many times */
s8 restart_fw;
struct work_struct fw_error_dump_wk;
- enum iwl_fw_dbg_conf fw_dbg_conf;
+ struct iwl_mvm_dump_ptrs *fw_error_dump;
#ifdef CPTCFG_IWLWIFI_LEDS
struct led_classdev led;
@@ -681,15 +659,6 @@
#ifdef CONFIG_PM_SLEEP
struct wiphy_wowlan_support wowlan;
int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen;
-
- /* sched scan settings for net detect */
- struct cfg80211_sched_scan_request *nd_config;
- struct ieee80211_scan_ies nd_ies;
- struct cfg80211_match_set *nd_match_sets;
- int n_nd_match_sets;
- struct ieee80211_channel **nd_channels;
- int n_nd_channels;
- bool net_detect;
#ifdef CPTCFG_IWLWIFI_DEBUGFS
u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */
bool d3_test_active;
@@ -762,28 +731,6 @@
u32 ap_last_beacon_gp2;
u8 low_latency_agg_frame_limit;
-
- /* TDLS channel switch data */
- struct {
- struct delayed_work dwork;
- enum iwl_mvm_tdls_cs_state state;
-
- /*
- * Current cs sta - might be different from periodic cs peer
- * station. Value is meaningless when the cs-state is idle.
- */
- u8 cur_sta_id;
-
- /* TDLS periodic channel-switch peer */
- struct {
- u8 sta_id;
- u8 op_class;
- bool initiator; /* are we the link initiator */
- struct cfg80211_chan_def chandef;
- struct sk_buff *skb; /* ch sw template */
- u32 ch_sw_tm_ie;
- } peer;
- } tdls_cs;
};
/* Extract MVM priv from op_mode and _hw */
@@ -800,7 +747,6 @@
IWL_MVM_STATUS_IN_HW_RESTART,
IWL_MVM_STATUS_IN_D0I3,
IWL_MVM_STATUS_ROC_AUX_RUNNING,
- IWL_MVM_STATUS_D3_RECONFIG,
};
static inline bool iwl_mvm_is_radio_killed(struct iwl_mvm *mvm)
@@ -809,26 +755,6 @@
test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status);
}
-/* Must be called with rcu_read_lock() held and it can only be
- * released when mvmsta is not needed anymore.
- */
-static inline struct iwl_mvm_sta *
-iwl_mvm_sta_from_staid_rcu(struct iwl_mvm *mvm, u8 sta_id)
-{
- struct ieee80211_sta *sta;
-
- if (sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))
- return NULL;
-
- sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]);
-
- /* This can happen if the station has been removed right now */
- if (IS_ERR_OR_NULL(sta))
- return NULL;
-
- return iwl_mvm_sta_from_mac80211(sta);
-}
-
static inline struct iwl_mvm_sta *
iwl_mvm_sta_from_staid_protected(struct iwl_mvm *mvm, u8 sta_id)
{
@@ -902,16 +828,6 @@
int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_sta *sta);
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb);
-void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct iwl_tx_cmd *tx_cmd,
- struct ieee80211_tx_info *info, u8 sta_id);
-void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
- struct ieee80211_tx_info *info,
- struct iwl_tx_cmd *tx_cmd,
- struct sk_buff *skb_frag);
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta, __le16 fc);
#ifdef CPTCFG_IWLWIFI_DEBUG
const char *iwl_mvm_get_tx_fail_reason(u32 status);
#else
@@ -968,8 +884,6 @@
struct iwl_device_cmd *cmd);
int iwl_mvm_rx_radio_ver(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
-int iwl_mvm_rx_mfuart_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd);
/* MVM PHY */
int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
@@ -983,8 +897,6 @@
void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
struct iwl_mvm_phy_ctxt *ctxt);
int iwl_mvm_phy_ctx_count(struct iwl_mvm *mvm);
-u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef);
-u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef);
/* MAC (virtual interface) programming */
int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -993,7 +905,8 @@
int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool force_assoc_off, const u8 *bssid_override);
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
-u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif);
+u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
@@ -1004,8 +917,6 @@
struct iwl_device_cmd *cmd);
void iwl_mvm_mac_ctxt_recalc_tsf_id(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
-unsigned long iwl_mvm_get_used_hw_queues(struct iwl_mvm *mvm,
- struct ieee80211_vif *exclude_vif);
/* Bindings */
int iwl_mvm_binding_add_vif(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
@@ -1016,7 +927,6 @@
struct ieee80211_vif *disabled_vif);
/* Scanning */
-int iwl_mvm_scan_size(struct iwl_mvm *mvm);
int iwl_mvm_scan_request(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct cfg80211_scan_request *req);
@@ -1039,10 +949,6 @@
struct cfg80211_sched_scan_request *req);
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
-int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct cfg80211_sched_scan_request *req,
- struct ieee80211_scan_ies *ies);
int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify);
int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
@@ -1057,17 +963,6 @@
struct cfg80211_sched_scan_request *req,
struct ieee80211_scan_ies *ies);
-/* UMAC scan */
-int iwl_mvm_config_scan(struct iwl_mvm *mvm);
-int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_scan_request *req);
-int iwl_mvm_sched_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct cfg80211_sched_scan_request *req,
- struct ieee80211_scan_ies *ies);
-int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd);
-
/* MVM debugfs */
#ifdef CPTCFG_IWLWIFI_DEBUGFS
int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir);
@@ -1147,7 +1042,7 @@
}
#endif
void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
- struct iwl_wowlan_config_cmd *cmd);
+ struct iwl_wowlan_config_cmd_v2 *cmd);
int iwl_mvm_send_proto_offload(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool disable_offloading,
@@ -1157,7 +1052,6 @@
void iwl_mvm_ref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
void iwl_mvm_unref(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
int iwl_mvm_ref_sync(struct iwl_mvm *mvm, enum iwl_mvm_ref_type ref_type);
-bool iwl_mvm_ref_taken(struct iwl_mvm *mvm);
void iwl_mvm_d0i3_enable_tx(struct iwl_mvm *mvm, __le16 *qos_seq);
int _iwl_mvm_exit_d0i3(struct iwl_mvm *mvm);
@@ -1173,14 +1067,12 @@
struct ieee80211_sta *sta);
bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
struct ieee80211_sta *sta);
-bool iwl_mvm_bt_coex_is_ant_avail(struct iwl_mvm *mvm, u8 ant);
bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm);
bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
enum ieee80211_band band);
u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *info, u8 ac);
-bool iwl_mvm_bt_coex_is_ant_avail_old(struct iwl_mvm *mvm, u8 ant);
bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm);
void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm);
int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm);
@@ -1296,10 +1188,6 @@
/* Thermal management and CT-kill */
void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff);
-void iwl_mvm_tt_temp_changed(struct iwl_mvm *mvm, u32 temp);
-int iwl_mvm_temp_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd);
void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
void iwl_mvm_tt_initialize(struct iwl_mvm *mvm, u32 min_backoff);
void iwl_mvm_tt_exit(struct iwl_mvm *mvm);
@@ -1311,37 +1199,18 @@
bool added_vif);
/* TDLS */
-
-/*
- * We use TID 4 (VI) as a FW-used-only TID when TDLS connections are present.
- * This TID is marked as used vs the AP and all connected TDLS peers.
- */
-#define IWL_MVM_TDLS_FW_TID 4
-
int iwl_mvm_tdls_sta_count(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm);
void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool sta_added);
void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
-int iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u8 oper_class,
- struct cfg80211_chan_def *chandef,
- struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie);
-void iwl_mvm_tdls_recv_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_tdls_ch_sw_params *params);
-void iwl_mvm_tdls_cancel_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
-int iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd);
-void iwl_mvm_tdls_ch_switch_work(struct work_struct *work);
-
-struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm);
void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error);
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm);
+#else
+static inline void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) {}
+#endif
#endif /* __IWL_MVM_H__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index 98203ab..f23b8fd 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -339,15 +339,11 @@
} *file_sec;
const u8 *eof, *temp;
int max_section_size;
- const __le32 *dword_buff;
#define NVM_WORD1_LEN(x) (8 * (x & 0x03FF))
#define NVM_WORD2_ID(x) (x >> 12)
#define NVM_WORD2_LEN_FAMILY_8000(x) (2 * ((x & 0xFF) << 8 | x >> 8))
#define NVM_WORD1_ID_FAMILY_8000(x) (x >> 4)
-#define NVM_HEADER_0 (0x2A504C54)
-#define NVM_HEADER_1 (0x4E564D2A)
-#define NVM_HEADER_SIZE (4 * sizeof(u32))
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n");
@@ -376,6 +372,12 @@
IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n",
mvm->nvm_file_name, fw_entry->size);
+ if (fw_entry->size < sizeof(*file_sec)) {
+ IWL_ERR(mvm, "NVM file too small\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
if (fw_entry->size > MAX_NVM_FILE_LEN) {
IWL_ERR(mvm, "NVM file too large\n");
ret = -EINVAL;
@@ -383,25 +385,8 @@
}
eof = fw_entry->data + fw_entry->size;
- dword_buff = (__le32 *)fw_entry->data;
- /* some NVM file will contain a header.
- * The header is identified by 2 dwords header as follow:
- * dword[0] = 0x2A504C54
- * dword[1] = 0x4E564D2A
- *
- * This header must be skipped when providing the NVM data to the FW.
- */
- if (fw_entry->size > NVM_HEADER_SIZE &&
- dword_buff[0] == cpu_to_le32(NVM_HEADER_0) &&
- dword_buff[1] == cpu_to_le32(NVM_HEADER_1)) {
- file_sec = (void *)(fw_entry->data + NVM_HEADER_SIZE);
- IWL_INFO(mvm, "NVM Version %08X\n", le32_to_cpu(dword_buff[2]));
- IWL_INFO(mvm, "NVM Manufacturing date %08X\n",
- le32_to_cpu(dword_buff[3]));
- } else {
- file_sec = (void *)fw_entry->data;
- }
+ file_sec = (void *)fw_entry->data;
while (true) {
if (file_sec->data > eof) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/offloading.c b/drivers/net/wireless/iwlwifi/mvm/offloading.c
index 68b0169..adcbf4c 100644
--- a/drivers/net/wireless/iwlwifi/mvm/offloading.c
+++ b/drivers/net/wireless/iwlwifi/mvm/offloading.c
@@ -67,7 +67,7 @@
#include "mvm.h"
void iwl_mvm_set_wowlan_qos_seq(struct iwl_mvm_sta *mvm_ap_sta,
- struct iwl_wowlan_config_cmd *cmd)
+ struct iwl_wowlan_config_cmd_v2 *cmd)
{
int i;
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index f10c327..4de8ec8 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -244,8 +244,6 @@
iwl_mvm_rx_scan_offload_complete_notif, true),
RX_HANDLER(MATCH_FOUND_NOTIFICATION, iwl_mvm_rx_scan_offload_results,
false),
- RX_HANDLER(SCAN_COMPLETE_UMAC, iwl_mvm_rx_umac_scan_complete_notif,
- true),
RX_HANDLER(RADIO_VERSION_NOTIFICATION, iwl_mvm_rx_radio_ver, false),
RX_HANDLER(CARD_STATE_NOTIFICATION, iwl_mvm_rx_card_state_notif, false),
@@ -256,12 +254,6 @@
RX_HANDLER(REPLY_ERROR, iwl_mvm_rx_fw_error, false),
RX_HANDLER(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION,
iwl_mvm_power_uapsd_misbehaving_ap_notif, false),
- RX_HANDLER(DTS_MEASUREMENT_NOTIFICATION, iwl_mvm_temp_notif, true),
-
- RX_HANDLER(TDLS_CHANNEL_SWITCH_NOTIFICATION, iwl_mvm_rx_tdls_notif,
- true),
- RX_HANDLER(MFUART_LOAD_NOTIFICATION, iwl_mvm_rx_mfuart_notif, false),
-
};
#undef RX_HANDLER
#define CMD(x) [x] = #x
@@ -325,9 +317,11 @@
CMD(WOWLAN_KEK_KCK_MATERIAL),
CMD(WOWLAN_GET_STATUSES),
CMD(WOWLAN_TX_POWER_PER_DB),
- CMD(SCAN_OFFLOAD_PROFILES_QUERY_CMD),
- CMD(SCAN_OFFLOAD_HOTSPOTS_CONFIG_CMD),
- CMD(SCAN_OFFLOAD_HOTSPOTS_QUERY_CMD),
+ CMD(NET_DETECT_CONFIG_CMD),
+ CMD(NET_DETECT_PROFILES_QUERY_CMD),
+ CMD(NET_DETECT_PROFILES_CMD),
+ CMD(NET_DETECT_HOTSPOTS_CMD),
+ CMD(NET_DETECT_HOTSPOTS_QUERY_CMD),
CMD(CARD_STATE_NOTIFICATION),
CMD(MISSED_BEACONS_NOTIFICATION),
CMD(BT_COEX_PRIO_TABLE),
@@ -342,7 +336,6 @@
CMD(DTS_MEASUREMENT_NOTIFICATION),
CMD(REPLY_THERMAL_MNG_BACKOFF),
CMD(MAC_PM_POWER_TABLE),
- CMD(LTR_CONFIG),
CMD(BT_COEX_CI),
CMD(BT_COEX_UPDATE_SW_BOOST),
CMD(BT_COEX_UPDATE_CORUN_LUT),
@@ -350,13 +343,6 @@
CMD(PSM_UAPSD_AP_MISBEHAVING_NOTIFICATION),
CMD(ANTENNA_COUPLING_NOTIFICATION),
CMD(SCD_QUEUE_CFG),
- CMD(SCAN_CFG_CMD),
- CMD(SCAN_REQ_UMAC),
- CMD(SCAN_ABORT_UMAC),
- CMD(SCAN_COMPLETE_UMAC),
- CMD(TDLS_CHANNEL_SWITCH_CMD),
- CMD(TDLS_CHANNEL_SWITCH_NOTIFICATION),
- CMD(TDLS_CONFIG_CMD),
};
#undef CMD
@@ -416,9 +402,6 @@
if (cfg->max_rx_agg_size)
hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size;
- if (cfg->max_tx_agg_size)
- hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size;
-
op_mode = hw->priv;
op_mode->ops = &iwl_mvm_ops;
@@ -440,7 +423,6 @@
}
mvm->sf_state = SF_UNINIT;
mvm->low_latency_agg_frame_limit = 6;
- mvm->cur_ucode = IWL_UCODE_INIT;
mutex_init(&mvm->mutex);
mutex_init(&mvm->d0i3_suspend_mutex);
@@ -455,7 +437,6 @@
INIT_WORK(&mvm->sta_drained_wk, iwl_mvm_sta_drained_wk);
INIT_WORK(&mvm->d0i3_exit_work, iwl_mvm_d0i3_exit_work);
INIT_WORK(&mvm->fw_error_dump_wk, iwl_mvm_fw_error_dump_wk);
- INIT_DELAYED_WORK(&mvm->tdls_cs.dwork, iwl_mvm_tdls_ch_switch_work);
spin_lock_init(&mvm->d0i3_tx_lock);
spin_lock_init(&mvm->refs_lock);
@@ -496,10 +477,6 @@
trans->rx_mpdu_cmd = REPLY_RX_MPDU_CMD;
trans->rx_mpdu_cmd_hdr_size = sizeof(struct iwl_rx_mpdu_res_start);
- trans->dbg_dest_tlv = mvm->fw->dbg_dest_tlv;
- trans->dbg_dest_reg_num = mvm->fw->dbg_dest_reg_num;
- memcpy(trans->dbg_conf_tlv, mvm->fw->dbg_conf_tlv,
- sizeof(trans->dbg_conf_tlv));
/* set up notification wait support */
iwl_notification_wait_init(&mvm->notif_wait);
@@ -543,8 +520,7 @@
mutex_lock(&mvm->mutex);
err = iwl_run_init_mvm_ucode(mvm, true);
- if (!err || !iwlmvm_mod_params.init_dbg)
- iwl_trans_stop_device(trans);
+ iwl_trans_stop_device(trans);
mutex_unlock(&mvm->mutex);
/* returns 0 if successful, 1 if success but in rfkill */
if (err < 0 && !iwlmvm_mod_params.init_dbg) {
@@ -553,7 +529,16 @@
}
}
- scan_size = iwl_mvm_scan_size(mvm);
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
+ scan_size = sizeof(struct iwl_scan_req_unified_lmac) +
+ sizeof(struct iwl_scan_channel_cfg_lmac) *
+ mvm->fw->ucode_capa.n_scan_channels +
+ sizeof(struct iwl_scan_probe_req);
+ else
+ scan_size = sizeof(struct iwl_scan_cmd) +
+ mvm->fw->ucode_capa.max_probe_length +
+ mvm->fw->ucode_capa.n_scan_channels *
+ sizeof(struct iwl_scan_channel);
mvm->scan_cmd = kmalloc(scan_size, GFP_KERNEL);
if (!mvm->scan_cmd)
@@ -598,16 +583,16 @@
ieee80211_unregister_hw(mvm->hw);
kfree(mvm->scan_cmd);
+ if (mvm->fw_error_dump) {
+ vfree(mvm->fw_error_dump->op_mode_ptr);
+ vfree(mvm->fw_error_dump->trans_ptr);
+ kfree(mvm->fw_error_dump);
+ }
kfree(mvm->mcast_filter_cmd);
mvm->mcast_filter_cmd = NULL;
#if defined(CONFIG_PM_SLEEP) && defined(CPTCFG_IWLWIFI_DEBUGFS)
kfree(mvm->d3_resume_sram);
- if (mvm->nd_config) {
- kfree(mvm->nd_config->match_sets);
- kfree(mvm->nd_config);
- mvm->nd_config = NULL;
- }
#endif
iwl_trans_op_mode_leave(mvm->trans);
@@ -766,7 +751,6 @@
static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state)
{
struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode);
- bool calibrating = ACCESS_ONCE(mvm->calibrating);
if (state)
set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status);
@@ -775,15 +759,7 @@
wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm));
- /* iwl_run_init_mvm_ucode is waiting for results, abort it */
- if (calibrating)
- iwl_abort_notification_waits(&mvm->notif_wait);
-
- /*
- * Stop the device if we run OPERATIONAL firmware or if we are in the
- * middle of the calibrations.
- */
- return state && (mvm->cur_ucode != IWL_UCODE_INIT || calibrating);
+ return state && mvm->cur_ucode != IWL_UCODE_INIT;
}
static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb)
@@ -1004,7 +980,7 @@
}
static void iwl_mvm_set_wowlan_data(struct iwl_mvm *mvm,
- struct iwl_wowlan_config_cmd *cmd,
+ struct iwl_wowlan_config_cmd_v3 *cmd,
struct iwl_d0i3_iter_data *iter_data)
{
struct ieee80211_sta *ap_sta;
@@ -1020,14 +996,14 @@
goto out;
mvm_ap_sta = iwl_mvm_sta_from_mac80211(ap_sta);
- cmd->is_11n_connection = ap_sta->ht_cap.ht_supported;
+ cmd->common.is_11n_connection = ap_sta->ht_cap.ht_supported;
cmd->offloading_tid = iter_data->offloading_tid;
/*
* The d0i3 uCode takes care of the nonqos counters,
* so configure only the qos seq ones.
*/
- iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, cmd);
+ iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &cmd->common);
out:
rcu_read_unlock();
}
@@ -1039,11 +1015,14 @@
struct iwl_d0i3_iter_data d0i3_iter_data = {
.mvm = mvm,
};
- struct iwl_wowlan_config_cmd wowlan_config_cmd = {
- .wakeup_filter = cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
- IWL_WOWLAN_WAKEUP_BEACON_MISS |
- IWL_WOWLAN_WAKEUP_LINK_CHANGE |
- IWL_WOWLAN_WAKEUP_BCN_FILTERING),
+ struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {
+ .common = {
+ .wakeup_filter =
+ cpu_to_le32(IWL_WOWLAN_WAKEUP_RX_FRAME |
+ IWL_WOWLAN_WAKEUP_BEACON_MISS |
+ IWL_WOWLAN_WAKEUP_LINK_CHANGE |
+ IWL_WOWLAN_WAKEUP_BCN_FILTERING),
+ },
};
struct iwl_d3_manager_config d3_cfg_cmd = {
.min_sleep_time = cpu_to_le32(1000),
@@ -1055,19 +1034,6 @@
set_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
synchronize_net();
- /*
- * iwl_mvm_ref_sync takes a reference before checking the flag.
- * so by checking there is no held reference we prevent a state
- * in which iwl_mvm_ref_sync continues successfully while we
- * configure the firmware to enter d0i3
- */
- if (iwl_mvm_ref_taken(mvm)) {
- IWL_DEBUG_RPM(mvm->trans, "abort d0i3 due to taken ref\n");
- clear_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status);
- wake_up(&mvm->d0i3_exit_waitq);
- return 1;
- }
-
ieee80211_iterate_active_interfaces_atomic(mvm->hw,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_enter_d0i3_iterator,
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index 1c0d4a4..12283b5 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -68,7 +68,7 @@
#include "mvm.h"
/* Maps the driver specific channel width definition to the the fw values */
-u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
+static inline u8 iwl_mvm_get_channel_width(struct cfg80211_chan_def *chandef)
{
switch (chandef->width) {
case NL80211_CHAN_WIDTH_20_NOHT:
@@ -90,7 +90,7 @@
* Maps the driver specific control channel position (relative to the center
* freq) definitions to the the fw values
*/
-u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef)
+static inline u8 iwl_mvm_get_ctrl_pos(struct cfg80211_chan_def *chandef)
{
switch (chandef->chan->center_freq - chandef->center_freq1) {
case -70:
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index a33a46e..27db05b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -286,27 +286,6 @@
return true;
}
-static int iwl_mvm_power_get_skip_over_dtim(int dtimper, int bi)
-{
- int numerator;
- int dtim_interval = dtimper * bi;
-
- if (WARN_ON(!dtim_interval))
- return 0;
-
- if (dtimper == 1) {
- if (bi > 100)
- numerator = 408;
- else
- numerator = 510;
- } else if (dtimper < 10) {
- numerator = 612;
- } else {
- return 0;
- }
- return max(1, (numerator / dtim_interval));
-}
-
static bool iwl_mvm_power_is_radar(struct ieee80211_vif *vif)
{
struct ieee80211_chanctx_conf *chanctx_conf;
@@ -329,7 +308,7 @@
struct ieee80211_vif *vif,
struct iwl_mac_power_cmd *cmd)
{
- int dtimper, bi;
+ int dtimper, dtimper_msec;
int keep_alive;
bool radar_detect = false;
struct iwl_mvm_vif *mvmvif __maybe_unused =
@@ -338,7 +317,6 @@
cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id,
mvmvif->color));
dtimper = vif->bss_conf.dtim_period;
- bi = vif->bss_conf.beacon_int;
/*
* Regardless of power management state the driver must set
@@ -346,9 +324,10 @@
* immediately after association. Check that keep alive period
* is at least 3 * DTIM
*/
- keep_alive = DIV_ROUND_UP(ieee80211_tu_to_usec(3 * dtimper * bi),
- USEC_PER_SEC);
- keep_alive = max(keep_alive, POWER_KEEP_ALIVE_PERIOD_SEC);
+ dtimper_msec = dtimper * vif->bss_conf.beacon_int;
+ keep_alive = max_t(int, 3 * dtimper_msec,
+ MSEC_PER_SEC * POWER_KEEP_ALIVE_PERIOD_SEC);
+ keep_alive = DIV_ROUND_UP(keep_alive, MSEC_PER_SEC);
cmd->keep_alive_seconds = cpu_to_le16(keep_alive);
if (mvm->ps_disabled)
@@ -373,14 +352,11 @@
radar_detect = iwl_mvm_power_is_radar(vif);
/* Check skip over DTIM conditions */
- if (!radar_detect && (dtimper < 10) &&
+ if (!radar_detect && (dtimper <= 10) &&
(iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_LP ||
mvm->cur_ucode == IWL_UCODE_WOWLAN)) {
- cmd->skip_dtim_periods =
- iwl_mvm_power_get_skip_over_dtim(dtimper, bi);
- if (cmd->skip_dtim_periods)
- cmd->flags |=
- cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+ cmd->flags |= cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
+ cmd->skip_dtim_periods = 3;
}
if (mvm->cur_ucode != IWL_UCODE_WOWLAN) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index cf25e6b..287e744 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -158,12 +158,6 @@
allow_column_func_t checks[MAX_COLUMN_CHECKS];
};
-static bool rs_ant_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
- struct iwl_scale_tbl_info *tbl)
-{
- return iwl_mvm_bt_coex_is_ant_avail(mvm, tbl->rate.ant);
-}
-
static bool rs_mimo_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
struct iwl_scale_tbl_info *tbl)
{
@@ -224,9 +218,6 @@
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
},
- .checks = {
- rs_ant_allow,
- },
},
[RS_COLUMN_LEGACY_ANT_B] = {
.mode = RS_LEGACY,
@@ -240,9 +231,6 @@
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
},
- .checks = {
- rs_ant_allow,
- },
},
[RS_COLUMN_SISO_ANT_A] = {
.mode = RS_SISO,
@@ -258,7 +246,6 @@
},
.checks = {
rs_siso_allow,
- rs_ant_allow,
},
},
[RS_COLUMN_SISO_ANT_B] = {
@@ -275,7 +262,6 @@
},
.checks = {
rs_siso_allow,
- rs_ant_allow,
},
},
[RS_COLUMN_SISO_ANT_A_SGI] = {
@@ -293,7 +279,6 @@
},
.checks = {
rs_siso_allow,
- rs_ant_allow,
rs_sgi_allow,
},
},
@@ -312,7 +297,6 @@
},
.checks = {
rs_siso_allow,
- rs_ant_allow,
rs_sgi_allow,
},
},
@@ -521,11 +505,10 @@
static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate,
const char *prefix)
{
- IWL_DEBUG_RATE(mvm,
- "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC: %d\n",
+ IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d\n",
prefix, rs_pretty_lq_type(rate->type),
rate->index, rs_pretty_ant(rate->ant),
- rate->bw, rate->sgi, rate->ldpc, rate->stbc);
+ rate->bw, rate->sgi, rate->ldpc);
}
static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
@@ -758,12 +741,6 @@
IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type);
}
- if (is_siso(rate) && rate->stbc) {
- /* To enable STBC we need to set both a flag and ANT_AB */
- ucode_rate |= RATE_MCS_ANT_AB_MSK;
- ucode_rate |= RATE_MCS_VHT_STBC_MSK;
- }
-
ucode_rate |= rate->bw;
if (rate->sgi)
ucode_rate |= RATE_MCS_SGI_MSK;
@@ -808,8 +785,6 @@
rate->sgi = true;
if (ucode_rate & RATE_MCS_LDPC_MSK)
rate->ldpc = true;
- if (ucode_rate & RATE_MCS_VHT_STBC_MSK)
- rate->stbc = true;
rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK;
@@ -819,7 +794,7 @@
if (nss == 1) {
rate->type = LQ_HT_SISO;
- WARN_ON_ONCE(!rate->stbc && num_of_ant != 1);
+ WARN_ON_ONCE(num_of_ant != 1);
} else if (nss == 2) {
rate->type = LQ_HT_MIMO2;
WARN_ON_ONCE(num_of_ant != 2);
@@ -832,7 +807,7 @@
if (nss == 1) {
rate->type = LQ_VHT_SISO;
- WARN_ON_ONCE(!rate->stbc && num_of_ant != 1);
+ WARN_ON_ONCE(num_of_ant != 1);
} else if (nss == 2) {
rate->type = LQ_VHT_MIMO2;
WARN_ON_ONCE(num_of_ant != 2);
@@ -1017,15 +992,7 @@
static inline bool rs_rate_match(struct rs_rate *a,
struct rs_rate *b)
{
- bool ant_match;
-
- if (a->stbc)
- ant_match = (b->ant == ANT_A || b->ant == ANT_B);
- else
- ant_match = (a->ant == b->ant);
-
- return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi)
- && ant_match;
+ return (a->type == b->type) && (a->ant == b->ant) && (a->sgi == b->sgi);
}
static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags)
@@ -1126,11 +1093,10 @@
if (time_after(jiffies,
(unsigned long)(lq_sta->last_tx + RS_IDLE_TIMEOUT))) {
- int t;
-
+ int tid;
IWL_DEBUG_RATE(mvm, "Tx idle for too long. reinit rs\n");
- for (t = 0; t < IWL_MAX_TID_COUNT; t++)
- ieee80211_stop_tx_ba_session(sta, t);
+ for (tid = 0; tid < IWL_MAX_TID_COUNT; tid++)
+ ieee80211_stop_tx_ba_session(sta, tid);
iwl_mvm_rs_rate_init(mvm, sta, info->band, false);
return;
@@ -1171,15 +1137,16 @@
/* Rate did match, so reset the missed_rate_counter */
lq_sta->missed_rate_counter = 0;
- if (!lq_sta->search_better_tbl) {
+ /* Figure out if rate scale algorithm is in active or search table */
+ if (rs_rate_match(&rate,
+ &(lq_sta->lq_info[lq_sta->active_tbl].rate))) {
curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
- } else {
+ } else if (rs_rate_match(&rate,
+ &lq_sta->lq_info[1 - lq_sta->active_tbl].rate)) {
curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
- }
-
- if (WARN_ON_ONCE(!rs_rate_match(&rate, &curr_tbl->rate))) {
+ } else {
IWL_DEBUG_RATE(mvm,
"Neither active nor search matches tx rate\n");
tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
@@ -1204,13 +1171,6 @@
* first index into rate scale table.
*/
if (info->flags & IEEE80211_TX_STAT_AMPDU) {
- /* ampdu_ack_len = 0 marks no BA was received. In this case
- * treat it as a single frame loss as we don't want the success
- * ratio to dip too quickly because a BA wasn't received
- */
- if (info->status.ampdu_ack_len == 0)
- info->status.ampdu_len = 1;
-
ucode_rate = le32_to_cpu(table->rs_table[0]);
rs_rate_from_ucode_rate(ucode_rate, info->band, &rate);
rs_collect_tx_data(lq_sta, curr_tbl, rate.index,
@@ -1265,7 +1225,7 @@
IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp);
done:
/* See if there's a better rate or modulation mode to try. */
- if (sta->supp_rates[info->band])
+ if (sta && sta->supp_rates[info->band])
rs_rate_scale_perform(mvm, sta, lq_sta, tid);
}
@@ -1663,8 +1623,6 @@
else
rate->type = LQ_LEGACY_G;
- rate->bw = RATE_MCS_CHAN_WIDTH_20;
- rate->ldpc = false;
rate_mask = lq_sta->active_legacy_rate;
} else if (column->mode == RS_SISO) {
rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO;
@@ -1676,11 +1634,8 @@
WARN_ON_ONCE("Bad column mode");
}
- if (column->mode != RS_LEGACY) {
- rate->bw = rs_bw_from_sta_bw(sta);
- rate->ldpc = lq_sta->ldpc;
- }
-
+ rate->bw = rs_bw_from_sta_bw(sta);
+ rate->ldpc = lq_sta->ldpc;
search_tbl->column = col_id;
rs_set_expected_tpt_table(lq_sta, search_tbl);
@@ -1799,29 +1754,6 @@
return action;
}
-static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta,
- struct iwl_lq_sta *lq_sta)
-{
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- struct ieee80211_vif *vif = mvmsta->vif;
- bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&
- !vif->bss_conf.ps);
-
- /* Our chip supports Tx STBC and the peer is an HT/VHT STA which
- * supports STBC of at least 1*SS
- */
- if (!lq_sta->stbc)
- return false;
-
- if (!mvm->ps_disabled && !sta_ps_disabled)
- return false;
-
- if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta))
- return false;
-
- return true;
-}
-
static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index,
int *weaker, int *stronger)
{
@@ -2743,11 +2675,6 @@
if (mvm->cfg->ht_params->ldpc &&
(ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING))
lq_sta->ldpc = true;
-
- if (mvm->cfg->ht_params->stbc &&
- (num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
- (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC))
- lq_sta->stbc = true;
} else {
rs_vht_set_enabled_rates(sta, vht_cap, lq_sta);
lq_sta->is_vht = true;
@@ -2755,16 +2682,8 @@
if (mvm->cfg->ht_params->ldpc &&
(vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC))
lq_sta->ldpc = true;
-
- if (mvm->cfg->ht_params->stbc &&
- (num_of_ant(mvm->fw->valid_tx_ant) > 1) &&
- (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK))
- lq_sta->stbc = true;
}
- if (IWL_MVM_RS_DISABLE_MIMO)
- lq_sta->active_mimo2_rate = 0;
-
lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate,
BITS_PER_LONG);
lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate,
@@ -2773,11 +2692,11 @@
BITS_PER_LONG);
IWL_DEBUG_RATE(mvm,
- "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC%d\n",
+ "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d\n",
lq_sta->active_legacy_rate,
lq_sta->active_siso_rate,
lq_sta->active_mimo2_rate,
- lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc);
+ lq_sta->is_vht, lq_sta->ldpc);
IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n",
lq_sta->max_legacy_rate_idx,
lq_sta->max_siso_rate_idx,
@@ -2901,7 +2820,6 @@
* rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps
*/
static void rs_build_rates_table(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta,
struct iwl_lq_sta *lq_sta,
const struct rs_rate *initial_rate)
{
@@ -2914,7 +2832,6 @@
memcpy(&rate, initial_rate, sizeof(rate));
valid_tx_ant = mvm->fw->valid_tx_ant;
- rate.stbc = rs_stbc_allow(mvm, sta, lq_sta);
if (is_siso(&rate)) {
num_rates = RS_INITIAL_SISO_NUM_RATES;
@@ -2986,7 +2903,7 @@
if (WARN_ON_ONCE(!sta || !initial_rate))
return;
- rs_build_rates_table(mvm, sta, lq_sta, initial_rate);
+ rs_build_rates_table(mvm, lq_sta, initial_rate);
if (num_of_ant(initial_rate->ant) == 1)
lq_cmd->single_stream_ant_msk = initial_rate->ant;
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h
index fdd0da5..bcb4b1d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.h
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.h
@@ -208,7 +208,6 @@
u32 bw;
bool sgi;
bool ldpc;
- bool stbc;
};
@@ -332,7 +331,6 @@
u64 last_tx;
bool is_vht;
bool ldpc; /* LDPC Rx is supported by the STA */
- bool stbc; /* Tx STBC is supported by chip and Rx by STA */
enum ieee80211_band band;
/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c
index 0f6a40d..e61514b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rx.c
@@ -96,27 +96,27 @@
* Adds the rxb to a new skb and give it to mac80211
*/
static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm,
- struct sk_buff *skb,
struct ieee80211_hdr *hdr, u16 len,
- u32 ampdu_status, u8 crypt_len,
- struct iwl_rx_cmd_buffer *rxb)
+ u32 ampdu_status,
+ struct iwl_rx_cmd_buffer *rxb,
+ struct ieee80211_rx_status *stats)
{
+ struct sk_buff *skb;
unsigned int hdrlen, fraglen;
- /* If frame is small enough to fit in skb->head, pull it completely.
- * If not, only pull ieee80211_hdr (including crypto if present, and
- * an additional 8 bytes for SNAP/ethertype, see below) so that
- * splice() or TCP coalesce are more efficient.
- *
- * Since, in addition, ieee80211_data_to_8023() always pull in at
- * least 8 bytes (possibly more for mesh) we can do the same here
- * to save the cost of doing it later. That still doesn't pull in
- * the actual IP header since the typical case has a SNAP header.
- * If the latter changes (there are efforts in the standards group
- * to do so) we should revisit this and ieee80211_data_to_8023().
+ /* Dont use dev_alloc_skb(), we'll have enough headroom once
+ * ieee80211_hdr pulled.
*/
- hdrlen = (len <= skb_tailroom(skb)) ? len :
- sizeof(*hdr) + crypt_len + 8;
+ skb = alloc_skb(128, GFP_ATOMIC);
+ if (!skb) {
+ IWL_ERR(mvm, "alloc_skb failed\n");
+ return;
+ }
+ /* If frame is small enough to fit in skb->head, pull it completely.
+ * If not, only pull ieee80211_hdr so that splice() or TCP coalesce
+ * are more efficient.
+ */
+ hdrlen = (len <= skb_tailroom(skb)) ? len : sizeof(*hdr);
memcpy(skb_put(skb, hdrlen), hdr, hdrlen);
fraglen = len - hdrlen;
@@ -129,6 +129,8 @@
fraglen, rxb->truesize);
}
+ memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
ieee80211_rx(mvm->hw, skb);
}
@@ -183,8 +185,7 @@
static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm,
struct ieee80211_hdr *hdr,
struct ieee80211_rx_status *stats,
- u32 rx_pkt_status,
- u8 *crypt_len)
+ u32 rx_pkt_status)
{
if (!ieee80211_has_protected(hdr->frame_control) ||
(rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
@@ -204,14 +205,12 @@
stats->flag |= RX_FLAG_DECRYPTED;
IWL_DEBUG_WEP(mvm, "hw decrypted CCMP successfully\n");
- *crypt_len = IEEE80211_CCMP_HDR_LEN;
return 0;
case RX_MPDU_RES_STATUS_SEC_TKIP_ENC:
/* Don't drop the frame and decrypt it in SW */
if (!(rx_pkt_status & RX_MPDU_RES_STATUS_TTAK_OK))
return 0;
- *crypt_len = IEEE80211_TKIP_IV_LEN;
/* fall through if TTAK OK */
case RX_MPDU_RES_STATUS_SEC_WEP_ENC:
@@ -219,9 +218,6 @@
return -1;
stats->flag |= RX_FLAG_DECRYPTED;
- if ((rx_pkt_status & RX_MPDU_RES_STATUS_SEC_ENC_MSK) ==
- RX_MPDU_RES_STATUS_SEC_WEP_ENC)
- *crypt_len = IEEE80211_WEP_IV_LEN;
return 0;
case RX_MPDU_RES_STATUS_SEC_EXT_ENC:
@@ -246,17 +242,15 @@
struct iwl_device_cmd *cmd)
{
struct ieee80211_hdr *hdr;
- struct ieee80211_rx_status *rx_status;
+ struct ieee80211_rx_status rx_status = {};
struct iwl_rx_packet *pkt = rxb_addr(rxb);
struct iwl_rx_phy_info *phy_info;
struct iwl_rx_mpdu_res_start *rx_res;
struct ieee80211_sta *sta;
- struct sk_buff *skb;
u32 len;
u32 ampdu_status;
u32 rate_n_flags;
u32 rx_pkt_status;
- u8 crypt_len = 0;
phy_info = &mvm->last_phy_info;
rx_res = (struct iwl_rx_mpdu_res_start *)pkt->data;
@@ -265,32 +259,20 @@
rx_pkt_status = le32_to_cpup((__le32 *)
(pkt->data + sizeof(*rx_res) + len));
- /* Dont use dev_alloc_skb(), we'll have enough headroom once
- * ieee80211_hdr pulled.
- */
- skb = alloc_skb(128, GFP_ATOMIC);
- if (!skb) {
- IWL_ERR(mvm, "alloc_skb failed\n");
- return 0;
- }
-
- rx_status = IEEE80211_SKB_RXCB(skb);
+ memset(&rx_status, 0, sizeof(rx_status));
/*
* drop the packet if it has failed being decrypted by HW
*/
- if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, rx_status, rx_pkt_status,
- &crypt_len)) {
+ if (iwl_mvm_set_mac80211_rx_flag(mvm, hdr, &rx_status, rx_pkt_status)) {
IWL_DEBUG_DROP(mvm, "Bad decryption results 0x%08x\n",
rx_pkt_status);
- kfree_skb(skb);
return 0;
}
if ((unlikely(phy_info->cfg_phy_cnt > 20))) {
IWL_DEBUG_DROP(mvm, "dsp size out of range [0,20]: %d\n",
phy_info->cfg_phy_cnt);
- kfree_skb(skb);
return 0;
}
@@ -301,31 +283,31 @@
if (!(rx_pkt_status & RX_MPDU_RES_STATUS_CRC_OK) ||
!(rx_pkt_status & RX_MPDU_RES_STATUS_OVERRUN_OK)) {
IWL_DEBUG_RX(mvm, "Bad CRC or FIFO: 0x%08X.\n", rx_pkt_status);
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+ rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
}
/* This will be used in several places later */
rate_n_flags = le32_to_cpu(phy_info->rate_n_flags);
/* rx_status carries information about the packet to mac80211 */
- rx_status->mactime = le64_to_cpu(phy_info->timestamp);
- rx_status->device_timestamp = le32_to_cpu(phy_info->system_timestamp);
- rx_status->band =
+ rx_status.mactime = le64_to_cpu(phy_info->timestamp);
+ rx_status.device_timestamp = le32_to_cpu(phy_info->system_timestamp);
+ rx_status.band =
(phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_BAND_24)) ?
IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
- rx_status->freq =
+ rx_status.freq =
ieee80211_channel_to_frequency(le16_to_cpu(phy_info->channel),
- rx_status->band);
+ rx_status.band);
/*
* TSF as indicated by the fw is at INA time, but mac80211 expects the
* TSF at the beginning of the MPDU.
*/
- /*rx_status->flag |= RX_FLAG_MACTIME_MPDU;*/
+ /*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
- iwl_mvm_get_signal_strength(mvm, phy_info, rx_status);
+ iwl_mvm_get_signal_strength(mvm, phy_info, &rx_status);
- IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status->signal,
- (unsigned long long)rx_status->mactime);
+ IWL_DEBUG_STATS_LIMIT(mvm, "Rssi %d, TSF %llu\n", rx_status.signal,
+ (unsigned long long)rx_status.mactime);
rcu_read_lock();
/*
@@ -344,14 +326,15 @@
if (sta) {
struct iwl_mvm_sta *mvmsta;
mvmsta = iwl_mvm_sta_from_mac80211(sta);
- rs_update_last_rssi(mvm, &mvmsta->lq_sta, rx_status);
+ rs_update_last_rssi(mvm, &mvmsta->lq_sta,
+ &rx_status);
}
rcu_read_unlock();
/* set the preamble flag if appropriate */
if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_SHORT_PREAMBLE))
- rx_status->flag |= RX_FLAG_SHORTPRE;
+ rx_status.flag |= RX_FLAG_SHORTPRE;
if (phy_info->phy_flags & cpu_to_le16(RX_RES_PHY_FLAGS_AGG)) {
/*
@@ -359,8 +342,8 @@
* together since we get a single PHY response
* from the firmware for all of them
*/
- rx_status->flag |= RX_FLAG_AMPDU_DETAILS;
- rx_status->ampdu_reference = mvm->ampdu_ref;
+ rx_status.flag |= RX_FLAG_AMPDU_DETAILS;
+ rx_status.ampdu_reference = mvm->ampdu_ref;
}
/* Set up the HT phy flags */
@@ -368,50 +351,50 @@
case RATE_MCS_CHAN_WIDTH_20:
break;
case RATE_MCS_CHAN_WIDTH_40:
- rx_status->flag |= RX_FLAG_40MHZ;
+ rx_status.flag |= RX_FLAG_40MHZ;
break;
case RATE_MCS_CHAN_WIDTH_80:
- rx_status->vht_flag |= RX_VHT_FLAG_80MHZ;
+ rx_status.vht_flag |= RX_VHT_FLAG_80MHZ;
break;
case RATE_MCS_CHAN_WIDTH_160:
- rx_status->vht_flag |= RX_VHT_FLAG_160MHZ;
+ rx_status.vht_flag |= RX_VHT_FLAG_160MHZ;
break;
}
if (rate_n_flags & RATE_MCS_SGI_MSK)
- rx_status->flag |= RX_FLAG_SHORT_GI;
+ rx_status.flag |= RX_FLAG_SHORT_GI;
if (rate_n_flags & RATE_HT_MCS_GF_MSK)
- rx_status->flag |= RX_FLAG_HT_GF;
+ rx_status.flag |= RX_FLAG_HT_GF;
if (rate_n_flags & RATE_MCS_LDPC_MSK)
- rx_status->flag |= RX_FLAG_LDPC;
+ rx_status.flag |= RX_FLAG_LDPC;
if (rate_n_flags & RATE_MCS_HT_MSK) {
u8 stbc = (rate_n_flags & RATE_MCS_HT_STBC_MSK) >>
RATE_MCS_STBC_POS;
- rx_status->flag |= RX_FLAG_HT;
- rx_status->rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
- rx_status->flag |= stbc << RX_FLAG_STBC_SHIFT;
+ rx_status.flag |= RX_FLAG_HT;
+ rx_status.rate_idx = rate_n_flags & RATE_HT_MCS_INDEX_MSK;
+ rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
} else if (rate_n_flags & RATE_MCS_VHT_MSK) {
u8 stbc = (rate_n_flags & RATE_MCS_VHT_STBC_MSK) >>
RATE_MCS_STBC_POS;
- rx_status->vht_nss =
+ rx_status.vht_nss =
((rate_n_flags & RATE_VHT_MCS_NSS_MSK) >>
RATE_VHT_MCS_NSS_POS) + 1;
- rx_status->rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
- rx_status->flag |= RX_FLAG_VHT;
- rx_status->flag |= stbc << RX_FLAG_STBC_SHIFT;
+ rx_status.rate_idx = rate_n_flags & RATE_VHT_MCS_RATE_CODE_MSK;
+ rx_status.flag |= RX_FLAG_VHT;
+ rx_status.flag |= stbc << RX_FLAG_STBC_SHIFT;
if (rate_n_flags & RATE_MCS_BF_MSK)
- rx_status->vht_flag |= RX_VHT_FLAG_BF;
+ rx_status.vht_flag |= RX_VHT_FLAG_BF;
} else {
- rx_status->rate_idx =
+ rx_status.rate_idx =
iwl_mvm_legacy_rate_to_mac80211_idx(rate_n_flags,
- rx_status->band);
+ rx_status.band);
}
#ifdef CPTCFG_IWLWIFI_DEBUGFS
iwl_mvm_update_frame_stats(mvm, &mvm->drv_rx_stats, rate_n_flags,
- rx_status->flag & RX_FLAG_AMPDU_DETAILS);
+ rx_status.flag & RX_FLAG_AMPDU_DETAILS);
#endif
- iwl_mvm_pass_packet_to_mac80211(mvm, skb, hdr, len, ampdu_status,
- crypt_len, rxb);
+ iwl_mvm_pass_packet_to_mac80211(mvm, hdr, len, ampdu_status,
+ rxb, &rx_status);
return 0;
}
@@ -517,8 +500,29 @@
.mvm = mvm,
};
- iwl_mvm_tt_temp_changed(mvm, le32_to_cpu(common->temperature));
+ /*
+ * set temperature debug enabled - ignore FW temperature updates
+ * and use the user set temperature.
+ */
+ if (mvm->temperature_test) {
+ if (mvm->temperature < le32_to_cpu(common->temperature))
+ IWL_DEBUG_TEMP(mvm,
+ "Ignoring FW temperature update that is greater than the debug set temperature (debug temp = %d, fw temp = %d)\n",
+ mvm->temperature,
+ le32_to_cpu(common->temperature));
+ /*
+ * skip iwl_mvm_tt_handler since we are in
+ * temperature debug mode and we are ignoring
+ * the new temperature value
+ */
+ goto update;
+ }
+ if (mvm->temperature != le32_to_cpu(common->temperature)) {
+ mvm->temperature = le32_to_cpu(common->temperature);
+ iwl_mvm_tt_handler(mvm);
+ }
+update:
iwl_mvm_update_rx_statistics(mvm, stats);
ieee80211_iterate_active_interfaces(mvm->hw,
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index e5294d0..cb85e63 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -83,29 +83,15 @@
} dwell[IEEE80211_NUM_BANDS];
};
-enum iwl_umac_scan_uid_type {
- IWL_UMAC_SCAN_UID_REG_SCAN = BIT(0),
- IWL_UMAC_SCAN_UID_SCHED_SCAN = BIT(1),
- IWL_UMAC_SCAN_UID_ALL = IWL_UMAC_SCAN_UID_REG_SCAN |
- IWL_UMAC_SCAN_UID_SCHED_SCAN,
-};
-
-static int iwl_umac_scan_stop(struct iwl_mvm *mvm,
- enum iwl_umac_scan_uid_type type, bool notify);
-
-static u8 iwl_mvm_scan_rx_ant(struct iwl_mvm *mvm)
-{
- if (mvm->scan_rx_ant != ANT_NONE)
- return mvm->scan_rx_ant;
- return mvm->fw->valid_rx_ant;
-}
-
static inline __le16 iwl_mvm_scan_rx_chain(struct iwl_mvm *mvm)
{
u16 rx_chain;
u8 rx_ant;
- rx_ant = iwl_mvm_scan_rx_ant(mvm);
+ if (mvm->scan_rx_ant != ANT_NONE)
+ rx_ant = mvm->scan_rx_ant;
+ else
+ rx_ant = mvm->fw->valid_rx_ant;
rx_chain = rx_ant << PHY_RX_CHAIN_VALID_POS;
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_MIMO_SEL_POS;
rx_chain |= rx_ant << PHY_RX_CHAIN_FORCE_SEL_POS;
@@ -284,8 +270,7 @@
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
bool *global_bound = data;
- if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt &&
- mvmvif->phy_ctxt->id < MAX_PHYS)
+ if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < MAX_PHYS)
*global_bound = true;
}
@@ -380,10 +365,6 @@
!is_sched_scan)
max_probe_len -= 32;
- /* DS parameter set element is added on 2.4GHZ band if required */
- if (iwl_mvm_rrm_scan_needed(mvm))
- max_probe_len -= 3;
-
return max_probe_len;
}
@@ -478,8 +459,7 @@
basic_ssid ? 1 : 0);
cmd->tx_cmd.tx_flags = cpu_to_le32(TX_CMD_FLG_SEQ_CTL |
- 3 << TX_CMD_FLG_BT_PRIO_POS);
-
+ TX_CMD_FLG_BT_DIS);
cmd->tx_cmd.sta_id = mvm->aux_sta.sta_id;
cmd->tx_cmd.life_time = cpu_to_le32(TX_CMD_LIFE_TIME_INFINITE);
cmd->tx_cmd.rate_n_flags =
@@ -555,17 +535,23 @@
struct iwl_device_cmd *cmd)
{
struct iwl_rx_packet *pkt = rxb_addr(rxb);
+ u8 client_bitmap = 0;
- if (!(mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) &&
- !(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
+ if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
struct iwl_sched_scan_results *notif = (void *)pkt->data;
- if (!(notif->client_bitmap & SCAN_CLIENT_SCHED_SCAN))
- return 0;
+ client_bitmap = notif->client_bitmap;
}
- IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
- ieee80211_sched_scan_results(mvm->hw);
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN ||
+ client_bitmap & SCAN_CLIENT_SCHED_SCAN) {
+ if (mvm->scan_status == IWL_MVM_SCAN_SCHED) {
+ IWL_DEBUG_SCAN(mvm, "Scheduled scan results\n");
+ ieee80211_sched_scan_results(mvm->hw);
+ } else {
+ IWL_DEBUG_SCAN(mvm, "Scan results\n");
+ }
+ }
return 0;
}
@@ -615,6 +601,16 @@
SCAN_COMPLETE_NOTIFICATION };
int ret;
+ if (mvm->scan_status == IWL_MVM_SCAN_NONE)
+ return 0;
+
+ if (iwl_mvm_is_radio_killed(mvm)) {
+ ieee80211_scan_completed(mvm->hw, true);
+ iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
+ mvm->scan_status = IWL_MVM_SCAN_NONE;
+ return 0;
+ }
+
iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort,
scan_abort_notif,
ARRAY_SIZE(scan_abort_notif),
@@ -675,7 +671,6 @@
mvm->scan_status = IWL_MVM_SCAN_NONE;
ieee80211_scan_completed(mvm->hw,
status == IWL_SCAN_OFFLOAD_ABORTED);
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
}
mvm->last_ebs_successful = !ebs_status;
@@ -977,20 +972,6 @@
return ret;
}
-static bool iwl_mvm_scan_pass_all(struct iwl_mvm *mvm,
- struct cfg80211_sched_scan_request *req)
-{
- if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {
- IWL_DEBUG_SCAN(mvm,
- "Sending scheduled scan with filtering, n_match_sets %d\n",
- req->n_match_sets);
- return false;
- }
-
- IWL_DEBUG_SCAN(mvm, "Sending Scheduled scan without filtering\n");
- return true;
-}
-
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req)
{
@@ -1006,8 +987,15 @@
.schedule_line[1].full_scan_mul = IWL_FULL_SCAN_MULTIPLIER,
};
- if (iwl_mvm_scan_pass_all(mvm, req))
+ if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {
+ IWL_DEBUG_SCAN(mvm,
+ "Sending scheduled scan with filtering, filter len %d\n",
+ req->n_match_sets);
+ } else {
+ IWL_DEBUG_SCAN(mvm,
+ "Sending Scheduled scan without filtering\n");
scan_req.flags |= cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_PASS_ALL);
+ }
if (mvm->last_ebs_successful &&
mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT)
@@ -1018,38 +1006,6 @@
sizeof(scan_req), &scan_req);
}
-int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct cfg80211_sched_scan_request *req,
- struct ieee80211_scan_ies *ies)
-{
- int ret;
-
- if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN) {
- ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
- if (ret)
- return ret;
- ret = iwl_mvm_sched_scan_umac(mvm, vif, req, ies);
- } else if ((mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) {
- mvm->scan_status = IWL_MVM_SCAN_SCHED;
- ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
- if (ret)
- return ret;
- ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies);
- } else {
- mvm->scan_status = IWL_MVM_SCAN_SCHED;
- ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies);
- if (ret)
- return ret;
- ret = iwl_mvm_config_sched_scan_profiles(mvm, req);
- if (ret)
- return ret;
- ret = iwl_mvm_sched_scan_start(mvm, req);
- }
-
- return ret;
-}
-
static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm)
{
int ret;
@@ -1094,10 +1050,6 @@
lockdep_assert_held(&mvm->mutex);
- if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
- return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN,
- notify);
-
if (mvm->scan_status != IWL_MVM_SCAN_SCHED &&
(!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) ||
mvm->scan_status != IWL_MVM_SCAN_OS)) {
@@ -1128,12 +1080,8 @@
/*
* Clear the scan status so the next scan requests will succeed. This
* also ensures the Rx handler doesn't do anything, as the scan was
- * stopped from above. Since the rx handler won't do anything now,
- * we have to release the scan reference here.
+ * stopped from above.
*/
- if (mvm->scan_status == IWL_MVM_SCAN_OS)
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
-
mvm->scan_status = IWL_MVM_SCAN_NONE;
if (notify) {
@@ -1185,64 +1133,20 @@
}
}
-static u8 *iwl_mvm_copy_and_insert_ds_elem(struct iwl_mvm *mvm, const u8 *ies,
- size_t len, u8 *const pos)
-{
- static const u8 before_ds_params[] = {
- WLAN_EID_SSID,
- WLAN_EID_SUPP_RATES,
- WLAN_EID_REQUEST,
- WLAN_EID_EXT_SUPP_RATES,
- };
- size_t offs;
- u8 *newpos = pos;
-
- if (!iwl_mvm_rrm_scan_needed(mvm)) {
- memcpy(newpos, ies, len);
- return newpos + len;
- }
-
- offs = ieee80211_ie_split(ies, len,
- before_ds_params,
- ARRAY_SIZE(before_ds_params),
- 0);
-
- memcpy(newpos, ies, offs);
- newpos += offs;
-
- /* Add a placeholder for DS Parameter Set element */
- *newpos++ = WLAN_EID_DS_PARAMS;
- *newpos++ = 1;
- *newpos++ = 0;
-
- memcpy(newpos, ies + offs, len - offs);
- newpos += len - offs;
-
- return newpos;
-}
-
static void
iwl_mvm_build_unified_scan_probe(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
struct ieee80211_scan_ies *ies,
- struct iwl_scan_probe_req *preq,
- const u8 *mac_addr, const u8 *mac_addr_mask)
+ struct iwl_scan_req_unified_lmac *cmd)
{
+ struct iwl_scan_probe_req *preq = (void *)(cmd->data +
+ sizeof(struct iwl_scan_channel_cfg_lmac) *
+ mvm->fw->ucode_capa.n_scan_channels);
struct ieee80211_mgmt *frame = (struct ieee80211_mgmt *)preq->buf;
- u8 *pos, *newpos;
-
- /*
- * Unfortunately, right now the offload scan doesn't support randomising
- * within the firmware, so until the firmware API is ready we implement
- * it in the driver. This means that the scan iterations won't really be
- * random, only when it's restarted, but at least that helps a bit.
- */
- if (mac_addr)
- get_random_mask_addr(frame->sa, mac_addr, mac_addr_mask);
- else
- memcpy(frame->sa, vif->addr, ETH_ALEN);
+ u8 *pos;
frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
eth_broadcast_addr(frame->da);
+ memcpy(frame->sa, vif->addr, ETH_ALEN);
eth_broadcast_addr(frame->bssid);
frame->seq_ctrl = 0;
@@ -1253,14 +1157,11 @@
preq->mac_header.offset = 0;
preq->mac_header.len = cpu_to_le16(24 + 2);
- /* Insert ds parameter set element on 2.4 GHz band */
- newpos = iwl_mvm_copy_and_insert_ds_elem(mvm,
- ies->ies[IEEE80211_BAND_2GHZ],
- ies->len[IEEE80211_BAND_2GHZ],
- pos);
+ memcpy(pos, ies->ies[IEEE80211_BAND_2GHZ],
+ ies->len[IEEE80211_BAND_2GHZ]);
preq->band_data[0].offset = cpu_to_le16(pos - preq->buf);
- preq->band_data[0].len = cpu_to_le16(newpos - pos);
- pos = newpos;
+ preq->band_data[0].len = cpu_to_le16(ies->len[IEEE80211_BAND_2GHZ]);
+ pos += ies->len[IEEE80211_BAND_2GHZ];
memcpy(pos, ies->ies[IEEE80211_BAND_5GHZ],
ies->len[IEEE80211_BAND_5GHZ]);
@@ -1321,10 +1222,9 @@
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
};
struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
- struct iwl_scan_probe_req *preq;
struct iwl_mvm_scan_params params = {};
u32 flags;
- u32 ssid_bitmap = 0;
+ int ssid_bitmap = 0;
int ret, i;
lockdep_assert_held(&mvm->mutex);
@@ -1383,13 +1283,7 @@
req->req.n_channels, ssid_bitmap,
cmd);
- preq = (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
- mvm->fw->ucode_capa.n_scan_channels);
-
- iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, preq,
- req->req.flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
- req->req.mac_addr : NULL,
- req->req.mac_addr_mask);
+ iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, cmd);
ret = iwl_mvm_send_cmd(mvm, &hcmd);
if (!ret) {
@@ -1422,7 +1316,6 @@
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
};
struct iwl_scan_req_unified_lmac *cmd = mvm->scan_cmd;
- struct iwl_scan_probe_req *preq;
struct iwl_mvm_scan_params params = {};
int ret;
u32 flags = 0, ssid_bitmap = 0;
@@ -1446,8 +1339,15 @@
cmd->n_channels = (u8)req->n_channels;
- if (iwl_mvm_scan_pass_all(mvm, req))
+ if (req->n_match_sets && req->match_sets[0].ssid.ssid_len) {
+ IWL_DEBUG_SCAN(mvm,
+ "Sending scheduled scan with filtering, n_match_sets %d\n",
+ req->n_match_sets);
+ } else {
+ IWL_DEBUG_SCAN(mvm,
+ "Sending Scheduled scan without filtering\n");
flags |= IWL_MVM_LMAC_SCAN_FLAG_PASS_ALL;
+ }
if (req->n_ssids == 1 && req->ssids[0].ssid_len != 0)
flags |= IWL_MVM_LMAC_SCAN_FLAG_PRE_CONNECTION;
@@ -1477,13 +1377,7 @@
iwl_mvm_lmac_scan_cfg_channels(mvm, req->channels, req->n_channels,
ssid_bitmap, cmd);
- preq = (void *)(cmd->data + sizeof(struct iwl_scan_channel_cfg_lmac) *
- mvm->fw->ucode_capa.n_scan_channels);
-
- iwl_mvm_build_unified_scan_probe(mvm, vif, ies, preq,
- req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
- req->mac_addr : NULL,
- req->mac_addr_mask);
+ iwl_mvm_build_unified_scan_probe(mvm, vif, ies, cmd);
ret = iwl_mvm_send_cmd(mvm, &hcmd);
if (!ret) {
@@ -1505,594 +1399,7 @@
int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
{
- if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
- return iwl_umac_scan_stop(mvm, IWL_UMAC_SCAN_UID_REG_SCAN,
- true);
-
- if (mvm->scan_status == IWL_MVM_SCAN_NONE)
- return 0;
-
- if (iwl_mvm_is_radio_killed(mvm)) {
- ieee80211_scan_completed(mvm->hw, true);
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
- mvm->scan_status = IWL_MVM_SCAN_NONE;
- return 0;
- }
-
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
return iwl_mvm_scan_offload_stop(mvm, true);
return iwl_mvm_cancel_regular_scan(mvm);
}
-
-/* UMAC scan API */
-
-struct iwl_umac_scan_done {
- struct iwl_mvm *mvm;
- enum iwl_umac_scan_uid_type type;
-};
-
-static int rate_to_scan_rate_flag(unsigned int rate)
-{
- static const int rate_to_scan_rate[IWL_RATE_COUNT] = {
- [IWL_RATE_1M_INDEX] = SCAN_CONFIG_RATE_1M,
- [IWL_RATE_2M_INDEX] = SCAN_CONFIG_RATE_2M,
- [IWL_RATE_5M_INDEX] = SCAN_CONFIG_RATE_5M,
- [IWL_RATE_11M_INDEX] = SCAN_CONFIG_RATE_11M,
- [IWL_RATE_6M_INDEX] = SCAN_CONFIG_RATE_6M,
- [IWL_RATE_9M_INDEX] = SCAN_CONFIG_RATE_9M,
- [IWL_RATE_12M_INDEX] = SCAN_CONFIG_RATE_12M,
- [IWL_RATE_18M_INDEX] = SCAN_CONFIG_RATE_18M,
- [IWL_RATE_24M_INDEX] = SCAN_CONFIG_RATE_24M,
- [IWL_RATE_36M_INDEX] = SCAN_CONFIG_RATE_36M,
- [IWL_RATE_48M_INDEX] = SCAN_CONFIG_RATE_48M,
- [IWL_RATE_54M_INDEX] = SCAN_CONFIG_RATE_54M,
- };
-
- return rate_to_scan_rate[rate];
-}
-
-static __le32 iwl_mvm_scan_config_rates(struct iwl_mvm *mvm)
-{
- struct ieee80211_supported_band *band;
- unsigned int rates = 0;
- int i;
-
- band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ];
- for (i = 0; i < band->n_bitrates; i++)
- rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value);
- band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ];
- for (i = 0; i < band->n_bitrates; i++)
- rates |= rate_to_scan_rate_flag(band->bitrates[i].hw_value);
-
- /* Set both basic rates and supported rates */
- rates |= SCAN_CONFIG_SUPPORTED_RATE(rates);
-
- return cpu_to_le32(rates);
-}
-
-int iwl_mvm_config_scan(struct iwl_mvm *mvm)
-{
-
- struct iwl_scan_config *scan_config;
- struct ieee80211_supported_band *band;
- int num_channels =
- mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels +
- mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
- int ret, i, j = 0, cmd_size, data_size;
- struct iwl_host_cmd cmd = {
- .id = SCAN_CFG_CMD,
- };
-
- if (WARN_ON(num_channels > mvm->fw->ucode_capa.n_scan_channels))
- return -ENOBUFS;
-
- cmd_size = sizeof(*scan_config) + mvm->fw->ucode_capa.n_scan_channels;
-
- scan_config = kzalloc(cmd_size, GFP_KERNEL);
- if (!scan_config)
- return -ENOMEM;
-
- data_size = cmd_size - sizeof(struct iwl_mvm_umac_cmd_hdr);
- scan_config->hdr.size = cpu_to_le16(data_size);
- scan_config->flags = cpu_to_le32(SCAN_CONFIG_FLAG_ACTIVATE |
- SCAN_CONFIG_FLAG_ALLOW_CHUB_REQS |
- SCAN_CONFIG_FLAG_SET_TX_CHAINS |
- SCAN_CONFIG_FLAG_SET_RX_CHAINS |
- SCAN_CONFIG_FLAG_SET_ALL_TIMES |
- SCAN_CONFIG_FLAG_SET_LEGACY_RATES |
- SCAN_CONFIG_FLAG_SET_MAC_ADDR |
- SCAN_CONFIG_FLAG_SET_CHANNEL_FLAGS|
- SCAN_CONFIG_N_CHANNELS(num_channels));
- scan_config->tx_chains = cpu_to_le32(mvm->fw->valid_tx_ant);
- scan_config->rx_chains = cpu_to_le32(iwl_mvm_scan_rx_ant(mvm));
- scan_config->legacy_rates = iwl_mvm_scan_config_rates(mvm);
- scan_config->out_of_channel_time = cpu_to_le32(170);
- scan_config->suspend_time = cpu_to_le32(30);
- scan_config->dwell_active = 20;
- scan_config->dwell_passive = 110;
- scan_config->dwell_fragmented = 20;
-
- memcpy(&scan_config->mac_addr, &mvm->addresses[0].addr, ETH_ALEN);
-
- scan_config->bcast_sta_id = mvm->aux_sta.sta_id;
- scan_config->channel_flags = IWL_CHANNEL_FLAG_EBS |
- IWL_CHANNEL_FLAG_ACCURATE_EBS |
- IWL_CHANNEL_FLAG_EBS_ADD |
- IWL_CHANNEL_FLAG_PRE_SCAN_PASSIVE2ACTIVE;
-
- band = &mvm->nvm_data->bands[IEEE80211_BAND_2GHZ];
- for (i = 0; i < band->n_channels; i++, j++)
- scan_config->channel_array[j] = band->channels[i].center_freq;
- band = &mvm->nvm_data->bands[IEEE80211_BAND_5GHZ];
- for (i = 0; i < band->n_channels; i++, j++)
- scan_config->channel_array[j] = band->channels[i].center_freq;
-
- cmd.data[0] = scan_config;
- cmd.len[0] = cmd_size;
- cmd.dataflags[0] = IWL_HCMD_DFL_NOCOPY;
-
- IWL_DEBUG_SCAN(mvm, "Sending UMAC scan config\n");
-
- ret = iwl_mvm_send_cmd(mvm, &cmd);
-
- kfree(scan_config);
- return ret;
-}
-
-static int iwl_mvm_find_scan_uid(struct iwl_mvm *mvm, u32 uid)
-{
- int i;
-
- for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++)
- if (mvm->scan_uid[i] == uid)
- return i;
-
- return i;
-}
-
-static int iwl_mvm_find_free_scan_uid(struct iwl_mvm *mvm)
-{
- return iwl_mvm_find_scan_uid(mvm, 0);
-}
-
-static bool iwl_mvm_find_scan_type(struct iwl_mvm *mvm,
- enum iwl_umac_scan_uid_type type)
-{
- int i;
-
- for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++)
- if (mvm->scan_uid[i] & type)
- return true;
-
- return false;
-}
-
-static u32 iwl_generate_scan_uid(struct iwl_mvm *mvm,
- enum iwl_umac_scan_uid_type type)
-{
- u32 uid;
-
- /* make sure exactly one bit is on in scan type */
- WARN_ON(hweight8(type) != 1);
-
- /*
- * Make sure scan uids are unique. If one scan lasts long time while
- * others are completing frequently, the seq number will wrap up and
- * we may have more than one scan with the same uid.
- */
- do {
- uid = type | (mvm->scan_seq_num <<
- IWL_UMAC_SCAN_UID_SEQ_OFFSET);
- mvm->scan_seq_num++;
- } while (iwl_mvm_find_scan_uid(mvm, uid) <
- IWL_MVM_MAX_SIMULTANEOUS_SCANS);
-
- IWL_DEBUG_SCAN(mvm, "Generated scan UID %u\n", uid);
-
- return uid;
-}
-
-static void
-iwl_mvm_build_generic_umac_scan_cmd(struct iwl_mvm *mvm,
- struct iwl_scan_req_umac *cmd,
- struct iwl_mvm_scan_params *params)
-{
- memset(cmd, 0, ksize(cmd));
- cmd->hdr.size = cpu_to_le16(iwl_mvm_scan_size(mvm) -
- sizeof(struct iwl_mvm_umac_cmd_hdr));
- cmd->active_dwell = params->dwell[IEEE80211_BAND_2GHZ].active;
- cmd->passive_dwell = params->dwell[IEEE80211_BAND_2GHZ].passive;
- if (params->passive_fragmented)
- cmd->fragmented_dwell =
- params->dwell[IEEE80211_BAND_2GHZ].passive;
- cmd->max_out_time = cpu_to_le32(params->max_out_time);
- cmd->suspend_time = cpu_to_le32(params->suspend_time);
- cmd->scan_priority = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
-}
-
-static void
-iwl_mvm_umac_scan_cfg_channels(struct iwl_mvm *mvm,
- struct ieee80211_channel **channels,
- int n_channels, u32 ssid_bitmap,
- struct iwl_scan_req_umac *cmd)
-{
- struct iwl_scan_channel_cfg_umac *channel_cfg = (void *)&cmd->data;
- int i;
-
- for (i = 0; i < n_channels; i++) {
- channel_cfg[i].flags = cpu_to_le32(ssid_bitmap);
- channel_cfg[i].channel_num = channels[i]->hw_value;
- channel_cfg[i].iter_count = 1;
- channel_cfg[i].iter_interval = 0;
- }
-}
-
-static u32 iwl_mvm_scan_umac_common_flags(struct iwl_mvm *mvm, int n_ssids,
- struct cfg80211_ssid *ssids,
- int fragmented)
-{
- int flags = 0;
-
- if (n_ssids == 0)
- flags = IWL_UMAC_SCAN_GEN_FLAGS_PASSIVE;
-
- if (n_ssids == 1 && ssids[0].ssid_len != 0)
- flags |= IWL_UMAC_SCAN_GEN_FLAGS_PRE_CONNECT;
-
- if (fragmented)
- flags |= IWL_UMAC_SCAN_GEN_FLAGS_FRAGMENTED;
-
- if (iwl_mvm_rrm_scan_needed(mvm))
- flags |= IWL_UMAC_SCAN_GEN_FLAGS_RRM_ENABLED;
-
- return flags;
-}
-
-int iwl_mvm_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct ieee80211_scan_request *req)
-{
- struct iwl_host_cmd hcmd = {
- .id = SCAN_REQ_UMAC,
- .len = { iwl_mvm_scan_size(mvm), },
- .data = { mvm->scan_cmd, },
- .dataflags = { IWL_HCMD_DFL_NOCOPY, },
- };
- struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
- struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
- sizeof(struct iwl_scan_channel_cfg_umac) *
- mvm->fw->ucode_capa.n_scan_channels;
- struct iwl_mvm_scan_params params = {};
- u32 uid, flags;
- u32 ssid_bitmap = 0;
- int ret, i, uid_idx;
-
- lockdep_assert_held(&mvm->mutex);
-
- uid_idx = iwl_mvm_find_free_scan_uid(mvm);
- if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
- return -EBUSY;
-
- /* we should have failed registration if scan_cmd was NULL */
- if (WARN_ON(mvm->scan_cmd == NULL))
- return -ENOMEM;
-
- if (WARN_ON(req->req.n_ssids > PROBE_OPTION_MAX ||
- req->ies.common_ie_len +
- req->ies.len[NL80211_BAND_2GHZ] +
- req->ies.len[NL80211_BAND_5GHZ] + 24 + 2 >
- SCAN_OFFLOAD_PROBE_REQ_SIZE || req->req.n_channels >
- mvm->fw->ucode_capa.n_scan_channels))
- return -ENOBUFS;
-
- iwl_mvm_scan_calc_params(mvm, vif, req->req.n_ssids, req->req.flags,
- ¶ms);
-
- iwl_mvm_build_generic_umac_scan_cmd(mvm, cmd, ¶ms);
-
- uid = iwl_generate_scan_uid(mvm, IWL_UMAC_SCAN_UID_REG_SCAN);
- mvm->scan_uid[uid_idx] = uid;
- cmd->uid = cpu_to_le32(uid);
-
- cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_HIGH);
-
- flags = iwl_mvm_scan_umac_common_flags(mvm, req->req.n_ssids,
- req->req.ssids,
- params.passive_fragmented);
-
- flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL;
-
- cmd->general_flags = cpu_to_le32(flags);
- cmd->n_channels = req->req.n_channels;
-
- for (i = 0; i < req->req.n_ssids; i++)
- ssid_bitmap |= BIT(i);
-
- iwl_mvm_umac_scan_cfg_channels(mvm, req->req.channels,
- req->req.n_channels, ssid_bitmap, cmd);
-
- sec_part->schedule[0].iter_count = 1;
- sec_part->delay = 0;
-
- iwl_mvm_build_unified_scan_probe(mvm, vif, &req->ies, &sec_part->preq,
- req->req.flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
- req->req.mac_addr : NULL,
- req->req.mac_addr_mask);
-
- iwl_mvm_scan_fill_ssids(sec_part->direct_scan, req->req.ssids,
- req->req.n_ssids, 0);
-
- ret = iwl_mvm_send_cmd(mvm, &hcmd);
- if (!ret) {
- IWL_DEBUG_SCAN(mvm,
- "Scan request was sent successfully\n");
- } else {
- /*
- * If the scan failed, it usually means that the FW was unable
- * to allocate the time events. Warn on it, but maybe we
- * should try to send the command again with different params.
- */
- IWL_ERR(mvm, "Scan failed! ret %d\n", ret);
- }
- return ret;
-}
-
-int iwl_mvm_sched_scan_umac(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- struct cfg80211_sched_scan_request *req,
- struct ieee80211_scan_ies *ies)
-{
-
- struct iwl_host_cmd hcmd = {
- .id = SCAN_REQ_UMAC,
- .len = { iwl_mvm_scan_size(mvm), },
- .data = { mvm->scan_cmd, },
- .dataflags = { IWL_HCMD_DFL_NOCOPY, },
- };
- struct iwl_scan_req_umac *cmd = mvm->scan_cmd;
- struct iwl_scan_req_umac_tail *sec_part = (void *)&cmd->data +
- sizeof(struct iwl_scan_channel_cfg_umac) *
- mvm->fw->ucode_capa.n_scan_channels;
- struct iwl_mvm_scan_params params = {};
- u32 uid, flags;
- u32 ssid_bitmap = 0;
- int ret, uid_idx;
-
- lockdep_assert_held(&mvm->mutex);
-
- uid_idx = iwl_mvm_find_free_scan_uid(mvm);
- if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
- return -EBUSY;
-
- /* we should have failed registration if scan_cmd was NULL */
- if (WARN_ON(mvm->scan_cmd == NULL))
- return -ENOMEM;
-
- if (WARN_ON(req->n_ssids > PROBE_OPTION_MAX ||
- ies->common_ie_len + ies->len[NL80211_BAND_2GHZ] +
- ies->len[NL80211_BAND_5GHZ] + 24 + 2 >
- SCAN_OFFLOAD_PROBE_REQ_SIZE || req->n_channels >
- mvm->fw->ucode_capa.n_scan_channels))
- return -ENOBUFS;
-
- iwl_mvm_scan_calc_params(mvm, vif, req->n_ssids, req->flags,
- ¶ms);
-
- iwl_mvm_build_generic_umac_scan_cmd(mvm, cmd, ¶ms);
-
- cmd->flags = cpu_to_le32(IWL_UMAC_SCAN_FLAG_PREEMPTIVE);
-
- uid = iwl_generate_scan_uid(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN);
- mvm->scan_uid[uid_idx] = uid;
- cmd->uid = cpu_to_le32(uid);
-
- cmd->ooc_priority = cpu_to_le32(IWL_SCAN_PRIORITY_LOW);
-
- flags = iwl_mvm_scan_umac_common_flags(mvm, req->n_ssids, req->ssids,
- params.passive_fragmented);
-
- flags |= IWL_UMAC_SCAN_GEN_FLAGS_PERIODIC;
-
- if (iwl_mvm_scan_pass_all(mvm, req))
- flags |= IWL_UMAC_SCAN_GEN_FLAGS_PASS_ALL;
- else
- flags |= IWL_UMAC_SCAN_GEN_FLAGS_MATCH;
-
- cmd->general_flags = cpu_to_le32(flags);
-
- if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_EBS_SUPPORT &&
- mvm->last_ebs_successful)
- cmd->channel_flags = IWL_SCAN_CHANNEL_FLAG_EBS |
- IWL_SCAN_CHANNEL_FLAG_EBS_ACCURATE |
- IWL_SCAN_CHANNEL_FLAG_CACHE_ADD;
-
- cmd->n_channels = req->n_channels;
-
- iwl_scan_offload_build_ssid(req, sec_part->direct_scan, &ssid_bitmap,
- false);
-
- /* This API uses bits 0-19 instead of 1-20. */
- ssid_bitmap = ssid_bitmap >> 1;
-
- iwl_mvm_umac_scan_cfg_channels(mvm, req->channels, req->n_channels,
- ssid_bitmap, cmd);
-
- sec_part->schedule[0].interval =
- cpu_to_le16(req->interval / MSEC_PER_SEC);
- sec_part->schedule[0].iter_count = 0xff;
-
- sec_part->delay = 0;
-
- iwl_mvm_build_unified_scan_probe(mvm, vif, ies, &sec_part->preq,
- req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR ?
- req->mac_addr : NULL,
- req->mac_addr_mask);
-
- ret = iwl_mvm_send_cmd(mvm, &hcmd);
- if (!ret) {
- IWL_DEBUG_SCAN(mvm,
- "Sched scan request was sent successfully\n");
- } else {
- /*
- * If the scan failed, it usually means that the FW was unable
- * to allocate the time events. Warn on it, but maybe we
- * should try to send the command again with different params.
- */
- IWL_ERR(mvm, "Sched scan failed! ret %d\n", ret);
- }
- return ret;
-}
-
-int iwl_mvm_rx_umac_scan_complete_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_umac_scan_complete *notif = (void *)pkt->data;
- u32 uid = __le32_to_cpu(notif->uid);
- bool sched = !!(uid & IWL_UMAC_SCAN_UID_SCHED_SCAN);
- int uid_idx = iwl_mvm_find_scan_uid(mvm, uid);
-
- /*
- * Scan uid may be set to zero in case of scan abort request from above.
- */
- if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
- return 0;
-
- IWL_DEBUG_SCAN(mvm,
- "Scan completed, uid %u type %s, status %s, EBS status %s\n",
- uid, sched ? "sched" : "regular",
- notif->status == IWL_SCAN_OFFLOAD_COMPLETED ?
- "completed" : "aborted",
- notif->ebs_status == IWL_SCAN_EBS_SUCCESS ?
- "success" : "failed");
-
- mvm->last_ebs_successful = !notif->ebs_status;
- mvm->scan_uid[uid_idx] = 0;
-
- if (!sched) {
- ieee80211_scan_completed(mvm->hw,
- notif->status ==
- IWL_SCAN_OFFLOAD_ABORTED);
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
- } else if (!iwl_mvm_find_scan_type(mvm, IWL_UMAC_SCAN_UID_SCHED_SCAN)) {
- ieee80211_sched_scan_stopped(mvm->hw);
- } else {
- IWL_DEBUG_SCAN(mvm, "Another sched scan is running\n");
- }
-
- return 0;
-}
-
-static bool iwl_scan_umac_done_check(struct iwl_notif_wait_data *notif_wait,
- struct iwl_rx_packet *pkt, void *data)
-{
- struct iwl_umac_scan_done *scan_done = data;
- struct iwl_umac_scan_complete *notif = (void *)pkt->data;
- u32 uid = __le32_to_cpu(notif->uid);
- int uid_idx = iwl_mvm_find_scan_uid(scan_done->mvm, uid);
-
- if (WARN_ON(pkt->hdr.cmd != SCAN_COMPLETE_UMAC))
- return false;
-
- if (uid_idx >= IWL_MVM_MAX_SIMULTANEOUS_SCANS)
- return false;
-
- /*
- * Clear scan uid of scans that was aborted from above and completed
- * in FW so the RX handler does nothing.
- */
- scan_done->mvm->scan_uid[uid_idx] = 0;
-
- return !iwl_mvm_find_scan_type(scan_done->mvm, scan_done->type);
-}
-
-static int iwl_umac_scan_abort_one(struct iwl_mvm *mvm, u32 uid)
-{
- struct iwl_umac_scan_abort cmd = {
- .hdr.size = cpu_to_le16(sizeof(struct iwl_umac_scan_abort) -
- sizeof(struct iwl_mvm_umac_cmd_hdr)),
- .uid = cpu_to_le32(uid),
- };
-
- lockdep_assert_held(&mvm->mutex);
-
- IWL_DEBUG_SCAN(mvm, "Sending scan abort, uid %u\n", uid);
-
- return iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_UMAC, 0, sizeof(cmd), &cmd);
-}
-
-static int iwl_umac_scan_stop(struct iwl_mvm *mvm,
- enum iwl_umac_scan_uid_type type, bool notify)
-{
- struct iwl_notification_wait wait_scan_done;
- static const u8 scan_done_notif[] = { SCAN_COMPLETE_UMAC, };
- struct iwl_umac_scan_done scan_done = {
- .mvm = mvm,
- .type = type,
- };
- int i, ret = -EIO;
-
- iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_done,
- scan_done_notif,
- ARRAY_SIZE(scan_done_notif),
- iwl_scan_umac_done_check, &scan_done);
-
- IWL_DEBUG_SCAN(mvm, "Preparing to stop scan, type %x\n", type);
-
- for (i = 0; i < IWL_MVM_MAX_SIMULTANEOUS_SCANS; i++) {
- if (mvm->scan_uid[i] & type) {
- int err;
-
- if (iwl_mvm_is_radio_killed(mvm) &&
- (type & IWL_UMAC_SCAN_UID_REG_SCAN)) {
- ieee80211_scan_completed(mvm->hw, true);
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
- break;
- }
-
- err = iwl_umac_scan_abort_one(mvm, mvm->scan_uid[i]);
- if (!err)
- ret = 0;
- }
- }
-
- if (ret) {
- IWL_DEBUG_SCAN(mvm, "Couldn't stop scan\n");
- iwl_remove_notification(&mvm->notif_wait, &wait_scan_done);
- return ret;
- }
-
- ret = iwl_wait_notification(&mvm->notif_wait, &wait_scan_done, 1 * HZ);
- if (ret)
- return ret;
-
- if (notify) {
- if (type & IWL_UMAC_SCAN_UID_SCHED_SCAN)
- ieee80211_sched_scan_stopped(mvm->hw);
- if (type & IWL_UMAC_SCAN_UID_REG_SCAN) {
- ieee80211_scan_completed(mvm->hw, true);
- iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN);
- }
- }
-
- return ret;
-}
-
-int iwl_mvm_scan_size(struct iwl_mvm *mvm)
-{
- if (mvm->fw->ucode_capa.capa[0] & IWL_UCODE_TLV_CAPA_UMAC_SCAN)
- return sizeof(struct iwl_scan_req_umac) +
- sizeof(struct iwl_scan_channel_cfg_umac) *
- mvm->fw->ucode_capa.n_scan_channels +
- sizeof(struct iwl_scan_req_umac_tail);
-
- if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)
- return sizeof(struct iwl_scan_req_unified_lmac) +
- sizeof(struct iwl_scan_channel_cfg_lmac) *
- mvm->fw->ucode_capa.n_scan_channels +
- sizeof(struct iwl_scan_probe_req);
-
- return sizeof(struct iwl_scan_cmd) +
- mvm->fw->ucode_capa.max_probe_length +
- mvm->fw->ucode_capa.n_scan_channels *
- sizeof(struct iwl_scan_channel);
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index d86fe43..1731c20 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -204,56 +204,6 @@
return ret;
}
-static int iwl_mvm_tdls_sta_init(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta)
-{
- unsigned long used_hw_queues;
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- u32 ac;
-
- lockdep_assert_held(&mvm->mutex);
-
- used_hw_queues = iwl_mvm_get_used_hw_queues(mvm, NULL);
-
- /* Find available queues, and allocate them to the ACs */
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- u8 queue = find_first_zero_bit(&used_hw_queues,
- mvm->first_agg_queue);
-
- if (queue >= mvm->first_agg_queue) {
- IWL_ERR(mvm, "Failed to allocate STA queue\n");
- return -EBUSY;
- }
-
- __set_bit(queue, &used_hw_queues);
- mvmsta->hw_queue[ac] = queue;
- }
-
- /* Found a place for all queues - enable them */
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- iwl_mvm_enable_ac_txq(mvm, mvmsta->hw_queue[ac],
- iwl_mvm_ac_to_tx_fifo[ac]);
- mvmsta->tfd_queue_msk |= BIT(mvmsta->hw_queue[ac]);
- }
-
- return 0;
-}
-
-static void iwl_mvm_tdls_sta_deinit(struct iwl_mvm *mvm,
- struct ieee80211_sta *sta)
-{
- struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
- unsigned long sta_msk;
- int i;
-
- lockdep_assert_held(&mvm->mutex);
-
- /* disable the TDLS STA-specific queues */
- sta_msk = mvmsta->tfd_queue_msk;
- for_each_set_bit(i, &sta_msk, sizeof(sta_msk))
- iwl_mvm_disable_txq(mvm, i);
-}
-
int iwl_mvm_add_sta(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
@@ -287,17 +237,9 @@
atomic_set(&mvm->pending_frames[sta_id], 0);
mvm_sta->tid_disable_agg = 0;
mvm_sta->tfd_queue_msk = 0;
-
- /* allocate new queues for a TDLS station */
- if (sta->tdls) {
- ret = iwl_mvm_tdls_sta_init(mvm, sta);
- if (ret)
- return ret;
- } else {
- for (i = 0; i < IEEE80211_NUM_ACS; i++)
- if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
- mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]);
- }
+ for (i = 0; i < IEEE80211_NUM_ACS; i++)
+ if (vif->hw_queue[i] != IEEE80211_INVAL_HW_QUEUE)
+ mvm_sta->tfd_queue_msk |= BIT(vif->hw_queue[i]);
/* for HW restart - reset everything but the sequence number */
for (i = 0; i < IWL_MAX_TID_COUNT; i++) {
@@ -309,7 +251,7 @@
ret = iwl_mvm_sta_send_to_fw(mvm, sta, false);
if (ret)
- goto err;
+ return ret;
if (vif->type == NL80211_IFTYPE_STATION) {
if (!sta->tdls) {
@@ -323,10 +265,6 @@
rcu_assign_pointer(mvm->fw_id_to_mac_id[sta_id], sta);
return 0;
-
-err:
- iwl_mvm_tdls_sta_deinit(mvm, sta);
- return ret;
}
int iwl_mvm_update_sta(struct iwl_mvm *mvm,
@@ -460,17 +398,6 @@
}
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[sta_id], NULL);
clear_bit(sta_id, mvm->sta_drained);
-
- if (mvm->tfd_drained[sta_id]) {
- unsigned long i, msk = mvm->tfd_drained[sta_id];
-
- for_each_set_bit(i, &msk, sizeof(msk))
- iwl_mvm_disable_txq(mvm, i);
-
- mvm->tfd_drained[sta_id] = 0;
- IWL_DEBUG_TDLS(mvm, "Drained sta %d, with queues %ld\n",
- sta_id, msk);
- }
}
mutex_unlock(&mvm->mutex);
@@ -504,15 +431,6 @@
}
/*
- * This shouldn't happen - the TDLS channel switch should be canceled
- * before the STA is removed.
- */
- if (WARN_ON_ONCE(mvm->tdls_cs.peer.sta_id == mvm_sta->sta_id)) {
- mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT;
- cancel_delayed_work(&mvm->tdls_cs.dwork);
- }
-
- /*
* Make sure that the tx response code sees the station as -EBUSY and
* calls the drain worker.
*/
@@ -525,22 +443,9 @@
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvm_sta->sta_id],
ERR_PTR(-EBUSY));
spin_unlock_bh(&mvm_sta->lock);
-
- /* disable TDLS sta queues on drain complete */
- if (sta->tdls) {
- mvm->tfd_drained[mvm_sta->sta_id] =
- mvm_sta->tfd_queue_msk;
- IWL_DEBUG_TDLS(mvm, "Draining TDLS sta %d\n",
- mvm_sta->sta_id);
- }
-
ret = iwl_mvm_drain_sta(mvm, mvm_sta, true);
} else {
spin_unlock_bh(&mvm_sta->lock);
-
- if (sta->tdls)
- iwl_mvm_tdls_sta_deinit(mvm, sta);
-
ret = iwl_mvm_rm_sta_common(mvm, mvm_sta->sta_id);
RCU_INIT_POINTER(mvm->fw_id_to_mac_id[mvm_sta->sta_id], NULL);
}
@@ -704,7 +609,7 @@
lockdep_assert_held(&mvm->mutex);
- qmask = iwl_mvm_mac_get_queues_mask(vif);
+ qmask = iwl_mvm_mac_get_queues_mask(mvm, vif);
/*
* The firmware defines the TFD queue mask to only be relevant
@@ -1166,16 +1071,15 @@
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
struct iwl_mvm_sta *mvm_sta,
- struct ieee80211_key_conf *keyconf, bool mcast,
- u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags)
+ struct ieee80211_key_conf *keyconf,
+ u8 sta_id, u32 tkip_iv32, u16 *tkip_p1k,
+ u32 cmd_flags)
{
struct iwl_mvm_add_sta_key_cmd cmd = {};
__le16 key_flags;
- int ret;
- u32 status;
+ int ret, status;
u16 keyidx;
int i;
- u8 sta_id = mvm_sta->sta_id;
keyidx = (keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
STA_KEY_FLG_KEYID_MSK;
@@ -1194,18 +1098,12 @@
key_flags |= cpu_to_le16(STA_KEY_FLG_CCM);
memcpy(cmd.key, keyconf->key, keyconf->keylen);
break;
- case WLAN_CIPHER_SUITE_WEP104:
- key_flags |= cpu_to_le16(STA_KEY_FLG_WEP_13BYTES);
- case WLAN_CIPHER_SUITE_WEP40:
- key_flags |= cpu_to_le16(STA_KEY_FLG_WEP);
- memcpy(cmd.key + 3, keyconf->key, keyconf->keylen);
- break;
default:
key_flags |= cpu_to_le16(STA_KEY_FLG_EXT);
memcpy(cmd.key, keyconf->key, keyconf->keylen);
}
- if (mcast)
+ if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
cmd.key_offset = keyconf->hw_key_idx;
@@ -1297,88 +1195,17 @@
return NULL;
}
-static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- struct ieee80211_key_conf *keyconf,
- bool mcast)
-{
- struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
- int ret;
- const u8 *addr;
- struct ieee80211_key_seq seq;
- u16 p1k[5];
-
- switch (keyconf->cipher) {
- case WLAN_CIPHER_SUITE_TKIP:
- addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
- /* get phase 1 key from mac80211 */
- ieee80211_get_key_rx_seq(keyconf, 0, &seq);
- ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
- ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
- seq.tkip.iv32, p1k, 0);
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
- 0, NULL, 0);
- break;
- default:
- ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
- 0, NULL, 0);
- }
-
- return ret;
-}
-
-static int __iwl_mvm_remove_sta_key(struct iwl_mvm *mvm, u8 sta_id,
- struct ieee80211_key_conf *keyconf,
- bool mcast)
-{
- struct iwl_mvm_add_sta_key_cmd cmd = {};
- __le16 key_flags;
- int ret;
- u32 status;
-
- key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
- STA_KEY_FLG_KEYID_MSK);
- key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
- key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
-
- if (mcast)
- key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
-
- cmd.key_flags = key_flags;
- cmd.key_offset = keyconf->hw_key_idx;
- cmd.sta_id = sta_id;
-
- status = ADD_STA_SUCCESS;
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
- &cmd, &status);
-
- switch (status) {
- case ADD_STA_SUCCESS:
- IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
- break;
- default:
- ret = -EIO;
- IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
- break;
- }
-
- return ret;
-}
-
int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
struct ieee80211_key_conf *keyconf,
bool have_key_offset)
{
- bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
- u8 sta_id;
+ struct iwl_mvm_sta *mvm_sta;
int ret;
+ u8 *addr, sta_id;
+ struct ieee80211_key_seq seq;
+ u16 p1k[5];
lockdep_assert_held(&mvm->mutex);
@@ -1407,7 +1234,8 @@
}
}
- if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
+ mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv;
+ if (WARN_ON_ONCE(mvm_sta->vif != vif))
return -EINVAL;
if (!have_key_offset) {
@@ -1421,26 +1249,26 @@
return -ENOSPC;
}
- ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, mcast);
- if (ret) {
- __clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
- goto end;
+ switch (keyconf->cipher) {
+ case WLAN_CIPHER_SUITE_TKIP:
+ addr = iwl_mvm_get_mac_addr(mvm, vif, sta);
+ /* get phase 1 key from mac80211 */
+ ieee80211_get_key_rx_seq(keyconf, 0, &seq);
+ ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
+ ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
+ seq.tkip.iv32, p1k, 0);
+ break;
+ case WLAN_CIPHER_SUITE_CCMP:
+ ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
+ 0, NULL, 0);
+ break;
+ default:
+ ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,
+ sta_id, 0, NULL, 0);
}
- /*
- * For WEP, the same key is used for multicast and unicast. Upload it
- * again, using the same key offset, and now pointing the other one
- * to the same key slot (offset).
- * If this fails, remove the original as well.
- */
- if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
- keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
- ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, !mcast);
- if (ret) {
- __clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
- __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
- }
- }
+ if (ret)
+ __clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
end:
IWL_DEBUG_WEP(mvm, "key: cipher=%x len=%d idx=%d sta=%pM ret=%d\n",
@@ -1454,9 +1282,11 @@
struct ieee80211_sta *sta,
struct ieee80211_key_conf *keyconf)
{
- bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
+ struct iwl_mvm_sta *mvm_sta;
+ struct iwl_mvm_add_sta_key_cmd cmd = {};
+ __le16 key_flags;
+ int ret, status;
u8 sta_id;
- int ret;
lockdep_assert_held(&mvm->mutex);
@@ -1469,7 +1299,8 @@
if (keyconf->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
return iwl_mvm_send_sta_igtk(mvm, keyconf, sta_id, true);
- if (!__test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table)) {
+ ret = __test_and_clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
+ if (!ret) {
IWL_ERR(mvm, "offset %d not used in fw key table.\n",
keyconf->hw_key_idx);
return -ENOENT;
@@ -1495,17 +1326,35 @@
}
}
- if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
+ mvm_sta = (struct iwl_mvm_sta *)sta->drv_priv;
+ if (WARN_ON_ONCE(mvm_sta->vif != vif))
return -EINVAL;
- ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
- if (ret)
- return ret;
+ key_flags = cpu_to_le16((keyconf->keyidx << STA_KEY_FLG_KEYID_POS) &
+ STA_KEY_FLG_KEYID_MSK);
+ key_flags |= cpu_to_le16(STA_KEY_FLG_NO_ENC | STA_KEY_FLG_WEP_KEY_MAP);
+ key_flags |= cpu_to_le16(STA_KEY_NOT_VALID);
- /* delete WEP key twice to get rid of (now useless) offset */
- if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
- keyconf->cipher == WLAN_CIPHER_SUITE_WEP104)
- ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, !mcast);
+ if (!(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+ key_flags |= cpu_to_le16(STA_KEY_MULTICAST);
+
+ cmd.key_flags = key_flags;
+ cmd.key_offset = keyconf->hw_key_idx;
+ cmd.sta_id = sta_id;
+
+ status = ADD_STA_SUCCESS;
+ ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
+ &cmd, &status);
+
+ switch (status) {
+ case ADD_STA_SUCCESS:
+ IWL_DEBUG_WEP(mvm, "MODIFY_STA: remove sta key passed\n");
+ break;
+ default:
+ ret = -EIO;
+ IWL_ERR(mvm, "MODIFY_STA: remove sta key failed\n");
+ break;
+ }
return ret;
}
@@ -1518,7 +1367,6 @@
{
struct iwl_mvm_sta *mvm_sta;
u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
- bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
return;
@@ -1533,8 +1381,8 @@
}
}
- mvm_sta = iwl_mvm_sta_from_mac80211(sta);
- iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
+ mvm_sta = (void *)sta->drv_priv;
+ iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
iv32, phase1key, CMD_ASYNC);
rcu_read_unlock();
}
@@ -1732,18 +1580,3 @@
iwl_mvm_sta_modify_disable_tx_ap(mvm, sta, disable);
}
}
-
-void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm_sta *mvmsta;
-
- rcu_read_lock();
-
- mvmsta = iwl_mvm_sta_from_staid_rcu(mvm, mvmvif->ap_sta_id);
-
- if (!WARN_ON(!mvmsta))
- iwl_mvm_sta_modify_disable_tx(mvm, mvmsta, true);
-
- rcu_read_unlock();
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index d8f4897..d9c0d7b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -264,7 +264,6 @@
* the first packet to be sent in legacy HW queue in Tx AGG stop flow.
* Basically when next_reclaimed reaches ssn, we can tell mac80211 that
* we are ready to finish the Tx AGG stop / start flow.
- * @tx_time: medium time consumed by this A-MPDU
*/
struct iwl_mvm_tid_data {
u16 seq_number;
@@ -275,7 +274,6 @@
enum iwl_mvm_agg_state state;
u16 txq_id;
u16 ssn;
- u16 tx_time;
};
static inline u16 iwl_mvm_tid_queued(struct iwl_mvm_tid_data *tid_data)
@@ -288,7 +286,6 @@
* struct iwl_mvm_sta - representation of a station in the driver
* @sta_id: the index of the station in the fw (will be replaced by id_n_color)
* @tfd_queue_msk: the tfd queues used by the station
- * @hw_queue: per-AC mapping of the TFD queues used by station
* @mac_id_n_color: the MAC context this station is linked to
* @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
* tid.
@@ -312,7 +309,6 @@
struct iwl_mvm_sta {
u32 sta_id;
u32 tfd_queue_msk;
- u8 hw_queue[IEEE80211_NUM_ACS];
u32 mac_id_n_color;
u16 tid_disable_agg;
u8 max_agg_bufsize;
@@ -422,6 +418,5 @@
void iwl_mvm_modify_all_sta_disable_tx(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif,
bool disable);
-void iwl_mvm_csa_client_absent(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
#endif /* __sta_h__ */
diff --git a/drivers/net/wireless/iwlwifi/mvm/tdls.c b/drivers/net/wireless/iwlwifi/mvm/tdls.c
index c0e00ba..66c82df 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tdls.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tdls.c
@@ -61,13 +61,9 @@
*
*****************************************************************************/
-#include <linux/etherdevice.h>
#include "mvm.h"
#include "time-event.h"
-#define TU_TO_US(x) (x * 1024)
-#define TU_TO_MS(x) (TU_TO_US(x) / 1000)
-
void iwl_mvm_teardown_tdls_peers(struct iwl_mvm *mvm)
{
struct ieee80211_sta *sta;
@@ -117,85 +113,17 @@
return count;
}
-static void iwl_mvm_tdls_config(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
- struct iwl_rx_packet *pkt;
- struct iwl_tdls_config_res *resp;
- struct iwl_tdls_config_cmd tdls_cfg_cmd = {};
- struct iwl_host_cmd cmd = {
- .id = TDLS_CONFIG_CMD,
- .flags = CMD_WANT_SKB,
- .data = { &tdls_cfg_cmd, },
- .len = { sizeof(struct iwl_tdls_config_cmd), },
- };
- struct ieee80211_sta *sta;
- int ret, i, cnt;
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- lockdep_assert_held(&mvm->mutex);
-
- tdls_cfg_cmd.id_and_color =
- cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
- tdls_cfg_cmd.tx_to_ap_tid = IWL_MVM_TDLS_FW_TID;
- tdls_cfg_cmd.tx_to_ap_ssn = cpu_to_le16(0); /* not used for now */
-
- /* for now the Tx cmd is empty and unused */
-
- /* populate TDLS peer data */
- cnt = 0;
- for (i = 0; i < IWL_MVM_STATION_COUNT; i++) {
- sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[i],
- lockdep_is_held(&mvm->mutex));
- if (IS_ERR_OR_NULL(sta) || !sta->tdls)
- continue;
-
- tdls_cfg_cmd.sta_info[cnt].sta_id = i;
- tdls_cfg_cmd.sta_info[cnt].tx_to_peer_tid =
- IWL_MVM_TDLS_FW_TID;
- tdls_cfg_cmd.sta_info[cnt].tx_to_peer_ssn = cpu_to_le16(0);
- tdls_cfg_cmd.sta_info[cnt].is_initiator =
- cpu_to_le32(sta->tdls_initiator ? 1 : 0);
-
- cnt++;
- }
-
- tdls_cfg_cmd.tdls_peer_count = cnt;
- IWL_DEBUG_TDLS(mvm, "send TDLS config to FW for %d peers\n", cnt);
-
- ret = iwl_mvm_send_cmd(mvm, &cmd);
- if (WARN_ON_ONCE(ret))
- return;
-
- pkt = cmd.resp_pkt;
- if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- IWL_ERR(mvm, "Bad return from TDLS_CONFIG_COMMAND (0x%08X)\n",
- pkt->hdr.flags);
- goto exit;
- }
-
- if (WARN_ON_ONCE(iwl_rx_packet_payload_len(pkt) != sizeof(*resp)))
- goto exit;
-
- /* we don't really care about the response at this point */
-
-exit:
- iwl_free_resp(&cmd);
-}
-
void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool sta_added)
{
int tdls_sta_cnt = iwl_mvm_tdls_sta_count(mvm, vif);
- /* when the first peer joins, send a power update first */
- if (tdls_sta_cnt == 1 && sta_added)
- iwl_mvm_power_update_mac(mvm);
-
- /* configure the FW with TDLS peer info */
- iwl_mvm_tdls_config(mvm, vif);
-
- /* when the last peer leaves, send a power update last */
- if (tdls_sta_cnt == 0 && !sta_added)
+ /*
+ * Disable ps when the first TDLS sta is added and re-enable it
+ * when the last TDLS sta is removed
+ */
+ if ((tdls_sta_cnt == 1 && sta_added) ||
+ (tdls_sta_cnt == 0 && !sta_added))
iwl_mvm_power_update_mac(mvm);
}
@@ -219,488 +147,3 @@
iwl_mvm_unref(mvm, IWL_MVM_REF_PROTECT_TDLS);
}
-
-static const char *
-iwl_mvm_tdls_cs_state_str(enum iwl_mvm_tdls_cs_state state)
-{
- switch (state) {
- case IWL_MVM_TDLS_SW_IDLE:
- return "IDLE";
- case IWL_MVM_TDLS_SW_REQ_SENT:
- return "REQ SENT";
- case IWL_MVM_TDLS_SW_REQ_RCVD:
- return "REQ RECEIVED";
- case IWL_MVM_TDLS_SW_ACTIVE:
- return "ACTIVE";
- }
-
- return NULL;
-}
-
-static void iwl_mvm_tdls_update_cs_state(struct iwl_mvm *mvm,
- enum iwl_mvm_tdls_cs_state state)
-{
- if (mvm->tdls_cs.state == state)
- return;
-
- IWL_DEBUG_TDLS(mvm, "TDLS channel switch state: %s -> %s\n",
- iwl_mvm_tdls_cs_state_str(mvm->tdls_cs.state),
- iwl_mvm_tdls_cs_state_str(state));
- mvm->tdls_cs.state = state;
-
- if (state == IWL_MVM_TDLS_SW_IDLE)
- mvm->tdls_cs.cur_sta_id = IWL_MVM_STATION_COUNT;
-}
-
-int iwl_mvm_rx_tdls_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- struct iwl_tdls_channel_switch_notif *notif = (void *)pkt->data;
- struct ieee80211_sta *sta;
- unsigned int delay;
- struct iwl_mvm_sta *mvmsta;
- struct ieee80211_vif *vif;
- u32 sta_id = le32_to_cpu(notif->sta_id);
-
- lockdep_assert_held(&mvm->mutex);
-
- /* can fail sometimes */
- if (!le32_to_cpu(notif->status)) {
- iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
- goto out;
- }
-
- if (WARN_ON(sta_id >= IWL_MVM_STATION_COUNT))
- goto out;
-
- sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
- lockdep_is_held(&mvm->mutex));
- /* the station may not be here, but if it is, it must be a TDLS peer */
- if (IS_ERR_OR_NULL(sta) || WARN_ON(!sta->tdls))
- goto out;
-
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
- vif = mvmsta->vif;
-
- /*
- * Update state and possibly switch again after this is over (DTIM).
- * Also convert TU to msec.
- */
- delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);
- mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
- msecs_to_jiffies(delay));
-
- iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_ACTIVE);
-
-out:
- return 0;
-}
-
-static int
-iwl_mvm_tdls_check_action(struct iwl_mvm *mvm,
- enum iwl_tdls_channel_switch_type type,
- const u8 *peer, bool peer_initiator)
-{
- bool same_peer = false;
- int ret = 0;
-
- /* get the existing peer if it's there */
- if (mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE &&
- mvm->tdls_cs.cur_sta_id != IWL_MVM_STATION_COUNT) {
- struct ieee80211_sta *sta = rcu_dereference_protected(
- mvm->fw_id_to_mac_id[mvm->tdls_cs.cur_sta_id],
- lockdep_is_held(&mvm->mutex));
- if (!IS_ERR_OR_NULL(sta))
- same_peer = ether_addr_equal(peer, sta->addr);
- }
-
- switch (mvm->tdls_cs.state) {
- case IWL_MVM_TDLS_SW_IDLE:
- /*
- * might be spurious packet from the peer after the switch is
- * already done
- */
- if (type == TDLS_MOVE_CH)
- ret = -EINVAL;
- break;
- case IWL_MVM_TDLS_SW_REQ_SENT:
- /*
- * We received a ch-switch request while an outgoing one is
- * pending. Allow it to proceed if the other peer is the same
- * one we sent to, and we are not the link initiator.
- */
- if (type == TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH) {
- if (!same_peer)
- ret = -EBUSY;
- else if (!peer_initiator) /* we are the initiator */
- ret = -EBUSY;
- }
- break;
- case IWL_MVM_TDLS_SW_REQ_RCVD:
- /* as above, allow the link initiator to proceed */
- if (type == TDLS_SEND_CHAN_SW_REQ) {
- if (!same_peer)
- ret = -EBUSY;
- else if (peer_initiator) /* they are the initiator */
- ret = -EBUSY;
- } else if (type == TDLS_MOVE_CH) {
- ret = -EINVAL;
- }
- break;
- case IWL_MVM_TDLS_SW_ACTIVE:
- /* we don't allow initiations during active channel switch */
- if (type == TDLS_SEND_CHAN_SW_REQ)
- ret = -EINVAL;
- break;
- }
-
- if (ret)
- IWL_DEBUG_TDLS(mvm,
- "Invalid TDLS action %d state %d peer %pM same_peer %d initiator %d\n",
- type, mvm->tdls_cs.state, peer, same_peer,
- peer_initiator);
-
- return ret;
-}
-
-static int
-iwl_mvm_tdls_config_channel_switch(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- enum iwl_tdls_channel_switch_type type,
- const u8 *peer, bool peer_initiator,
- u8 oper_class,
- struct cfg80211_chan_def *chandef,
- u32 timestamp, u16 switch_time,
- u16 switch_timeout, struct sk_buff *skb,
- u32 ch_sw_tm_ie)
-{
- struct ieee80211_sta *sta;
- struct iwl_mvm_sta *mvmsta;
- struct ieee80211_tx_info *info;
- struct ieee80211_hdr *hdr;
- struct iwl_tdls_channel_switch_cmd cmd = {0};
- int ret;
-
- lockdep_assert_held(&mvm->mutex);
-
- ret = iwl_mvm_tdls_check_action(mvm, type, peer, peer_initiator);
- if (ret)
- return ret;
-
- if (!skb || WARN_ON(skb->len > IWL_TDLS_CH_SW_FRAME_MAX_SIZE)) {
- ret = -EINVAL;
- goto out;
- }
-
- cmd.switch_type = type;
- cmd.timing.frame_timestamp = cpu_to_le32(timestamp);
- cmd.timing.switch_time = cpu_to_le32(switch_time);
- cmd.timing.switch_timeout = cpu_to_le32(switch_timeout);
-
- rcu_read_lock();
- sta = ieee80211_find_sta(vif, peer);
- if (!sta) {
- rcu_read_unlock();
- ret = -ENOENT;
- goto out;
- }
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
- cmd.peer_sta_id = cpu_to_le32(mvmsta->sta_id);
-
- if (!chandef) {
- if (mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
- mvm->tdls_cs.peer.chandef.chan) {
- /* actually moving to the channel */
- chandef = &mvm->tdls_cs.peer.chandef;
- } else if (mvm->tdls_cs.state == IWL_MVM_TDLS_SW_ACTIVE &&
- type == TDLS_MOVE_CH) {
- /* we need to return to base channel */
- struct ieee80211_chanctx_conf *chanctx =
- rcu_dereference(vif->chanctx_conf);
-
- if (WARN_ON_ONCE(!chanctx)) {
- rcu_read_unlock();
- goto out;
- }
-
- chandef = &chanctx->def;
- }
- }
-
- if (chandef) {
- cmd.ci.band = (chandef->chan->band == IEEE80211_BAND_2GHZ ?
- PHY_BAND_24 : PHY_BAND_5);
- cmd.ci.channel = chandef->chan->hw_value;
- cmd.ci.width = iwl_mvm_get_channel_width(chandef);
- cmd.ci.ctrl_pos = iwl_mvm_get_ctrl_pos(chandef);
- }
-
- /* keep quota calculation simple for now - 50% of DTIM for TDLS */
- cmd.timing.max_offchan_duration =
- cpu_to_le32(TU_TO_US(vif->bss_conf.dtim_period *
- vif->bss_conf.beacon_int) / 2);
-
- /* Switch time is the first element in the switch-timing IE. */
- cmd.frame.switch_time_offset = cpu_to_le32(ch_sw_tm_ie + 2);
-
- info = IEEE80211_SKB_CB(skb);
- if (info->control.hw_key)
- iwl_mvm_set_tx_cmd_crypto(mvm, info, &cmd.frame.tx_cmd, skb);
-
- iwl_mvm_set_tx_cmd(mvm, skb, &cmd.frame.tx_cmd, info,
- mvmsta->sta_id);
-
- hdr = (void *)skb->data;
- iwl_mvm_set_tx_cmd_rate(mvm, &cmd.frame.tx_cmd, info, sta,
- hdr->frame_control);
- rcu_read_unlock();
-
- memcpy(cmd.frame.data, skb->data, skb->len);
-
- ret = iwl_mvm_send_cmd_pdu(mvm, TDLS_CHANNEL_SWITCH_CMD, 0,
- sizeof(cmd), &cmd);
- if (ret) {
- IWL_ERR(mvm, "Failed to send TDLS_CHANNEL_SWITCH cmd: %d\n",
- ret);
- goto out;
- }
-
- /* channel switch has started, update state */
- if (type != TDLS_MOVE_CH) {
- mvm->tdls_cs.cur_sta_id = mvmsta->sta_id;
- iwl_mvm_tdls_update_cs_state(mvm,
- type == TDLS_SEND_CHAN_SW_REQ ?
- IWL_MVM_TDLS_SW_REQ_SENT :
- IWL_MVM_TDLS_SW_REQ_RCVD);
- }
-
-out:
-
- /* channel switch failed - we are idle */
- if (ret)
- iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
-
- return ret;
-}
-
-void iwl_mvm_tdls_ch_switch_work(struct work_struct *work)
-{
- struct iwl_mvm *mvm;
- struct ieee80211_sta *sta;
- struct iwl_mvm_sta *mvmsta;
- struct ieee80211_vif *vif;
- unsigned int delay;
- int ret;
-
- mvm = container_of(work, struct iwl_mvm, tdls_cs.dwork.work);
- mutex_lock(&mvm->mutex);
-
- /* called after an active channel switch has finished or timed-out */
- iwl_mvm_tdls_update_cs_state(mvm, IWL_MVM_TDLS_SW_IDLE);
-
- /* station might be gone, in that case do nothing */
- if (mvm->tdls_cs.peer.sta_id == IWL_MVM_STATION_COUNT)
- goto out;
-
- sta = rcu_dereference_protected(
- mvm->fw_id_to_mac_id[mvm->tdls_cs.peer.sta_id],
- lockdep_is_held(&mvm->mutex));
- /* the station may not be here, but if it is, it must be a TDLS peer */
- if (!sta || IS_ERR(sta) || WARN_ON(!sta->tdls))
- goto out;
-
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
- vif = mvmsta->vif;
- ret = iwl_mvm_tdls_config_channel_switch(mvm, vif,
- TDLS_SEND_CHAN_SW_REQ,
- sta->addr,
- mvm->tdls_cs.peer.initiator,
- mvm->tdls_cs.peer.op_class,
- &mvm->tdls_cs.peer.chandef,
- 0, 0, 0,
- mvm->tdls_cs.peer.skb,
- mvm->tdls_cs.peer.ch_sw_tm_ie);
- if (ret)
- IWL_ERR(mvm, "Not sending TDLS channel switch: %d\n", ret);
-
- /* retry after a DTIM if we failed sending now */
- delay = TU_TO_MS(vif->bss_conf.dtim_period * vif->bss_conf.beacon_int);
- queue_delayed_work(system_wq, &mvm->tdls_cs.dwork,
- msecs_to_jiffies(delay));
-out:
- mutex_unlock(&mvm->mutex);
-}
-
-int
-iwl_mvm_tdls_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u8 oper_class,
- struct cfg80211_chan_def *chandef,
- struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct iwl_mvm_sta *mvmsta;
- unsigned int delay;
- int ret;
-
- mutex_lock(&mvm->mutex);
-
- IWL_DEBUG_TDLS(mvm, "TDLS channel switch with %pM ch %d width %d\n",
- sta->addr, chandef->chan->center_freq, chandef->width);
-
- /* we only support a single peer for channel switching */
- if (mvm->tdls_cs.peer.sta_id != IWL_MVM_STATION_COUNT) {
- IWL_DEBUG_TDLS(mvm,
- "Existing peer. Can't start switch with %pM\n",
- sta->addr);
- ret = -EBUSY;
- goto out;
- }
-
- ret = iwl_mvm_tdls_config_channel_switch(mvm, vif,
- TDLS_SEND_CHAN_SW_REQ,
- sta->addr, sta->tdls_initiator,
- oper_class, chandef, 0, 0, 0,
- tmpl_skb, ch_sw_tm_ie);
- if (ret)
- goto out;
-
- /*
- * Mark the peer as "in tdls switch" for this vif. We only allow a
- * single such peer per vif.
- */
- mvm->tdls_cs.peer.skb = skb_copy(tmpl_skb, GFP_KERNEL);
- if (!mvm->tdls_cs.peer.skb) {
- ret = -ENOMEM;
- goto out;
- }
-
- mvmsta = iwl_mvm_sta_from_mac80211(sta);
- mvm->tdls_cs.peer.sta_id = mvmsta->sta_id;
- mvm->tdls_cs.peer.chandef = *chandef;
- mvm->tdls_cs.peer.initiator = sta->tdls_initiator;
- mvm->tdls_cs.peer.op_class = oper_class;
- mvm->tdls_cs.peer.ch_sw_tm_ie = ch_sw_tm_ie;
-
- /*
- * Wait for 2 DTIM periods before attempting the next switch. The next
- * switch will be made sooner if the current one completes before that.
- */
- delay = 2 * TU_TO_MS(vif->bss_conf.dtim_period *
- vif->bss_conf.beacon_int);
- mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
- msecs_to_jiffies(delay));
-
-out:
- mutex_unlock(&mvm->mutex);
- return ret;
-}
-
-void iwl_mvm_tdls_cancel_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- struct ieee80211_sta *cur_sta;
- bool wait_for_phy = false;
-
- mutex_lock(&mvm->mutex);
-
- IWL_DEBUG_TDLS(mvm, "TDLS cancel channel switch with %pM\n", sta->addr);
-
- /* we only support a single peer for channel switching */
- if (mvm->tdls_cs.peer.sta_id == IWL_MVM_STATION_COUNT) {
- IWL_DEBUG_TDLS(mvm, "No ch switch peer - %pM\n", sta->addr);
- goto out;
- }
-
- cur_sta = rcu_dereference_protected(
- mvm->fw_id_to_mac_id[mvm->tdls_cs.peer.sta_id],
- lockdep_is_held(&mvm->mutex));
- /* make sure it's the same peer */
- if (cur_sta != sta)
- goto out;
-
- /*
- * If we're currently in a switch because of the now canceled peer,
- * wait a DTIM here to make sure the phy is back on the base channel.
- * We can't otherwise force it.
- */
- if (mvm->tdls_cs.cur_sta_id == mvm->tdls_cs.peer.sta_id &&
- mvm->tdls_cs.state != IWL_MVM_TDLS_SW_IDLE)
- wait_for_phy = true;
-
- mvm->tdls_cs.peer.sta_id = IWL_MVM_STATION_COUNT;
- dev_kfree_skb(mvm->tdls_cs.peer.skb);
- mvm->tdls_cs.peer.skb = NULL;
-
-out:
- mutex_unlock(&mvm->mutex);
-
- /* make sure the phy is on the base channel */
- if (wait_for_phy)
- msleep(TU_TO_MS(vif->bss_conf.dtim_period *
- vif->bss_conf.beacon_int));
-
- /* flush the channel switch state */
- flush_delayed_work(&mvm->tdls_cs.dwork);
-
- IWL_DEBUG_TDLS(mvm, "TDLS ending channel switch with %pM\n", sta->addr);
-}
-
-void
-iwl_mvm_tdls_recv_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_tdls_ch_sw_params *params)
-{
- struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
- enum iwl_tdls_channel_switch_type type;
- unsigned int delay;
-
- mutex_lock(&mvm->mutex);
-
- IWL_DEBUG_TDLS(mvm,
- "Received TDLS ch switch action %d from %pM status %d\n",
- params->action_code, params->sta->addr, params->status);
-
- /*
- * we got a non-zero status from a peer we were switching to - move to
- * the idle state and retry again later
- */
- if (params->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE &&
- params->status != 0 &&
- mvm->tdls_cs.state == IWL_MVM_TDLS_SW_REQ_SENT &&
- mvm->tdls_cs.cur_sta_id != IWL_MVM_STATION_COUNT) {
- struct ieee80211_sta *cur_sta;
-
- /* make sure it's the same peer */
- cur_sta = rcu_dereference_protected(
- mvm->fw_id_to_mac_id[mvm->tdls_cs.cur_sta_id],
- lockdep_is_held(&mvm->mutex));
- if (cur_sta == params->sta) {
- iwl_mvm_tdls_update_cs_state(mvm,
- IWL_MVM_TDLS_SW_IDLE);
- goto retry;
- }
- }
-
- type = (params->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST) ?
- TDLS_SEND_CHAN_SW_RESP_AND_MOVE_CH : TDLS_MOVE_CH;
-
- iwl_mvm_tdls_config_channel_switch(mvm, vif, type, params->sta->addr,
- params->sta->tdls_initiator, 0,
- params->chandef, params->timestamp,
- params->switch_time,
- params->switch_timeout,
- params->tmpl_skb,
- params->ch_sw_tm_ie);
-
-retry:
- /* register a timeout in case we don't succeed in switching */
- delay = vif->bss_conf.dtim_period * vif->bss_conf.beacon_int *
- 1024 / 1000;
- mod_delayed_work(system_wq, &mvm->tdls_cs.dwork,
- msecs_to_jiffies(delay));
- mutex_unlock(&mvm->mutex);
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index 54fafbf..b7f9e61 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -191,35 +191,6 @@
return true;
}
-static void
-iwl_mvm_te_handle_notify_csa(struct iwl_mvm *mvm,
- struct iwl_mvm_time_event_data *te_data,
- struct iwl_time_event_notif *notif)
-{
- if (!le32_to_cpu(notif->status)) {
- IWL_DEBUG_TE(mvm, "CSA time event failed to start\n");
- iwl_mvm_te_clear_data(mvm, te_data);
- return;
- }
-
- switch (te_data->vif->type) {
- case NL80211_IFTYPE_AP:
- iwl_mvm_csa_noa_start(mvm);
- break;
- case NL80211_IFTYPE_STATION:
- iwl_mvm_csa_client_absent(mvm, te_data->vif);
- ieee80211_chswitch_done(te_data->vif, true);
- break;
- default:
- /* should never happen */
- WARN_ON_ONCE(1);
- break;
- }
-
- /* we don't need it anymore */
- iwl_mvm_te_clear_data(mvm, te_data);
-}
-
/*
* Handles a FW notification for an event that is known to the driver.
*
@@ -281,8 +252,14 @@
set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
iwl_mvm_ref(mvm, IWL_MVM_REF_ROC);
ieee80211_ready_on_channel(mvm->hw);
- } else if (te_data->id == TE_CHANNEL_SWITCH_PERIOD) {
- iwl_mvm_te_handle_notify_csa(mvm, te_data, notif);
+ } else if (te_data->vif->type == NL80211_IFTYPE_AP) {
+ if (le32_to_cpu(notif->status))
+ iwl_mvm_csa_noa_start(mvm);
+ else
+ IWL_DEBUG_TE(mvm, "CSA NOA failed to start\n");
+
+ /* we don't need it anymore */
+ iwl_mvm_te_clear_data(mvm, te_data);
}
} else {
IWL_WARN(mvm, "Got TE with unknown action\n");
@@ -328,8 +305,8 @@
te_data->running = false;
te_data->vif = NULL;
te_data->uid = 0;
- te_data->id = TE_MAX;
} else if (le32_to_cpu(notif->action) == TE_V2_NOTIF_HOST_EVENT_START) {
+ set_bit(IWL_MVM_STATUS_ROC_RUNNING, &mvm->status);
set_bit(IWL_MVM_STATUS_ROC_AUX_RUNNING, &mvm->status);
te_data->running = true;
ieee80211_ready_on_channel(mvm->hw); /* Start TE */
@@ -572,11 +549,18 @@
}
}
-static bool __iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
- struct iwl_mvm_time_event_data *te_data,
- u32 *uid)
+/*
+ * Explicit request to remove a time event. The removal of a time event needs to
+ * be synchronized with the flow of a time event's end notification, which also
+ * removes the time event from the op mode data structures.
+ */
+void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
+ struct iwl_mvm_vif *mvmvif,
+ struct iwl_mvm_time_event_data *te_data)
{
- u32 id;
+ struct iwl_time_event_cmd time_cmd = {};
+ u32 id, uid;
+ int ret;
/*
* It is possible that by the time we got to this point the time
@@ -585,7 +569,7 @@
spin_lock_bh(&mvm->time_event_lock);
/* Save time event uid before clearing its data */
- *uid = te_data->uid;
+ uid = te_data->uid;
id = te_data->id;
/*
@@ -600,59 +584,10 @@
* send a removal command.
*/
if (id == TE_MAX) {
- IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", *uid);
- return false;
+ IWL_DEBUG_TE(mvm, "TE 0x%x has already ended\n", uid);
+ return;
}
- return true;
-}
-
-/*
- * Explicit request to remove a aux roc time event. The removal of a time
- * event needs to be synchronized with the flow of a time event's end
- * notification, which also removes the time event from the op mode
- * data structures.
- */
-static void iwl_mvm_remove_aux_roc_te(struct iwl_mvm *mvm,
- struct iwl_mvm_vif *mvmvif,
- struct iwl_mvm_time_event_data *te_data)
-{
- struct iwl_hs20_roc_req aux_cmd = {};
- u32 uid;
- int ret;
-
- if (!__iwl_mvm_remove_time_event(mvm, te_data, &uid))
- return;
-
- aux_cmd.event_unique_id = cpu_to_le32(uid);
- aux_cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
- aux_cmd.id_and_color =
- cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
- IWL_DEBUG_TE(mvm, "Removing BSS AUX ROC TE 0x%x\n",
- le32_to_cpu(aux_cmd.event_unique_id));
- ret = iwl_mvm_send_cmd_pdu(mvm, HOT_SPOT_CMD, 0,
- sizeof(aux_cmd), &aux_cmd);
-
- if (WARN_ON(ret))
- return;
-}
-
-/*
- * Explicit request to remove a time event. The removal of a time event needs to
- * be synchronized with the flow of a time event's end notification, which also
- * removes the time event from the op mode data structures.
- */
-void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
- struct iwl_mvm_vif *mvmvif,
- struct iwl_mvm_time_event_data *te_data)
-{
- struct iwl_time_event_cmd time_cmd = {};
- u32 uid;
- int ret;
-
- if (!__iwl_mvm_remove_time_event(mvm, te_data, &uid))
- return;
-
/* When we remove a TE, the UID is to be set in the id field */
time_cmd.id = cpu_to_le32(uid);
time_cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
@@ -731,17 +666,13 @@
return iwl_mvm_time_event_send_add(mvm, vif, te_data, &time_cmd);
}
-void iwl_mvm_stop_roc(struct iwl_mvm *mvm)
+void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm)
{
struct iwl_mvm_vif *mvmvif;
struct iwl_mvm_time_event_data *te_data;
- bool is_p2p = false;
lockdep_assert_held(&mvm->mutex);
- mvmvif = NULL;
- spin_lock_bh(&mvm->time_event_lock);
-
/*
* Iterate over the list of time events and find the time event that is
* associated with a P2P_DEVICE interface.
@@ -749,41 +680,22 @@
* event at any given time and this time event coresponds to a ROC
* request
*/
+ mvmvif = NULL;
+ spin_lock_bh(&mvm->time_event_lock);
list_for_each_entry(te_data, &mvm->time_event_list, list) {
- if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE &&
- te_data->running) {
+ if (te_data->vif->type == NL80211_IFTYPE_P2P_DEVICE) {
mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
- is_p2p = true;
- goto remove_te;
+ break;
}
}
-
- /*
- * Iterate over the list of aux roc time events and find the time
- * event that is associated with a BSS interface.
- * This assumes that a BSS interface can have only a single time
- * event at any given time and this time event coresponds to a ROC
- * request
- */
- list_for_each_entry(te_data, &mvm->aux_roc_te_list, list) {
- if (te_data->running) {
- mvmvif = iwl_mvm_vif_from_mac80211(te_data->vif);
- goto remove_te;
- }
- }
-
-remove_te:
spin_unlock_bh(&mvm->time_event_lock);
if (!mvmvif) {
- IWL_WARN(mvm, "No remain on channel event\n");
+ IWL_WARN(mvm, "P2P_DEVICE no remain on channel event\n");
return;
}
- if (is_p2p)
- iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
- else
- iwl_mvm_remove_aux_roc_te(mvm, mvmvif, te_data);
+ iwl_mvm_remove_time_event(mvm, mvmvif, te_data);
iwl_mvm_roc_finished(mvm);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.h b/drivers/net/wireless/iwlwifi/mvm/time-event.h
index 6f6b35d..b350e47 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.h
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.h
@@ -182,14 +182,14 @@
int duration, enum ieee80211_roc_type type);
/**
- * iwl_mvm_stop_roc - stop remain on channel functionality
+ * iwl_mvm_stop_p2p_roc - stop remain on channel for p2p device functionlity
* @mvm: the mvm component
*
* This function can be used to cancel an ongoing ROC session.
* The function is async, it will instruct the FW to stop serving the ROC
* session, but will not wait for the actual stopping of the session.
*/
-void iwl_mvm_stop_roc(struct iwl_mvm *mvm);
+void iwl_mvm_stop_p2p_roc(struct iwl_mvm *mvm);
/**
* iwl_mvm_remove_time_event - general function to clean up of time event
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index 2b1e61f..acca44a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -64,6 +64,10 @@
*****************************************************************************/
#include "mvm.h"
+#include "iwl-config.h"
+#include "iwl-io.h"
+#include "iwl-csr.h"
+#include "iwl-prph.h"
#define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ
@@ -95,81 +99,32 @@
iwl_mvm_set_hw_ctkill_state(mvm, false);
}
-void iwl_mvm_tt_temp_changed(struct iwl_mvm *mvm, u32 temp)
-{
- /* ignore the notification if we are in test mode */
- if (mvm->temperature_test)
- return;
-
- if (mvm->temperature == temp)
- return;
-
- mvm->temperature = temp;
- iwl_mvm_tt_handler(mvm);
-}
-
-static int iwl_mvm_temp_notif_parse(struct iwl_mvm *mvm,
- struct iwl_rx_packet *pkt)
-{
- struct iwl_dts_measurement_notif *notif;
- int len = iwl_rx_packet_payload_len(pkt);
- int temp;
-
- if (WARN_ON_ONCE(len != sizeof(*notif))) {
- IWL_ERR(mvm, "Invalid DTS_MEASUREMENT_NOTIFICATION\n");
- return -EINVAL;
- }
-
- notif = (void *)pkt->data;
-
- temp = le32_to_cpu(notif->temp);
-
- /* shouldn't be negative, but since it's s32, make sure it isn't */
- if (WARN_ON_ONCE(temp < 0))
- temp = 0;
-
- IWL_DEBUG_TEMP(mvm, "DTS_MEASUREMENT_NOTIFICATION - %d\n", temp);
-
- return temp;
-}
-
-static bool iwl_mvm_temp_notif_wait(struct iwl_notif_wait_data *notif_wait,
- struct iwl_rx_packet *pkt, void *data)
+static bool iwl_mvm_temp_notif(struct iwl_notif_wait_data *notif_wait,
+ struct iwl_rx_packet *pkt, void *data)
{
struct iwl_mvm *mvm =
container_of(notif_wait, struct iwl_mvm, notif_wait);
int *temp = data;
- int ret;
+ struct iwl_dts_measurement_notif *notif;
+ int len = iwl_rx_packet_payload_len(pkt);
- ret = iwl_mvm_temp_notif_parse(mvm, pkt);
- if (ret < 0)
+ if (WARN_ON_ONCE(len != sizeof(*notif))) {
+ IWL_ERR(mvm, "Invalid DTS_MEASUREMENT_NOTIFICATION\n");
return true;
+ }
- *temp = ret;
+ notif = (void *)pkt->data;
+ *temp = le32_to_cpu(notif->temp);
+
+ /* shouldn't be negative, but since it's s32, make sure it isn't */
+ if (WARN_ON_ONCE(*temp < 0))
+ *temp = 0;
+
+ IWL_DEBUG_TEMP(mvm, "DTS_MEASUREMENT_NOTIFICATION - %d\n", *temp);
return true;
}
-int iwl_mvm_temp_notif(struct iwl_mvm *mvm,
- struct iwl_rx_cmd_buffer *rxb,
- struct iwl_device_cmd *cmd)
-{
- struct iwl_rx_packet *pkt = rxb_addr(rxb);
- int temp;
-
- /* the notification is handled synchronously in ctkill, so skip here */
- if (test_bit(IWL_MVM_STATUS_HW_CTKILL, &mvm->status))
- return 0;
-
- temp = iwl_mvm_temp_notif_parse(mvm, pkt);
- if (temp < 0)
- return 0;
-
- iwl_mvm_tt_temp_changed(mvm, temp);
-
- return 0;
-}
-
static int iwl_mvm_get_temp_cmd(struct iwl_mvm *mvm)
{
struct iwl_dts_measurement_cmd cmd = {
@@ -190,7 +145,7 @@
iwl_init_notification_wait(&mvm->notif_wait, &wait_temp_notif,
temp_notif, ARRAY_SIZE(temp_notif),
- iwl_mvm_temp_notif_wait, &temp);
+ iwl_mvm_temp_notif, &temp);
ret = iwl_mvm_get_temp_cmd(mvm);
if (ret) {
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index 178bdce..9877937 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -73,9 +73,9 @@
/*
* Sets most of the Tx cmd's fields
*/
-void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
- struct iwl_tx_cmd *tx_cmd,
- struct ieee80211_tx_info *info, u8 sta_id)
+static void iwl_mvm_set_tx_cmd(struct iwl_mvm *mvm, struct sk_buff *skb,
+ struct iwl_tx_cmd *tx_cmd,
+ struct ieee80211_tx_info *info, u8 sta_id)
{
struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control;
@@ -149,9 +149,11 @@
/*
* Sets the fields in the Tx cmd that are rate related
*/
-void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, struct iwl_tx_cmd *tx_cmd,
- struct ieee80211_tx_info *info,
- struct ieee80211_sta *sta, __le16 fc)
+static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm,
+ struct iwl_tx_cmd *tx_cmd,
+ struct ieee80211_tx_info *info,
+ struct ieee80211_sta *sta,
+ __le16 fc)
{
u32 rate_flags;
int rate_idx;
@@ -173,10 +175,14 @@
/*
* for data packets, rate info comes from the table inside the fw. This
- * table is controlled by LINK_QUALITY commands
+ * table is controlled by LINK_QUALITY commands. Exclude ctrl port
+ * frames like EAPOLs which should be treated as mgmt frames. This
+ * avoids them being sent initially in high rates which increases the
+ * chances for completion of the 4-Way handshake.
*/
- if (ieee80211_is_data(fc) && sta) {
+ if (ieee80211_is_data(fc) && sta &&
+ !(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) {
tx_cmd->initial_rate_index = 0;
tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE);
return;
@@ -187,10 +193,8 @@
/* HT rate doesn't make sense for a non data frame */
WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS,
- "Got an HT rate (flags:0x%x/mcs:%d) for a non data frame (fc:0x%x)\n",
- info->control.rates[0].flags,
- info->control.rates[0].idx,
- le16_to_cpu(fc));
+ "Got an HT rate for a non data frame 0x%x\n",
+ info->control.rates[0].flags);
rate_idx = info->control.rates[0].idx;
/* if the rate isn't a well known legacy rate, take the lowest one */
@@ -230,10 +234,10 @@
/*
* Sets the fields in the Tx cmd that are crypto related
*/
-void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
- struct ieee80211_tx_info *info,
- struct iwl_tx_cmd *tx_cmd,
- struct sk_buff *skb_frag)
+static void iwl_mvm_set_tx_cmd_crypto(struct iwl_mvm *mvm,
+ struct ieee80211_tx_info *info,
+ struct iwl_tx_cmd *tx_cmd,
+ struct sk_buff *skb_frag)
{
struct ieee80211_key_conf *keyconf = info->control.hw_key;
@@ -424,13 +428,6 @@
WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM);
- if (sta->tdls) {
- /* default to TID 0 for non-QoS packets */
- u8 tdls_tid = tid == IWL_MAX_TID_COUNT ? 0 : tid;
-
- txq_id = mvmsta->hw_queue[tid_to_mac80211_ac[tdls_tid]];
- }
-
if (is_ampdu) {
if (WARN_ON_ONCE(mvmsta->tid_data[tid].state != IWL_AGG_ON))
goto drop_unlock_sta;
@@ -665,12 +662,6 @@
seq_ctl = le16_to_cpu(hdr->seq_ctrl);
}
- /*
- * TODO: this is not accurate if we are freeing more than one
- * packet.
- */
- info->status.tx_time =
- le16_to_cpu(tx_resp->wireless_media_time);
BUILD_BUG_ON(ARRAY_SIZE(info->status.status_driver_data) < 1);
info->status.status_driver_data[0] =
(void *)(uintptr_t)tx_resp->reduced_tpc;
@@ -863,8 +854,6 @@
mvmsta->tid_data[tid].rate_n_flags =
le32_to_cpu(tx_resp->initial_rate);
mvmsta->tid_data[tid].reduced_tpc = tx_resp->reduced_tpc;
- mvmsta->tid_data[tid].tx_time =
- le16_to_cpu(tx_resp->wireless_media_time);
}
rcu_read_unlock();
@@ -893,8 +882,6 @@
info->status.ampdu_len = ba_notif->txed;
iwl_mvm_hwrate_to_tx_status(tid_data->rate_n_flags,
info);
- /* TODO: not accounted if the whole A-MPDU failed */
- info->status.tx_time = tid_data->tx_time;
info->status.status_driver_data[0] =
(void *)(uintptr_t)tid_data->reduced_tpc;
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index 8497660..ee6e5f9 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -734,40 +734,3 @@
return idle;
}
-
-struct iwl_bss_iter_data {
- struct ieee80211_vif *vif;
- bool error;
-};
-
-static void iwl_mvm_bss_iface_iterator(void *_data, u8 *mac,
- struct ieee80211_vif *vif)
-{
- struct iwl_bss_iter_data *data = _data;
-
- if (vif->type != NL80211_IFTYPE_STATION || vif->p2p)
- return;
-
- if (data->vif) {
- data->error = true;
- return;
- }
-
- data->vif = vif;
-}
-
-struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm)
-{
- struct iwl_bss_iter_data bss_iter_data = {};
-
- ieee80211_iterate_active_interfaces_atomic(
- mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
- iwl_mvm_bss_iface_iterator, &bss_iter_data);
-
- if (bss_iter_data.error) {
- IWL_ERR(mvm, "More than one managed interface active!\n");
- return ERR_PTR(-EINVAL);
- }
-
- return bss_iter_data.vif;
-}
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 14d92d1..082d286 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -499,7 +499,6 @@
static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
const struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
- const struct iwl_cfg *cfg_7265d __maybe_unused = NULL;
struct iwl_trans *iwl_trans;
struct iwl_trans_pcie *trans_pcie;
int ret;
@@ -508,25 +507,6 @@
if (IS_ERR(iwl_trans))
return PTR_ERR(iwl_trans);
-#if IS_ENABLED(CPTCFG_IWLMVM)
- /*
- * special-case 7265D, it has the same PCI IDs.
- *
- * Note that because we already pass the cfg to the transport above,
- * all the parameters that the transport uses must, until that is
- * changed, be identical to the ones in the 7265D configuration.
- */
- if (cfg == &iwl7265_2ac_cfg)
- cfg_7265d = &iwl7265d_2ac_cfg;
- else if (cfg == &iwl7265_2n_cfg)
- cfg_7265d = &iwl7265d_2n_cfg;
- else if (cfg == &iwl7265_n_cfg)
- cfg_7265d = &iwl7265d_n_cfg;
- if (cfg_7265d &&
- (iwl_trans->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_7265D)
- cfg = cfg_7265d;
-#endif
-
pci_set_drvdata(pdev, iwl_trans);
trans_pcie = IWL_TRANS_GET_PCIE_TRANS(iwl_trans);
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index 93a9e59..9062249 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -78,11 +78,6 @@
#include "iwl-agn-hw.h"
#include "iwl-fw-error-dump.h"
#include "internal.h"
-#include "iwl-fh.h"
-
-/* extended range in FW SRAM */
-#define IWL_FW_MEM_EXTENDED_START 0x40000
-#define IWL_FW_MEM_EXTENDED_END 0x57FFF
static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
{
@@ -138,7 +133,7 @@
break;
}
- if (WARN_ON_ONCE(!page))
+ if (!page)
return;
trans_pcie->fw_mon_page = page;
@@ -179,7 +174,6 @@
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
u16 lctl;
- u16 cap;
/*
* HW bug W/A for instability in PCIe bus L0S->L1 transition.
@@ -190,17 +184,16 @@
* power savings, even without L1.
*/
pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_LNKCTL, &lctl);
- if (lctl & PCI_EXP_LNKCTL_ASPM_L1)
+ if (lctl & PCI_EXP_LNKCTL_ASPM_L1) {
+ /* L1-ASPM enabled; disable(!) L0S */
iwl_set_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
- else
+ dev_info(trans->dev, "L1 Enabled; Disabling L0S\n");
+ } else {
+ /* L1-ASPM disabled; enable(!) L0S */
iwl_clear_bit(trans, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED);
+ dev_info(trans->dev, "L1 Disabled; Enabling L0S\n");
+ }
trans->pm_support = !(lctl & PCI_EXP_LNKCTL_ASPM_L0S);
-
- pcie_capability_read_word(trans_pcie->pci_dev, PCI_EXP_DEVCTL2, &cap);
- trans->ltr_enabled = cap & PCI_EXP_DEVCTL2_LTR_EN;
- dev_info(trans->dev, "L1 %sabled - LTR %sabled\n",
- (lctl & PCI_EXP_LNKCTL_ASPM_L1) ? "En" : "Dis",
- trans->ltr_enabled ? "En" : "Dis");
}
/*
@@ -435,7 +428,7 @@
ret = iwl_poll_bit(trans, CSR_RESET,
CSR_RESET_REG_FLAG_MASTER_DISABLED,
CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
- if (ret < 0)
+ if (ret)
IWL_WARN(trans, "Master Disable Timed Out, 100 usec\n");
IWL_DEBUG_INFO(trans, "stop master\n");
@@ -517,9 +510,6 @@
CSR_HW_IF_CONFIG_REG_BIT_NIC_READY,
HW_READY_TIMEOUT);
- if (ret >= 0)
- iwl_set_bit(trans, CSR_MBOX_SET_REG, CSR_MBOX_SET_REG_OS_ALIVE);
-
IWL_DEBUG_INFO(trans, "hardware%s ready\n", ret < 0 ? " not" : "");
return ret;
}
@@ -554,7 +544,7 @@
msleep(25);
}
- IWL_ERR(trans, "Couldn't prepare the card\n");
+ IWL_DEBUG_INFO(trans, "got NIC after %d iterations\n", iter);
return ret;
}
@@ -632,28 +622,14 @@
}
for (offset = 0; offset < section->len; offset += chunk_sz) {
- u32 copy_size, dst_addr;
- bool extended_addr = false;
+ u32 copy_size;
copy_size = min_t(u32, chunk_sz, section->len - offset);
- dst_addr = section->offset + offset;
-
- if (dst_addr >= IWL_FW_MEM_EXTENDED_START &&
- dst_addr <= IWL_FW_MEM_EXTENDED_END)
- extended_addr = true;
-
- if (extended_addr)
- iwl_set_bits_prph(trans, LMPM_CHICK,
- LMPM_CHICK_EXTENDED_ADDR_SPACE);
memcpy(v_addr, (u8 *)section->data + offset, copy_size);
- ret = iwl_pcie_load_firmware_chunk(trans, dst_addr, p_addr,
- copy_size);
-
- if (extended_addr)
- iwl_clear_bits_prph(trans, LMPM_CHICK,
- LMPM_CHICK_EXTENDED_ADDR_SPACE);
-
+ ret = iwl_pcie_load_firmware_chunk(trans,
+ section->offset + offset,
+ p_addr, copy_size);
if (ret) {
IWL_ERR(trans,
"Could not load the [%d] uCode section\n",
@@ -666,14 +642,14 @@
return ret;
}
-static int iwl_pcie_load_cpu_sections_8000b(struct iwl_trans *trans,
- const struct fw_img *image,
- int cpu,
- int *first_ucode_section)
+static int iwl_pcie_load_cpu_secured_sections(struct iwl_trans *trans,
+ const struct fw_img *image,
+ int cpu,
+ int *first_ucode_section)
{
int shift_param;
- int i, ret = 0, sec_num = 0x1;
- u32 val, last_read_idx = 0;
+ int i, ret = 0;
+ u32 last_read_idx = 0;
if (cpu == 1) {
shift_param = 0;
@@ -694,16 +670,21 @@
break;
}
+ if (i == (*first_ucode_section) + 1)
+ /* set CPU to started */
+ iwl_set_bits_prph(trans,
+ CSR_UCODE_LOAD_STATUS_ADDR,
+ LMPM_CPU_HDRS_LOADING_COMPLETED
+ << shift_param);
+
ret = iwl_pcie_load_section(trans, i, &image->sec[i]);
if (ret)
return ret;
-
- /* Notify the ucode of the loaded section number and status */
- val = iwl_read_direct32(trans, FH_UCODE_LOAD_STATUS);
- val = val | (sec_num << shift_param);
- iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, val);
- sec_num = (sec_num << 1) | 0x1;
}
+ /* image loading complete */
+ iwl_set_bits_prph(trans,
+ CSR_UCODE_LOAD_STATUS_ADDR,
+ LMPM_CPU_UCODE_LOADING_COMPLETED << shift_param);
*first_ucode_section = last_read_idx;
@@ -756,64 +737,6 @@
return 0;
}
-static void iwl_pcie_apply_destination(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- const struct iwl_fw_dbg_dest_tlv *dest = trans->dbg_dest_tlv;
- int i;
-
- if (dest->version)
- IWL_ERR(trans,
- "DBG DEST version is %d - expect issues\n",
- dest->version);
-
- IWL_INFO(trans, "Applying debug destination %s\n",
- get_fw_dbg_mode_string(dest->monitor_mode));
-
- if (dest->monitor_mode == EXTERNAL_MODE)
- iwl_pcie_alloc_fw_monitor(trans);
- else
- IWL_WARN(trans, "PCI should have external buffer debug\n");
-
- for (i = 0; i < trans->dbg_dest_reg_num; i++) {
- u32 addr = le32_to_cpu(dest->reg_ops[i].addr);
- u32 val = le32_to_cpu(dest->reg_ops[i].val);
-
- switch (dest->reg_ops[i].op) {
- case CSR_ASSIGN:
- iwl_write32(trans, addr, val);
- break;
- case CSR_SETBIT:
- iwl_set_bit(trans, addr, BIT(val));
- break;
- case CSR_CLEARBIT:
- iwl_clear_bit(trans, addr, BIT(val));
- break;
- case PRPH_ASSIGN:
- iwl_write_prph(trans, addr, val);
- break;
- case PRPH_SETBIT:
- iwl_set_bits_prph(trans, addr, BIT(val));
- break;
- case PRPH_CLEARBIT:
- iwl_clear_bits_prph(trans, addr, BIT(val));
- break;
- default:
- IWL_ERR(trans, "FW debug - unknown OP %d\n",
- dest->reg_ops[i].op);
- break;
- }
- }
-
- if (dest->monitor_mode == EXTERNAL_MODE && trans_pcie->fw_mon_size) {
- iwl_write_prph(trans, le32_to_cpu(dest->base_reg),
- trans_pcie->fw_mon_phys >> dest->base_shift);
- iwl_write_prph(trans, le32_to_cpu(dest->end_reg),
- (trans_pcie->fw_mon_phys +
- trans_pcie->fw_mon_size) >> dest->end_shift);
- }
-}
-
static int iwl_pcie_load_given_ucode(struct iwl_trans *trans,
const struct fw_img *image)
{
@@ -821,13 +744,42 @@
int ret = 0;
int first_ucode_section;
- IWL_DEBUG_FW(trans, "working with %s CPU\n",
+ IWL_DEBUG_FW(trans,
+ "working with %s image\n",
+ image->is_secure ? "Secured" : "Non Secured");
+ IWL_DEBUG_FW(trans,
+ "working with %s CPU\n",
image->is_dual_cpus ? "Dual" : "Single");
- /* load to FW the binary non secured sections of CPU1 */
- ret = iwl_pcie_load_cpu_sections(trans, image, 1, &first_ucode_section);
- if (ret)
- return ret;
+ /* configure the ucode to be ready to get the secured image */
+ if (image->is_secure) {
+ /* set secure boot inspector addresses */
+ iwl_write_prph(trans,
+ LMPM_SECURE_INSPECTOR_CODE_ADDR,
+ LMPM_SECURE_INSPECTOR_CODE_MEM_SPACE);
+
+ iwl_write_prph(trans,
+ LMPM_SECURE_INSPECTOR_DATA_ADDR,
+ LMPM_SECURE_INSPECTOR_DATA_MEM_SPACE);
+
+ /* set CPU1 header address */
+ iwl_write_prph(trans,
+ LMPM_SECURE_UCODE_LOAD_CPU1_HDR_ADDR,
+ LMPM_SECURE_CPU1_HDR_MEM_SPACE);
+
+ /* load to FW the binary Secured sections of CPU1 */
+ ret = iwl_pcie_load_cpu_secured_sections(trans, image, 1,
+ &first_ucode_section);
+ if (ret)
+ return ret;
+
+ } else {
+ /* load to FW the binary Non secured sections of CPU1 */
+ ret = iwl_pcie_load_cpu_sections(trans, image, 1,
+ &first_ucode_section);
+ if (ret)
+ return ret;
+ }
if (image->is_dual_cpus) {
/* set CPU2 header address */
@@ -836,8 +788,13 @@
LMPM_SECURE_CPU2_HDR_MEM_SPACE);
/* load to FW the binary sections of CPU2 */
- ret = iwl_pcie_load_cpu_sections(trans, image, 2,
- &first_ucode_section);
+ if (image->is_secure)
+ ret = iwl_pcie_load_cpu_secured_sections(
+ trans, image, 2,
+ &first_ucode_section);
+ else
+ ret = iwl_pcie_load_cpu_sections(trans, image, 2,
+ &first_ucode_section);
if (ret)
return ret;
}
@@ -854,8 +811,6 @@
(trans_pcie->fw_mon_phys +
trans_pcie->fw_mon_size) >> 4);
}
- } else if (trans->dbg_dest_tlv) {
- iwl_pcie_apply_destination(trans);
}
/* release CPU reset */
@@ -864,50 +819,18 @@
else
iwl_write32(trans, CSR_RESET, 0);
- return 0;
-}
+ if (image->is_secure) {
+ /* wait for image verification to complete */
+ ret = iwl_poll_prph_bit(trans,
+ LMPM_SECURE_BOOT_CPU1_STATUS_ADDR,
+ LMPM_SECURE_BOOT_STATUS_SUCCESS,
+ LMPM_SECURE_BOOT_STATUS_SUCCESS,
+ LMPM_SECURE_TIME_OUT);
-static int iwl_pcie_load_given_ucode_8000b(struct iwl_trans *trans,
- const struct fw_img *image)
-{
- int ret = 0;
- int first_ucode_section;
- u32 reg;
-
- IWL_DEBUG_FW(trans, "working with %s CPU\n",
- image->is_dual_cpus ? "Dual" : "Single");
-
- /* configure the ucode to be ready to get the secured image */
- /* release CPU reset */
- iwl_write_prph(trans, RELEASE_CPU_RESET, RELEASE_CPU_RESET_BIT);
-
- /* load to FW the binary Secured sections of CPU1 */
- ret = iwl_pcie_load_cpu_sections_8000b(trans, image, 1,
- &first_ucode_section);
- if (ret)
- return ret;
-
- /* load to FW the binary sections of CPU2 */
- ret = iwl_pcie_load_cpu_sections_8000b(trans, image, 2,
- &first_ucode_section);
- if (ret)
- return ret;
-
- /* Notify FW loading is done */
- iwl_write_direct32(trans, FH_UCODE_LOAD_STATUS, 0xFFFFFFFF);
-
- /* wait for image verification to complete */
- ret = iwl_poll_prph_bit(trans, LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0,
- LMPM_SECURE_BOOT_STATUS_SUCCESS,
- LMPM_SECURE_BOOT_STATUS_SUCCESS,
- LMPM_SECURE_TIME_OUT);
- if (ret < 0) {
- reg = iwl_read_prph(trans,
- LMPM_SECURE_BOOT_CPU1_STATUS_ADDR_B0);
-
- IWL_ERR(trans, "Timeout on secure boot process, reg = %x\n",
- reg);
- return ret;
+ if (ret < 0) {
+ IWL_ERR(trans, "Time out on secure boot process\n");
+ return ret;
+ }
}
return 0;
@@ -959,11 +882,7 @@
iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
/* Load the given image to the HW */
- if ((trans->cfg->device_family == IWL_DEVICE_FAMILY_8000) &&
- (CSR_HW_REV_STEP(trans->hw_rev) == SILICON_B_STEP))
- return iwl_pcie_load_given_ucode_8000b(trans, fw);
- else
- return iwl_pcie_load_given_ucode(trans, fw);
+ return iwl_pcie_load_given_ucode(trans, fw);
}
static void iwl_trans_pcie_fw_alive(struct iwl_trans *trans, u32 scd_addr)
@@ -994,8 +913,7 @@
* restart. So don't process again if the device is
* already dead.
*/
- if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
- IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n");
+ if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
iwl_pcie_tx_stop(trans);
iwl_pcie_rx_stop(trans);
@@ -1020,12 +938,12 @@
spin_unlock(&trans_pcie->irq_lock);
/* stop and reset the on-board processor */
- iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
- udelay(20);
+ iwl_write32(trans, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
/* clear all status bits */
clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status);
clear_bit(STATUS_INT_ENABLED, &trans->status);
+ clear_bit(STATUS_DEVICE_ENABLED, &trans->status);
clear_bit(STATUS_TPOWER_PMI, &trans->status);
clear_bit(STATUS_RFKILL, &trans->status);
@@ -1054,9 +972,6 @@
clear_bit(STATUS_RFKILL, &trans->status);
if (hw_rfkill != was_hw_rfkill)
iwl_trans_pcie_rf_kill(trans, hw_rfkill);
-
- /* re-take ownership to prevent other users from stealing the deivce */
- iwl_pcie_prepare_card_hw(trans);
}
void iwl_trans_pcie_rf_kill(struct iwl_trans *trans, bool state)
@@ -1106,6 +1021,14 @@
return 0;
}
+ iwl_pcie_set_pwr(trans, false);
+
+ val = iwl_read32(trans, CSR_RESET);
+ if (val & CSR_RESET_REG_FLAG_NEVO_RESET) {
+ *status = IWL_D3_STATUS_RESET;
+ return 0;
+ }
+
/*
* Also enables interrupts - none will happen as the device doesn't
* know we're waking it up, only when the opmode actually tells it
@@ -1116,20 +1039,15 @@
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
iwl_set_bit(trans, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
- udelay(2);
-
ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
25000);
- if (ret < 0) {
+ if (ret) {
IWL_ERR(trans, "Failed to resume the device (mac ready)\n");
return ret;
}
- iwl_pcie_set_pwr(trans, false);
-
iwl_trans_pcie_tx_reset(trans);
ret = iwl_pcie_rx_init(trans);
@@ -1138,12 +1056,7 @@
return ret;
}
- val = iwl_read32(trans, CSR_RESET);
- if (val & CSR_RESET_REG_FLAG_NEVO_RESET)
- *status = IWL_D3_STATUS_RESET;
- else
- *status = IWL_D3_STATUS_ALIVE;
-
+ *status = IWL_D3_STATUS_ALIVE;
return 0;
}
@@ -1321,8 +1234,6 @@
/* this bit wakes up the NIC */
__iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
- udelay(2);
/*
* These bits say the device is running, and should keep running for
@@ -1854,13 +1765,6 @@
IWL_ERR(trans, "failed to create the trans debugfs entry\n");
return -ENOMEM;
}
-#else
-static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
- struct dentry *dir)
-{
- return 0;
-}
-#endif /*CPTCFG_IWLWIFI_DEBUGFS */
static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
{
@@ -1988,7 +1892,8 @@
int reg;
__le32 *val;
- prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk;
+ prph_len += sizeof(*data) + sizeof(*prph) +
+ num_bytes_in_chunk;
(*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH);
(*data)->len = cpu_to_le32(sizeof(*prph) +
@@ -2031,31 +1936,6 @@
return csr_len;
}
-static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans,
- struct iwl_fw_error_dump_data **data)
-{
- u32 fh_regs_len = FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND;
- unsigned long flags;
- __le32 *val;
- int i;
-
- if (!iwl_trans_grab_nic_access(trans, false, &flags))
- return 0;
-
- (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FH_REGS);
- (*data)->len = cpu_to_le32(fh_regs_len);
- val = (void *)(*data)->data;
-
- for (i = FH_MEM_LOWER_BOUND; i < FH_MEM_UPPER_BOUND; i += sizeof(u32))
- *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i));
-
- iwl_trans_release_nic_access(trans, &flags);
-
- *data = iwl_fw_error_next_data(*data);
-
- return sizeof(**data) + fh_regs_len;
-}
-
static
struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans)
{
@@ -2065,7 +1945,6 @@
struct iwl_fw_error_dump_txcmd *txcmd;
struct iwl_trans_dump_data *dump_data;
u32 len;
- u32 monitor_len;
int i, ptr;
/* transport dump header */
@@ -2088,34 +1967,10 @@
num_bytes_in_chunk;
}
- /* FH registers */
- len += sizeof(*data) + (FH_MEM_UPPER_BOUND - FH_MEM_LOWER_BOUND);
-
/* FW monitor */
- if (trans_pcie->fw_mon_page) {
+ if (trans_pcie->fw_mon_page)
len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
- trans_pcie->fw_mon_size;
- monitor_len = trans_pcie->fw_mon_size;
- } else if (trans->dbg_dest_tlv) {
- u32 base, end;
-
- base = le32_to_cpu(trans->dbg_dest_tlv->base_reg);
- end = le32_to_cpu(trans->dbg_dest_tlv->end_reg);
-
- base = iwl_read_prph(trans, base) <<
- trans->dbg_dest_tlv->base_shift;
- end = iwl_read_prph(trans, end) <<
- trans->dbg_dest_tlv->end_shift;
-
- /* Make "end" point to the actual end */
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
- end += (1 << trans->dbg_dest_tlv->end_shift);
- monitor_len = end - base;
- len += sizeof(*data) + sizeof(struct iwl_fw_error_dump_fw_mon) +
- monitor_len;
- } else {
- monitor_len = 0;
- }
+ trans_pcie->fw_mon_size;
dump_data = vzalloc(len);
if (!dump_data)
@@ -2152,77 +2007,49 @@
len += iwl_trans_pcie_dump_prph(trans, &data);
len += iwl_trans_pcie_dump_csr(trans, &data);
- len += iwl_trans_pcie_fh_regs_dump(trans, &data);
/* data is already pointing to the next section */
- if ((trans_pcie->fw_mon_page &&
- trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) ||
- trans->dbg_dest_tlv) {
+ if (trans_pcie->fw_mon_page) {
struct iwl_fw_error_dump_fw_mon *fw_mon_data;
- u32 base, write_ptr, wrap_cnt;
-
- /* If there was a dest TLV - use the values from there */
- if (trans->dbg_dest_tlv) {
- write_ptr =
- le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg);
- wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count);
- base = le32_to_cpu(trans->dbg_dest_tlv->base_reg);
- } else {
- base = MON_BUFF_BASE_ADDR;
- write_ptr = MON_BUFF_WRPTR;
- wrap_cnt = MON_BUFF_CYCLE_CNT;
- }
data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_FW_MONITOR);
+ data->len = cpu_to_le32(trans_pcie->fw_mon_size +
+ sizeof(*fw_mon_data));
fw_mon_data = (void *)data->data;
fw_mon_data->fw_mon_wr_ptr =
- cpu_to_le32(iwl_read_prph(trans, write_ptr));
+ cpu_to_le32(iwl_read_prph(trans, MON_BUFF_WRPTR));
fw_mon_data->fw_mon_cycle_cnt =
- cpu_to_le32(iwl_read_prph(trans, wrap_cnt));
+ cpu_to_le32(iwl_read_prph(trans, MON_BUFF_CYCLE_CNT));
fw_mon_data->fw_mon_base_ptr =
- cpu_to_le32(iwl_read_prph(trans, base));
+ cpu_to_le32(iwl_read_prph(trans, MON_BUFF_BASE_ADDR));
- len += sizeof(*data) + sizeof(*fw_mon_data);
- if (trans_pcie->fw_mon_page) {
- data->len = cpu_to_le32(trans_pcie->fw_mon_size +
- sizeof(*fw_mon_data));
+ /*
+ * The firmware is now asserted, it won't write anything to
+ * the buffer. CPU can take ownership to fetch the data.
+ * The buffer will be handed back to the device before the
+ * firmware will be restarted.
+ */
+ dma_sync_single_for_cpu(trans->dev, trans_pcie->fw_mon_phys,
+ trans_pcie->fw_mon_size,
+ DMA_FROM_DEVICE);
+ memcpy(fw_mon_data->data, page_address(trans_pcie->fw_mon_page),
+ trans_pcie->fw_mon_size);
- /*
- * The firmware is now asserted, it won't write anything
- * to the buffer. CPU can take ownership to fetch the
- * data. The buffer will be handed back to the device
- * before the firmware will be restarted.
- */
- dma_sync_single_for_cpu(trans->dev,
- trans_pcie->fw_mon_phys,
- trans_pcie->fw_mon_size,
- DMA_FROM_DEVICE);
- memcpy(fw_mon_data->data,
- page_address(trans_pcie->fw_mon_page),
- trans_pcie->fw_mon_size);
-
- len += trans_pcie->fw_mon_size;
- } else {
- /* If we are here then the buffer is internal */
-
- /*
- * Update pointers to reflect actual values after
- * shifting
- */
- base = iwl_read_prph(trans, base) <<
- trans->dbg_dest_tlv->base_shift;
- iwl_trans_read_mem(trans, base, fw_mon_data->data,
- monitor_len / sizeof(u32));
- data->len = cpu_to_le32(sizeof(*fw_mon_data) +
- monitor_len);
- len += monitor_len;
- }
+ len += sizeof(*data) + sizeof(*fw_mon_data) +
+ trans_pcie->fw_mon_size;
}
dump_data->len = len;
return dump_data;
}
+#else
+static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
+ struct dentry *dir)
+{
+ return 0;
+}
+#endif /*CPTCFG_IWLWIFI_DEBUGFS */
static const struct iwl_trans_ops trans_ops_pcie = {
.start_hw = iwl_trans_pcie_start_hw,
@@ -2259,7 +2086,9 @@
.release_nic_access = iwl_trans_pcie_release_nic_access,
.set_bits_mask = iwl_trans_pcie_set_bits_mask,
+#ifdef CPTCFG_IWLWIFI_DEBUGFS
.dump_data = iwl_trans_pcie_dump_data,
+#endif
};
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index 8a6c7a0..eb8e298 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -989,65 +989,6 @@
spin_unlock_bh(&txq->lock);
}
-static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
- int ret;
-
- lockdep_assert_held(&trans_pcie->reg_lock);
-
- if (trans_pcie->cmd_in_flight)
- return 0;
-
- trans_pcie->cmd_in_flight = true;
-
- /*
- * wake up the NIC to make sure that the firmware will see the host
- * command - we will let the NIC sleep once all the host commands
- * returned. This needs to be done only on NICs that have
- * apmg_wake_up_wa set.
- */
- if (trans->cfg->base_params->apmg_wake_up_wa) {
- __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- if (trans->cfg->device_family == IWL_DEVICE_FAMILY_8000)
- udelay(2);
-
- ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
- (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
- CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
- 15000);
- if (ret < 0) {
- __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
- trans_pcie->cmd_in_flight = false;
- IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
- return -EIO;
- }
- }
-
- return 0;
-}
-
-static int iwl_pcie_clear_cmd_in_flight(struct iwl_trans *trans)
-{
- struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-
- lockdep_assert_held(&trans_pcie->reg_lock);
-
- if (WARN_ON(!trans_pcie->cmd_in_flight))
- return 0;
-
- trans_pcie->cmd_in_flight = false;
-
- if (trans->cfg->base_params->apmg_wake_up_wa)
- __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
- CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
-
- return 0;
-}
-
/*
* iwl_pcie_cmdq_reclaim - Reclaim TX command queue entries already Tx'd
*
@@ -1083,9 +1024,14 @@
}
}
- if (q->read_ptr == q->write_ptr) {
+ if (trans->cfg->base_params->apmg_wake_up_wa &&
+ q->read_ptr == q->write_ptr) {
spin_lock_irqsave(&trans_pcie->reg_lock, flags);
- iwl_pcie_clear_cmd_in_flight(trans);
+ WARN_ON(!trans_pcie->cmd_in_flight);
+ trans_pcie->cmd_in_flight = false;
+ __iwl_trans_pcie_clear_bit(trans,
+ CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
}
@@ -1473,11 +1419,32 @@
mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
spin_lock_irqsave(&trans_pcie->reg_lock, flags);
- ret = iwl_pcie_set_cmd_in_flight(trans);
- if (ret < 0) {
- idx = ret;
- spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
- goto out;
+
+ /*
+ * wake up the NIC to make sure that the firmware will see the host
+ * command - we will let the NIC sleep once all the host commands
+ * returned. This needs to be done only on NICs that have
+ * apmg_wake_up_wa set.
+ */
+ if (trans->cfg->base_params->apmg_wake_up_wa &&
+ !trans_pcie->cmd_in_flight) {
+ trans_pcie->cmd_in_flight = true;
+ __iwl_trans_pcie_set_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ ret = iwl_poll_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+ (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+ CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP),
+ 15000);
+ if (ret < 0) {
+ __iwl_trans_pcie_clear_bit(trans, CSR_GP_CNTRL,
+ CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+ spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
+ trans_pcie->cmd_in_flight = false;
+ IWL_ERR(trans, "Failed to wake NIC for hcmd\n");
+ idx = -EIO;
+ goto out;
+ }
}
/* Increment and update queue's write index */
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index c6755b8..a3f2e06 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -395,6 +395,7 @@
static struct platform_driver mac80211_hwsim_driver = {
.driver = {
.name = "mac80211_hwsim",
+ .owner = THIS_MODULE,
},
};
@@ -411,11 +412,6 @@
struct mac_address addresses[2];
int channels, idx;
bool use_chanctx;
- bool destroy_on_close;
- struct work_struct destroy_work;
- u32 portid;
- char alpha2[2];
- const struct ieee80211_regdomain *regd;
struct ieee80211_channel *tmp_chan;
struct delayed_work roc_done;
@@ -423,7 +419,6 @@
struct cfg80211_scan_request *hw_scan_request;
struct ieee80211_vif *hw_scan_vif;
int scan_chan_idx;
- u8 scan_addr[ETH_ALEN];
struct ieee80211_channel *channel;
u64 beacon_int /* beacon interval in us */;
@@ -441,7 +436,7 @@
/*
* Only radios in the same group can communicate together (the
* channel has to match too). Each bit represents a group. A
- * radio can be in more than one group.
+ * radio can be in more then one group.
*/
u64 group;
@@ -452,14 +447,6 @@
s64 bcn_delta;
/* absolute beacon transmission time. Used to cover up "tx" delay. */
u64 abs_bcn_ts;
-
- /* Stats */
- u64 tx_pkts;
- u64 rx_pkts;
- u64 tx_bytes;
- u64 rx_bytes;
- u64 tx_dropped;
- u64 tx_failed;
};
@@ -489,14 +476,6 @@
.maxattr = HWSIM_ATTR_MAX,
};
-enum hwsim_multicast_groups {
- HWSIM_MCGRP_CONFIG,
-};
-
-static __genl_const struct genl_multicast_group hwsim_mcgrps[] = {
- [HWSIM_MCGRP_CONFIG] = { .name = "config", },
-};
-
/* MAC80211_HWSIM netlink policy */
static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = {
@@ -517,10 +496,6 @@
[HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 },
[HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG },
[HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG },
- [HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG },
- [HWSIM_ATTR_RADIO_NAME] = { .type = NLA_STRING },
- [HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG },
- [HWSIM_ATTR_FREQ] = { .type = NLA_U32 },
};
static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw,
@@ -832,9 +807,6 @@
.ret = false,
};
- if (data->scanning && memcmp(addr, data->scan_addr, ETH_ALEN) == 0)
- return true;
-
memcpy(md.addr, addr, ETH_ALEN);
ieee80211_iterate_active_interfaces_atomic(data->hw,
@@ -889,10 +861,8 @@
/* If the queue contains MAX_QUEUE skb's drop some */
if (skb_queue_len(&data->pending) >= MAX_QUEUE) {
/* Droping until WARN_QUEUE level */
- while (skb_queue_len(&data->pending) >= WARN_QUEUE) {
- ieee80211_free_txskb(hw, skb_dequeue(&data->pending));
- data->tx_dropped++;
- }
+ while (skb_queue_len(&data->pending) >= WARN_QUEUE)
+ skb_dequeue(&data->pending);
}
skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC);
@@ -926,9 +896,6 @@
if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags))
goto nla_put_failure;
- if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq))
- goto nla_put_failure;
-
/* We get the tx control (rate and retries) info*/
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
@@ -950,14 +917,10 @@
/* Enqueue the packet */
skb_queue_tail(&data->pending, my_skb);
- data->tx_pkts++;
- data->tx_bytes += my_skb->len;
return;
nla_put_failure:
printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
- ieee80211_free_txskb(hw, my_skb);
- data->tx_failed++;
}
static bool hwsim_chans_compat(struct ieee80211_channel *c1,
@@ -989,53 +952,6 @@
data->receive = true;
}
-static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb)
-{
- /*
- * To enable this code, #define the HWSIM_RADIOTAP_OUI,
- * e.g. like this:
- * #define HWSIM_RADIOTAP_OUI "\x02\x00\x00"
- * (but you should use a valid OUI, not that)
- *
- * If anyone wants to 'donate' a radiotap OUI/subns code
- * please send a patch removing this #ifdef and changing
- * the values accordingly.
- */
-#ifdef HWSIM_RADIOTAP_OUI
- struct ieee80211_vendor_radiotap *rtap;
-
- /*
- * Note that this code requires the headroom in the SKB
- * that was allocated earlier.
- */
- rtap = (void *)skb_push(skb, sizeof(*rtap) + 8 + 4);
- rtap->oui[0] = HWSIM_RADIOTAP_OUI[0];
- rtap->oui[1] = HWSIM_RADIOTAP_OUI[1];
- rtap->oui[2] = HWSIM_RADIOTAP_OUI[2];
- rtap->subns = 127;
-
- /*
- * Radiotap vendor namespaces can (and should) also be
- * split into fields by using the standard radiotap
- * presence bitmap mechanism. Use just BIT(0) here for
- * the presence bitmap.
- */
- rtap->present = BIT(0);
- /* We have 8 bytes of (dummy) data */
- rtap->len = 8;
- /* For testing, also require it to be aligned */
- rtap->align = 8;
- /* And also test that padding works, 4 bytes */
- rtap->pad = 4;
- /* push the data */
- memcpy(rtap->data, "ABCDEFGH", 8);
- /* make sure to clear padding, mac80211 doesn't */
- memset(rtap->data + 8, 0, 4);
-
- IEEE80211_SKB_RXCB(skb)->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA;
-#endif
-}
-
static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
struct sk_buff *skb,
struct ieee80211_channel *chan)
@@ -1150,11 +1066,6 @@
rx_status.mactime = now + data2->tsf_offset;
memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status));
-
- mac80211_hwsim_add_vendor_rtap(nskb);
-
- data2->rx_pkts++;
- data2->rx_bytes += nskb->len;
ieee80211_rx_irqsafe(data2->hw, nskb);
}
spin_unlock(&hwsim_radio_lock);
@@ -1222,8 +1133,6 @@
return mac80211_hwsim_tx_frame_nl(hw, skb, _portid);
/* NO wmediumd detected, perfect medium simulation */
- data->tx_pkts++;
- data->tx_bytes += skb->len;
ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel);
if (ack && skb->len >= 16) {
@@ -1807,7 +1716,7 @@
struct sk_buff *probe;
probe = ieee80211_probereq_get(hwsim->hw,
- hwsim->scan_addr,
+ hwsim->hw_scan_vif,
req->ssids[i].ssid,
req->ssids[i].ssid_len,
req->ie_len);
@@ -1845,12 +1754,6 @@
hwsim->hw_scan_request = req;
hwsim->hw_scan_vif = vif;
hwsim->scan_chan_idx = 0;
- if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
- get_random_mask_addr(hwsim->scan_addr,
- hw_req->req.mac_addr,
- hw_req->req.mac_addr_mask);
- else
- memcpy(hwsim->scan_addr, vif->addr, ETH_ALEN);
mutex_unlock(&hwsim->mutex);
wiphy_debug(hw->wiphy, "hwsim hw_scan request\n");
@@ -1877,9 +1780,7 @@
mutex_unlock(&hwsim->mutex);
}
-static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw)
{
struct mac80211_hwsim_data *hwsim = hw->priv;
@@ -1891,16 +1792,13 @@
}
printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n");
-
- memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN);
hwsim->scanning = true;
out:
mutex_unlock(&hwsim->mutex);
}
-static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw)
{
struct mac80211_hwsim_data *hwsim = hw->priv;
@@ -1908,7 +1806,6 @@
printk(KERN_DEBUG "hwsim sw_scan_complete\n");
hwsim->scanning = false;
- memset(hwsim->scan_addr, 0, ETH_ALEN);
mutex_unlock(&hwsim->mutex);
}
@@ -2019,57 +1916,6 @@
hwsim_check_chanctx_magic(ctx);
}
-static const char mac80211_hwsim_gstrings_stats[][ETH_GSTRING_LEN] = {
- "tx_pkts_nic",
- "tx_bytes_nic",
- "rx_pkts_nic",
- "rx_bytes_nic",
- "d_tx_dropped",
- "d_tx_failed",
- "d_ps_mode",
- "d_group",
- "d_tx_power",
-};
-
-#define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats)
-
-static void mac80211_hwsim_get_et_strings(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- u32 sset, u8 *data)
-{
- if (sset == ETH_SS_STATS)
- memcpy(data, *mac80211_hwsim_gstrings_stats,
- sizeof(mac80211_hwsim_gstrings_stats));
-}
-
-static int mac80211_hwsim_get_et_sset_count(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif, int sset)
-{
- if (sset == ETH_SS_STATS)
- return MAC80211_HWSIM_SSTATS_LEN;
- return 0;
-}
-
-static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ethtool_stats *stats, u64 *data)
-{
- struct mac80211_hwsim_data *ar = hw->priv;
- int i = 0;
-
- data[i++] = ar->tx_pkts;
- data[i++] = ar->tx_bytes;
- data[i++] = ar->rx_pkts;
- data[i++] = ar->rx_bytes;
- data[i++] = ar->tx_dropped;
- data[i++] = ar->tx_failed;
- data[i++] = ar->ps;
- data[i++] = ar->group;
- data[i++] = ar->power_level;
-
- WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN);
-}
-
static const struct ieee80211_ops mac80211_hwsim_ops = {
.tx = mac80211_hwsim_tx,
.start = mac80211_hwsim_start,
@@ -2093,131 +1939,14 @@
.flush = mac80211_hwsim_flush,
.get_tsf = mac80211_hwsim_get_tsf,
.set_tsf = mac80211_hwsim_set_tsf,
- .get_et_sset_count = mac80211_hwsim_get_et_sset_count,
- .get_et_stats = mac80211_hwsim_get_et_stats,
- .get_et_strings = mac80211_hwsim_get_et_strings,
};
static struct ieee80211_ops mac80211_hwsim_mchan_ops;
-struct hwsim_new_radio_params {
- unsigned int channels;
- const char *reg_alpha2;
- const struct ieee80211_regdomain *regd;
- bool reg_strict;
- bool p2p_device;
- bool use_chanctx;
- bool destroy_on_close;
- const char *hwname;
- bool no_vif;
-};
-
-static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb,
- struct genl_info *info)
-{
- if (info)
- genl_notify(&hwsim_genl_family, mcast_skb,
- genl_info_net(info), genl_info_snd_portid(info),
- HWSIM_MCGRP_CONFIG, info->nlhdr, GFP_KERNEL);
- else
- genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0,
- HWSIM_MCGRP_CONFIG, GFP_KERNEL);
-}
-
-static int append_radio_msg(struct sk_buff *skb, int id,
- struct hwsim_new_radio_params *param)
-{
- int ret;
-
- ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id);
- if (ret < 0)
- return ret;
-
- if (param->channels) {
- ret = nla_put_u32(skb, HWSIM_ATTR_CHANNELS, param->channels);
- if (ret < 0)
- return ret;
- }
-
- if (param->reg_alpha2) {
- ret = nla_put(skb, HWSIM_ATTR_REG_HINT_ALPHA2, 2,
- param->reg_alpha2);
- if (ret < 0)
- return ret;
- }
-
- if (param->regd) {
- int i;
-
- for (i = 0; hwsim_world_regdom_custom[i] != param->regd &&
- i < ARRAY_SIZE(hwsim_world_regdom_custom); i++)
- ;
-
- if (i < ARRAY_SIZE(hwsim_world_regdom_custom)) {
- ret = nla_put_u32(skb, HWSIM_ATTR_REG_CUSTOM_REG, i);
- if (ret < 0)
- return ret;
- }
- }
-
- if (param->reg_strict) {
- ret = nla_put_flag(skb, HWSIM_ATTR_REG_STRICT_REG);
- if (ret < 0)
- return ret;
- }
-
- if (param->p2p_device) {
- ret = nla_put_flag(skb, HWSIM_ATTR_SUPPORT_P2P_DEVICE);
- if (ret < 0)
- return ret;
- }
-
- if (param->use_chanctx) {
- ret = nla_put_flag(skb, HWSIM_ATTR_USE_CHANCTX);
- if (ret < 0)
- return ret;
- }
-
- if (param->hwname) {
- ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME,
- strlen(param->hwname), param->hwname);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-static void hwsim_mcast_new_radio(int id, struct genl_info *info,
- struct hwsim_new_radio_params *param)
-{
- struct sk_buff *mcast_skb;
- void *data;
-
- mcast_skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!mcast_skb)
- return;
-
- data = genlmsg_put(mcast_skb, 0, 0, &hwsim_genl_family, 0,
- HWSIM_CMD_NEW_RADIO);
- if (!data)
- goto out_err;
-
- if (append_radio_msg(mcast_skb, id, param) < 0)
- goto out_err;
-
- genlmsg_end(mcast_skb, data);
-
- hwsim_mcast_config_msg(mcast_skb, info);
- return;
-
-out_err:
- genlmsg_cancel(mcast_skb, data);
- nlmsg_free(mcast_skb);
-}
-
-static int mac80211_hwsim_new_radio(struct genl_info *info,
- struct hwsim_new_radio_params *param)
+static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2,
+ const struct ieee80211_regdomain *regd,
+ bool reg_strict, bool p2p_device,
+ bool use_chanctx)
{
int err;
u8 addr[ETH_ALEN];
@@ -2227,16 +1956,16 @@
const struct ieee80211_ops *ops = &mac80211_hwsim_ops;
int idx;
- if (WARN_ON(param->channels > 1 && !param->use_chanctx))
+ if (WARN_ON(channels > 1 && !use_chanctx))
return -EINVAL;
spin_lock_bh(&hwsim_radio_lock);
idx = hwsim_radio_idx++;
spin_unlock_bh(&hwsim_radio_lock);
- if (param->use_chanctx)
+ if (use_chanctx)
ops = &mac80211_hwsim_mchan_ops;
- hw = ieee80211_alloc_hw_nm(sizeof(*data), ops, param->hwname);
+ hw = ieee80211_alloc_hw(sizeof(*data), ops);
if (!hw) {
printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n");
err = -ENOMEM;
@@ -2258,7 +1987,7 @@
if (err != 0) {
printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n",
err);
- goto failed_bind;
+ goto failed_hw;
}
skb_queue_head_init(&data->pending);
@@ -2274,12 +2003,9 @@
hw->wiphy->n_addresses = 2;
hw->wiphy->addresses = data->addresses;
- data->channels = param->channels;
- data->use_chanctx = param->use_chanctx;
+ data->channels = channels;
+ data->use_chanctx = use_chanctx;
data->idx = idx;
- data->destroy_on_close = param->destroy_on_close;
- if (info)
- data->portid = genl_info_snd_portid(info);
if (data->use_chanctx) {
hw->wiphy->max_scan_ssids = 255;
@@ -2288,12 +2014,12 @@
/* For channels > 1 DFS is not allowed */
hw->wiphy->n_iface_combinations = 1;
hw->wiphy->iface_combinations = &data->if_combination;
- if (param->p2p_device)
+ if (p2p_device)
data->if_combination = hwsim_if_comb_p2p_dev[0];
else
data->if_combination = hwsim_if_comb[0];
data->if_combination.num_different_channels = data->channels;
- } else if (param->p2p_device) {
+ } else if (p2p_device) {
hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev;
hw->wiphy->n_iface_combinations =
ARRAY_SIZE(hwsim_if_comb_p2p_dev);
@@ -2314,7 +2040,7 @@
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
- if (param->p2p_device)
+ if (p2p_device)
hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE);
hw->flags = IEEE80211_HW_MFP_CAPABLE |
@@ -2334,8 +2060,7 @@
hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR |
NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE |
NL80211_FEATURE_STATIC_SMPS |
- NL80211_FEATURE_DYNAMIC_SMPS |
- NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+ NL80211_FEATURE_DYNAMIC_SMPS;
/* ask mac80211 to reserve space for magic */
hw->vif_data_size = sizeof(struct hwsim_vif_priv);
@@ -2370,7 +2095,6 @@
sband->ht_cap.ht_supported = true;
sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
IEEE80211_HT_CAP_GRN_FLD |
- IEEE80211_HT_CAP_SGI_20 |
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_DSSSCCK40;
sband->ht_cap.ampdu_factor = 0x3;
@@ -2387,6 +2111,7 @@
sband->vht_cap.cap =
IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
+ IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
IEEE80211_VHT_CAP_RXLDPC |
IEEE80211_VHT_CAP_SHORT_GI_80 |
IEEE80211_VHT_CAP_SHORT_GI_160 |
@@ -2417,19 +2142,15 @@
hw->max_rates = 4;
hw->max_rate_tries = 11;
- if (param->reg_strict)
+ if (reg_strict)
hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
- if (param->regd) {
- data->regd = param->regd;
+ if (regd) {
hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
- wiphy_apply_custom_regulatory(hw->wiphy, param->regd);
+ wiphy_apply_custom_regulatory(hw->wiphy, regd);
/* give the regulatory workqueue a chance to run */
schedule_timeout_interruptible(1);
}
- if (param->no_vif)
- hw->flags |= IEEE80211_HW_NO_AUTO_VIF;
-
err = ieee80211_register_hw(hw);
if (err < 0) {
printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n",
@@ -2439,11 +2160,8 @@
wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr);
- if (param->reg_alpha2) {
- data->alpha2[0] = param->reg_alpha2[0];
- data->alpha2[1] = param->reg_alpha2[1];
- regulatory_hint(hw->wiphy, param->reg_alpha2);
- }
+ if (reg_alpha2)
+ regulatory_hint(hw->wiphy, reg_alpha2);
data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir);
debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps);
@@ -2462,14 +2180,9 @@
list_add_tail(&data->list, &hwsim_radios);
spin_unlock_bh(&hwsim_radio_lock);
- if (idx > 0)
- hwsim_mcast_new_radio(idx, info, param);
-
return idx;
failed_hw:
- device_release_driver(data->dev);
-failed_bind:
device_unregister(data->dev);
failed_drvdata:
ieee80211_free_hw(hw);
@@ -2477,46 +2190,8 @@
return err;
}
-static void hwsim_mcast_del_radio(int id, const char *hwname,
- struct genl_info *info)
+static void mac80211_hwsim_destroy_radio(struct mac80211_hwsim_data *data)
{
- struct sk_buff *skb;
- void *data;
- int ret;
-
- skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!skb)
- return;
-
- data = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0,
- HWSIM_CMD_DEL_RADIO);
- if (!data)
- goto error;
-
- ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id);
- if (ret < 0)
- goto error;
-
- ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, strlen(hwname),
- hwname);
- if (ret < 0)
- goto error;
-
- genlmsg_end(skb, data);
-
- hwsim_mcast_config_msg(skb, info);
-
- return;
-
-error:
- nlmsg_free(skb);
-}
-
-static void mac80211_hwsim_del_radio(struct mac80211_hwsim_data *data,
- const char *hwname,
- struct genl_info *info)
-{
- hwsim_mcast_del_radio(data->idx, hwname, info);
debugfs_remove_recursive(data->debugfs);
ieee80211_unregister_hw(data->hw);
device_release_driver(data->dev);
@@ -2524,46 +2199,6 @@
ieee80211_free_hw(data->hw);
}
-static int mac80211_hwsim_get_radio(struct sk_buff *skb,
- struct mac80211_hwsim_data *data,
- u32 portid, u32 seq,
- struct netlink_callback *cb, int flags)
-{
- void *hdr;
- struct hwsim_new_radio_params param = { };
- int res = -EMSGSIZE;
-
- hdr = genlmsg_put(skb, portid, seq, &hwsim_genl_family, flags,
- HWSIM_CMD_GET_RADIO);
- if (!hdr)
- return -EMSGSIZE;
-
- if (cb)
- genl_dump_check_consistent(cb, hdr, &hwsim_genl_family);
-
- if (data->alpha2[0] && data->alpha2[1])
- param.reg_alpha2 = data->alpha2;
-
- param.reg_strict = !!(data->hw->wiphy->regulatory_flags &
- REGULATORY_STRICT_REG);
- param.p2p_device = !!(data->hw->wiphy->interface_modes &
- BIT(NL80211_IFTYPE_P2P_DEVICE));
- param.use_chanctx = data->use_chanctx;
- param.regd = data->regd;
- param.channels = data->channels;
- param.hwname = wiphy_name(data->hw->wiphy);
-
- res = append_radio_msg(skb, data->idx, ¶m);
- if (res < 0)
- goto out_err;
-
- return genlmsg_end(skb, hdr);
-
-out_err:
- genlmsg_cancel(skb, hdr);
- return res;
-}
-
static void mac80211_hwsim_free(void)
{
struct mac80211_hwsim_data *data;
@@ -2574,8 +2209,7 @@
list))) {
list_del(&data->list);
spin_unlock_bh(&hwsim_radio_lock);
- mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
- NULL);
+ mac80211_hwsim_destroy_radio(data);
spin_lock_bh(&hwsim_radio_lock);
}
spin_unlock_bh(&hwsim_radio_lock);
@@ -2703,6 +2337,7 @@
static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2,
struct genl_info *info)
{
+
struct mac80211_hwsim_data *data2;
struct ieee80211_rx_status rx_status;
const u8 *dst;
@@ -2745,22 +2380,18 @@
/* A frame is received from user space */
memset(&rx_status, 0, sizeof(rx_status));
- /* TODO: Check ATTR_FREQ if it exists, and maybe throw away off-channel
- * packets?
- */
rx_status.freq = data2->channel->center_freq;
rx_status.band = data2->channel->band;
rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]);
rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]);
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
- data2->rx_pkts++;
- data2->rx_bytes += skb->len;
ieee80211_rx_irqsafe(data2->hw, skb);
return 0;
err:
printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__);
+ goto out;
out:
dev_kfree_skb(skb);
return -EINVAL;
@@ -2797,84 +2428,42 @@
return 0;
}
-static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
+static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info)
{
- struct hwsim_new_radio_params param = { 0 };
-
- param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG];
- param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE];
- param.channels = channels;
- param.destroy_on_close =
- info->attrs[HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE];
+ unsigned int chans = channels;
+ const char *alpha2 = NULL;
+ const struct ieee80211_regdomain *regd = NULL;
+ bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG];
+ bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE];
+ bool use_chanctx;
if (info->attrs[HWSIM_ATTR_CHANNELS])
- param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);
-
- if (info->attrs[HWSIM_ATTR_NO_VIF])
- param.no_vif = true;
-
- if (info->attrs[HWSIM_ATTR_RADIO_NAME])
- param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]);
+ chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]);
if (info->attrs[HWSIM_ATTR_USE_CHANCTX])
- param.use_chanctx = true;
+ use_chanctx = true;
else
- param.use_chanctx = (param.channels > 1);
+ use_chanctx = (chans > 1);
if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2])
- param.reg_alpha2 =
- nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]);
+ alpha2 = nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]);
if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) {
u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]);
if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom))
return -EINVAL;
- param.regd = hwsim_world_regdom_custom[idx];
+ regd = hwsim_world_regdom_custom[idx];
}
- return mac80211_hwsim_new_radio(info, ¶m);
+ return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict,
+ p2p_device, use_chanctx);
}
-static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info)
+static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info)
{
struct mac80211_hwsim_data *data;
- s64 idx = -1;
- const char *hwname = NULL;
-
- if (info->attrs[HWSIM_ATTR_RADIO_ID])
- idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]);
- else if (info->attrs[HWSIM_ATTR_RADIO_NAME])
- hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]);
- else
- return -EINVAL;
-
- spin_lock_bh(&hwsim_radio_lock);
- list_for_each_entry(data, &hwsim_radios, list) {
- if (idx >= 0) {
- if (data->idx != idx)
- continue;
- } else {
- if (strcmp(hwname, wiphy_name(data->hw->wiphy)))
- continue;
- }
-
- list_del(&data->list);
- spin_unlock_bh(&hwsim_radio_lock);
- mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy),
- info);
- return 0;
- }
- spin_unlock_bh(&hwsim_radio_lock);
-
- return -ENODEV;
-}
-
-static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
-{
- struct mac80211_hwsim_data *data;
- struct sk_buff *skb;
- int idx, res = -ENODEV;
+ int idx;
if (!info->attrs[HWSIM_ATTR_RADIO_ID])
return -EINVAL;
@@ -2884,62 +2473,14 @@
list_for_each_entry(data, &hwsim_radios, list) {
if (data->idx != idx)
continue;
-
- skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!skb) {
- res = -ENOMEM;
- goto out_err;
- }
-
- res = mac80211_hwsim_get_radio(skb, data,
- genl_info_snd_portid(info),
- info->snd_seq, NULL, 0);
- if (res < 0) {
- nlmsg_free(skb);
- goto out_err;
- }
-
- genlmsg_reply(skb, info);
- break;
+ list_del(&data->list);
+ spin_unlock_bh(&hwsim_radio_lock);
+ mac80211_hwsim_destroy_radio(data);
+ return 0;
}
-
-out_err:
spin_unlock_bh(&hwsim_radio_lock);
- return res;
-}
-
-static int hwsim_dump_radio_nl(struct sk_buff *skb,
- struct netlink_callback *cb)
-{
- int idx = cb->args[0];
- struct mac80211_hwsim_data *data = NULL;
- int res;
-
- spin_lock_bh(&hwsim_radio_lock);
-
- if (idx == hwsim_radio_idx)
- goto done;
-
- list_for_each_entry(data, &hwsim_radios, list) {
- if (data->idx < idx)
- continue;
-
- res = mac80211_hwsim_get_radio(skb, data,
- NETLINK_CB_PORTID(cb->skb),
- cb->nlh->nlmsg_seq, cb,
- NLM_F_MULTI);
- if (res < 0)
- break;
-
- idx = data->idx + 1;
- }
-
- cb->args[0] = idx;
-
-done:
- spin_unlock_bh(&hwsim_radio_lock);
- return skb->len;
+ return -ENODEV;
}
/* Generic Netlink operations array */
@@ -2961,48 +2502,19 @@
.doit = hwsim_tx_info_frame_received_nl,
},
{
- .cmd = HWSIM_CMD_NEW_RADIO,
+ .cmd = HWSIM_CMD_CREATE_RADIO,
.policy = hwsim_genl_policy,
- .doit = hwsim_new_radio_nl,
+ .doit = hwsim_create_radio_nl,
.flags = GENL_ADMIN_PERM,
},
{
- .cmd = HWSIM_CMD_DEL_RADIO,
+ .cmd = HWSIM_CMD_DESTROY_RADIO,
.policy = hwsim_genl_policy,
- .doit = hwsim_del_radio_nl,
+ .doit = hwsim_destroy_radio_nl,
.flags = GENL_ADMIN_PERM,
},
- {
- .cmd = HWSIM_CMD_GET_RADIO,
- .policy = hwsim_genl_policy,
- .doit = hwsim_get_radio_nl,
- .dumpit = hwsim_dump_radio_nl,
- },
};
-static void destroy_radio(struct work_struct *work)
-{
- struct mac80211_hwsim_data *data =
- container_of(work, struct mac80211_hwsim_data, destroy_work);
-
- mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL);
-}
-
-static void remove_user_radios(u32 portid)
-{
- struct mac80211_hwsim_data *entry, *tmp;
-
- spin_lock_bh(&hwsim_radio_lock);
- list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) {
- if (entry->destroy_on_close && entry->portid == portid) {
- list_del(&entry->list);
- INIT_WORK(&entry->destroy_work, destroy_radio);
- schedule_work(&entry->destroy_work);
- }
- }
- spin_unlock_bh(&hwsim_radio_lock);
-}
-
static int mac80211_hwsim_netlink_notify(struct notifier_block *nb,
unsigned long state,
void *_notify)
@@ -3012,8 +2524,6 @@
if (state != NETLINK_URELEASE)
return NOTIFY_DONE;
- remove_user_radios(netlink_notify_portid(notify));
-
if (netlink_notify_portid(notify) == wmediumd_portid) {
printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink"
" socket, switching to perfect channel medium\n");
@@ -3033,9 +2543,7 @@
printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
- rc = genl_register_family_with_ops_groups(&hwsim_genl_family,
- hwsim_ops,
- hwsim_mcgrps);
+ rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops);
if (rc)
goto failure;
@@ -3096,73 +2604,69 @@
goto out_unregister_driver;
}
- err = hwsim_init_netlink();
- if (err < 0)
- goto out_unregister_driver;
-
for (i = 0; i < radios; i++) {
- struct hwsim_new_radio_params param = { 0 };
-
- param.channels = channels;
+ const char *reg_alpha2 = NULL;
+ const struct ieee80211_regdomain *regd = NULL;
+ bool reg_strict = false;
switch (regtest) {
case HWSIM_REGTEST_DIFF_COUNTRY:
if (i < ARRAY_SIZE(hwsim_alpha2s))
- param.reg_alpha2 = hwsim_alpha2s[i];
+ reg_alpha2 = hwsim_alpha2s[i];
break;
case HWSIM_REGTEST_DRIVER_REG_FOLLOW:
if (!i)
- param.reg_alpha2 = hwsim_alpha2s[0];
+ reg_alpha2 = hwsim_alpha2s[0];
break;
case HWSIM_REGTEST_STRICT_ALL:
- param.reg_strict = true;
+ reg_strict = true;
case HWSIM_REGTEST_DRIVER_REG_ALL:
- param.reg_alpha2 = hwsim_alpha2s[0];
+ reg_alpha2 = hwsim_alpha2s[0];
break;
case HWSIM_REGTEST_WORLD_ROAM:
if (i == 0)
- param.regd = &hwsim_world_regdom_custom_01;
+ regd = &hwsim_world_regdom_custom_01;
break;
case HWSIM_REGTEST_CUSTOM_WORLD:
- param.regd = &hwsim_world_regdom_custom_01;
+ regd = &hwsim_world_regdom_custom_01;
break;
case HWSIM_REGTEST_CUSTOM_WORLD_2:
if (i == 0)
- param.regd = &hwsim_world_regdom_custom_01;
+ regd = &hwsim_world_regdom_custom_01;
else if (i == 1)
- param.regd = &hwsim_world_regdom_custom_02;
+ regd = &hwsim_world_regdom_custom_02;
break;
case HWSIM_REGTEST_STRICT_FOLLOW:
if (i == 0) {
- param.reg_strict = true;
- param.reg_alpha2 = hwsim_alpha2s[0];
+ reg_strict = true;
+ reg_alpha2 = hwsim_alpha2s[0];
}
break;
case HWSIM_REGTEST_STRICT_AND_DRIVER_REG:
if (i == 0) {
- param.reg_strict = true;
- param.reg_alpha2 = hwsim_alpha2s[0];
+ reg_strict = true;
+ reg_alpha2 = hwsim_alpha2s[0];
} else if (i == 1) {
- param.reg_alpha2 = hwsim_alpha2s[1];
+ reg_alpha2 = hwsim_alpha2s[1];
}
break;
case HWSIM_REGTEST_ALL:
switch (i) {
case 0:
- param.regd = &hwsim_world_regdom_custom_01;
+ regd = &hwsim_world_regdom_custom_01;
break;
case 1:
- param.regd = &hwsim_world_regdom_custom_02;
+ regd = &hwsim_world_regdom_custom_02;
break;
case 2:
- param.reg_alpha2 = hwsim_alpha2s[0];
+ reg_alpha2 = hwsim_alpha2s[0];
break;
case 3:
- param.reg_alpha2 = hwsim_alpha2s[1];
+ reg_alpha2 = hwsim_alpha2s[1];
break;
case 4:
- param.reg_strict = true;
- param.reg_alpha2 = hwsim_alpha2s[2];
+ reg_strict = true;
+ reg_alpha2 = hwsim_alpha2s[2];
break;
}
break;
@@ -3170,10 +2674,10 @@
break;
}
- param.p2p_device = support_p2p_device;
- param.use_chanctx = channels > 1;
-
- err = mac80211_hwsim_new_radio(NULL, ¶m);
+ err = mac80211_hwsim_create_radio(channels, reg_alpha2,
+ regd, reg_strict,
+ support_p2p_device,
+ channels > 1);
if (err < 0)
goto out_free_radios;
}
@@ -3199,6 +2703,10 @@
}
rtnl_unlock();
+ err = hwsim_init_netlink();
+ if (err < 0)
+ goto out_free_mon;
+
return 0;
out_free_mon:
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h
index 66e1c73..c9d0315 100644
--- a/drivers/net/wireless/mac80211_hwsim.h
+++ b/drivers/net/wireless/mac80211_hwsim.h
@@ -60,17 +60,14 @@
* space, uses:
* %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER,
* %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE,
- * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE, %HWSIM_ATTR_FREQ (optional)
+ * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
* @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to
* kernel, uses:
* %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS,
* %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE
- * @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters,
- * returns the radio ID (>= 0) or negative on errors, if successful
- * then multicast the result
- * @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted
- * @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses:
- * %HWSIM_ATTR_RADIO_ID
+ * @HWSIM_CMD_CREATE_RADIO: create a new radio with the given parameters,
+ * returns the radio ID (>= 0) or negative on errors
+ * @HWSIM_CMD_DESTROY_RADIO: destroy a radio
* @__HWSIM_CMD_MAX: enum limit
*/
enum {
@@ -78,16 +75,12 @@
HWSIM_CMD_REGISTER,
HWSIM_CMD_FRAME,
HWSIM_CMD_TX_INFO_FRAME,
- HWSIM_CMD_NEW_RADIO,
- HWSIM_CMD_DEL_RADIO,
- HWSIM_CMD_GET_RADIO,
+ HWSIM_CMD_CREATE_RADIO,
+ HWSIM_CMD_DESTROY_RADIO,
__HWSIM_CMD_MAX,
};
#define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1)
-#define HWSIM_CMD_CREATE_RADIO HWSIM_CMD_NEW_RADIO
-#define HWSIM_CMD_DESTROY_RADIO HWSIM_CMD_DEL_RADIO
-
/**
* enum hwsim_attrs - hwsim netlink attributes
*
@@ -118,11 +111,6 @@
* @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO
* command to force use of channel contexts even when only a
* single channel is supported
- * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO
- * command to force radio removal when process that created the radio dies
- * @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666
- * @HWSIM_ATTR_NO_VIF: Do not create vif (wlanX) when creating radio.
- * @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received.
* @__HWSIM_ATTR_MAX: enum limit
*/
@@ -144,10 +132,6 @@
HWSIM_ATTR_REG_STRICT_REG,
HWSIM_ATTR_SUPPORT_P2P_DEVICE,
HWSIM_ATTR_USE_CHANCTX,
- HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE,
- HWSIM_ATTR_RADIO_NAME,
- HWSIM_ATTR_NO_VIF,
- HWSIM_ATTR_FREQ,
__HWSIM_ATTR_MAX,
};
#define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1)
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 9d4786e..62f5dbe 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -544,7 +544,6 @@
u32 tx_win_size = priv->add_ba_param.tx_win_size;
static u8 dialog_tok;
int ret;
- unsigned long flags;
u16 block_ack_param_set;
dev_dbg(priv->adapter->dev, "cmd: %s: tid %d\n", __func__, tid);
@@ -555,18 +554,15 @@
memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) {
struct mwifiex_sta_node *sta_ptr;
- spin_lock_irqsave(&priv->sta_list_spinlock, flags);
sta_ptr = mwifiex_get_sta_entry(priv, peer_mac);
if (!sta_ptr) {
dev_warn(priv->adapter->dev,
"BA setup with unknown TDLS peer %pM!\n",
peer_mac);
- spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
return -1;
}
if (sta_ptr->is_11ac_enabled)
tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE;
- spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
}
block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) |
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index f275675..2ee268b 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -84,8 +84,6 @@
{
struct mwifiex_tx_ba_stream_tbl *tx_tbl;
- if (is_broadcast_ether_addr(ptr->ra))
- return false;
tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra);
if (tx_tbl)
return tx_tbl->amsdu;
@@ -98,8 +96,6 @@
mwifiex_is_ampdu_allowed(struct mwifiex_private *priv,
struct mwifiex_ra_list_tbl *ptr, int tid)
{
- if (is_broadcast_ether_addr(ptr->ra))
- return false;
if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) {
return mwifiex_is_station_ampdu_allowed(priv, ptr, tid);
} else {
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index d73fda3..4005707 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -196,7 +196,6 @@
mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win);
del_timer_sync(&tbl->timer_context.timer);
- tbl->timer_context.timer_is_set = false;
spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
list_del(&tbl->list);
@@ -298,7 +297,6 @@
(struct reorder_tmr_cnxt *) context;
int start_win, seq_num;
- ctx->timer_is_set = false;
seq_num = mwifiex_11n_find_last_seq_num(ctx);
if (seq_num < 0)
@@ -351,7 +349,6 @@
new_node->init_win = seq_num;
new_node->flags = 0;
- spin_lock_irqsave(&priv->sta_list_spinlock, flags);
if (mwifiex_queuing_ra_based(priv)) {
dev_dbg(priv->adapter->dev,
"info: AP/ADHOC:last_seq=%d start_win=%d\n",
@@ -368,7 +365,6 @@
else
last_seq = priv->rx_seq[tid];
}
- spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
last_seq >= new_node->start_win) {
@@ -389,7 +385,6 @@
new_node->timer_context.ptr = new_node;
new_node->timer_context.priv = priv;
- new_node->timer_context.timer_is_set = false;
init_timer(&new_node->timer_context.timer);
new_node->timer_context.timer.function = mwifiex_flush_data;
@@ -404,22 +399,6 @@
spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
}
-static void
-mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl)
-{
- u32 min_flush_time;
-
- if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32)
- min_flush_time = MIN_FLUSH_TIMER_15_MS;
- else
- min_flush_time = MIN_FLUSH_TIMER_MS;
-
- mod_timer(&tbl->timer_context.timer,
- jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size));
-
- tbl->timer_context.timer_is_set = true;
-}
-
/*
* This function prepares command for adding a BA request.
*
@@ -457,26 +436,22 @@
u32 rx_win_size = priv->add_ba_param.rx_win_size;
u8 tid;
int win_size;
- unsigned long flags;
uint16_t block_ack_param_set;
if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
priv->adapter->is_hw_11ac_capable &&
memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) {
- spin_lock_irqsave(&priv->sta_list_spinlock, flags);
sta_ptr = mwifiex_get_sta_entry(priv,
cmd_addba_req->peer_mac_addr);
if (!sta_ptr) {
dev_warn(priv->adapter->dev,
"BA setup with unknown TDLS peer %pM!\n",
cmd_addba_req->peer_mac_addr);
- spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
return -1;
}
if (sta_ptr->is_11ac_enabled)
rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE;
- spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
}
cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP);
@@ -548,31 +523,31 @@
u8 *ta, u8 pkt_type, void *payload)
{
struct mwifiex_rx_reorder_tbl *tbl;
- int prev_start_win, start_win, end_win, win_size;
+ int start_win, end_win, win_size;
u16 pkt_index;
bool init_window_shift = false;
- int ret = 0;
tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
if (!tbl) {
if (pkt_type != PKT_TYPE_BAR)
mwifiex_11n_dispatch_pkt(priv, payload);
- return ret;
+ return 0;
}
if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) {
mwifiex_11n_dispatch_pkt(priv, payload);
- return ret;
+ return 0;
}
start_win = tbl->start_win;
- prev_start_win = start_win;
win_size = tbl->win_size;
end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1);
if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) {
init_window_shift = true;
tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT;
}
+ mod_timer(&tbl->timer_context.timer,
+ jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size));
if (tbl->flags & RXREOR_FORCE_NO_DROP) {
dev_dbg(priv->adapter->dev,
@@ -593,14 +568,11 @@
if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {
if (seq_num >= ((start_win + TWOPOW11) &
(MAX_TID_VALUE - 1)) &&
- seq_num < start_win) {
- ret = -1;
- goto done;
- }
+ seq_num < start_win)
+ return -1;
} else if ((seq_num < start_win) ||
- (seq_num >= (start_win + TWOPOW11))) {
- ret = -1;
- goto done;
+ (seq_num > (start_win + TWOPOW11))) {
+ return -1;
}
}
@@ -629,10 +601,8 @@
else
pkt_index = (seq_num+MAX_TID_VALUE) - start_win;
- if (tbl->rx_reorder_ptr[pkt_index]) {
- ret = -1;
- goto done;
- }
+ if (tbl->rx_reorder_ptr[pkt_index])
+ return -1;
tbl->rx_reorder_ptr[pkt_index] = payload;
}
@@ -643,11 +613,7 @@
*/
mwifiex_11n_scan_and_dispatch(priv, tbl);
-done:
- if (!tbl->timer_context.timer_is_set ||
- prev_start_win != tbl->start_win)
- mwifiex_11n_rxreorder_timer_restart(tbl);
- return ret;
+ return 0;
}
/*
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 63ecea8..3a87bb0 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -21,8 +21,6 @@
#define _MWIFIEX_11N_RXREORDER_H_
#define MIN_FLUSH_TIMER_MS 50
-#define MIN_FLUSH_TIMER_15_MS 15
-#define MWIFIEX_BA_WIN_SIZE_32 32
#define PKT_TYPE_BAR 0xE7
#define MAX_TID_VALUE (2 << 11)
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig
index 689cf90..43e31bf 100644
--- a/drivers/net/wireless/mwifiex/Kconfig
+++ b/drivers/net/wireless/mwifiex/Kconfig
@@ -34,7 +34,7 @@
mwifiex_pcie.
config MWIFIEX_USB
- tristate "Marvell WiFi-Ex Driver for USB8766/8797/8897"
+ tristate "Marvell WiFi-Ex Driver for USB8797/8897"
depends on m
depends on MWIFIEX && USB
depends on FW_LOADER
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 4a66a65..0dd6729 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -194,18 +194,11 @@
tx_info->pkt_len = pkt_len;
mwifiex_form_mgmt_frame(skb, buf, len);
- *cookie = prandom_u32() | 1;
-
- if (ieee80211_is_action(mgmt->frame_control))
- skb = mwifiex_clone_skb_for_tx_status(priv,
- skb,
- MWIFIEX_BUF_FLAG_ACTION_TX_STATUS, cookie);
- else
- cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true,
- GFP_ATOMIC);
-
mwifiex_queue_tx_pkt(priv, skb);
+ *cookie = prandom_u32() | 1;
+ cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_ATOMIC);
+
wiphy_dbg(wiphy, "info: management frame transmitted\n");
return 0;
}
@@ -999,52 +992,6 @@
return mwifiex_dump_station_info(priv, sinfo);
}
-static int
-mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
- int idx, struct survey_info *survey)
-{
- struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
- struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats;
- enum ieee80211_band band;
-
- dev_dbg(priv->adapter->dev, "dump_survey idx=%d\n", idx);
-
- memset(survey, 0, sizeof(struct survey_info));
-
- if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
- priv->media_connected && idx == 0) {
- u8 curr_bss_band = priv->curr_bss_params.band;
- u32 chan = priv->curr_bss_params.bss_descriptor.channel;
-
- band = mwifiex_band_to_radio_type(curr_bss_band);
- survey->channel = ieee80211_get_channel(wiphy,
- ieee80211_channel_to_frequency(chan, band));
-
- if (priv->bcn_nf_last) {
- survey->filled = SURVEY_INFO_NOISE_DBM;
- survey->noise = priv->bcn_nf_last;
- }
- return 0;
- }
-
- if (idx >= priv->adapter->num_in_chan_stats)
- return -ENOENT;
-
- if (!pchan_stats[idx].cca_scan_dur)
- return 0;
-
- band = pchan_stats[idx].bandcfg;
- survey->channel = ieee80211_get_channel(wiphy,
- ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band));
- survey->filled = SURVEY_INFO_NOISE_DBM |
- SURVEY_INFO_CHANNEL_TIME | SURVEY_INFO_CHANNEL_TIME_BUSY;
- survey->noise = pchan_stats[idx].noise;
- survey->channel_time = pchan_stats[idx].cca_scan_dur;
- survey->channel_time_busy = pchan_stats[idx].cca_busy_dur;
-
- return 0;
-}
-
/* Supported rates to be advertised to the cfg80211 */
static struct ieee80211_rate mwifiex_rates[] = {
{.bitrate = 10, .hw_value = 2, },
@@ -1292,34 +1239,36 @@
*/
static int
mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
- struct station_del_parameters *params)
+ const u8 *mac)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct mwifiex_sta_node *sta_node;
- u8 deauth_mac[ETH_ALEN];
unsigned long flags;
if (list_empty(&priv->sta_list) || !priv->bss_started)
return 0;
- if (!params->mac || is_broadcast_ether_addr(params->mac))
- return 0;
-
- wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, params->mac);
-
- memset(deauth_mac, 0, ETH_ALEN);
-
- spin_lock_irqsave(&priv->sta_list_spinlock, flags);
- sta_node = mwifiex_get_sta_entry(priv, params->mac);
- if (sta_node)
- ether_addr_copy(deauth_mac, params->mac);
- spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
-
- if (is_valid_ether_addr(deauth_mac)) {
- if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
- HostCmd_ACT_GEN_SET, 0,
- deauth_mac, true))
- return -1;
+ if (!mac || is_broadcast_ether_addr(mac)) {
+ wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__);
+ list_for_each_entry(sta_node, &priv->sta_list, list) {
+ if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
+ HostCmd_ACT_GEN_SET, 0,
+ sta_node->mac_addr, true))
+ return -1;
+ mwifiex_uap_del_sta_data(priv, sta_node);
+ }
+ } else {
+ wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, mac);
+ spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+ sta_node = mwifiex_get_sta_entry(priv, mac);
+ spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+ if (sta_node) {
+ if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH,
+ HostCmd_ACT_GEN_SET, 0,
+ sta_node->mac_addr, true))
+ return -1;
+ mwifiex_uap_del_sta_data(priv, sta_node);
+ }
}
return 0;
@@ -1810,10 +1759,6 @@
dev_dbg(priv->adapter->dev,
"info: associated to bssid %pM successfully\n",
priv->cfg_bssid);
- if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
- priv->adapter->auto_tdls &&
- priv->bss_type == MWIFIEX_BSS_TYPE_STA)
- mwifiex_setup_auto_tdls_timer(priv);
} else {
dev_dbg(priv->adapter->dev,
"info: association to bssid %pM failed\n",
@@ -2685,13 +2630,11 @@
dev_dbg(priv->adapter->dev,
"Send TDLS Setup Request to %pM status_code=%d\n", peer,
status_code);
- mwifiex_add_auto_tdls_peer(priv, peer);
ret = mwifiex_send_tdls_data_frame(priv, peer, action_code,
dialog_token, status_code,
extra_ies, extra_ies_len);
break;
case WLAN_TDLS_SETUP_RESPONSE:
- mwifiex_add_auto_tdls_peer(priv, peer);
dev_dbg(priv->adapter->dev,
"Send TDLS Setup Response to %pM status_code=%d\n",
peer, status_code);
@@ -2836,7 +2779,6 @@
.disconnect = mwifiex_cfg80211_disconnect,
.get_station = mwifiex_cfg80211_get_station,
.dump_station = mwifiex_cfg80211_dump_station,
- .dump_survey = mwifiex_cfg80211_dump_survey,
.set_wiphy_params = mwifiex_cfg80211_set_wiphy_params,
.join_ibss = mwifiex_cfg80211_join_ibss,
.leave_ibss = mwifiex_cfg80211_leave_ibss,
@@ -2898,25 +2840,6 @@
.max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN,
};
-int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter)
-{
- u32 n_channels_bg, n_channels_a = 0;
-
- n_channels_bg = mwifiex_band_2ghz.n_channels;
-
- if (adapter->config_bands & BAND_A)
- n_channels_a = mwifiex_band_5ghz.n_channels;
-
- adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a);
- adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) *
- adapter->num_in_chan_stats);
-
- if (!adapter->chan_stats)
- return -ENOMEM;
-
- return 0;
-}
-
/*
* This function registers the device with CFG802.11 subsystem.
*
@@ -2992,9 +2915,6 @@
NL80211_FEATURE_INACTIVITY_TIMER |
NL80211_FEATURE_NEED_OBSS_SCAN;
- if (adapter->fw_api_ver == MWIFIEX_FW_V15)
- wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
-
/* Reserve space for mwifiex specific private data for BSS */
wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv);
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 343240a..9c054d2 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -76,8 +76,6 @@
#define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0)
#define MWIFIEX_BUF_FLAG_BRIDGED_PKT BIT(1)
#define MWIFIEX_BUF_FLAG_TDLS_PKT BIT(2)
-#define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS BIT(3)
-#define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS BIT(4)
#define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024
#define MWIFIEX_BRIDGED_PKTS_THR_LOW 128
@@ -87,11 +85,6 @@
#define MWIFIEX_TDLS_CREATE_LINK 0x02
#define MWIFIEX_TDLS_CONFIG_LINK 0x03
-#define MWIFIEX_TDLS_RSSI_HIGH 50
-#define MWIFIEX_TDLS_RSSI_LOW 55
-#define MWIFIEX_TDLS_MAX_FAIL_COUNT 4
-#define MWIFIEX_AUTO_TDLS_IDLE_TIME 10
-
enum mwifiex_bss_type {
MWIFIEX_BSS_TYPE_STA = 0,
MWIFIEX_BSS_TYPE_UAP = 1,
@@ -161,8 +154,6 @@
u8 bss_num;
u8 bss_type;
u32 pkt_len;
- u8 ack_frame_id;
- u64 cookie;
};
enum mwifiex_wmm_ac_e {
@@ -194,14 +185,4 @@
u8 ar_tha[ETH_ALEN];
u8 ar_tip[4];
} __packed;
-
-struct mwifiex_chan_stats {
- u8 chan_num;
- u8 bandcfg;
- u8 flags;
- s8 noise;
- u16 total_bss;
- u16 cca_scan_dur;
- u16 cca_busy_dur;
-} __packed;
#endif /* !_MWIFIEX_DECL_H_ */
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index fb5936e..1eb6173 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -172,7 +172,6 @@
#define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194)
#define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197)
#define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199)
-#define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 198)
#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048
@@ -494,7 +493,6 @@
#define EVENT_TDLS_GENERIC_EVENT 0x00000052
#define EVENT_EXT_SCAN_REPORT 0x00000058
#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
-#define EVENT_TX_STATUS_REPORT 0x00000074
#define EVENT_ID_MASK 0xffff
#define BSS_NUM_MASK 0xf
@@ -543,7 +541,6 @@
#define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08
#define MWIFIEX_TXPD_FLAGS_TDLS_PACKET 0x10
#define MWIFIEX_RXPD_FLAGS_TDLS_PACKET 0x01
-#define MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS 0x20
struct txpd {
u8 bss_type;
@@ -555,9 +552,7 @@
u8 priority;
u8 flags;
u8 pkt_delay_2ms;
- u8 reserved1[2];
- u8 tx_token_id;
- u8 reserved[2];
+ u8 reserved1;
} __packed;
struct rxpd {
@@ -588,7 +583,6 @@
* [Bit 7] Reserved
*/
u8 ht_info;
- u8 reserved[3];
u8 flags;
} __packed;
@@ -602,9 +596,8 @@
u8 priority;
u8 flags;
u8 pkt_delay_2ms;
- u8 reserved1[2];
- u8 tx_token_id;
- u8 reserved[2];
+ u8 reserved1;
+ __le32 reserved2;
};
struct uap_rxpd {
@@ -618,16 +611,6 @@
u8 reserved1;
};
-struct mwifiex_fw_chan_stats {
- u8 chan_num;
- u8 bandcfg;
- u8 flags;
- s8 noise;
- __le16 total_bss;
- __le16 cca_scan_dur;
- __le16 cca_busy_dur;
-} __packed;
-
enum mwifiex_chan_scan_mode_bitmasks {
MWIFIEX_PASSIVE_SCAN = BIT(0),
MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
@@ -677,11 +660,6 @@
__le16 chan_gap;
} __packed;
-struct mwifiex_ietypes_chanstats {
- struct mwifiex_ie_types_header header;
- struct mwifiex_fw_chan_stats chanstats[0];
-} __packed;
-
struct mwifiex_ie_types_wildcard_ssid_params {
struct mwifiex_ie_types_header header;
u8 max_ssid_length;
@@ -1229,12 +1207,6 @@
u8 num_of_set;
} __packed;
-struct tx_status_event {
- u8 packet_type;
- u8 tx_token_id;
- u8 status;
-} __packed;
-
#define MWIFIEX_USER_SCAN_CHAN_MAX 50
#define MWIFIEX_MAX_SSID_LIST_LENGTH 10
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 520ad4a..580aa45 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -137,7 +137,6 @@
priv->csa_expire_time = 0;
priv->del_list_idx = 0;
priv->hs2_enabled = false;
- priv->check_tdls_tx = false;
memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID);
return mwifiex_add_bss_prio_tbl(priv);
@@ -367,7 +366,6 @@
list_del(&priv->tx_ba_stream_tbl_ptr);
list_del(&priv->rx_reorder_tbl_ptr);
list_del(&priv->sta_list);
- list_del(&priv->auto_tdls_list);
}
}
}
@@ -436,7 +434,6 @@
spin_lock_init(&priv->wmm.ra_list_spinlock);
spin_lock_init(&priv->curr_bcn_buf_lock);
spin_lock_init(&priv->sta_list_spinlock);
- spin_lock_init(&priv->auto_tdls_lock);
}
}
@@ -452,6 +449,7 @@
spin_lock_init(&adapter->scan_pending_q_lock);
spin_lock_init(&adapter->rx_proc_lock);
+ skb_queue_head_init(&adapter->usb_rx_data_q);
skb_queue_head_init(&adapter->rx_data_q);
for (i = 0; i < adapter->priv_num; ++i) {
@@ -468,14 +466,10 @@
INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
INIT_LIST_HEAD(&priv->sta_list);
- INIT_LIST_HEAD(&priv->auto_tdls_list);
skb_queue_head_init(&priv->tdls_txq);
spin_lock_init(&priv->tx_ba_stream_tbl_lock);
spin_lock_init(&priv->rx_reorder_tbl_lock);
-
- spin_lock_init(&priv->ack_status_lock);
- idr_init(&priv->ack_status_frames);
}
return 0;
@@ -652,7 +646,6 @@
if (adapter->priv[i]) {
priv = adapter->priv[i];
- mwifiex_clean_auto_tdls(priv);
mwifiex_clean_txrx(priv);
mwifiex_delete_bss_prio_tbl(priv);
}
@@ -675,6 +668,19 @@
spin_lock(&adapter->mwifiex_lock);
+ if (adapter->if_ops.data_complete) {
+ while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) {
+ struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
+
+ priv = adapter->priv[rx_info->bss_num];
+ if (priv)
+ priv->stats.rx_dropped++;
+
+ dev_kfree_skb_any(skb);
+ adapter->if_ops.data_complete(adapter);
+ }
+ }
+
mwifiex_adapter_cleanup(adapter);
spin_unlock(&adapter->mwifiex_lock);
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 411a6c2..8d6c259 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -880,7 +880,9 @@
/* Set Capability info */
bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS;
- tmp_cap = WLAN_CAPABILITY_IBSS;
+ tmp_cap = le16_to_cpu(adhoc_start->cap_info_bitmap);
+ tmp_cap &= ~WLAN_CAPABILITY_ESS;
+ tmp_cap |= WLAN_CAPABILITY_IBSS;
/* Set up privacy in bss_desc */
if (priv->sec_info.encryption_mode) {
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 875eb77..6044804 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -28,11 +28,6 @@
static char *cal_data_cfg;
module_param(cal_data_cfg, charp, 0);
-static unsigned short driver_mode;
-module_param(driver_mode, ushort, 0);
-MODULE_PARM_DESC(driver_mode,
- "station=0x1(default), ap-sta=0x3, station-p2p=0x5, ap-sta-p2p=0x7");
-
/*
* This function registers the device and performs all the necessary
* initializations.
@@ -127,7 +122,6 @@
}
}
- vfree(adapter->chan_stats);
kfree(adapter);
return 0;
}
@@ -149,11 +143,8 @@
/* Check for Rx data */
while ((skb = skb_dequeue(&adapter->rx_data_q))) {
atomic_dec(&adapter->rx_pending);
- if ((adapter->delay_main_work ||
- adapter->iface_type == MWIFIEX_USB) &&
+ if (adapter->delay_main_work &&
(atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) {
- if (adapter->if_ops.submit_rem_rx_urbs)
- adapter->if_ops.submit_rem_rx_urbs(adapter);
adapter->delay_main_work = false;
queue_work(adapter->workqueue, &adapter->main_work);
}
@@ -186,6 +177,7 @@
{
int ret = 0;
unsigned long flags;
+ struct sk_buff *skb;
spin_lock_irqsave(&adapter->main_proc_lock, flags);
@@ -203,15 +195,12 @@
(adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY))
break;
- /* For non-USB interfaces, If we process interrupts first, it
- * would increase RX pending even further. Avoid this by
- * checking if rx_pending has crossed high threshold and
- * schedule rx work queue and then process interrupts.
- * For USB interface, there are no interrupts. We already have
- * HIGH_RX_PENDING check in usb.c
+ /* If we process interrupts first, it would increase RX pending
+ * even further. Avoid this by checking if rx_pending has
+ * crossed high threshold and schedule rx work queue
+ * and then process interrupts
*/
- if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING &&
- adapter->iface_type != MWIFIEX_USB) {
+ if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING) {
adapter->delay_main_work = true;
if (!adapter->rx_processing)
queue_work(adapter->rx_workqueue,
@@ -263,6 +252,11 @@
}
}
+ /* Check Rx data for USB */
+ if (adapter->iface_type == MWIFIEX_USB)
+ while ((skb = skb_dequeue(&adapter->usb_rx_data_q)))
+ mwifiex_handle_rx_packet(adapter, skb);
+
/* Check for event */
if (adapter->event_received) {
adapter->event_received = false;
@@ -453,16 +447,6 @@
goto err_init_fw;
}
- if (mwifiex_init_channel_scan_gap(adapter)) {
- dev_err(adapter->dev, "could not init channel stats table\n");
- goto err_init_fw;
- }
-
- if (driver_mode) {
- driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK;
- driver_mode |= MWIFIEX_DRIVER_MODE_STA;
- }
-
rtnl_lock();
/* Create station interface by default */
wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d",
@@ -472,28 +456,6 @@
rtnl_unlock();
goto err_add_intf;
}
-
- if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) {
- wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d",
- NL80211_IFTYPE_AP, NULL, NULL);
- if (IS_ERR(wdev)) {
- dev_err(adapter->dev, "cannot create AP interface\n");
- rtnl_unlock();
- goto err_add_intf;
- }
- }
-
- if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) {
- wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d",
- NL80211_IFTYPE_P2P_CLIENT, NULL,
- NULL);
- if (IS_ERR(wdev)) {
- dev_err(adapter->dev,
- "cannot create p2p client interface\n");
- rtnl_unlock();
- goto err_add_intf;
- }
- }
rtnl_unlock();
mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
@@ -608,48 +570,6 @@
return 0;
}
-struct sk_buff *
-mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
- struct sk_buff *skb, u8 flag, u64 *cookie)
-{
- struct sk_buff *orig_skb = skb;
- struct mwifiex_txinfo *tx_info, *orig_tx_info;
-
- skb = skb_clone(skb, GFP_ATOMIC);
- if (skb) {
- unsigned long flags;
- int id;
-
- spin_lock_irqsave(&priv->ack_status_lock, flags);
- id = idr_alloc(&priv->ack_status_frames, orig_skb,
- 1, 0xff, GFP_ATOMIC);
- spin_unlock_irqrestore(&priv->ack_status_lock, flags);
-
- if (id >= 0) {
- tx_info = MWIFIEX_SKB_TXCB(skb);
- tx_info->ack_frame_id = id;
- tx_info->flags |= flag;
- orig_tx_info = MWIFIEX_SKB_TXCB(orig_skb);
- orig_tx_info->ack_frame_id = id;
- orig_tx_info->flags |= flag;
-
- if (flag == MWIFIEX_BUF_FLAG_ACTION_TX_STATUS && cookie)
- orig_tx_info->cookie = *cookie;
-
- } else if (skb_shared(skb)) {
- kfree_skb(orig_skb);
- } else {
- kfree_skb(skb);
- skb = orig_skb;
- }
- } else {
- /* couldn't clone -- lose tx status ... */
- skb = orig_skb;
- }
-
- return skb;
-}
-
/*
* CFG802.11 network device handler for data transmission.
*/
@@ -659,9 +579,6 @@
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct sk_buff *new_skb;
struct mwifiex_txinfo *tx_info;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
- bool multicast;
-#endif
dev_dbg(priv->adapter->dev, "data: %lu BSS(%d-%d): Data <= kernel\n",
jiffies, priv->bss_type, priv->bss_num);
@@ -702,17 +619,6 @@
tx_info->bss_type = priv->bss_type;
tx_info->pkt_len = skb->len;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
- multicast = is_multicast_ether_addr(skb->data);
-
- if (unlikely(!multicast && skb->sk &&
- skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS &&
- priv->adapter->fw_api_ver == MWIFIEX_FW_V15))
- skb = mwifiex_clone_skb_for_tx_status(priv,
- skb,
- MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS, NULL);
-#endif
-
/* Record the current time the packet was queued; used to
* determine the amount of time the packet was queued in
* the driver before it was sent to the firmware.
@@ -722,13 +628,6 @@
*/
__net_timestamp(skb);
- if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
- priv->bss_type == MWIFIEX_BSS_TYPE_STA &&
- !ether_addr_equal_unaligned(priv->cfg_bssid, skb->data)) {
- if (priv->adapter->auto_tdls && priv->check_tdls_tx)
- mwifiex_tdls_check_tx(priv, skb);
- }
-
mwifiex_queue_tx_pkt(priv, skb);
return 0;
@@ -969,7 +868,7 @@
adapter->cmd_wait_q.status = 0;
adapter->scan_wait_q_woken = false;
- if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB) {
+ if (num_possible_cpus() > 1) {
adapter->rx_work_enabled = true;
pr_notice("rx work enabled, cpus %d\n", num_possible_cpus());
}
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index e66993c..e263574 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -34,7 +34,6 @@
#include <linux/firmware.h>
#include <linux/ctype.h>
#include <linux/of.h>
-#include <linux/idr.h>
#include "decl.h"
#include "ioctl.h"
@@ -49,11 +48,6 @@
MWIFIEX_SYNC_CMD
};
-#define MWIFIEX_DRIVER_MODE_STA BIT(0)
-#define MWIFIEX_DRIVER_MODE_UAP BIT(1)
-#define MWIFIEX_DRIVER_MODE_P2P BIT(2)
-#define MWIFIEX_DRIVER_MODE_BITMASK (BIT(0) | BIT(1) | BIT(2))
-
#define MWIFIEX_MAX_AP 64
#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ)
@@ -112,7 +106,10 @@
*/
#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \
adapter->event_received || \
- adapter->data_received)
+ ((adapter->iface_type != MWIFIEX_USB) && \
+ adapter->data_received) || \
+ ((adapter->iface_type == MWIFIEX_USB) && \
+ !skb_queue_empty(&adapter->usb_rx_data_q)))
#define MWIFIEX_TYPE_CMD 1
#define MWIFIEX_TYPE_DATA 0
@@ -507,11 +504,8 @@
struct mwifiex_wmm_desc wmm;
atomic_t wmm_tx_pending[IEEE80211_NUM_ACS];
struct list_head sta_list;
- /* spin lock for associated station/TDLS peers list */
+ /* spin lock for associated station list */
spinlock_t sta_list_spinlock;
- struct list_head auto_tdls_list;
- /* spin lock for auto TDLS peer list */
- spinlock_t auto_tdls_lock;
struct list_head tx_ba_stream_tbl_ptr;
/* spin lock for tx_ba_stream_tbl_ptr queue */
spinlock_t tx_ba_stream_tbl_lock;
@@ -576,12 +570,6 @@
bool hs2_enabled;
struct station_parameters *sta_params;
struct sk_buff_head tdls_txq;
- u8 check_tdls_tx;
- struct timer_list auto_tdls_timer;
- bool auto_tdls_timer_active;
- struct idr ack_status_frames;
- /* spin lock for ack status */
- spinlock_t ack_status_lock;
};
enum mwifiex_ba_status {
@@ -604,7 +592,6 @@
struct timer_list timer;
struct mwifiex_rx_reorder_tbl *ptr;
struct mwifiex_private *priv;
- u8 timer_is_set;
};
struct mwifiex_rx_reorder_tbl {
@@ -682,17 +669,6 @@
struct mwifiex_tdls_capab tdls_cap;
};
-struct mwifiex_auto_tdls_peer {
- struct list_head list;
- u8 mac_addr[ETH_ALEN];
- u8 tdls_status;
- int rssi;
- long rssi_jiffies;
- u8 failure_count;
- u8 do_discover;
- u8 do_setup;
-};
-
struct mwifiex_if_ops {
int (*init_if) (struct mwifiex_adapter *);
void (*cleanup_if) (struct mwifiex_adapter *);
@@ -713,13 +689,13 @@
void (*cleanup_mpa_buf) (struct mwifiex_adapter *);
int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *);
int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *);
+ int (*data_complete) (struct mwifiex_adapter *);
int (*init_fw_port) (struct mwifiex_adapter *);
int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
void (*card_reset) (struct mwifiex_adapter *);
void (*fw_dump)(struct mwifiex_adapter *);
int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
void (*iface_work)(struct work_struct *work);
- void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter);
};
struct mwifiex_adapter {
@@ -790,6 +766,7 @@
spinlock_t scan_pending_q_lock;
/* spin lock for RX processing routine */
spinlock_t rx_proc_lock;
+ struct sk_buff_head usb_rx_data_q;
u32 scan_processing;
u16 region_code;
struct mwifiex_802_11d_domain_reg domain_reg;
@@ -867,10 +844,6 @@
u8 curr_mem_idx;
bool scan_chan_gap_enabled;
struct sk_buff_head rx_data_q;
- struct mwifiex_chan_stats *chan_stats;
- u32 num_in_chan_stats;
- int survey_idx;
- bool auto_tdls;
};
int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -975,8 +948,6 @@
int mwifiex_process_sta_event(struct mwifiex_private *);
int mwifiex_process_uap_event(struct mwifiex_private *);
void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
-void mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv,
- const u8 *ra_addr);
void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
@@ -1059,8 +1030,7 @@
int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
struct host_cmd_ds_command *cmd,
void *data_buf);
-int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
- struct host_cmd_ds_command *resp);
+int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv);
int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
void *buf);
@@ -1330,24 +1300,6 @@
u32 pri_chan, u8 chan_bw);
int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter);
-int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb);
-void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv);
-void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
- const u8 *mac, u8 link_status);
-void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
- u8 *mac, s8 snr, s8 nflr);
-void mwifiex_check_auto_tdls(unsigned long context);
-void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac);
-void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv);
-void mwifiex_clean_auto_tdls(struct mwifiex_private *priv);
-
-void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
- void *event_body);
-
-struct sk_buff *
-mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv,
- struct sk_buff *skb, u8 flag, u64 *cookie);
-
#ifdef CONFIG_DEBUG_FS
void mwifiex_debugfs_init(void);
void mwifiex_debugfs_remove(void);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 984a7a4..ca64d4c 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1623,7 +1623,7 @@
if (*bytes_left >= sizeof(beacon_size)) {
/* Extract & convert beacon size from command buffer */
- beacon_size = le16_to_cpu(*(__le16 *)(*bss_info));
+ memcpy(&beacon_size, *bss_info, sizeof(beacon_size));
*bytes_left -= sizeof(beacon_size);
*bss_info += sizeof(beacon_size);
}
@@ -1755,7 +1755,6 @@
{
struct mwifiex_adapter *adapter = priv->adapter;
- adapter->survey_idx = 0;
if (adapter->curr_cmd->wait_q_enabled) {
adapter->cmd_wait_q.status = 0;
if (!priv->scan_request) {
@@ -1977,53 +1976,10 @@
return 0;
}
-static void
-mwifiex_update_chan_statistics(struct mwifiex_private *priv,
- struct mwifiex_ietypes_chanstats *tlv_stat)
-{
- struct mwifiex_adapter *adapter = priv->adapter;
- u8 i, num_chan;
- struct mwifiex_fw_chan_stats *fw_chan_stats;
- struct mwifiex_chan_stats chan_stats;
-
- fw_chan_stats = (void *)((u8 *)tlv_stat +
- sizeof(struct mwifiex_ie_types_header));
- num_chan = le16_to_cpu(tlv_stat->header.len) /
- sizeof(struct mwifiex_chan_stats);
-
- for (i = 0 ; i < num_chan; i++) {
- chan_stats.chan_num = fw_chan_stats->chan_num;
- chan_stats.bandcfg = fw_chan_stats->bandcfg;
- chan_stats.flags = fw_chan_stats->flags;
- chan_stats.noise = fw_chan_stats->noise;
- chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
- chan_stats.cca_scan_dur =
- le16_to_cpu(fw_chan_stats->cca_scan_dur);
- chan_stats.cca_busy_dur =
- le16_to_cpu(fw_chan_stats->cca_busy_dur);
- dev_dbg(adapter->dev,
- "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
- chan_stats.chan_num,
- chan_stats.noise,
- chan_stats.total_bss,
- chan_stats.cca_scan_dur,
- chan_stats.cca_busy_dur);
- memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
- sizeof(struct mwifiex_chan_stats));
- fw_chan_stats++;
- }
-}
-
/* This function handles the command response of extended scan */
-int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
- struct host_cmd_ds_command *resp)
+int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv)
{
struct mwifiex_adapter *adapter = priv->adapter;
- struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
- struct mwifiex_ie_types_header *tlv;
- struct mwifiex_ietypes_chanstats *tlv_stat;
- u16 buf_left, type, len;
-
struct host_cmd_ds_command *cmd_ptr;
struct cmd_ctrl_node *cmd_node;
unsigned long cmd_flags, scan_flags;
@@ -2031,36 +1987,6 @@
dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n");
- ext_scan_resp = &resp->params.ext_scan;
-
- tlv = (void *)ext_scan_resp->tlv_buffer;
- buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
- - 1);
-
- while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
- type = le16_to_cpu(tlv->type);
- len = le16_to_cpu(tlv->len);
-
- if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
- dev_err(adapter->dev,
- "error processing scan response TLVs");
- break;
- }
-
- switch (type) {
- case TLV_TYPE_CHANNEL_STATS:
- tlv_stat = (void *)tlv;
- mwifiex_update_chan_statistics(priv, tlv_stat);
- break;
- default:
- break;
- }
-
- buf_left -= len + sizeof(struct mwifiex_ie_types_header);
- tlv = (void *)((u8 *)tlv + len +
- sizeof(struct mwifiex_ie_types_header));
- }
-
spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags);
spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags);
if (list_empty(&adapter->scan_pending_q)) {
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index a6ab0a8..78e36e5 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -106,7 +106,6 @@
card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size;
card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size;
card->supports_fw_dump = data->supports_fw_dump;
- card->auto_tdls = data->auto_tdls;
}
sdio_claim_host(func);
@@ -1881,7 +1880,6 @@
return -1;
}
- adapter->auto_tdls = card->auto_tdls;
return ret;
}
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h
index 54c0715..20cd9ad 100644
--- a/drivers/net/wireless/mwifiex/sdio.h
+++ b/drivers/net/wireless/mwifiex/sdio.h
@@ -246,7 +246,6 @@
u8 curr_wr_port;
u8 *mp_regs;
- u8 auto_tdls;
struct mwifiex_sdio_mpa_tx mpa_tx;
struct mwifiex_sdio_mpa_rx mpa_rx;
@@ -263,7 +262,6 @@
u16 tx_buf_size;
u32 mp_tx_agg_buf_size;
u32 mp_rx_agg_buf_size;
- u8 auto_tdls;
};
static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = {
@@ -389,7 +387,6 @@
.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
.supports_fw_dump = false,
- .auto_tdls = false,
};
static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = {
@@ -403,7 +400,6 @@
.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
.supports_fw_dump = false,
- .auto_tdls = false,
};
static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = {
@@ -417,7 +413,6 @@
.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K,
.supports_fw_dump = false,
- .auto_tdls = false,
};
static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = {
@@ -431,7 +426,6 @@
.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
.supports_fw_dump = true,
- .auto_tdls = false,
};
static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = {
@@ -445,7 +439,6 @@
.mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
.mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K,
.supports_fw_dump = false,
- .auto_tdls = true,
};
/*
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index b65e101..4aad446 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -983,7 +983,7 @@
adapter->curr_cmd->wait_q_enabled = false;
break;
case HostCmd_CMD_802_11_SCAN_EXT:
- ret = mwifiex_ret_802_11_scan_ext(priv, resp);
+ ret = mwifiex_ret_802_11_scan_ext(priv);
adapter->curr_cmd->wait_q_enabled = false;
break;
case HostCmd_CMD_802_11_BG_SCAN_QUERY:
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index b8c171d..f1c240e 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -55,13 +55,9 @@
priv->scan_block = false;
if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) &&
- ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) {
+ ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info))
mwifiex_disable_all_tdls_links(priv);
- if (priv->adapter->auto_tdls)
- mwifiex_clean_auto_tdls(priv);
- }
-
/* Free Tx and Rx packets, report disconnect to upper layer */
mwifiex_clean_txrx(priv);
@@ -167,6 +163,9 @@
NL80211_TDLS_TEARDOWN,
le16_to_cpu(tdls_evt->u.reason_code),
GFP_KERNEL);
+ ret = mwifiex_tdls_oper(priv, tdls_evt->peer_mac,
+ MWIFIEX_TDLS_DISABLE_LINK);
+ queue_work(adapter->workqueue, &adapter->main_work);
break;
default:
break;
@@ -504,11 +503,6 @@
ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
break;
- case EVENT_TX_STATUS_REPORT:
- dev_dbg(adapter->dev, "event: TX_STATUS Report\n");
- mwifiex_parse_tx_status_event(priv, adapter->event_body);
- break;
-
default:
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
eventcause);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 1626868..92f3eb8 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -1026,12 +1026,12 @@
int max_len)
{
union {
- __le32 l;
+ u32 l;
u8 c[4];
} ver;
char fw_ver[32];
- ver.l = cpu_to_le32(adapter->fw_release_number);
+ ver.l = adapter->fw_release_number;
sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
snprintf(version, max_len, driver_version, fw_ver);
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 860fbb9..308e781 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -232,9 +232,6 @@
if (sta_ptr)
sta_ptr->rx_seq[local_rx_pd->priority] =
le16_to_cpu(local_rx_pd->seq_num);
- mwifiex_auto_tdls_update_peer_signal(priv, ta,
- local_rx_pd->snr,
- local_rx_pd->nf);
}
} else {
if (rx_pkt_type != PKT_TYPE_BAR)
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index b896d73..dab7b33 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -77,12 +77,6 @@
local_tx_pd->pkt_delay_2ms =
mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
- if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS ||
- tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) {
- local_tx_pd->tx_token_id = tx_info->ack_frame_id;
- local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS;
- }
-
if (local_tx_pd->priority <
ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
/*
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index 22884b4..e294907 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -24,7 +24,6 @@
#define TDLS_REQ_FIX_LEN 6
#define TDLS_RESP_FIX_LEN 8
#define TDLS_CONFIRM_FIX_LEN 6
-#define MWIFIEX_TDLS_WMM_INFO_SIZE 7
static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
const u8 *mac, u8 status)
@@ -368,55 +367,6 @@
*pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB;
}
-static void
-mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb)
-{
- struct ieee80211_wmm_param_ie *wmm;
- u8 ac_vi[] = {0x42, 0x43, 0x5e, 0x00};
- u8 ac_vo[] = {0x62, 0x32, 0x2f, 0x00};
- u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00};
- u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00};
-
- wmm = (void *)skb_put(skb, sizeof(*wmm));
- memset(wmm, 0, sizeof(*wmm));
-
- wmm->element_id = WLAN_EID_VENDOR_SPECIFIC;
- wmm->len = sizeof(*wmm) - 2;
- wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */
- wmm->oui[1] = 0x50;
- wmm->oui[2] = 0xf2;
- wmm->oui_type = 2; /* WME */
- wmm->oui_subtype = 1; /* WME param */
- wmm->version = 1; /* WME ver */
- wmm->qos_info = 0; /* U-APSD not in use */
-
- /* use default WMM AC parameters for TDLS link*/
- memcpy(&wmm->ac[0], ac_be, sizeof(ac_be));
- memcpy(&wmm->ac[1], ac_bk, sizeof(ac_bk));
- memcpy(&wmm->ac[2], ac_vi, sizeof(ac_vi));
- memcpy(&wmm->ac[3], ac_vo, sizeof(ac_vo));
-}
-
-static void
-mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb,
- u8 qosinfo)
-{
- u8 *buf;
-
- buf = (void *)skb_put(skb, MWIFIEX_TDLS_WMM_INFO_SIZE +
- sizeof(struct ieee_types_header));
-
- *buf++ = WLAN_EID_VENDOR_SPECIFIC;
- *buf++ = 7; /* len */
- *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */
- *buf++ = 0x50;
- *buf++ = 0xf2;
- *buf++ = 2; /* WME */
- *buf++ = 0; /* WME info */
- *buf++ = 1; /* WME ver */
- *buf++ = qosinfo; /* U-APSD no in use */
-}
-
static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
const u8 *peer, u8 action_code,
u8 dialog_token,
@@ -471,7 +421,6 @@
mwifiex_tdls_add_ext_capab(priv, skb);
mwifiex_tdls_add_qos_capab(skb);
- mwifiex_add_wmm_info_ie(priv, skb, 0);
break;
case WLAN_TDLS_SETUP_RESPONSE:
@@ -509,7 +458,6 @@
mwifiex_tdls_add_ext_capab(priv, skb);
mwifiex_tdls_add_qos_capab(skb);
- mwifiex_add_wmm_info_ie(priv, skb, 0);
break;
case WLAN_TDLS_SETUP_CONFIRM:
@@ -518,8 +466,6 @@
skb_put(skb, sizeof(tf->u.setup_cfm));
tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
tf->u.setup_cfm.dialog_token = dialog_token;
-
- mwifiex_tdls_add_wmm_param_ie(priv, skb);
if (priv->adapter->is_hw_11ac_capable) {
ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);
if (ret) {
@@ -598,7 +544,6 @@
sizeof(struct ieee_types_bss_co_2040) +
sizeof(struct ieee80211_ht_operation) +
sizeof(struct ieee80211_tdls_lnkie) +
- sizeof(struct ieee80211_wmm_param_ie) +
extra_ies_len;
if (priv->adapter->is_hw_11ac_capable)
@@ -1028,7 +973,6 @@
}
mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
- mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP);
memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN);
tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK;
return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER,
@@ -1073,8 +1017,6 @@
memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq));
mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE);
- mwifiex_auto_tdls_update_peer_status(priv, peer,
- TDLS_SETUP_COMPLETE);
} else {
dev_dbg(priv->adapter->dev,
"tdls: enable link %pM failed\n", peer);
@@ -1088,8 +1030,6 @@
mwifiex_del_sta_entry(priv, peer);
}
mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN);
- mwifiex_auto_tdls_update_peer_status(priv, peer,
- TDLS_NOT_SETUP);
return -1;
}
@@ -1157,231 +1097,3 @@
mwifiex_del_all_sta_list(priv);
}
-
-int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb)
-{
- struct mwifiex_auto_tdls_peer *peer;
- unsigned long flags;
- u8 mac[ETH_ALEN];
-
- ether_addr_copy(mac, skb->data);
-
- spin_lock_irqsave(&priv->auto_tdls_lock, flags);
- list_for_each_entry(peer, &priv->auto_tdls_list, list) {
- if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) {
- if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
- peer->tdls_status == TDLS_NOT_SETUP &&
- (peer->failure_count <
- MWIFIEX_TDLS_MAX_FAIL_COUNT)) {
- peer->tdls_status = TDLS_SETUP_INPROGRESS;
- dev_dbg(priv->adapter->dev,
- "setup TDLS link, peer=%pM rssi=%d\n",
- peer->mac_addr, peer->rssi);
-
- cfg80211_tdls_oper_request(priv->netdev,
- peer->mac_addr,
- NL80211_TDLS_SETUP,
- 0, GFP_ATOMIC);
- peer->do_setup = false;
- priv->check_tdls_tx = false;
- } else if (peer->failure_count <
- MWIFIEX_TDLS_MAX_FAIL_COUNT &&
- peer->do_discover) {
- mwifiex_send_tdls_data_frame(priv,
- peer->mac_addr,
- WLAN_TDLS_DISCOVERY_REQUEST,
- 1, 0, NULL, 0);
- peer->do_discover = false;
- }
- }
- }
- spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-
- return 0;
-}
-
-void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv)
-{
- struct mwifiex_auto_tdls_peer *peer, *tmp_node;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->auto_tdls_lock, flags);
- list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) {
- list_del(&peer->list);
- kfree(peer);
- }
-
- INIT_LIST_HEAD(&priv->auto_tdls_list);
- spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
- priv->check_tdls_tx = false;
-}
-
-void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac)
-{
- struct mwifiex_auto_tdls_peer *tdls_peer;
- unsigned long flags;
-
- if (!priv->adapter->auto_tdls)
- return;
-
- spin_lock_irqsave(&priv->auto_tdls_lock, flags);
- list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
- if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) {
- tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
- tdls_peer->rssi_jiffies = jiffies;
- spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
- return;
- }
- }
-
- /* create new TDLS peer */
- tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC);
- if (tdls_peer) {
- ether_addr_copy(tdls_peer->mac_addr, mac);
- tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS;
- tdls_peer->rssi_jiffies = jiffies;
- INIT_LIST_HEAD(&tdls_peer->list);
- list_add_tail(&tdls_peer->list, &priv->auto_tdls_list);
- dev_dbg(priv->adapter->dev, "Add auto TDLS peer= %pM to list\n",
- mac);
- }
-
- spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-}
-
-void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv,
- const u8 *mac, u8 link_status)
-{
- struct mwifiex_auto_tdls_peer *peer;
- unsigned long flags;
-
- if (!priv->adapter->auto_tdls)
- return;
-
- spin_lock_irqsave(&priv->auto_tdls_lock, flags);
- list_for_each_entry(peer, &priv->auto_tdls_list, list) {
- if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
- if ((link_status == TDLS_NOT_SETUP) &&
- (peer->tdls_status == TDLS_SETUP_INPROGRESS))
- peer->failure_count++;
- else if (link_status == TDLS_SETUP_COMPLETE)
- peer->failure_count = 0;
-
- peer->tdls_status = link_status;
- break;
- }
- }
- spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-}
-
-void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv,
- u8 *mac, s8 snr, s8 nflr)
-{
- struct mwifiex_auto_tdls_peer *peer;
- unsigned long flags;
-
- if (!priv->adapter->auto_tdls)
- return;
-
- spin_lock_irqsave(&priv->auto_tdls_lock, flags);
- list_for_each_entry(peer, &priv->auto_tdls_list, list) {
- if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) {
- peer->rssi = nflr - snr;
- peer->rssi_jiffies = jiffies;
- break;
- }
- }
- spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-}
-
-void mwifiex_check_auto_tdls(unsigned long context)
-{
- struct mwifiex_private *priv = (struct mwifiex_private *)context;
- struct mwifiex_auto_tdls_peer *tdls_peer;
- unsigned long flags;
- u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED;
-
- if (WARN_ON_ONCE(!priv || !priv->adapter)) {
- pr_err("mwifiex: %s: adapter or private structure is NULL\n",
- __func__);
- return;
- }
-
- if (unlikely(!priv->adapter->auto_tdls))
- return;
-
- if (!priv->auto_tdls_timer_active) {
- dev_dbg(priv->adapter->dev,
- "auto TDLS timer inactive; return");
- return;
- }
-
- priv->check_tdls_tx = false;
-
- if (list_empty(&priv->auto_tdls_list)) {
- mod_timer(&priv->auto_tdls_timer,
- jiffies +
- msecs_to_jiffies(MWIFIEX_TIMER_10S));
- return;
- }
-
- spin_lock_irqsave(&priv->auto_tdls_lock, flags);
- list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) {
- if ((jiffies - tdls_peer->rssi_jiffies) >
- (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) {
- tdls_peer->rssi = 0;
- tdls_peer->do_discover = true;
- priv->check_tdls_tx = true;
- }
-
- if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) ||
- !tdls_peer->rssi) &&
- tdls_peer->tdls_status == TDLS_SETUP_COMPLETE) {
- tdls_peer->tdls_status = TDLS_LINK_TEARDOWN;
- dev_dbg(priv->adapter->dev,
- "teardown TDLS link,peer=%pM rssi=%d\n",
- tdls_peer->mac_addr, -tdls_peer->rssi);
- tdls_peer->do_discover = true;
- priv->check_tdls_tx = true;
- cfg80211_tdls_oper_request(priv->netdev,
- tdls_peer->mac_addr,
- NL80211_TDLS_TEARDOWN,
- reason, GFP_ATOMIC);
- } else if (tdls_peer->rssi &&
- tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH &&
- tdls_peer->tdls_status == TDLS_NOT_SETUP &&
- tdls_peer->failure_count <
- MWIFIEX_TDLS_MAX_FAIL_COUNT) {
- priv->check_tdls_tx = true;
- tdls_peer->do_setup = true;
- dev_dbg(priv->adapter->dev,
- "check TDLS with peer=%pM rssi=%d\n",
- tdls_peer->mac_addr, -tdls_peer->rssi);
- }
- }
- spin_unlock_irqrestore(&priv->auto_tdls_lock, flags);
-
- mod_timer(&priv->auto_tdls_timer,
- jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
-}
-
-void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv)
-{
- init_timer(&priv->auto_tdls_timer);
- priv->auto_tdls_timer.function = mwifiex_check_auto_tdls;
- priv->auto_tdls_timer.data = (unsigned long)priv;
- priv->auto_tdls_timer_active = true;
- mod_timer(&priv->auto_tdls_timer,
- jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S));
-}
-
-void mwifiex_clean_auto_tdls(struct mwifiex_private *priv)
-{
- if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
- priv->adapter->auto_tdls &&
- priv->bss_type == MWIFIEX_BSS_TYPE_STA) {
- priv->auto_tdls_timer_active = false;
- del_timer(&priv->auto_tdls_timer);
- mwifiex_flush_auto_tdls_list(priv);
- }
-}
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 6ae1333..96a2126 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -64,6 +64,10 @@
else
ret = mwifiex_process_sta_rx_packet(priv, skb);
+ /* Decrement RX pending counter for each packet */
+ if (adapter->if_ops.data_complete)
+ adapter->if_ops.data_complete(adapter);
+
return ret;
}
EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
@@ -203,34 +207,3 @@
}
EXPORT_SYMBOL_GPL(mwifiex_write_data_complete);
-void mwifiex_parse_tx_status_event(struct mwifiex_private *priv,
- void *event_body)
-{
- struct tx_status_event *tx_status = (void *)priv->adapter->event_body;
- struct sk_buff *ack_skb;
- unsigned long flags;
- struct mwifiex_txinfo *tx_info;
-
- if (!tx_status->tx_token_id)
- return;
-
- spin_lock_irqsave(&priv->ack_status_lock, flags);
- ack_skb = idr_find(&priv->ack_status_frames, tx_status->tx_token_id);
- if (ack_skb)
- idr_remove(&priv->ack_status_frames, tx_status->tx_token_id);
- spin_unlock_irqrestore(&priv->ack_status_lock, flags);
-
- if (ack_skb) {
- tx_info = MWIFIEX_SKB_TXCB(ack_skb);
-
- if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS) {
- /* consumes ack_skb */
- skb_complete_wifi_ack(ack_skb, !tx_status->status);
- } else {
- cfg80211_mgmt_tx_status(priv->wdev, tx_info->cookie,
- ack_skb->data, ack_skb->len,
- !tx_status->status, GFP_ATOMIC);
- dev_kfree_skb_any(ack_skb);
- }
- }
-}
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index 0f347fd..300bab4 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -167,7 +167,7 @@
ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail,
params->beacon.tail_len);
if (ht_ie) {
- memcpy(&bss_cfg->ht_cap, ht_ie,
+ memcpy(&bss_cfg->ht_cap, ht_ie + 2,
sizeof(struct ieee80211_ht_cap));
cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info);
memset(&bss_cfg->ht_cap.mcs, 0,
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index c54a537..7c2b976 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -110,7 +110,6 @@
mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac);
mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac);
}
- mwifiex_wmm_del_peer_ra_list(priv, deauth_mac);
mwifiex_del_sta_entry(priv, deauth_mac);
break;
case EVENT_UAP_BSS_IDLE:
@@ -173,10 +172,6 @@
return mwifiex_handle_event_ext_scan_report(priv,
adapter->event_skb->data);
break;
- case EVENT_TX_STATUS_REPORT:
- dev_dbg(adapter->dev, "event: TX_STATUS Report\n");
- mwifiex_parse_tx_status_event(priv, adapter->event_body);
- break;
default:
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
eventcause);
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index be3a203..ec7309d 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -266,7 +266,6 @@
struct rx_packet_hdr *rx_pkt_hdr;
u16 rx_pkt_type;
u8 ta[ETH_ALEN], pkt_type;
- unsigned long flags;
struct mwifiex_sta_node *node;
uap_rx_pd = (struct uap_rxpd *)(skb->data);
@@ -295,12 +294,10 @@
memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
- spin_lock_irqsave(&priv->sta_list_spinlock, flags);
node = mwifiex_get_sta_entry(priv, ta);
if (node)
node->rx_seq[uap_rx_pd->priority] =
le16_to_cpu(uap_rx_pd->seq_num);
- spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
}
if (!priv->ap_11n_enabled ||
@@ -373,16 +370,10 @@
txpd->bss_num = priv->bss_num;
txpd->bss_type = priv->bss_type;
txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - len));
+
txpd->priority = (u8)skb->priority;
-
txpd->pkt_delay_2ms = mwifiex_wmm_compute_drv_pkt_delay(priv, skb);
- if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS ||
- tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) {
- txpd->tx_token_id = tx_info->ack_frame_id;
- txpd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS;
- }
-
if (txpd->priority < ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl))
/*
* Set the priority specific tx_control field, setting of 0 will
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c
index 1b56495..4371e12 100644
--- a/drivers/net/wireless/mwifiex/usb.c
+++ b/drivers/net/wireless/mwifiex/usb.c
@@ -27,11 +27,6 @@
static struct semaphore add_remove_card_sem;
static struct usb_device_id mwifiex_usb_table[] = {
- /* 8766 */
- {USB_DEVICE(USB8XXX_VID, USB8766_PID_1)},
- {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8766_PID_2,
- USB_CLASS_VENDOR_SPEC,
- USB_SUBCLASS_VENDOR_SPEC, 0xff)},
/* 8797 */
{USB_DEVICE(USB8XXX_VID, USB8797_PID_1)},
{USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2,
@@ -130,10 +125,8 @@
dev_err(dev, "DATA: skb->len too large\n");
return -1;
}
-
- skb_queue_tail(&adapter->rx_data_q, skb);
+ skb_queue_tail(&adapter->usb_rx_data_q, skb);
adapter->data_received = true;
- atomic_inc(&adapter->rx_pending);
break;
default:
dev_err(dev, "%s: unknown endport %#x\n", __func__, ep);
@@ -183,6 +176,7 @@
else
skb_put(skb, recv_length - skb->len);
+ atomic_inc(&adapter->rx_pending);
status = mwifiex_usb_recv(adapter, skb, context->ep);
dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n",
@@ -197,6 +191,7 @@
if (card->rx_cmd_ep == context->ep)
return;
} else {
+ atomic_dec(&adapter->rx_pending);
if (status == -1)
dev_err(adapter->dev,
"received data processing failed!\n");
@@ -227,13 +222,7 @@
else
size = MWIFIEX_RX_DATA_BUF_SIZE;
- if (card->rx_cmd_ep == context->ep) {
- mwifiex_usb_submit_rx_urb(context, size);
- } else {
- context->skb = NULL;
- if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING)
- mwifiex_usb_submit_rx_urb(context, size);
- }
+ mwifiex_usb_submit_rx_urb(context, size);
return;
}
@@ -359,12 +348,10 @@
/* PID_1 is used for firmware downloading only */
switch (id_product) {
- case USB8766_PID_1:
case USB8797_PID_1:
case USB8897_PID_1:
card->usb_boot_state = USB8XXX_FW_DNLD;
break;
- case USB8766_PID_2:
case USB8797_PID_2:
case USB8897_PID_2:
card->usb_boot_state = USB8XXX_FW_READY;
@@ -793,11 +780,6 @@
adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K;
strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME);
break;
- case USB8766_PID_1:
- case USB8766_PID_2:
- adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K;
- strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME);
- break;
case USB8797_PID_1:
case USB8797_PID_2:
default:
@@ -980,11 +962,19 @@
static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter,
struct sk_buff *skb)
{
+ atomic_dec(&adapter->rx_pending);
mwifiex_submit_rx_urb(adapter, MWIFIEX_USB_EP_CMD_EVENT);
return 0;
}
+static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter)
+{
+ atomic_dec(&adapter->rx_pending);
+
+ return 0;
+}
+
/* This function wakes up the card. */
static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter)
{
@@ -996,20 +986,6 @@
return 0;
}
-static void mwifiex_usb_submit_rem_rx_urbs(struct mwifiex_adapter *adapter)
-{
- struct usb_card_rec *card = (struct usb_card_rec *)adapter->card;
- int i;
- struct urb_context *ctx;
-
- for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) {
- if (card->rx_data_list[i].skb)
- continue;
- ctx = &card->rx_data_list[i];
- mwifiex_usb_submit_rx_urb(ctx, MWIFIEX_RX_DATA_BUF_SIZE);
- }
-}
-
static struct mwifiex_if_ops usb_ops = {
.register_dev = mwifiex_register_dev,
.unregister_dev = mwifiex_unregister_dev,
@@ -1020,8 +996,8 @@
.dnld_fw = mwifiex_usb_dnld_fw,
.cmdrsp_complete = mwifiex_usb_cmd_event_complete,
.event_complete = mwifiex_usb_cmd_event_complete,
+ .data_complete = mwifiex_usb_data_complete,
.host_to_card = mwifiex_usb_host_to_card,
- .submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs,
};
/* This function initializes the USB driver module.
@@ -1072,6 +1048,5 @@
MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION);
MODULE_VERSION(USB_VERSION);
MODULE_LICENSE("GPL v2");
-MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME);
MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME);
MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME);
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h
index a7cbba1..4c41c2a 100644
--- a/drivers/net/wireless/mwifiex/usb.h
+++ b/drivers/net/wireless/mwifiex/usb.h
@@ -24,8 +24,6 @@
#define USB8XXX_VID 0x1286
-#define USB8766_PID_1 0x2041
-#define USB8766_PID_2 0x2042
#define USB8797_PID_1 0x2043
#define USB8797_PID_2 0x2044
#define USB8897_PID_1 0x2045
@@ -39,7 +37,6 @@
#define MWIFIEX_RX_DATA_URB 6
#define MWIFIEX_USB_TIMEOUT 100
-#define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin"
#define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin"
#define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin"
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index b1768fb..ec79c49 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -141,38 +141,6 @@
return 0;
}
-static int
-mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len,
- struct rxpd *rx_pd)
-{
- u16 stype;
- u8 category, action_code;
- struct ieee80211_hdr *ieee_hdr = (void *)payload;
-
- stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE);
-
- switch (stype) {
- case IEEE80211_STYPE_ACTION:
- category = *(payload + sizeof(struct ieee80211_hdr));
- action_code = *(payload + sizeof(struct ieee80211_hdr) + 1);
- if (category == WLAN_CATEGORY_PUBLIC &&
- action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
- dev_dbg(priv->adapter->dev,
- "TDLS discovery response %pM nf=%d, snr=%d\n",
- ieee_hdr->addr2, rx_pd->nf, rx_pd->snr);
- mwifiex_auto_tdls_update_peer_signal(priv,
- ieee_hdr->addr2,
- rx_pd->snr,
- rx_pd->nf);
- }
- break;
- default:
- dev_dbg(priv->adapter->dev,
- "unknown mgmt frame subytpe %#x\n", stype);
- }
-
- return 0;
-}
/*
* This function processes the received management packet and send it
* to the kernel.
@@ -183,7 +151,6 @@
{
struct rxpd *rx_pd;
u16 pkt_len;
- struct ieee80211_hdr *ieee_hdr;
if (!skb)
return -1;
@@ -195,11 +162,6 @@
pkt_len = le16_to_cpu(rx_pd->rx_pkt_length);
- ieee_hdr = (void *)skb->data;
- if (ieee80211_is_mgmt(ieee_hdr->frame_control)) {
- mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr,
- pkt_len, rx_pd);
- }
/* Remove address4 */
memmove(skb->data + sizeof(struct ieee80211_hdr_3addr),
skb->data + sizeof(struct ieee80211_hdr),
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index ffffd2c..94c98a8 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -147,6 +147,9 @@
struct mwifiex_sta_node *node;
unsigned long flags;
+ spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+ node = mwifiex_get_sta_entry(priv, ra);
+ spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
for (i = 0; i < MAX_NUM_TID; ++i) {
ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
@@ -167,13 +170,10 @@
ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
}
} else {
- spin_lock_irqsave(&priv->sta_list_spinlock, flags);
- node = mwifiex_get_sta_entry(priv, ra);
ra_list->is_11n_enabled =
mwifiex_is_sta_11n_enabled(priv, node);
if (ra_list->is_11n_enabled)
ra_list->max_amsdu = node->max_amsdu;
- spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
}
dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
@@ -523,13 +523,6 @@
}
}
-static int mwifiex_free_ack_frame(int id, void *p, void *data)
-{
- pr_warn("Have pending ack frames!\n");
- kfree_skb(p);
- return 0;
-}
-
/*
* This function cleans up the Tx and Rx queues.
*
@@ -565,9 +558,6 @@
skb_queue_walk_safe(&priv->tdls_txq, skb, tmp)
mwifiex_write_data_complete(priv->adapter, skb, 0, -1);
-
- idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL);
- idr_destroy(&priv->ack_status_frames);
}
/*
@@ -611,32 +601,6 @@
}
/*
- * This function deletes RA list nodes for given mac for all TIDs.
- * Function also decrements TX pending count accordingly.
- */
-void
-mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr)
-{
- struct mwifiex_ra_list_tbl *ra_list;
- unsigned long flags;
- int i;
-
- spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags);
-
- for (i = 0; i < MAX_NUM_TID; ++i) {
- ra_list = mwifiex_wmm_get_ralist_node(priv, i, ra_addr);
-
- if (!ra_list)
- continue;
- mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list);
- atomic_sub(ra_list->total_pkt_count, &priv->wmm.tx_pkts_queued);
- list_del(&ra_list->list);
- kfree(ra_list);
- }
- spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags);
-}
-
-/*
* This function checks if a particular RA list node exists in a given TID
* table index.
*/
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index b8d1e04..ef11044 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -5548,9 +5548,7 @@
return rc;
}
-static void mwl8k_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void mwl8k_sw_scan_start(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
u8 tmp;
@@ -5567,8 +5565,7 @@
priv->sw_scan_start = true;
}
-static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw)
{
struct mwl8k_priv *priv = hw->priv;
u8 tmp;
diff --git a/drivers/net/wireless/p54/net2280.h b/drivers/net/wireless/p54/net2280.h
new file mode 100644
index 0000000..aedfaf2
--- /dev/null
+++ b/drivers/net/wireless/p54/net2280.h
@@ -0,0 +1,451 @@
+#ifndef NET2280_H
+#define NET2280_H
+/*
+ * NetChip 2280 high/full speed USB device controller.
+ * Unlike many such controllers, this one talks PCI.
+ */
+
+/*
+ * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com)
+ * Copyright (C) 2003 David Brownell
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+/*-------------------------------------------------------------------------*/
+
+/* NET2280 MEMORY MAPPED REGISTERS
+ *
+ * The register layout came from the chip documentation, and the bit
+ * number definitions were extracted from chip specification.
+ *
+ * Use the shift operator ('<<') to build bit masks, with readl/writel
+ * to access the registers through PCI.
+ */
+
+/* main registers, BAR0 + 0x0000 */
+struct net2280_regs {
+ /* offset 0x0000 */
+ __le32 devinit;
+#define LOCAL_CLOCK_FREQUENCY 8
+#define FORCE_PCI_RESET 7
+#define PCI_ID 6
+#define PCI_ENABLE 5
+#define FIFO_SOFT_RESET 4
+#define CFG_SOFT_RESET 3
+#define PCI_SOFT_RESET 2
+#define USB_SOFT_RESET 1
+#define M8051_RESET 0
+ __le32 eectl;
+#define EEPROM_ADDRESS_WIDTH 23
+#define EEPROM_CHIP_SELECT_ACTIVE 22
+#define EEPROM_PRESENT 21
+#define EEPROM_VALID 20
+#define EEPROM_BUSY 19
+#define EEPROM_CHIP_SELECT_ENABLE 18
+#define EEPROM_BYTE_READ_START 17
+#define EEPROM_BYTE_WRITE_START 16
+#define EEPROM_READ_DATA 8
+#define EEPROM_WRITE_DATA 0
+ __le32 eeclkfreq;
+ u32 _unused0;
+ /* offset 0x0010 */
+
+ __le32 pciirqenb0; /* interrupt PCI master ... */
+#define SETUP_PACKET_INTERRUPT_ENABLE 7
+#define ENDPOINT_F_INTERRUPT_ENABLE 6
+#define ENDPOINT_E_INTERRUPT_ENABLE 5
+#define ENDPOINT_D_INTERRUPT_ENABLE 4
+#define ENDPOINT_C_INTERRUPT_ENABLE 3
+#define ENDPOINT_B_INTERRUPT_ENABLE 2
+#define ENDPOINT_A_INTERRUPT_ENABLE 1
+#define ENDPOINT_0_INTERRUPT_ENABLE 0
+ __le32 pciirqenb1;
+#define PCI_INTERRUPT_ENABLE 31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+#define GPIO_INTERRUPT_ENABLE 13
+#define DMA_D_INTERRUPT_ENABLE 12
+#define DMA_C_INTERRUPT_ENABLE 11
+#define DMA_B_INTERRUPT_ENABLE 10
+#define DMA_A_INTERRUPT_ENABLE 9
+#define EEPROM_DONE_INTERRUPT_ENABLE 8
+#define VBUS_INTERRUPT_ENABLE 7
+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+#define RESUME_INTERRUPT_ENABLE 1
+#define SOF_INTERRUPT_ENABLE 0
+ __le32 cpu_irqenb0; /* ... or onboard 8051 */
+#define SETUP_PACKET_INTERRUPT_ENABLE 7
+#define ENDPOINT_F_INTERRUPT_ENABLE 6
+#define ENDPOINT_E_INTERRUPT_ENABLE 5
+#define ENDPOINT_D_INTERRUPT_ENABLE 4
+#define ENDPOINT_C_INTERRUPT_ENABLE 3
+#define ENDPOINT_B_INTERRUPT_ENABLE 2
+#define ENDPOINT_A_INTERRUPT_ENABLE 1
+#define ENDPOINT_0_INTERRUPT_ENABLE 0
+ __le32 cpu_irqenb1;
+#define CPU_INTERRUPT_ENABLE 31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+#define PCI_INTA_INTERRUPT_ENABLE 24
+#define PCI_PME_INTERRUPT_ENABLE 23
+#define PCI_SERR_INTERRUPT_ENABLE 22
+#define PCI_PERR_INTERRUPT_ENABLE 21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+#define GPIO_INTERRUPT_ENABLE 13
+#define DMA_D_INTERRUPT_ENABLE 12
+#define DMA_C_INTERRUPT_ENABLE 11
+#define DMA_B_INTERRUPT_ENABLE 10
+#define DMA_A_INTERRUPT_ENABLE 9
+#define EEPROM_DONE_INTERRUPT_ENABLE 8
+#define VBUS_INTERRUPT_ENABLE 7
+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+#define RESUME_INTERRUPT_ENABLE 1
+#define SOF_INTERRUPT_ENABLE 0
+
+ /* offset 0x0020 */
+ u32 _unused1;
+ __le32 usbirqenb1;
+#define USB_INTERRUPT_ENABLE 31
+#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26
+#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25
+#define PCI_INTA_INTERRUPT_ENABLE 24
+#define PCI_PME_INTERRUPT_ENABLE 23
+#define PCI_SERR_INTERRUPT_ENABLE 22
+#define PCI_PERR_INTERRUPT_ENABLE 21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19
+#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16
+#define GPIO_INTERRUPT_ENABLE 13
+#define DMA_D_INTERRUPT_ENABLE 12
+#define DMA_C_INTERRUPT_ENABLE 11
+#define DMA_B_INTERRUPT_ENABLE 10
+#define DMA_A_INTERRUPT_ENABLE 9
+#define EEPROM_DONE_INTERRUPT_ENABLE 8
+#define VBUS_INTERRUPT_ENABLE 7
+#define CONTROL_STATUS_INTERRUPT_ENABLE 6
+#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4
+#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2
+#define RESUME_INTERRUPT_ENABLE 1
+#define SOF_INTERRUPT_ENABLE 0
+ __le32 irqstat0;
+#define INTA_ASSERTED 12
+#define SETUP_PACKET_INTERRUPT 7
+#define ENDPOINT_F_INTERRUPT 6
+#define ENDPOINT_E_INTERRUPT 5
+#define ENDPOINT_D_INTERRUPT 4
+#define ENDPOINT_C_INTERRUPT 3
+#define ENDPOINT_B_INTERRUPT 2
+#define ENDPOINT_A_INTERRUPT 1
+#define ENDPOINT_0_INTERRUPT 0
+ __le32 irqstat1;
+#define POWER_STATE_CHANGE_INTERRUPT 27
+#define PCI_ARBITER_TIMEOUT_INTERRUPT 26
+#define PCI_PARITY_ERROR_INTERRUPT 25
+#define PCI_INTA_INTERRUPT 24
+#define PCI_PME_INTERRUPT 23
+#define PCI_SERR_INTERRUPT 22
+#define PCI_PERR_INTERRUPT 21
+#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20
+#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
+#define PCI_RETRY_ABORT_INTERRUPT 17
+#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
+#define GPIO_INTERRUPT 13
+#define DMA_D_INTERRUPT 12
+#define DMA_C_INTERRUPT 11
+#define DMA_B_INTERRUPT 10
+#define DMA_A_INTERRUPT 9
+#define EEPROM_DONE_INTERRUPT 8
+#define VBUS_INTERRUPT 7
+#define CONTROL_STATUS_INTERRUPT 6
+#define ROOT_PORT_RESET_INTERRUPT 4
+#define SUSPEND_REQUEST_INTERRUPT 3
+#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2
+#define RESUME_INTERRUPT 1
+#define SOF_INTERRUPT 0
+ /* offset 0x0030 */
+ __le32 idxaddr;
+ __le32 idxdata;
+ __le32 fifoctl;
+#define PCI_BASE2_RANGE 16
+#define IGNORE_FIFO_AVAILABILITY 3
+#define PCI_BASE2_SELECT 2
+#define FIFO_CONFIGURATION_SELECT 0
+ u32 _unused2;
+ /* offset 0x0040 */
+ __le32 memaddr;
+#define START 28
+#define DIRECTION 27
+#define FIFO_DIAGNOSTIC_SELECT 24
+#define MEMORY_ADDRESS 0
+ __le32 memdata0;
+ __le32 memdata1;
+ u32 _unused3;
+ /* offset 0x0050 */
+ __le32 gpioctl;
+#define GPIO3_LED_SELECT 12
+#define GPIO3_INTERRUPT_ENABLE 11
+#define GPIO2_INTERRUPT_ENABLE 10
+#define GPIO1_INTERRUPT_ENABLE 9
+#define GPIO0_INTERRUPT_ENABLE 8
+#define GPIO3_OUTPUT_ENABLE 7
+#define GPIO2_OUTPUT_ENABLE 6
+#define GPIO1_OUTPUT_ENABLE 5
+#define GPIO0_OUTPUT_ENABLE 4
+#define GPIO3_DATA 3
+#define GPIO2_DATA 2
+#define GPIO1_DATA 1
+#define GPIO0_DATA 0
+ __le32 gpiostat;
+#define GPIO3_INTERRUPT 3
+#define GPIO2_INTERRUPT 2
+#define GPIO1_INTERRUPT 1
+#define GPIO0_INTERRUPT 0
+} __packed;
+
+/* usb control, BAR0 + 0x0080 */
+struct net2280_usb_regs {
+ /* offset 0x0080 */
+ __le32 stdrsp;
+#define STALL_UNSUPPORTED_REQUESTS 31
+#define SET_TEST_MODE 16
+#define GET_OTHER_SPEED_CONFIGURATION 15
+#define GET_DEVICE_QUALIFIER 14
+#define SET_ADDRESS 13
+#define ENDPOINT_SET_CLEAR_HALT 12
+#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11
+#define GET_STRING_DESCRIPTOR_2 10
+#define GET_STRING_DESCRIPTOR_1 9
+#define GET_STRING_DESCRIPTOR_0 8
+#define GET_SET_INTERFACE 6
+#define GET_SET_CONFIGURATION 5
+#define GET_CONFIGURATION_DESCRIPTOR 4
+#define GET_DEVICE_DESCRIPTOR 3
+#define GET_ENDPOINT_STATUS 2
+#define GET_INTERFACE_STATUS 1
+#define GET_DEVICE_STATUS 0
+ __le32 prodvendid;
+#define PRODUCT_ID 16
+#define VENDOR_ID 0
+ __le32 relnum;
+ __le32 usbctl;
+#define SERIAL_NUMBER_INDEX 16
+#define PRODUCT_ID_STRING_ENABLE 13
+#define VENDOR_ID_STRING_ENABLE 12
+#define USB_ROOT_PORT_WAKEUP_ENABLE 11
+#define VBUS_PIN 10
+#define TIMED_DISCONNECT 9
+#define SUSPEND_IMMEDIATELY 7
+#define SELF_POWERED_USB_DEVICE 6
+#define REMOTE_WAKEUP_SUPPORT 5
+#define PME_POLARITY 4
+#define USB_DETECT_ENABLE 3
+#define PME_WAKEUP_ENABLE 2
+#define DEVICE_REMOTE_WAKEUP_ENABLE 1
+#define SELF_POWERED_STATUS 0
+ /* offset 0x0090 */
+ __le32 usbstat;
+#define HIGH_SPEED 7
+#define FULL_SPEED 6
+#define GENERATE_RESUME 5
+#define GENERATE_DEVICE_REMOTE_WAKEUP 4
+ __le32 xcvrdiag;
+#define FORCE_HIGH_SPEED_MODE 31
+#define FORCE_FULL_SPEED_MODE 30
+#define USB_TEST_MODE 24
+#define LINE_STATE 16
+#define TRANSCEIVER_OPERATION_MODE 2
+#define TRANSCEIVER_SELECT 1
+#define TERMINATION_SELECT 0
+ __le32 setup0123;
+ __le32 setup4567;
+ /* offset 0x0090 */
+ u32 _unused0;
+ __le32 ouraddr;
+#define FORCE_IMMEDIATE 7
+#define OUR_USB_ADDRESS 0
+ __le32 ourconfig;
+} __packed;
+
+/* pci control, BAR0 + 0x0100 */
+struct net2280_pci_regs {
+ /* offset 0x0100 */
+ __le32 pcimstctl;
+#define PCI_ARBITER_PARK_SELECT 13
+#define PCI_MULTI LEVEL_ARBITER 12
+#define PCI_RETRY_ABORT_ENABLE 11
+#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10
+#define DMA_READ_MULTIPLE_ENABLE 9
+#define DMA_READ_LINE_ENABLE 8
+#define PCI_MASTER_COMMAND_SELECT 6
+#define MEM_READ_OR_WRITE 0
+#define IO_READ_OR_WRITE 1
+#define CFG_READ_OR_WRITE 2
+#define PCI_MASTER_START 5
+#define PCI_MASTER_READ_WRITE 4
+#define PCI_MASTER_WRITE 0
+#define PCI_MASTER_READ 1
+#define PCI_MASTER_BYTE_WRITE_ENABLES 0
+ __le32 pcimstaddr;
+ __le32 pcimstdata;
+ __le32 pcimststat;
+#define PCI_ARBITER_CLEAR 2
+#define PCI_EXTERNAL_ARBITER 1
+#define PCI_HOST_MODE 0
+} __packed;
+
+/* dma control, BAR0 + 0x0180 ... array of four structs like this,
+ * for channels 0..3. see also struct net2280_dma: descriptor
+ * that can be loaded into some of these registers.
+ */
+struct net2280_dma_regs { /* [11.7] */
+ /* offset 0x0180, 0x01a0, 0x01c0, 0x01e0, */
+ __le32 dmactl;
+#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25
+#define DMA_CLEAR_COUNT_ENABLE 21
+#define DESCRIPTOR_POLLING_RATE 19
+#define POLL_CONTINUOUS 0
+#define POLL_1_USEC 1
+#define POLL_100_USEC 2
+#define POLL_1_MSEC 3
+#define DMA_VALID_BIT_POLLING_ENABLE 18
+#define DMA_VALID_BIT_ENABLE 17
+#define DMA_SCATTER_GATHER_ENABLE 16
+#define DMA_OUT_AUTO_START_ENABLE 4
+#define DMA_PREEMPT_ENABLE 3
+#define DMA_FIFO_VALIDATE 2
+#define DMA_ENABLE 1
+#define DMA_ADDRESS_HOLD 0
+ __le32 dmastat;
+#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
+#define DMA_TRANSACTION_DONE_INTERRUPT 24
+#define DMA_ABORT 1
+#define DMA_START 0
+ u32 _unused0[2];
+ /* offset 0x0190, 0x01b0, 0x01d0, 0x01f0, */
+ __le32 dmacount;
+#define VALID_BIT 31
+#define DMA_DIRECTION 30
+#define DMA_DONE_INTERRUPT_ENABLE 29
+#define END_OF_CHAIN 28
+#define DMA_BYTE_COUNT_MASK ((1<<24)-1)
+#define DMA_BYTE_COUNT 0
+ __le32 dmaaddr;
+ __le32 dmadesc;
+ u32 _unused1;
+} __packed;
+
+/* dedicated endpoint registers, BAR0 + 0x0200 */
+
+struct net2280_dep_regs { /* [11.8] */
+ /* offset 0x0200, 0x0210, 0x220, 0x230, 0x240 */
+ __le32 dep_cfg;
+ /* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */
+ __le32 dep_rsp;
+ u32 _unused[2];
+} __packed;
+
+/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs
+ * like this, for ep0 then the configurable endpoints A..F
+ * ep0 reserved for control; E and F have only 64 bytes of fifo
+ */
+struct net2280_ep_regs { /* [11.9] */
+ /* offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 */
+ __le32 ep_cfg;
+#define ENDPOINT_BYTE_COUNT 16
+#define ENDPOINT_ENABLE 10
+#define ENDPOINT_TYPE 8
+#define ENDPOINT_DIRECTION 7
+#define ENDPOINT_NUMBER 0
+ __le32 ep_rsp;
+#define SET_NAK_OUT_PACKETS 15
+#define SET_EP_HIDE_STATUS_PHASE 14
+#define SET_EP_FORCE_CRC_ERROR 13
+#define SET_INTERRUPT_MODE 12
+#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11
+#define SET_NAK_OUT_PACKETS_MODE 10
+#define SET_ENDPOINT_TOGGLE 9
+#define SET_ENDPOINT_HALT 8
+#define CLEAR_NAK_OUT_PACKETS 7
+#define CLEAR_EP_HIDE_STATUS_PHASE 6
+#define CLEAR_EP_FORCE_CRC_ERROR 5
+#define CLEAR_INTERRUPT_MODE 4
+#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3
+#define CLEAR_NAK_OUT_PACKETS_MODE 2
+#define CLEAR_ENDPOINT_TOGGLE 1
+#define CLEAR_ENDPOINT_HALT 0
+ __le32 ep_irqenb;
+#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6
+#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5
+#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3
+#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2
+#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1
+#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0
+ __le32 ep_stat;
+#define FIFO_VALID_COUNT 24
+#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22
+#define TIMEOUT 21
+#define USB_STALL_SENT 20
+#define USB_IN_NAK_SENT 19
+#define USB_IN_ACK_RCVD 18
+#define USB_OUT_PING_NAK_SENT 17
+#define USB_OUT_ACK_SENT 16
+#define FIFO_OVERFLOW 13
+#define FIFO_UNDERFLOW 12
+#define FIFO_FULL 11
+#define FIFO_EMPTY 10
+#define FIFO_FLUSH 9
+#define SHORT_PACKET_OUT_DONE_INTERRUPT 6
+#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5
+#define NAK_OUT_PACKETS 4
+#define DATA_PACKET_RECEIVED_INTERRUPT 3
+#define DATA_PACKET_TRANSMITTED_INTERRUPT 2
+#define DATA_OUT_PING_TOKEN_INTERRUPT 1
+#define DATA_IN_TOKEN_INTERRUPT 0
+ /* offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 */
+ __le32 ep_avail;
+ __le32 ep_data;
+ u32 _unused0[2];
+} __packed;
+
+struct net2280_reg_write {
+ __le16 port;
+ __le32 addr;
+ __le32 val;
+} __packed;
+
+struct net2280_reg_read {
+ __le16 port;
+ __le32 addr;
+} __packed;
+#endif /* NET2280_H */
diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h
index a5f5f0f..d273be7 100644
--- a/drivers/net/wireless/p54/p54usb.h
+++ b/drivers/net/wireless/p54/p54usb.h
@@ -16,7 +16,7 @@
/* for isl3886 register definitions used on ver 1 devices */
#include "p54pci.h"
-#include <linux/usb/net2280.h>
+#include "net2280.h"
/* pci */
#define NET2280_BASE 0x10000000
@@ -93,17 +93,6 @@
NET2280_DEV_CFG_U16 = 0x0883
};
-struct net2280_reg_write {
- __le16 port;
- __le32 addr;
- __le32 val;
-} __packed;
-
-struct net2280_reg_read {
- __le16 port;
- __le32 addr;
-} __packed;
-
#define P54U_FW_BLOCK 2048
#define X2_SIGNATURE "x2 "
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index b6c87b7..7d0df2b 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -256,7 +256,7 @@
config RT2X00_LIB
tristate
depends on m
- select BPAUTO_AVERAGE
+ select BACKPORT_AVERAGE
config RT2X00_LIB_FIRMWARE
boolean
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 8f446c1..bcee58c 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -47,7 +47,7 @@
* BBP and RF register require indirect register access,
* and use the CSR registers BBPCSR and RFCSR to achieve this.
* These indirect registers work with busy bits,
- * and we will try maximal REGISTER_USB_BUSY_COUNT times to access
+ * and we will try maximal REGISTER_BUSY_COUNT times to access
* the register while taking a REGISTER_BUSY_DELAY us delay
* between each attampt. When the busy bit is still set at that time,
* the access attempt is considered to have failed,
@@ -62,7 +62,7 @@
__le16 reg;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- ®, sizeof(reg));
+ ®, sizeof(reg), REGISTER_TIMEOUT);
*value = le16_to_cpu(reg);
}
@@ -83,7 +83,8 @@
{
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- value, length);
+ value, length,
+ REGISTER_TIMEOUT16(length));
}
static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev,
@@ -93,7 +94,7 @@
__le16 reg = cpu_to_le16(value);
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- ®, sizeof(reg));
+ ®, sizeof(reg), REGISTER_TIMEOUT);
}
static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev,
@@ -112,7 +113,8 @@
{
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- value, length);
+ value, length,
+ REGISTER_TIMEOUT16(length));
}
static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev,
@@ -122,7 +124,7 @@
{
unsigned int i;
- for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2500usb_register_read_lock(rt2x00dev, offset, reg);
if (!rt2x00_get_field16(*reg, field))
return 1;
@@ -904,7 +906,7 @@
unsigned int i;
u8 value;
- for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2500usb_bbp_read(rt2x00dev, 0, &value);
if ((value != 0xff) && (value != 0x00))
return 0;
@@ -1023,7 +1025,7 @@
* We must wait until the register indicates that the
* device has entered the correct state.
*/
- for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2500usb_register_read(rt2x00dev, MAC_CSR17, ®2);
bbp_state = rt2x00_get_field16(reg2, MAC_CSR17_BBP_CURR_STATE);
rf_state = rt2x00_get_field16(reg2, MAC_CSR17_RF_CURR_STATE);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index b12c863..5ad3899 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -4119,20 +4119,7 @@
* expected. We adjust it, based on TSSI reference and boundaries values
* provided in EEPROM.
*/
- switch (rt2x00dev->chip.rt) {
- case RT2860:
- case RT2872:
- case RT2883:
- case RT3070:
- case RT3071:
- case RT3090:
- case RT3572:
- delta += rt2800_get_gain_calibration_delta(rt2x00dev);
- break;
- default:
- /* TODO: temperature compensation code for other chips. */
- break;
- }
+ delta += rt2800_get_gain_calibration_delta(rt2x00dev);
/*
* Decrease power according to user settings, on devices with unknown
@@ -4149,19 +4136,25 @@
* TODO: we do not use +6 dBm option to do not increase power beyond
* regulatory limit, however this could be utilized for devices with
* CAPABILITY_POWER_LIMIT.
+ *
+ * TODO: add different temperature compensation code for RT3290 & RT5390
+ * to allow to use BBP_R1 for those chips.
*/
- if (delta <= -12) {
- power_ctrl = 2;
- delta += 12;
- } else if (delta <= -6) {
- power_ctrl = 1;
- delta += 6;
- } else {
- power_ctrl = 0;
+ if (!rt2x00_rt(rt2x00dev, RT3290) &&
+ !rt2x00_rt(rt2x00dev, RT5390)) {
+ rt2800_bbp_read(rt2x00dev, 1, &r1);
+ if (delta <= -12) {
+ power_ctrl = 2;
+ delta += 12;
+ } else if (delta <= -6) {
+ power_ctrl = 1;
+ delta += 6;
+ } else {
+ power_ctrl = 0;
+ }
+ rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
+ rt2800_bbp_write(rt2x00dev, 1, r1);
}
- rt2800_bbp_read(rt2x00dev, 1, &r1);
- rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, power_ctrl);
- rt2800_bbp_write(rt2x00dev, 1, r1);
offset = TX_PWR_CFG_0;
diff --git a/drivers/net/wireless/rt2x00/rt2800soc.c b/drivers/net/wireless/rt2x00/rt2800soc.c
index e6d747f..71ccac7 100644
--- a/drivers/net/wireless/rt2x00/rt2800soc.c
+++ b/drivers/net/wireless/rt2x00/rt2800soc.c
@@ -244,6 +244,7 @@
static struct platform_driver rt2800soc_driver = {
.driver = {
.name = "rt2800_wmac",
+ .owner = THIS_MODULE,
.mod_name = KBUILD_MODNAME,
},
.probe = rt2800soc_probe,
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index df74814..7737af9 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1111,7 +1111,6 @@
/* Ovislink */
{ USB_DEVICE(0x1b75, 0x3071) },
{ USB_DEVICE(0x1b75, 0x3072) },
- { USB_DEVICE(0x1b75, 0xa200) },
/* Para */
{ USB_DEVICE(0x20b8, 0x8888) },
/* Pegatron */
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index caa6400..57b2509 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -1019,12 +1019,9 @@
* Register defines.
* Some registers require multiple attempts before success,
* in those cases REGISTER_BUSY_COUNT attempts should be
- * taken with a REGISTER_BUSY_DELAY interval. Due to USB
- * bus delays, we do not have to loop so many times to wait
- * for valid register value on that bus.
+ * taken with a REGISTER_BUSY_DELAY interval.
*/
#define REGISTER_BUSY_COUNT 100
-#define REGISTER_USB_BUSY_COUNT 20
#define REGISTER_BUSY_DELAY 100
/*
@@ -1440,11 +1437,8 @@
struct ieee80211_sta *sta);
int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
struct ieee80211_sta *sta);
-void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr);
-void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw);
+void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw);
int rt2x00mac_get_stats(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 7f9e471..9206634 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -568,9 +568,7 @@
}
EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove);
-void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
@@ -578,8 +576,7 @@
}
EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start);
-void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw)
{
struct rt2x00_dev *rt2x00dev = hw->priv;
clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags);
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 66ff364..8e68f87 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -158,29 +158,55 @@
skb_trim(skb, frame_length);
}
-/*
- * H/W needs L2 padding between the header and the paylod if header size
- * is not 4 bytes aligned.
- */
-void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len)
+void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
{
- unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
+ unsigned int payload_length = skb->len - header_length;
+ unsigned int header_align = ALIGN_SIZE(skb, 0);
+ unsigned int payload_align = ALIGN_SIZE(skb, header_length);
+ unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0;
- if (!l2pad)
+ /*
+ * Adjust the header alignment if the payload needs to be moved more
+ * than the header.
+ */
+ if (payload_align > header_align)
+ header_align += 4;
+
+ /* There is nothing to do if no alignment is needed */
+ if (!header_align)
return;
- skb_push(skb, l2pad);
- memmove(skb->data, skb->data + l2pad, hdr_len);
+ /* Reserve the amount of space needed in front of the frame */
+ skb_push(skb, header_align);
+
+ /*
+ * Move the header.
+ */
+ memmove(skb->data, skb->data + header_align, header_length);
+
+ /* Move the payload, if present and if required */
+ if (payload_length && payload_align)
+ memmove(skb->data + header_length + l2pad,
+ skb->data + header_length + l2pad + payload_align,
+ payload_length);
+
+ /* Trim the skb to the correct size */
+ skb_trim(skb, header_length + l2pad + payload_length);
}
-void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len)
+void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length)
{
- unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0;
+ /*
+ * L2 padding is only present if the skb contains more than just the
+ * IEEE 802.11 header.
+ */
+ unsigned int l2pad = (skb->len > header_length) ?
+ L2PAD_SIZE(header_length) : 0;
if (!l2pad)
return;
- memmove(skb->data + l2pad, skb->data, hdr_len);
+ memmove(skb->data + l2pad, skb->data, header_length);
skb_pull(skb, l2pad);
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 892270d..86c43d1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -42,27 +42,37 @@
{
struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
int status;
+ unsigned int i;
unsigned int pipe =
(requesttype == USB_VENDOR_REQUEST_IN) ?
usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0);
- unsigned long expire = jiffies + msecs_to_jiffies(timeout);
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return -ENODEV;
- do {
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
status = usb_control_msg(usb_dev, pipe, request, requesttype,
value, offset, buffer, buffer_length,
- timeout / 2);
+ timeout);
if (status >= 0)
return 0;
- if (status == -ENODEV) {
- /* Device has disappeared. */
+ /*
+ * Check for errors
+ * -ENODEV: Device has disappeared, no point continuing.
+ * All other errors: Try again.
+ */
+ else if (status == -ENODEV) {
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
break;
}
- } while (time_before(jiffies, expire));
+ }
+
+ /* If the port is powered down, we get a -EPROTO error, and this
+ * leads to a endless loop. So just say that the device is gone.
+ */
+ if (status == -EPROTO)
+ clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
rt2x00_err(rt2x00dev,
"Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
@@ -106,7 +116,7 @@
int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
- const u16 buffer_length)
+ const u16 buffer_length, const int timeout)
{
int status = 0;
unsigned char *tb;
@@ -121,7 +131,7 @@
bsize = min_t(u16, CSR_CACHE_SIZE, len);
status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request,
requesttype, off, tb,
- bsize, REGISTER_TIMEOUT);
+ bsize, timeout);
tb += bsize;
len -= bsize;
@@ -144,7 +154,7 @@
if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
return -ENODEV;
- for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt2x00usb_register_read_lock(rt2x00dev, offset, reg);
if (!rt2x00_get_field32(*reg, field))
return 1;
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index 8f85fbd..831b65f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -33,14 +33,27 @@
})
/*
- * For USB vendor requests we need to pass a timeout time in ms, for this we
- * use the REGISTER_TIMEOUT, however when loading firmware or read EEPROM
- * a higher value is required. In that case we use the REGISTER_TIMEOUT_FIRMWARE
- * and EEPROM_TIMEOUT.
+ * For USB vendor requests we need to pass a timeout
+ * time in ms, for this we use the REGISTER_TIMEOUT,
+ * however when loading firmware a higher value is
+ * required. In that case we use the REGISTER_TIMEOUT_FIRMWARE.
*/
-#define REGISTER_TIMEOUT 100
+#define REGISTER_TIMEOUT 500
#define REGISTER_TIMEOUT_FIRMWARE 1000
-#define EEPROM_TIMEOUT 2000
+
+/**
+ * REGISTER_TIMEOUT16 - Determine the timeout for 16bit register access
+ * @__datalen: Data length
+ */
+#define REGISTER_TIMEOUT16(__datalen) \
+ ( REGISTER_TIMEOUT * ((__datalen) / sizeof(u16)) )
+
+/**
+ * REGISTER_TIMEOUT32 - Determine the timeout for 32bit register access
+ * @__datalen: Data length
+ */
+#define REGISTER_TIMEOUT32(__datalen) \
+ ( REGISTER_TIMEOUT * ((__datalen) / sizeof(u32)) )
/*
* Cache size
@@ -113,6 +126,7 @@
* @offset: Register offset to perform action on
* @buffer: Buffer where information will be read/written to by device
* @buffer_length: Size of &buffer
+ * @timeout: Operation timeout
*
* This function will use a previously with kmalloc allocated cache
* to communicate with the device. The contents of the buffer pointer
@@ -125,7 +139,7 @@
int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev,
const u8 request, const u8 requesttype,
const u16 offset, void *buffer,
- const u16 buffer_length);
+ const u16 buffer_length, const int timeout);
/**
* rt2x00usb_vendor_request_buff - Send register command to device (buffered)
@@ -183,7 +197,8 @@
{
return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ,
USB_VENDOR_REQUEST_IN, 0, 0,
- eeprom, length, EEPROM_TIMEOUT);
+ eeprom, length,
+ REGISTER_TIMEOUT16(length));
}
/**
@@ -202,7 +217,7 @@
__le32 reg;
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- ®, sizeof(reg));
+ ®, sizeof(reg), REGISTER_TIMEOUT);
*value = le32_to_cpu(reg);
}
@@ -242,7 +257,8 @@
{
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ,
USB_VENDOR_REQUEST_IN, offset,
- value, length);
+ value, length,
+ REGISTER_TIMEOUT32(length));
}
/**
@@ -261,7 +277,7 @@
__le32 reg = cpu_to_le32(value);
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- ®, sizeof(reg));
+ ®, sizeof(reg), REGISTER_TIMEOUT);
}
/**
@@ -300,7 +316,8 @@
{
rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE,
USB_VENDOR_REQUEST_OUT, offset,
- (void *)value, length);
+ (void *)value, length,
+ REGISTER_TIMEOUT32(length));
}
/**
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index b0a75d9..80d48e9 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -1295,7 +1295,7 @@
unsigned int i;
u8 value;
- for (i = 0; i < REGISTER_USB_BUSY_COUNT; i++) {
+ for (i = 0; i < REGISTER_BUSY_COUNT; i++) {
rt73usb_bbp_read(rt2x00dev, 0, &value);
if ((value != 0xff) && (value != 0x00))
return 0;
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c
index 40b6d1d..58ba718 100644
--- a/drivers/net/wireless/rtlwifi/base.c
+++ b/drivers/net/wireless/rtlwifi/base.c
@@ -467,7 +467,7 @@
rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw);
/* <2> work queue */
rtlpriv->works.hw = hw;
- rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name);
+ rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0);
INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq,
(void *)rtl_watchdog_wq_callback);
INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq,
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index 5fc6f52..f6179bc 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -786,7 +786,6 @@
unsigned int changed_flags,
unsigned int *new_flags, u64 multicast)
{
- bool update_rcr = false;
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -807,7 +806,6 @@
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
"Disable receive multicast frame\n");
}
- update_rcr = true;
}
if (changed_flags & FIF_FCSFAIL) {
@@ -820,8 +818,6 @@
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
"Disable receive FCS error frame\n");
}
- if (!update_rcr)
- update_rcr = true;
}
/* if ssid not set to hw don't check bssid
@@ -836,8 +832,6 @@
rtlpriv->cfg->ops->set_chk_bssid(hw, false);
else
rtlpriv->cfg->ops->set_chk_bssid(hw, true);
- if (update_rcr)
- update_rcr = false;
}
}
@@ -852,8 +846,6 @@
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
"Disable receive control frame.\n");
}
- if (!update_rcr)
- update_rcr = true;
}
if (changed_flags & FIF_OTHER_BSS) {
@@ -866,13 +858,7 @@
RT_TRACE(rtlpriv, COMP_MAC80211, DBG_LOUD,
"Disable receive other BSS's frame.\n");
}
- if (!update_rcr)
- update_rcr = true;
}
-
- if (update_rcr)
- rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
- (u8 *)(&mac->rx_conf));
}
static int rtl_op_sta_add(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -1375,9 +1361,7 @@
return 0;
}
-static void rtl_op_sw_scan_start(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr)
+static void rtl_op_sw_scan_start(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -1412,8 +1396,7 @@
rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP_BAND0);
}
-static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -1845,9 +1828,3 @@
.flush = rtl_op_flush,
};
EXPORT_SYMBOL_GPL(rtl_ops);
-
-bool rtl_btc_status_false(void)
-{
- return false;
-}
-EXPORT_SYMBOL_GPL(rtl_btc_status_false);
diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h
index 624e1dc..59cd3b9 100644
--- a/drivers/net/wireless/rtlwifi/core.h
+++ b/drivers/net/wireless/rtlwifi/core.h
@@ -42,6 +42,5 @@
u32 mask, u32 data);
void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data);
bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb);
-bool rtl_btc_status_false(void);
#endif
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 846a2e6..667aba8 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -842,8 +842,7 @@
break;
}
/* handle command packet here */
- if (rtlpriv->cfg->ops->rx_command_packet &&
- rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) {
+ if (rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) {
dev_kfree_skb_any(skb);
goto end;
}
@@ -1128,14 +1127,9 @@
__skb_queue_tail(&ring->queue, pskb);
- if (rtlpriv->use_new_trx_flow) {
- temp_one = 4;
- rtlpriv->cfg->ops->set_desc(hw, (u8 *)pbuffer_desc, true,
- HW_DESC_OWN, (u8 *)&temp_one);
- } else {
- rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN,
- &temp_one);
- }
+ rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN,
+ &temp_one);
+
return;
}
@@ -1376,9 +1370,9 @@
ring->desc = NULL;
if (rtlpriv->use_new_trx_flow) {
pci_free_consistent(rtlpci->pdev,
- sizeof(*ring->buffer_desc) * ring->entries,
+ sizeof(*ring->desc) * ring->entries,
ring->buffer_desc, ring->buffer_desc_dma);
- ring->buffer_desc = NULL;
+ ring->desc = NULL;
}
}
@@ -1549,6 +1543,7 @@
true,
HW_DESC_TXBUFF_ADDR),
skb->len, PCI_DMA_TODEVICE);
+ ring->idx = (ring->idx + 1) % ring->entries;
kfree_skb(skb);
ring->idx = (ring->idx + 1) % ring->entries;
}
@@ -1801,8 +1796,7 @@
rtl_pci_reset_trx_ring(hw);
rtlpci->driver_is_goingto_unload = false;
- if (rtlpriv->cfg->ops->get_btc_status &&
- rtlpriv->cfg->ops->get_btc_status()) {
+ if (rtlpriv->cfg->ops->get_btc_status()) {
rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv);
rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv);
}
@@ -2249,16 +2243,6 @@
/*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");
- err = -ENODEV;
- goto fail3;
- }
- rtlpriv->cfg->ops->init_sw_leds(hw);
-
- /*aspm */
- rtl_pci_init_aspm(hw);
-
/* Init mac80211 sw */
err = rtl_init_core(hw);
if (err) {
@@ -2274,6 +2258,16 @@
goto fail3;
}
+ if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "Can't init_sw_vars\n");
+ err = -ENODEV;
+ goto fail3;
+ }
+ rtlpriv->cfg->ops->init_sw_leds(hw);
+
+ /*aspm */
+ rtl_pci_init_aspm(hw);
+
err = ieee80211_register_hw(hw);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
index 29983bc..a00861b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
@@ -656,8 +656,7 @@
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw,
- bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *))
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -723,10 +722,7 @@
memcpy((u8 *)skb_put(skb, totalpacketlen),
&reserved_page_packet, totalpacketlen);
- if (cmd_send_packet)
- rtstatus = cmd_send_packet(hw, skb);
- else
- rtstatus = rtl_cmd_send_packet(hw, skb);
+ rtstatus = rtl_cmd_send_packet(hw, skb);
if (rtstatus)
b_dlok = true;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
index b64ae45..a815bd6 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
@@ -109,9 +109,7 @@
u32 cmd_len, u8 *p_cmdbuffer);
void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
-void rtl92c_set_fw_rsvdpagepkt
- (struct ieee80211_hw *hw,
- bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *));
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len);
void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
index 9b660df..831df10 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
@@ -114,8 +114,6 @@
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4)
#define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \
LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12)
-#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \
- SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32)
#define CHIP_VER_B BIT(4)
#define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 5c646d5..8ec0f03 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -459,7 +459,7 @@
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
tmp_reg422 & (~BIT(6)));
- rtl92c_set_fw_rsvdpagepkt(hw, NULL);
+ rtl92c_set_fw_rsvdpagepkt(hw, 0);
_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4));
@@ -955,7 +955,6 @@
local_save_flags(flags);
local_irq_enable();
- rtlhal->fw_ready = false;
rtlpriv->intf_ops->disable_aspm(hw);
rtstatus = _rtl92ce_init_mac(hw);
if (!rtstatus) {
@@ -972,7 +971,6 @@
goto exit;
}
- rtlhal->fw_ready = true;
rtlhal->last_hmeboxnum = 0;
rtl92c_phy_mac_config(hw);
/* because last function modify RCR, so we update
@@ -1289,7 +1287,6 @@
rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] & 0xFFFFFFFF);
rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] & 0xFFFFFFFF);
- rtlpci->irq_enabled = true;
}
void rtl92ce_disable_interrupt(struct ieee80211_hw *hw)
@@ -1299,7 +1296,7 @@
rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
- rtlpci->irq_enabled = false;
+ synchronize_irq(rtlpci->pdev->irq);
}
static void _rtl92ce_poweroff_adapter(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index dd5aa08..d86b5b5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -228,7 +228,6 @@
.led_control = rtl92ce_led_control,
.set_desc = rtl92ce_set_desc,
.get_desc = rtl92ce_get_desc,
- .is_tx_desc_closed = rtl92ce_is_tx_desc_closed,
.tx_polling = rtl92ce_tx_polling,
.enable_hw_sec = rtl92ce_enable_hw_security_config,
.set_key = rtl92ce_set_key,
@@ -245,7 +244,6 @@
.phy_lc_calibrate = _rtl92ce_phy_lc_calibrate,
.phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback,
.dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower,
- .get_btc_status = rtl_btc_status_false,
};
static struct rtl_mod_params rtl92ce_mod_params = {
@@ -272,8 +270,6 @@
.maps[MAC_RCR_ACRC32] = ACRC32,
.maps[MAC_RCR_ACF] = ACF,
.maps[MAC_RCR_AAP] = AAP,
- .maps[MAC_HIMR] = REG_HIMR,
- .maps[MAC_HIMRE] = REG_HIMRE,
.maps[EFUSE_TEST] = REG_EFUSE_TEST,
.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
index e88dcd0..2fb9c7a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
@@ -720,15 +720,13 @@
break;
}
} else {
+ struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
switch (desc_name) {
case HW_DESC_OWN:
- ret = GET_RX_DESC_OWN(p_desc);
+ ret = GET_RX_DESC_OWN(pdesc);
break;
case HW_DESC_RXPKT_LEN:
- ret = GET_RX_DESC_PKT_LEN(p_desc);
- break;
- case HW_DESC_RXBUFF_ADDR:
- ret = GET_RX_DESC_BUFF_ADDR(p_desc);
+ ret = GET_RX_DESC_PKT_LEN(pdesc);
break;
default:
RT_ASSERT(false, "ERR rxdesc :%d not process\n",
@@ -739,23 +737,6 @@
return ret;
}
-bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw,
- u8 hw_queue, u16 index)
-{
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
- u8 *entry = (u8 *)(&ring->desc[ring->idx]);
- u8 own = (u8)rtl92ce_get_desc(entry, true, HW_DESC_OWN);
-
- /*beacon packet will only use the first
- *descriptor defautly,and the own may not
- *be cleared by the hardware
- */
- if (own)
- return false;
- return true;
-}
-
void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
index 4bec4b0..9a39ec4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
@@ -723,8 +723,6 @@
void rtl92ce_set_desc(struct ieee80211_hw *hw, u8 *pdesc, bool istx,
u8 desc_name, u8 *val);
u32 rtl92ce_get_desc(u8 *pdesc, bool istx, u8 desc_name);
-bool rtl92ce_is_tx_desc_closed(struct ieee80211_hw *hw,
- u8 hw_queue, u16 index);
void rtl92ce_tx_polling(struct ieee80211_hw *hw, u8 hw_queue);
void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
bool b_firstseg, bool b_lastseg,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 5513217..04aa0b5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -1592,20 +1592,6 @@
}
}
-static bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
- /* Currently nothing happens here.
- * Traffic stops after some seconds in WPA2 802.11n mode.
- * Maybe because rtl8192cu chip should be set from here?
- * If I understand correctly, the realtek vendor driver sends some urbs
- * if its "here".
- *
- * This is maybe necessary:
- * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb);
- */
- return true;
-}
-
void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
{
struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -1953,8 +1939,7 @@
recover = true;
rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
tmp_reg422 & (~BIT(6)));
- rtl92c_set_fw_rsvdpagepkt(hw,
- &usb_cmd_send_packet);
+ rtl92c_set_fw_rsvdpagepkt(hw, 0);
_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
if (recover)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
index c1e33b0..0f7812e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
@@ -104,6 +104,7 @@
void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
int rtl92c_download_fw(struct ieee80211_hw *hw);
void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished);
void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index 97f85b7..18933c0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -101,12 +101,6 @@
}
}
-/* get bt coexist status */
-static bool rtl92cu_get_btc_status(void)
-{
- return false;
-}
-
static struct rtl_hal_ops rtl8192cu_hal_ops = {
.init_sw_vars = rtl92cu_init_sw_vars,
.deinit_sw_vars = rtl92cu_deinit_sw_vars,
@@ -154,7 +148,6 @@
.phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback,
.dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower,
.fill_h2c_cmd = rtl92c_fill_h2c_cmd,
- .get_btc_status = rtl92cu_get_btc_status,
};
static struct rtl_mod_params rtl92cu_mod_params = {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
index a0aba08..edab5a5 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c
@@ -251,7 +251,6 @@
.get_rfreg = rtl92d_phy_query_rf_reg,
.set_rfreg = rtl92d_phy_set_rf_reg,
.linked_set_reg = rtl92d_linked_set_reg,
- .get_btc_status = rtl_btc_status_false,
};
static struct rtl_mod_params rtl92de_mod_params = {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile b/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile
index c5e6f97..aeea8a9 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/Makefile
@@ -1,3 +1,6 @@
+obj-m := rtl8192ee.o
+
+
rtl8192ee-objs := \
dm.o \
fw.o \
@@ -11,6 +14,6 @@
trx.o \
-obj-$(CPTCFG_RTL8192EE) += rtl8192ee.o
+obj-$(CPTCFG_RTL8821AE) += rtl8192ee.o
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
index 1a87edc..dfdc9b2 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c
@@ -362,7 +362,7 @@
}
break;
default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not process %x\n", variable);
break;
}
@@ -591,7 +591,7 @@
acm_ctrl &= (~ACMHW_BEQEN);
break;
default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not process\n");
break;
}
@@ -710,7 +710,7 @@
}
break;
default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not process %x\n", variable);
break;
}
@@ -2424,7 +2424,7 @@
enc_algo = CAM_AES;
break;
default:
- RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
"switch case not process\n");
enc_algo = CAM_TKIP;
break;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
index 6e7a70b..83c9867 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h
@@ -446,8 +446,6 @@
/* DWORD 6 */
#define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \
SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val)
-#define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \
- SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32)
#define SE_RX_HAL_IS_CCK_RATE(_pdesc)\
(GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 5761d5b..00e0670 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -1201,9 +1201,6 @@
}
- if (type != NL80211_IFTYPE_AP &&
- rtlpriv->mac80211.link_state < MAC80211_LINKED)
- bt_msr = rtl_read_byte(rtlpriv, MSR) & ~MSR_LINK_MASK;
rtl_write_byte(rtlpriv, (MSR), bt_msr);
temp = rtl_read_dword(rtlpriv, TCR);
@@ -1265,7 +1262,6 @@
rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]);
/* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */
rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F);
- rtlpci->irq_enabled = true;
}
void rtl92se_disable_interrupt(struct ieee80211_hw *hw)
@@ -1280,7 +1276,8 @@
rtlpci = rtl_pcidev(rtl_pcipriv(hw));
rtl_write_dword(rtlpriv, INTA_MASK, 0);
rtl_write_dword(rtlpriv, INTA_MASK + 4, 0);
- rtlpci->irq_enabled = false;
+
+ synchronize_irq(rtlpci->pdev->irq);
}
static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data)
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
index 4b4612f..77c5b5f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c
@@ -399,8 +399,6 @@
case 2:
currentcmd = &postcommoncmd[*step];
break;
- default:
- return true;
}
if (currentcmd->cmdid == CMDID_END) {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index fb00386..1bff2a0 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -87,8 +87,11 @@
static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
{
struct ieee80211_hw *hw = context;
+ struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
struct rtl_priv *rtlpriv = rtl_priv(hw);
+ struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
struct rt_firmware *pfirmware = NULL;
+ int err;
RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD,
"Firmware callback routine entered!\n");
@@ -109,6 +112,20 @@
memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
pfirmware->sz_fw_tmpbufferlen = firmware->size;
release_firmware(firmware);
+
+ err = ieee80211_register_hw(hw);
+ if (err) {
+ RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+ "Can't register mac80211 hw\n");
+ return;
+ } else {
+ rtlpriv->mac80211.mac80211_registered = 1;
+ }
+ rtlpci->irq_alloc = 1;
+ set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
+
+ /*init rfkill */
+ rtl_init_rfkill(hw);
}
static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
@@ -209,8 +226,8 @@
if (!rtlpriv->rtlhal.pfirmware)
return 1;
- rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 +
- sizeof(struct fw_hdr);
+ rtlpriv->max_fw_size = RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE;
+
pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n"
"Loading firmware %s\n", rtlpriv->cfg->fw_name);
/* request fw */
@@ -236,19 +253,6 @@
}
}
-static bool rtl92se_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue,
- u16 index)
-{
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
- struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
- u8 *entry = (u8 *)(&ring->desc[ring->idx]);
- u8 own = (u8)rtl92se_get_desc(entry, true, HW_DESC_OWN);
-
- if (own)
- return false;
- return true;
-}
-
static struct rtl_hal_ops rtl8192se_hal_ops = {
.init_sw_vars = rtl92s_init_sw_vars,
.deinit_sw_vars = rtl92s_deinit_sw_vars,
@@ -282,7 +286,6 @@
.led_control = rtl92se_led_control,
.set_desc = rtl92se_set_desc,
.get_desc = rtl92se_get_desc,
- .is_tx_desc_closed = rtl92se_is_tx_desc_closed,
.tx_polling = rtl92se_tx_polling,
.enable_hw_sec = rtl92se_enable_hw_security_config,
.set_key = rtl92se_set_key,
@@ -291,7 +294,6 @@
.set_bbreg = rtl92s_phy_set_bb_reg,
.get_rfreg = rtl92s_phy_query_rf_reg,
.set_rfreg = rtl92s_phy_set_rf_reg,
- .get_btc_status = rtl_btc_status_false,
};
static struct rtl_mod_params rtl92se_mod_params = {
@@ -320,8 +322,6 @@
.maps[MAC_RCR_ACRC32] = RCR_ACRC32,
.maps[MAC_RCR_ACF] = RCR_ACF,
.maps[MAC_RCR_AAP] = RCR_AAP,
- .maps[MAC_HIMR] = INTA_MASK,
- .maps[MAC_HIMRE] = INTA_MASK + 4,
.maps[EFUSE_TEST] = REG_EFUSE_TEST,
.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 672fd3b..b358ebc 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -640,9 +640,6 @@
case HW_DESC_RXPKT_LEN:
ret = GET_RX_STATUS_DESC_PKT_LEN(desc);
break;
- case HW_DESC_RXBUFF_ADDR:
- ret = GET_RX_STATUS_DESC_BUFF_ADDR(desc);
- break;
default:
RT_ASSERT(false, "ERR rxdesc :%d not process\n",
desc_name);
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile b/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
index e8ce901..e0b1dde 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/Makefile
@@ -1,3 +1,6 @@
+obj-m := rtl8723ae.o
+
+
rtl8723ae-objs := \
dm.o \
fw.o \
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile b/drivers/net/wireless/rtlwifi/rtl8723be/Makefile
index cd01566..5d18f04 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/Makefile
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/Makefile
@@ -1,3 +1,6 @@
+obj-m := rtl8723be.o
+
+
rtl8723be-objs := \
dm.o \
fw.o \
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile b/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile
index 5215004..445930c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/Makefile
@@ -1,3 +1,6 @@
+obj-m := rtl8821ae.o
+
+
rtl8821ae-objs := \
dm.o \
fw.o \
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c b/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
index ba30b0d..9be1061 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/dm.c
@@ -2078,7 +2078,8 @@
if (rtldm->tx_rate != 0xFF)
tx_rate = rtl8821ae_hw_rate_to_mrate(hw, rtldm->tx_rate);
- RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "===>%s\n", __func__);
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
if (tx_rate != 0xFF) { /* Mimic Modify High Rate BBSwing Limit.*/
/*CCK*/
@@ -2127,7 +2128,7 @@
if (method == BBSWING) {
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
- "===>%s\n", __func__);
+ "===>rtl8812ae_dm_txpwr_track_set_pwr\n");
if (rf_path == RF90_PATH_A) {
final_swing_idx[RF90_PATH_A] =
(rtldm->ofdm_index[RF90_PATH_A] >
@@ -2259,8 +2260,7 @@
rtldm->txpower_trackinginit = true;
RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
- "===>%s,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
- __func__,
+ "===>rtl8812ae_dm_txpower_tracking_callback_thermalmeter,\n pDM_Odm->BbSwingIdxCckBase: %d,pDM_Odm->BbSwingIdxOfdmBase[A]:%d, pDM_Odm->DefaultOfdmIndex: %d\n",
rtldm->swing_idx_cck_base,
rtldm->swing_idx_ofdm_base[RF90_PATH_A],
rtldm->default_ofdm_index);
@@ -2539,7 +2539,8 @@
}
}
- RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, "<===%s\n", __func__);
+ RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+ "<===rtl8812ae_dm_txpower_tracking_callback_thermalmeter\n");
}
void rtl8821ae_dm_check_txpower_tracking_thermalmeter(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
index 8ec8200..310d316 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/hw.c
@@ -3672,9 +3672,8 @@
mac->opmode == NL80211_IFTYPE_ADHOC)
macid = sta->aid + 1;
if (wirelessmode == WIRELESS_MODE_N_5G ||
- wirelessmode == WIRELESS_MODE_AC_5G ||
- wirelessmode == WIRELESS_MODE_A)
- ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ] << 4;
+ wirelessmode == WIRELESS_MODE_AC_5G)
+ ratr_bitmap = sta->supp_rates[NL80211_BAND_5GHZ];
else
ratr_bitmap = sta->supp_rates[NL80211_BAND_2GHZ];
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
index 9b4d8a6..9786313 100644
--- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c
@@ -800,7 +800,7 @@
"Invalid RateSection %d in Band 2.4G,Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n",
rate_section, path, txnum);
break;
- }
+ };
} else if (band == BAND_ON_5G) {
switch (rate_section) {
case OFDM:
@@ -823,7 +823,7 @@
"Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n",
rate_section, path, txnum);
break;
- }
+ };
} else {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Invalid Band %d in PHY_SetTxPowerByRateBase()\n", band);
@@ -870,7 +870,7 @@
"Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n",
rate_section, path, txnum);
break;
- }
+ };
} else if (band == BAND_ON_5G) {
switch (rate_section) {
case OFDM:
@@ -893,7 +893,7 @@
"Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n",
rate_section, path, txnum);
break;
- }
+ };
} else {
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"Invalid Band %d in PHY_GetTxPowerByRateBase()\n", band);
@@ -1889,18 +1889,15 @@
struct rtl_phy *rtlphy = &rtlpriv->phy;
u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr);
- if (band != BAND_ON_2_4G && band != BAND_ON_5G) {
+ if (band != BAND_ON_2_4G && band != BAND_ON_5G)
RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band);
- band = BAND_ON_2_4G;
- }
- if (rfpath >= MAX_RF_PATH) {
+
+ if (rfpath >= MAX_RF_PATH)
RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath);
- rfpath = MAX_RF_PATH - 1;
- }
- if (txnum >= MAX_RF_PATH) {
+
+ if (txnum >= MAX_RF_PATH)
RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum);
- txnum = MAX_RF_PATH - 1;
- }
+
rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data;
RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
"TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n",
@@ -3746,7 +3743,7 @@
break;
default:
break;
- }
+ };
}
static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw,
@@ -3767,7 +3764,7 @@
break;
default:
break;
- }
+ };
}
#define cal_num 10
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
index 46ee956..10cf69c 100644
--- a/drivers/net/wireless/rtlwifi/usb.c
+++ b/drivers/net/wireless/rtlwifi/usb.c
@@ -1117,18 +1117,7 @@
}
rtlpriv->cfg->ops->init_sw_leds(hw);
- err = ieee80211_register_hw(hw);
- if (err) {
- RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
- "Can't register mac80211 hw.\n");
- err = -ENODEV;
- goto error_out;
- }
- rtlpriv->mac80211.mac80211_registered = 1;
-
- set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
return 0;
-
error_out:
rtl_deinit_core(hw);
_rtl_usb_io_handler_release(hw);
diff --git a/drivers/net/wireless/ti/wl1251/Kconfig b/drivers/net/wireless/ti/wl1251/Kconfig
index 1d9ca90..76649c5 100644
--- a/drivers/net/wireless/ti/wl1251/Kconfig
+++ b/drivers/net/wireless/ti/wl1251/Kconfig
@@ -12,7 +12,7 @@
N if unsure.
config WL1251_SPI
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_5
tristate "TI wl1251 SPI support"
depends on m
depends on WL1251 && SPI_MASTER
@@ -25,7 +25,7 @@
Say N if unsure.
config WL1251_SDIO
- depends on !KERNEL_3_15
+ depends on !BACKPORT_KERNEL_3_15
tristate "TI wl1251 SDIO support"
depends on m
depends on WL1251 && MMC
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 0b30a7b..3823485 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -1029,7 +1029,7 @@
goto out_sleep;
}
- skb = ieee80211_probereq_get(wl->hw, wl->vif->addr, ssid, ssid_len,
+ skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
req->ie_len);
if (!skb) {
ret = -ENOMEM;
diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index d6d0d6d..0bccf12 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1900,6 +1900,7 @@
.id_table = wl12xx_id_table,
.driver = {
.name = "wl12xx_driver",
+ .owner = THIS_MODULE,
}
};
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 8e56261..7af1936 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1968,6 +1968,7 @@
.id_table = wl18xx_id_table,
.driver = {
.name = "wl18xx_driver",
+ .owner = THIS_MODULE,
}
};
diff --git a/drivers/net/wireless/ti/wlcore/Kconfig b/drivers/net/wireless/ti/wlcore/Kconfig
index 09bb747..4bab094 100644
--- a/drivers/net/wireless/ti/wlcore/Kconfig
+++ b/drivers/net/wireless/ti/wlcore/Kconfig
@@ -26,7 +26,7 @@
Say N if unsure.
config WLCORE_SDIO
- depends on !KERNEL_3_15
+ depends on !BACKPORT_KERNEL_3_15
tristate "TI wlcore SDIO support"
depends on m
depends on WLCORE && MMC
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index b826619..05604ee 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -64,9 +64,6 @@
id != CMD_STOP_FWLOGGER))
return -EIO;
- if (WARN_ON_ONCE(len < sizeof(*cmd)))
- return -EIO;
-
cmd = buf;
cmd->id = cpu_to_le16(id);
cmd->status = 0;
@@ -131,9 +128,8 @@
* send command to fw and return cmd status on success
* valid_rets contains a bitmap of allowed error codes
*/
-static int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf,
- size_t len, size_t res_len,
- unsigned long valid_rets)
+int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len,
+ size_t res_len, unsigned long valid_rets)
{
int ret = __wlcore_cmd_send(wl, id, buf, len, res_len);
@@ -154,6 +150,7 @@
wl12xx_queue_recovery_work(wl);
return ret;
}
+EXPORT_SYMBOL_GPL(wl1271_cmd_send);
/*
* wrapper for wlcore_cmd_send that accept only CMD_STATUS_SUCCESS
@@ -168,7 +165,6 @@
return ret;
return 0;
}
-EXPORT_SYMBOL_GPL(wl1271_cmd_send);
/*
* Poll the mailbox event field until any of the bits in the mask is set or a
@@ -895,9 +891,6 @@
wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id);
- if (WARN_ON_ONCE(len < sizeof(*acx)))
- return -EIO;
-
acx->id = cpu_to_le16(id);
/* payload length, does not include any headers */
@@ -1145,7 +1138,7 @@
wl1271_debug(DEBUG_SCAN, "build probe request band %d", band);
- skb = ieee80211_probereq_get(wl->hw, vif->addr, ssid, ssid_len,
+ skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len,
ie0_len + ie1_len);
if (!skb) {
ret = -ENOMEM;
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h
index 453684a..ca6a28b 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.h
+++ b/drivers/net/wireless/ti/wlcore/cmd.h
@@ -31,6 +31,8 @@
int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
size_t res_len);
+int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len,
+ size_t res_len, unsigned long valid_rets);
int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type,
u8 *role_id);
int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
diff --git a/drivers/net/wireless/ti/wlcore/event.c b/drivers/net/wireless/ti/wlcore/event.c
index 5153640..16d1028 100644
--- a/drivers/net/wireless/ti/wlcore/event.c
+++ b/drivers/net/wireless/ti/wlcore/event.c
@@ -259,7 +259,10 @@
&wlvif->connection_loss_work,
msecs_to_jiffies(delay));
- ieee80211_cqm_beacon_loss_notify(vif, GFP_KERNEL);
+ ieee80211_cqm_rssi_notify(
+ vif,
+ NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
+ GFP_KERNEL);
}
}
EXPORT_SYMBOL_GPL(wlcore_event_beacon_loss);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 6ad3fce..575c8f6 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5177,11 +5177,10 @@
}
static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
struct ieee80211_channel_switch *ch_switch)
{
struct wl1271 *wl = hw->priv;
- struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl12xx_vif *wlvif;
int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
@@ -5191,8 +5190,14 @@
mutex_lock(&wl->mutex);
if (unlikely(wl->state == WLCORE_STATE_OFF)) {
- if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
+ struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif);
+
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+ continue;
+
ieee80211_chswitch_done(vif, false);
+ }
goto out;
} else if (unlikely(wl->state != WLCORE_STATE_ON)) {
goto out;
@@ -5203,10 +5208,12 @@
goto out;
/* TODO: change mac80211 to pass vif as param */
-
- if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) {
+ wl12xx_for_each_wlvif_sta(wl, wlvif) {
unsigned long delay_usec;
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+ continue;
+
ret = wl->ops->channel_switch(wl, wlvif, ch_switch);
if (ret)
goto out_sleep;
@@ -5215,10 +5222,10 @@
/* indicate failure 5 seconds after channel switch time */
delay_usec = ieee80211_tu_to_usec(wlvif->beacon_int) *
- ch_switch->count;
+ ch_switch->count;
ieee80211_queue_delayed_work(hw, &wlvif->channel_switch_work,
- usecs_to_jiffies(delay_usec) +
- msecs_to_jiffies(5000));
+ usecs_to_jiffies(delay_usec) +
+ msecs_to_jiffies(5000));
}
out_sleep:
diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c
index 07b94ed..73a49b8 100644
--- a/drivers/net/wireless/zd1211rw/zd_chip.c
+++ b/drivers/net/wireless/zd1211rw/zd_chip.c
@@ -129,7 +129,7 @@
r = zd_ioread16v_locked(chip, v16, a16, count16);
if (r) {
dev_dbg_f(zd_chip_dev(chip),
- "error: %s. Error number %d\n", __func__, r);
+ "error: zd_ioread16v_locked. Error number %d\n", r);
return r;
}
@@ -256,8 +256,8 @@
if (r) {
zd_usb_iowrite16v_async_end(&chip->usb, 0);
dev_dbg_f(zd_chip_dev(chip),
- "error _%s. Error number %d\n", __func__,
- r);
+ "error _zd_iowrite32v_locked."
+ " Error number %d\n", r);
return r;
}
}
diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig
index 5d8f3a9..6d0ae8f 100644
--- a/drivers/nfc/Kconfig
+++ b/drivers/nfc/Kconfig
@@ -29,7 +29,7 @@
into the kernel or say M to compile it as module.
config NFC_TRF7970A
- depends on !KERNEL_3_4
+ depends on !BACKPORT_KERNEL_3_4
tristate "Texas Instruments TRF7970a NFC driver"
depends on m
depends on SPI && NFC_DIGITAL
@@ -43,7 +43,7 @@
trf7970a.ko.
config NFC_MEI_PHY
- depends on !KERNEL_3_10
+ depends on !BACKPORT_KERNEL_3_10
tristate "MEI bus NFC device support"
depends on m
depends on INTEL_MEI && NFC_HCI
diff --git a/drivers/nfc/nfcwilink.c b/drivers/nfc/nfcwilink.c
index ce2e2cf..683671a 100644
--- a/drivers/nfc/nfcwilink.c
+++ b/drivers/nfc/nfcwilink.c
@@ -566,6 +566,7 @@
.remove = nfcwilink_remove,
.driver = {
.name = "nfcwilink",
+ .owner = THIS_MODULE,
},
};
diff --git a/drivers/nfc/pn544/i2c.c b/drivers/nfc/pn544/i2c.c
index fc02e8d..440291a 100644
--- a/drivers/nfc/pn544/i2c.c
+++ b/drivers/nfc/pn544/i2c.c
@@ -29,8 +29,8 @@
#include <linux/delay.h>
#include <linux/nfc.h>
#include <linux/firmware.h>
+#include <linux/unaligned/access_ok.h>
#include <linux/platform_data/pn544.h>
-#include <asm/unaligned.h>
#include <net/nfc/hci.h>
#include <net/nfc/llc.h>
diff --git a/drivers/nfc/st21nfca/i2c.c b/drivers/nfc/st21nfca/i2c.c
index 0572208..0ea756b 100644
--- a/drivers/nfc/st21nfca/i2c.c
+++ b/drivers/nfc/st21nfca/i2c.c
@@ -28,8 +28,8 @@
#include <linux/delay.h>
#include <linux/nfc.h>
#include <linux/firmware.h>
+#include <linux/unaligned/access_ok.h>
#include <linux/platform_data/st21nfca.h>
-#include <asm/unaligned.h>
#include <net/nfc/hci.h>
#include <net/nfc/llc.h>
@@ -72,6 +72,7 @@
struct nfc_hci_dev *hdev;
unsigned int gpio_ena;
+ unsigned int gpio_irq;
unsigned int irq_polarity;
struct sk_buff *pending_skb;
@@ -530,12 +531,20 @@
"clf_enable");
if (r) {
nfc_err(&client->dev, "Failed to request enable pin\n");
- return r;
+ return -ENODEV;
}
phy->gpio_ena = gpio;
- phy->irq_polarity = irq_get_trigger_type(client->irq);
+ /* IRQ */
+ r = irq_of_parse_and_map(pp, 0);
+ if (r < 0) {
+ nfc_err(&client->dev, "Unable to get irq, error: %d\n", r);
+ return r;
+ }
+
+ phy->irq_polarity = irq_get_trigger_type(r);
+ client->irq = r;
return 0;
}
@@ -551,6 +560,7 @@
struct st21nfca_nfc_platform_data *pdata;
struct st21nfca_i2c_phy *phy = i2c_get_clientdata(client);
int r;
+ int irq;
pdata = client->dev.platform_data;
if (pdata == NULL) {
@@ -559,18 +569,36 @@
}
/* store for later use */
+ phy->gpio_irq = pdata->gpio_irq;
phy->gpio_ena = pdata->gpio_ena;
phy->irq_polarity = pdata->irq_polarity;
+ r = devm_gpio_request_one(&client->dev, phy->gpio_irq, GPIOF_IN,
+ "wake_up");
+ if (r) {
+ pr_err("%s : gpio_request failed\n", __FILE__);
+ return -ENODEV;
+ }
+
if (phy->gpio_ena > 0) {
r = devm_gpio_request_one(&client->dev, phy->gpio_ena,
GPIOF_OUT_INIT_HIGH, "clf_enable");
if (r) {
pr_err("%s : ena gpio_request failed\n", __FILE__);
- return r;
+ return -ENODEV;
}
}
+ /* IRQ */
+ irq = gpio_to_irq(phy->gpio_irq);
+ if (irq < 0) {
+ nfc_err(&client->dev,
+ "Unable to get irq number for GPIO %d error %d\n",
+ phy->gpio_irq, r);
+ return -ENODEV;
+ }
+ client->irq = irq;
+
return 0;
}
@@ -628,7 +656,7 @@
r = st21nfca_hci_platform_init(phy);
if (r < 0) {
nfc_err(&client->dev, "Unable to reboot st21nfca\n");
- return r;
+ return -ENODEV;
}
r = devm_request_threaded_irq(&client->dev, client->irq, NULL,
@@ -659,13 +687,10 @@
return 0;
}
-#ifdef CONFIG_OF
static const struct of_device_id of_st21nfca_i2c_match[] = {
{ .compatible = "st,st21nfca_i2c", },
{}
};
-MODULE_DEVICE_TABLE(of, of_st21nfca_i2c_match);
-#endif
static struct i2c_driver st21nfca_hci_i2c_driver = {
.driver = {
diff --git a/drivers/nfc/st21nfca/st21nfca.c b/drivers/nfc/st21nfca/st21nfca.c
index f2596c8..a89e56c 100644
--- a/drivers/nfc/st21nfca/st21nfca.c
+++ b/drivers/nfc/st21nfca/st21nfca.c
@@ -77,6 +77,10 @@
((p & 0x0f) == (ST21NFCA_DM_PIPE_CREATED | ST21NFCA_DM_PIPE_OPEN))
#define ST21NFCA_NFC_MODE 0x03 /* NFC_MODE parameter*/
+#define ST21NFCA_EVT_FIELD_ON 0x11
+#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12
+#define ST21NFCA_EVT_CARD_ACTIVATED 0x13
+#define ST21NFCA_EVT_FIELD_OFF 0x14
static DECLARE_BITMAP(dev_mask, ST21NFCA_NUM_DEVICES);
@@ -837,11 +841,31 @@
static int st21nfca_hci_event_received(struct nfc_hci_dev *hdev, u8 gate,
u8 event, struct sk_buff *skb)
{
- pr_debug("hci event: %d gate: %x\n", event, gate);
+ int r;
+ struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
- switch (gate) {
- case ST21NFCA_RF_CARD_F_GATE:
- return st21nfca_dep_event_received(hdev, event, skb);
+ pr_debug("hci event: %d\n", event);
+
+ switch (event) {
+ case ST21NFCA_EVT_CARD_ACTIVATED:
+ if (gate == ST21NFCA_RF_CARD_F_GATE)
+ info->dep_info.curr_nfc_dep_pni = 0;
+ break;
+ case ST21NFCA_EVT_CARD_DEACTIVATED:
+ break;
+ case ST21NFCA_EVT_FIELD_ON:
+ break;
+ case ST21NFCA_EVT_FIELD_OFF:
+ break;
+ case ST21NFCA_EVT_SEND_DATA:
+ if (gate == ST21NFCA_RF_CARD_F_GATE) {
+ r = st21nfca_tm_event_send_data(hdev, skb, gate);
+ if (r < 0)
+ return r;
+ return 0;
+ }
+ info->dep_info.curr_nfc_dep_pni = 0;
+ return 1;
default:
return 1;
}
diff --git a/drivers/nfc/st21nfca/st21nfca.h b/drivers/nfc/st21nfca/st21nfca.h
index 7c2a852..a0b77f1 100644
--- a/drivers/nfc/st21nfca/st21nfca.h
+++ b/drivers/nfc/st21nfca/st21nfca.h
@@ -85,4 +85,6 @@
#define ST21NFCA_RF_CARD_F_GATE 0x24
+#define ST21NFCA_EVT_SEND_DATA 0x10
+
#endif /* __LOCAL_ST21NFCA_H_ */
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.c b/drivers/nfc/st21nfca/st21nfca_dep.c
index 8882181..bfb6df5 100644
--- a/drivers/nfc/st21nfca/st21nfca_dep.c
+++ b/drivers/nfc/st21nfca/st21nfca_dep.c
@@ -49,12 +49,6 @@
#define ST21NFCA_LR_BITS_PAYLOAD_SIZE_254B 0x30
#define ST21NFCA_GB_BIT 0x02
-#define ST21NFCA_EVT_SEND_DATA 0x10
-#define ST21NFCA_EVT_FIELD_ON 0x11
-#define ST21NFCA_EVT_CARD_DEACTIVATED 0x12
-#define ST21NFCA_EVT_CARD_ACTIVATED 0x13
-#define ST21NFCA_EVT_FIELD_OFF 0x14
-
#define ST21NFCA_EVT_CARD_F_BITRATE 0x16
#define ST21NFCA_EVT_READER_F_BITRATE 0x13
#define ST21NFCA_PSL_REQ_SEND_SPEED(brs) (brs & 0x38)
@@ -378,8 +372,8 @@
return r;
}
-static int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev,
- struct sk_buff *skb)
+int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb,
+ u8 gate)
{
u8 cmd0, cmd1;
int r;
@@ -406,42 +400,7 @@
}
return r;
}
-
-/*
- * Returns:
- * <= 0: driver handled the event, skb consumed
- * 1: driver does not handle the event, please do standard processing
- */
-int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
- u8 event, struct sk_buff *skb)
-{
- int r = 0;
- struct st21nfca_hci_info *info = nfc_hci_get_clientdata(hdev);
-
- pr_debug("dep event: %d\n", event);
-
- switch (event) {
- case ST21NFCA_EVT_CARD_ACTIVATED:
- info->dep_info.curr_nfc_dep_pni = 0;
- break;
- case ST21NFCA_EVT_CARD_DEACTIVATED:
- break;
- case ST21NFCA_EVT_FIELD_ON:
- break;
- case ST21NFCA_EVT_FIELD_OFF:
- break;
- case ST21NFCA_EVT_SEND_DATA:
- r = st21nfca_tm_event_send_data(hdev, skb);
- if (r < 0)
- return r;
- return 0;
- default:
- return 1;
- }
- kfree_skb(skb);
- return r;
-}
-EXPORT_SYMBOL(st21nfca_dep_event_received);
+EXPORT_SYMBOL(st21nfca_tm_event_send_data);
static void st21nfca_im_send_psl_req(struct nfc_hci_dev *hdev, u8 did, u8 bsi,
u8 bri, u8 lri)
diff --git a/drivers/nfc/st21nfca/st21nfca_dep.h b/drivers/nfc/st21nfca/st21nfca_dep.h
index baf4664..ca213de 100644
--- a/drivers/nfc/st21nfca/st21nfca_dep.h
+++ b/drivers/nfc/st21nfca/st21nfca_dep.h
@@ -32,8 +32,8 @@
u8 lri;
} __packed;
-int st21nfca_dep_event_received(struct nfc_hci_dev *hdev,
- u8 event, struct sk_buff *skb);
+int st21nfca_tm_event_send_data(struct nfc_hci_dev *hdev, struct sk_buff *skb,
+ u8 gate);
int st21nfca_tm_send_dep_res(struct nfc_hci_dev *hdev, struct sk_buff *skb);
int st21nfca_im_send_atr_req(struct nfc_hci_dev *hdev, u8 *gb, size_t gb_len);
diff --git a/drivers/nfc/st21nfcb/i2c.c b/drivers/nfc/st21nfcb/i2c.c
index 01ba865..c5d2427 100644
--- a/drivers/nfc/st21nfcb/i2c.c
+++ b/drivers/nfc/st21nfcb/i2c.c
@@ -50,6 +50,7 @@
struct i2c_client *i2c_dev;
struct llt_ndlc *ndlc;
+ unsigned int gpio_irq;
unsigned int gpio_reset;
unsigned int irq_polarity;
@@ -80,6 +81,8 @@
{
struct st21nfcb_i2c_phy *phy = phy_id;
+ pr_info("\n");
+
phy->powered = 0;
/* reset chip in order to flush clf */
gpio_set_value(phy->gpio_reset, 0);
@@ -255,11 +258,19 @@
GPIOF_OUT_INIT_HIGH, "clf_reset");
if (r) {
nfc_err(&client->dev, "Failed to request reset pin\n");
- return r;
+ return -ENODEV;
}
phy->gpio_reset = gpio;
- phy->irq_polarity = irq_get_trigger_type(client->irq);
+ /* IRQ */
+ r = irq_of_parse_and_map(pp, 0);
+ if (r < 0) {
+ nfc_err(&client->dev, "Unable to get irq, error: %d\n", r);
+ return r;
+ }
+
+ phy->irq_polarity = irq_get_trigger_type(r);
+ client->irq = r;
return 0;
}
@@ -275,6 +286,7 @@
struct st21nfcb_nfc_platform_data *pdata;
struct st21nfcb_i2c_phy *phy = i2c_get_clientdata(client);
int r;
+ int irq;
pdata = client->dev.platform_data;
if (pdata == NULL) {
@@ -283,16 +295,34 @@
}
/* store for later use */
+ phy->gpio_irq = pdata->gpio_irq;
phy->gpio_reset = pdata->gpio_reset;
phy->irq_polarity = pdata->irq_polarity;
+ r = devm_gpio_request_one(&client->dev, phy->gpio_irq,
+ GPIOF_IN, "clf_irq");
+ if (r) {
+ pr_err("%s : gpio_request failed\n", __FILE__);
+ return -ENODEV;
+ }
+
r = devm_gpio_request_one(&client->dev,
phy->gpio_reset, GPIOF_OUT_INIT_HIGH, "clf_reset");
if (r) {
pr_err("%s : reset gpio_request failed\n", __FILE__);
- return r;
+ return -ENODEV;
}
+ /* IRQ */
+ irq = gpio_to_irq(phy->gpio_irq);
+ if (irq < 0) {
+ nfc_err(&client->dev,
+ "Unable to get irq number for GPIO %d error %d\n",
+ phy->gpio_irq, r);
+ return -ENODEV;
+ }
+ client->irq = irq;
+
return 0;
}
@@ -371,13 +401,10 @@
return 0;
}
-#ifdef CONFIG_OF
static const struct of_device_id of_st21nfcb_i2c_match[] = {
{ .compatible = "st,st21nfcb_i2c", },
{}
};
-MODULE_DEVICE_TABLE(of, of_st21nfcb_i2c_match);
-#endif
static struct i2c_driver st21nfcb_nci_i2c_driver = {
.driver = {
diff --git a/drivers/nfc/st21nfcb/ndlc.c b/drivers/nfc/st21nfcb/ndlc.c
index bac50e8..e7bff89 100644
--- a/drivers/nfc/st21nfcb/ndlc.c
+++ b/drivers/nfc/st21nfcb/ndlc.c
@@ -266,7 +266,7 @@
*ndlc_id = ndlc;
- /* initialize timers */
+ /* start timers */
init_timer(&ndlc->t1_timer);
ndlc->t1_timer.data = (unsigned long)ndlc;
ndlc->t1_timer.function = ndlc_t1_timeout;
diff --git a/drivers/nfc/trf7970a.c b/drivers/nfc/trf7970a.c
index aa6a333..d2ccd28 100644
--- a/drivers/nfc/trf7970a.c
+++ b/drivers/nfc/trf7970a.c
@@ -2154,7 +2154,7 @@
}
#endif
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_RUNTIME
static int trf7970a_pm_runtime_suspend(struct device *dev)
{
struct spi_device *spi = container_of(dev, struct spi_device, dev);
diff --git a/drivers/ssb/Kconfig b/drivers/ssb/Kconfig
index cc86fa1..4bc1252 100644
--- a/drivers/ssb/Kconfig
+++ b/drivers/ssb/Kconfig
@@ -128,7 +128,7 @@
PCIcore hostmode operation (external PCI bus).
config SSB_DRIVER_MIPS
- depends on !KERNEL_3_3
+ depends on !BACKPORT_KERNEL_3_3
bool "SSB Broadcom MIPS core driver"
depends on SSB && MIPS
select SSB_SERIAL
diff --git a/drivers/ssb/driver_mipscore.c b/drivers/ssb/driver_mipscore.c
index 7b986f9..0907706 100644
--- a/drivers/ssb/driver_mipscore.c
+++ b/drivers/ssb/driver_mipscore.c
@@ -15,9 +15,6 @@
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/time.h>
-#ifdef CONFIG_BCM47XX
-#include <bcm47xx_nvram.h>
-#endif
#include "ssb_private.h"
@@ -213,7 +210,6 @@
static void ssb_mips_flash_detect(struct ssb_mipscore *mcore)
{
struct ssb_bus *bus = mcore->dev->bus;
- struct ssb_sflash *sflash = &mcore->sflash;
struct ssb_pflash *pflash = &mcore->pflash;
/* When there is no chipcommon on the bus there is 4MB flash */
@@ -246,15 +242,7 @@
}
ssb_pflash:
- if (sflash->present) {
-#ifdef CONFIG_BCM47XX
- bcm47xx_nvram_init_from_mem(sflash->window, sflash->size);
-#endif
- } else if (pflash->present) {
-#ifdef CONFIG_BCM47XX
- bcm47xx_nvram_init_from_mem(pflash->window, pflash->window_size);
-#endif
-
+ if (pflash->present) {
ssb_pflash_data.width = pflash->buswidth;
ssb_pflash_resource.start = pflash->window;
ssb_pflash_resource.end = pflash->window + pflash->window_size;
diff --git a/drivers/ssb/pcihost_wrapper.c b/drivers/ssb/pcihost_wrapper.c
index b9ea3fb..69161bb 100644
--- a/drivers/ssb/pcihost_wrapper.c
+++ b/drivers/ssb/pcihost_wrapper.c
@@ -11,17 +11,15 @@
* Licensed under the GNU/GPL. See COPYING for details.
*/
-#include <linux/pm.h>
#include <linux/pci.h>
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/ssb/ssb.h>
-#ifdef CONFIG_PM_SLEEP
-static int ssb_pcihost_suspend(struct device *d)
+#ifdef CONFIG_PM
+static int ssb_pcihost_suspend(struct pci_dev *dev, pm_message_t state)
{
- struct pci_dev *dev = to_pci_dev(d);
struct ssb_bus *ssb = pci_get_drvdata(dev);
int err;
@@ -30,25 +28,17 @@
return err;
pci_save_state(dev);
pci_disable_device(dev);
-
- /* if there is a wakeup enabled child device on ssb bus,
- enable pci wakeup posibility. */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0)
- device_set_wakeup_enable(d, d->power.wakeup_path);
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,2,0) */
-
- pci_prepare_to_sleep(dev);
+ pci_set_power_state(dev, pci_choose_state(dev, state));
return 0;
}
-static int ssb_pcihost_resume(struct device *d)
+static int ssb_pcihost_resume(struct pci_dev *dev)
{
- struct pci_dev *dev = to_pci_dev(d);
struct ssb_bus *ssb = pci_get_drvdata(dev);
int err;
- pci_back_from_sleep(dev);
+ pci_set_power_state(dev, PCI_D0);
err = pci_enable_device(dev);
if (err)
return err;
@@ -59,12 +49,10 @@
return 0;
}
-
-static const struct dev_pm_ops ssb_pcihost_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(ssb_pcihost_suspend, ssb_pcihost_resume)
-};
-
-#endif /* CONFIG_PM_SLEEP */
+#else /* CONFIG_PM */
+# define ssb_pcihost_suspend NULL
+# define ssb_pcihost_resume NULL
+#endif /* CONFIG_PM */
static int ssb_pcihost_probe(struct pci_dev *dev,
const struct pci_device_id *id)
@@ -127,9 +115,8 @@
{
driver->probe = ssb_pcihost_probe;
driver->remove = ssb_pcihost_remove;
-#ifdef CONFIG_PM_SLEEP
- driver->driver.pm = &ssb_pcihost_pm_ops;
-#endif
+ driver->suspend = ssb_pcihost_suspend;
+ driver->resume = ssb_pcihost_resume;
return pci_register_driver(driver);
}
diff --git a/include/linux/ath9k_platform.h b/include/linux/ath9k_platform.h
index 33eb274..a495a95 100644
--- a/include/linux/ath9k_platform.h
+++ b/include/linux/ath9k_platform.h
@@ -31,11 +31,8 @@
u32 gpio_mask;
u32 gpio_val;
- bool endian_check;
bool is_clk_25mhz;
bool tx_gain_buffalo;
- bool disable_2ghz;
- bool disable_5ghz;
int (*get_mac_revision)(void);
int (*external_reset)(void);
diff --git a/include/linux/average.h b/include/linux/average.h
index e900121..dc5ba21 100644
--- a/include/linux/average.h
+++ b/include/linux/average.h
@@ -1,5 +1,5 @@
/* Automatically created during backport process */
-#ifndef CPTCFG_BPAUTO_BUILD_AVERAGE
+#ifndef CPTCFG_BACKPORT_BUILD_AVERAGE
#include_next <linux/average.h>
#else
#undef ewma_init
@@ -7,4 +7,4 @@
#undef ewma_add
#define ewma_add LINUX_BACKPORT(ewma_add)
#include <linux/backport-average.h>
-#endif /* CPTCFG_BPAUTO_BUILD_AVERAGE */
+#endif /* CPTCFG_BACKPORT_BUILD_AVERAGE */
diff --git a/include/linux/backport-devcoredump.h b/include/linux/backport-devcoredump.h
deleted file mode 100644
index c1d2d00..0000000
--- a/include/linux/backport-devcoredump.h
+++ /dev/null
@@ -1,35 +0,0 @@
-#ifndef __DEVCOREDUMP_H
-#define __DEVCOREDUMP_H
-
-#include <linux/device.h>
-#include <linux/module.h>
-#include <linux/vmalloc.h>
-
-#ifdef CPTCFG_BPAUTO_WANT_DEV_COREDUMP
-void dev_coredumpv(struct device *dev, const void *data, size_t datalen,
- gfp_t gfp);
-
-void dev_coredumpm(struct device *dev, struct module *owner,
- const void *data, size_t datalen, gfp_t gfp,
- ssize_t (*read)(char *buffer, loff_t offset, size_t count,
- const void *data, size_t datalen),
- void (*free)(const void *data));
-#else
-static inline void dev_coredumpv(struct device *dev, const void *data,
- size_t datalen, gfp_t gfp)
-{
- vfree(data);
-}
-
-static inline void
-dev_coredumpm(struct device *dev, struct module *owner,
- const void *data, size_t datalen, gfp_t gfp,
- ssize_t (*read)(char *buffer, loff_t offset, size_t count,
- const void *data, size_t datalen),
- void (*free)(const void *data))
-{
- free(data);
-}
-#endif /* CPTCFG_BPAUTO_WANT_DEV_COREDUMP */
-
-#endif /* __DEVCOREDUMP_H */
diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h
index 2ad74c6..8356303 100644
--- a/include/linux/bcma/bcma.h
+++ b/include/linux/bcma/bcma.h
@@ -447,6 +447,4 @@
#define BCMA_DMA_TRANSLATION_DMA64_CMT 0x80000000 /* Client Mode Translation for 64-bit DMA */
extern u32 bcma_core_dma_translation(struct bcma_device *core);
-extern unsigned int bcma_core_irq(struct bcma_device *core, int num);
-
#endif /* LINUX_BCMA_H_ */
diff --git a/include/linux/bcma/bcma_driver_mips.h b/include/linux/bcma/bcma_driver_mips.h
index 907c48c..73c8a7b 100644
--- a/include/linux/bcma/bcma_driver_mips.h
+++ b/include/linux/bcma/bcma_driver_mips.h
@@ -43,12 +43,12 @@
extern void bcma_core_mips_init(struct bcma_drv_mips *mcore);
extern void bcma_core_mips_early_init(struct bcma_drv_mips *mcore);
-extern unsigned int bcma_core_mips_irq(struct bcma_device *dev);
+extern unsigned int bcma_core_irq(struct bcma_device *core);
#else
static inline void bcma_core_mips_init(struct bcma_drv_mips *mcore) { }
static inline void bcma_core_mips_early_init(struct bcma_drv_mips *mcore) { }
-static inline unsigned int bcma_core_mips_irq(struct bcma_device *dev)
+static inline unsigned int bcma_core_irq(struct bcma_device *core)
{
return 0;
}
diff --git a/include/linux/devcoredump.h b/include/linux/devcoredump.h
deleted file mode 100644
index 9c215fa..0000000
--- a/include/linux/devcoredump.h
+++ /dev/null
@@ -1,10 +0,0 @@
-/* Automatically created during backport process */
-#ifndef CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP
-#include_next <linux/devcoredump.h>
-#else
-#undef dev_coredumpv
-#define dev_coredumpv LINUX_BACKPORT(dev_coredumpv)
-#undef dev_coredumpm
-#define dev_coredumpm LINUX_BACKPORT(dev_coredumpm)
-#include <linux/backport-devcoredump.h>
-#endif /* CPTCFG_BPAUTO_BUILD_WANT_DEV_COREDUMP */
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 4f4eea8..b1be39c 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -19,7 +19,6 @@
#include <linux/types.h>
#include <linux/if_ether.h>
#include <asm/byteorder.h>
-#include <asm/unaligned.h>
/*
* DS bit usage
@@ -1067,12 +1066,6 @@
/* TDLS */
-/* Channel switch timing */
-struct ieee80211_ch_switch_timing {
- __le16 switch_time;
- __le16 switch_timeout;
-} __packed;
-
/* Link-id information element */
struct ieee80211_tdls_lnkie {
u8 ie_type; /* Link Identifier IE */
@@ -1114,15 +1107,6 @@
u8 dialog_token;
u8 variable[0];
} __packed discover_req;
- struct {
- u8 target_channel;
- u8 oper_class;
- u8 variable[0];
- } __packed chan_switch_req;
- struct {
- __le16 status_code;
- u8 variable[0];
- } __packed chan_switch_resp;
} u;
} __packed;
@@ -1290,7 +1274,7 @@
#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2
/*
- * Maximum length of AMPDU that the STA can receive in high-throughput (HT).
+ * Maximum length of AMPDU that the STA can receive.
* Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
*/
enum ieee80211_max_ampdu_length_exp {
@@ -1300,21 +1284,6 @@
IEEE80211_HT_MAX_AMPDU_64K = 3
};
-/*
- * Maximum length of AMPDU that the STA can receive in VHT.
- * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets)
- */
-enum ieee80211_vht_max_ampdu_length_exp {
- IEEE80211_VHT_MAX_AMPDU_8K = 0,
- IEEE80211_VHT_MAX_AMPDU_16K = 1,
- IEEE80211_VHT_MAX_AMPDU_32K = 2,
- IEEE80211_VHT_MAX_AMPDU_64K = 3,
- IEEE80211_VHT_MAX_AMPDU_128K = 4,
- IEEE80211_VHT_MAX_AMPDU_256K = 5,
- IEEE80211_VHT_MAX_AMPDU_512K = 6,
- IEEE80211_VHT_MAX_AMPDU_1024K = 7
-};
-
#define IEEE80211_HT_MAX_AMPDU_FACTOR 13
/* Minimum MPDU start spacing */
@@ -2029,16 +1998,6 @@
WLAN_TDLS_DISCOVERY_REQUEST = 10,
};
-/* Extended Channel Switching capability to be set in the 1st byte of
- * the @WLAN_EID_EXT_CAPABILITY information element
- */
-#define WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING BIT(2)
-
-/* TDLS capabilities in the the 4th byte of @WLAN_EID_EXT_CAPABILITY */
-#define WLAN_EXT_CAPA4_TDLS_BUFFER_STA BIT(4)
-#define WLAN_EXT_CAPA4_TDLS_PEER_PSM BIT(5)
-#define WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH BIT(6)
-
/* Interworking capabilities are set in 7th bit of 4th byte of the
* @WLAN_EID_EXT_CAPABILITY information element
*/
@@ -2050,7 +2009,6 @@
*/
#define WLAN_EXT_CAPA5_TDLS_ENABLED BIT(5)
#define WLAN_EXT_CAPA5_TDLS_PROHIBITED BIT(6)
-#define WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED BIT(7)
#define WLAN_EXT_CAPA8_OPMODE_NOTIF BIT(6)
#define WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED BIT(7)
@@ -2058,9 +2016,6 @@
/* TDLS specific payload type in the LLC/SNAP header */
#define WLAN_TDLS_SNAP_RFTYPE 0x2
-/* BSS Coex IE information field bits */
-#define WLAN_BSS_COEX_INFORMATION_REQUEST BIT(0)
-
/**
* enum - mesh synchronization method identifier
*
@@ -2443,30 +2398,6 @@
return !!(tim->virtual_map[index] & mask);
}
-/**
- * ieee80211_get_tdls_action - get tdls packet action (or -1, if not tdls packet)
- * @skb: the skb containing the frame, length will not be checked
- * @hdr_size: the size of the ieee80211_hdr that starts at skb->data
- *
- * This function assumes the frame is a data frame, and that the network header
- * is in the correct place.
- */
-static inline int ieee80211_get_tdls_action(struct sk_buff *skb, u32 hdr_size)
-{
- if (!skb_is_nonlinear(skb) &&
- skb->len > (skb_network_offset(skb) + 2)) {
- /* Point to where the indication of TDLS should start */
- const u8 *tdls_data = skb_network_header(skb) - 2;
-
- if (get_unaligned_be16(tdls_data) == ETH_P_TDLS &&
- tdls_data[2] == WLAN_TDLS_SNAP_RFTYPE &&
- tdls_data[3] == WLAN_CATEGORY_TDLS)
- return tdls_data[4];
- }
-
- return -1;
-}
-
/* convert time units */
#define TU_TO_JIFFIES(x) (usecs_to_jiffies((x) * 1024))
#define TU_TO_EXP_TIME(x) (jiffies + TU_TO_JIFFIES(x))
diff --git a/include/linux/nl802154.h b/include/linux/nl802154.h
index 167342c..20163b9 100644
--- a/include/linux/nl802154.h
+++ b/include/linux/nl802154.h
@@ -12,6 +12,10 @@
* 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 NL802154_H
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index e63c02a..1fa99a3 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -522,8 +522,6 @@
#define PCI_DEVICE_ID_AMD_15H_M10H_F3 0x1403
#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F3 0x141d
#define PCI_DEVICE_ID_AMD_15H_M30H_NB_F4 0x141e
-#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F3 0x1573
-#define PCI_DEVICE_ID_AMD_15H_M60H_NB_F4 0x1574
#define PCI_DEVICE_ID_AMD_15H_NB_F0 0x1600
#define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601
#define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602
@@ -564,7 +562,6 @@
#define PCI_DEVICE_ID_AMD_8131_BRIDGE 0x7450
#define PCI_DEVICE_ID_AMD_8131_APIC 0x7451
#define PCI_DEVICE_ID_AMD_8132_BRIDGE 0x7458
-#define PCI_DEVICE_ID_AMD_NL_USB 0x7912
#define PCI_DEVICE_ID_AMD_CS5535_IDE 0x208F
#define PCI_DEVICE_ID_AMD_CS5536_ISA 0x2090
#define PCI_DEVICE_ID_AMD_CS5536_FLASH 0x2091
diff --git a/include/linux/platform_data/st21nfca.h b/include/linux/platform_data/st21nfca.h
index 5087fff..1730312 100644
--- a/include/linux/platform_data/st21nfca.h
+++ b/include/linux/platform_data/st21nfca.h
@@ -24,6 +24,7 @@
#define ST21NFCA_HCI_DRIVER_NAME "st21nfca_hci"
struct st21nfca_nfc_platform_data {
+ unsigned int gpio_irq;
unsigned int gpio_ena;
unsigned int irq_polarity;
};
diff --git a/include/linux/platform_data/st21nfcb.h b/include/linux/platform_data/st21nfcb.h
index c3b432f..2d11f1f 100644
--- a/include/linux/platform_data/st21nfcb.h
+++ b/include/linux/platform_data/st21nfcb.h
@@ -24,6 +24,7 @@
#define ST21NFCB_NCI_DRIVER_NAME "st21nfcb_nci"
struct st21nfcb_nfc_platform_data {
+ unsigned int gpio_irq;
unsigned int gpio_reset;
unsigned int irq_polarity;
};
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index d9a4905..26088fe 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -78,7 +78,6 @@
# define EVENT_NO_RUNTIME_PM 9
# define EVENT_RX_KILL 10
# define EVENT_LINK_CHANGE 11
-# define EVENT_SET_RX_MODE 12
};
static inline struct usb_driver *driver_of(struct usb_interface *intf)
@@ -160,9 +159,6 @@
/* called by minidriver when receiving indication */
void (*indication)(struct usbnet *dev, void *ind, int indlen);
- /* rx mode change (device changes address list filtering) */
- void (*set_rx_mode)(struct usbnet *dev);
-
/* for new devices, use the descriptor-reading code instead */
int in; /* rx endpoint */
int out; /* tx endpoint */
diff --git a/include/media/davinci/vpbe.h b/include/media/davinci/vpbe.h
index 4376bee..57585c7 100644
--- a/include/media/davinci/vpbe.h
+++ b/include/media/davinci/vpbe.h
@@ -63,7 +63,7 @@
* output basis. If per mode is needed, we may have to move this to
* mode_info structure
*/
- u32 if_params;
+ enum v4l2_mbus_pixelcode if_params;
};
/* encoder configuration info */
diff --git a/include/media/davinci/vpbe_display.h b/include/media/davinci/vpbe_display.h
index fa0247a..637749a 100644
--- a/include/media/davinci/vpbe_display.h
+++ b/include/media/davinci/vpbe_display.h
@@ -70,6 +70,8 @@
/* vpbe display object structure */
struct vpbe_layer {
+ /* number of buffers in fbuffers */
+ unsigned int numbuffers;
/* Pointer to the vpbe_display */
struct vpbe_display *disp_dev;
/* Pointer pointing to current v4l2_buffer */
@@ -89,6 +91,10 @@
/* V4l2 specific parameters */
/* Identifies video device for this layer */
struct video_device video_dev;
+ /* This field keeps track of type of buffer exchange mechanism user
+ * has selected
+ */
+ enum v4l2_memory memory;
/* Used to store pixel format */
struct v4l2_pix_format pix_fmt;
enum v4l2_field buf_field;
@@ -100,8 +106,12 @@
unsigned char window_enable;
/* number of open instances of the layer */
unsigned int usrs;
+ /* number of users performing IO */
+ unsigned int io_usrs;
/* Indicates id of the field which is being displayed */
unsigned int field_id;
+ /* Indicates whether streaming started */
+ unsigned char started;
/* Identifies device object */
enum vpbe_display_device_id device_id;
/* facilitation of ioctl ops lock by v4l2*/
@@ -121,6 +131,17 @@
struct osd_state *osd_device;
};
+/* File handle structure */
+struct vpbe_fh {
+ struct v4l2_fh fh;
+ /* vpbe device structure */
+ struct vpbe_display *disp_dev;
+ /* pointer to layer object for opened device */
+ struct vpbe_layer *layer;
+ /* Indicates whether this file handle is doing IO */
+ unsigned char io_allowed;
+};
+
struct buf_config_params {
unsigned char min_numbuffers;
unsigned char numbuffers[VPBE_DISPLAY_MAX_DEVICES];
diff --git a/include/media/davinci/vpbe_venc.h b/include/media/davinci/vpbe_venc.h
index 3dbd200..476fafc 100644
--- a/include/media/davinci/vpbe_venc.h
+++ b/include/media/davinci/vpbe_venc.h
@@ -30,10 +30,11 @@
#define VENC_SECOND_FIELD BIT(2)
struct venc_platform_data {
- int (*setup_pinmux)(u32 if_type, int field);
+ int (*setup_pinmux)(enum v4l2_mbus_pixelcode if_type,
+ int field);
int (*setup_clock)(enum vpbe_enc_timings_type type,
unsigned int pixclock);
- int (*setup_if_config)(u32 pixcode);
+ int (*setup_if_config)(enum v4l2_mbus_pixelcode pixcode);
/* Number of LCD outputs supported */
int num_lcd_outputs;
struct vpbe_if_params *lcd_if_params;
diff --git a/include/media/exynos-fimc.h b/include/media/exynos-fimc.h
index 69bcd2a..aa44660 100644
--- a/include/media/exynos-fimc.h
+++ b/include/media/exynos-fimc.h
@@ -101,7 +101,7 @@
* @flags: flags indicating which operation mode format applies to
*/
struct fimc_fmt {
- u32 mbus_code;
+ enum v4l2_mbus_pixelcode mbus_code;
char *name;
u32 fourcc;
u32 color;
diff --git a/include/media/lirc_dev.h b/include/media/lirc_dev.h
index 05e7ad5..78f0637 100644
--- a/include/media/lirc_dev.h
+++ b/include/media/lirc_dev.h
@@ -29,13 +29,14 @@
/* Using chunks instead of bytes pretends to simplify boundary checking
* And should allow for some performance fine tunning later */
struct kfifo fifo;
+ u8 fifo_initialized;
};
static inline void lirc_buffer_clear(struct lirc_buffer *buf)
{
unsigned long flags;
- if (kfifo_initialized(&buf->fifo)) {
+ if (buf->fifo_initialized) {
spin_lock_irqsave(&buf->fifo_lock, flags);
kfifo_reset(&buf->fifo);
spin_unlock_irqrestore(&buf->fifo_lock, flags);
@@ -55,14 +56,17 @@
buf->chunk_size = chunk_size;
buf->size = size;
ret = kfifo_alloc(&buf->fifo, size * chunk_size, GFP_KERNEL);
+ if (ret == 0)
+ buf->fifo_initialized = 1;
return ret;
}
static inline void lirc_buffer_free(struct lirc_buffer *buf)
{
- if (kfifo_initialized(&buf->fifo)) {
+ if (buf->fifo_initialized) {
kfifo_free(&buf->fifo);
+ buf->fifo_initialized = 0;
} else
WARN(1, "calling %s on an uninitialized lirc_buffer\n",
__func__);
diff --git a/include/media/radio-si4713.h b/include/media/radio-si4713.h
new file mode 100644
index 0000000..f6aae29
--- /dev/null
+++ b/include/media/radio-si4713.h
@@ -0,0 +1,30 @@
+/*
+ * include/media/radio-si4713.h
+ *
+ * Board related data definitions for Si4713 radio transmitter chip.
+ *
+ * Copyright (c) 2009 Nokia Corporation
+ * Contact: Eduardo Valentin <eduardo.valentin@nokia.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#ifndef RADIO_SI4713_H
+#define RADIO_SI4713_H
+
+#include <linux/i2c.h>
+
+#define SI4713_NAME "radio-si4713"
+
+/*
+ * Platform dependent definition
+ */
+struct radio_si4713_platform_data {
+ int i2c_bus;
+ struct i2c_board_info *subdev_board_info;
+};
+
+#endif /* ifndef RADIO_SI4713_H*/
diff --git a/include/media/si4713.h b/include/media/si4713.h
index be4f58e..f98a0a7 100644
--- a/include/media/si4713.h
+++ b/include/media/si4713.h
@@ -23,7 +23,9 @@
* Platform dependent definition
*/
struct si4713_platform_data {
- bool is_platform_device;
+ const char * const *supply_names;
+ unsigned supplies;
+ int gpio_reset; /* < 0 if not used */
};
/*
diff --git a/include/media/soc_camera.h b/include/media/soc_camera.h
index 2f6261f..865246b 100644
--- a/include/media/soc_camera.h
+++ b/include/media/soc_camera.h
@@ -296,7 +296,7 @@
* format setup.
*/
struct soc_camera_format_xlate {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
const struct soc_mbus_pixelfmt *host_fmt;
};
diff --git a/include/media/soc_mediabus.h b/include/media/soc_mediabus.h
index 2ff7737..d33f6d0 100644
--- a/include/media/soc_mediabus.h
+++ b/include/media/soc_mediabus.h
@@ -91,16 +91,16 @@
* @fmt: pixel format description
*/
struct soc_mbus_lookup {
- u32 code;
+ enum v4l2_mbus_pixelcode code;
struct soc_mbus_pixelfmt fmt;
};
const struct soc_mbus_pixelfmt *soc_mbus_find_fmtdesc(
- u32 code,
+ enum v4l2_mbus_pixelcode code,
const struct soc_mbus_lookup *lookup,
int n);
const struct soc_mbus_pixelfmt *soc_mbus_get_fmtdesc(
- u32 code);
+ enum v4l2_mbus_pixelcode code);
s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf);
s32 soc_mbus_image_size(const struct soc_mbus_pixelfmt *mf,
u32 bytes_per_line, u32 height);
diff --git a/include/media/v4l2-common.h b/include/media/v4l2-common.h
index 1cc0c5b..48f9748 100644
--- a/include/media/v4l2-common.h
+++ b/include/media/v4l2-common.h
@@ -80,9 +80,24 @@
/* ------------------------------------------------------------------------- */
-/* Control helper function */
+/* Control helper functions */
+int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
+ const char * const *menu_items);
+const char *v4l2_ctrl_get_name(u32 id);
+const char * const *v4l2_ctrl_get_menu(u32 id);
+const s64 *v4l2_ctrl_get_int_menu(u32 id, u32 *len);
int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def);
+int v4l2_ctrl_query_menu(struct v4l2_querymenu *qmenu,
+ struct v4l2_queryctrl *qctrl, const char * const *menu_items);
+#define V4L2_CTRL_MENU_IDS_END (0xffffffff)
+int v4l2_ctrl_query_menu_valid_items(struct v4l2_querymenu *qmenu, const u32 *ids);
+
+/* Note: ctrl_classes points to an array of u32 pointers. Each u32 array is a
+ 0-terminated array of control IDs. Each array must be sorted low to high
+ and belong to the same control class. The array of u32 pointers must also
+ be sorted, from low class IDs to high class IDs. */
+u32 v4l2_ctrl_next(const u32 * const *ctrl_classes, u32 id);
/* ------------------------------------------------------------------------- */
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 911f3e5..b7cd7a6 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -670,31 +670,6 @@
*/
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv);
-/** v4l2_ctrl_get_name() - Get the name of the control
- * @id: The control ID.
- *
- * This function returns the name of the given control ID or NULL if it isn't
- * a known control.
- */
-const char *v4l2_ctrl_get_name(u32 id);
-
-/** v4l2_ctrl_get_menu() - Get the menu string array of the control
- * @id: The control ID.
- *
- * This function returns the NULL-terminated menu string array name of the
- * given control ID or NULL if it isn't a known menu control.
- */
-const char * const *v4l2_ctrl_get_menu(u32 id);
-
-/** v4l2_ctrl_get_int_menu() - Get the integer menu array of the control
- * @id: The control ID.
- * @len: The size of the integer array.
- *
- * This function returns the integer array of the given control ID or NULL if it
- * if it isn't a known integer menu control.
- */
-const s64 *v4l2_ctrl_get_int_menu(u32 id, u32 *len);
-
/** v4l2_ctrl_g_ctrl() - Helper function to get the control's value from within a driver.
* @ctrl: The control.
*
diff --git a/include/media/v4l2-image-sizes.h b/include/media/v4l2-image-sizes.h
index a07d7a6..10daf92 100644
--- a/include/media/v4l2-image-sizes.h
+++ b/include/media/v4l2-image-sizes.h
@@ -25,19 +25,10 @@
#define QVGA_WIDTH 320
#define QVGA_HEIGHT 240
-#define SVGA_WIDTH 800
-#define SVGA_HEIGHT 600
-
#define SXGA_WIDTH 1280
#define SXGA_HEIGHT 1024
#define VGA_WIDTH 640
#define VGA_HEIGHT 480
-#define UXGA_WIDTH 1600
-#define UXGA_HEIGHT 1200
-
-#define XGA_WIDTH 1024
-#define XGA_HEIGHT 768
-
#endif /* _IMAGE_SIZES_H */
diff --git a/include/media/v4l2-mediabus.h b/include/media/v4l2-mediabus.h
index 38d960d..395c4a9 100644
--- a/include/media/v4l2-mediabus.h
+++ b/include/media/v4l2-mediabus.h
@@ -94,20 +94,16 @@
pix_fmt->height = mbus_fmt->height;
pix_fmt->field = mbus_fmt->field;
pix_fmt->colorspace = mbus_fmt->colorspace;
- pix_fmt->ycbcr_enc = mbus_fmt->ycbcr_enc;
- pix_fmt->quantization = mbus_fmt->quantization;
}
static inline void v4l2_fill_mbus_format(struct v4l2_mbus_framefmt *mbus_fmt,
const struct v4l2_pix_format *pix_fmt,
- u32 code)
+ enum v4l2_mbus_pixelcode code)
{
mbus_fmt->width = pix_fmt->width;
mbus_fmt->height = pix_fmt->height;
mbus_fmt->field = pix_fmt->field;
mbus_fmt->colorspace = pix_fmt->colorspace;
- mbus_fmt->ycbcr_enc = pix_fmt->ycbcr_enc;
- mbus_fmt->quantization = pix_fmt->quantization;
mbus_fmt->code = code;
}
diff --git a/include/media/v4l2-subdev.h b/include/media/v4l2-subdev.h
index 063a83e..8e95674 100644
--- a/include/media/v4l2-subdev.h
+++ b/include/media/v4l2-subdev.h
@@ -341,7 +341,7 @@
int (*query_dv_timings)(struct v4l2_subdev *sd,
struct v4l2_dv_timings *timings);
int (*enum_mbus_fmt)(struct v4l2_subdev *sd, unsigned int index,
- u32 *code);
+ enum v4l2_mbus_pixelcode *code);
int (*enum_mbus_fsizes)(struct v4l2_subdev *sd,
struct v4l2_frmsizeenum *fsize);
int (*g_mbus_fmt)(struct v4l2_subdev *sd,
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index e320202..69a9595 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -82,17 +82,14 @@
* unmap_dmabuf.
*/
struct vb2_mem_ops {
- void *(*alloc)(void *alloc_ctx, unsigned long size,
- enum dma_data_direction dma_dir,
- gfp_t gfp_flags);
+ void *(*alloc)(void *alloc_ctx, unsigned long size, gfp_t gfp_flags);
void (*put)(void *buf_priv);
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
struct dma_buf *(*get_dmabuf)(void *buf_priv, unsigned long flags);
#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) */
void *(*get_userptr)(void *alloc_ctx, unsigned long vaddr,
- unsigned long size,
- enum dma_data_direction dma_dir);
+ unsigned long size, int write);
void (*put_userptr)(void *buf_priv);
void (*prepare)(void *buf_priv);
@@ -100,8 +97,7 @@
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
void *(*attach_dmabuf)(void *alloc_ctx, struct dma_buf *dbuf,
- unsigned long size,
- enum dma_data_direction dma_dir);
+ unsigned long size, int write);
void (*detach_dmabuf)(void *buf_priv);
int (*map_dmabuf)(void *buf_priv);
void (*unmap_dmabuf)(void *buf_priv);
@@ -278,24 +274,22 @@
* queue setup from completing successfully; optional.
* @buf_prepare: called every time the buffer is queued from userspace
* and from the VIDIOC_PREPARE_BUF ioctl; drivers may
- * perform any initialization required before each
- * hardware operation in this callback; drivers can
- * access/modify the buffer here as it is still synced for
- * the CPU; drivers that support VIDIOC_CREATE_BUFS must
- * also validate the buffer size; if an error is returned,
- * the buffer will not be queued in driver; optional.
+ * perform any initialization required before each hardware
+ * operation in this callback; drivers that support
+ * VIDIOC_CREATE_BUFS must also validate the buffer size;
+ * if an error is returned, the buffer will not be queued
+ * in driver; optional.
* @buf_finish: called before every dequeue of the buffer back to
- * userspace; the buffer is synced for the CPU, so drivers
- * can access/modify the buffer contents; drivers may
- * perform any operations required before userspace
- * accesses the buffer; optional. The buffer state can be
- * one of the following: DONE and ERROR occur while
- * streaming is in progress, and the PREPARED state occurs
- * when the queue has been canceled and all pending
- * buffers are being returned to their default DEQUEUED
- * state. Typically you only have to do something if the
- * state is VB2_BUF_STATE_DONE, since in all other cases
- * the buffer contents will be ignored anyway.
+ * userspace; drivers may perform any operations required
+ * before userspace accesses the buffer; optional. The
+ * buffer state can be one of the following: DONE and
+ * ERROR occur while streaming is in progress, and the
+ * PREPARED state occurs when the queue has been canceled
+ * and all pending buffers are being returned to their
+ * default DEQUEUED state. Typically you only have to do
+ * something if the state is VB2_BUF_STATE_DONE, since in
+ * all other cases the buffer contents will be ignored
+ * anyway.
* @buf_cleanup: called once before the buffer is freed; drivers may
* perform any additional cleanup; optional.
* @start_streaming: called once to enter 'streaming' state; the driver may
diff --git a/include/media/videobuf2-dma-sg.h b/include/media/videobuf2-dma-sg.h
index 14ce306..7b89852 100644
--- a/include/media/videobuf2-dma-sg.h
+++ b/include/media/videobuf2-dma-sg.h
@@ -21,9 +21,6 @@
return (struct sg_table *)vb2_plane_cookie(vb, plane_no);
}
-void *vb2_dma_sg_init_ctx(struct device *dev);
-void vb2_dma_sg_cleanup_ctx(void *alloc_ctx);
-
extern const struct vb2_mem_ops vb2_dma_sg_memops;
#endif
diff --git a/include/net/6lowpan.h b/include/net/6lowpan.h
index dc03d77..d184df1 100644
--- a/include/net/6lowpan.h
+++ b/include/net/6lowpan.h
@@ -372,12 +372,12 @@
return skb->len + uncomp_header - ret;
}
-int
-lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
- const u8 *saddr, const u8 saddr_type,
- const u8 saddr_len, const u8 *daddr,
- const u8 daddr_type, const u8 daddr_len,
- u8 iphc0, u8 iphc1);
+typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev);
+
+int lowpan_process_data(struct sk_buff *skb, struct net_device *dev,
+ const u8 *saddr, const u8 saddr_type, const u8 saddr_len,
+ const u8 *daddr, const u8 daddr_type, const u8 daddr_len,
+ u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver);
int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *_daddr,
const void *_saddr, unsigned int len);
diff --git a/include/net/af_ieee802154.h b/include/net/af_ieee802154.h
index 7d38e2f..085940f 100644
--- a/include/net/af_ieee802154.h
+++ b/include/net/af_ieee802154.h
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 40129b3..6e8f249 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -129,15 +129,6 @@
* during the hdev->setup vendor callback.
*/
HCI_QUIRK_INVALID_BDADDR,
-
- /* When this quirk is set, the duplicate filtering during
- * scanning is based on Bluetooth devices addresses. To allow
- * RSSI based updates, restart scanning if needed.
- *
- * This quirk can be set before hci_register_dev is called or
- * during the hdev->setup vendor callback.
- */
- HCI_QUIRK_STRICT_DUPLICATE_FILTER,
};
/* HCI device flags */
@@ -163,7 +154,6 @@
enum {
HCI_DUT_MODE,
HCI_FORCE_SC,
- HCI_FORCE_LESC,
HCI_FORCE_STATIC_ADDR,
};
@@ -275,7 +265,6 @@
/* Low Energy links do not have defined link type. Use invented one */
#define LE_LINK 0x80
#define AMP_LINK 0x81
-#define INVALID_LINK 0xff
/* LMP features */
#define LMP_3SLOT 0x01
@@ -343,7 +332,6 @@
#define HCI_LE_ENCRYPTION 0x01
#define HCI_LE_CONN_PARAM_REQ_PROC 0x02
#define HCI_LE_PING 0x10
-#define HCI_LE_EXT_SCAN_POLICY 0x80
/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
@@ -413,7 +401,6 @@
/* The core spec defines 127 as the "not available" value */
#define HCI_TX_POWER_INVALID 127
-#define HCI_RSSI_INVALID 127
#define HCI_ROLE_MASTER 0x00
#define HCI_ROLE_SLAVE 0x01
@@ -642,7 +629,7 @@
struct hci_cp_remote_oob_data_reply {
bdaddr_t bdaddr;
__u8 hash[16];
- __u8 rand[16];
+ __u8 randomizer[16];
} __packed;
#define HCI_OP_REMOTE_OOB_DATA_NEG_REPLY 0x0433
@@ -734,9 +721,9 @@
struct hci_cp_remote_oob_ext_data_reply {
bdaddr_t bdaddr;
__u8 hash192[16];
- __u8 rand192[16];
+ __u8 randomizer192[16];
__u8 hash256[16];
- __u8 rand256[16];
+ __u8 randomizer256[16];
} __packed;
#define HCI_OP_SNIFF_MODE 0x0803
@@ -943,7 +930,7 @@
struct hci_rp_read_local_oob_data {
__u8 status;
__u8 hash[16];
- __u8 rand[16];
+ __u8 randomizer[16];
} __packed;
#define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58
@@ -1027,9 +1014,9 @@
struct hci_rp_read_local_oob_ext_data {
__u8 status;
__u8 hash192[16];
- __u8 rand192[16];
+ __u8 randomizer192[16];
__u8 hash256[16];
- __u8 rand256[16];
+ __u8 randomizer256[16];
} __packed;
#define HCI_OP_READ_LOCAL_VERSION 0x1001
@@ -1476,11 +1463,6 @@
__le16 opcode;
} __packed;
-#define HCI_EV_HARDWARE_ERROR 0x10
-struct hci_ev_hardware_error {
- __u8 code;
-} __packed;
-
#define HCI_EV_ROLE_CHANGE 0x12
struct hci_ev_role_change {
__u8 status;
@@ -1752,25 +1734,6 @@
__u8 clk_accurancy;
} __packed;
-/* Advertising report event types */
-#define LE_ADV_IND 0x00
-#define LE_ADV_DIRECT_IND 0x01
-#define LE_ADV_SCAN_IND 0x02
-#define LE_ADV_NONCONN_IND 0x03
-#define LE_ADV_SCAN_RSP 0x04
-
-#define ADDR_LE_DEV_PUBLIC 0x00
-#define ADDR_LE_DEV_RANDOM 0x01
-
-#define HCI_EV_LE_ADVERTISING_REPORT 0x02
-struct hci_ev_le_advertising_info {
- __u8 evt_type;
- __u8 bdaddr_type;
- bdaddr_t bdaddr;
- __u8 length;
- __u8 data[0];
-} __packed;
-
#define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03
struct hci_ev_le_conn_update_complete {
__u8 status;
@@ -1796,14 +1759,23 @@
__le16 timeout;
} __packed;
-#define HCI_EV_LE_DIRECT_ADV_REPORT 0x0B
-struct hci_ev_le_direct_adv_info {
+/* Advertising report event types */
+#define LE_ADV_IND 0x00
+#define LE_ADV_DIRECT_IND 0x01
+#define LE_ADV_SCAN_IND 0x02
+#define LE_ADV_NONCONN_IND 0x03
+#define LE_ADV_SCAN_RSP 0x04
+
+#define ADDR_LE_DEV_PUBLIC 0x00
+#define ADDR_LE_DEV_RANDOM 0x01
+
+#define HCI_EV_LE_ADVERTISING_REPORT 0x02
+struct hci_ev_le_advertising_info {
__u8 evt_type;
__u8 bdaddr_type;
bdaddr_t bdaddr;
- __u8 direct_addr_type;
- bdaddr_t direct_addr;
- __s8 rssi;
+ __u8 length;
+ __u8 data[0];
} __packed;
/* Internal events generated by Bluetooth stack */
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 3c78270..37ff1ae 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -75,10 +75,6 @@
u32 last_adv_flags;
u8 last_adv_data[HCI_MAX_AD_LENGTH];
u8 last_adv_data_len;
- bool report_invalid_rssi;
- s8 rssi;
- u16 uuid_count;
- u8 (*uuids)[16];
};
struct hci_conn_hash {
@@ -112,7 +108,6 @@
struct smp_ltk {
struct list_head list;
- struct rcu_head rcu;
bdaddr_t bdaddr;
u8 bdaddr_type;
u8 authenticated;
@@ -125,7 +120,6 @@
struct smp_irk {
struct list_head list;
- struct rcu_head rcu;
bdaddr_t rpa;
bdaddr_t bdaddr;
u8 addr_type;
@@ -134,7 +128,6 @@
struct link_key {
struct list_head list;
- struct rcu_head rcu;
bdaddr_t bdaddr;
u8 type;
u8 val[HCI_LINK_KEY_SIZE];
@@ -144,11 +137,10 @@
struct oob_data {
struct list_head list;
bdaddr_t bdaddr;
- u8 bdaddr_type;
u8 hash192[16];
- u8 rand192[16];
+ u8 randomizer192[16];
u8 hash256[16];
- u8 rand256[16];
+ u8 randomizer256[16];
};
#define HCI_MAX_SHORT_NAME_LENGTH 10
@@ -311,7 +303,6 @@
__u32 req_result;
void *smp_data;
- void *smp_bredr_data;
struct discovery_state discovery;
struct hci_conn_hash conn_hash;
@@ -407,8 +398,6 @@
__u16 le_conn_interval;
__u16 le_conn_latency;
__u16 le_supv_timeout;
- __u8 le_adv_data[HCI_MAX_AD_LENGTH];
- __u8 le_adv_data_len;
__s8 rssi;
__s8 tx_power;
__s8 max_tx_power;
@@ -507,17 +496,6 @@
INIT_LIST_HEAD(&hdev->discovery.all);
INIT_LIST_HEAD(&hdev->discovery.unknown);
INIT_LIST_HEAD(&hdev->discovery.resolve);
- hdev->discovery.report_invalid_rssi = true;
- hdev->discovery.rssi = HCI_RSSI_INVALID;
-}
-
-static inline void hci_discovery_filter_clear(struct hci_dev *hdev)
-{
- hdev->discovery.report_invalid_rssi = true;
- hdev->discovery.rssi = HCI_RSSI_INVALID;
- hdev->discovery.uuid_count = 0;
- kfree(hdev->discovery.uuids);
- hdev->discovery.uuids = NULL;
}
bool hci_discovery_active(struct hci_dev *hdev);
@@ -575,8 +553,6 @@
HCI_CONN_STK_ENCRYPT,
HCI_CONN_AUTH_INITIATOR,
HCI_CONN_DROP,
- HCI_CONN_PARAM_REMOVAL_PEND,
- HCI_CONN_NEW_LINK_KEY,
};
static inline bool hci_conn_ssp_enabled(struct hci_conn *conn)
@@ -667,26 +643,6 @@
return c->acl_num + c->amp_num + c->sco_num + c->le_num;
}
-static inline __u8 hci_conn_lookup_type(struct hci_dev *hdev, __u16 handle)
-{
- struct hci_conn_hash *h = &hdev->conn_hash;
- struct hci_conn *c;
- __u8 type = INVALID_LINK;
-
- rcu_read_lock();
-
- list_for_each_entry_rcu(c, &h->list, list) {
- if (c->handle == handle) {
- type = c->type;
- break;
- }
- }
-
- rcu_read_unlock();
-
- return type;
-}
-
static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
__u16 handle)
{
@@ -897,7 +853,6 @@
void hci_unregister_dev(struct hci_dev *hdev);
int hci_suspend_dev(struct hci_dev *hdev);
int hci_resume_dev(struct hci_dev *hdev);
-int hci_reset_dev(struct hci_dev *hdev);
int hci_dev_open(__u16 dev);
int hci_dev_close(__u16 dev);
int hci_dev_reset(__u16 dev);
@@ -939,11 +894,13 @@
struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
bdaddr_t *bdaddr, u8 *val, u8 type,
u8 pin_len, bool *persistent);
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
+ u8 role);
struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, u8 type, u8 authenticated,
u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand);
-struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 addr_type, u8 role);
+struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 addr_type, u8 role);
int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type);
void hci_smp_ltks_clear(struct hci_dev *hdev);
int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
@@ -958,12 +915,13 @@
void hci_remote_oob_data_clear(struct hci_dev *hdev);
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
- bdaddr_t *bdaddr, u8 bdaddr_type);
+ bdaddr_t *bdaddr);
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 bdaddr_type, u8 *hash192, u8 *rand192,
- u8 *hash256, u8 *rand256);
-int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 bdaddr_type);
+ u8 *hash, u8 *randomizer);
+int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 *hash192, u8 *randomizer192,
+ u8 *hash256, u8 *randomizer256);
+int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
@@ -1014,9 +972,6 @@
#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
!test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
-#define bredr_sc_enabled(dev) ((lmp_sc_capable(dev) || \
- test_bit(HCI_FORCE_SC, &(dev)->dbg_flags)) && \
- test_bit(HCI_SC_ENABLED, &(dev)->dev_flags))
/* ----- HCI protocols ----- */
#define HCI_PROTO_DEFER 0x01
@@ -1355,8 +1310,9 @@
void mgmt_discoverable_timeout(struct hci_dev *hdev);
void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
bool persistent);
-void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
- u32 flags, u8 *name, u8 name_len);
+void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type, u32 flags, u8 *name, u8 name_len,
+ u8 *dev_class);
void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 reason,
bool mgmt_connected);
@@ -1393,8 +1349,8 @@
u8 status);
void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
- u8 *rand192, u8 *hash256, u8 *rand256,
- u8 status);
+ u8 *randomizer192, u8 *hash256,
+ u8 *randomizer256, u8 status);
void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len);
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index eee3ef5..ead99f0 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -28,7 +28,6 @@
#define __L2CAP_H
#include <asm/unaligned.h>
-#include <linux/atomic.h>
/* L2CAP defaults */
#define L2CAP_DEFAULT_MTU 672
@@ -141,7 +140,6 @@
#define L2CAP_FC_ATT 0x10
#define L2CAP_FC_SIG_LE 0x20
#define L2CAP_FC_SMP_LE 0x40
-#define L2CAP_FC_SMP_BREDR 0x80
/* L2CAP Control Field bit masks */
#define L2CAP_CTRL_SAR 0xC000
@@ -256,7 +254,6 @@
#define L2CAP_CID_ATT 0x0004
#define L2CAP_CID_LE_SIGNALING 0x0005
#define L2CAP_CID_SMP 0x0006
-#define L2CAP_CID_SMP_BREDR 0x0007
#define L2CAP_CID_DYN_START 0x0040
#define L2CAP_CID_DYN_END 0xffff
#define L2CAP_CID_LE_DYN_END 0x007f
@@ -484,7 +481,6 @@
struct hci_conn *hs_hcon;
struct hci_chan *hs_hchan;
struct kref kref;
- atomic_t nesting;
__u8 state;
@@ -621,8 +617,8 @@
unsigned int mtu;
__u32 feat_mask;
- __u8 remote_fixed_chan;
- __u8 local_fixed_chan;
+ __u8 fixed_chan_mask;
+ bool hs_enabled;
__u8 info_state;
__u8 info_ident;
@@ -717,17 +713,6 @@
FLAG_HOLD_HCI_CONN,
};
-/* Lock nesting levels for L2CAP channels. We need these because lockdep
- * otherwise considers all channels equal and will e.g. complain about a
- * connection oriented channel triggering SMP procedures or a listening
- * channel creating and locking a child channel.
- */
-enum {
- L2CAP_NESTING_SMP,
- L2CAP_NESTING_NORMAL,
- L2CAP_NESTING_PARENT,
-};
-
enum {
L2CAP_TX_STATE_XMIT,
L2CAP_TX_STATE_WAIT_F,
@@ -793,7 +778,7 @@
static inline void l2cap_chan_lock(struct l2cap_chan *chan)
{
- mutex_lock_nested(&chan->lock, atomic_read(&chan->nesting));
+ mutex_lock(&chan->lock);
}
static inline void l2cap_chan_unlock(struct l2cap_chan *chan)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 95c34d5..414cd2f 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -184,9 +184,6 @@
#define MGMT_LTK_UNAUTHENTICATED 0x00
#define MGMT_LTK_AUTHENTICATED 0x01
-#define MGMT_LTK_P256_UNAUTH 0x02
-#define MGMT_LTK_P256_AUTH 0x03
-#define MGMT_LTK_P256_DEBUG 0x04
struct mgmt_ltk_info {
struct mgmt_addr_info addr;
@@ -302,28 +299,28 @@
#define MGMT_READ_LOCAL_OOB_DATA_SIZE 0
struct mgmt_rp_read_local_oob_data {
__u8 hash[16];
- __u8 rand[16];
+ __u8 randomizer[16];
} __packed;
struct mgmt_rp_read_local_oob_ext_data {
__u8 hash192[16];
- __u8 rand192[16];
+ __u8 randomizer192[16];
__u8 hash256[16];
- __u8 rand256[16];
+ __u8 randomizer256[16];
} __packed;
#define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0021
struct mgmt_cp_add_remote_oob_data {
struct mgmt_addr_info addr;
__u8 hash[16];
- __u8 rand[16];
+ __u8 randomizer[16];
} __packed;
#define MGMT_ADD_REMOTE_OOB_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 32)
struct mgmt_cp_add_remote_oob_ext_data {
struct mgmt_addr_info addr;
__u8 hash192[16];
- __u8 rand192[16];
+ __u8 randomizer192[16];
__u8 hash256[16];
- __u8 rand256[16];
+ __u8 randomizer256[16];
} __packed;
#define MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE (MGMT_ADDR_INFO_SIZE + 64)
@@ -498,15 +495,6 @@
} __packed;
#define MGMT_SET_PUBLIC_ADDRESS_SIZE 6
-#define MGMT_OP_START_SERVICE_DISCOVERY 0x003A
-struct mgmt_cp_start_service_discovery {
- __u8 type;
- __s8 rssi;
- __le16 uuid_count;
- __u8 uuids[0][16];
-} __packed;
-#define MGMT_START_SERVICE_DISCOVERY_SIZE 4
-
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 66fc97a..87362c1 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -319,12 +319,9 @@
/**
* struct vif_params - describes virtual interface parameters
* @use_4addr: use 4-address frames
- * @macaddr: address to use for this virtual interface.
- * If this parameter is set to zero address the driver may
- * determine the address as needed.
- * This feature is only fully supported by drivers that enable the
- * %NL80211_FEATURE_MAC_ON_CREATE flag. Others may support creating
- ** only p2p devices with specified MAC.
+ * @macaddr: address to use for this virtual interface. This will only
+ * be used for non-netdevice interfaces. If this parameter is set
+ * to zero address the driver may determine the address as needed.
*/
struct vif_params {
int use_4addr;
@@ -802,22 +799,6 @@
};
/**
- * struct station_del_parameters - station deletion parameters
- *
- * Used to delete a station entry (or all stations).
- *
- * @mac: MAC address of the station to remove or NULL to remove all stations
- * @subtype: Management frame subtype to use for indicating removal
- * (10 = Disassociation, 12 = Deauthentication)
- * @reason_code: Reason code for the Disassociation/Deauthentication frame
- */
-struct station_del_parameters {
- const u8 *mac;
- u8 subtype;
- u16 reason_code;
-};
-
-/**
* enum cfg80211_station_type - the type of station being modified
* @CFG80211_STA_AP_CLIENT: client of an AP interface
* @CFG80211_STA_AP_MLME_CLIENT: client of an AP interface that has
@@ -1359,16 +1340,6 @@
};
/**
- * struct ocb_setup - 802.11p OCB mode setup configuration
- * @chandef: defines the channel to use
- *
- * These parameters are fixed when connecting to the network
- */
-struct ocb_setup {
- struct cfg80211_chan_def chandef;
-};
-
-/**
* struct ieee80211_txq_params - TX queue parameters
* @ac: AC identifier
* @txop: Maximum burst time in units of 32 usecs, 0 meaning disabled
@@ -1437,10 +1408,6 @@
* @aborted: (internal) scan request was notified as aborted
* @notified: (internal) scan request was notified as done or aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
- * @mac_addr: MAC address used with randomisation
- * @mac_addr_mask: MAC address mask used with randomisation, bits that
- * are 0 in the mask should be randomised, bits that are 1 should
- * be taken from the @mac_addr
*/
struct cfg80211_scan_request {
struct cfg80211_ssid *ssids;
@@ -1455,9 +1422,6 @@
struct wireless_dev *wdev;
- u8 mac_addr[ETH_ALEN] __aligned(2);
- u8 mac_addr_mask[ETH_ALEN] __aligned(2);
-
/* internal */
struct wiphy *wiphy;
unsigned long scan_start;
@@ -1468,17 +1432,6 @@
struct ieee80211_channel *channels[0];
};
-static inline void get_random_mask_addr(u8 *buf, const u8 *addr, const u8 *mask)
-{
- int i;
-
- get_random_bytes(buf, ETH_ALEN);
- for (i = 0; i < ETH_ALEN; i++) {
- buf[i] &= ~mask[i];
- buf[i] |= addr[i] & mask[i];
- }
-}
-
/**
* struct cfg80211_match_set - sets of attributes to match
*
@@ -1512,10 +1465,6 @@
* @channels: channels to scan
* @min_rssi_thold: for drivers only supporting a single threshold, this
* contains the minimum over all matchsets
- * @mac_addr: MAC address used with randomisation
- * @mac_addr_mask: MAC address mask used with randomisation, bits that
- * are 0 in the mask should be randomised, bits that are 1 should
- * be taken from the @mac_addr
*/
struct cfg80211_sched_scan_request {
struct cfg80211_ssid *ssids;
@@ -1530,9 +1479,6 @@
int n_match_sets;
s32 min_rssi_thold;
- u8 mac_addr[ETH_ALEN] __aligned(2);
- u8 mac_addr_mask[ETH_ALEN] __aligned(2);
-
/* internal */
struct wiphy *wiphy;
struct net_device *dev;
@@ -1965,7 +1911,6 @@
* @rfkill_release: wake up when rfkill is released
* @tcp: TCP connection establishment/wakeup parameters, see nl80211.h.
* NULL if not configured.
- * @nd_config: configuration for the scan to be used for net detect wake.
*/
struct cfg80211_wowlan {
bool any, disconnect, magic_pkt, gtk_rekey_failure,
@@ -1974,7 +1919,6 @@
struct cfg80211_pkt_pattern *patterns;
struct cfg80211_wowlan_tcp *tcp;
int n_patterns;
- struct cfg80211_sched_scan_request *nd_config;
};
/**
@@ -2007,35 +1951,6 @@
};
/**
- * struct cfg80211_wowlan_nd_match - information about the match
- *
- * @ssid: SSID of the match that triggered the wake up
- * @n_channels: Number of channels where the match occurred. This
- * value may be zero if the driver can't report the channels.
- * @channels: center frequencies of the channels where a match
- * occurred (in MHz)
- */
-struct cfg80211_wowlan_nd_match {
- struct cfg80211_ssid ssid;
- int n_channels;
- u32 channels[];
-};
-
-/**
- * struct cfg80211_wowlan_nd_info - net detect wake up information
- *
- * @n_matches: Number of match information instances provided in
- * @matches. This value may be zero if the driver can't provide
- * match information.
- * @matches: Array of pointers to matches containing information about
- * the matches that triggered the wake up.
- */
-struct cfg80211_wowlan_nd_info {
- int n_matches;
- struct cfg80211_wowlan_nd_match *matches[];
-};
-
-/**
* struct cfg80211_wowlan_wakeup - wakeup report
* @disconnect: woke up by getting disconnected
* @magic_pkt: woke up by receiving magic packet
@@ -2054,7 +1969,6 @@
* @tcp_match: TCP wakeup packet received
* @tcp_connlost: TCP connection lost or failed to establish
* @tcp_nomoretokens: TCP data ran out of tokens
- * @net_detect: if not %NULL, woke up because of net detect
*/
struct cfg80211_wowlan_wakeup {
bool disconnect, magic_pkt, gtk_rekey_failure,
@@ -2064,7 +1978,6 @@
s32 pattern_idx;
u32 packet_present_len, packet_len;
const void *packet;
- struct cfg80211_wowlan_nd_info *net_detect;
};
/**
@@ -2219,7 +2132,7 @@
* @stop_ap: Stop being an AP, including stopping beaconing.
*
* @add_station: Add a new station.
- * @del_station: Remove a station
+ * @del_station: Remove a station; @mac may be NULL to remove all stations.
* @change_station: Modify a given station. Note that flags changes are not much
* validated in cfg80211, in particular the auth/assoc/authorized flags
* might come to the driver in invalid combinations -- make sure to check
@@ -2233,8 +2146,6 @@
* @change_mpath: change a given mesh path
* @get_mpath: get a mesh path for the given parameters
* @dump_mpath: dump mesh path callback -- resume dump at index @idx
- * @get_mpp: get a mesh proxy path for the given parameters
- * @dump_mpp: dump mesh proxy path callback -- resume dump at index @idx
* @join_mesh: join the mesh network with the specified parameters
* (invoked with the wireless_dev mutex held)
* @leave_mesh: leave the current mesh network
@@ -2420,17 +2331,6 @@
* with the peer followed by immediate teardown when the addition is later
* rejected)
* @del_tx_ts: remove an existing TX TS
- *
- * @join_ocb: join the OCB network with the specified parameters
- * (invoked with the wireless_dev mutex held)
- * @leave_ocb: leave the current OCB network
- * (invoked with the wireless_dev mutex held)
- *
- * @tdls_channel_switch: Start channel-switching with a TDLS peer. The driver
- * is responsible for continually initiating channel-switching operations
- * and returning to the base channel for communication with the AP.
- * @tdls_cancel_channel_switch: Stop channel-switching with a TDLS peer. Both
- * peers must be on the base channel when the call completes.
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -2476,7 +2376,7 @@
const u8 *mac,
struct station_parameters *params);
int (*del_station)(struct wiphy *wiphy, struct net_device *dev,
- struct station_del_parameters *params);
+ const u8 *mac);
int (*change_station)(struct wiphy *wiphy, struct net_device *dev,
const u8 *mac,
struct station_parameters *params);
@@ -2496,11 +2396,6 @@
int (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
int idx, u8 *dst, u8 *next_hop,
struct mpath_info *pinfo);
- int (*get_mpp)(struct wiphy *wiphy, struct net_device *dev,
- u8 *dst, u8 *mpp, struct mpath_info *pinfo);
- int (*dump_mpp)(struct wiphy *wiphy, struct net_device *dev,
- int idx, u8 *dst, u8 *mpp,
- struct mpath_info *pinfo);
int (*get_mesh_config)(struct wiphy *wiphy,
struct net_device *dev,
struct mesh_config *conf);
@@ -2512,10 +2407,6 @@
const struct mesh_setup *setup);
int (*leave_mesh)(struct wiphy *wiphy, struct net_device *dev);
- int (*join_ocb)(struct wiphy *wiphy, struct net_device *dev,
- struct ocb_setup *setup);
- int (*leave_ocb)(struct wiphy *wiphy, struct net_device *dev);
-
int (*change_bss)(struct wiphy *wiphy, struct net_device *dev,
struct bss_parameters *params);
@@ -2686,14 +2577,6 @@
u16 admitted_time);
int (*del_tx_ts)(struct wiphy *wiphy, struct net_device *dev,
u8 tsid, const u8 *peer);
-
- int (*tdls_channel_switch)(struct wiphy *wiphy,
- struct net_device *dev,
- const u8 *addr, u8 oper_class,
- struct cfg80211_chan_def *chandef);
- void (*tdls_cancel_channel_switch)(struct wiphy *wiphy,
- struct net_device *dev,
- const u8 *addr);
};
/*
@@ -2740,9 +2623,13 @@
* @WIPHY_FLAG_SUPPORTS_5_10_MHZ: Device supports 5 MHz and 10 MHz channels.
* @WIPHY_FLAG_HAS_CHANNEL_SWITCH: Device supports channel switch in
* beaconing mode (AP, IBSS, Mesh, ...).
+ * @WIPHY_FLAG_SUPPORTS_WMM_ADMISSION: the device supports setting up WMM
+ * TSPEC sessions (TID aka TSID 0-7) with the NL80211_CMD_ADD_TX_TS
+ * command. Standard IEEE 802.11 TSPEC setup is not yet supported, it
+ * needs to be able to handle Block-Ack agreements and other things.
*/
enum wiphy_flags {
- /* use hole at 0 */
+ WIPHY_FLAG_SUPPORTS_WMM_ADMISSION = BIT(0),
/* use hole at 1 */
/* use hole at 2 */
WIPHY_FLAG_NETNS_OK = BIT(3),
@@ -2868,7 +2755,6 @@
* @WIPHY_WOWLAN_EAP_IDENTITY_REQ: supports wakeup on EAP identity request
* @WIPHY_WOWLAN_4WAY_HANDSHAKE: supports wakeup on 4-way handshake failure
* @WIPHY_WOWLAN_RFKILL_RELEASE: supports wakeup on RF-kill release
- * @WIPHY_WOWLAN_NET_DETECT: supports wakeup on network detection
*/
enum wiphy_wowlan_support_flags {
WIPHY_WOWLAN_ANY = BIT(0),
@@ -2879,7 +2765,6 @@
WIPHY_WOWLAN_EAP_IDENTITY_REQ = BIT(5),
WIPHY_WOWLAN_4WAY_HANDSHAKE = BIT(6),
WIPHY_WOWLAN_RFKILL_RELEASE = BIT(7),
- WIPHY_WOWLAN_NET_DETECT = BIT(8),
};
struct wiphy_wowlan_tcp_support {
@@ -2898,11 +2783,6 @@
* @pattern_max_len: maximum length of each pattern
* @pattern_min_len: minimum length of each pattern
* @max_pkt_offset: maximum Rx packet offset
- * @max_nd_match_sets: maximum number of matchsets for net-detect,
- * similar, but not necessarily identical, to max_match_sets for
- * scheduled scans.
- * See &struct cfg80211_sched_scan_request.@match_sets for more
- * details.
* @tcp: TCP wakeup support information
*/
struct wiphy_wowlan_support {
@@ -2911,7 +2791,6 @@
int pattern_max_len;
int pattern_min_len;
int max_pkt_offset;
- int max_nd_match_sets;
const struct wiphy_wowlan_tcp_support *tcp;
};
@@ -3290,23 +3169,6 @@
}
/**
- * wiphy_new_nm - create a new wiphy for use with cfg80211
- *
- * @ops: The configuration operations for this device
- * @sizeof_priv: The size of the private area to allocate
- * @requested_name: Request a particular name.
- * NULL is valid value, and means use the default phy%d naming.
- *
- * Create a new wiphy and associate the given operations with it.
- * @sizeof_priv bytes are allocated for private use.
- *
- * Return: A pointer to the new wiphy. This pointer must be
- * assigned to each netdev's ieee80211_ptr for proper operation.
- */
-struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
- const char *requested_name);
-
-/**
* wiphy_new - create a new wiphy for use with cfg80211
*
* @ops: The configuration operations for this device
@@ -3318,11 +3180,7 @@
* Return: A pointer to the new wiphy. This pointer must be
* assigned to each netdev's ieee80211_ptr for proper operation.
*/
-static inline struct wiphy *wiphy_new(const struct cfg80211_ops *ops,
- int sizeof_priv)
-{
- return wiphy_new_nm(ops, sizeof_priv, NULL);
-}
+struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv);
/**
* wiphy_register - register a wiphy with cfg80211
@@ -4646,42 +4504,6 @@
gfp_t gfp);
/**
- * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
- * @dev: network device
- * @peer: peer's MAC address
- * @num_packets: how many packets were lost -- should be a fixed threshold
- * but probably no less than maybe 50, or maybe a throughput dependent
- * threshold (to account for temporary interference)
- * @gfp: context flags
- */
-void cfg80211_cqm_pktloss_notify(struct net_device *dev,
- const u8 *peer, u32 num_packets, gfp_t gfp);
-
-/**
- * cfg80211_cqm_txe_notify - TX error rate event
- * @dev: network device
- * @peer: peer's MAC address
- * @num_packets: how many packets were lost
- * @rate: % of packets which failed transmission
- * @intvl: interval (in s) over which the TX failure threshold was breached.
- * @gfp: context flags
- *
- * Notify userspace when configured % TX failures over number of packets in a
- * given interval is exceeded.
- */
-void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer,
- u32 num_packets, u32 rate, u32 intvl, gfp_t gfp);
-
-/**
- * cfg80211_cqm_beacon_loss_notify - beacon loss event
- * @dev: network device
- * @gfp: context flags
- *
- * Notify userspace about beacon loss from the connected AP.
- */
-void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp);
-
-/**
* cfg80211_radar_event - radar detection event
* @wiphy: the wiphy
* @chandef: chandef for the current channel
@@ -4709,6 +4531,33 @@
/**
+ * cfg80211_cqm_pktloss_notify - notify userspace about packetloss to peer
+ * @dev: network device
+ * @peer: peer's MAC address
+ * @num_packets: how many packets were lost -- should be a fixed threshold
+ * but probably no less than maybe 50, or maybe a throughput dependent
+ * threshold (to account for temporary interference)
+ * @gfp: context flags
+ */
+void cfg80211_cqm_pktloss_notify(struct net_device *dev,
+ const u8 *peer, u32 num_packets, gfp_t gfp);
+
+/**
+ * cfg80211_cqm_txe_notify - TX error rate event
+ * @dev: network device
+ * @peer: peer's MAC address
+ * @num_packets: how many packets were lost
+ * @rate: % of packets which failed transmission
+ * @intvl: interval (in s) over which the TX failure threshold was breached.
+ * @gfp: context flags
+ *
+ * Notify userspace when configured % TX failures over number of packets in a
+ * given interval is exceeded.
+ */
+void cfg80211_cqm_txe_notify(struct net_device *dev, const u8 *peer,
+ u32 num_packets, u32 rate, u32 intvl, gfp_t gfp);
+
+/**
* cfg80211_gtk_rekey_notify - notify userspace about driver rekeying
* @dev: network device
* @bssid: BSSID of AP (to avoid races)
@@ -4811,20 +4660,6 @@
void cfg80211_ch_switch_notify(struct net_device *dev,
struct cfg80211_chan_def *chandef);
-/*
- * cfg80211_ch_switch_started_notify - notify channel switch start
- * @dev: the device on which the channel switch started
- * @chandef: the future channel definition
- * @count: the number of TBTTs until the channel switch happens
- *
- * Inform the userspace about the channel switch that has just
- * started, so that it can take appropriate actions (eg. starting
- * channel switch on other vifs), if necessary.
- */
-void cfg80211_ch_switch_started_notify(struct net_device *dev,
- struct cfg80211_chan_def *chandef,
- u8 count);
-
/**
* ieee80211_operating_class_to_band - convert operating class to band
*
diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h
deleted file mode 100644
index 7f713ac..0000000
--- a/include/net/cfg802154.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2007, 2008, 2009 Siemens AG
- *
- * 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.
- *
- * Written by:
- * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
- */
-
-#ifndef __NET_CFG802154_H
-#define __NET_CFG802154_H
-
-#include <linux/ieee802154.h>
-#include <linux/netdevice.h>
-#include <linux/mutex.h>
-#include <linux/bug.h>
-
-#include <net/nl802154.h>
-
-struct wpan_phy;
-
-struct cfg802154_ops {
- struct net_device * (*add_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
- const char *name,
- int type);
- void (*del_virtual_intf_deprecated)(struct wpan_phy *wpan_phy,
- struct net_device *dev);
- int (*add_virtual_intf)(struct wpan_phy *wpan_phy,
- const char *name,
- enum nl802154_iftype type,
- __le64 extended_addr);
- int (*del_virtual_intf)(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev);
- int (*set_channel)(struct wpan_phy *wpan_phy, u8 page, u8 channel);
- int (*set_pan_id)(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev, __le16 pan_id);
- int (*set_short_addr)(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev, __le16 short_addr);
- int (*set_backoff_exponent)(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev, u8 min_be,
- u8 max_be);
- int (*set_max_csma_backoffs)(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev,
- u8 max_csma_backoffs);
- int (*set_max_frame_retries)(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev,
- s8 max_frame_retries);
- int (*set_lbt_mode)(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev, bool mode);
-};
-
-struct wpan_phy {
- struct mutex pib_lock;
-
- /* If multiple wpan_phys are registered and you're handed e.g.
- * a regular netdev with assigned ieee802154_ptr, you won't
- * know whether it points to a wpan_phy your driver has registered
- * or not. Assign this to something global to your driver to
- * help determine whether you own this wpan_phy or not.
- */
- const void *privid;
-
- /*
- * This is a PIB according to 802.15.4-2011.
- * We do not provide timing-related variables, as they
- * aren't used outside of driver
- */
- u8 current_channel;
- u8 current_page;
- u32 channels_supported[IEEE802154_MAX_PAGE + 1];
- s8 transmit_power;
- u8 cca_mode;
-
- __le64 perm_extended_addr;
-
- s32 cca_ed_level;
-
- /* PHY depended MAC PIB values */
-
- /* 802.15.4 acronym: Tdsym in usec */
- u8 symbol_duration;
- /* lifs and sifs periods timing */
- u16 lifs_period;
- u16 sifs_period;
-
- struct device dev;
-
- char priv[0] __aligned(NETDEV_ALIGN);
-};
-
-struct wpan_dev {
- struct wpan_phy *wpan_phy;
- int iftype;
-
- /* the remainder of this struct should be private to cfg802154 */
- struct list_head list;
- struct net_device *netdev;
-
- u32 identifier;
-
- /* MAC PIB */
- __le16 pan_id;
- __le16 short_addr;
- __le64 extended_addr;
-
- /* MAC BSN field */
- u8 bsn;
- /* MAC DSN field */
- u8 dsn;
-
- u8 min_be;
- u8 max_be;
- u8 csma_retries;
- s8 frame_retries;
-
- bool lbt;
-
- bool promiscuous_mode;
-};
-
-#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
-
-struct wpan_phy *
-wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size);
-static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev)
-{
- phy->dev.parent = dev;
-}
-
-int wpan_phy_register(struct wpan_phy *phy);
-void wpan_phy_unregister(struct wpan_phy *phy);
-void wpan_phy_free(struct wpan_phy *phy);
-/* Same semantics as for class_for_each_device */
-int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), void *data);
-
-static inline void *wpan_phy_priv(struct wpan_phy *phy)
-{
- BUG_ON(!phy);
- return &phy->priv;
-}
-
-struct wpan_phy *wpan_phy_find(const char *str);
-
-static inline void wpan_phy_put(struct wpan_phy *phy)
-{
- put_device(&phy->dev);
-}
-
-static inline const char *wpan_phy_name(struct wpan_phy *phy)
-{
- return dev_name(&phy->dev);
-}
-
-#endif /* __NET_CFG802154_H */
diff --git a/include/linux/ieee802154.h b/include/net/ieee802154.h
similarity index 79%
rename from include/linux/ieee802154.h
rename to include/net/ieee802154.h
index 6e82d88..0aa7122 100644
--- a/include/linux/ieee802154.h
+++ b/include/net/ieee802154.h
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
* Maxim Gorbachyov <maxim.gorbachev@siemens.com>
@@ -20,27 +24,10 @@
* Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
*/
-#ifndef LINUX_IEEE802154_H
-#define LINUX_IEEE802154_H
-
-#include <linux/types.h>
-#include <linux/random.h>
-#include <asm/byteorder.h>
+#ifndef NET_IEEE802154_H
+#define NET_IEEE802154_H
#define IEEE802154_MTU 127
-#define IEEE802154_MIN_PSDU_LEN 5
-
-#define IEEE802154_PAN_ID_BROADCAST 0xffff
-#define IEEE802154_ADDR_SHORT_BROADCAST 0xffff
-#define IEEE802154_ADDR_SHORT_UNSPEC 0xfffe
-
-#define IEEE802154_EXTENDED_ADDR_LEN 8
-
-#define IEEE802154_LIFS_PERIOD 40
-#define IEEE802154_SIFS_PERIOD 12
-
-#define IEEE802154_MAX_CHANNEL 26
-#define IEEE802154_MAX_PAGE 31
#define IEEE802154_FC_TYPE_BEACON 0x0 /* Frame is beacon */
#define IEEE802154_FC_TYPE_DATA 0x1 /* Frame is data */
@@ -202,41 +189,7 @@
IEEE802154_SCAN_IN_PROGRESS = 0xfc,
};
-/**
- * ieee802154_is_valid_psdu_len - check if psdu len is valid
- * @len: psdu len with (MHR + payload + MFR)
- */
-static inline bool ieee802154_is_valid_psdu_len(const u8 len)
-{
- return (len >= IEEE802154_MIN_PSDU_LEN && len <= IEEE802154_MTU);
-}
-/**
- * ieee802154_is_valid_psdu_len - check if extended addr is valid
- * @addr: extended addr to check
- */
-static inline bool ieee802154_is_valid_extended_addr(const __le64 addr)
-{
- /* These EUI-64 addresses are reserved by IEEE. 0xffffffffffffffff
- * is used internally as extended to short address broadcast mapping.
- * This is currently a workaround because neighbor discovery can't
- * deal with short addresses types right now.
- */
- return ((addr != cpu_to_le64(0x0000000000000000ULL)) &&
- (addr != cpu_to_le64(0xffffffffffffffffULL)));
-}
+#endif
-/**
- * ieee802154_random_extended_addr - generates a random extended address
- * @addr: extended addr pointer to place the random address
- */
-static inline void ieee802154_random_extended_addr(__le64 *addr)
-{
- get_random_bytes(addr, IEEE802154_EXTENDED_ADDR_LEN);
- /* toggle some bit if we hit an invalid extended addr */
- if (!ieee802154_is_valid_extended_addr(*addr))
- ((u8 *)addr)[IEEE802154_EXTENDED_ADDR_LEN - 1] ^= 0x01;
-}
-
-#endif /* LINUX_IEEE802154_H */
diff --git a/include/net/ieee802154_netdev.h b/include/net/ieee802154_netdev.h
index 83bb8a7..3b53c8e 100644
--- a/include/net/ieee802154_netdev.h
+++ b/include/net/ieee802154_netdev.h
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
* Maxim Gorbachyov <maxim.gorbachev@siemens.com>
@@ -23,10 +27,10 @@
#ifndef IEEE802154_NETDEVICE_H
#define IEEE802154_NETDEVICE_H
+#include <net/ieee802154.h>
#include <net/af_ieee802154.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
-#include <linux/ieee802154.h>
struct ieee802154_sechdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
@@ -423,6 +427,8 @@
/* The fields below are required. */
+ struct wpan_phy *(*get_phy)(const struct net_device *dev);
+
/*
* FIXME: these should become the part of PIB/MIB interface.
* However we still don't have IB interface of any kind
@@ -432,6 +438,16 @@
u8 (*get_dsn)(const struct net_device *dev);
};
+/* The IEEE 802.15.4 standard defines 2 type of the devices:
+ * - FFD - full functionality device
+ * - RFD - reduce functionality device
+ *
+ * So 2 sets of mlme operations are needed
+ */
+struct ieee802154_reduced_mlme_ops {
+ struct wpan_phy *(*get_phy)(const struct net_device *dev);
+};
+
static inline struct ieee802154_mlme_ops *
ieee802154_mlme_ops(const struct net_device *dev)
{
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 96323df..c5ba507 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -263,7 +263,6 @@
* @BSS_CHANGED_BANDWIDTH: The bandwidth used by this interface changed,
* note that this is only called when it changes after the channel
* context had been assigned.
- * @BSS_CHANGED_OCB: OCB join status changed
*/
enum ieee80211_bss_change {
BSS_CHANGED_ASSOC = 1<<0,
@@ -288,7 +287,6 @@
BSS_CHANGED_P2P_PS = 1<<19,
BSS_CHANGED_BEACON_INFO = 1<<20,
BSS_CHANGED_BANDWIDTH = 1<<21,
- BSS_CHANGED_OCB = 1<<22,
/* when adding here, make sure to change ieee80211_reconfig */
};
@@ -741,8 +739,7 @@
u8 ampdu_ack_len;
u8 ampdu_len;
u8 antenna;
- u16 tx_time;
- void *status_driver_data[19 / sizeof(void *)];
+ void *status_driver_data[21 / sizeof(void *)];
} status;
struct {
struct ieee80211_tx_rate driver_rates[
@@ -882,9 +879,6 @@
* subframes share the same sequence number. Reported subframes can be
* either regular MSDU or singly A-MSDUs. Subframes must not be
* interleaved with other frames.
- * @RX_FLAG_RADIOTAP_VENDOR_DATA: This frame contains vendor-specific
- * radiotap data in the skb->data (before the frame) as described by
- * the &struct ieee80211_vendor_radiotap.
*/
enum mac80211_rx_flags {
RX_FLAG_MMIC_ERROR = BIT(0),
@@ -914,7 +908,6 @@
RX_FLAG_10MHZ = BIT(28),
RX_FLAG_5MHZ = BIT(29),
RX_FLAG_AMSDU_MORE = BIT(30),
- RX_FLAG_RADIOTAP_VENDOR_DATA = BIT(31),
};
#define RX_FLAG_STBC_SHIFT 26
@@ -986,39 +979,6 @@
};
/**
- * struct ieee80211_vendor_radiotap - vendor radiotap data information
- * @present: presence bitmap for this vendor namespace
- * (this could be extended in the future if any vendor needs more
- * bits, the radiotap spec does allow for that)
- * @align: radiotap vendor namespace alignment. This defines the needed
- * alignment for the @data field below, not for the vendor namespace
- * description itself (which has a fixed 2-byte alignment)
- * Must be a power of two, and be set to at least 1!
- * @oui: radiotap vendor namespace OUI
- * @subns: radiotap vendor sub namespace
- * @len: radiotap vendor sub namespace skip length, if alignment is done
- * then that's added to this, i.e. this is only the length of the
- * @data field.
- * @pad: number of bytes of padding after the @data, this exists so that
- * the skb data alignment can be preserved even if the data has odd
- * length
- * @data: the actual vendor namespace data
- *
- * This struct, including the vendor data, goes into the skb->data before
- * the 802.11 header. It's split up in mac80211 using the align/oui/subns
- * data.
- */
-struct ieee80211_vendor_radiotap {
- u32 present;
- u8 align;
- u8 oui[3];
- u8 subns;
- u8 pad;
- u16 len;
- u8 data[];
-} __packed;
-
-/**
* enum ieee80211_conf_flags - configuration flags
*
* Flags to define PHY configuration options
@@ -1157,8 +1117,6 @@
* Function (TSF) timer when the frame containing the channel switch
* announcement was received. This is simply the rx.mactime parameter
* the driver passed into mac80211.
- * @device_timestamp: arbitrary timestamp for the device, this is the
- * rx.device_timestamp parameter the driver passed to mac80211.
* @block_tx: Indicates whether transmission must be blocked before the
* scheduled channel switch, as indicated by the AP.
* @chandef: the new channel to switch to
@@ -1166,7 +1124,6 @@
*/
struct ieee80211_channel_switch {
u64 timestamp;
- u32 device_timestamp;
bool block_tx;
struct cfg80211_chan_def chandef;
u8 count;
@@ -1466,8 +1423,6 @@
* @smps_mode: current SMPS mode (off, static or dynamic)
* @rates: rate control selection table
* @tdls: indicates whether the STA is a TDLS peer
- * @tdls_initiator: indicates the STA is an initiator of the TDLS link. Only
- * valid if the STA is a TDLS peer in the first place.
*/
struct ieee80211_sta {
u32 supp_rates[IEEE80211_NUM_BANDS];
@@ -1483,7 +1438,6 @@
enum ieee80211_smps_mode smps_mode;
struct ieee80211_sta_rates __rcu *rates;
bool tdls;
- bool tdls_initiator;
/* must be last */
u8 drv_priv[0] __aligned(sizeof(void *));
@@ -1622,10 +1576,6 @@
* a virtual monitor interface when monitor interfaces are the only
* active interfaces.
*
- * @IEEE80211_HW_NO_AUTO_VIF: The driver would like for no wlanX to
- * be created. It is expected user-space will create vifs as
- * desired (and thus have them named as desired).
- *
* @IEEE80211_HW_QUEUE_CONTROL: The driver wants to control per-interface
* queue mapping in order to use different queues (not just one per AC)
* for different virtual interfaces. See the doc section on HW queue
@@ -1672,8 +1622,7 @@
IEEE80211_HW_SUPPORTS_DYNAMIC_PS = 1<<12,
IEEE80211_HW_MFP_CAPABLE = 1<<13,
IEEE80211_HW_WANT_MONITOR_VIF = 1<<14,
- IEEE80211_HW_NO_AUTO_VIF = 1<<15,
- /* free slot */
+ /* free slots */
IEEE80211_HW_SUPPORTS_UAPSD = 1<<17,
IEEE80211_HW_REPORTS_TX_ACK_STATUS = 1<<18,
IEEE80211_HW_CONNECTION_MONITOR = 1<<19,
@@ -1827,31 +1776,6 @@
};
/**
- * struct ieee80211_tdls_ch_sw_params - TDLS channel switch parameters
- *
- * @sta: peer this TDLS channel-switch request/response came from
- * @chandef: channel referenced in a TDLS channel-switch request
- * @action_code: see &enum ieee80211_tdls_actioncode
- * @status: channel-switch response status
- * @timestamp: time at which the frame was received
- * @switch_time: switch-timing parameter received in the frame
- * @switch_timeout: switch-timing parameter received in the frame
- * @tmpl_skb: TDLS switch-channel response template
- * @ch_sw_tm_ie: offset of the channel-switch timing IE inside @tmpl_skb
- */
-struct ieee80211_tdls_ch_sw_params {
- struct ieee80211_sta *sta;
- struct cfg80211_chan_def *chandef;
- u8 action_code;
- u32 status;
- u32 timestamp;
- u16 switch_time;
- u16 switch_timeout;
- struct sk_buff *tmpl_skb;
- u32 ch_sw_tm_ie;
-};
-
-/**
* wiphy_to_ieee80211_hw - return a mac80211 driver hw struct from a wiphy
*
* @wiphy: the &struct wiphy which we want to query
@@ -2451,22 +2375,6 @@
};
/**
- * enum ieee80211_reconfig_complete_type - reconfig type
- *
- * This enum is used by the reconfig_complete() callback to indicate what
- * reconfiguration type was completed.
- *
- * @IEEE80211_RECONFIG_TYPE_RESTART: hw restart type
- * (also due to resume() callback returning 1)
- * @IEEE80211_RECONFIG_TYPE_SUSPEND: suspend type (regardless
- * of wowlan configuration)
- */
-enum ieee80211_reconfig_type {
- IEEE80211_RECONFIG_TYPE_RESTART,
- IEEE80211_RECONFIG_TYPE_SUSPEND,
-};
-
-/**
* struct ieee80211_ops - callbacks from mac80211 to the driver
*
* This structure contains various callbacks that the driver may
@@ -2622,9 +2530,7 @@
*
* @sw_scan_start: Notifier function that is called just before a software scan
* is started. Can be NULL, if the driver doesn't need this notification.
- * The mac_addr parameter allows supporting NL80211_SCAN_FLAG_RANDOM_ADDR,
- * the driver may set the NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR flag if it
- * can use this parameter. The callback can sleep.
+ * The callback can sleep.
*
* @sw_scan_complete: Notifier function that is called just after a
* software scan finished. Can be NULL, if the driver doesn't need
@@ -2695,9 +2601,6 @@
* uses hardware rate control (%IEEE80211_HW_HAS_RATE_CONTROL) since
* otherwise the rate control algorithm is notified directly.
* Must be atomic.
- * @sta_rate_tbl_update: Notifies the driver that the rate table changed. This
- * is only used if the configured rate control algorithm actually uses
- * the new rate table API, and is therefore optional. Must be atomic.
*
* @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
* bursting) for a hardware TX queue.
@@ -2906,11 +2809,11 @@
* disabled/enabled via @bss_info_changed.
* @stop_ap: Stop operation on the AP interface.
*
- * @reconfig_complete: Called after a call to ieee80211_restart_hw() and
- * during resume, when the reconfiguration has completed.
- * This can help the driver implement the reconfiguration step (and
- * indicate mac80211 is ready to receive frames).
- * This callback may sleep.
+ * @restart_complete: Called after a call to ieee80211_restart_hw(), when the
+ * reconfiguration has completed. This can help the driver implement the
+ * reconfiguration step. Also called when reconfiguring because the
+ * driver's resume function returned 1, as this is just like an "inline"
+ * hardware restart. This callback may sleep.
*
* @ipv6_addr_change: IPv6 address assignment on the given interface changed.
* Currently, this is only called for managed or P2P client interfaces.
@@ -2926,13 +2829,6 @@
* transmitted and then call ieee80211_csa_finish().
* If the CSA count starts as zero or 1, this function will not be called,
* since there won't be any time to beacon before the switch anyway.
- * @pre_channel_switch: This is an optional callback that is called
- * before a channel switch procedure is started (ie. when a STA
- * gets a CSA or an userspace initiated channel-switch), allowing
- * the driver to prepare for the channel switch.
- * @post_channel_switch: This is an optional callback that is called
- * after a channel switch procedure is completed, allowing the
- * driver to go back to a normal configuration.
*
* @join_ibss: Join an IBSS (on an IBSS interface); this is called after all
* information in bss_conf is set up and the beacon can be retrieved. A
@@ -2942,26 +2838,6 @@
* @get_expected_throughput: extract the expected throughput towards the
* specified station. The returned value is expressed in Kbps. It returns 0
* if the RC algorithm does not have proper data to provide.
- *
- * @get_txpower: get current maximum tx power (in dBm) based on configuration
- * and hardware limits.
- *
- * @tdls_channel_switch: Start channel-switching with a TDLS peer. The driver
- * is responsible for continually initiating channel-switching operations
- * and returning to the base channel for communication with the AP. The
- * driver receives a channel-switch request template and the location of
- * the switch-timing IE within the template as part of the invocation.
- * The template is valid only within the call, and the driver can
- * optionally copy the skb for further re-use.
- * @tdls_cancel_channel_switch: Stop channel-switching with a TDLS peer. Both
- * peers must be on the base channel when the call completes.
- * @tdls_recv_channel_switch: a TDLS channel-switch related frame (request or
- * response) has been received from a remote peer. The driver gets
- * parameters parsed from the incoming frame and may use them to continue
- * an ongoing channel-switch operation. In addition, a channel-switch
- * response template is provided, together with the location of the
- * switch-timing IE within the template. The skb can only be used within
- * the function call.
*/
struct ieee80211_ops {
void (*tx)(struct ieee80211_hw *hw,
@@ -3021,11 +2897,8 @@
struct ieee80211_scan_ies *ies);
int (*sched_scan_stop)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif);
- void (*sw_scan_start)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- const u8 *mac_addr);
- void (*sw_scan_complete)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
+ void (*sw_scan_start)(struct ieee80211_hw *hw);
+ void (*sw_scan_complete)(struct ieee80211_hw *hw);
int (*get_stats)(struct ieee80211_hw *hw,
struct ieee80211_low_level_stats *stats);
void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
@@ -3059,9 +2932,6 @@
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
u32 changed);
- void (*sta_rate_tbl_update)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
int (*conf_tx)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif, u16 ac,
const struct ieee80211_tx_queue_params *params);
@@ -3089,7 +2959,6 @@
void (*flush)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u32 queues, bool drop);
void (*channel_switch)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
struct ieee80211_channel_switch *ch_switch);
int (*set_antenna)(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant);
int (*get_antenna)(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant);
@@ -3156,8 +3025,7 @@
int n_vifs,
enum ieee80211_chanctx_switch_mode mode);
- void (*reconfig_complete)(struct ieee80211_hw *hw,
- enum ieee80211_reconfig_type reconfig_type);
+ void (*restart_complete)(struct ieee80211_hw *hw);
#if IS_ENABLED(CONFIG_IPV6)
void (*ipv6_addr_change)(struct ieee80211_hw *hw,
@@ -3167,54 +3035,14 @@
void (*channel_switch_beacon)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct cfg80211_chan_def *chandef);
- int (*pre_channel_switch)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_channel_switch *ch_switch);
-
- int (*post_channel_switch)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif);
int (*join_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
void (*leave_ibss)(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
u32 (*get_expected_throughput)(struct ieee80211_sta *sta);
- int (*get_txpower)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- int *dbm);
-
- int (*tdls_channel_switch)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta, u8 oper_class,
- struct cfg80211_chan_def *chandef,
- struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie);
- void (*tdls_cancel_channel_switch)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta);
- void (*tdls_recv_channel_switch)(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_tdls_ch_sw_params *params);
};
/**
- * ieee80211_alloc_hw_nm - Allocate a new hardware device
- *
- * This must be called once for each hardware device. The returned pointer
- * must be used to refer to this device when calling other functions.
- * mac80211 allocates a private data area for the driver pointed to by
- * @priv in &struct ieee80211_hw, the size of this area is given as
- * @priv_data_len.
- *
- * @priv_data_len: length of private data
- * @ops: callbacks for this device
- * @requested_name: Requested name for this device.
- * NULL is valid value, and means use the default naming (phy%d)
- *
- * Return: A pointer to the new hardware device, or %NULL on error.
- */
-struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
- const struct ieee80211_ops *ops,
- const char *requested_name);
-
-/**
- * ieee80211_alloc_hw - Allocate a new hardware device
+ * ieee80211_alloc_hw - Allocate a new hardware device
*
* This must be called once for each hardware device. The returned pointer
* must be used to refer to this device when calling other functions.
@@ -3227,12 +3055,8 @@
*
* Return: A pointer to the new hardware device, or %NULL on error.
*/
-static inline
struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
- const struct ieee80211_ops *ops)
-{
- return ieee80211_alloc_hw_nm(priv_data_len, ops, NULL);
-}
+ const struct ieee80211_ops *ops);
/**
* ieee80211_register_hw - Register hardware device
@@ -3619,26 +3443,6 @@
struct sk_buff *skb);
/**
- * ieee80211_tx_status_noskb - transmit status callback without skb
- *
- * This function can be used as a replacement for ieee80211_tx_status
- * in drivers that cannot reliably map tx status information back to
- * specific skbs.
- *
- * Calls to this function for a single hardware must be synchronized
- * against each other. Calls to this function, ieee80211_tx_status_ni()
- * and ieee80211_tx_status_irqsafe() may not be mixed for a single hardware.
- *
- * @hw: the hardware the frame was transmitted by
- * @sta: the receiver station to which this packet is sent
- * (NULL for multicast packets)
- * @info: tx status information
- */
-void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
- struct ieee80211_sta *sta,
- struct ieee80211_tx_info *info);
-
-/**
* ieee80211_tx_status_ni - transmit status callback (in process context)
*
* Like ieee80211_tx_status() but can be called in process context.
@@ -3851,7 +3655,7 @@
/**
* ieee80211_probereq_get - retrieve a Probe Request template
* @hw: pointer obtained from ieee80211_alloc_hw().
- * @src_addr: source MAC address
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
* @ssid: SSID buffer
* @ssid_len: length of SSID
* @tailroom: tailroom to reserve at end of SKB for IEs
@@ -3862,7 +3666,7 @@
* Return: The Probe Request template. %NULL on error.
*/
struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
- const u8 *src_addr,
+ struct ieee80211_vif *vif,
const u8 *ssid, size_t ssid_len,
size_t tailroom);
@@ -4368,22 +4172,6 @@
void *data);
/**
- * ieee80211_iterate_stations_atomic - iterate stations
- *
- * This function iterates over all stations associated with a given
- * hardware that are currently uploaded to the driver and calls the callback
- * function for them.
- * This function requires the iterator callback function to be atomic,
- *
- * @hw: the hardware struct of which the interfaces should be iterated over
- * @iterator: the iterator function to call, cannot sleep
- * @data: first argument of the iterator function
- */
-void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
- void (*iterator)(void *data,
- struct ieee80211_sta *sta),
- void *data);
-/**
* ieee80211_queue_work - add work onto the mac80211 workqueue
*
* Drivers and mac80211 use this to add work onto the mac80211 workqueue.
@@ -4692,14 +4480,6 @@
gfp_t gfp);
/**
- * ieee80211_cqm_beacon_loss_notify - inform CQM of beacon loss
- *
- * @vif: &struct ieee80211_vif pointer from the add_interface callback.
- * @gfp: context flags
- */
-void ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp);
-
-/**
* ieee80211_radar_detected - inform that a radar was detected
*
* @hw: pointer as obtained from ieee80211_alloc_hw()
@@ -4857,10 +4637,6 @@
void (*free_sta)(void *priv, struct ieee80211_sta *sta,
void *priv_sta);
- void (*tx_status_noskb)(void *priv,
- struct ieee80211_supported_band *sband,
- struct ieee80211_sta *sta, void *priv_sta,
- struct ieee80211_tx_info *info);
void (*tx_status)(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
struct sk_buff *skb);
@@ -5112,69 +4888,4 @@
void ieee80211_tdls_oper_request(struct ieee80211_vif *vif, const u8 *peer,
enum nl80211_tdls_operation oper,
u16 reason_code, gfp_t gfp);
-
-/**
- * ieee80211_reserve_tid - request to reserve a specific TID
- *
- * There is sometimes a need (such as in TDLS) for blocking the driver from
- * using a specific TID so that the FW can use it for certain operations such
- * as sending PTI requests. To make sure that the driver doesn't use that TID,
- * this function must be called as it flushes out packets on this TID and marks
- * it as blocked, so that any transmit for the station on this TID will be
- * redirected to the alternative TID in the same AC.
- *
- * Note that this function blocks and may call back into the driver, so it
- * should be called without driver locks held. Also note this function should
- * only be called from the driver's @sta_state callback.
- *
- * @sta: the station to reserve the TID for
- * @tid: the TID to reserve
- *
- * Returns: 0 on success, else on failure
- */
-int ieee80211_reserve_tid(struct ieee80211_sta *sta, u8 tid);
-
-/**
- * ieee80211_unreserve_tid - request to unreserve a specific TID
- *
- * Once there is no longer any need for reserving a certain TID, this function
- * should be called, and no longer will packets have their TID modified for
- * preventing use of this TID in the driver.
- *
- * Note that this function blocks and acquires a lock, so it should be called
- * without driver locks held. Also note this function should only be called
- * from the driver's @sta_state callback.
- *
- * @sta: the station
- * @tid: the TID to unreserve
- */
-void ieee80211_unreserve_tid(struct ieee80211_sta *sta, u8 tid);
-
-/**
- * ieee80211_ie_split - split an IE buffer according to ordering
- *
- * @ies: the IE buffer
- * @ielen: the length of the IE buffer
- * @ids: an array with element IDs that are allowed before
- * the split
- * @n_ids: the size of the element ID array
- * @offset: offset where to start splitting in the buffer
- *
- * This function splits an IE buffer by updating the @offset
- * variable to point to the location where the buffer should be
- * split.
- *
- * It assumes that the given IE buffer is well-formed, this
- * has to be guaranteed by the caller!
- *
- * It also assumes that the IEs in the buffer are ordered
- * correctly, if not the result of using this function will not
- * be ordered correctly either, i.e. it does no reordering.
- *
- * The function returns the offset where the next part of the
- * buffer starts, which may be @ielen if the entire (remainder)
- * of the buffer should be used.
- */
-size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
- const u8 *ids, int n_ids, size_t offset);
#endif /* MAC80211_H */
diff --git a/include/net/mac802154.h b/include/net/mac802154.h
index c823d91..2e67cdd 100644
--- a/include/net/mac802154.h
+++ b/include/net/mac802154.h
@@ -12,12 +12,14 @@
* 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 NET_MAC802154_H
#define NET_MAC802154_H
#include <net/af_ieee802154.h>
-#include <linux/ieee802154.h>
#include <linux/skbuff.h>
/* General MAC frame format:
@@ -33,13 +35,13 @@
*/
/* indicates that the Short Address changed */
-#define IEEE802154_AFILT_SADDR_CHANGED 0x00000001
+#define IEEE802515_AFILT_SADDR_CHANGED 0x00000001
/* indicates that the IEEE Address changed */
-#define IEEE802154_AFILT_IEEEADDR_CHANGED 0x00000002
+#define IEEE802515_AFILT_IEEEADDR_CHANGED 0x00000002
/* indicates that the PAN ID changed */
-#define IEEE802154_AFILT_PANID_CHANGED 0x00000004
+#define IEEE802515_AFILT_PANID_CHANGED 0x00000004
/* indicates that PAN Coordinator status changed */
-#define IEEE802154_AFILT_PANC_CHANGED 0x00000008
+#define IEEE802515_AFILT_PANC_CHANGED 0x00000008
struct ieee802154_hw_addr_filt {
__le16 pan_id; /* Each independent PAN selects a unique
@@ -53,14 +55,7 @@
u8 pan_coord;
};
-struct ieee802154_vif {
- int type;
-
- /* must be last */
- u8 drv_priv[0] __aligned(sizeof(void *));
-};
-
-struct ieee802154_hw {
+struct ieee802154_dev {
/* filled by the driver */
int extra_tx_headroom;
u32 flags;
@@ -70,7 +65,6 @@
struct ieee802154_hw_addr_filt hw_filt;
void *priv;
struct wpan_phy *phy;
- size_t vif_data_size;
};
/* Checksum is in hardware and is omitted from a packet
@@ -82,43 +76,28 @@
* however, so you are advised to review these flags carefully.
*/
-/* Indicates that xmitter will add FCS on it's own. */
-#define IEEE802154_HW_TX_OMIT_CKSUM 0x00000001
+/* Indicates that receiver omits FCS and xmitter will add FCS on it's own. */
+#define IEEE802154_HW_OMIT_CKSUM 0x00000001
/* Indicates that receiver will autorespond with ACK frames. */
-#define IEEE802154_HW_AACK 0x00000002
+#define IEEE802154_HW_AACK 0x00000002
/* Indicates that transceiver will support transmit power setting. */
-#define IEEE802154_HW_TXPOWER 0x00000004
+#define IEEE802154_HW_TXPOWER 0x00000004
/* Indicates that transceiver will support listen before transmit. */
-#define IEEE802154_HW_LBT 0x00000008
+#define IEEE802154_HW_LBT 0x00000008
/* Indicates that transceiver will support cca mode setting. */
-#define IEEE802154_HW_CCA_MODE 0x00000010
+#define IEEE802154_HW_CCA_MODE 0x00000010
/* Indicates that transceiver will support cca ed level setting. */
-#define IEEE802154_HW_CCA_ED_LEVEL 0x00000020
+#define IEEE802154_HW_CCA_ED_LEVEL 0x00000020
/* Indicates that transceiver will support csma (max_be, min_be, csma retries)
* settings. */
-#define IEEE802154_HW_CSMA_PARAMS 0x00000040
+#define IEEE802154_HW_CSMA_PARAMS 0x00000040
/* Indicates that transceiver will support ARET frame retries setting. */
-#define IEEE802154_HW_FRAME_RETRIES 0x00000080
-/* Indicates that transceiver will support hardware address filter setting. */
-#define IEEE802154_HW_AFILT 0x00000100
-/* Indicates that transceiver will support promiscuous mode setting. */
-#define IEEE802154_HW_PROMISCUOUS 0x00000200
-/* Indicates that receiver omits FCS. */
-#define IEEE802154_HW_RX_OMIT_CKSUM 0x00000400
-/* Indicates that receiver will not filter frames with bad checksum. */
-#define IEEE802154_HW_RX_DROP_BAD_CKSUM 0x00000800
-
-/* Indicates that receiver omits FCS and xmitter will add FCS on it's own. */
-#define IEEE802154_HW_OMIT_CKSUM (IEEE802154_HW_TX_OMIT_CKSUM | \
- IEEE802154_HW_RX_OMIT_CKSUM)
+#define IEEE802154_HW_FRAME_RETRIES 0x00000080
/* This groups the most common CSMA support fields into one. */
#define IEEE802154_HW_CSMA (IEEE802154_HW_CCA_MODE | \
IEEE802154_HW_CCA_ED_LEVEL | \
- IEEE802154_HW_CSMA_PARAMS)
-
-/* This groups the most common ARET support fields into one. */
-#define IEEE802154_HW_ARET (IEEE802154_HW_CSMA | \
+ IEEE802154_HW_CSMA_PARAMS | \
IEEE802154_HW_FRAME_RETRIES)
/* struct ieee802154_ops - callbacks from mac802154 to the driver
@@ -133,24 +112,12 @@
* stop: Handler that 802.15.4 module calls for device cleanup.
* This function is called after the last interface is removed.
*
- * xmit_sync:
- * Handler that 802.15.4 module calls for each transmitted frame.
- * skb cntains the buffer starting from the IEEE 802.15.4 header.
- * The low-level driver should send the frame based on available
- * configuration. This is called by a workqueue and useful for
- * synchronous 802.15.4 drivers.
- * This function should return zero or negative errno.
- *
- * WARNING:
- * This will be deprecated soon. We don't accept synced xmit callbacks
- * drivers anymore.
- *
- * xmit_async:
- * Handler that 802.15.4 module calls for each transmitted frame.
+ * xmit: Handler that 802.15.4 module calls for each transmitted frame.
* skb cntains the buffer starting from the IEEE 802.15.4 header.
* The low-level driver should send the frame based on available
* configuration.
- * This function should return zero or negative errno.
+ * This function should return zero or negative errno. Called with
+ * pib_lock held.
*
* ed: Handler that 802.15.4 module calls for Energy Detection.
* This function should place the value for detected energy
@@ -192,75 +159,40 @@
* set_frame_retries
* Sets the retransmission attempt limit. Called with pib_lock held.
* Returns either zero, or negative errno.
- *
- * set_promiscuous_mode
- * Enables or disable promiscuous mode.
*/
struct ieee802154_ops {
struct module *owner;
- int (*start)(struct ieee802154_hw *hw);
- void (*stop)(struct ieee802154_hw *hw);
- int (*xmit_sync)(struct ieee802154_hw *hw,
- struct sk_buff *skb);
- int (*xmit_async)(struct ieee802154_hw *hw,
- struct sk_buff *skb);
- int (*ed)(struct ieee802154_hw *hw, u8 *level);
- int (*set_channel)(struct ieee802154_hw *hw, u8 page,
- u8 channel);
- int (*set_hw_addr_filt)(struct ieee802154_hw *hw,
- struct ieee802154_hw_addr_filt *filt,
+ int (*start)(struct ieee802154_dev *dev);
+ void (*stop)(struct ieee802154_dev *dev);
+ int (*xmit)(struct ieee802154_dev *dev,
+ struct sk_buff *skb);
+ int (*ed)(struct ieee802154_dev *dev, u8 *level);
+ int (*set_channel)(struct ieee802154_dev *dev,
+ int page,
+ int channel);
+ int (*set_hw_addr_filt)(struct ieee802154_dev *dev,
+ struct ieee802154_hw_addr_filt *filt,
unsigned long changed);
- int (*set_txpower)(struct ieee802154_hw *hw, int db);
- int (*set_lbt)(struct ieee802154_hw *hw, bool on);
- int (*set_cca_mode)(struct ieee802154_hw *hw, u8 mode);
- int (*set_cca_ed_level)(struct ieee802154_hw *hw,
+ int (*ieee_addr)(struct ieee802154_dev *dev, __le64 addr);
+ int (*set_txpower)(struct ieee802154_dev *dev, int db);
+ int (*set_lbt)(struct ieee802154_dev *dev, bool on);
+ int (*set_cca_mode)(struct ieee802154_dev *dev, u8 mode);
+ int (*set_cca_ed_level)(struct ieee802154_dev *dev,
s32 level);
- int (*set_csma_params)(struct ieee802154_hw *hw,
+ int (*set_csma_params)(struct ieee802154_dev *dev,
u8 min_be, u8 max_be, u8 retries);
- int (*set_frame_retries)(struct ieee802154_hw *hw,
+ int (*set_frame_retries)(struct ieee802154_dev *dev,
s8 retries);
- int (*set_promiscuous_mode)(struct ieee802154_hw *hw,
- const bool on);
};
-/**
- * ieee802154_be64_to_le64 - copies and convert be64 to le64
- * @le64_dst: le64 destination pointer
- * @be64_src: be64 source pointer
- */
-static inline void ieee802154_be64_to_le64(void *le64_dst, const void *be64_src)
-{
- __le64 tmp = (__force __le64)swab64p(be64_src);
+/* Basic interface to register ieee802154 device */
+struct ieee802154_dev *
+ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops);
+void ieee802154_free_device(struct ieee802154_dev *dev);
+int ieee802154_register_device(struct ieee802154_dev *dev);
+void ieee802154_unregister_device(struct ieee802154_dev *dev);
- memcpy(le64_dst, &tmp, IEEE802154_EXTENDED_ADDR_LEN);
-}
-
-/**
- * ieee802154_le64_to_be64 - copies and convert le64 to be64
- * @be64_dst: be64 destination pointer
- * @le64_src: le64 source pointer
- */
-static inline void ieee802154_le64_to_be64(void *be64_dst, const void *le64_src)
-{
- __be64 tmp = (__force __be64)swab64p(le64_src);
-
- memcpy(be64_dst, &tmp, IEEE802154_EXTENDED_ADDR_LEN);
-}
-
-/* Basic interface to register ieee802154 hwice */
-struct ieee802154_hw *
-ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops);
-void ieee802154_free_hw(struct ieee802154_hw *hw);
-int ieee802154_register_hw(struct ieee802154_hw *hw);
-void ieee802154_unregister_hw(struct ieee802154_hw *hw);
-
-void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb);
-void ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb,
+void ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb,
u8 lqi);
-void ieee802154_wake_queue(struct ieee802154_hw *hw);
-void ieee802154_stop_queue(struct ieee802154_hw *hw);
-void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
- bool ifs_handling);
-
#endif /* NET_MAC802154_H */
diff --git a/include/net/nfc/digital.h b/include/net/nfc/digital.h
index 0ae101e..d9a5cf7 100644
--- a/include/net/nfc/digital.h
+++ b/include/net/nfc/digital.h
@@ -225,19 +225,6 @@
u8 curr_protocol;
u8 curr_rf_tech;
u8 curr_nfc_dep_pni;
- u8 did;
-
- u8 local_payload_max;
- u8 remote_payload_max;
-
- struct sk_buff *chaining_skb;
- struct digital_data_exch *data_exch;
-
- int atn_count;
- int nack_count;
-
- struct sk_buff *saved_skb;
- unsigned int saved_skb_len;
u16 target_fsc;
diff --git a/include/net/nfc/hci.h b/include/net/nfc/hci.h
index 14bd0e1..7ee8f4c 100644
--- a/include/net/nfc/hci.h
+++ b/include/net/nfc/hci.h
@@ -57,14 +57,10 @@
int (*discover_se)(struct nfc_hci_dev *dev);
int (*enable_se)(struct nfc_hci_dev *dev, u32 se_idx);
int (*disable_se)(struct nfc_hci_dev *dev, u32 se_idx);
- int (*se_io)(struct nfc_hci_dev *dev, u32 se_idx,
- u8 *apdu, size_t apdu_length,
- se_io_cb_t cb, void *cb_context);
};
/* Pipes */
#define NFC_HCI_INVALID_PIPE 0x80
-#define NFC_HCI_DO_NOT_CREATE_PIPE 0x81
#define NFC_HCI_LINK_MGMT_PIPE 0x00
#define NFC_HCI_ADMIN_PIPE 0x01
diff --git a/include/net/nfc/nci.h b/include/net/nfc/nci.h
index e7257a4..9eca9ae 100644
--- a/include/net/nfc/nci.h
+++ b/include/net/nfc/nci.h
@@ -28,8 +28,6 @@
#ifndef __NCI_H
#define __NCI_H
-#include <net/nfc/nfc.h>
-
/* NCI constants */
#define NCI_MAX_NUM_MAPPING_CONFIGS 10
#define NCI_MAX_NUM_RF_CONFIGS 10
@@ -75,8 +73,6 @@
#define NCI_NFC_A_ACTIVE_LISTEN_MODE 0x83
#define NCI_NFC_F_ACTIVE_LISTEN_MODE 0x85
-#define NCI_RF_TECH_MODE_LISTEN_MASK 0x80
-
/* NCI RF Technologies */
#define NCI_NFC_RF_TECHNOLOGY_A 0x00
#define NCI_NFC_RF_TECHNOLOGY_B 0x01
@@ -110,17 +106,6 @@
/* NCI Configuration Parameter Tags */
#define NCI_PN_ATR_REQ_GEN_BYTES 0x29
-#define NCI_LN_ATR_RES_GEN_BYTES 0x61
-#define NCI_LA_SEL_INFO 0x32
-#define NCI_LF_PROTOCOL_TYPE 0x50
-#define NCI_LF_CON_BITR_F 0x54
-
-/* NCI Configuration Parameters masks */
-#define NCI_LA_SEL_INFO_ISO_DEP_MASK 0x20
-#define NCI_LA_SEL_INFO_NFC_DEP_MASK 0x40
-#define NCI_LF_PROTOCOL_TYPE_NFC_DEP_MASK 0x02
-#define NCI_LF_CON_BITR_F_212 0x02
-#define NCI_LF_CON_BITR_F_424 0x04
/* NCI Reset types */
#define NCI_RESET_TYPE_KEEP_CONFIG 0x00
@@ -329,31 +314,26 @@
struct rf_tech_specific_params_nfca_poll {
__u16 sens_res;
__u8 nfcid1_len; /* 0, 4, 7, or 10 Bytes */
- __u8 nfcid1[NFC_NFCID1_MAXSIZE];
+ __u8 nfcid1[10];
__u8 sel_res_len; /* 0 or 1 Bytes */
__u8 sel_res;
} __packed;
struct rf_tech_specific_params_nfcb_poll {
__u8 sensb_res_len;
- __u8 sensb_res[NFC_SENSB_RES_MAXSIZE]; /* 11 or 12 Bytes */
+ __u8 sensb_res[12]; /* 11 or 12 Bytes */
} __packed;
struct rf_tech_specific_params_nfcf_poll {
__u8 bit_rate;
__u8 sensf_res_len;
- __u8 sensf_res[NFC_SENSF_RES_MAXSIZE]; /* 16 or 18 Bytes */
+ __u8 sensf_res[18]; /* 16 or 18 Bytes */
} __packed;
struct rf_tech_specific_params_nfcv_poll {
__u8 res_flags;
__u8 dsfid;
- __u8 uid[NFC_ISO15693_UID_MAXSIZE]; /* 8 Bytes */
-} __packed;
-
-struct rf_tech_specific_params_nfcf_listen {
- __u8 local_nfcid2_len;
- __u8 local_nfcid2[NFC_NFCID2_MAXSIZE]; /* 0 or 8 Bytes */
+ __u8 uid[8]; /* 8 Bytes */
} __packed;
struct nci_rf_discover_ntf {
@@ -385,12 +365,7 @@
struct activation_params_poll_nfc_dep {
__u8 atr_res_len;
- __u8 atr_res[NFC_ATR_RES_MAXSIZE - 2]; /* ATR_RES from byte 3 */
-};
-
-struct activation_params_listen_nfc_dep {
- __u8 atr_req_len;
- __u8 atr_req[NFC_ATR_REQ_MAXSIZE - 2]; /* ATR_REQ from byte 3 */
+ __u8 atr_res[63];
};
struct nci_rf_intf_activated_ntf {
@@ -407,7 +382,6 @@
struct rf_tech_specific_params_nfcb_poll nfcb_poll;
struct rf_tech_specific_params_nfcf_poll nfcf_poll;
struct rf_tech_specific_params_nfcv_poll nfcv_poll;
- struct rf_tech_specific_params_nfcf_listen nfcf_listen;
} rf_tech_specific_params;
__u8 data_exch_rf_tech_and_mode;
@@ -419,7 +393,6 @@
struct activation_params_nfca_poll_iso_dep nfca_poll_iso_dep;
struct activation_params_nfcb_poll_iso_dep nfcb_poll_iso_dep;
struct activation_params_poll_nfc_dep poll_nfc_dep;
- struct activation_params_listen_nfc_dep listen_nfc_dep;
} activation_params;
} __packed;
diff --git a/include/net/nfc/nci_core.h b/include/net/nfc/nci_core.h
index 9e51bb4..75d10e6 100644
--- a/include/net/nfc/nci_core.h
+++ b/include/net/nfc/nci_core.h
@@ -4,7 +4,6 @@
*
* Copyright (C) 2011 Texas Instruments, Inc.
* Copyright (C) 2013 Intel Corporation. All rights reserved.
- * Copyright (C) 2014 Marvell International Ltd.
*
* Written by Ilan Elias <ilane@ti.com>
*
@@ -50,8 +49,6 @@
NCI_W4_ALL_DISCOVERIES,
NCI_W4_HOST_SELECT,
NCI_POLL_ACTIVE,
- NCI_LISTEN_ACTIVE,
- NCI_LISTEN_SLEEP,
};
/* NCI timeouts */
@@ -72,12 +69,6 @@
int (*send)(struct nci_dev *ndev, struct sk_buff *skb);
int (*setup)(struct nci_dev *ndev);
__u32 (*get_rfprotocol)(struct nci_dev *ndev, __u8 rf_protocol);
- int (*discover_se)(struct nci_dev *ndev);
- int (*disable_se)(struct nci_dev *ndev, u32 se_idx);
- int (*enable_se)(struct nci_dev *ndev, u32 se_idx);
- int (*se_io)(struct nci_dev *ndev, u32 se_idx,
- u8 *apdu, size_t apdu_length,
- se_io_cb_t cb, void *cb_context);
};
#define NCI_MAX_SUPPORTED_RF_INTERFACES 4
diff --git a/include/net/nfc/nfc.h b/include/net/nfc/nfc.h
index 12adb81..6c583e2 100644
--- a/include/net/nfc/nfc.h
+++ b/include/net/nfc/nfc.h
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2011 Instituto Nokia de Tecnologia
- * Copyright (C) 2014 Marvell International Ltd.
*
* Authors:
* Lauro Ramos Venancio <lauro.venancio@openbossa.org>
@@ -88,7 +87,6 @@
#define NFC_TARGET_IDX_ANY -1
#define NFC_MAX_GT_LEN 48
#define NFC_ATR_RES_GT_OFFSET 15
-#define NFC_ATR_REQ_GT_OFFSET 14
/**
* struct nfc_target - NFC target descriptiom
diff --git a/include/net/nl802154.h b/include/net/nl802154.h
index 6dbd406..b23548e 100644
--- a/include/net/nl802154.h
+++ b/include/net/nl802154.h
@@ -1,122 +1,126 @@
-#ifndef __NL802154_H
-#define __NL802154_H
/*
- * 802.15.4 netlink interface public header
+ * nl802154.h
*
- * Copyright 2014 Alexander Aring <aar@pengutronix.de>
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
*
- * 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.
+ * 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.
*
- * 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 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.
*
*/
-#define NL802154_GENL_NAME "nl802154"
+#ifndef IEEE802154_NL_H
+#define IEEE802154_NL_H
-enum nl802154_commands {
-/* don't change the order or add anything between, this is ABI! */
-/* currently we don't shipping this file via uapi, ignore the above one */
- NL802154_CMD_UNSPEC,
+struct net_device;
+struct ieee802154_addr;
- NL802154_CMD_GET_WPAN_PHY, /* can dump */
- NL802154_CMD_SET_WPAN_PHY,
- NL802154_CMD_NEW_WPAN_PHY,
- NL802154_CMD_DEL_WPAN_PHY,
+/**
+ * ieee802154_nl_assoc_indic - Notify userland of an association request.
+ * @dev: The network device on which this association request was
+ * received.
+ * @addr: The address of the device requesting association.
+ * @cap: The capability information field from the device.
+ *
+ * This informs a userland coordinator of a device requesting to
+ * associate with the PAN controlled by the coordinator.
+ *
+ * Note: This is in section 7.3.1 of the IEEE 802.15.4-2006 document.
+ */
+int ieee802154_nl_assoc_indic(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 cap);
- NL802154_CMD_GET_INTERFACE, /* can dump */
- NL802154_CMD_SET_INTERFACE,
- NL802154_CMD_NEW_INTERFACE,
- NL802154_CMD_DEL_INTERFACE,
+/**
+ * ieee802154_nl_assoc_confirm - Notify userland of association.
+ * @dev: The device which has completed association.
+ * @short_addr: The short address assigned to the device.
+ * @status: The status of the association.
+ *
+ * Inform userland of the result of an association request. If the
+ * association request included asking the coordinator to allocate
+ * a short address then it is returned in @short_addr.
+ *
+ * Note: This is in section 7.3.2 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_assoc_confirm(struct net_device *dev,
+ __le16 short_addr, u8 status);
- NL802154_CMD_SET_CHANNEL,
+/**
+ * ieee802154_nl_disassoc_indic - Notify userland of disassociation.
+ * @dev: The device on which disassociation was indicated.
+ * @addr: The device which is disassociating.
+ * @reason: The reason for the disassociation.
+ *
+ * Inform userland that a device has disassociated from the network.
+ *
+ * Note: This is in section 7.3.3 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_disassoc_indic(struct net_device *dev,
+ struct ieee802154_addr *addr, u8 reason);
- NL802154_CMD_SET_PAN_ID,
- NL802154_CMD_SET_SHORT_ADDR,
+/**
+ * ieee802154_nl_disassoc_confirm - Notify userland of disassociation
+ * completion.
+ * @dev: The device on which disassociation was ordered.
+ * @status: The result of the disassociation.
+ *
+ * Inform userland of the result of requesting that a device
+ * disassociate, or the result of requesting that we disassociate from
+ * a PAN managed by another coordinator.
+ *
+ * Note: This is in section 7.1.4.3 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_disassoc_confirm(struct net_device *dev,
+ u8 status);
- NL802154_CMD_SET_TX_POWER,
- NL802154_CMD_SET_CCA_MODE,
- NL802154_CMD_SET_CCA_ED_LEVEL,
+/**
+ * ieee802154_nl_scan_confirm - Notify userland of completion of scan.
+ * @dev: The device which was instructed to scan.
+ * @status: The status of the scan operation.
+ * @scan_type: What type of scan was performed.
+ * @unscanned: Any channels that the device was unable to scan.
+ * @edl: The energy levels (if a passive scan).
+ *
+ *
+ * Note: This is in section 7.1.11 of the IEEE 802.15.4 document.
+ * Note: This API does not permit the return of an active scan result.
+ */
+int ieee802154_nl_scan_confirm(struct net_device *dev,
+ u8 status, u8 scan_type, u32 unscanned, u8 page,
+ u8 *edl/*, struct list_head *pan_desc_list */);
- NL802154_CMD_SET_MAX_FRAME_RETRIES,
+/**
+ * ieee802154_nl_beacon_indic - Notify userland of a received beacon.
+ * @dev: The device on which a beacon was received.
+ * @panid: The PAN of the coordinator.
+ * @coord_addr: The short address of the coordinator on that PAN.
+ *
+ * Note: This is in section 7.1.5 of the IEEE 802.15.4 document.
+ * Note: This API does not provide extended information such as what
+ * channel the PAN is on or what the LQI of the beacon frame was on
+ * receipt.
+ * Note: This API cannot indicate a beacon frame for a coordinator
+ * operating in long addressing mode.
+ */
+int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid,
+ __le16 coord_addr);
- NL802154_CMD_SET_BACKOFF_EXPONENT,
- NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
+/**
+ * ieee802154_nl_start_confirm - Notify userland of completion of start.
+ * @dev: The device which was instructed to scan.
+ * @status: The status of the scan operation.
+ *
+ * Note: This is in section 7.1.14 of the IEEE 802.15.4 document.
+ */
+int ieee802154_nl_start_confirm(struct net_device *dev, u8 status);
- NL802154_CMD_SET_LBT_MODE,
-
- /* add new commands above here */
-
- /* used to define NL802154_CMD_MAX below */
- __NL802154_CMD_AFTER_LAST,
- NL802154_CMD_MAX = __NL802154_CMD_AFTER_LAST - 1
-};
-
-enum nl802154_attrs {
-/* don't change the order or add anything between, this is ABI! */
-/* currently we don't shipping this file via uapi, ignore the above one */
- NL802154_ATTR_UNSPEC,
-
- NL802154_ATTR_WPAN_PHY,
- NL802154_ATTR_WPAN_PHY_NAME,
-
- NL802154_ATTR_IFINDEX,
- NL802154_ATTR_IFNAME,
- NL802154_ATTR_IFTYPE,
-
- NL802154_ATTR_WPAN_DEV,
-
- NL802154_ATTR_PAGE,
- NL802154_ATTR_CHANNEL,
-
- NL802154_ATTR_PAN_ID,
- NL802154_ATTR_SHORT_ADDR,
-
- NL802154_ATTR_TX_POWER,
-
- NL802154_ATTR_CCA_MODE,
- NL802154_ATTR_CCA_MODE3_AND,
- NL802154_ATTR_CCA_ED_LEVEL,
-
- NL802154_ATTR_MAX_FRAME_RETRIES,
-
- NL802154_ATTR_MAX_BE,
- NL802154_ATTR_MIN_BE,
- NL802154_ATTR_MAX_CSMA_BACKOFFS,
-
- NL802154_ATTR_LBT_MODE,
-
- NL802154_ATTR_GENERATION,
-
- NL802154_ATTR_CHANNELS_SUPPORTED,
- NL802154_ATTR_SUPPORTED_CHANNEL,
-
- NL802154_ATTR_EXTENDED_ADDR,
-
- /* add attributes here, update the policy in nl802154.c */
-
- __NL802154_ATTR_AFTER_LAST,
- NL802154_ATTR_MAX = __NL802154_ATTR_AFTER_LAST - 1
-};
-
-enum nl802154_iftype {
- /* for backwards compatibility TODO */
- NL802154_IFTYPE_UNSPEC = -1,
-
- NL802154_IFTYPE_NODE,
- NL802154_IFTYPE_MONITOR,
- NL802154_IFTYPE_COORD,
-
- /* keep last */
- NUM_NL802154_IFTYPES,
- NL802154_IFTYPE_MAX = NUM_NL802154_IFTYPES - 1
-};
-
-#endif /* __NL802154_H */
+#endif
diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index b776d72..dad7ab2 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -136,17 +136,6 @@
* otherwise initiating radiation is not allowed. This will enable the
* relaxations enabled under the CFG80211_REG_RELAX_NO_IR configuration
* option
- * @REGULATORY_IGNORE_STALE_KICKOFF: the regulatory core will _not_ make sure
- * all interfaces on this wiphy reside on allowed channels. If this flag
- * is not set, upon a regdomain change, the interfaces are given a grace
- * period (currently 60 seconds) to disconnect or move to an allowed
- * channel. Interfaces on forbidden channels are forcibly disconnected.
- * Currently these types of interfaces are supported for enforcement:
- * NL80211_IFTYPE_ADHOC, NL80211_IFTYPE_STATION, NL80211_IFTYPE_AP,
- * NL80211_IFTYPE_AP_VLAN, NL80211_IFTYPE_MONITOR,
- * NL80211_IFTYPE_P2P_CLIENT, NL80211_IFTYPE_P2P_GO,
- * NL80211_IFTYPE_P2P_DEVICE. The flag will be set by default if a device
- * includes any modes unsupported for enforcement checking.
*/
enum ieee80211_regulatory_flags {
REGULATORY_CUSTOM_REG = BIT(0),
@@ -155,7 +144,6 @@
REGULATORY_COUNTRY_IE_FOLLOW_POWER = BIT(3),
REGULATORY_COUNTRY_IE_IGNORE = BIT(4),
REGULATORY_ENABLE_RELAX_NO_IR = BIT(5),
- REGULATORY_IGNORE_STALE_KICKOFF = BIT(6),
};
struct ieee80211_freq_range {
diff --git a/include/net/wpan-phy.h b/include/net/wpan-phy.h
new file mode 100644
index 0000000..10ab0fc
--- /dev/null
+++ b/include/net/wpan-phy.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ */
+
+#ifndef WPAN_PHY_H
+#define WPAN_PHY_H
+
+#include <linux/netdevice.h>
+#include <linux/mutex.h>
+#include <linux/bug.h>
+
+/* According to the IEEE 802.15.4 stadard the upper most significant bits of
+ * the 32-bit channel bitmaps shall be used as an integer value to specify 32
+ * possible channel pages. The lower 27 bits of the channel bit map shall be
+ * used as a bit mask to specify channel numbers within a channel page.
+ */
+#define WPAN_NUM_CHANNELS 27
+#define WPAN_NUM_PAGES 32
+
+struct wpan_phy {
+ struct mutex pib_lock;
+
+ /*
+ * This is a PIB according to 802.15.4-2011.
+ * We do not provide timing-related variables, as they
+ * aren't used outside of driver
+ */
+ u8 current_channel;
+ u8 current_page;
+ u32 channels_supported[32];
+ s8 transmit_power;
+ u8 cca_mode;
+ u8 min_be;
+ u8 max_be;
+ u8 csma_retries;
+ s8 frame_retries;
+
+ bool lbt;
+ s32 cca_ed_level;
+
+ struct device dev;
+ int idx;
+
+ struct net_device *(*add_iface)(struct wpan_phy *phy,
+ const char *name, int type);
+ void (*del_iface)(struct wpan_phy *phy, struct net_device *dev);
+
+ int (*set_txpower)(struct wpan_phy *phy, int db);
+ int (*set_lbt)(struct wpan_phy *phy, bool on);
+ int (*set_cca_mode)(struct wpan_phy *phy, u8 cca_mode);
+ int (*set_cca_ed_level)(struct wpan_phy *phy, int level);
+ int (*set_csma_params)(struct wpan_phy *phy, u8 min_be, u8 max_be,
+ u8 retries);
+ int (*set_frame_retries)(struct wpan_phy *phy, s8 retries);
+
+ char priv[0] __attribute__((__aligned__(NETDEV_ALIGN)));
+};
+
+#define to_phy(_dev) container_of(_dev, struct wpan_phy, dev)
+
+struct wpan_phy *wpan_phy_alloc(size_t priv_size);
+static inline void wpan_phy_set_dev(struct wpan_phy *phy, struct device *dev)
+{
+ phy->dev.parent = dev;
+}
+int wpan_phy_register(struct wpan_phy *phy);
+void wpan_phy_unregister(struct wpan_phy *phy);
+void wpan_phy_free(struct wpan_phy *phy);
+/* Same semantics as for class_for_each_device */
+int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), void *data);
+
+static inline void *wpan_phy_priv(struct wpan_phy *phy)
+{
+ BUG_ON(!phy);
+ return &phy->priv;
+}
+
+struct wpan_phy *wpan_phy_find(const char *str);
+
+static inline void wpan_phy_put(struct wpan_phy *phy)
+{
+ put_device(&phy->dev);
+}
+
+static inline const char *wpan_phy_name(struct wpan_phy *phy)
+{
+ return dev_name(&phy->dev);
+}
+#endif
diff --git a/include/uapi/linux/media-bus-format.h b/include/uapi/linux/media-bus-format.h
deleted file mode 100644
index 23b4090..0000000
--- a/include/uapi/linux/media-bus-format.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Media Bus API header
- *
- * Copyright (C) 2009, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
- *
- * 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 __LINUX_MEDIA_BUS_FORMAT_H
-#define __LINUX_MEDIA_BUS_FORMAT_H
-
-/*
- * These bus formats uniquely identify data formats on the data bus. Format 0
- * is reserved, MEDIA_BUS_FMT_FIXED shall be used by host-client pairs, where
- * the data format is fixed. Additionally, "2X8" means that one pixel is
- * transferred in two 8-bit samples, "BE" or "LE" specify in which order those
- * samples are transferred over the bus: "LE" means that the least significant
- * bits are transferred first, "BE" means that the most significant bits are
- * transferred first, and "PADHI" and "PADLO" define which bits - low or high,
- * in the incomplete high byte, are filled with padding bits.
- *
- * The bus formats are grouped by type, bus_width, bits per component, samples
- * per pixel and order of subsamples. Numerical values are sorted using generic
- * numerical sort order (8 thus comes before 10).
- *
- * As their value can't change when a new bus format is inserted in the
- * enumeration, the bus formats are explicitly given a numerical value. The next
- * free values for each category are listed below, update them when inserting
- * new pixel codes.
- */
-
-#define MEDIA_BUS_FMT_FIXED 0x0001
-
-/* RGB - next is 0x100e */
-#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_BE 0x1001
-#define MEDIA_BUS_FMT_RGB444_2X8_PADHI_LE 0x1002
-#define MEDIA_BUS_FMT_RGB555_2X8_PADHI_BE 0x1003
-#define MEDIA_BUS_FMT_RGB555_2X8_PADHI_LE 0x1004
-#define MEDIA_BUS_FMT_BGR565_2X8_BE 0x1005
-#define MEDIA_BUS_FMT_BGR565_2X8_LE 0x1006
-#define MEDIA_BUS_FMT_RGB565_2X8_BE 0x1007
-#define MEDIA_BUS_FMT_RGB565_2X8_LE 0x1008
-#define MEDIA_BUS_FMT_RGB666_1X18 0x1009
-#define MEDIA_BUS_FMT_RGB888_1X24 0x100a
-#define MEDIA_BUS_FMT_RGB888_2X12_BE 0x100b
-#define MEDIA_BUS_FMT_RGB888_2X12_LE 0x100c
-#define MEDIA_BUS_FMT_ARGB8888_1X32 0x100d
-
-/* YUV (including grey) - next is 0x2024 */
-#define MEDIA_BUS_FMT_Y8_1X8 0x2001
-#define MEDIA_BUS_FMT_UV8_1X8 0x2015
-#define MEDIA_BUS_FMT_UYVY8_1_5X8 0x2002
-#define MEDIA_BUS_FMT_VYUY8_1_5X8 0x2003
-#define MEDIA_BUS_FMT_YUYV8_1_5X8 0x2004
-#define MEDIA_BUS_FMT_YVYU8_1_5X8 0x2005
-#define MEDIA_BUS_FMT_UYVY8_2X8 0x2006
-#define MEDIA_BUS_FMT_VYUY8_2X8 0x2007
-#define MEDIA_BUS_FMT_YUYV8_2X8 0x2008
-#define MEDIA_BUS_FMT_YVYU8_2X8 0x2009
-#define MEDIA_BUS_FMT_Y10_1X10 0x200a
-#define MEDIA_BUS_FMT_UYVY10_2X10 0x2018
-#define MEDIA_BUS_FMT_VYUY10_2X10 0x2019
-#define MEDIA_BUS_FMT_YUYV10_2X10 0x200b
-#define MEDIA_BUS_FMT_YVYU10_2X10 0x200c
-#define MEDIA_BUS_FMT_Y12_1X12 0x2013
-#define MEDIA_BUS_FMT_UYVY8_1X16 0x200f
-#define MEDIA_BUS_FMT_VYUY8_1X16 0x2010
-#define MEDIA_BUS_FMT_YUYV8_1X16 0x2011
-#define MEDIA_BUS_FMT_YVYU8_1X16 0x2012
-#define MEDIA_BUS_FMT_YDYUYDYV8_1X16 0x2014
-#define MEDIA_BUS_FMT_UYVY10_1X20 0x201a
-#define MEDIA_BUS_FMT_VYUY10_1X20 0x201b
-#define MEDIA_BUS_FMT_YUYV10_1X20 0x200d
-#define MEDIA_BUS_FMT_YVYU10_1X20 0x200e
-#define MEDIA_BUS_FMT_YUV10_1X30 0x2016
-#define MEDIA_BUS_FMT_AYUV8_1X32 0x2017
-#define MEDIA_BUS_FMT_UYVY12_2X12 0x201c
-#define MEDIA_BUS_FMT_VYUY12_2X12 0x201d
-#define MEDIA_BUS_FMT_YUYV12_2X12 0x201e
-#define MEDIA_BUS_FMT_YVYU12_2X12 0x201f
-#define MEDIA_BUS_FMT_UYVY12_1X24 0x2020
-#define MEDIA_BUS_FMT_VYUY12_1X24 0x2021
-#define MEDIA_BUS_FMT_YUYV12_1X24 0x2022
-#define MEDIA_BUS_FMT_YVYU12_1X24 0x2023
-
-/* Bayer - next is 0x3019 */
-#define MEDIA_BUS_FMT_SBGGR8_1X8 0x3001
-#define MEDIA_BUS_FMT_SGBRG8_1X8 0x3013
-#define MEDIA_BUS_FMT_SGRBG8_1X8 0x3002
-#define MEDIA_BUS_FMT_SRGGB8_1X8 0x3014
-#define MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8 0x3015
-#define MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8 0x3016
-#define MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8 0x3017
-#define MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8 0x3018
-#define MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8 0x300b
-#define MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8 0x300c
-#define MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8 0x3009
-#define MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8 0x300d
-#define MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE 0x3003
-#define MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE 0x3004
-#define MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE 0x3005
-#define MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE 0x3006
-#define MEDIA_BUS_FMT_SBGGR10_1X10 0x3007
-#define MEDIA_BUS_FMT_SGBRG10_1X10 0x300e
-#define MEDIA_BUS_FMT_SGRBG10_1X10 0x300a
-#define MEDIA_BUS_FMT_SRGGB10_1X10 0x300f
-#define MEDIA_BUS_FMT_SBGGR12_1X12 0x3008
-#define MEDIA_BUS_FMT_SGBRG12_1X12 0x3010
-#define MEDIA_BUS_FMT_SGRBG12_1X12 0x3011
-#define MEDIA_BUS_FMT_SRGGB12_1X12 0x3012
-
-/* JPEG compressed formats - next is 0x4002 */
-#define MEDIA_BUS_FMT_JPEG_1X8 0x4001
-
-/* Vendor specific formats - next is 0x5002 */
-
-/* S5C73M3 sensor specific interleaved UYVY and JPEG */
-#define MEDIA_BUS_FMT_S5C_UYVY_JPEG_1X8 0x5001
-
-/* HSV - next is 0x6002 */
-#define MEDIA_BUS_FMT_AHSV8888_1X32 0x6001
-
-#endif /* __LINUX_MEDIA_BUS_FORMAT_H */
diff --git a/include/uapi/linux/nfc.h b/include/uapi/linux/nfc.h
index 8119255..9b19b44 100644
--- a/include/uapi/linux/nfc.h
+++ b/include/uapi/linux/nfc.h
@@ -116,7 +116,6 @@
NFC_EVENT_SE_TRANSACTION,
NFC_CMD_GET_SE,
NFC_CMD_SE_IO,
- NFC_CMD_ACTIVATE_TARGET,
/* private: internal use only */
__NFC_CMD_AFTER_LAST
};
@@ -197,19 +196,15 @@
};
#define NFC_SDP_ATTR_MAX (__NFC_SDP_ATTR_AFTER_LAST - 1)
-#define NFC_DEVICE_NAME_MAXSIZE 8
-#define NFC_NFCID1_MAXSIZE 10
-#define NFC_NFCID2_MAXSIZE 8
-#define NFC_NFCID3_MAXSIZE 10
-#define NFC_SENSB_RES_MAXSIZE 12
-#define NFC_SENSF_RES_MAXSIZE 18
-#define NFC_ATR_REQ_MAXSIZE 64
-#define NFC_ATR_RES_MAXSIZE 64
-#define NFC_ATR_REQ_GB_MAXSIZE 48
-#define NFC_ATR_RES_GB_MAXSIZE 47
-#define NFC_GB_MAXSIZE 48
-#define NFC_FIRMWARE_NAME_MAXSIZE 32
-#define NFC_ISO15693_UID_MAXSIZE 8
+#define NFC_DEVICE_NAME_MAXSIZE 8
+#define NFC_NFCID1_MAXSIZE 10
+#define NFC_NFCID2_MAXSIZE 8
+#define NFC_NFCID3_MAXSIZE 10
+#define NFC_SENSB_RES_MAXSIZE 12
+#define NFC_SENSF_RES_MAXSIZE 18
+#define NFC_GB_MAXSIZE 48
+#define NFC_FIRMWARE_NAME_MAXSIZE 32
+#define NFC_ISO15693_UID_MAXSIZE 8
/* NFC protocols */
#define NFC_PROTO_JEWEL 1
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index b37bd5a..4b28dc0 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -227,11 +227,7 @@
* the interface identified by %NL80211_ATTR_IFINDEX.
* @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC
* or, if no MAC address given, all stations, on the interface identified
- * by %NL80211_ATTR_IFINDEX. %NL80211_ATTR_MGMT_SUBTYPE and
- * %NL80211_ATTR_REASON_CODE can optionally be used to specify which type
- * of disconnection indication should be sent to the station
- * (Deauthentication or Disassociation frame and reason code for that
- * frame).
+ * by %NL80211_ATTR_IFINDEX.
*
* @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to
* destination %NL80211_ATTR_MAC on the interface identified by
@@ -643,18 +639,7 @@
* @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels
* independently of the userspace SME, send this event indicating
* %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the
- * attributes determining channel width. This indication may also be
- * sent when a remotely-initiated switch (e.g., when a STA receives a CSA
- * from the remote AP) is completed;
- *
- * @NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: Notify that a channel switch
- * has been started on an interface, regardless of the initiator
- * (ie. whether it was requested from a remote device or
- * initiated on our own). It indicates that
- * %NL80211_ATTR_IFINDEX will be on %NL80211_ATTR_WIPHY_FREQ
- * after %NL80211_ATTR_CH_SWITCH_COUNT TBTT's. The userspace may
- * decide to react to this indication by requesting other
- * interfaces to change channel as well.
+ * attributes determining channel width.
*
* @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by
* its %NL80211_ATTR_WDEV identifier. It must have been created with
@@ -753,27 +738,6 @@
* before removing a station entry entirely, or before disassociating
* or similar, cleanup will happen in the driver/device in this case.
*
- * @NL80211_CMD_GET_MPP: Get mesh path attributes for mesh proxy path to
- * destination %NL80211_ATTR_MAC on the interface identified by
- * %NL80211_ATTR_IFINDEX.
- *
- * @NL80211_CMD_JOIN_OCB: Join the OCB network. The center frequency and
- * bandwidth of a channel must be given.
- * @NL80211_CMD_LEAVE_OCB: Leave the OCB network -- no special arguments, the
- * network is determined by the network interface.
- *
- * @NL80211_CMD_TDLS_CHANNEL_SWITCH: Start channel-switching with a TDLS peer,
- * identified by the %NL80211_ATTR_MAC parameter. A target channel is
- * provided via %NL80211_ATTR_WIPHY_FREQ and other attributes determining
- * channel width/type. The target operating class is given via
- * %NL80211_ATTR_OPER_CLASS.
- * The driver is responsible for continually initiating channel-switching
- * operations and returning to the base channel for communication with the
- * AP.
- * @NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH: Stop channel-switching with a TDLS
- * peer given by %NL80211_ATTR_MAC. Both peers must be on the base channel
- * when this command completes.
- *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -948,16 +912,6 @@
NL80211_CMD_ADD_TX_TS,
NL80211_CMD_DEL_TX_TS,
- NL80211_CMD_GET_MPP,
-
- NL80211_CMD_JOIN_OCB,
- NL80211_CMD_LEAVE_OCB,
-
- NL80211_CMD_CH_SWITCH_STARTED_NOTIFY,
-
- NL80211_CMD_TDLS_CHANNEL_SWITCH,
- NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
-
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -1652,9 +1606,9 @@
* @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32.
* As specified in the &enum nl80211_tdls_peer_capability.
*
- * @NL80211_ATTR_SOCKET_OWNER: Flag attribute, if set during interface
+ * @NL80211_ATTR_IFACE_SOCKET_OWNER: flag attribute, if set during interface
* creation then the new interface will be owned by the netlink socket
- * that created it and will be destroyed when the socket is closed.
+ * that created it and will be destroyed when the socket is closed
*
* @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
* the TDLS link initiator.
@@ -1684,11 +1638,6 @@
* @NL80211_ATTR_SMPS_MODE: SMPS mode to use (ap mode). see
* &enum nl80211_smps_mode.
*
- * @NL80211_ATTR_OPER_CLASS: operating class
- *
- * @NL80211_ATTR_MAC_MASK: MAC address mask
- *
- * @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
*/
@@ -2024,7 +1973,7 @@
NL80211_ATTR_TDLS_PEER_CAPABILITY,
- NL80211_ATTR_SOCKET_OWNER,
+ NL80211_ATTR_IFACE_SOCKET_OWNER,
NL80211_ATTR_CSA_C_OFFSETS_TX,
NL80211_ATTR_MAX_CSA_COUNTERS,
@@ -2041,21 +1990,15 @@
NL80211_ATTR_SMPS_MODE,
- NL80211_ATTR_OPER_CLASS,
-
- NL80211_ATTR_MAC_MASK,
-
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
- NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST,
NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1
};
/* source-level API compatibility */
#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION
#define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG
-#define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER
/*
* Allow user space programs to use #ifdef on new attributes by defining them
@@ -2121,8 +2064,6 @@
* and therefore can't be created in the normal ways, use the
* %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE
* commands to create and destroy one
- * @NL80211_IF_TYPE_OCB: Outside Context of a BSS
- * This mode corresponds to the MIB variable dot11OCBActivated=true
* @NL80211_IFTYPE_MAX: highest interface type number currently defined
* @NUM_NL80211_IFTYPES: number of defined interface types
*
@@ -2142,7 +2083,6 @@
NL80211_IFTYPE_P2P_CLIENT,
NL80211_IFTYPE_P2P_GO,
NL80211_IFTYPE_P2P_DEVICE,
- NL80211_IFTYPE_OCB,
/* keep last */
NUM_NL80211_IFTYPES,
@@ -2691,11 +2631,6 @@
* @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated
* base on contiguous rules and wider channels will be allowed to cross
* multiple contiguous/overlapping frequency ranges.
- * @NL80211_RRF_GO_CONCURRENT: See &NL80211_FREQUENCY_ATTR_GO_CONCURRENT
- * @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation
- * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation
- * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed
- * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed
*/
enum nl80211_reg_rule_flags {
NL80211_RRF_NO_OFDM = 1<<0,
@@ -2708,18 +2643,11 @@
NL80211_RRF_NO_IR = 1<<7,
__NL80211_RRF_NO_IBSS = 1<<8,
NL80211_RRF_AUTO_BW = 1<<11,
- NL80211_RRF_GO_CONCURRENT = 1<<12,
- NL80211_RRF_NO_HT40MINUS = 1<<13,
- NL80211_RRF_NO_HT40PLUS = 1<<14,
- NL80211_RRF_NO_80MHZ = 1<<15,
- NL80211_RRF_NO_160MHZ = 1<<16,
};
#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR
#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR
#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR
-#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS |\
- NL80211_RRF_NO_HT40PLUS)
/* For backport compatibility with older userspace */
#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS)
@@ -3451,8 +3379,6 @@
* interval in which %NL80211_ATTR_CQM_TXE_PKTS and
* %NL80211_ATTR_CQM_TXE_RATE must be satisfied before generating an
* %NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting.
- * @NL80211_ATTR_CQM_BEACON_LOSS_EVENT: flag attribute that's set in a beacon
- * loss event
* @__NL80211_ATTR_CQM_AFTER_LAST: internal
* @NL80211_ATTR_CQM_MAX: highest key attribute
*/
@@ -3465,7 +3391,6 @@
NL80211_ATTR_CQM_TXE_RATE,
NL80211_ATTR_CQM_TXE_PKTS,
NL80211_ATTR_CQM_TXE_INTVL,
- NL80211_ATTR_CQM_BEACON_LOSS_EVENT,
/* keep last */
__NL80211_ATTR_CQM_AFTER_LAST,
@@ -3478,7 +3403,9 @@
* configured threshold
* @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the
* configured threshold
- * @NL80211_CQM_RSSI_BEACON_LOSS_EVENT: (reserved, never sent)
+ * @NL80211_CQM_RSSI_BEACON_LOSS_EVENT: The device experienced beacon loss.
+ * (Note that deauth/disassoc will still follow if the AP is not
+ * available. This event might get used as roaming event, etc.)
*/
enum nl80211_cqm_rssi_threshold_event {
NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
@@ -3618,25 +3545,6 @@
* @NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS: For wakeup reporting only,
* the TCP connection ran out of tokens to use for data to send to the
* service
- * @NL80211_WOWLAN_TRIG_NET_DETECT: wake up when a configured network
- * is detected. This is a nested attribute that contains the
- * same attributes used with @NL80211_CMD_START_SCHED_SCAN. It
- * specifies how the scan is performed (e.g. the interval and the
- * channels to scan) as well as the scan results that will
- * trigger a wake (i.e. the matchsets).
- * @NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS: nested attribute
- * containing an array with information about what triggered the
- * wake up. If no elements are present in the array, it means
- * that the information is not available. If more than one
- * element is present, it means that more than one match
- * occurred.
- * Each element in the array is a nested attribute that contains
- * one optional %NL80211_ATTR_SSID attribute and one optional
- * %NL80211_ATTR_SCAN_FREQUENCIES attribute. At least one of
- * these attributes must be present. If
- * %NL80211_ATTR_SCAN_FREQUENCIES contains more than one
- * frequency, it means that the match occurred in more than one
- * channel.
* @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers
* @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number
*
@@ -3662,8 +3570,6 @@
NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH,
NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST,
NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS,
- NL80211_WOWLAN_TRIG_NET_DETECT,
- NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS,
/* keep last */
NUM_NL80211_WOWLAN_TRIG,
@@ -4136,27 +4042,6 @@
* multiplexing powersave, ie. can turn off all but one chain
* and then wake the rest up as required after, for example,
* rts/cts handshake.
- * @NL80211_FEATURE_SUPPORTS_WMM_ADMISSION: the device supports setting up WMM
- * TSPEC sessions (TID aka TSID 0-7) with the %NL80211_CMD_ADD_TX_TS
- * command. Standard IEEE 802.11 TSPEC setup is not yet supported, it
- * needs to be able to handle Block-Ack agreements and other things.
- * @NL80211_FEATURE_MAC_ON_CREATE: Device supports configuring
- * the vif's MAC address upon creation.
- * See 'macaddr' field in the vif_params (cfg80211.h).
- * @NL80211_FEATURE_TDLS_CHANNEL_SWITCH: Driver supports channel switching when
- * operating as a TDLS peer.
- * @NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR: This device/driver supports using a
- * random MAC address during scan (if the device is unassociated); the
- * %NL80211_SCAN_FLAG_RANDOM_ADDR flag may be set for scans and the MAC
- * address mask/value will be used.
- * @NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR: This device/driver supports
- * using a random MAC address for every scan iteration during scheduled
- * scan (while not associated), the %NL80211_SCAN_FLAG_RANDOM_ADDR may
- * be set for scheduled scan and the MAC address mask/value will be used.
- * @NL80211_FEATURE_ND_RANDOM_MAC_ADDR: This device/driver supports using a
- * random MAC address for every scan iteration during "net detect", i.e.
- * scan in unassociated WoWLAN, the %NL80211_SCAN_FLAG_RANDOM_ADDR may
- * be set for scheduled scan and the MAC address mask/value will be used.
*/
enum nl80211_feature_flags {
NL80211_FEATURE_SK_TX_STATUS = 1 << 0,
@@ -4185,12 +4070,6 @@
NL80211_FEATURE_ACKTO_ESTIMATION = 1 << 23,
NL80211_FEATURE_STATIC_SMPS = 1 << 24,
NL80211_FEATURE_DYNAMIC_SMPS = 1 << 25,
- NL80211_FEATURE_SUPPORTS_WMM_ADMISSION = 1 << 26,
- NL80211_FEATURE_MAC_ON_CREATE = 1 << 27,
- NL80211_FEATURE_TDLS_CHANNEL_SWITCH = 1 << 28,
- NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR = 1 << 29,
- NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR = 1 << 30,
- NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1 << 31,
};
/**
@@ -4239,21 +4118,11 @@
* dangerous because will destroy stations performance as a lot of frames
* will be lost while scanning off-channel, therefore it must be used only
* when really needed
- * @NL80211_SCAN_FLAG_RANDOM_ADDR: use a random MAC address for this scan (or
- * for scheduled scan: a different one for every scan iteration). When the
- * flag is set, depending on device capabilities the @NL80211_ATTR_MAC and
- * @NL80211_ATTR_MAC_MASK attributes may also be given in which case only
- * the masked bits will be preserved from the MAC address and the remainder
- * randomised. If the attributes are not given full randomisation (46 bits,
- * locally administered 1, multicast 0) is assumed.
- * This flag must not be requested when the feature isn't supported, check
- * the nl80211 feature flags for the device.
*/
enum nl80211_scan_flags {
NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0,
NL80211_SCAN_FLAG_FLUSH = 1<<1,
NL80211_SCAN_FLAG_AP = 1<<2,
- NL80211_SCAN_FLAG_RANDOM_ADDR = 1<<3,
};
/**
diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
deleted file mode 100644
index 4a1d0cc..0000000
--- a/include/uapi/linux/pci_regs.h
+++ /dev/null
@@ -1,903 +0,0 @@
-/*
- * pci_regs.h
- *
- * PCI standard defines
- * Copyright 1994, Drew Eckhardt
- * Copyright 1997--1999 Martin Mares <mj@ucw.cz>
- *
- * For more information, please consult the following manuals (look at
- * http://www.pcisig.com/ for how to get them):
- *
- * PCI BIOS Specification
- * PCI Local Bus Specification
- * PCI to PCI Bridge Specification
- * PCI System Design Guide
- *
- * For HyperTransport information, please consult the following manuals
- * from http://www.hypertransport.org
- *
- * The HyperTransport I/O Link Specification
- */
-
-#ifndef LINUX_PCI_REGS_H
-#define LINUX_PCI_REGS_H
-
-/*
- * Under PCI, each device has 256 bytes of configuration address space,
- * of which the first 64 bytes are standardized as follows:
- */
-#define PCI_STD_HEADER_SIZEOF 64
-#define PCI_VENDOR_ID 0x00 /* 16 bits */
-#define PCI_DEVICE_ID 0x02 /* 16 bits */
-#define PCI_COMMAND 0x04 /* 16 bits */
-#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
-#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
-#define PCI_COMMAND_MASTER 0x4 /* Enable bus mastering */
-#define PCI_COMMAND_SPECIAL 0x8 /* Enable response to special cycles */
-#define PCI_COMMAND_INVALIDATE 0x10 /* Use memory write and invalidate */
-#define PCI_COMMAND_VGA_PALETTE 0x20 /* Enable palette snooping */
-#define PCI_COMMAND_PARITY 0x40 /* Enable parity checking */
-#define PCI_COMMAND_WAIT 0x80 /* Enable address/data stepping */
-#define PCI_COMMAND_SERR 0x100 /* Enable SERR */
-#define PCI_COMMAND_FAST_BACK 0x200 /* Enable back-to-back writes */
-#define PCI_COMMAND_INTX_DISABLE 0x400 /* INTx Emulation Disable */
-
-#define PCI_STATUS 0x06 /* 16 bits */
-#define PCI_STATUS_INTERRUPT 0x08 /* Interrupt status */
-#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
-#define PCI_STATUS_66MHZ 0x20 /* Support 66 MHz PCI 2.1 bus */
-#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
-#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
-#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
-#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
-#define PCI_STATUS_DEVSEL_FAST 0x000
-#define PCI_STATUS_DEVSEL_MEDIUM 0x200
-#define PCI_STATUS_DEVSEL_SLOW 0x400
-#define PCI_STATUS_SIG_TARGET_ABORT 0x800 /* Set on target abort */
-#define PCI_STATUS_REC_TARGET_ABORT 0x1000 /* Master ack of " */
-#define PCI_STATUS_REC_MASTER_ABORT 0x2000 /* Set on master abort */
-#define PCI_STATUS_SIG_SYSTEM_ERROR 0x4000 /* Set when we drive SERR */
-#define PCI_STATUS_DETECTED_PARITY 0x8000 /* Set on parity error */
-
-#define PCI_CLASS_REVISION 0x08 /* High 24 bits are class, low 8 revision */
-#define PCI_REVISION_ID 0x08 /* Revision ID */
-#define PCI_CLASS_PROG 0x09 /* Reg. Level Programming Interface */
-#define PCI_CLASS_DEVICE 0x0a /* Device class */
-
-#define PCI_CACHE_LINE_SIZE 0x0c /* 8 bits */
-#define PCI_LATENCY_TIMER 0x0d /* 8 bits */
-#define PCI_HEADER_TYPE 0x0e /* 8 bits */
-#define PCI_HEADER_TYPE_NORMAL 0
-#define PCI_HEADER_TYPE_BRIDGE 1
-#define PCI_HEADER_TYPE_CARDBUS 2
-
-#define PCI_BIST 0x0f /* 8 bits */
-#define PCI_BIST_CODE_MASK 0x0f /* Return result */
-#define PCI_BIST_START 0x40 /* 1 to start BIST, 2 secs or less */
-#define PCI_BIST_CAPABLE 0x80 /* 1 if BIST capable */
-
-/*
- * Base addresses specify locations in memory or I/O space.
- * Decoded size can be determined by writing a value of
- * 0xffffffff to the register, and reading it back. Only
- * 1 bits are decoded.
- */
-#define PCI_BASE_ADDRESS_0 0x10 /* 32 bits */
-#define PCI_BASE_ADDRESS_1 0x14 /* 32 bits [htype 0,1 only] */
-#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */
-#define PCI_BASE_ADDRESS_3 0x1c /* 32 bits */
-#define PCI_BASE_ADDRESS_4 0x20 /* 32 bits */
-#define PCI_BASE_ADDRESS_5 0x24 /* 32 bits */
-#define PCI_BASE_ADDRESS_SPACE 0x01 /* 0 = memory, 1 = I/O */
-#define PCI_BASE_ADDRESS_SPACE_IO 0x01
-#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
-#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
-#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
-#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
-#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
-#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
-#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
-#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
-/* bit 1 is reserved if address_space = 1 */
-
-/* Header type 0 (normal devices) */
-#define PCI_CARDBUS_CIS 0x28
-#define PCI_SUBSYSTEM_VENDOR_ID 0x2c
-#define PCI_SUBSYSTEM_ID 0x2e
-#define PCI_ROM_ADDRESS 0x30 /* Bits 31..11 are address, 10..1 reserved */
-#define PCI_ROM_ADDRESS_ENABLE 0x01
-#define PCI_ROM_ADDRESS_MASK (~0x7ffUL)
-
-#define PCI_CAPABILITY_LIST 0x34 /* Offset of first capability list entry */
-
-/* 0x35-0x3b are reserved */
-#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
-#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
-#define PCI_MIN_GNT 0x3e /* 8 bits */
-#define PCI_MAX_LAT 0x3f /* 8 bits */
-
-/* Header type 1 (PCI-to-PCI bridges) */
-#define PCI_PRIMARY_BUS 0x18 /* Primary bus number */
-#define PCI_SECONDARY_BUS 0x19 /* Secondary bus number */
-#define PCI_SUBORDINATE_BUS 0x1a /* Highest bus number behind the bridge */
-#define PCI_SEC_LATENCY_TIMER 0x1b /* Latency timer for secondary interface */
-#define PCI_IO_BASE 0x1c /* I/O range behind the bridge */
-#define PCI_IO_LIMIT 0x1d
-#define PCI_IO_RANGE_TYPE_MASK 0x0fUL /* I/O bridging type */
-#define PCI_IO_RANGE_TYPE_16 0x00
-#define PCI_IO_RANGE_TYPE_32 0x01
-#define PCI_IO_RANGE_MASK (~0x0fUL) /* Standard 4K I/O windows */
-#define PCI_IO_1K_RANGE_MASK (~0x03UL) /* Intel 1K I/O windows */
-#define PCI_SEC_STATUS 0x1e /* Secondary status register, only bit 14 used */
-#define PCI_MEMORY_BASE 0x20 /* Memory range behind */
-#define PCI_MEMORY_LIMIT 0x22
-#define PCI_MEMORY_RANGE_TYPE_MASK 0x0fUL
-#define PCI_MEMORY_RANGE_MASK (~0x0fUL)
-#define PCI_PREF_MEMORY_BASE 0x24 /* Prefetchable memory range behind */
-#define PCI_PREF_MEMORY_LIMIT 0x26
-#define PCI_PREF_RANGE_TYPE_MASK 0x0fUL
-#define PCI_PREF_RANGE_TYPE_32 0x00
-#define PCI_PREF_RANGE_TYPE_64 0x01
-#define PCI_PREF_RANGE_MASK (~0x0fUL)
-#define PCI_PREF_BASE_UPPER32 0x28 /* Upper half of prefetchable memory range */
-#define PCI_PREF_LIMIT_UPPER32 0x2c
-#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
-#define PCI_IO_LIMIT_UPPER16 0x32
-/* 0x34 same as for htype 0 */
-/* 0x35-0x3b is reserved */
-#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_BRIDGE_CONTROL 0x3e
-#define PCI_BRIDGE_CTL_PARITY 0x01 /* Enable parity detection on secondary interface */
-#define PCI_BRIDGE_CTL_SERR 0x02 /* The same for SERR forwarding */
-#define PCI_BRIDGE_CTL_ISA 0x04 /* Enable ISA mode */
-#define PCI_BRIDGE_CTL_VGA 0x08 /* Forward VGA addresses */
-#define PCI_BRIDGE_CTL_MASTER_ABORT 0x20 /* Report master aborts */
-#define PCI_BRIDGE_CTL_BUS_RESET 0x40 /* Secondary bus reset */
-#define PCI_BRIDGE_CTL_FAST_BACK 0x80 /* Fast Back2Back enabled on secondary interface */
-
-/* Header type 2 (CardBus bridges) */
-#define PCI_CB_CAPABILITY_LIST 0x14
-/* 0x15 reserved */
-#define PCI_CB_SEC_STATUS 0x16 /* Secondary status */
-#define PCI_CB_PRIMARY_BUS 0x18 /* PCI bus number */
-#define PCI_CB_CARD_BUS 0x19 /* CardBus bus number */
-#define PCI_CB_SUBORDINATE_BUS 0x1a /* Subordinate bus number */
-#define PCI_CB_LATENCY_TIMER 0x1b /* CardBus latency timer */
-#define PCI_CB_MEMORY_BASE_0 0x1c
-#define PCI_CB_MEMORY_LIMIT_0 0x20
-#define PCI_CB_MEMORY_BASE_1 0x24
-#define PCI_CB_MEMORY_LIMIT_1 0x28
-#define PCI_CB_IO_BASE_0 0x2c
-#define PCI_CB_IO_BASE_0_HI 0x2e
-#define PCI_CB_IO_LIMIT_0 0x30
-#define PCI_CB_IO_LIMIT_0_HI 0x32
-#define PCI_CB_IO_BASE_1 0x34
-#define PCI_CB_IO_BASE_1_HI 0x36
-#define PCI_CB_IO_LIMIT_1 0x38
-#define PCI_CB_IO_LIMIT_1_HI 0x3a
-#define PCI_CB_IO_RANGE_MASK (~0x03UL)
-/* 0x3c-0x3d are same as for htype 0 */
-#define PCI_CB_BRIDGE_CONTROL 0x3e
-#define PCI_CB_BRIDGE_CTL_PARITY 0x01 /* Similar to standard bridge control register */
-#define PCI_CB_BRIDGE_CTL_SERR 0x02
-#define PCI_CB_BRIDGE_CTL_ISA 0x04
-#define PCI_CB_BRIDGE_CTL_VGA 0x08
-#define PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
-#define PCI_CB_BRIDGE_CTL_CB_RESET 0x40 /* CardBus reset */
-#define PCI_CB_BRIDGE_CTL_16BIT_INT 0x80 /* Enable interrupt for 16-bit cards */
-#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 /* Prefetch enable for both memory regions */
-#define PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
-#define PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
-#define PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
-#define PCI_CB_SUBSYSTEM_ID 0x42
-#define PCI_CB_LEGACY_MODE_BASE 0x44 /* 16-bit PC Card legacy mode base address (ExCa) */
-/* 0x48-0x7f reserved */
-
-/* Capability lists */
-
-#define PCI_CAP_LIST_ID 0 /* Capability ID */
-#define PCI_CAP_ID_PM 0x01 /* Power Management */
-#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
-#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
-#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
-#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
-#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
-#define PCI_CAP_ID_PCIX 0x07 /* PCI-X */
-#define PCI_CAP_ID_HT 0x08 /* HyperTransport */
-#define PCI_CAP_ID_VNDR 0x09 /* Vendor-Specific */
-#define PCI_CAP_ID_DBG 0x0A /* Debug port */
-#define PCI_CAP_ID_CCRC 0x0B /* CompactPCI Central Resource Control */
-#define PCI_CAP_ID_SHPC 0x0C /* PCI Standard Hot-Plug Controller */
-#define PCI_CAP_ID_SSVID 0x0D /* Bridge subsystem vendor/device ID */
-#define PCI_CAP_ID_AGP3 0x0E /* AGP Target PCI-PCI bridge */
-#define PCI_CAP_ID_SECDEV 0x0F /* Secure Device */
-#define PCI_CAP_ID_EXP 0x10 /* PCI Express */
-#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
-#define PCI_CAP_ID_SATA 0x12 /* SATA Data/Index Conf. */
-#define PCI_CAP_ID_AF 0x13 /* PCI Advanced Features */
-#define PCI_CAP_ID_MAX PCI_CAP_ID_AF
-#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
-#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
-#define PCI_CAP_SIZEOF 4
-
-/* Power Management Registers */
-
-#define PCI_PM_PMC 2 /* PM Capabilities Register */
-#define PCI_PM_CAP_VER_MASK 0x0007 /* Version */
-#define PCI_PM_CAP_PME_CLOCK 0x0008 /* PME clock required */
-#define PCI_PM_CAP_RESERVED 0x0010 /* Reserved field */
-#define PCI_PM_CAP_DSI 0x0020 /* Device specific initialization */
-#define PCI_PM_CAP_AUX_POWER 0x01C0 /* Auxiliary power support mask */
-#define PCI_PM_CAP_D1 0x0200 /* D1 power state support */
-#define PCI_PM_CAP_D2 0x0400 /* D2 power state support */
-#define PCI_PM_CAP_PME 0x0800 /* PME pin supported */
-#define PCI_PM_CAP_PME_MASK 0xF800 /* PME Mask of all supported states */
-#define PCI_PM_CAP_PME_D0 0x0800 /* PME# from D0 */
-#define PCI_PM_CAP_PME_D1 0x1000 /* PME# from D1 */
-#define PCI_PM_CAP_PME_D2 0x2000 /* PME# from D2 */
-#define PCI_PM_CAP_PME_D3 0x4000 /* PME# from D3 (hot) */
-#define PCI_PM_CAP_PME_D3cold 0x8000 /* PME# from D3 (cold) */
-#define PCI_PM_CAP_PME_SHIFT 11 /* Start of the PME Mask in PMC */
-#define PCI_PM_CTRL 4 /* PM control and status register */
-#define PCI_PM_CTRL_STATE_MASK 0x0003 /* Current power state (D0 to D3) */
-#define PCI_PM_CTRL_NO_SOFT_RESET 0x0008 /* No reset for D3hot->D0 */
-#define PCI_PM_CTRL_PME_ENABLE 0x0100 /* PME pin enable */
-#define PCI_PM_CTRL_DATA_SEL_MASK 0x1e00 /* Data select (??) */
-#define PCI_PM_CTRL_DATA_SCALE_MASK 0x6000 /* Data scale (??) */
-#define PCI_PM_CTRL_PME_STATUS 0x8000 /* PME pin status */
-#define PCI_PM_PPB_EXTENSIONS 6 /* PPB support extensions (??) */
-#define PCI_PM_PPB_B2_B3 0x40 /* Stop clock when in D3hot (??) */
-#define PCI_PM_BPCC_ENABLE 0x80 /* Bus power/clock control enable (??) */
-#define PCI_PM_DATA_REGISTER 7 /* (??) */
-#define PCI_PM_SIZEOF 8
-
-/* AGP registers */
-
-#define PCI_AGP_VERSION 2 /* BCD version number */
-#define PCI_AGP_RFU 3 /* Rest of capability flags */
-#define PCI_AGP_STATUS 4 /* Status register */
-#define PCI_AGP_STATUS_RQ_MASK 0xff000000 /* Maximum number of requests - 1 */
-#define PCI_AGP_STATUS_SBA 0x0200 /* Sideband addressing supported */
-#define PCI_AGP_STATUS_64BIT 0x0020 /* 64-bit addressing supported */
-#define PCI_AGP_STATUS_FW 0x0010 /* FW transfers supported */
-#define PCI_AGP_STATUS_RATE4 0x0004 /* 4x transfer rate supported */
-#define PCI_AGP_STATUS_RATE2 0x0002 /* 2x transfer rate supported */
-#define PCI_AGP_STATUS_RATE1 0x0001 /* 1x transfer rate supported */
-#define PCI_AGP_COMMAND 8 /* Control register */
-#define PCI_AGP_COMMAND_RQ_MASK 0xff000000 /* Master: Maximum number of requests */
-#define PCI_AGP_COMMAND_SBA 0x0200 /* Sideband addressing enabled */
-#define PCI_AGP_COMMAND_AGP 0x0100 /* Allow processing of AGP transactions */
-#define PCI_AGP_COMMAND_64BIT 0x0020 /* Allow processing of 64-bit addresses */
-#define PCI_AGP_COMMAND_FW 0x0010 /* Force FW transfers */
-#define PCI_AGP_COMMAND_RATE4 0x0004 /* Use 4x rate */
-#define PCI_AGP_COMMAND_RATE2 0x0002 /* Use 2x rate */
-#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 1x rate */
-#define PCI_AGP_SIZEOF 12
-
-/* Vital Product Data */
-
-#define PCI_VPD_ADDR 2 /* Address to access (15 bits!) */
-#define PCI_VPD_ADDR_MASK 0x7fff /* Address mask */
-#define PCI_VPD_ADDR_F 0x8000 /* Write 0, 1 indicates completion */
-#define PCI_VPD_DATA 4 /* 32-bits of data returned here */
-#define PCI_CAP_VPD_SIZEOF 8
-
-/* Slot Identification */
-
-#define PCI_SID_ESR 2 /* Expansion Slot Register */
-#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
-#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
-#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */
-
-/* Message Signalled Interrupts registers */
-
-#define PCI_MSI_FLAGS 2 /* Message Control */
-#define PCI_MSI_FLAGS_ENABLE 0x0001 /* MSI feature enabled */
-#define PCI_MSI_FLAGS_QMASK 0x000e /* Maximum queue size available */
-#define PCI_MSI_FLAGS_QSIZE 0x0070 /* Message queue size configured */
-#define PCI_MSI_FLAGS_64BIT 0x0080 /* 64-bit addresses allowed */
-#define PCI_MSI_FLAGS_MASKBIT 0x0100 /* Per-vector masking capable */
-#define PCI_MSI_RFU 3 /* Rest of capability flags */
-#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
-#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
-#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
-#define PCI_MSI_MASK_32 12 /* Mask bits register for 32-bit devices */
-#define PCI_MSI_PENDING_32 16 /* Pending intrs for 32-bit devices */
-#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
-#define PCI_MSI_MASK_64 16 /* Mask bits register for 64-bit devices */
-#define PCI_MSI_PENDING_64 20 /* Pending intrs for 64-bit devices */
-
-/* MSI-X registers */
-#define PCI_MSIX_FLAGS 2 /* Message Control */
-#define PCI_MSIX_FLAGS_QSIZE 0x07FF /* Table size */
-#define PCI_MSIX_FLAGS_MASKALL 0x4000 /* Mask all vectors for this function */
-#define PCI_MSIX_FLAGS_ENABLE 0x8000 /* MSI-X enable */
-#define PCI_MSIX_TABLE 4 /* Table offset */
-#define PCI_MSIX_TABLE_BIR 0x00000007 /* BAR index */
-#define PCI_MSIX_TABLE_OFFSET 0xfffffff8 /* Offset into specified BAR */
-#define PCI_MSIX_PBA 8 /* Pending Bit Array offset */
-#define PCI_MSIX_PBA_BIR 0x00000007 /* BAR index */
-#define PCI_MSIX_PBA_OFFSET 0xfffffff8 /* Offset into specified BAR */
-#define PCI_CAP_MSIX_SIZEOF 12 /* size of MSIX registers */
-
-/* MSI-X Table entry format */
-#define PCI_MSIX_ENTRY_SIZE 16
-#define PCI_MSIX_ENTRY_LOWER_ADDR 0
-#define PCI_MSIX_ENTRY_UPPER_ADDR 4
-#define PCI_MSIX_ENTRY_DATA 8
-#define PCI_MSIX_ENTRY_VECTOR_CTRL 12
-#define PCI_MSIX_ENTRY_CTRL_MASKBIT 1
-
-/* CompactPCI Hotswap Register */
-
-#define PCI_CHSWP_CSR 2 /* Control and Status Register */
-#define PCI_CHSWP_DHA 0x01 /* Device Hiding Arm */
-#define PCI_CHSWP_EIM 0x02 /* ENUM# Signal Mask */
-#define PCI_CHSWP_PIE 0x04 /* Pending Insert or Extract */
-#define PCI_CHSWP_LOO 0x08 /* LED On / Off */
-#define PCI_CHSWP_PI 0x30 /* Programming Interface */
-#define PCI_CHSWP_EXT 0x40 /* ENUM# status - extraction */
-#define PCI_CHSWP_INS 0x80 /* ENUM# status - insertion */
-
-/* PCI Advanced Feature registers */
-
-#define PCI_AF_LENGTH 2
-#define PCI_AF_CAP 3
-#define PCI_AF_CAP_TP 0x01
-#define PCI_AF_CAP_FLR 0x02
-#define PCI_AF_CTRL 4
-#define PCI_AF_CTRL_FLR 0x01
-#define PCI_AF_STATUS 5
-#define PCI_AF_STATUS_TP 0x01
-#define PCI_CAP_AF_SIZEOF 6 /* size of AF registers */
-
-/* PCI-X registers (Type 0 (non-bridge) devices) */
-
-#define PCI_X_CMD 2 /* Modes & Features */
-#define PCI_X_CMD_DPERR_E 0x0001 /* Data Parity Error Recovery Enable */
-#define PCI_X_CMD_ERO 0x0002 /* Enable Relaxed Ordering */
-#define PCI_X_CMD_READ_512 0x0000 /* 512 byte maximum read byte count */
-#define PCI_X_CMD_READ_1K 0x0004 /* 1Kbyte maximum read byte count */
-#define PCI_X_CMD_READ_2K 0x0008 /* 2Kbyte maximum read byte count */
-#define PCI_X_CMD_READ_4K 0x000c /* 4Kbyte maximum read byte count */
-#define PCI_X_CMD_MAX_READ 0x000c /* Max Memory Read Byte Count */
- /* Max # of outstanding split transactions */
-#define PCI_X_CMD_SPLIT_1 0x0000 /* Max 1 */
-#define PCI_X_CMD_SPLIT_2 0x0010 /* Max 2 */
-#define PCI_X_CMD_SPLIT_3 0x0020 /* Max 3 */
-#define PCI_X_CMD_SPLIT_4 0x0030 /* Max 4 */
-#define PCI_X_CMD_SPLIT_8 0x0040 /* Max 8 */
-#define PCI_X_CMD_SPLIT_12 0x0050 /* Max 12 */
-#define PCI_X_CMD_SPLIT_16 0x0060 /* Max 16 */
-#define PCI_X_CMD_SPLIT_32 0x0070 /* Max 32 */
-#define PCI_X_CMD_MAX_SPLIT 0x0070 /* Max Outstanding Split Transactions */
-#define PCI_X_CMD_VERSION(x) (((x) >> 12) & 3) /* Version */
-#define PCI_X_STATUS 4 /* PCI-X capabilities */
-#define PCI_X_STATUS_DEVFN 0x000000ff /* A copy of devfn */
-#define PCI_X_STATUS_BUS 0x0000ff00 /* A copy of bus nr */
-#define PCI_X_STATUS_64BIT 0x00010000 /* 64-bit device */
-#define PCI_X_STATUS_133MHZ 0x00020000 /* 133 MHz capable */
-#define PCI_X_STATUS_SPL_DISC 0x00040000 /* Split Completion Discarded */
-#define PCI_X_STATUS_UNX_SPL 0x00080000 /* Unexpected Split Completion */
-#define PCI_X_STATUS_COMPLEX 0x00100000 /* Device Complexity */
-#define PCI_X_STATUS_MAX_READ 0x00600000 /* Designed Max Memory Read Count */
-#define PCI_X_STATUS_MAX_SPLIT 0x03800000 /* Designed Max Outstanding Split Transactions */
-#define PCI_X_STATUS_MAX_CUM 0x1c000000 /* Designed Max Cumulative Read Size */
-#define PCI_X_STATUS_SPL_ERR 0x20000000 /* Rcvd Split Completion Error Msg */
-#define PCI_X_STATUS_266MHZ 0x40000000 /* 266 MHz capable */
-#define PCI_X_STATUS_533MHZ 0x80000000 /* 533 MHz capable */
-#define PCI_X_ECC_CSR 8 /* ECC control and status */
-#define PCI_CAP_PCIX_SIZEOF_V0 8 /* size of registers for Version 0 */
-#define PCI_CAP_PCIX_SIZEOF_V1 24 /* size for Version 1 */
-#define PCI_CAP_PCIX_SIZEOF_V2 PCI_CAP_PCIX_SIZEOF_V1 /* Same for v2 */
-
-/* PCI-X registers (Type 1 (bridge) devices) */
-
-#define PCI_X_BRIDGE_SSTATUS 2 /* Secondary Status */
-#define PCI_X_SSTATUS_64BIT 0x0001 /* Secondary AD interface is 64 bits */
-#define PCI_X_SSTATUS_133MHZ 0x0002 /* 133 MHz capable */
-#define PCI_X_SSTATUS_FREQ 0x03c0 /* Secondary Bus Mode and Frequency */
-#define PCI_X_SSTATUS_VERS 0x3000 /* PCI-X Capability Version */
-#define PCI_X_SSTATUS_V1 0x1000 /* Mode 2, not Mode 1 */
-#define PCI_X_SSTATUS_V2 0x2000 /* Mode 1 or Modes 1 and 2 */
-#define PCI_X_SSTATUS_266MHZ 0x4000 /* 266 MHz capable */
-#define PCI_X_SSTATUS_533MHZ 0x8000 /* 533 MHz capable */
-#define PCI_X_BRIDGE_STATUS 4 /* Bridge Status */
-
-/* PCI Bridge Subsystem ID registers */
-
-#define PCI_SSVID_VENDOR_ID 4 /* PCI Bridge subsystem vendor ID */
-#define PCI_SSVID_DEVICE_ID 6 /* PCI Bridge subsystem device ID */
-
-/* PCI Express capability registers */
-
-#define PCI_EXP_FLAGS 2 /* Capabilities register */
-#define PCI_EXP_FLAGS_VERS 0x000f /* Capability version */
-#define PCI_EXP_FLAGS_TYPE 0x00f0 /* Device/Port type */
-#define PCI_EXP_TYPE_ENDPOINT 0x0 /* Express Endpoint */
-#define PCI_EXP_TYPE_LEG_END 0x1 /* Legacy Endpoint */
-#define PCI_EXP_TYPE_ROOT_PORT 0x4 /* Root Port */
-#define PCI_EXP_TYPE_UPSTREAM 0x5 /* Upstream Port */
-#define PCI_EXP_TYPE_DOWNSTREAM 0x6 /* Downstream Port */
-#define PCI_EXP_TYPE_PCI_BRIDGE 0x7 /* PCIe to PCI/PCI-X Bridge */
-#define PCI_EXP_TYPE_PCIE_BRIDGE 0x8 /* PCI/PCI-X to PCIe Bridge */
-#define PCI_EXP_TYPE_RC_END 0x9 /* Root Complex Integrated Endpoint */
-#define PCI_EXP_TYPE_RC_EC 0xa /* Root Complex Event Collector */
-#define PCI_EXP_FLAGS_SLOT 0x0100 /* Slot implemented */
-#define PCI_EXP_FLAGS_IRQ 0x3e00 /* Interrupt message number */
-#define PCI_EXP_DEVCAP 4 /* Device capabilities */
-#define PCI_EXP_DEVCAP_PAYLOAD 0x00000007 /* Max_Payload_Size */
-#define PCI_EXP_DEVCAP_PHANTOM 0x00000018 /* Phantom functions */
-#define PCI_EXP_DEVCAP_EXT_TAG 0x00000020 /* Extended tags */
-#define PCI_EXP_DEVCAP_L0S 0x000001c0 /* L0s Acceptable Latency */
-#define PCI_EXP_DEVCAP_L1 0x00000e00 /* L1 Acceptable Latency */
-#define PCI_EXP_DEVCAP_ATN_BUT 0x00001000 /* Attention Button Present */
-#define PCI_EXP_DEVCAP_ATN_IND 0x00002000 /* Attention Indicator Present */
-#define PCI_EXP_DEVCAP_PWR_IND 0x00004000 /* Power Indicator Present */
-#define PCI_EXP_DEVCAP_RBER 0x00008000 /* Role-Based Error Reporting */
-#define PCI_EXP_DEVCAP_PWR_VAL 0x03fc0000 /* Slot Power Limit Value */
-#define PCI_EXP_DEVCAP_PWR_SCL 0x0c000000 /* Slot Power Limit Scale */
-#define PCI_EXP_DEVCAP_FLR 0x10000000 /* Function Level Reset */
-#define PCI_EXP_DEVCTL 8 /* Device Control */
-#define PCI_EXP_DEVCTL_CERE 0x0001 /* Correctable Error Reporting En. */
-#define PCI_EXP_DEVCTL_NFERE 0x0002 /* Non-Fatal Error Reporting Enable */
-#define PCI_EXP_DEVCTL_FERE 0x0004 /* Fatal Error Reporting Enable */
-#define PCI_EXP_DEVCTL_URRE 0x0008 /* Unsupported Request Reporting En. */
-#define PCI_EXP_DEVCTL_RELAX_EN 0x0010 /* Enable relaxed ordering */
-#define PCI_EXP_DEVCTL_PAYLOAD 0x00e0 /* Max_Payload_Size */
-#define PCI_EXP_DEVCTL_EXT_TAG 0x0100 /* Extended Tag Field Enable */
-#define PCI_EXP_DEVCTL_PHANTOM 0x0200 /* Phantom Functions Enable */
-#define PCI_EXP_DEVCTL_AUX_PME 0x0400 /* Auxiliary Power PM Enable */
-#define PCI_EXP_DEVCTL_NOSNOOP_EN 0x0800 /* Enable No Snoop */
-#define PCI_EXP_DEVCTL_READRQ 0x7000 /* Max_Read_Request_Size */
-#define PCI_EXP_DEVCTL_BCR_FLR 0x8000 /* Bridge Configuration Retry / FLR */
-#define PCI_EXP_DEVSTA 10 /* Device Status */
-#define PCI_EXP_DEVSTA_CED 0x0001 /* Correctable Error Detected */
-#define PCI_EXP_DEVSTA_NFED 0x0002 /* Non-Fatal Error Detected */
-#define PCI_EXP_DEVSTA_FED 0x0004 /* Fatal Error Detected */
-#define PCI_EXP_DEVSTA_URD 0x0008 /* Unsupported Request Detected */
-#define PCI_EXP_DEVSTA_AUXPD 0x0010 /* AUX Power Detected */
-#define PCI_EXP_DEVSTA_TRPND 0x0020 /* Transactions Pending */
-#define PCI_EXP_LNKCAP 12 /* Link Capabilities */
-#define PCI_EXP_LNKCAP_SLS 0x0000000f /* Supported Link Speeds */
-#define PCI_EXP_LNKCAP_SLS_2_5GB 0x00000001 /* LNKCAP2 SLS Vector bit 0 */
-#define PCI_EXP_LNKCAP_SLS_5_0GB 0x00000002 /* LNKCAP2 SLS Vector bit 1 */
-#define PCI_EXP_LNKCAP_MLW 0x000003f0 /* Maximum Link Width */
-#define PCI_EXP_LNKCAP_ASPMS 0x00000c00 /* ASPM Support */
-#define PCI_EXP_LNKCAP_L0SEL 0x00007000 /* L0s Exit Latency */
-#define PCI_EXP_LNKCAP_L1EL 0x00038000 /* L1 Exit Latency */
-#define PCI_EXP_LNKCAP_CLKPM 0x00040000 /* Clock Power Management */
-#define PCI_EXP_LNKCAP_SDERC 0x00080000 /* Surprise Down Error Reporting Capable */
-#define PCI_EXP_LNKCAP_DLLLARC 0x00100000 /* Data Link Layer Link Active Reporting Capable */
-#define PCI_EXP_LNKCAP_LBNC 0x00200000 /* Link Bandwidth Notification Capability */
-#define PCI_EXP_LNKCAP_PN 0xff000000 /* Port Number */
-#define PCI_EXP_LNKCTL 16 /* Link Control */
-#define PCI_EXP_LNKCTL_ASPMC 0x0003 /* ASPM Control */
-#define PCI_EXP_LNKCTL_ASPM_L0S 0x0001 /* L0s Enable */
-#define PCI_EXP_LNKCTL_ASPM_L1 0x0002 /* L1 Enable */
-#define PCI_EXP_LNKCTL_RCB 0x0008 /* Read Completion Boundary */
-#define PCI_EXP_LNKCTL_LD 0x0010 /* Link Disable */
-#define PCI_EXP_LNKCTL_RL 0x0020 /* Retrain Link */
-#define PCI_EXP_LNKCTL_CCC 0x0040 /* Common Clock Configuration */
-#define PCI_EXP_LNKCTL_ES 0x0080 /* Extended Synch */
-#define PCI_EXP_LNKCTL_CLKREQ_EN 0x0100 /* Enable clkreq */
-#define PCI_EXP_LNKCTL_HAWD 0x0200 /* Hardware Autonomous Width Disable */
-#define PCI_EXP_LNKCTL_LBMIE 0x0400 /* Link Bandwidth Management Interrupt Enable */
-#define PCI_EXP_LNKCTL_LABIE 0x0800 /* Link Autonomous Bandwidth Interrupt Enable */
-#define PCI_EXP_LNKSTA 18 /* Link Status */
-#define PCI_EXP_LNKSTA_CLS 0x000f /* Current Link Speed */
-#define PCI_EXP_LNKSTA_CLS_2_5GB 0x0001 /* Current Link Speed 2.5GT/s */
-#define PCI_EXP_LNKSTA_CLS_5_0GB 0x0002 /* Current Link Speed 5.0GT/s */
-#define PCI_EXP_LNKSTA_CLS_8_0GB 0x0003 /* Current Link Speed 8.0GT/s */
-#define PCI_EXP_LNKSTA_NLW 0x03f0 /* Negotiated Link Width */
-#define PCI_EXP_LNKSTA_NLW_X1 0x0010 /* Current Link Width x1 */
-#define PCI_EXP_LNKSTA_NLW_X2 0x0020 /* Current Link Width x2 */
-#define PCI_EXP_LNKSTA_NLW_X4 0x0040 /* Current Link Width x4 */
-#define PCI_EXP_LNKSTA_NLW_X8 0x0080 /* Current Link Width x8 */
-#define PCI_EXP_LNKSTA_NLW_SHIFT 4 /* start of NLW mask in link status */
-#define PCI_EXP_LNKSTA_LT 0x0800 /* Link Training */
-#define PCI_EXP_LNKSTA_SLC 0x1000 /* Slot Clock Configuration */
-#define PCI_EXP_LNKSTA_DLLLA 0x2000 /* Data Link Layer Link Active */
-#define PCI_EXP_LNKSTA_LBMS 0x4000 /* Link Bandwidth Management Status */
-#define PCI_EXP_LNKSTA_LABS 0x8000 /* Link Autonomous Bandwidth Status */
-#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V1 20 /* v1 endpoints end here */
-#define PCI_EXP_SLTCAP 20 /* Slot Capabilities */
-#define PCI_EXP_SLTCAP_ABP 0x00000001 /* Attention Button Present */
-#define PCI_EXP_SLTCAP_PCP 0x00000002 /* Power Controller Present */
-#define PCI_EXP_SLTCAP_MRLSP 0x00000004 /* MRL Sensor Present */
-#define PCI_EXP_SLTCAP_AIP 0x00000008 /* Attention Indicator Present */
-#define PCI_EXP_SLTCAP_PIP 0x00000010 /* Power Indicator Present */
-#define PCI_EXP_SLTCAP_HPS 0x00000020 /* Hot-Plug Surprise */
-#define PCI_EXP_SLTCAP_HPC 0x00000040 /* Hot-Plug Capable */
-#define PCI_EXP_SLTCAP_SPLV 0x00007f80 /* Slot Power Limit Value */
-#define PCI_EXP_SLTCAP_SPLS 0x00018000 /* Slot Power Limit Scale */
-#define PCI_EXP_SLTCAP_EIP 0x00020000 /* Electromechanical Interlock Present */
-#define PCI_EXP_SLTCAP_NCCS 0x00040000 /* No Command Completed Support */
-#define PCI_EXP_SLTCAP_PSN 0xfff80000 /* Physical Slot Number */
-#define PCI_EXP_SLTCTL 24 /* Slot Control */
-#define PCI_EXP_SLTCTL_ABPE 0x0001 /* Attention Button Pressed Enable */
-#define PCI_EXP_SLTCTL_PFDE 0x0002 /* Power Fault Detected Enable */
-#define PCI_EXP_SLTCTL_MRLSCE 0x0004 /* MRL Sensor Changed Enable */
-#define PCI_EXP_SLTCTL_PDCE 0x0008 /* Presence Detect Changed Enable */
-#define PCI_EXP_SLTCTL_CCIE 0x0010 /* Command Completed Interrupt Enable */
-#define PCI_EXP_SLTCTL_HPIE 0x0020 /* Hot-Plug Interrupt Enable */
-#define PCI_EXP_SLTCTL_AIC 0x00c0 /* Attention Indicator Control */
-#define PCI_EXP_SLTCTL_ATTN_IND_ON 0x0040 /* Attention Indicator on */
-#define PCI_EXP_SLTCTL_ATTN_IND_BLINK 0x0080 /* Attention Indicator blinking */
-#define PCI_EXP_SLTCTL_ATTN_IND_OFF 0x00c0 /* Attention Indicator off */
-#define PCI_EXP_SLTCTL_PIC 0x0300 /* Power Indicator Control */
-#define PCI_EXP_SLTCTL_PWR_IND_ON 0x0100 /* Power Indicator on */
-#define PCI_EXP_SLTCTL_PWR_IND_BLINK 0x0200 /* Power Indicator blinking */
-#define PCI_EXP_SLTCTL_PWR_IND_OFF 0x0300 /* Power Indicator off */
-#define PCI_EXP_SLTCTL_PCC 0x0400 /* Power Controller Control */
-#define PCI_EXP_SLTCTL_PWR_ON 0x0000 /* Power On */
-#define PCI_EXP_SLTCTL_PWR_OFF 0x0400 /* Power Off */
-#define PCI_EXP_SLTCTL_EIC 0x0800 /* Electromechanical Interlock Control */
-#define PCI_EXP_SLTCTL_DLLSCE 0x1000 /* Data Link Layer State Changed Enable */
-#define PCI_EXP_SLTSTA 26 /* Slot Status */
-#define PCI_EXP_SLTSTA_ABP 0x0001 /* Attention Button Pressed */
-#define PCI_EXP_SLTSTA_PFD 0x0002 /* Power Fault Detected */
-#define PCI_EXP_SLTSTA_MRLSC 0x0004 /* MRL Sensor Changed */
-#define PCI_EXP_SLTSTA_PDC 0x0008 /* Presence Detect Changed */
-#define PCI_EXP_SLTSTA_CC 0x0010 /* Command Completed */
-#define PCI_EXP_SLTSTA_MRLSS 0x0020 /* MRL Sensor State */
-#define PCI_EXP_SLTSTA_PDS 0x0040 /* Presence Detect State */
-#define PCI_EXP_SLTSTA_EIS 0x0080 /* Electromechanical Interlock Status */
-#define PCI_EXP_SLTSTA_DLLSC 0x0100 /* Data Link Layer State Changed */
-#define PCI_EXP_RTCTL 28 /* Root Control */
-#define PCI_EXP_RTCTL_SECEE 0x0001 /* System Error on Correctable Error */
-#define PCI_EXP_RTCTL_SENFEE 0x0002 /* System Error on Non-Fatal Error */
-#define PCI_EXP_RTCTL_SEFEE 0x0004 /* System Error on Fatal Error */
-#define PCI_EXP_RTCTL_PMEIE 0x0008 /* PME Interrupt Enable */
-#define PCI_EXP_RTCTL_CRSSVE 0x0010 /* CRS Software Visibility Enable */
-#define PCI_EXP_RTCAP 30 /* Root Capabilities */
-#define PCI_EXP_RTCAP_CRSVIS 0x0001 /* CRS Software Visibility capability */
-#define PCI_EXP_RTSTA 32 /* Root Status */
-#define PCI_EXP_RTSTA_PME 0x00010000 /* PME status */
-#define PCI_EXP_RTSTA_PENDING 0x00020000 /* PME pending */
-/*
- * The Device Capabilities 2, Device Status 2, Device Control 2,
- * Link Capabilities 2, Link Status 2, Link Control 2,
- * Slot Capabilities 2, Slot Status 2, and Slot Control 2 registers
- * are only present on devices with PCIe Capability version 2.
- * Use pcie_capability_read_word() and similar interfaces to use them
- * safely.
- */
-#define PCI_EXP_DEVCAP2 36 /* Device Capabilities 2 */
-#define PCI_EXP_DEVCAP2_ARI 0x00000020 /* Alternative Routing-ID */
-#define PCI_EXP_DEVCAP2_LTR 0x00000800 /* Latency tolerance reporting */
-#define PCI_EXP_DEVCAP2_OBFF_MASK 0x000c0000 /* OBFF support mechanism */
-#define PCI_EXP_DEVCAP2_OBFF_MSG 0x00040000 /* New message signaling */
-#define PCI_EXP_DEVCAP2_OBFF_WAKE 0x00080000 /* Re-use WAKE# for OBFF */
-#define PCI_EXP_DEVCTL2 40 /* Device Control 2 */
-#define PCI_EXP_DEVCTL2_COMP_TIMEOUT 0x000f /* Completion Timeout Value */
-#define PCI_EXP_DEVCTL2_ARI 0x0020 /* Alternative Routing-ID */
-#define PCI_EXP_DEVCTL2_IDO_REQ_EN 0x0100 /* Allow IDO for requests */
-#define PCI_EXP_DEVCTL2_IDO_CMP_EN 0x0200 /* Allow IDO for completions */
-#define PCI_EXP_DEVCTL2_LTR_EN 0x0400 /* Enable LTR mechanism */
-#define PCI_EXP_DEVCTL2_OBFF_MSGA_EN 0x2000 /* Enable OBFF Message type A */
-#define PCI_EXP_DEVCTL2_OBFF_MSGB_EN 0x4000 /* Enable OBFF Message type B */
-#define PCI_EXP_DEVCTL2_OBFF_WAKE_EN 0x6000 /* OBFF using WAKE# signaling */
-#define PCI_EXP_DEVSTA2 42 /* Device Status 2 */
-#define PCI_CAP_EXP_ENDPOINT_SIZEOF_V2 44 /* v2 endpoints end here */
-#define PCI_EXP_LNKCAP2 44 /* Link Capabilities 2 */
-#define PCI_EXP_LNKCAP2_SLS_2_5GB 0x00000002 /* Supported Speed 2.5GT/s */
-#define PCI_EXP_LNKCAP2_SLS_5_0GB 0x00000004 /* Supported Speed 5.0GT/s */
-#define PCI_EXP_LNKCAP2_SLS_8_0GB 0x00000008 /* Supported Speed 8.0GT/s */
-#define PCI_EXP_LNKCAP2_CROSSLINK 0x00000100 /* Crosslink supported */
-#define PCI_EXP_LNKCTL2 48 /* Link Control 2 */
-#define PCI_EXP_LNKSTA2 50 /* Link Status 2 */
-#define PCI_EXP_SLTCAP2 52 /* Slot Capabilities 2 */
-#define PCI_EXP_SLTCTL2 56 /* Slot Control 2 */
-#define PCI_EXP_SLTSTA2 58 /* Slot Status 2 */
-
-/* Extended Capabilities (PCI-X 2.0 and Express) */
-#define PCI_EXT_CAP_ID(header) (header & 0x0000ffff)
-#define PCI_EXT_CAP_VER(header) ((header >> 16) & 0xf)
-#define PCI_EXT_CAP_NEXT(header) ((header >> 20) & 0xffc)
-
-#define PCI_EXT_CAP_ID_ERR 0x01 /* Advanced Error Reporting */
-#define PCI_EXT_CAP_ID_VC 0x02 /* Virtual Channel Capability */
-#define PCI_EXT_CAP_ID_DSN 0x03 /* Device Serial Number */
-#define PCI_EXT_CAP_ID_PWR 0x04 /* Power Budgeting */
-#define PCI_EXT_CAP_ID_RCLD 0x05 /* Root Complex Link Declaration */
-#define PCI_EXT_CAP_ID_RCILC 0x06 /* Root Complex Internal Link Control */
-#define PCI_EXT_CAP_ID_RCEC 0x07 /* Root Complex Event Collector */
-#define PCI_EXT_CAP_ID_MFVC 0x08 /* Multi-Function VC Capability */
-#define PCI_EXT_CAP_ID_VC9 0x09 /* same as _VC */
-#define PCI_EXT_CAP_ID_RCRB 0x0A /* Root Complex RB? */
-#define PCI_EXT_CAP_ID_VNDR 0x0B /* Vendor-Specific */
-#define PCI_EXT_CAP_ID_CAC 0x0C /* Config Access - obsolete */
-#define PCI_EXT_CAP_ID_ACS 0x0D /* Access Control Services */
-#define PCI_EXT_CAP_ID_ARI 0x0E /* Alternate Routing ID */
-#define PCI_EXT_CAP_ID_ATS 0x0F /* Address Translation Services */
-#define PCI_EXT_CAP_ID_SRIOV 0x10 /* Single Root I/O Virtualization */
-#define PCI_EXT_CAP_ID_MRIOV 0x11 /* Multi Root I/O Virtualization */
-#define PCI_EXT_CAP_ID_MCAST 0x12 /* Multicast */
-#define PCI_EXT_CAP_ID_PRI 0x13 /* Page Request Interface */
-#define PCI_EXT_CAP_ID_AMD_XXX 0x14 /* Reserved for AMD */
-#define PCI_EXT_CAP_ID_REBAR 0x15 /* Resizable BAR */
-#define PCI_EXT_CAP_ID_DPA 0x16 /* Dynamic Power Allocation */
-#define PCI_EXT_CAP_ID_TPH 0x17 /* TPH Requester */
-#define PCI_EXT_CAP_ID_LTR 0x18 /* Latency Tolerance Reporting */
-#define PCI_EXT_CAP_ID_SECPCI 0x19 /* Secondary PCIe Capability */
-#define PCI_EXT_CAP_ID_PMUX 0x1A /* Protocol Multiplexing */
-#define PCI_EXT_CAP_ID_PASID 0x1B /* Process Address Space ID */
-#define PCI_EXT_CAP_ID_MAX PCI_EXT_CAP_ID_PASID
-
-#define PCI_EXT_CAP_DSN_SIZEOF 12
-#define PCI_EXT_CAP_MCAST_ENDPOINT_SIZEOF 40
-
-/* Advanced Error Reporting */
-#define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */
-#define PCI_ERR_UNC_UND 0x00000001 /* Undefined */
-#define PCI_ERR_UNC_DLP 0x00000010 /* Data Link Protocol */
-#define PCI_ERR_UNC_SURPDN 0x00000020 /* Surprise Down */
-#define PCI_ERR_UNC_POISON_TLP 0x00001000 /* Poisoned TLP */
-#define PCI_ERR_UNC_FCP 0x00002000 /* Flow Control Protocol */
-#define PCI_ERR_UNC_COMP_TIME 0x00004000 /* Completion Timeout */
-#define PCI_ERR_UNC_COMP_ABORT 0x00008000 /* Completer Abort */
-#define PCI_ERR_UNC_UNX_COMP 0x00010000 /* Unexpected Completion */
-#define PCI_ERR_UNC_RX_OVER 0x00020000 /* Receiver Overflow */
-#define PCI_ERR_UNC_MALF_TLP 0x00040000 /* Malformed TLP */
-#define PCI_ERR_UNC_ECRC 0x00080000 /* ECRC Error Status */
-#define PCI_ERR_UNC_UNSUP 0x00100000 /* Unsupported Request */
-#define PCI_ERR_UNC_ACSV 0x00200000 /* ACS Violation */
-#define PCI_ERR_UNC_INTN 0x00400000 /* internal error */
-#define PCI_ERR_UNC_MCBTLP 0x00800000 /* MC blocked TLP */
-#define PCI_ERR_UNC_ATOMEG 0x01000000 /* Atomic egress blocked */
-#define PCI_ERR_UNC_TLPPRE 0x02000000 /* TLP prefix blocked */
-#define PCI_ERR_UNCOR_MASK 8 /* Uncorrectable Error Mask */
- /* Same bits as above */
-#define PCI_ERR_UNCOR_SEVER 12 /* Uncorrectable Error Severity */
- /* Same bits as above */
-#define PCI_ERR_COR_STATUS 16 /* Correctable Error Status */
-#define PCI_ERR_COR_RCVR 0x00000001 /* Receiver Error Status */
-#define PCI_ERR_COR_BAD_TLP 0x00000040 /* Bad TLP Status */
-#define PCI_ERR_COR_BAD_DLLP 0x00000080 /* Bad DLLP Status */
-#define PCI_ERR_COR_REP_ROLL 0x00000100 /* REPLAY_NUM Rollover */
-#define PCI_ERR_COR_REP_TIMER 0x00001000 /* Replay Timer Timeout */
-#define PCI_ERR_COR_ADV_NFAT 0x00002000 /* Advisory Non-Fatal */
-#define PCI_ERR_COR_INTERNAL 0x00004000 /* Corrected Internal */
-#define PCI_ERR_COR_LOG_OVER 0x00008000 /* Header Log Overflow */
-#define PCI_ERR_COR_MASK 20 /* Correctable Error Mask */
- /* Same bits as above */
-#define PCI_ERR_CAP 24 /* Advanced Error Capabilities */
-#define PCI_ERR_CAP_FEP(x) ((x) & 31) /* First Error Pointer */
-#define PCI_ERR_CAP_ECRC_GENC 0x00000020 /* ECRC Generation Capable */
-#define PCI_ERR_CAP_ECRC_GENE 0x00000040 /* ECRC Generation Enable */
-#define PCI_ERR_CAP_ECRC_CHKC 0x00000080 /* ECRC Check Capable */
-#define PCI_ERR_CAP_ECRC_CHKE 0x00000100 /* ECRC Check Enable */
-#define PCI_ERR_HEADER_LOG 28 /* Header Log Register (16 bytes) */
-#define PCI_ERR_ROOT_COMMAND 44 /* Root Error Command */
-/* Correctable Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_COR_EN 0x00000001
-/* Non-fatal Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_NONFATAL_EN 0x00000002
-/* Fatal Err Reporting Enable */
-#define PCI_ERR_ROOT_CMD_FATAL_EN 0x00000004
-#define PCI_ERR_ROOT_STATUS 48
-#define PCI_ERR_ROOT_COR_RCV 0x00000001 /* ERR_COR Received */
-/* Multi ERR_COR Received */
-#define PCI_ERR_ROOT_MULTI_COR_RCV 0x00000002
-/* ERR_FATAL/NONFATAL Received */
-#define PCI_ERR_ROOT_UNCOR_RCV 0x00000004
-/* Multi ERR_FATAL/NONFATAL Received */
-#define PCI_ERR_ROOT_MULTI_UNCOR_RCV 0x00000008
-#define PCI_ERR_ROOT_FIRST_FATAL 0x00000010 /* First Fatal */
-#define PCI_ERR_ROOT_NONFATAL_RCV 0x00000020 /* Non-Fatal Received */
-#define PCI_ERR_ROOT_FATAL_RCV 0x00000040 /* Fatal Received */
-#define PCI_ERR_ROOT_ERR_SRC 52 /* Error Source Identification */
-
-/* Virtual Channel */
-#define PCI_VC_PORT_CAP1 4
-#define PCI_VC_CAP1_EVCC 0x00000007 /* extended VC count */
-#define PCI_VC_CAP1_LPEVCC 0x00000070 /* low prio extended VC count */
-#define PCI_VC_CAP1_ARB_SIZE 0x00000c00
-#define PCI_VC_PORT_CAP2 8
-#define PCI_VC_CAP2_32_PHASE 0x00000002
-#define PCI_VC_CAP2_64_PHASE 0x00000004
-#define PCI_VC_CAP2_128_PHASE 0x00000008
-#define PCI_VC_CAP2_ARB_OFF 0xff000000
-#define PCI_VC_PORT_CTRL 12
-#define PCI_VC_PORT_CTRL_LOAD_TABLE 0x00000001
-#define PCI_VC_PORT_STATUS 14
-#define PCI_VC_PORT_STATUS_TABLE 0x00000001
-#define PCI_VC_RES_CAP 16
-#define PCI_VC_RES_CAP_32_PHASE 0x00000002
-#define PCI_VC_RES_CAP_64_PHASE 0x00000004
-#define PCI_VC_RES_CAP_128_PHASE 0x00000008
-#define PCI_VC_RES_CAP_128_PHASE_TB 0x00000010
-#define PCI_VC_RES_CAP_256_PHASE 0x00000020
-#define PCI_VC_RES_CAP_ARB_OFF 0xff000000
-#define PCI_VC_RES_CTRL 20
-#define PCI_VC_RES_CTRL_LOAD_TABLE 0x00010000
-#define PCI_VC_RES_CTRL_ARB_SELECT 0x000e0000
-#define PCI_VC_RES_CTRL_ID 0x07000000
-#define PCI_VC_RES_CTRL_ENABLE 0x80000000
-#define PCI_VC_RES_STATUS 26
-#define PCI_VC_RES_STATUS_TABLE 0x00000001
-#define PCI_VC_RES_STATUS_NEGO 0x00000002
-#define PCI_CAP_VC_BASE_SIZEOF 0x10
-#define PCI_CAP_VC_PER_VC_SIZEOF 0x0C
-
-/* Power Budgeting */
-#define PCI_PWR_DSR 4 /* Data Select Register */
-#define PCI_PWR_DATA 8 /* Data Register */
-#define PCI_PWR_DATA_BASE(x) ((x) & 0xff) /* Base Power */
-#define PCI_PWR_DATA_SCALE(x) (((x) >> 8) & 3) /* Data Scale */
-#define PCI_PWR_DATA_PM_SUB(x) (((x) >> 10) & 7) /* PM Sub State */
-#define PCI_PWR_DATA_PM_STATE(x) (((x) >> 13) & 3) /* PM State */
-#define PCI_PWR_DATA_TYPE(x) (((x) >> 15) & 7) /* Type */
-#define PCI_PWR_DATA_RAIL(x) (((x) >> 18) & 7) /* Power Rail */
-#define PCI_PWR_CAP 12 /* Capability */
-#define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */
-#define PCI_EXT_CAP_PWR_SIZEOF 16
-
-/* Vendor-Specific (VSEC, PCI_EXT_CAP_ID_VNDR) */
-#define PCI_VNDR_HEADER 4 /* Vendor-Specific Header */
-#define PCI_VNDR_HEADER_ID(x) ((x) & 0xffff)
-#define PCI_VNDR_HEADER_REV(x) (((x) >> 16) & 0xf)
-#define PCI_VNDR_HEADER_LEN(x) (((x) >> 20) & 0xfff)
-
-/*
- * HyperTransport sub capability types
- *
- * Unfortunately there are both 3 bit and 5 bit capability types defined
- * in the HT spec, catering for that is a little messy. You probably don't
- * want to use these directly, just use pci_find_ht_capability() and it
- * will do the right thing for you.
- */
-#define HT_3BIT_CAP_MASK 0xE0
-#define HT_CAPTYPE_SLAVE 0x00 /* Slave/Primary link configuration */
-#define HT_CAPTYPE_HOST 0x20 /* Host/Secondary link configuration */
-
-#define HT_5BIT_CAP_MASK 0xF8
-#define HT_CAPTYPE_IRQ 0x80 /* IRQ Configuration */
-#define HT_CAPTYPE_REMAPPING_40 0xA0 /* 40 bit address remapping */
-#define HT_CAPTYPE_REMAPPING_64 0xA2 /* 64 bit address remapping */
-#define HT_CAPTYPE_UNITID_CLUMP 0x90 /* Unit ID clumping */
-#define HT_CAPTYPE_EXTCONF 0x98 /* Extended Configuration Space Access */
-#define HT_CAPTYPE_MSI_MAPPING 0xA8 /* MSI Mapping Capability */
-#define HT_MSI_FLAGS 0x02 /* Offset to flags */
-#define HT_MSI_FLAGS_ENABLE 0x1 /* Mapping enable */
-#define HT_MSI_FLAGS_FIXED 0x2 /* Fixed mapping only */
-#define HT_MSI_FIXED_ADDR 0x00000000FEE00000ULL /* Fixed addr */
-#define HT_MSI_ADDR_LO 0x04 /* Offset to low addr bits */
-#define HT_MSI_ADDR_LO_MASK 0xFFF00000 /* Low address bit mask */
-#define HT_MSI_ADDR_HI 0x08 /* Offset to high addr bits */
-#define HT_CAPTYPE_DIRECT_ROUTE 0xB0 /* Direct routing configuration */
-#define HT_CAPTYPE_VCSET 0xB8 /* Virtual Channel configuration */
-#define HT_CAPTYPE_ERROR_RETRY 0xC0 /* Retry on error configuration */
-#define HT_CAPTYPE_GEN3 0xD0 /* Generation 3 HyperTransport configuration */
-#define HT_CAPTYPE_PM 0xE0 /* HyperTransport power management configuration */
-#define HT_CAP_SIZEOF_LONG 28 /* slave & primary */
-#define HT_CAP_SIZEOF_SHORT 24 /* host & secondary */
-
-/* Alternative Routing-ID Interpretation */
-#define PCI_ARI_CAP 0x04 /* ARI Capability Register */
-#define PCI_ARI_CAP_MFVC 0x0001 /* MFVC Function Groups Capability */
-#define PCI_ARI_CAP_ACS 0x0002 /* ACS Function Groups Capability */
-#define PCI_ARI_CAP_NFN(x) (((x) >> 8) & 0xff) /* Next Function Number */
-#define PCI_ARI_CTRL 0x06 /* ARI Control Register */
-#define PCI_ARI_CTRL_MFVC 0x0001 /* MFVC Function Groups Enable */
-#define PCI_ARI_CTRL_ACS 0x0002 /* ACS Function Groups Enable */
-#define PCI_ARI_CTRL_FG(x) (((x) >> 4) & 7) /* Function Group */
-#define PCI_EXT_CAP_ARI_SIZEOF 8
-
-/* Address Translation Service */
-#define PCI_ATS_CAP 0x04 /* ATS Capability Register */
-#define PCI_ATS_CAP_QDEP(x) ((x) & 0x1f) /* Invalidate Queue Depth */
-#define PCI_ATS_MAX_QDEP 32 /* Max Invalidate Queue Depth */
-#define PCI_ATS_CTRL 0x06 /* ATS Control Register */
-#define PCI_ATS_CTRL_ENABLE 0x8000 /* ATS Enable */
-#define PCI_ATS_CTRL_STU(x) ((x) & 0x1f) /* Smallest Translation Unit */
-#define PCI_ATS_MIN_STU 12 /* shift of minimum STU block */
-#define PCI_EXT_CAP_ATS_SIZEOF 8
-
-/* Page Request Interface */
-#define PCI_PRI_CTRL 0x04 /* PRI control register */
-#define PCI_PRI_CTRL_ENABLE 0x01 /* Enable */
-#define PCI_PRI_CTRL_RESET 0x02 /* Reset */
-#define PCI_PRI_STATUS 0x06 /* PRI status register */
-#define PCI_PRI_STATUS_RF 0x001 /* Response Failure */
-#define PCI_PRI_STATUS_UPRGI 0x002 /* Unexpected PRG index */
-#define PCI_PRI_STATUS_STOPPED 0x100 /* PRI Stopped */
-#define PCI_PRI_MAX_REQ 0x08 /* PRI max reqs supported */
-#define PCI_PRI_ALLOC_REQ 0x0c /* PRI max reqs allowed */
-#define PCI_EXT_CAP_PRI_SIZEOF 16
-
-/* Process Address Space ID */
-#define PCI_PASID_CAP 0x04 /* PASID feature register */
-#define PCI_PASID_CAP_EXEC 0x02 /* Exec permissions Supported */
-#define PCI_PASID_CAP_PRIV 0x04 /* Privilege Mode Supported */
-#define PCI_PASID_CTRL 0x06 /* PASID control register */
-#define PCI_PASID_CTRL_ENABLE 0x01 /* Enable bit */
-#define PCI_PASID_CTRL_EXEC 0x02 /* Exec permissions Enable */
-#define PCI_PASID_CTRL_PRIV 0x04 /* Privilege Mode Enable */
-#define PCI_EXT_CAP_PASID_SIZEOF 8
-
-/* Single Root I/O Virtualization */
-#define PCI_SRIOV_CAP 0x04 /* SR-IOV Capabilities */
-#define PCI_SRIOV_CAP_VFM 0x01 /* VF Migration Capable */
-#define PCI_SRIOV_CAP_INTR(x) ((x) >> 21) /* Interrupt Message Number */
-#define PCI_SRIOV_CTRL 0x08 /* SR-IOV Control */
-#define PCI_SRIOV_CTRL_VFE 0x01 /* VF Enable */
-#define PCI_SRIOV_CTRL_VFM 0x02 /* VF Migration Enable */
-#define PCI_SRIOV_CTRL_INTR 0x04 /* VF Migration Interrupt Enable */
-#define PCI_SRIOV_CTRL_MSE 0x08 /* VF Memory Space Enable */
-#define PCI_SRIOV_CTRL_ARI 0x10 /* ARI Capable Hierarchy */
-#define PCI_SRIOV_STATUS 0x0a /* SR-IOV Status */
-#define PCI_SRIOV_STATUS_VFM 0x01 /* VF Migration Status */
-#define PCI_SRIOV_INITIAL_VF 0x0c /* Initial VFs */
-#define PCI_SRIOV_TOTAL_VF 0x0e /* Total VFs */
-#define PCI_SRIOV_NUM_VF 0x10 /* Number of VFs */
-#define PCI_SRIOV_FUNC_LINK 0x12 /* Function Dependency Link */
-#define PCI_SRIOV_VF_OFFSET 0x14 /* First VF Offset */
-#define PCI_SRIOV_VF_STRIDE 0x16 /* Following VF Stride */
-#define PCI_SRIOV_VF_DID 0x1a /* VF Device ID */
-#define PCI_SRIOV_SUP_PGSIZE 0x1c /* Supported Page Sizes */
-#define PCI_SRIOV_SYS_PGSIZE 0x20 /* System Page Size */
-#define PCI_SRIOV_BAR 0x24 /* VF BAR0 */
-#define PCI_SRIOV_NUM_BARS 6 /* Number of VF BARs */
-#define PCI_SRIOV_VFM 0x3c /* VF Migration State Array Offset*/
-#define PCI_SRIOV_VFM_BIR(x) ((x) & 7) /* State BIR */
-#define PCI_SRIOV_VFM_OFFSET(x) ((x) & ~7) /* State Offset */
-#define PCI_SRIOV_VFM_UA 0x0 /* Inactive.Unavailable */
-#define PCI_SRIOV_VFM_MI 0x1 /* Dormant.MigrateIn */
-#define PCI_SRIOV_VFM_MO 0x2 /* Active.MigrateOut */
-#define PCI_SRIOV_VFM_AV 0x3 /* Active.Available */
-#define PCI_EXT_CAP_SRIOV_SIZEOF 64
-
-#define PCI_LTR_MAX_SNOOP_LAT 0x4
-#define PCI_LTR_MAX_NOSNOOP_LAT 0x6
-#define PCI_LTR_VALUE_MASK 0x000003ff
-#define PCI_LTR_SCALE_MASK 0x00001c00
-#define PCI_LTR_SCALE_SHIFT 10
-#define PCI_EXT_CAP_LTR_SIZEOF 8
-
-/* Access Control Service */
-#define PCI_ACS_CAP 0x04 /* ACS Capability Register */
-#define PCI_ACS_SV 0x01 /* Source Validation */
-#define PCI_ACS_TB 0x02 /* Translation Blocking */
-#define PCI_ACS_RR 0x04 /* P2P Request Redirect */
-#define PCI_ACS_CR 0x08 /* P2P Completion Redirect */
-#define PCI_ACS_UF 0x10 /* Upstream Forwarding */
-#define PCI_ACS_EC 0x20 /* P2P Egress Control */
-#define PCI_ACS_DT 0x40 /* Direct Translated P2P */
-#define PCI_ACS_EGRESS_BITS 0x05 /* ACS Egress Control Vector Size */
-#define PCI_ACS_CTRL 0x06 /* ACS Control Register */
-#define PCI_ACS_EGRESS_CTL_V 0x08 /* ACS Egress Control Vector */
-
-#define PCI_VSEC_HDR 4 /* extended cap - vendor-specific */
-#define PCI_VSEC_HDR_LEN_SHIFT 20 /* shift for length field */
-
-/* SATA capability */
-#define PCI_SATA_REGS 4 /* SATA REGs specifier */
-#define PCI_SATA_REGS_MASK 0xF /* location - BAR#/inline */
-#define PCI_SATA_REGS_INLINE 0xF /* REGS in config space */
-#define PCI_SATA_SIZEOF_SHORT 8
-#define PCI_SATA_SIZEOF_LONG 16
-
-/* Resizable BARs */
-#define PCI_REBAR_CTRL 8 /* control register */
-#define PCI_REBAR_CTRL_NBAR_MASK (7 << 5) /* mask for # bars */
-#define PCI_REBAR_CTRL_NBAR_SHIFT 5 /* shift for # bars */
-
-/* Dynamic Power Allocation */
-#define PCI_DPA_CAP 4 /* capability register */
-#define PCI_DPA_CAP_SUBSTATE_MASK 0x1F /* # substates - 1 */
-#define PCI_DPA_BASE_SIZEOF 16 /* size with 0 substates */
-
-/* TPH Requester */
-#define PCI_TPH_CAP 4 /* capability register */
-#define PCI_TPH_CAP_LOC_MASK 0x600 /* location mask */
-#define PCI_TPH_LOC_NONE 0x000 /* no location */
-#define PCI_TPH_LOC_CAP 0x200 /* in capability */
-#define PCI_TPH_LOC_MSIX 0x400 /* in MSI-X */
-#define PCI_TPH_CAP_ST_MASK 0x07FF0000 /* st table mask */
-#define PCI_TPH_CAP_ST_SHIFT 16 /* st table shift */
-#define PCI_TPH_BASE_SIZEOF 12 /* size with no st table */
-
-#endif /* LINUX_PCI_REGS_H */
diff --git a/include/uapi/linux/v4l2-common.h b/include/uapi/linux/v4l2-common.h
index 1527398..2f6f8ca 100644
--- a/include/uapi/linux/v4l2-common.h
+++ b/include/uapi/linux/v4l2-common.h
@@ -43,8 +43,6 @@
#define V4L2_SEL_TGT_CROP_DEFAULT 0x0001
/* Cropping bounds */
#define V4L2_SEL_TGT_CROP_BOUNDS 0x0002
-/* Native frame size */
-#define V4L2_SEL_TGT_NATIVE_SIZE 0x0003
/* Current composing area */
#define V4L2_SEL_TGT_COMPOSE 0x0100
/* Default composing area */
diff --git a/include/uapi/linux/v4l2-dv-timings.h b/include/uapi/linux/v4l2-dv-timings.h
index 6c8f159..6a0764c 100644
--- a/include/uapi/linux/v4l2-dv-timings.h
+++ b/include/uapi/linux/v4l2-dv-timings.h
@@ -21,17 +21,8 @@
#ifndef _V4L2_DV_TIMINGS_H
#define _V4L2_DV_TIMINGS_H
-#if __GNUC__ < 4 || (__GNUC__ == 4 && (__GNUC_MINOR__ < 6))
-/* Sadly gcc versions older than 4.6 have a bug in how they initialize
- anonymous unions where they require additional curly brackets.
- This violates the C1x standard. This workaround adds the curly brackets
- if needed. */
#define V4L2_INIT_BT_TIMINGS(_width, args...) \
{ .bt = { _width , ## args } }
-#else
-#define V4L2_INIT_BT_TIMINGS(_width, args...) \
- .bt = { _width , ## args }
-#endif
/* CEA-861-E timings (i.e. standard HDTV timings) */
diff --git a/include/uapi/linux/v4l2-mediabus.h b/include/uapi/linux/v4l2-mediabus.h
index 26db206..1445e85 100644
--- a/include/uapi/linux/v4l2-mediabus.h
+++ b/include/uapi/linux/v4l2-mediabus.h
@@ -11,10 +11,122 @@
#ifndef __LINUX_V4L2_MEDIABUS_H
#define __LINUX_V4L2_MEDIABUS_H
-#include <linux/media-bus-format.h>
#include <linux/types.h>
#include <linux/videodev2.h>
+/*
+ * These pixel codes uniquely identify data formats on the media bus. Mostly
+ * they correspond to similarly named V4L2_PIX_FMT_* formats, format 0 is
+ * reserved, V4L2_MBUS_FMT_FIXED shall be used by host-client pairs, where the
+ * data format is fixed. Additionally, "2X8" means that one pixel is transferred
+ * in two 8-bit samples, "BE" or "LE" specify in which order those samples are
+ * transferred over the bus: "LE" means that the least significant bits are
+ * transferred first, "BE" means that the most significant bits are transferred
+ * first, and "PADHI" and "PADLO" define which bits - low or high, in the
+ * incomplete high byte, are filled with padding bits.
+ *
+ * The pixel codes are grouped by type, bus_width, bits per component, samples
+ * per pixel and order of subsamples. Numerical values are sorted using generic
+ * numerical sort order (8 thus comes before 10).
+ *
+ * As their value can't change when a new pixel code is inserted in the
+ * enumeration, the pixel codes are explicitly given a numerical value. The next
+ * free values for each category are listed below, update them when inserting
+ * new pixel codes.
+ */
+enum v4l2_mbus_pixelcode {
+ V4L2_MBUS_FMT_FIXED = 0x0001,
+
+ /* RGB - next is 0x100e */
+ V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE = 0x1001,
+ V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE = 0x1002,
+ V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE = 0x1003,
+ V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE = 0x1004,
+ V4L2_MBUS_FMT_BGR565_2X8_BE = 0x1005,
+ V4L2_MBUS_FMT_BGR565_2X8_LE = 0x1006,
+ V4L2_MBUS_FMT_RGB565_2X8_BE = 0x1007,
+ V4L2_MBUS_FMT_RGB565_2X8_LE = 0x1008,
+ V4L2_MBUS_FMT_RGB666_1X18 = 0x1009,
+ V4L2_MBUS_FMT_RGB888_1X24 = 0x100a,
+ V4L2_MBUS_FMT_RGB888_2X12_BE = 0x100b,
+ V4L2_MBUS_FMT_RGB888_2X12_LE = 0x100c,
+ V4L2_MBUS_FMT_ARGB8888_1X32 = 0x100d,
+
+ /* YUV (including grey) - next is 0x2024 */
+ V4L2_MBUS_FMT_Y8_1X8 = 0x2001,
+ V4L2_MBUS_FMT_UV8_1X8 = 0x2015,
+ V4L2_MBUS_FMT_UYVY8_1_5X8 = 0x2002,
+ V4L2_MBUS_FMT_VYUY8_1_5X8 = 0x2003,
+ V4L2_MBUS_FMT_YUYV8_1_5X8 = 0x2004,
+ V4L2_MBUS_FMT_YVYU8_1_5X8 = 0x2005,
+ V4L2_MBUS_FMT_UYVY8_2X8 = 0x2006,
+ V4L2_MBUS_FMT_VYUY8_2X8 = 0x2007,
+ V4L2_MBUS_FMT_YUYV8_2X8 = 0x2008,
+ V4L2_MBUS_FMT_YVYU8_2X8 = 0x2009,
+ V4L2_MBUS_FMT_Y10_1X10 = 0x200a,
+ V4L2_MBUS_FMT_UYVY10_2X10 = 0x2018,
+ V4L2_MBUS_FMT_VYUY10_2X10 = 0x2019,
+ V4L2_MBUS_FMT_YUYV10_2X10 = 0x200b,
+ V4L2_MBUS_FMT_YVYU10_2X10 = 0x200c,
+ V4L2_MBUS_FMT_Y12_1X12 = 0x2013,
+ V4L2_MBUS_FMT_UYVY8_1X16 = 0x200f,
+ V4L2_MBUS_FMT_VYUY8_1X16 = 0x2010,
+ V4L2_MBUS_FMT_YUYV8_1X16 = 0x2011,
+ V4L2_MBUS_FMT_YVYU8_1X16 = 0x2012,
+ V4L2_MBUS_FMT_YDYUYDYV8_1X16 = 0x2014,
+ V4L2_MBUS_FMT_UYVY10_1X20 = 0x201a,
+ V4L2_MBUS_FMT_VYUY10_1X20 = 0x201b,
+ V4L2_MBUS_FMT_YUYV10_1X20 = 0x200d,
+ V4L2_MBUS_FMT_YVYU10_1X20 = 0x200e,
+ V4L2_MBUS_FMT_YUV10_1X30 = 0x2016,
+ V4L2_MBUS_FMT_AYUV8_1X32 = 0x2017,
+ V4L2_MBUS_FMT_UYVY12_2X12 = 0x201c,
+ V4L2_MBUS_FMT_VYUY12_2X12 = 0x201d,
+ V4L2_MBUS_FMT_YUYV12_2X12 = 0x201e,
+ V4L2_MBUS_FMT_YVYU12_2X12 = 0x201f,
+ V4L2_MBUS_FMT_UYVY12_1X24 = 0x2020,
+ V4L2_MBUS_FMT_VYUY12_1X24 = 0x2021,
+ V4L2_MBUS_FMT_YUYV12_1X24 = 0x2022,
+ V4L2_MBUS_FMT_YVYU12_1X24 = 0x2023,
+
+ /* Bayer - next is 0x3019 */
+ V4L2_MBUS_FMT_SBGGR8_1X8 = 0x3001,
+ V4L2_MBUS_FMT_SGBRG8_1X8 = 0x3013,
+ V4L2_MBUS_FMT_SGRBG8_1X8 = 0x3002,
+ V4L2_MBUS_FMT_SRGGB8_1X8 = 0x3014,
+ V4L2_MBUS_FMT_SBGGR10_ALAW8_1X8 = 0x3015,
+ V4L2_MBUS_FMT_SGBRG10_ALAW8_1X8 = 0x3016,
+ V4L2_MBUS_FMT_SGRBG10_ALAW8_1X8 = 0x3017,
+ V4L2_MBUS_FMT_SRGGB10_ALAW8_1X8 = 0x3018,
+ V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8 = 0x300b,
+ V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8 = 0x300c,
+ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8 = 0x3009,
+ V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8 = 0x300d,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE = 0x3003,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE = 0x3004,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE = 0x3005,
+ V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE = 0x3006,
+ V4L2_MBUS_FMT_SBGGR10_1X10 = 0x3007,
+ V4L2_MBUS_FMT_SGBRG10_1X10 = 0x300e,
+ V4L2_MBUS_FMT_SGRBG10_1X10 = 0x300a,
+ V4L2_MBUS_FMT_SRGGB10_1X10 = 0x300f,
+ V4L2_MBUS_FMT_SBGGR12_1X12 = 0x3008,
+ V4L2_MBUS_FMT_SGBRG12_1X12 = 0x3010,
+ V4L2_MBUS_FMT_SGRBG12_1X12 = 0x3011,
+ V4L2_MBUS_FMT_SRGGB12_1X12 = 0x3012,
+
+ /* JPEG compressed formats - next is 0x4002 */
+ V4L2_MBUS_FMT_JPEG_1X8 = 0x4001,
+
+ /* Vendor specific formats - next is 0x5002 */
+
+ /* S5C73M3 sensor specific interleaved UYVY and JPEG */
+ V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8 = 0x5001,
+
+ /* HSV - next is 0x6002 */
+ V4L2_MBUS_FMT_AHSV8888_1X32 = 0x6001,
+};
+
/**
* struct v4l2_mbus_framefmt - frame format on the media bus
* @width: frame width
@@ -22,8 +134,6 @@
* @code: data format code (from enum v4l2_mbus_pixelcode)
* @field: used interlacing type (from enum v4l2_field)
* @colorspace: colorspace of the data (from enum v4l2_colorspace)
- * @ycbcr_enc: YCbCr encoding of the data (from enum v4l2_ycbcr_encoding)
- * @quantization: quantization of the data (from enum v4l2_quantization)
*/
struct v4l2_mbus_framefmt {
__u32 width;
@@ -31,108 +141,7 @@
__u32 code;
__u32 field;
__u32 colorspace;
- __u16 ycbcr_enc;
- __u16 quantization;
- __u32 reserved[6];
+ __u32 reserved[7];
};
-#ifndef __KERNEL__
-/*
- * enum v4l2_mbus_pixelcode and its definitions are now deprecated, and
- * MEDIA_BUS_FMT_ definitions (defined in media-bus-format.h) should be
- * used instead.
- *
- * New defines should only be added to media-bus-format.h. The
- * v4l2_mbus_pixelcode enum is frozen.
- */
-
-#define V4L2_MBUS_FROM_MEDIA_BUS_FMT(name) \
- V4L2_MBUS_FMT_ ## name = MEDIA_BUS_FMT_ ## name
-
-enum v4l2_mbus_pixelcode {
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(FIXED),
-
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB444_2X8_PADHI_BE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB444_2X8_PADHI_LE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB555_2X8_PADHI_BE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB555_2X8_PADHI_LE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(BGR565_2X8_BE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(BGR565_2X8_LE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB565_2X8_BE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB565_2X8_LE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB666_1X18),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB888_1X24),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB888_2X12_BE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(RGB888_2X12_LE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(ARGB8888_1X32),
-
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(Y8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(UV8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY8_1_5X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY8_1_5X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV8_1_5X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU8_1_5X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY8_2X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY8_2X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV8_2X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU8_2X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(Y10_1X10),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY10_2X10),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY10_2X10),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV10_2X10),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU10_2X10),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(Y12_1X12),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY8_1X16),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY8_1X16),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV8_1X16),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU8_1X16),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YDYUYDYV8_1X16),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY10_1X20),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY10_1X20),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV10_1X20),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU10_1X20),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUV10_1X30),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(AYUV8_1X32),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY12_2X12),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY12_2X12),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV12_2X12),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU12_2X12),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(UYVY12_1X24),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(VYUY12_1X24),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YUYV12_1X24),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(YVYU12_1X24),
-
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_ALAW8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG10_ALAW8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG10_ALAW8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB10_ALAW8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_DPCM8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG10_DPCM8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG10_DPCM8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB10_DPCM8_1X8),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_2X8_PADHI_BE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_2X8_PADHI_LE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_2X8_PADLO_BE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_2X8_PADLO_LE),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR10_1X10),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG10_1X10),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG10_1X10),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB10_1X10),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SBGGR12_1X12),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGBRG12_1X12),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SGRBG12_1X12),
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(SRGGB12_1X12),
-
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(JPEG_1X8),
-
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(S5C_UYVY_JPEG_1X8),
-
- V4L2_MBUS_FROM_MEDIA_BUS_FMT(AHSV8888_1X32),
-};
-#endif /* __KERNEL__ */
-
#endif
diff --git a/include/uapi/linux/v4l2-subdev.h b/include/uapi/linux/v4l2-subdev.h
index e0a7e3d..a619cdd 100644
--- a/include/uapi/linux/v4l2-subdev.h
+++ b/include/uapi/linux/v4l2-subdev.h
@@ -68,7 +68,7 @@
* struct v4l2_subdev_mbus_code_enum - Media bus format enumeration
* @pad: pad number, as reported by the media API
* @index: format index during enumeration
- * @code: format code (MEDIA_BUS_FMT_ definitions)
+ * @code: format code (from enum v4l2_mbus_pixelcode)
*/
struct v4l2_subdev_mbus_code_enum {
__u32 pad;
@@ -81,7 +81,7 @@
* struct v4l2_subdev_frame_size_enum - Media bus format enumeration
* @pad: pad number, as reported by the media API
* @index: format index during enumeration
- * @code: format code (MEDIA_BUS_FMT_ definitions)
+ * @code: format code (from enum v4l2_mbus_pixelcode)
*/
struct v4l2_subdev_frame_size_enum {
__u32 index;
@@ -109,7 +109,7 @@
* struct v4l2_subdev_frame_interval_enum - Frame interval enumeration
* @pad: pad number, as reported by the media API
* @index: frame interval index during enumeration
- * @code: format code (MEDIA_BUS_FMT_ definitions)
+ * @code: format code (from enum v4l2_mbus_pixelcode)
* @width: frame width in pixels
* @height: frame height in pixels
* @interval: frame interval in seconds
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 7a26b65..accc4ef 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -178,103 +178,30 @@
/* see also http://vektor.theorem.ca/graphics/ycbcr/ */
enum v4l2_colorspace {
- /* SMPTE 170M: used for broadcast NTSC/PAL SDTV */
+ /* ITU-R 601 -- broadcast NTSC/PAL */
V4L2_COLORSPACE_SMPTE170M = 1,
- /* Obsolete pre-1998 SMPTE 240M HDTV standard, superseded by Rec 709 */
+ /* 1125-Line (US) HDTV */
V4L2_COLORSPACE_SMPTE240M = 2,
- /* Rec.709: used for HDTV */
+ /* HD and modern captures. */
V4L2_COLORSPACE_REC709 = 3,
- /*
- * Deprecated, do not use. No driver will ever return this. This was
- * based on a misunderstanding of the bt878 datasheet.
- */
+ /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */
V4L2_COLORSPACE_BT878 = 4,
- /*
- * NTSC 1953 colorspace. This only makes sense when dealing with
- * really, really old NTSC recordings. Superseded by SMPTE 170M.
- */
+ /* These should be useful. Assume 601 extents. */
V4L2_COLORSPACE_470_SYSTEM_M = 5,
-
- /*
- * EBU Tech 3213 PAL/SECAM colorspace. This only makes sense when
- * dealing with really old PAL/SECAM recordings. Superseded by
- * SMPTE 170M.
- */
V4L2_COLORSPACE_470_SYSTEM_BG = 6,
- /*
- * Effectively shorthand for V4L2_COLORSPACE_SRGB, V4L2_YCBCR_ENC_601
- * and V4L2_QUANTIZATION_FULL_RANGE. To be used for (Motion-)JPEG.
+ /* I know there will be cameras that send this. So, this is
+ * unspecified chromaticities and full 0-255 on each of the
+ * Y'CbCr components
*/
V4L2_COLORSPACE_JPEG = 7,
- /* For RGB colorspaces such as produces by most webcams. */
+ /* For RGB colourspaces, this is probably a good start. */
V4L2_COLORSPACE_SRGB = 8,
-
- /* AdobeRGB colorspace */
- V4L2_COLORSPACE_ADOBERGB = 9,
-
- /* BT.2020 colorspace, used for UHDTV. */
- V4L2_COLORSPACE_BT2020 = 10,
-};
-
-enum v4l2_ycbcr_encoding {
- /*
- * Mapping of V4L2_YCBCR_ENC_DEFAULT to actual encodings for the
- * various colorspaces:
- *
- * V4L2_COLORSPACE_SMPTE170M, V4L2_COLORSPACE_470_SYSTEM_M,
- * V4L2_COLORSPACE_470_SYSTEM_BG, V4L2_COLORSPACE_ADOBERGB and
- * V4L2_COLORSPACE_JPEG: V4L2_YCBCR_ENC_601
- *
- * V4L2_COLORSPACE_REC709: V4L2_YCBCR_ENC_709
- *
- * V4L2_COLORSPACE_SRGB: V4L2_YCBCR_ENC_SYCC
- *
- * V4L2_COLORSPACE_BT2020: V4L2_YCBCR_ENC_BT2020
- *
- * V4L2_COLORSPACE_SMPTE240M: V4L2_YCBCR_ENC_SMPTE240M
- */
- V4L2_YCBCR_ENC_DEFAULT = 0,
-
- /* ITU-R 601 -- SDTV */
- V4L2_YCBCR_ENC_601 = 1,
-
- /* Rec. 709 -- HDTV */
- V4L2_YCBCR_ENC_709 = 2,
-
- /* ITU-R 601/EN 61966-2-4 Extended Gamut -- SDTV */
- V4L2_YCBCR_ENC_XV601 = 3,
-
- /* Rec. 709/EN 61966-2-4 Extended Gamut -- HDTV */
- V4L2_YCBCR_ENC_XV709 = 4,
-
- /* sYCC (Y'CbCr encoding of sRGB) */
- V4L2_YCBCR_ENC_SYCC = 5,
-
- /* BT.2020 Non-constant Luminance Y'CbCr */
- V4L2_YCBCR_ENC_BT2020 = 6,
-
- /* BT.2020 Constant Luminance Y'CbcCrc */
- V4L2_YCBCR_ENC_BT2020_CONST_LUM = 7,
-
- /* SMPTE 240M -- Obsolete HDTV */
- V4L2_YCBCR_ENC_SMPTE240M = 8,
-};
-
-enum v4l2_quantization {
- /*
- * The default for R'G'B' quantization is always full range. For
- * Y'CbCr the quantization is always limited range, except for
- * SYCC, XV601, XV709 or JPEG: those are full range.
- */
- V4L2_QUANTIZATION_DEFAULT = 0,
- V4L2_QUANTIZATION_FULL_RANGE = 1,
- V4L2_QUANTIZATION_LIM_RANGE = 2,
};
enum v4l2_priority {
@@ -367,8 +294,6 @@
__u32 colorspace; /* enum v4l2_colorspace */
__u32 priv; /* private data, depends on pixelformat */
__u32 flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */
- __u32 ycbcr_enc; /* enum v4l2_ycbcr_encoding */
- __u32 quantization; /* enum v4l2_quantization */
};
/* Pixel format FOURCC depth Description */
@@ -1324,7 +1249,6 @@
#define V4L2_IN_CAP_DV_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */
#define V4L2_IN_CAP_CUSTOM_TIMINGS V4L2_IN_CAP_DV_TIMINGS /* For compatibility */
#define V4L2_IN_CAP_STD 0x00000004 /* Supports S_STD */
-#define V4L2_IN_CAP_NATIVE_SIZE 0x00000008 /* Supports setting native size */
/*
* V I D E O O U T P U T S
@@ -1348,7 +1272,6 @@
#define V4L2_OUT_CAP_DV_TIMINGS 0x00000002 /* Supports S_DV_TIMINGS */
#define V4L2_OUT_CAP_CUSTOM_TIMINGS V4L2_OUT_CAP_DV_TIMINGS /* For compatibility */
#define V4L2_OUT_CAP_STD 0x00000004 /* Supports S_STD */
-#define V4L2_OUT_CAP_NATIVE_SIZE 0x00000008 /* Supports setting native size */
/*
* C O N T R O L S
@@ -1854,8 +1777,6 @@
* @plane_fmt: per-plane information
* @num_planes: number of planes for this format
* @flags: format flags (V4L2_PIX_FMT_FLAG_*)
- * @ycbcr_enc: enum v4l2_ycbcr_encoding, Y'CbCr encoding
- * @quantization: enum v4l2_quantization, colorspace quantization
*/
struct v4l2_pix_format_mplane {
__u32 width;
@@ -1867,9 +1788,7 @@
struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES];
__u8 num_planes;
__u8 flags;
- __u8 ycbcr_enc;
- __u8 quantization;
- __u8 reserved[8];
+ __u8 reserved[10];
} __attribute__ ((packed));
/**
diff --git a/kconf/Makefile b/kconf/Makefile
index 9edd957..b307c65 100644
--- a/kconf/Makefile
+++ b/kconf/Makefile
@@ -3,12 +3,9 @@
LXDIALOG := lxdialog/checklist.o lxdialog/inputbox.o lxdialog/menubox.o lxdialog/textbox.o lxdialog/util.o lxdialog/yesno.o
conf: conf.o zconf.tab.o
-mconf_CFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ccflags) -DLOCALE
-mconf_LDFLAGS := $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
-mconf: CFLAGS += $(mconf_CFLAGS)
-
+mconf: LDFLAGS = -Wl,--add-needed $(shell ./lxdialog/check-lxdialog.sh -ldflags $(CC))
+mconf: CFLAGS += -DCURSES_LOC="<ncurses.h>" -DLOCALE
mconf: mconf.o zconf.tab.o $(LXDIALOG)
- $(CC) -o mconf $^ $(mconf_LDFLAGS)
.PHONY: clean
clean:
diff --git a/net/6lowpan/Kconfig b/net/6lowpan/Kconfig
deleted file mode 100644
index cb540f5..0000000
--- a/net/6lowpan/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config 6LOWPAN
- tristate "6LoWPAN Support"
- depends on m
- depends on IPV6
- ---help---
- This enables IPv6 over Low power Wireless Personal Area Network -
- "6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks.
diff --git a/net/6lowpan/Makefile b/net/6lowpan/Makefile
deleted file mode 100644
index 0f2fd34..0000000
--- a/net/6lowpan/Makefile
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CPTCFG_6LOWPAN) := 6lowpan.o
-
-6lowpan-y := iphc.o
diff --git a/net/6lowpan/iphc.c b/net/6lowpan/iphc.c
deleted file mode 100644
index 32ffec6..0000000
--- a/net/6lowpan/iphc.c
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * Copyright 2011, Siemens AG
- * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
- */
-
-/* Based on patches from Jon Smirl <jonsmirl@gmail.com>
- * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
- *
- * 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.
- *
- */
-
-/* Jon's code is based on 6lowpan implementation for Contiki which is:
- * Copyright (c) 2008, Swedish Institute of Computer Science.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <linux/bitops.h>
-#include <linux/if_arp.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-#include <net/6lowpan.h>
-#include <net/ipv6.h>
-#include <net/af_ieee802154.h>
-
-/* Uncompress address function for source and
- * destination address(non-multicast).
- *
- * address_mode is sam value or dam value.
- */
-static int uncompress_addr(struct sk_buff *skb,
- struct in6_addr *ipaddr, const u8 address_mode,
- const u8 *lladdr, const u8 addr_type,
- const u8 addr_len)
-{
- bool fail;
-
- switch (address_mode) {
- case LOWPAN_IPHC_ADDR_00:
- /* for global link addresses */
- fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
- break;
- case LOWPAN_IPHC_ADDR_01:
- /* fe:80::XXXX:XXXX:XXXX:XXXX */
- ipaddr->s6_addr[0] = 0xFE;
- ipaddr->s6_addr[1] = 0x80;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[8], 8);
- break;
- case LOWPAN_IPHC_ADDR_02:
- /* fe:80::ff:fe00:XXXX */
- ipaddr->s6_addr[0] = 0xFE;
- ipaddr->s6_addr[1] = 0x80;
- ipaddr->s6_addr[11] = 0xFF;
- ipaddr->s6_addr[12] = 0xFE;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[14], 2);
- break;
- case LOWPAN_IPHC_ADDR_03:
- fail = false;
- switch (addr_type) {
- case IEEE802154_ADDR_LONG:
- /* fe:80::XXXX:XXXX:XXXX:XXXX
- * \_________________/
- * hwaddr
- */
- ipaddr->s6_addr[0] = 0xFE;
- ipaddr->s6_addr[1] = 0x80;
- memcpy(&ipaddr->s6_addr[8], lladdr, addr_len);
- /* second bit-flip (Universe/Local)
- * is done according RFC2464
- */
- ipaddr->s6_addr[8] ^= 0x02;
- break;
- case IEEE802154_ADDR_SHORT:
- /* fe:80::ff:fe00:XXXX
- * \__/
- * short_addr
- *
- * Universe/Local bit is zero.
- */
- ipaddr->s6_addr[0] = 0xFE;
- ipaddr->s6_addr[1] = 0x80;
- ipaddr->s6_addr[11] = 0xFF;
- ipaddr->s6_addr[12] = 0xFE;
- ipaddr->s6_addr16[7] = htons(*((u16 *)lladdr));
- break;
- default:
- pr_debug("Invalid addr_type set\n");
- return -EINVAL;
- }
- break;
- default:
- pr_debug("Invalid address mode value: 0x%x\n", address_mode);
- return -EINVAL;
- }
-
- if (fail) {
- pr_debug("Failed to fetch skb data\n");
- return -EIO;
- }
-
- raw_dump_inline(NULL, "Reconstructed ipv6 addr is",
- ipaddr->s6_addr, 16);
-
- return 0;
-}
-
-/* Uncompress address function for source context
- * based address(non-multicast).
- */
-static int uncompress_context_based_src_addr(struct sk_buff *skb,
- struct in6_addr *ipaddr,
- const u8 sam)
-{
- switch (sam) {
- case LOWPAN_IPHC_ADDR_00:
- /* unspec address ::
- * Do nothing, address is already ::
- */
- break;
- case LOWPAN_IPHC_ADDR_01:
- /* TODO */
- case LOWPAN_IPHC_ADDR_02:
- /* TODO */
- case LOWPAN_IPHC_ADDR_03:
- /* TODO */
- netdev_warn(skb->dev, "SAM value 0x%x not supported\n", sam);
- return -EINVAL;
- default:
- pr_debug("Invalid sam value: 0x%x\n", sam);
- return -EINVAL;
- }
-
- raw_dump_inline(NULL,
- "Reconstructed context based ipv6 src addr is",
- ipaddr->s6_addr, 16);
-
- return 0;
-}
-
-/* Uncompress function for multicast destination address,
- * when M bit is set.
- */
-static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb,
- struct in6_addr *ipaddr,
- const u8 dam)
-{
- bool fail;
-
- switch (dam) {
- case LOWPAN_IPHC_DAM_00:
- /* 00: 128 bits. The full address
- * is carried in-line.
- */
- fail = lowpan_fetch_skb(skb, ipaddr->s6_addr, 16);
- break;
- case LOWPAN_IPHC_DAM_01:
- /* 01: 48 bits. The address takes
- * the form ffXX::00XX:XXXX:XXXX.
- */
- ipaddr->s6_addr[0] = 0xFF;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
- fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[11], 5);
- break;
- case LOWPAN_IPHC_DAM_10:
- /* 10: 32 bits. The address takes
- * the form ffXX::00XX:XXXX.
- */
- ipaddr->s6_addr[0] = 0xFF;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[1], 1);
- fail |= lowpan_fetch_skb(skb, &ipaddr->s6_addr[13], 3);
- break;
- case LOWPAN_IPHC_DAM_11:
- /* 11: 8 bits. The address takes
- * the form ff02::00XX.
- */
- ipaddr->s6_addr[0] = 0xFF;
- ipaddr->s6_addr[1] = 0x02;
- fail = lowpan_fetch_skb(skb, &ipaddr->s6_addr[15], 1);
- break;
- default:
- pr_debug("DAM value has a wrong value: 0x%x\n", dam);
- return -EINVAL;
- }
-
- if (fail) {
- pr_debug("Failed to fetch skb data\n");
- return -EIO;
- }
-
- raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is",
- ipaddr->s6_addr, 16);
-
- return 0;
-}
-
-static int uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh)
-{
- bool fail;
- u8 tmp = 0, val = 0;
-
- fail = lowpan_fetch_skb(skb, &tmp, sizeof(tmp));
-
- if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) {
- pr_debug("UDP header uncompression\n");
- switch (tmp & LOWPAN_NHC_UDP_CS_P_11) {
- case LOWPAN_NHC_UDP_CS_P_00:
- fail |= lowpan_fetch_skb(skb, &uh->source,
- sizeof(uh->source));
- fail |= lowpan_fetch_skb(skb, &uh->dest,
- sizeof(uh->dest));
- break;
- case LOWPAN_NHC_UDP_CS_P_01:
- fail |= lowpan_fetch_skb(skb, &uh->source,
- sizeof(uh->source));
- fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
- uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
- break;
- case LOWPAN_NHC_UDP_CS_P_10:
- fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
- uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT);
- fail |= lowpan_fetch_skb(skb, &uh->dest,
- sizeof(uh->dest));
- break;
- case LOWPAN_NHC_UDP_CS_P_11:
- fail |= lowpan_fetch_skb(skb, &val, sizeof(val));
- uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT +
- (val >> 4));
- uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT +
- (val & 0x0f));
- break;
- default:
- pr_debug("ERROR: unknown UDP format\n");
- goto err;
- }
-
- pr_debug("uncompressed UDP ports: src = %d, dst = %d\n",
- ntohs(uh->source), ntohs(uh->dest));
-
- /* checksum */
- if (tmp & LOWPAN_NHC_UDP_CS_C) {
- pr_debug_ratelimited("checksum elided currently not supported\n");
- goto err;
- } else {
- fail |= lowpan_fetch_skb(skb, &uh->check,
- sizeof(uh->check));
- }
-
- /* UDP length needs to be infered from the lower layers
- * here, we obtain the hint from the remaining size of the
- * frame
- */
- uh->len = htons(skb->len + sizeof(struct udphdr));
- pr_debug("uncompressed UDP length: src = %d", ntohs(uh->len));
- } else {
- pr_debug("ERROR: unsupported NH format\n");
- goto err;
- }
-
- if (fail)
- goto err;
-
- return 0;
-err:
- return -EINVAL;
-}
-
-/* TTL uncompression values */
-static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 };
-
-int
-lowpan_header_decompress(struct sk_buff *skb, struct net_device *dev,
- const u8 *saddr, const u8 saddr_type,
- const u8 saddr_len, const u8 *daddr,
- const u8 daddr_type, const u8 daddr_len,
- u8 iphc0, u8 iphc1)
-{
- struct ipv6hdr hdr = {};
- u8 tmp, num_context = 0;
- int err;
-
- raw_dump_table(__func__, "raw skb data dump uncompressed",
- skb->data, skb->len);
-
- /* another if the CID flag is set */
- if (iphc1 & LOWPAN_IPHC_CID) {
- pr_debug("CID flag is set, increase header with one\n");
- if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context)))
- return -EINVAL;
- }
-
- hdr.version = 6;
-
- /* Traffic Class and Flow Label */
- switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) {
- /* Traffic Class and FLow Label carried in-line
- * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes)
- */
- case 0: /* 00b */
- if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
- return -EINVAL;
-
- memcpy(&hdr.flow_lbl, &skb->data[0], 3);
- skb_pull(skb, 3);
- hdr.priority = ((tmp >> 2) & 0x0f);
- hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) |
- (hdr.flow_lbl[0] & 0x0f);
- break;
- /* Traffic class carried in-line
- * ECN + DSCP (1 byte), Flow Label is elided
- */
- case 2: /* 10b */
- if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
- return -EINVAL;
-
- hdr.priority = ((tmp >> 2) & 0x0f);
- hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30);
- break;
- /* Flow Label carried in-line
- * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided
- */
- case 1: /* 01b */
- if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp)))
- return -EINVAL;
-
- hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30);
- memcpy(&hdr.flow_lbl[1], &skb->data[0], 2);
- skb_pull(skb, 2);
- break;
- /* Traffic Class and Flow Label are elided */
- case 3: /* 11b */
- break;
- default:
- break;
- }
-
- /* Next Header */
- if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) {
- /* Next header is carried inline */
- if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr)))
- return -EINVAL;
-
- pr_debug("NH flag is set, next header carried inline: %02x\n",
- hdr.nexthdr);
- }
-
- /* Hop Limit */
- if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) {
- hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03];
- } else {
- if (lowpan_fetch_skb(skb, &hdr.hop_limit,
- sizeof(hdr.hop_limit)))
- return -EINVAL;
- }
-
- /* Extract SAM to the tmp variable */
- tmp = ((iphc1 & LOWPAN_IPHC_SAM) >> LOWPAN_IPHC_SAM_BIT) & 0x03;
-
- if (iphc1 & LOWPAN_IPHC_SAC) {
- /* Source address context based uncompression */
- pr_debug("SAC bit is set. Handle context based source address.\n");
- err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp);
- } else {
- /* Source address uncompression */
- pr_debug("source address stateless compression\n");
- err = uncompress_addr(skb, &hdr.saddr, tmp, saddr,
- saddr_type, saddr_len);
- }
-
- /* Check on error of previous branch */
- if (err)
- return -EINVAL;
-
- /* Extract DAM to the tmp variable */
- tmp = ((iphc1 & LOWPAN_IPHC_DAM_11) >> LOWPAN_IPHC_DAM_BIT) & 0x03;
-
- /* check for Multicast Compression */
- if (iphc1 & LOWPAN_IPHC_M) {
- if (iphc1 & LOWPAN_IPHC_DAC) {
- pr_debug("dest: context-based mcast compression\n");
- /* TODO: implement this */
- } else {
- err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr,
- tmp);
-
- if (err)
- return -EINVAL;
- }
- } else {
- err = uncompress_addr(skb, &hdr.daddr, tmp, daddr,
- daddr_type, daddr_len);
- pr_debug("dest: stateless compression mode %d dest %pI6c\n",
- tmp, &hdr.daddr);
- if (err)
- return -EINVAL;
- }
-
- /* UDP data uncompression */
- if (iphc0 & LOWPAN_IPHC_NH_C) {
- struct udphdr uh;
- const int needed = sizeof(struct udphdr) + sizeof(hdr);
-
- if (uncompress_udp_header(skb, &uh))
- return -EINVAL;
-
- /* replace the compressed UDP head by the uncompressed UDP
- * header
- */
- err = skb_cow(skb, needed);
- if (unlikely(err))
- return err;
-
- skb_push(skb, sizeof(struct udphdr));
- skb_reset_transport_header(skb);
- skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr));
-
- raw_dump_table(__func__, "raw UDP header dump",
- (u8 *)&uh, sizeof(uh));
-
- hdr.nexthdr = UIP_PROTO_UDP;
- } else {
- err = skb_cow(skb, sizeof(hdr));
- if (unlikely(err))
- return err;
- }
-
- hdr.payload_len = htons(skb->len);
-
- pr_debug("skb headroom size = %d, data length = %d\n",
- skb_headroom(skb), skb->len);
-
- pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n\t"
- "nexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
- hdr.version, ntohs(hdr.payload_len), hdr.nexthdr,
- hdr.hop_limit, &hdr.daddr);
-
- skb_push(skb, sizeof(hdr));
- skb_reset_network_header(skb);
- skb_copy_to_linear_data(skb, &hdr, sizeof(hdr));
-
- raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr));
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(lowpan_header_decompress);
-
-static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift,
- const struct in6_addr *ipaddr,
- const unsigned char *lladdr)
-{
- u8 val = 0;
-
- if (is_addr_mac_addr_based(ipaddr, lladdr)) {
- val = 3; /* 0-bits */
- pr_debug("address compression 0 bits\n");
- } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) {
- /* compress IID to 16 bits xxxx::XXXX */
- lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2);
- val = 2; /* 16-bits */
- raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)",
- *hc_ptr - 2, 2);
- } else {
- /* do not compress IID => xxxx::IID */
- lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8);
- val = 1; /* 64-bits */
- raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)",
- *hc_ptr - 8, 8);
- }
-
- return rol8(val, shift);
-}
-
-static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb)
-{
- struct udphdr *uh;
- u8 tmp;
-
- /* In the case of RAW sockets the transport header is not set by
- * the ip6 stack so we must set it ourselves
- */
- if (skb->transport_header == skb->network_header)
- skb_set_transport_header(skb, sizeof(struct ipv6hdr));
-
- uh = udp_hdr(skb);
-
- if (((ntohs(uh->source) & LOWPAN_NHC_UDP_4BIT_MASK) ==
- LOWPAN_NHC_UDP_4BIT_PORT) &&
- ((ntohs(uh->dest) & LOWPAN_NHC_UDP_4BIT_MASK) ==
- LOWPAN_NHC_UDP_4BIT_PORT)) {
- pr_debug("UDP header: both ports compression to 4 bits\n");
- /* compression value */
- tmp = LOWPAN_NHC_UDP_CS_P_11;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* source and destination port */
- tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT +
- ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4);
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) ==
- LOWPAN_NHC_UDP_8BIT_PORT) {
- pr_debug("UDP header: remove 8 bits of dest\n");
- /* compression value */
- tmp = LOWPAN_NHC_UDP_CS_P_01;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* source port */
- lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
- /* destination port */
- tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) ==
- LOWPAN_NHC_UDP_8BIT_PORT) {
- pr_debug("UDP header: remove 8 bits of source\n");
- /* compression value */
- tmp = LOWPAN_NHC_UDP_CS_P_10;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* source port */
- tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* destination port */
- lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
- } else {
- pr_debug("UDP header: can't compress\n");
- /* compression value */
- tmp = LOWPAN_NHC_UDP_CS_P_00;
- lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp));
- /* source port */
- lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source));
- /* destination port */
- lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest));
- }
-
- /* checksum is always inline */
- lowpan_push_hc_data(hc_ptr, &uh->check, sizeof(uh->check));
-
- /* skip the UDP header */
- skb_pull(skb, sizeof(struct udphdr));
-}
-
-int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev,
- unsigned short type, const void *_daddr,
- const void *_saddr, unsigned int len)
-{
- u8 tmp, iphc0, iphc1, *hc_ptr;
- struct ipv6hdr *hdr;
- u8 head[100] = {};
- int addr_type;
-
- if (type != ETH_P_IPV6)
- return -EINVAL;
-
- hdr = ipv6_hdr(skb);
- hc_ptr = head + 2;
-
- pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n"
- "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n",
- hdr->version, ntohs(hdr->payload_len), hdr->nexthdr,
- hdr->hop_limit, &hdr->daddr);
-
- raw_dump_table(__func__, "raw skb network header dump",
- skb_network_header(skb), sizeof(struct ipv6hdr));
-
- /* As we copy some bit-length fields, in the IPHC encoding bytes,
- * we sometimes use |=
- * If the field is 0, and the current bit value in memory is 1,
- * this does not work. We therefore reset the IPHC encoding here
- */
- iphc0 = LOWPAN_DISPATCH_IPHC;
- iphc1 = 0;
-
- /* TODO: context lookup */
-
- raw_dump_inline(__func__, "saddr",
- (unsigned char *)_saddr, IEEE802154_ADDR_LEN);
- raw_dump_inline(__func__, "daddr",
- (unsigned char *)_daddr, IEEE802154_ADDR_LEN);
-
- raw_dump_table(__func__, "sending raw skb network uncompressed packet",
- skb->data, skb->len);
-
- /* Traffic class, flow label
- * If flow label is 0, compress it. If traffic class is 0, compress it
- * We have to process both in the same time as the offset of traffic
- * class depends on the presence of version and flow label
- */
-
- /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */
- tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4);
- tmp = ((tmp & 0x03) << 6) | (tmp >> 2);
-
- if (((hdr->flow_lbl[0] & 0x0F) == 0) &&
- (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) {
- /* flow label can be compressed */
- iphc0 |= LOWPAN_IPHC_FL_C;
- if ((hdr->priority == 0) &&
- ((hdr->flow_lbl[0] & 0xF0) == 0)) {
- /* compress (elide) all */
- iphc0 |= LOWPAN_IPHC_TC_C;
- } else {
- /* compress only the flow label */
- *hc_ptr = tmp;
- hc_ptr += 1;
- }
- } else {
- /* Flow label cannot be compressed */
- if ((hdr->priority == 0) &&
- ((hdr->flow_lbl[0] & 0xF0) == 0)) {
- /* compress only traffic class */
- iphc0 |= LOWPAN_IPHC_TC_C;
- *hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F);
- memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2);
- hc_ptr += 3;
- } else {
- /* compress nothing */
- memcpy(hc_ptr, hdr, 4);
- /* replace the top byte with new ECN | DSCP format */
- *hc_ptr = tmp;
- hc_ptr += 4;
- }
- }
-
- /* NOTE: payload length is always compressed */
-
- /* Next Header is compress if UDP */
- if (hdr->nexthdr == UIP_PROTO_UDP)
- iphc0 |= LOWPAN_IPHC_NH_C;
-
- if ((iphc0 & LOWPAN_IPHC_NH_C) == 0)
- lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr,
- sizeof(hdr->nexthdr));
-
- /* Hop limit
- * if 1: compress, encoding is 01
- * if 64: compress, encoding is 10
- * if 255: compress, encoding is 11
- * else do not compress
- */
- switch (hdr->hop_limit) {
- case 1:
- iphc0 |= LOWPAN_IPHC_TTL_1;
- break;
- case 64:
- iphc0 |= LOWPAN_IPHC_TTL_64;
- break;
- case 255:
- iphc0 |= LOWPAN_IPHC_TTL_255;
- break;
- default:
- lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit,
- sizeof(hdr->hop_limit));
- }
-
- addr_type = ipv6_addr_type(&hdr->saddr);
- /* source address compression */
- if (addr_type == IPV6_ADDR_ANY) {
- pr_debug("source address is unspecified, setting SAC\n");
- iphc1 |= LOWPAN_IPHC_SAC;
- } else {
- if (addr_type & IPV6_ADDR_LINKLOCAL) {
- iphc1 |= lowpan_compress_addr_64(&hc_ptr,
- LOWPAN_IPHC_SAM_BIT,
- &hdr->saddr, _saddr);
- pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n",
- &hdr->saddr, iphc1);
- } else {
- pr_debug("send the full source address\n");
- lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16);
- }
- }
-
- addr_type = ipv6_addr_type(&hdr->daddr);
- /* destination address compression */
- if (addr_type & IPV6_ADDR_MULTICAST) {
- pr_debug("destination address is multicast: ");
- iphc1 |= LOWPAN_IPHC_M;
- if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) {
- pr_debug("compressed to 1 octet\n");
- iphc1 |= LOWPAN_IPHC_DAM_11;
- /* use last byte */
- lowpan_push_hc_data(&hc_ptr,
- &hdr->daddr.s6_addr[15], 1);
- } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) {
- pr_debug("compressed to 4 octets\n");
- iphc1 |= LOWPAN_IPHC_DAM_10;
- /* second byte + the last three */
- lowpan_push_hc_data(&hc_ptr,
- &hdr->daddr.s6_addr[1], 1);
- lowpan_push_hc_data(&hc_ptr,
- &hdr->daddr.s6_addr[13], 3);
- } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) {
- pr_debug("compressed to 6 octets\n");
- iphc1 |= LOWPAN_IPHC_DAM_01;
- /* second byte + the last five */
- lowpan_push_hc_data(&hc_ptr,
- &hdr->daddr.s6_addr[1], 1);
- lowpan_push_hc_data(&hc_ptr,
- &hdr->daddr.s6_addr[11], 5);
- } else {
- pr_debug("using full address\n");
- iphc1 |= LOWPAN_IPHC_DAM_00;
- lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
- }
- } else {
- if (addr_type & IPV6_ADDR_LINKLOCAL) {
- /* TODO: context lookup */
- iphc1 |= lowpan_compress_addr_64(&hc_ptr,
- LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr);
- pr_debug("dest address unicast link-local %pI6c "
- "iphc1 0x%02x\n", &hdr->daddr, iphc1);
- } else {
- pr_debug("dest address unicast %pI6c\n", &hdr->daddr);
- lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16);
- }
- }
-
- /* UDP header compression */
- if (hdr->nexthdr == UIP_PROTO_UDP)
- compress_udp_header(&hc_ptr, skb);
-
- head[0] = iphc0;
- head[1] = iphc1;
-
- skb_pull(skb, sizeof(struct ipv6hdr));
- skb_reset_transport_header(skb);
- memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head);
- skb_reset_network_header(skb);
-
- pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len);
-
- raw_dump_table(__func__, "raw skb data dump compressed",
- skb->data, skb->len);
- return 0;
-}
-EXPORT_SYMBOL_GPL(lowpan_header_compress);
-
-MODULE_LICENSE("GPL");
diff --git a/net/Kconfig b/net/Kconfig
index ff9ffc1..6272420 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -6,7 +6,7 @@
bool "Networking support"
select NLATTR
select GENERIC_NET_UTILS
- select BPF
+ select ANON_INODES
---help---
Unless you really know what you are doing, you should say Y here.
The reason is that some programs need kernel networking support even
@@ -228,7 +228,6 @@
source "net/netlink/Kconfig"
source "net/mpls/Kconfig"
source "net/hsr/Kconfig"
-source "net/switchdev/Kconfig"
config RPS
boolean
diff --git a/net/Makefile b/net/Makefile
index 76f0349..23a0b60 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -5,6 +5,8 @@
# Rewritten to use lists instead of if-statements.
#
+obj-y := nonet.o
+
obj-$(CONFIG_NET) := socket.o core/
tmp-$(CONFIG_COMPAT) := compat.o
@@ -55,7 +57,7 @@
ifneq ($(CONFIG_DCB),)
obj-y += dcb/
endif
-obj-$(CPTCFG_6LOWPAN) += 6lowpan/
+obj-$(CONFIG_6LOWPAN) += 6lowpan/
obj-$(CPTCFG_IEEE802154) += ieee802154/
obj-$(CPTCFG_MAC802154) += mac802154/
@@ -71,6 +73,3 @@
obj-$(CONFIG_VSOCKETS) += vmw_vsock/
obj-$(CONFIG_NET_MPLS_GSO) += mpls/
obj-$(CONFIG_HSR) += hsr/
-ifneq ($(CONFIG_NET_SWITCHDEV),)
-obj-y += switchdev/
-endif
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 8ea2d68..c2e0d14 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -18,7 +18,6 @@
#include <linux/debugfs.h>
#include <net/ipv6.h>
-#include <net/ip6_fib.h>
#include <net/ip6_route.h>
#include <net/addrconf.h>
@@ -54,7 +53,7 @@
* The list contains struct lowpan_dev elements.
*/
static LIST_HEAD(bt_6lowpan_devices);
-static DEFINE_SPINLOCK(devices_lock);
+static DEFINE_RWLOCK(devices_lock);
/* If psm is set to 0 (default value), then 6lowpan is disabled.
* Other values are used to indicate a Protocol Service Multiplexer
@@ -68,7 +67,6 @@
struct lowpan_peer {
struct list_head list;
- struct rcu_head rcu;
struct l2cap_chan *chan;
/* peer addresses in various formats */
@@ -95,14 +93,13 @@
static inline void peer_add(struct lowpan_dev *dev, struct lowpan_peer *peer)
{
- list_add_rcu(&peer->list, &dev->peers);
+ list_add(&peer->list, &dev->peers);
atomic_inc(&dev->peer_count);
}
static inline bool peer_del(struct lowpan_dev *dev, struct lowpan_peer *peer)
{
- list_del_rcu(&peer->list);
- kfree_rcu(peer, rcu);
+ list_del(&peer->list);
module_put(THIS_MODULE);
@@ -117,37 +114,31 @@
static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_dev *dev,
bdaddr_t *ba, __u8 type)
{
- struct lowpan_peer *peer;
+ struct lowpan_peer *peer, *tmp;
BT_DBG("peers %d addr %pMR type %d", atomic_read(&dev->peer_count),
ba, type);
- rcu_read_lock();
-
- list_for_each_entry_rcu(peer, &dev->peers, list) {
+ list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
BT_DBG("dst addr %pMR dst type %d",
&peer->chan->dst, peer->chan->dst_type);
if (bacmp(&peer->chan->dst, ba))
continue;
- if (type == peer->chan->dst_type) {
- rcu_read_unlock();
+ if (type == peer->chan->dst_type)
return peer;
- }
}
- rcu_read_unlock();
-
return NULL;
}
-static inline struct lowpan_peer *__peer_lookup_chan(struct lowpan_dev *dev,
- struct l2cap_chan *chan)
+static inline struct lowpan_peer *peer_lookup_chan(struct lowpan_dev *dev,
+ struct l2cap_chan *chan)
{
- struct lowpan_peer *peer;
+ struct lowpan_peer *peer, *tmp;
- list_for_each_entry_rcu(peer, &dev->peers, list) {
+ list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
if (peer->chan == chan)
return peer;
}
@@ -155,12 +146,12 @@
return NULL;
}
-static inline struct lowpan_peer *__peer_lookup_conn(struct lowpan_dev *dev,
- struct l2cap_conn *conn)
+static inline struct lowpan_peer *peer_lookup_conn(struct lowpan_dev *dev,
+ struct l2cap_conn *conn)
{
- struct lowpan_peer *peer;
+ struct lowpan_peer *peer, *tmp;
- list_for_each_entry_rcu(peer, &dev->peers, list) {
+ list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
if (peer->chan->conn == conn)
return peer;
}
@@ -172,7 +163,7 @@
struct in6_addr *daddr,
struct sk_buff *skb)
{
- struct lowpan_peer *peer;
+ struct lowpan_peer *peer, *tmp;
struct in6_addr *nexthop;
struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
int count = atomic_read(&dev->peer_count);
@@ -183,13 +174,9 @@
* send the packet. If only one peer exists, then we can send the
* packet right away.
*/
- if (count == 1) {
- rcu_read_lock();
- peer = list_first_or_null_rcu(&dev->peers, struct lowpan_peer,
- list);
- rcu_read_unlock();
- return peer;
- }
+ if (count == 1)
+ return list_first_entry(&dev->peers, struct lowpan_peer,
+ list);
if (!rt) {
nexthop = &lowpan_cb(skb)->gw;
@@ -208,57 +195,53 @@
BT_DBG("gw %pI6c", nexthop);
- rcu_read_lock();
-
- list_for_each_entry_rcu(peer, &dev->peers, list) {
+ list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
BT_DBG("dst addr %pMR dst type %d ip %pI6c",
&peer->chan->dst, peer->chan->dst_type,
&peer->peer_addr);
- if (!ipv6_addr_cmp(&peer->peer_addr, nexthop)) {
- rcu_read_unlock();
+ if (!ipv6_addr_cmp(&peer->peer_addr, nexthop))
return peer;
- }
}
- rcu_read_unlock();
-
return NULL;
}
static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn)
{
- struct lowpan_dev *entry;
+ struct lowpan_dev *entry, *tmp;
struct lowpan_peer *peer = NULL;
+ unsigned long flags;
- rcu_read_lock();
+ read_lock_irqsave(&devices_lock, flags);
- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
- peer = __peer_lookup_conn(entry, conn);
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+ peer = peer_lookup_conn(entry, conn);
if (peer)
break;
}
- rcu_read_unlock();
+ read_unlock_irqrestore(&devices_lock, flags);
return peer;
}
static struct lowpan_dev *lookup_dev(struct l2cap_conn *conn)
{
- struct lowpan_dev *entry;
+ struct lowpan_dev *entry, *tmp;
struct lowpan_dev *dev = NULL;
+ unsigned long flags;
- rcu_read_lock();
+ read_lock_irqsave(&devices_lock, flags);
- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
if (conn->hcon->hdev == entry->hdev) {
dev = entry;
break;
}
}
- rcu_read_unlock();
+ read_unlock_irqrestore(&devices_lock, flags);
return dev;
}
@@ -266,49 +249,59 @@
static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev)
{
struct sk_buff *skb_cp;
+ int ret;
skb_cp = skb_copy(skb, GFP_ATOMIC);
if (!skb_cp)
- return NET_RX_DROP;
+ return -ENOMEM;
- return netif_rx(skb_cp);
+ ret = netif_rx(skb_cp);
+ if (ret < 0) {
+ BT_DBG("receive skb %d", ret);
+ return NET_RX_DROP;
+ }
+
+ return ret;
}
-static int iphc_decompress(struct sk_buff *skb, struct net_device *netdev,
- struct l2cap_chan *chan)
+static int process_data(struct sk_buff *skb, struct net_device *netdev,
+ struct l2cap_chan *chan)
{
const u8 *saddr, *daddr;
u8 iphc0, iphc1;
struct lowpan_dev *dev;
struct lowpan_peer *peer;
+ unsigned long flags;
dev = lowpan_dev(netdev);
- rcu_read_lock();
- peer = __peer_lookup_chan(dev, chan);
- rcu_read_unlock();
+ read_lock_irqsave(&devices_lock, flags);
+ peer = peer_lookup_chan(dev, chan);
+ read_unlock_irqrestore(&devices_lock, flags);
if (!peer)
- return -EINVAL;
+ goto drop;
saddr = peer->eui64_addr;
daddr = dev->netdev->dev_addr;
/* at least two bytes will be used for the encoding */
if (skb->len < 2)
- return -EINVAL;
+ goto drop;
if (lowpan_fetch_skb_u8(skb, &iphc0))
- return -EINVAL;
+ goto drop;
if (lowpan_fetch_skb_u8(skb, &iphc1))
- return -EINVAL;
+ goto drop;
- return lowpan_header_decompress(skb, netdev,
- saddr, IEEE802154_ADDR_LONG,
- EUI64_ADDR_LEN, daddr,
- IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
- iphc0, iphc1);
+ return lowpan_process_data(skb, netdev,
+ saddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+ daddr, IEEE802154_ADDR_LONG, EUI64_ADDR_LEN,
+ iphc0, iphc1, give_skb_to_upper);
+drop:
+ kfree_skb(skb);
+ return -EINVAL;
}
static int recv_pkt(struct sk_buff *skb, struct net_device *dev,
@@ -323,10 +316,6 @@
if (dev->type != ARPHRD_6LOWPAN)
goto drop;
- skb = skb_share_check(skb, GFP_ATOMIC);
- if (!skb)
- goto drop;
-
/* check that it's our buffer */
if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
/* Copy the packet so that the IPv6 header is
@@ -351,8 +340,8 @@
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
- consume_skb(local_skb);
- consume_skb(skb);
+ kfree_skb(local_skb);
+ kfree_skb(skb);
} else {
switch (skb->data[0] & 0xe0) {
case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
@@ -360,27 +349,14 @@
if (!local_skb)
goto drop;
- ret = iphc_decompress(local_skb, dev, chan);
- if (ret < 0) {
- kfree_skb(local_skb);
+ ret = process_data(local_skb, dev, chan);
+ if (ret != NET_RX_SUCCESS)
goto drop;
- }
-
- local_skb->protocol = htons(ETH_P_IPV6);
- local_skb->pkt_type = PACKET_HOST;
- local_skb->dev = dev;
-
- if (give_skb_to_upper(local_skb, dev)
- != NET_RX_SUCCESS) {
- kfree_skb(local_skb);
- goto drop;
- }
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
- consume_skb(local_skb);
- consume_skb(skb);
+ kfree_skb(skb);
break;
default:
break;
@@ -467,6 +443,7 @@
if (ipv6_addr_is_multicast(&ipv6_daddr)) {
lowpan_cb(skb)->chan = NULL;
} else {
+ unsigned long flags;
u8 addr_type;
/* Get destination BT device from skb.
@@ -477,14 +454,19 @@
BT_DBG("dest addr %pMR type %d IP %pI6c", &addr,
addr_type, &ipv6_daddr);
+ read_lock_irqsave(&devices_lock, flags);
peer = peer_lookup_ba(dev, &addr, addr_type);
+ read_unlock_irqrestore(&devices_lock, flags);
+
if (!peer) {
/* The packet might be sent to 6lowpan interface
* because of routing (either via default route
* or user set route) so get peer according to
* the destination address.
*/
+ read_lock_irqsave(&devices_lock, flags);
peer = peer_lookup_dst(dev, &ipv6_daddr, skb);
+ read_unlock_irqrestore(&devices_lock, flags);
if (!peer) {
BT_DBG("no such peer %pMR found", &addr);
return -ENOENT;
@@ -538,19 +520,12 @@
*/
chan->data = skb;
-#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0)
memset(&msg, 0, sizeof(msg));
msg.msg_iov = (struct iovec *) &iv;
msg.msg_iovlen = 1;
-#endif
iv.iov_base = skb->data;
iv.iov_len = skb->len;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
- memset(&msg, 0, sizeof(msg));
- iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, skb->len);
-#endif
-
err = l2cap_chan_send(chan, &msg, skb->len);
if (err > 0) {
netdev->stats.tx_bytes += err;
@@ -574,13 +549,14 @@
static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
{
struct sk_buff *local_skb;
- struct lowpan_dev *entry;
+ struct lowpan_dev *entry, *tmp;
+ unsigned long flags;
int err = 0;
- rcu_read_lock();
+ read_lock_irqsave(&devices_lock, flags);
- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
- struct lowpan_peer *pentry;
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
+ struct lowpan_peer *pentry, *ptmp;
struct lowpan_dev *dev;
if (entry->netdev != netdev)
@@ -588,7 +564,7 @@
dev = lowpan_dev(entry->netdev);
- list_for_each_entry_rcu(pentry, &dev->peers, list) {
+ list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) {
int ret;
local_skb = skb_clone(skb, GFP_ATOMIC);
@@ -605,7 +581,7 @@
}
}
- rcu_read_unlock();
+ read_unlock_irqrestore(&devices_lock, flags);
return err;
}
@@ -615,13 +591,17 @@
int err = 0;
bdaddr_t addr;
u8 addr_type;
+ struct sk_buff *tmpskb;
/* We must take a copy of the skb before we modify/replace the ipv6
* header as the header could be used elsewhere
*/
- skb = skb_unshare(skb, GFP_ATOMIC);
- if (!skb)
+ tmpskb = skb_unshare(skb, GFP_ATOMIC);
+ if (!tmpskb) {
+ kfree_skb(skb);
return NET_XMIT_DROP;
+ }
+ skb = tmpskb;
/* Return values from setup_header()
* <0 - error, packet is dropped
@@ -658,28 +638,7 @@
return err < 0 ? NET_XMIT_DROP : err;
}
-static struct lock_class_key bt_tx_busylock;
-static struct lock_class_key bt_netdev_xmit_lock_key;
-
-static void bt_set_lockdep_class_one(struct net_device *dev,
- struct netdev_queue *txq,
- void *_unused)
-{
- lockdep_set_class(&txq->_xmit_lock, &bt_netdev_xmit_lock_key);
-}
-
-static int bt_dev_init(struct net_device *dev)
-{
- netdev_for_each_tx_queue(dev, bt_set_lockdep_class_one, NULL);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
- dev->qdisc_tx_busylock = &bt_tx_busylock;
-#endif
-
- return 0;
-}
-
static const struct net_device_ops netdev_ops = {
- .ndo_init = bt_dev_init,
.ndo_start_xmit = bt_xmit,
};
@@ -824,6 +783,7 @@
struct lowpan_dev *dev)
{
struct lowpan_peer *peer;
+ unsigned long flags;
peer = kzalloc(sizeof(*peer), GFP_ATOMIC);
if (!peer)
@@ -846,10 +806,10 @@
*/
set_ip_addr_bits(chan->dst_type, (u8 *)&peer->peer_addr.s6_addr + 8);
- spin_lock(&devices_lock);
+ write_lock_irqsave(&devices_lock, flags);
INIT_LIST_HEAD(&peer->list);
peer_add(dev, peer);
- spin_unlock(&devices_lock);
+ write_unlock_irqrestore(&devices_lock, flags);
/* Notifying peers about us needs to be done without locks held */
INIT_DELAYED_WORK(&dev->notify_peers, do_notify_peers);
@@ -862,6 +822,7 @@
{
struct net_device *netdev;
int err = 0;
+ unsigned long flags;
netdev = alloc_netdev(sizeof(struct lowpan_dev), IFACE_NAME_TEMPLATE,
NET_NAME_UNKNOWN, netdev_setup);
@@ -891,10 +852,10 @@
(*dev)->hdev = chan->conn->hcon->hdev;
INIT_LIST_HEAD(&(*dev)->peers);
- spin_lock(&devices_lock);
+ write_lock_irqsave(&devices_lock, flags);
INIT_LIST_HEAD(&(*dev)->list);
- list_add_rcu(&(*dev)->list, &bt_6lowpan_devices);
- spin_unlock(&devices_lock);
+ list_add(&(*dev)->list, &bt_6lowpan_devices);
+ write_unlock_irqrestore(&devices_lock, flags);
return 0;
@@ -948,10 +909,11 @@
static void chan_close_cb(struct l2cap_chan *chan)
{
- struct lowpan_dev *entry;
+ struct lowpan_dev *entry, *tmp;
struct lowpan_dev *dev = NULL;
struct lowpan_peer *peer;
int err = -ENOENT;
+ unsigned long flags;
bool last = false, removed = true;
BT_DBG("chan %p conn %p", chan, chan->conn);
@@ -966,11 +928,11 @@
removed = false;
}
- spin_lock(&devices_lock);
+ write_lock_irqsave(&devices_lock, flags);
- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
dev = lowpan_dev(entry->netdev);
- peer = __peer_lookup_chan(dev, chan);
+ peer = peer_lookup_chan(dev, chan);
if (peer) {
last = peer_del(dev, peer);
err = 0;
@@ -981,12 +943,13 @@
atomic_read(&chan->kref.refcount));
l2cap_chan_put(chan);
+ kfree(peer);
break;
}
}
if (!err && last && dev && !atomic_read(&dev->peer_count)) {
- spin_unlock(&devices_lock);
+ write_unlock_irqrestore(&devices_lock, flags);
cancel_delayed_work_sync(&dev->notify_peers);
@@ -997,7 +960,7 @@
schedule_work(&entry->delete_netdev);
}
} else {
- spin_unlock(&devices_lock);
+ write_unlock_irqrestore(&devices_lock, flags);
}
return;
@@ -1140,8 +1103,6 @@
pchan->state = BT_LISTEN;
pchan->src_type = BDADDR_LE_PUBLIC;
- atomic_set(&pchan->nesting, L2CAP_NESTING_PARENT);
-
BT_DBG("psm 0x%04x chan %p src type %d", psm_6lowpan, pchan,
pchan->src_type);
@@ -1191,9 +1152,10 @@
static void disconnect_all_peers(void)
{
- struct lowpan_dev *entry;
+ struct lowpan_dev *entry, *tmp_dev;
struct lowpan_peer *peer, *tmp_peer, *new_peer;
struct list_head peers;
+ unsigned long flags;
INIT_LIST_HEAD(&peers);
@@ -1202,10 +1164,10 @@
* with the same list at the same time.
*/
- rcu_read_lock();
+ read_lock_irqsave(&devices_lock, flags);
- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
- list_for_each_entry_rcu(peer, &entry->peers, list) {
+ list_for_each_entry_safe(entry, tmp_dev, &bt_6lowpan_devices, list) {
+ list_for_each_entry_safe(peer, tmp_peer, &entry->peers, list) {
new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC);
if (!new_peer)
break;
@@ -1217,36 +1179,26 @@
}
}
- rcu_read_unlock();
+ read_unlock_irqrestore(&devices_lock, flags);
- spin_lock(&devices_lock);
list_for_each_entry_safe(peer, tmp_peer, &peers, list) {
l2cap_chan_close(peer->chan, ENOENT);
-
- list_del_rcu(&peer->list);
- kfree_rcu(peer, rcu);
-
- module_put(THIS_MODULE);
+ kfree(peer);
}
- spin_unlock(&devices_lock);
}
-struct set_psm {
- struct work_struct work;
- u16 psm;
-};
-
-static void do_psm_set(struct work_struct *work)
+static int lowpan_psm_set(void *data, u64 val)
{
- struct set_psm *set_psm = container_of(work, struct set_psm, work);
+ u16 psm;
- if (set_psm->psm == 0 || psm_6lowpan != set_psm->psm)
+ psm = val;
+ if (psm == 0 || psm_6lowpan != psm)
/* Disconnect existing connections if 6lowpan is
* disabled (psm = 0), or if psm changes.
*/
disconnect_all_peers();
- psm_6lowpan = set_psm->psm;
+ psm_6lowpan = psm;
if (listen_chan) {
l2cap_chan_close(listen_chan, 0);
@@ -1255,22 +1207,6 @@
listen_chan = bt_6lowpan_listen();
- kfree(set_psm);
-}
-
-static int lowpan_psm_set(void *data, u64 val)
-{
- struct set_psm *set_psm;
-
- set_psm = kzalloc(sizeof(*set_psm), GFP_KERNEL);
- if (!set_psm)
- return -ENOMEM;
-
- set_psm->psm = val;
- INIT_WORK(&set_psm->work, do_psm_set);
-
- schedule_work(&set_psm->work);
-
return 0;
}
@@ -1352,18 +1288,19 @@
static int lowpan_control_show(struct seq_file *f, void *ptr)
{
- struct lowpan_dev *entry;
- struct lowpan_peer *peer;
+ struct lowpan_dev *entry, *tmp_dev;
+ struct lowpan_peer *peer, *tmp_peer;
+ unsigned long flags;
- spin_lock(&devices_lock);
+ read_lock_irqsave(&devices_lock, flags);
- list_for_each_entry(entry, &bt_6lowpan_devices, list) {
- list_for_each_entry(peer, &entry->peers, list)
+ list_for_each_entry_safe(entry, tmp_dev, &bt_6lowpan_devices, list) {
+ list_for_each_entry_safe(peer, tmp_peer, &entry->peers, list)
seq_printf(f, "%pMR (type %u)\n",
&peer->chan->dst, peer->chan->dst_type);
}
- spin_unlock(&devices_lock);
+ read_unlock_irqrestore(&devices_lock, flags);
return 0;
}
@@ -1385,6 +1322,7 @@
{
struct lowpan_dev *entry, *tmp, *new_dev;
struct list_head devices;
+ unsigned long flags;
INIT_LIST_HEAD(&devices);
@@ -1393,9 +1331,9 @@
* devices list.
*/
- rcu_read_lock();
+ read_lock_irqsave(&devices_lock, flags);
- list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) {
new_dev = kmalloc(sizeof(*new_dev), GFP_ATOMIC);
if (!new_dev)
break;
@@ -1403,10 +1341,10 @@
new_dev->netdev = entry->netdev;
INIT_LIST_HEAD(&new_dev->list);
- list_add_rcu(&new_dev->list, &devices);
+ list_add(&new_dev->list, &devices);
}
- rcu_read_unlock();
+ read_unlock_irqrestore(&devices_lock, flags);
list_for_each_entry_safe(entry, tmp, &devices, list) {
ifdown(entry->netdev);
@@ -1421,15 +1359,17 @@
unsigned long event, void *ptr)
{
struct net_device *netdev = netdev_notifier_info_to_dev(ptr);
- struct lowpan_dev *entry;
+ struct lowpan_dev *entry, *tmp;
+ unsigned long flags;
if (netdev->type != ARPHRD_6LOWPAN)
return NOTIFY_DONE;
switch (event) {
case NETDEV_UNREGISTER:
- spin_lock(&devices_lock);
- list_for_each_entry(entry, &bt_6lowpan_devices, list) {
+ write_lock_irqsave(&devices_lock, flags);
+ list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices,
+ list) {
if (entry->netdev == netdev) {
BT_DBG("Unregistered netdev %s %p",
netdev->name, netdev);
@@ -1438,7 +1378,7 @@
break;
}
}
- spin_unlock(&devices_lock);
+ write_unlock_irqrestore(&devices_lock, flags);
break;
}
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
index a68caf3..b5df2e3 100644
--- a/net/bluetooth/Kconfig
+++ b/net/bluetooth/Kconfig
@@ -11,7 +11,6 @@
depends on CRYPTO
depends on CRYPTO_BLKCIPHER
depends on CRYPTO_AES
- depends on CRYPTO_CMAC
depends on CRYPTO_ECB
depends on CRYPTO_SHA256
help
@@ -41,10 +40,12 @@
to Bluetooth kernel modules are provided in the BlueZ packages. For
more information, see <http://www.bluez.org/>.
-config BT_BREDR
- bool "Bluetooth Classic (BR/EDR) features"
- depends on BT
- default y
+config BT_6LOWPAN
+ tristate "Bluetooth 6LoWPAN support"
+ depends on m
+ depends on BT && 6LOWPAN
+ help
+ IPv6 compression over Bluetooth Low Energy.
source "net/bluetooth/rfcomm/Kconfig"
@@ -54,16 +55,4 @@
source "net/bluetooth/hidp/Kconfig"
-config BT_LE
- bool "Bluetooth Low Energy (LE) features"
- depends on BT
- default y
-
-config BT_6LOWPAN
- tristate "Bluetooth 6LoWPAN support"
- depends on m
- depends on BT_LE && 6LOWPAN
- help
- IPv6 compression over Bluetooth Low Energy.
-
source "drivers/bluetooth/Kconfig"
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
index e3474dd..cb87c99 100644
--- a/net/bluetooth/Makefile
+++ b/net/bluetooth/Makefile
@@ -13,6 +13,6 @@
bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \
- a2mp.o amp.o ecc.o
+ a2mp.o amp.o
subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c
index 6fcb9bf..5dcade5 100644
--- a/net/bluetooth/a2mp.c
+++ b/net/bluetooth/a2mp.c
@@ -60,12 +60,8 @@
memset(&msg, 0, sizeof(msg));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
- iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, total_len);
-#else
msg.msg_iov = (struct iovec *) &iv;
msg.msg_iovlen = 1;
-#endif
l2cap_chan_send(chan, &msg, total_len);
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 012e3b0..339c74a 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -31,7 +31,7 @@
#include <net/bluetooth/bluetooth.h>
#include <linux/proc_fs.h>
-#define VERSION "2.20"
+#define VERSION "2.19"
/* Bluetooth sockets */
#define BT_MAX_PROTO 8
@@ -237,7 +237,7 @@
}
skb_reset_transport_header(skb);
- err = skb_copy_datagram_msg(skb, 0, msg, copied);
+ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
if (err == 0) {
sock_recv_ts_and_drops(msg, sk, skb);
@@ -328,7 +328,7 @@
}
chunk = min_t(unsigned int, skb->len, size);
- if (skb_copy_datagram_msg(skb, 0, msg, chunk)) {
+ if (skb_copy_datagram_iovec(skb, 0, msg->msg_iov, chunk)) {
skb_queue_head(&sk->sk_receive_queue, skb);
if (!copied)
copied = -EFAULT;
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c
index ee016f0..2640d78 100644
--- a/net/bluetooth/amp.c
+++ b/net/bluetooth/amp.c
@@ -134,7 +134,6 @@
static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output)
{
struct crypto_shash *tfm;
- struct shash_desc *shash;
int ret;
if (!ksize)
@@ -149,24 +148,18 @@
ret = crypto_shash_setkey(tfm, key, ksize);
if (ret) {
BT_DBG("crypto_ahash_setkey failed: err %d", ret);
- goto failed;
+ } else {
+ char desc[sizeof(struct shash_desc) +
+ crypto_shash_descsize(tfm)] CRYPTO_MINALIGN_ATTR;
+ struct shash_desc *shash = (struct shash_desc *)desc;
+
+ shash->tfm = tfm;
+ shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
+
+ ret = crypto_shash_digest(shash, plaintext, psize,
+ output);
}
- shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
- GFP_KERNEL);
- if (!shash) {
- ret = -ENOMEM;
- goto failed;
- }
-
- shash->tfm = tfm;
- shash->flags = CRYPTO_TFM_REQ_MAY_SLEEP;
-
- ret = crypto_shash_digest(shash, plaintext, psize, output);
-
- kfree(shash);
-
-failed:
crypto_free_shash(tfm);
return ret;
}
diff --git a/net/bluetooth/bnep/Kconfig b/net/bluetooth/bnep/Kconfig
index 64ffb40..7ca2e1c 100644
--- a/net/bluetooth/bnep/Kconfig
+++ b/net/bluetooth/bnep/Kconfig
@@ -1,7 +1,7 @@
config BT_BNEP
tristate "BNEP protocol support"
depends on m
- depends on BT_BREDR
+ depends on BT
depends on CRC32
help
BNEP (Bluetooth Network Encapsulation Protocol) is Ethernet
diff --git a/net/bluetooth/cmtp/Kconfig b/net/bluetooth/cmtp/Kconfig
index 7acd7ea..accf52d 100644
--- a/net/bluetooth/cmtp/Kconfig
+++ b/net/bluetooth/cmtp/Kconfig
@@ -1,7 +1,7 @@
config BT_CMTP
tristate "CMTP protocol support"
depends on m
- depends on BT_BREDR && ISDN_CAPI
+ depends on BT && ISDN_CAPI
help
CMTP (CAPI Message Transport Protocol) is a transport layer
for CAPI messages. CMTP is required for the Bluetooth Common
diff --git a/net/bluetooth/ecc.c b/net/bluetooth/ecc.c
deleted file mode 100644
index e1709f8..0000000
--- a/net/bluetooth/ecc.c
+++ /dev/null
@@ -1,816 +0,0 @@
-/*
- * Copyright (c) 2013, Kenneth MacKay
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/random.h>
-
-#include "ecc.h"
-
-/* 256-bit curve */
-#define ECC_BYTES 32
-
-#define MAX_TRIES 16
-
-/* Number of u64's needed */
-#define NUM_ECC_DIGITS (ECC_BYTES / 8)
-
-struct ecc_point {
- u64 x[NUM_ECC_DIGITS];
- u64 y[NUM_ECC_DIGITS];
-};
-
-typedef struct {
- u64 m_low;
- u64 m_high;
-} uint128_t;
-
-#define CURVE_P_32 { 0xFFFFFFFFFFFFFFFFull, 0x00000000FFFFFFFFull, \
- 0x0000000000000000ull, 0xFFFFFFFF00000001ull }
-
-#define CURVE_G_32 { \
- { 0xF4A13945D898C296ull, 0x77037D812DEB33A0ull, \
- 0xF8BCE6E563A440F2ull, 0x6B17D1F2E12C4247ull }, \
- { 0xCBB6406837BF51F5ull, 0x2BCE33576B315ECEull, \
- 0x8EE7EB4A7C0F9E16ull, 0x4FE342E2FE1A7F9Bull } \
-}
-
-#define CURVE_N_32 { 0xF3B9CAC2FC632551ull, 0xBCE6FAADA7179E84ull, \
- 0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFF00000000ull }
-
-static u64 curve_p[NUM_ECC_DIGITS] = CURVE_P_32;
-static struct ecc_point curve_g = CURVE_G_32;
-static u64 curve_n[NUM_ECC_DIGITS] = CURVE_N_32;
-
-static void vli_clear(u64 *vli)
-{
- int i;
-
- for (i = 0; i < NUM_ECC_DIGITS; i++)
- vli[i] = 0;
-}
-
-/* Returns true if vli == 0, false otherwise. */
-static bool vli_is_zero(const u64 *vli)
-{
- int i;
-
- for (i = 0; i < NUM_ECC_DIGITS; i++) {
- if (vli[i])
- return false;
- }
-
- return true;
-}
-
-/* Returns nonzero if bit bit of vli is set. */
-static u64 vli_test_bit(const u64 *vli, unsigned int bit)
-{
- return (vli[bit / 64] & ((u64) 1 << (bit % 64)));
-}
-
-/* Counts the number of 64-bit "digits" in vli. */
-static unsigned int vli_num_digits(const u64 *vli)
-{
- int i;
-
- /* Search from the end until we find a non-zero digit.
- * We do it in reverse because we expect that most digits will
- * be nonzero.
- */
- for (i = NUM_ECC_DIGITS - 1; i >= 0 && vli[i] == 0; i--);
-
- return (i + 1);
-}
-
-/* Counts the number of bits required for vli. */
-static unsigned int vli_num_bits(const u64 *vli)
-{
- unsigned int i, num_digits;
- u64 digit;
-
- num_digits = vli_num_digits(vli);
- if (num_digits == 0)
- return 0;
-
- digit = vli[num_digits - 1];
- for (i = 0; digit; i++)
- digit >>= 1;
-
- return ((num_digits - 1) * 64 + i);
-}
-
-/* Sets dest = src. */
-static void vli_set(u64 *dest, const u64 *src)
-{
- int i;
-
- for (i = 0; i < NUM_ECC_DIGITS; i++)
- dest[i] = src[i];
-}
-
-/* Returns sign of left - right. */
-static int vli_cmp(const u64 *left, const u64 *right)
-{
- int i;
-
- for (i = NUM_ECC_DIGITS - 1; i >= 0; i--) {
- if (left[i] > right[i])
- return 1;
- else if (left[i] < right[i])
- return -1;
- }
-
- return 0;
-}
-
-/* Computes result = in << c, returning carry. Can modify in place
- * (if result == in). 0 < shift < 64.
- */
-static u64 vli_lshift(u64 *result, const u64 *in,
- unsigned int shift)
-{
- u64 carry = 0;
- int i;
-
- for (i = 0; i < NUM_ECC_DIGITS; i++) {
- u64 temp = in[i];
-
- result[i] = (temp << shift) | carry;
- carry = temp >> (64 - shift);
- }
-
- return carry;
-}
-
-/* Computes vli = vli >> 1. */
-static void vli_rshift1(u64 *vli)
-{
- u64 *end = vli;
- u64 carry = 0;
-
- vli += NUM_ECC_DIGITS;
-
- while (vli-- > end) {
- u64 temp = *vli;
- *vli = (temp >> 1) | carry;
- carry = temp << 63;
- }
-}
-
-/* Computes result = left + right, returning carry. Can modify in place. */
-static u64 vli_add(u64 *result, const u64 *left,
- const u64 *right)
-{
- u64 carry = 0;
- int i;
-
- for (i = 0; i < NUM_ECC_DIGITS; i++) {
- u64 sum;
-
- sum = left[i] + right[i] + carry;
- if (sum != left[i])
- carry = (sum < left[i]);
-
- result[i] = sum;
- }
-
- return carry;
-}
-
-/* Computes result = left - right, returning borrow. Can modify in place. */
-static u64 vli_sub(u64 *result, const u64 *left, const u64 *right)
-{
- u64 borrow = 0;
- int i;
-
- for (i = 0; i < NUM_ECC_DIGITS; i++) {
- u64 diff;
-
- diff = left[i] - right[i] - borrow;
- if (diff != left[i])
- borrow = (diff > left[i]);
-
- result[i] = diff;
- }
-
- return borrow;
-}
-
-static uint128_t mul_64_64(u64 left, u64 right)
-{
- u64 a0 = left & 0xffffffffull;
- u64 a1 = left >> 32;
- u64 b0 = right & 0xffffffffull;
- u64 b1 = right >> 32;
- u64 m0 = a0 * b0;
- u64 m1 = a0 * b1;
- u64 m2 = a1 * b0;
- u64 m3 = a1 * b1;
- uint128_t result;
-
- m2 += (m0 >> 32);
- m2 += m1;
-
- /* Overflow */
- if (m2 < m1)
- m3 += 0x100000000ull;
-
- result.m_low = (m0 & 0xffffffffull) | (m2 << 32);
- result.m_high = m3 + (m2 >> 32);
-
- return result;
-}
-
-static uint128_t add_128_128(uint128_t a, uint128_t b)
-{
- uint128_t result;
-
- result.m_low = a.m_low + b.m_low;
- result.m_high = a.m_high + b.m_high + (result.m_low < a.m_low);
-
- return result;
-}
-
-static void vli_mult(u64 *result, const u64 *left, const u64 *right)
-{
- uint128_t r01 = { 0, 0 };
- u64 r2 = 0;
- unsigned int i, k;
-
- /* Compute each digit of result in sequence, maintaining the
- * carries.
- */
- for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
- unsigned int min;
-
- if (k < NUM_ECC_DIGITS)
- min = 0;
- else
- min = (k + 1) - NUM_ECC_DIGITS;
-
- for (i = min; i <= k && i < NUM_ECC_DIGITS; i++) {
- uint128_t product;
-
- product = mul_64_64(left[i], right[k - i]);
-
- r01 = add_128_128(r01, product);
- r2 += (r01.m_high < product.m_high);
- }
-
- result[k] = r01.m_low;
- r01.m_low = r01.m_high;
- r01.m_high = r2;
- r2 = 0;
- }
-
- result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
-}
-
-static void vli_square(u64 *result, const u64 *left)
-{
- uint128_t r01 = { 0, 0 };
- u64 r2 = 0;
- int i, k;
-
- for (k = 0; k < NUM_ECC_DIGITS * 2 - 1; k++) {
- unsigned int min;
-
- if (k < NUM_ECC_DIGITS)
- min = 0;
- else
- min = (k + 1) - NUM_ECC_DIGITS;
-
- for (i = min; i <= k && i <= k - i; i++) {
- uint128_t product;
-
- product = mul_64_64(left[i], left[k - i]);
-
- if (i < k - i) {
- r2 += product.m_high >> 63;
- product.m_high = (product.m_high << 1) |
- (product.m_low >> 63);
- product.m_low <<= 1;
- }
-
- r01 = add_128_128(r01, product);
- r2 += (r01.m_high < product.m_high);
- }
-
- result[k] = r01.m_low;
- r01.m_low = r01.m_high;
- r01.m_high = r2;
- r2 = 0;
- }
-
- result[NUM_ECC_DIGITS * 2 - 1] = r01.m_low;
-}
-
-/* Computes result = (left + right) % mod.
- * Assumes that left < mod and right < mod, result != mod.
- */
-static void vli_mod_add(u64 *result, const u64 *left, const u64 *right,
- const u64 *mod)
-{
- u64 carry;
-
- carry = vli_add(result, left, right);
-
- /* result > mod (result = mod + remainder), so subtract mod to
- * get remainder.
- */
- if (carry || vli_cmp(result, mod) >= 0)
- vli_sub(result, result, mod);
-}
-
-/* Computes result = (left - right) % mod.
- * Assumes that left < mod and right < mod, result != mod.
- */
-static void vli_mod_sub(u64 *result, const u64 *left, const u64 *right,
- const u64 *mod)
-{
- u64 borrow = vli_sub(result, left, right);
-
- /* In this case, p_result == -diff == (max int) - diff.
- * Since -x % d == d - x, we can get the correct result from
- * result + mod (with overflow).
- */
- if (borrow)
- vli_add(result, result, mod);
-}
-
-/* Computes result = product % curve_p
- from http://www.nsa.gov/ia/_files/nist-routines.pdf */
-static void vli_mmod_fast(u64 *result, const u64 *product)
-{
- u64 tmp[NUM_ECC_DIGITS];
- int carry;
-
- /* t */
- vli_set(result, product);
-
- /* s1 */
- tmp[0] = 0;
- tmp[1] = product[5] & 0xffffffff00000000ull;
- tmp[2] = product[6];
- tmp[3] = product[7];
- carry = vli_lshift(tmp, tmp, 1);
- carry += vli_add(result, result, tmp);
-
- /* s2 */
- tmp[1] = product[6] << 32;
- tmp[2] = (product[6] >> 32) | (product[7] << 32);
- tmp[3] = product[7] >> 32;
- carry += vli_lshift(tmp, tmp, 1);
- carry += vli_add(result, result, tmp);
-
- /* s3 */
- tmp[0] = product[4];
- tmp[1] = product[5] & 0xffffffff;
- tmp[2] = 0;
- tmp[3] = product[7];
- carry += vli_add(result, result, tmp);
-
- /* s4 */
- tmp[0] = (product[4] >> 32) | (product[5] << 32);
- tmp[1] = (product[5] >> 32) | (product[6] & 0xffffffff00000000ull);
- tmp[2] = product[7];
- tmp[3] = (product[6] >> 32) | (product[4] << 32);
- carry += vli_add(result, result, tmp);
-
- /* d1 */
- tmp[0] = (product[5] >> 32) | (product[6] << 32);
- tmp[1] = (product[6] >> 32);
- tmp[2] = 0;
- tmp[3] = (product[4] & 0xffffffff) | (product[5] << 32);
- carry -= vli_sub(result, result, tmp);
-
- /* d2 */
- tmp[0] = product[6];
- tmp[1] = product[7];
- tmp[2] = 0;
- tmp[3] = (product[4] >> 32) | (product[5] & 0xffffffff00000000ull);
- carry -= vli_sub(result, result, tmp);
-
- /* d3 */
- tmp[0] = (product[6] >> 32) | (product[7] << 32);
- tmp[1] = (product[7] >> 32) | (product[4] << 32);
- tmp[2] = (product[4] >> 32) | (product[5] << 32);
- tmp[3] = (product[6] << 32);
- carry -= vli_sub(result, result, tmp);
-
- /* d4 */
- tmp[0] = product[7];
- tmp[1] = product[4] & 0xffffffff00000000ull;
- tmp[2] = product[5];
- tmp[3] = product[6] & 0xffffffff00000000ull;
- carry -= vli_sub(result, result, tmp);
-
- if (carry < 0) {
- do {
- carry += vli_add(result, result, curve_p);
- } while (carry < 0);
- } else {
- while (carry || vli_cmp(curve_p, result) != 1)
- carry -= vli_sub(result, result, curve_p);
- }
-}
-
-/* Computes result = (left * right) % curve_p. */
-static void vli_mod_mult_fast(u64 *result, const u64 *left, const u64 *right)
-{
- u64 product[2 * NUM_ECC_DIGITS];
-
- vli_mult(product, left, right);
- vli_mmod_fast(result, product);
-}
-
-/* Computes result = left^2 % curve_p. */
-static void vli_mod_square_fast(u64 *result, const u64 *left)
-{
- u64 product[2 * NUM_ECC_DIGITS];
-
- vli_square(product, left);
- vli_mmod_fast(result, product);
-}
-
-#define EVEN(vli) (!(vli[0] & 1))
-/* Computes result = (1 / p_input) % mod. All VLIs are the same size.
- * See "From Euclid's GCD to Montgomery Multiplication to the Great Divide"
- * https://labs.oracle.com/techrep/2001/smli_tr-2001-95.pdf
- */
-static void vli_mod_inv(u64 *result, const u64 *input, const u64 *mod)
-{
- u64 a[NUM_ECC_DIGITS], b[NUM_ECC_DIGITS];
- u64 u[NUM_ECC_DIGITS], v[NUM_ECC_DIGITS];
- u64 carry;
- int cmp_result;
-
- if (vli_is_zero(input)) {
- vli_clear(result);
- return;
- }
-
- vli_set(a, input);
- vli_set(b, mod);
- vli_clear(u);
- u[0] = 1;
- vli_clear(v);
-
- while ((cmp_result = vli_cmp(a, b)) != 0) {
- carry = 0;
-
- if (EVEN(a)) {
- vli_rshift1(a);
-
- if (!EVEN(u))
- carry = vli_add(u, u, mod);
-
- vli_rshift1(u);
- if (carry)
- u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
- } else if (EVEN(b)) {
- vli_rshift1(b);
-
- if (!EVEN(v))
- carry = vli_add(v, v, mod);
-
- vli_rshift1(v);
- if (carry)
- v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
- } else if (cmp_result > 0) {
- vli_sub(a, a, b);
- vli_rshift1(a);
-
- if (vli_cmp(u, v) < 0)
- vli_add(u, u, mod);
-
- vli_sub(u, u, v);
- if (!EVEN(u))
- carry = vli_add(u, u, mod);
-
- vli_rshift1(u);
- if (carry)
- u[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
- } else {
- vli_sub(b, b, a);
- vli_rshift1(b);
-
- if (vli_cmp(v, u) < 0)
- vli_add(v, v, mod);
-
- vli_sub(v, v, u);
- if (!EVEN(v))
- carry = vli_add(v, v, mod);
-
- vli_rshift1(v);
- if (carry)
- v[NUM_ECC_DIGITS - 1] |= 0x8000000000000000ull;
- }
- }
-
- vli_set(result, u);
-}
-
-/* ------ Point operations ------ */
-
-/* Returns true if p_point is the point at infinity, false otherwise. */
-static bool ecc_point_is_zero(const struct ecc_point *point)
-{
- return (vli_is_zero(point->x) && vli_is_zero(point->y));
-}
-
-/* Point multiplication algorithm using Montgomery's ladder with co-Z
- * coordinates. From http://eprint.iacr.org/2011/338.pdf
- */
-
-/* Double in place */
-static void ecc_point_double_jacobian(u64 *x1, u64 *y1, u64 *z1)
-{
- /* t1 = x, t2 = y, t3 = z */
- u64 t4[NUM_ECC_DIGITS];
- u64 t5[NUM_ECC_DIGITS];
-
- if (vli_is_zero(z1))
- return;
-
- vli_mod_square_fast(t4, y1); /* t4 = y1^2 */
- vli_mod_mult_fast(t5, x1, t4); /* t5 = x1*y1^2 = A */
- vli_mod_square_fast(t4, t4); /* t4 = y1^4 */
- vli_mod_mult_fast(y1, y1, z1); /* t2 = y1*z1 = z3 */
- vli_mod_square_fast(z1, z1); /* t3 = z1^2 */
-
- vli_mod_add(x1, x1, z1, curve_p); /* t1 = x1 + z1^2 */
- vli_mod_add(z1, z1, z1, curve_p); /* t3 = 2*z1^2 */
- vli_mod_sub(z1, x1, z1, curve_p); /* t3 = x1 - z1^2 */
- vli_mod_mult_fast(x1, x1, z1); /* t1 = x1^2 - z1^4 */
-
- vli_mod_add(z1, x1, x1, curve_p); /* t3 = 2*(x1^2 - z1^4) */
- vli_mod_add(x1, x1, z1, curve_p); /* t1 = 3*(x1^2 - z1^4) */
- if (vli_test_bit(x1, 0)) {
- u64 carry = vli_add(x1, x1, curve_p);
- vli_rshift1(x1);
- x1[NUM_ECC_DIGITS - 1] |= carry << 63;
- } else {
- vli_rshift1(x1);
- }
- /* t1 = 3/2*(x1^2 - z1^4) = B */
-
- vli_mod_square_fast(z1, x1); /* t3 = B^2 */
- vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - A */
- vli_mod_sub(z1, z1, t5, curve_p); /* t3 = B^2 - 2A = x3 */
- vli_mod_sub(t5, t5, z1, curve_p); /* t5 = A - x3 */
- vli_mod_mult_fast(x1, x1, t5); /* t1 = B * (A - x3) */
- vli_mod_sub(t4, x1, t4, curve_p); /* t4 = B * (A - x3) - y1^4 = y3 */
-
- vli_set(x1, z1);
- vli_set(z1, y1);
- vli_set(y1, t4);
-}
-
-/* Modify (x1, y1) => (x1 * z^2, y1 * z^3) */
-static void apply_z(u64 *x1, u64 *y1, u64 *z)
-{
- u64 t1[NUM_ECC_DIGITS];
-
- vli_mod_square_fast(t1, z); /* z^2 */
- vli_mod_mult_fast(x1, x1, t1); /* x1 * z^2 */
- vli_mod_mult_fast(t1, t1, z); /* z^3 */
- vli_mod_mult_fast(y1, y1, t1); /* y1 * z^3 */
-}
-
-/* P = (x1, y1) => 2P, (x2, y2) => P' */
-static void xycz_initial_double(u64 *x1, u64 *y1, u64 *x2, u64 *y2,
- u64 *p_initial_z)
-{
- u64 z[NUM_ECC_DIGITS];
-
- vli_set(x2, x1);
- vli_set(y2, y1);
-
- vli_clear(z);
- z[0] = 1;
-
- if (p_initial_z)
- vli_set(z, p_initial_z);
-
- apply_z(x1, y1, z);
-
- ecc_point_double_jacobian(x1, y1, z);
-
- apply_z(x2, y2, z);
-}
-
-/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
- * Output P' = (x1', y1', Z3), P + Q = (x3, y3, Z3)
- * or P => P', Q => P + Q
- */
-static void xycz_add(u64 *x1, u64 *y1, u64 *x2, u64 *y2)
-{
- /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
- u64 t5[NUM_ECC_DIGITS];
-
- vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
- vli_mod_square_fast(t5, t5); /* t5 = (x2 - x1)^2 = A */
- vli_mod_mult_fast(x1, x1, t5); /* t1 = x1*A = B */
- vli_mod_mult_fast(x2, x2, t5); /* t3 = x2*A = C */
- vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
- vli_mod_square_fast(t5, y2); /* t5 = (y2 - y1)^2 = D */
-
- vli_mod_sub(t5, t5, x1, curve_p); /* t5 = D - B */
- vli_mod_sub(t5, t5, x2, curve_p); /* t5 = D - B - C = x3 */
- vli_mod_sub(x2, x2, x1, curve_p); /* t3 = C - B */
- vli_mod_mult_fast(y1, y1, x2); /* t2 = y1*(C - B) */
- vli_mod_sub(x2, x1, t5, curve_p); /* t3 = B - x3 */
- vli_mod_mult_fast(y2, y2, x2); /* t4 = (y2 - y1)*(B - x3) */
- vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
-
- vli_set(x2, t5);
-}
-
-/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
- * Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
- * or P => P - Q, Q => P + Q
- */
-static void xycz_add_c(u64 *x1, u64 *y1, u64 *x2, u64 *y2)
-{
- /* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
- u64 t5[NUM_ECC_DIGITS];
- u64 t6[NUM_ECC_DIGITS];
- u64 t7[NUM_ECC_DIGITS];
-
- vli_mod_sub(t5, x2, x1, curve_p); /* t5 = x2 - x1 */
- vli_mod_square_fast(t5, t5); /* t5 = (x2 - x1)^2 = A */
- vli_mod_mult_fast(x1, x1, t5); /* t1 = x1*A = B */
- vli_mod_mult_fast(x2, x2, t5); /* t3 = x2*A = C */
- vli_mod_add(t5, y2, y1, curve_p); /* t4 = y2 + y1 */
- vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y2 - y1 */
-
- vli_mod_sub(t6, x2, x1, curve_p); /* t6 = C - B */
- vli_mod_mult_fast(y1, y1, t6); /* t2 = y1 * (C - B) */
- vli_mod_add(t6, x1, x2, curve_p); /* t6 = B + C */
- vli_mod_square_fast(x2, y2); /* t3 = (y2 - y1)^2 */
- vli_mod_sub(x2, x2, t6, curve_p); /* t3 = x3 */
-
- vli_mod_sub(t7, x1, x2, curve_p); /* t7 = B - x3 */
- vli_mod_mult_fast(y2, y2, t7); /* t4 = (y2 - y1)*(B - x3) */
- vli_mod_sub(y2, y2, y1, curve_p); /* t4 = y3 */
-
- vli_mod_square_fast(t7, t5); /* t7 = (y2 + y1)^2 = F */
- vli_mod_sub(t7, t7, t6, curve_p); /* t7 = x3' */
- vli_mod_sub(t6, t7, x1, curve_p); /* t6 = x3' - B */
- vli_mod_mult_fast(t6, t6, t5); /* t6 = (y2 + y1)*(x3' - B) */
- vli_mod_sub(y1, t6, y1, curve_p); /* t2 = y3' */
-
- vli_set(x1, t7);
-}
-
-static void ecc_point_mult(struct ecc_point *result,
- const struct ecc_point *point, u64 *scalar,
- u64 *initial_z, int num_bits)
-{
- /* R0 and R1 */
- u64 rx[2][NUM_ECC_DIGITS];
- u64 ry[2][NUM_ECC_DIGITS];
- u64 z[NUM_ECC_DIGITS];
- int i, nb;
-
- vli_set(rx[1], point->x);
- vli_set(ry[1], point->y);
-
- xycz_initial_double(rx[1], ry[1], rx[0], ry[0], initial_z);
-
- for (i = num_bits - 2; i > 0; i--) {
- nb = !vli_test_bit(scalar, i);
- xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
- xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
- }
-
- nb = !vli_test_bit(scalar, 0);
- xycz_add_c(rx[1 - nb], ry[1 - nb], rx[nb], ry[nb]);
-
- /* Find final 1/Z value. */
- vli_mod_sub(z, rx[1], rx[0], curve_p); /* X1 - X0 */
- vli_mod_mult_fast(z, z, ry[1 - nb]); /* Yb * (X1 - X0) */
- vli_mod_mult_fast(z, z, point->x); /* xP * Yb * (X1 - X0) */
- vli_mod_inv(z, z, curve_p); /* 1 / (xP * Yb * (X1 - X0)) */
- vli_mod_mult_fast(z, z, point->y); /* yP / (xP * Yb * (X1 - X0)) */
- vli_mod_mult_fast(z, z, rx[1 - nb]); /* Xb * yP / (xP * Yb * (X1 - X0)) */
- /* End 1/Z calculation */
-
- xycz_add(rx[nb], ry[nb], rx[1 - nb], ry[1 - nb]);
-
- apply_z(rx[0], ry[0], z);
-
- vli_set(result->x, rx[0]);
- vli_set(result->y, ry[0]);
-}
-
-static void ecc_bytes2native(const u8 bytes[ECC_BYTES],
- u64 native[NUM_ECC_DIGITS])
-{
- int i;
-
- for (i = 0; i < NUM_ECC_DIGITS; i++) {
- const u8 *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
-
- native[NUM_ECC_DIGITS - 1 - i] =
- ((u64) digit[0] << 0) |
- ((u64) digit[1] << 8) |
- ((u64) digit[2] << 16) |
- ((u64) digit[3] << 24) |
- ((u64) digit[4] << 32) |
- ((u64) digit[5] << 40) |
- ((u64) digit[6] << 48) |
- ((u64) digit[7] << 56);
- }
-}
-
-static void ecc_native2bytes(const u64 native[NUM_ECC_DIGITS],
- u8 bytes[ECC_BYTES])
-{
- int i;
-
- for (i = 0; i < NUM_ECC_DIGITS; i++) {
- u8 *digit = bytes + 8 * (NUM_ECC_DIGITS - 1 - i);
-
- digit[0] = native[NUM_ECC_DIGITS - 1 - i] >> 0;
- digit[1] = native[NUM_ECC_DIGITS - 1 - i] >> 8;
- digit[2] = native[NUM_ECC_DIGITS - 1 - i] >> 16;
- digit[3] = native[NUM_ECC_DIGITS - 1 - i] >> 24;
- digit[4] = native[NUM_ECC_DIGITS - 1 - i] >> 32;
- digit[5] = native[NUM_ECC_DIGITS - 1 - i] >> 40;
- digit[6] = native[NUM_ECC_DIGITS - 1 - i] >> 48;
- digit[7] = native[NUM_ECC_DIGITS - 1 - i] >> 56;
- }
-}
-
-bool ecc_make_key(u8 public_key[64], u8 private_key[32])
-{
- struct ecc_point pk;
- u64 priv[NUM_ECC_DIGITS];
- unsigned int tries = 0;
-
- do {
- if (tries++ >= MAX_TRIES)
- return false;
-
- get_random_bytes(priv, ECC_BYTES);
-
- if (vli_is_zero(priv))
- continue;
-
- /* Make sure the private key is in the range [1, n-1]. */
- if (vli_cmp(curve_n, priv) != 1)
- continue;
-
- ecc_point_mult(&pk, &curve_g, priv, NULL, vli_num_bits(priv));
- } while (ecc_point_is_zero(&pk));
-
- ecc_native2bytes(priv, private_key);
- ecc_native2bytes(pk.x, public_key);
- ecc_native2bytes(pk.y, &public_key[32]);
-
- return true;
-}
-
-bool ecdh_shared_secret(const u8 public_key[64], const u8 private_key[32],
- u8 secret[32])
-{
- u64 priv[NUM_ECC_DIGITS];
- u64 rand[NUM_ECC_DIGITS];
- struct ecc_point product, pk;
-
- get_random_bytes(rand, ECC_BYTES);
-
- ecc_bytes2native(public_key, pk.x);
- ecc_bytes2native(&public_key[32], pk.y);
- ecc_bytes2native(private_key, priv);
-
- ecc_point_mult(&product, &pk, priv, rand, vli_num_bits(priv));
-
- ecc_native2bytes(product.x, secret);
-
- return !ecc_point_is_zero(&product);
-}
diff --git a/net/bluetooth/ecc.h b/net/bluetooth/ecc.h
deleted file mode 100644
index 8d6a2f4..0000000
--- a/net/bluetooth/ecc.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2013, Kenneth MacKay
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/* Create a public/private key pair.
- * Outputs:
- * public_key - Will be filled in with the public key.
- * private_key - Will be filled in with the private key.
- *
- * Returns true if the key pair was generated successfully, false
- * if an error occurred. The keys are with the LSB first.
- */
-bool ecc_make_key(u8 public_key[64], u8 private_key[32]);
-
-/* Compute a shared secret given your secret key and someone else's
- * public key.
- * Note: It is recommended that you hash the result of ecdh_shared_secret
- * before using it for symmetric encryption or HMAC.
- *
- * Inputs:
- * public_key - The public key of the remote party
- * private_key - Your private key.
- *
- * Outputs:
- * secret - Will be filled in with the shared secret value.
- *
- * Returns true if the shared secret was generated successfully, false
- * if an error occurred. Both input and output parameters are with the
- * LSB first.
- */
-bool ecdh_shared_secret(const u8 public_key[64], const u8 private_key[32],
- u8 secret[32]);
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c
index fe18825..b9517bd 100644
--- a/net/bluetooth/hci_conn.c
+++ b/net/bluetooth/hci_conn.c
@@ -141,11 +141,10 @@
*/
if (conn->type == ACL_LINK && conn->role == HCI_ROLE_MASTER) {
struct hci_dev *hdev = conn->hdev;
- struct hci_cp_read_clock_offset clkoff_cp;
+ struct hci_cp_read_clock_offset cp;
- clkoff_cp.handle = cpu_to_le16(conn->handle);
- hci_send_cmd(hdev, HCI_OP_READ_CLOCK_OFFSET, sizeof(clkoff_cp),
- &clkoff_cp);
+ cp.handle = cpu_to_le16(conn->handle);
+ hci_send_cmd(hdev, HCI_OP_READ_CLOCK_OFFSET, sizeof(cp), &cp);
}
conn->state = BT_DISCONN;
@@ -416,7 +415,7 @@
* happen with broken hardware or if low duty cycle was used
* (which doesn't have a timeout of its own).
*/
- if (conn->role == HCI_ROLE_SLAVE) {
+ if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) {
u8 enable = 0x00;
hci_send_cmd(hdev, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable),
&enable);
@@ -449,7 +448,6 @@
conn->io_capability = hdev->io_capability;
conn->remote_auth = 0xff;
conn->key_type = 0xff;
- conn->rssi = HCI_RSSI_INVALID;
conn->tx_power = HCI_TX_POWER_INVALID;
conn->max_tx_power = HCI_TX_POWER_INVALID;
@@ -519,7 +517,7 @@
/* Unacked frames */
hdev->acl_cnt += conn->sent;
} else if (conn->type == LE_LINK) {
- cancel_delayed_work(&conn->le_conn_timeout);
+ cancel_delayed_work_sync(&conn->le_conn_timeout);
if (hdev->le_pkts)
hdev->le_cnt += conn->sent;
@@ -546,9 +544,6 @@
hci_conn_del_sysfs(conn);
- if (test_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags))
- hci_conn_params_del(conn->hdev, &conn->dst, conn->dst_type);
-
hci_dev_put(hdev);
hci_conn_put(conn);
@@ -661,7 +656,7 @@
memset(&cp, 0, sizeof(cp));
/* Update random address, but set require_privacy to false so
- * that we never connect with an non-resolvable address.
+ * that we never connect with an unresolvable address.
*/
if (hci_update_random_address(req, false, &own_addr_type))
return;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 5dcacf9..cb05d7f 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -200,6 +200,31 @@
.release = single_release,
};
+static int whitelist_show(struct seq_file *f, void *p)
+{
+ struct hci_dev *hdev = f->private;
+ struct bdaddr_list *b;
+
+ hci_dev_lock(hdev);
+ list_for_each_entry(b, &hdev->whitelist, list)
+ seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
+ hci_dev_unlock(hdev);
+
+ return 0;
+}
+
+static int whitelist_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, whitelist_show, inode->i_private);
+}
+
+static const struct file_operations whitelist_fops = {
+ .open = whitelist_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
static int uuids_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
@@ -274,13 +299,15 @@
static int link_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
- struct link_key *key;
+ struct list_head *p, *n;
- rcu_read_lock();
- list_for_each_entry_rcu(key, &hdev->link_keys, list)
+ hci_dev_lock(hdev);
+ list_for_each_safe(p, n, &hdev->link_keys) {
+ struct link_key *key = list_entry(p, struct link_key, list);
seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
HCI_LINK_KEY_SIZE, key->val, key->pin_len);
- rcu_read_unlock();
+ }
+ hci_dev_unlock(hdev);
return 0;
}
@@ -406,49 +433,6 @@
.llseek = default_llseek,
};
-static ssize_t force_lesc_support_read(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct hci_dev *hdev = file->private_data;
- char buf[3];
-
- buf[0] = test_bit(HCI_FORCE_LESC, &hdev->dbg_flags) ? 'Y': 'N';
- buf[1] = '\n';
- buf[2] = '\0';
- return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
-}
-
-static ssize_t force_lesc_support_write(struct file *file,
- const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct hci_dev *hdev = file->private_data;
- char buf[32];
- size_t buf_size = min(count, (sizeof(buf)-1));
- bool enable;
-
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
-
- buf[buf_size] = '\0';
- if (strtobool(buf, &enable))
- return -EINVAL;
-
- if (enable == test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
- return -EALREADY;
-
- change_bit(HCI_FORCE_LESC, &hdev->dbg_flags);
-
- return count;
-}
-
-static const struct file_operations force_lesc_support_fops = {
- .open = simple_open,
- .read = force_lesc_support_read,
- .write = force_lesc_support_write,
- .llseek = default_llseek,
-};
-
static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -789,15 +773,16 @@
static int identity_resolving_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
- struct smp_irk *irk;
+ struct list_head *p, *n;
- rcu_read_lock();
- list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
+ hci_dev_lock(hdev);
+ list_for_each_safe(p, n, &hdev->identity_resolving_keys) {
+ struct smp_irk *irk = list_entry(p, struct smp_irk, list);
seq_printf(f, "%pMR (type %u) %*phN %pMR\n",
&irk->bdaddr, irk->addr_type,
16, irk->val, &irk->rpa);
}
- rcu_read_unlock();
+ hci_dev_unlock(hdev);
return 0;
}
@@ -818,15 +803,17 @@
static int long_term_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
- struct smp_ltk *ltk;
+ struct list_head *p, *n;
- rcu_read_lock();
- list_for_each_entry_rcu(ltk, &hdev->long_term_keys, list)
+ hci_dev_lock(hdev);
+ list_for_each_safe(p, n, &hdev->long_term_keys) {
+ struct smp_ltk *ltk = list_entry(p, struct smp_ltk, list);
seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n",
<k->bdaddr, ltk->bdaddr_type, ltk->authenticated,
ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv),
__le64_to_cpu(ltk->rand), 16, ltk->val);
- rcu_read_unlock();
+ }
+ hci_dev_unlock(hdev);
return 0;
}
@@ -1043,13 +1030,10 @@
{
struct hci_dev *hdev = f->private;
struct hci_conn_params *p;
- struct bdaddr_list *b;
hci_dev_lock(hdev);
- list_for_each_entry(b, &hdev->whitelist, list)
- seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
list_for_each_entry(p, &hdev->le_conn_params, list) {
- seq_printf(f, "%pMR (type %u) %u\n", &p->addr, p->addr_type,
+ seq_printf(f, "%pMR %u %u\n", &p->addr, p->addr_type,
p->auto_connect);
}
hci_dev_unlock(hdev);
@@ -1163,16 +1147,13 @@
hdev->req_status = HCI_REQ_PEND;
+ err = hci_req_run(&req, hci_req_sync_complete);
+ if (err < 0)
+ return ERR_PTR(err);
+
add_wait_queue(&hdev->req_wait_q, &wait);
set_current_state(TASK_INTERRUPTIBLE);
- err = hci_req_run(&req, hci_req_sync_complete);
- if (err < 0) {
- remove_wait_queue(&hdev->req_wait_q, &wait);
- set_current_state(TASK_RUNNING);
- return ERR_PTR(err);
- }
-
schedule_timeout(timeout);
remove_wait_queue(&hdev->req_wait_q, &wait);
@@ -1230,16 +1211,10 @@
func(&req, opt);
- add_wait_queue(&hdev->req_wait_q, &wait);
- set_current_state(TASK_INTERRUPTIBLE);
-
err = hci_req_run(&req, hci_req_sync_complete);
if (err < 0) {
hdev->req_status = 0;
- remove_wait_queue(&hdev->req_wait_q, &wait);
- set_current_state(TASK_RUNNING);
-
/* ENODATA means the HCI request command queue is empty.
* This can happen when a request with conditionals doesn't
* trigger any commands to be sent. This is normal behavior
@@ -1251,6 +1226,9 @@
return err;
}
+ add_wait_queue(&hdev->req_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+
schedule_timeout(timeout);
remove_wait_queue(&hdev->req_wait_q, &wait);
@@ -1373,6 +1351,8 @@
static void bredr_setup(struct hci_request *req)
{
+ struct hci_dev *hdev = req->hdev;
+
__le16 param;
__u8 flt_type;
@@ -1401,6 +1381,14 @@
/* Connection accept timeout ~20 secs */
param = cpu_to_le16(0x7d00);
hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m);
+
+ /* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2,
+ * but it does not support page scan related HCI commands.
+ */
+ if (hdev->manufacturer != 31 && hdev->hci_ver > BLUETOOTH_VER_1_1) {
+ hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
+ hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL);
+ }
}
static void le_setup(struct hci_request *req)
@@ -1708,16 +1696,6 @@
if (hdev->commands[5] & 0x10)
hci_setup_link_policy(req);
- if (hdev->commands[8] & 0x01)
- hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL);
-
- /* Some older Broadcom based Bluetooth 1.2 controllers do not
- * support the Read Page Scan Type command. Check support for
- * this command in the bit mask of supported commands.
- */
- if (hdev->commands[13] & 0x01)
- hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL);
-
if (lmp_le_capable(hdev)) {
u8 events[8];
@@ -1735,28 +1713,6 @@
* Parameter Request
*/
- /* If the controller supports Extended Scanner Filter
- * Policies, enable the correspondig event.
- */
- if (hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY)
- events[1] |= 0x04; /* LE Direct Advertising
- * Report
- */
-
- /* If the controller supports the LE Read Local P-256
- * Public Key command, enable the corresponding event.
- */
- if (hdev->commands[34] & 0x02)
- events[0] |= 0x80; /* LE Read Local P-256
- * Public Key Complete
- */
-
- /* If the controller supports the LE Generate DHKey
- * command, enable the corresponding event.
- */
- if (hdev->commands[34] & 0x04)
- events[1] |= 0x01; /* LE Generate DHKey Complete */
-
hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events),
events);
@@ -1799,7 +1755,9 @@
hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL);
/* Enable Secure Connections if supported and configured */
- if (bredr_sc_enabled(hdev)) {
+ if ((lmp_sc_capable(hdev) ||
+ test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) &&
+ test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
u8 support = 0x01;
hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT,
sizeof(support), &support);
@@ -1853,10 +1811,10 @@
&hdev->manufacturer);
debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
- debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
- &device_list_fops);
debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
&blacklist_fops);
+ debugfs_create_file("whitelist", 0444, hdev->debugfs, hdev,
+ &whitelist_fops);
debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev,
@@ -1882,10 +1840,6 @@
hdev, &force_sc_support_fops);
debugfs_create_file("sc_only_mode", 0444, hdev->debugfs,
hdev, &sc_only_mode_fops);
- if (lmp_le_capable(hdev))
- debugfs_create_file("force_lesc_support", 0644,
- hdev->debugfs, hdev,
- &force_lesc_support_fops);
}
if (lmp_sniff_capable(hdev)) {
@@ -1939,6 +1893,8 @@
hdev, &adv_min_interval_fops);
debugfs_create_file("adv_max_interval", 0644, hdev->debugfs,
hdev, &adv_max_interval_fops);
+ debugfs_create_file("device_list", 0444, hdev->debugfs, hdev,
+ &device_list_fops);
debugfs_create_u16("discov_interleaved_timeout", 0644,
hdev->debugfs,
&hdev->discov_interleaved_timeout);
@@ -2182,7 +2138,7 @@
BT_DBG("cache %p, %pMR", cache, &data->bdaddr);
- hci_remove_remote_oob_data(hdev, &data->bdaddr, BDADDR_BREDR);
+ hci_remove_remote_oob_data(hdev, &data->bdaddr);
if (!data->ssp_mode)
flags |= MGMT_DEV_FOUND_LEGACY_PAIRING;
@@ -2628,18 +2584,7 @@
if (test_bit(HCI_MGMT, &hdev->dev_flags))
cancel_delayed_work_sync(&hdev->rpa_expired);
- /* Avoid potential lockdep warnings from the *_flush() calls by
- * ensuring the workqueue is empty up front.
- */
- drain_workqueue(hdev->workqueue);
-
hci_dev_lock(hdev);
-
- if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
- if (hdev->dev_type == HCI_BREDR)
- mgmt_powered(hdev, 0);
- }
-
hci_inquiry_cache_flush(hdev);
hci_pend_le_actions_clear(hdev);
hci_conn_hash_flush(hdev);
@@ -2687,6 +2632,14 @@
hdev->flags &= BIT(HCI_RAW);
hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
+ if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) {
+ if (hdev->dev_type == HCI_BREDR) {
+ hci_dev_lock(hdev);
+ mgmt_powered(hdev, 0);
+ hci_dev_unlock(hdev);
+ }
+ }
+
/* Controller radio is available but is currently powered down */
hdev->amp_status = AMP_STATUS_POWERED_DOWN;
@@ -2754,11 +2707,6 @@
skb_queue_purge(&hdev->rx_q);
skb_queue_purge(&hdev->cmd_q);
- /* Avoid potential lockdep warnings from the *_flush() calls by
- * ensuring the workqueue is empty up front.
- */
- drain_workqueue(hdev->workqueue);
-
hci_dev_lock(hdev);
hci_inquiry_cache_flush(hdev);
hci_conn_hash_flush(hdev);
@@ -3081,9 +3029,7 @@
err = hci_dev_do_open(hdev);
if (err < 0) {
- hci_dev_lock(hdev);
mgmt_set_powered_failed(hdev, err);
- hci_dev_unlock(hdev);
return;
}
@@ -3166,31 +3112,35 @@
void hci_link_keys_clear(struct hci_dev *hdev)
{
- struct link_key *key;
+ struct list_head *p, *n;
- list_for_each_entry_rcu(key, &hdev->link_keys, list) {
- list_del_rcu(&key->list);
- kfree_rcu(key, rcu);
+ list_for_each_safe(p, n, &hdev->link_keys) {
+ struct link_key *key;
+
+ key = list_entry(p, struct link_key, list);
+
+ list_del(p);
+ kfree(key);
}
}
void hci_smp_ltks_clear(struct hci_dev *hdev)
{
- struct smp_ltk *k;
+ struct smp_ltk *k, *tmp;
- list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
- list_del_rcu(&k->list);
- kfree_rcu(k, rcu);
+ list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
+ list_del(&k->list);
+ kfree(k);
}
}
void hci_smp_irks_clear(struct hci_dev *hdev)
{
- struct smp_irk *k;
+ struct smp_irk *k, *tmp;
- list_for_each_entry_rcu(k, &hdev->identity_resolving_keys, list) {
- list_del_rcu(&k->list);
- kfree_rcu(k, rcu);
+ list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
+ list_del(&k->list);
+ kfree(k);
}
}
@@ -3198,14 +3148,9 @@
{
struct link_key *k;
- rcu_read_lock();
- list_for_each_entry_rcu(k, &hdev->link_keys, list) {
- if (bacmp(bdaddr, &k->bdaddr) == 0) {
- rcu_read_unlock();
+ list_for_each_entry(k, &hdev->link_keys, list)
+ if (bacmp(bdaddr, &k->bdaddr) == 0)
return k;
- }
- }
- rcu_read_unlock();
return NULL;
}
@@ -3229,10 +3174,6 @@
if (!conn)
return true;
- /* BR/EDR key derived using SC from an LE link */
- if (conn->type == LE_LINK)
- return true;
-
/* Neither local nor remote side had no-bonding as requirement */
if (conn->auth_type > 0x01 && conn->remote_auth > 0x01)
return true;
@@ -3258,22 +3199,34 @@
return HCI_ROLE_SLAVE;
}
-struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 addr_type, u8 role)
+struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand,
+ u8 role)
{
struct smp_ltk *k;
- rcu_read_lock();
- list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
- if (addr_type != k->bdaddr_type || bacmp(bdaddr, &k->bdaddr))
+ list_for_each_entry(k, &hdev->long_term_keys, list) {
+ if (k->ediv != ediv || k->rand != rand)
continue;
- if (smp_ltk_is_sc(k) || ltk_role(k->type) == role) {
- rcu_read_unlock();
- return k;
- }
+ if (ltk_role(k->type) != role)
+ continue;
+
+ return k;
}
- rcu_read_unlock();
+
+ return NULL;
+}
+
+struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 addr_type, u8 role)
+{
+ struct smp_ltk *k;
+
+ list_for_each_entry(k, &hdev->long_term_keys, list)
+ if (addr_type == k->bdaddr_type &&
+ bacmp(bdaddr, &k->bdaddr) == 0 &&
+ ltk_role(k->type) == role)
+ return k;
return NULL;
}
@@ -3282,22 +3235,17 @@
{
struct smp_irk *irk;
- rcu_read_lock();
- list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
- if (!bacmp(&irk->rpa, rpa)) {
- rcu_read_unlock();
+ list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
+ if (!bacmp(&irk->rpa, rpa))
return irk;
- }
}
- list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
+ list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
if (smp_irk_matches(hdev, irk->val, rpa)) {
bacpy(&irk->rpa, rpa);
- rcu_read_unlock();
return irk;
}
}
- rcu_read_unlock();
return NULL;
}
@@ -3311,15 +3259,11 @@
if (addr_type == ADDR_LE_DEV_RANDOM && (bdaddr->b[5] & 0xc0) != 0xc0)
return NULL;
- rcu_read_lock();
- list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
+ list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
if (addr_type == irk->addr_type &&
- bacmp(bdaddr, &irk->bdaddr) == 0) {
- rcu_read_unlock();
+ bacmp(bdaddr, &irk->bdaddr) == 0)
return irk;
- }
}
- rcu_read_unlock();
return NULL;
}
@@ -3340,7 +3284,7 @@
key = kzalloc(sizeof(*key), GFP_KERNEL);
if (!key)
return NULL;
- list_add_rcu(&key->list, &hdev->link_keys);
+ list_add(&key->list, &hdev->link_keys);
}
BT_DBG("%s key for %pMR type %u", hdev->name, bdaddr, type);
@@ -3378,14 +3322,14 @@
struct smp_ltk *key, *old_key;
u8 role = ltk_role(type);
- old_key = hci_find_ltk(hdev, bdaddr, addr_type, role);
+ old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, role);
if (old_key)
key = old_key;
else {
key = kzalloc(sizeof(*key), GFP_KERNEL);
if (!key)
return NULL;
- list_add_rcu(&key->list, &hdev->long_term_keys);
+ list_add(&key->list, &hdev->long_term_keys);
}
bacpy(&key->bdaddr, bdaddr);
@@ -3414,7 +3358,7 @@
bacpy(&irk->bdaddr, bdaddr);
irk->addr_type = addr_type;
- list_add_rcu(&irk->list, &hdev->identity_resolving_keys);
+ list_add(&irk->list, &hdev->identity_resolving_keys);
}
memcpy(irk->val, val, 16);
@@ -3433,25 +3377,25 @@
BT_DBG("%s removing %pMR", hdev->name, bdaddr);
- list_del_rcu(&key->list);
- kfree_rcu(key, rcu);
+ list_del(&key->list);
+ kfree(key);
return 0;
}
int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type)
{
- struct smp_ltk *k;
+ struct smp_ltk *k, *tmp;
int removed = 0;
- list_for_each_entry_rcu(k, &hdev->long_term_keys, list) {
+ list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) {
if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type)
continue;
BT_DBG("%s removing %pMR", hdev->name, bdaddr);
- list_del_rcu(&k->list);
- kfree_rcu(k, rcu);
+ list_del(&k->list);
+ kfree(k);
removed++;
}
@@ -3460,16 +3404,16 @@
void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type)
{
- struct smp_irk *k;
+ struct smp_irk *k, *tmp;
- list_for_each_entry_rcu(k, &hdev->identity_resolving_keys, list) {
+ list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) {
if (bacmp(bdaddr, &k->bdaddr) || k->addr_type != addr_type)
continue;
BT_DBG("%s removing %pMR", hdev->name, bdaddr);
- list_del_rcu(&k->list);
- kfree_rcu(k, rcu);
+ list_del(&k->list);
+ kfree(k);
}
}
@@ -3493,31 +3437,26 @@
}
struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
- bdaddr_t *bdaddr, u8 bdaddr_type)
+ bdaddr_t *bdaddr)
{
struct oob_data *data;
- list_for_each_entry(data, &hdev->remote_oob_data, list) {
- if (bacmp(bdaddr, &data->bdaddr) != 0)
- continue;
- if (data->bdaddr_type != bdaddr_type)
- continue;
- return data;
- }
+ list_for_each_entry(data, &hdev->remote_oob_data, list)
+ if (bacmp(bdaddr, &data->bdaddr) == 0)
+ return data;
return NULL;
}
-int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 bdaddr_type)
+int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct oob_data *data;
- data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
+ data = hci_find_remote_oob_data(hdev, bdaddr);
if (!data)
return -ENOENT;
- BT_DBG("%s removing %pMR (%u)", hdev->name, bdaddr, bdaddr_type);
+ BT_DBG("%s removing %pMR", hdev->name, bdaddr);
list_del(&data->list);
kfree(data);
@@ -3536,37 +3475,52 @@
}
int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
- u8 bdaddr_type, u8 *hash192, u8 *rand192,
- u8 *hash256, u8 *rand256)
+ u8 *hash, u8 *randomizer)
{
struct oob_data *data;
- data = hci_find_remote_oob_data(hdev, bdaddr, bdaddr_type);
+ data = hci_find_remote_oob_data(hdev, bdaddr);
if (!data) {
data = kmalloc(sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
bacpy(&data->bdaddr, bdaddr);
- data->bdaddr_type = bdaddr_type;
list_add(&data->list, &hdev->remote_oob_data);
}
- if (hash192 && rand192) {
- memcpy(data->hash192, hash192, sizeof(data->hash192));
- memcpy(data->rand192, rand192, sizeof(data->rand192));
- } else {
- memset(data->hash192, 0, sizeof(data->hash192));
- memset(data->rand192, 0, sizeof(data->rand192));
+ memcpy(data->hash192, hash, sizeof(data->hash192));
+ memcpy(data->randomizer192, randomizer, sizeof(data->randomizer192));
+
+ memset(data->hash256, 0, sizeof(data->hash256));
+ memset(data->randomizer256, 0, sizeof(data->randomizer256));
+
+ BT_DBG("%s for %pMR", hdev->name, bdaddr);
+
+ return 0;
+}
+
+int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ u8 *hash192, u8 *randomizer192,
+ u8 *hash256, u8 *randomizer256)
+{
+ struct oob_data *data;
+
+ data = hci_find_remote_oob_data(hdev, bdaddr);
+ if (!data) {
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ bacpy(&data->bdaddr, bdaddr);
+ list_add(&data->list, &hdev->remote_oob_data);
}
- if (hash256 && rand256) {
- memcpy(data->hash256, hash256, sizeof(data->hash256));
- memcpy(data->rand256, rand256, sizeof(data->rand256));
- } else {
- memset(data->hash256, 0, sizeof(data->hash256));
- memset(data->rand256, 0, sizeof(data->rand256));
- }
+ memcpy(data->hash192, hash192, sizeof(data->hash192));
+ memcpy(data->randomizer192, randomizer192, sizeof(data->randomizer192));
+
+ memcpy(data->hash256, hash256, sizeof(data->hash256));
+ memcpy(data->randomizer256, randomizer256, sizeof(data->randomizer256));
BT_DBG("%s for %pMR", hdev->name, bdaddr);
@@ -3959,29 +3913,17 @@
}
/* In case of required privacy without resolvable private address,
- * use an non-resolvable private address. This is useful for active
+ * use an unresolvable private address. This is useful for active
* scanning and non-connectable advertising.
*/
if (require_privacy) {
- bdaddr_t nrpa;
+ bdaddr_t urpa;
- while (true) {
- /* The non-resolvable private address is generated
- * from random six bytes with the two most significant
- * bits cleared.
- */
- get_random_bytes(&nrpa, 6);
- nrpa.b[5] &= 0x3f;
-
- /* The non-resolvable private address shall not be
- * equal to the public address.
- */
- if (bacmp(&hdev->bdaddr, &nrpa))
- break;
- }
+ get_random_bytes(&urpa, 6);
+ urpa.b[5] &= 0x3f; /* Clear two most significant bits */
*own_addr_type = ADDR_LE_DEV_RANDOM;
- set_random_addr(req, &nrpa);
+ set_random_addr(req, &urpa);
return 0;
}
@@ -4278,7 +4220,6 @@
hci_remote_oob_data_clear(hdev);
hci_bdaddr_list_clear(&hdev->le_white_list);
hci_conn_params_clear_all(hdev);
- hci_discovery_filter_clear(hdev);
hci_dev_unlock(hdev);
hci_dev_put(hdev);
@@ -4303,24 +4244,6 @@
}
EXPORT_SYMBOL(hci_resume_dev);
-/* Reset HCI device */
-int hci_reset_dev(struct hci_dev *hdev)
-{
- const u8 hw_err[] = { HCI_EV_HARDWARE_ERROR, 0x01, 0x00 };
- struct sk_buff *skb;
-
- skb = bt_skb_alloc(3, GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- bt_cb(skb)->pkt_type = HCI_EVENT_PKT;
- memcpy(skb_put(skb, 3), hw_err, 3);
-
- /* Send Hardware Error to upper stack */
- return hci_recv_frame(hdev, skb);
-}
-EXPORT_SYMBOL(hci_reset_dev);
-
/* Receive frame from HCI drivers */
int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
@@ -4554,7 +4477,7 @@
BT_DBG("length %u", skb_queue_len(&req->cmd_q));
- /* If an error occurred during request building, remove all HCI
+ /* If an error occured during request building, remove all HCI
* commands queued on the HCI request queue.
*/
if (req->err) {
@@ -4623,7 +4546,7 @@
return -ENOMEM;
}
- /* Stand-alone HCI commands must be flagged as
+ /* Stand-alone HCI commands must be flaged as
* single-command requests.
*/
bt_cb(skb)->req.start = true;
@@ -4643,7 +4566,7 @@
BT_DBG("%s opcode 0x%4.4x plen %d", hdev->name, opcode, plen);
- /* If an error occurred during request building, there is no point in
+ /* If an error occured during request building, there is no point in
* queueing the HCI command. We can simply return.
*/
if (req->err)
@@ -4738,12 +4661,8 @@
skb_shinfo(skb)->frag_list = NULL;
- /* Queue all fragments atomically. We need to use spin_lock_bh
- * here because of 6LoWPAN links, as there this function is
- * called from softirq and using normal spin lock could cause
- * deadlocks.
- */
- spin_lock_bh(&queue->lock);
+ /* Queue all fragments atomically */
+ spin_lock(&queue->lock);
__skb_queue_tail(queue, skb);
@@ -4760,7 +4679,7 @@
__skb_queue_tail(queue, skb);
} while (list);
- spin_unlock_bh(&queue->lock);
+ spin_unlock(&queue->lock);
}
}
@@ -5637,7 +5556,7 @@
u8 filter_policy;
/* Set require_privacy to false since no SCAN_REQ are send
- * during passive scanning. Not using an non-resolvable address
+ * during passive scanning. Not using an unresolvable address
* here is important so that peer devices using direct
* advertising with our address will be correctly reported
* by the controller.
@@ -5651,19 +5570,6 @@
*/
filter_policy = update_white_list(req);
- /* When the controller is using random resolvable addresses and
- * with that having LE privacy enabled, then controllers with
- * Extended Scanner Filter Policies support can now enable support
- * for handling directed advertising.
- *
- * So instead of using filter polices 0x00 (no whitelist)
- * and 0x01 (whitelist enabled) use the new filter policies
- * 0x02 (no whitelist) and 0x03 (whitelist enabled).
- */
- if (test_bit(HCI_PRIVACY, &hdev->dev_flags) &&
- (hdev->le_features[0] & HCI_LE_EXT_SCAN_POLICY))
- filter_policy |= 0x02;
-
memset(¶m_cp, 0, sizeof(param_cp));
param_cp.type = LE_SCAN_PASSIVE;
param_cp.interval = cpu_to_le16(hdev->le_scan_interval);
@@ -5715,15 +5621,6 @@
if (hdev->discovery.state != DISCOVERY_STOPPED)
return;
- /* Reset RSSI and UUID filters when starting background scanning
- * since these filters are meant for service discovery only.
- *
- * The Start Discovery and Start Service Discovery operations
- * ensure to set proper values for RSSI threshold and UUID
- * filter list. So it is safe to just reset them here.
- */
- hci_discovery_filter_clear(hdev);
-
hci_req_init(&req, hdev);
if (list_empty(&hdev->pend_le_conns) &&
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 39a5c8a..8b0a2a6 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -189,9 +189,6 @@
clear_bit(HCI_RESET, &hdev->flags);
- if (status)
- return;
-
/* Reset all non-persistent flags */
hdev->dev_flags &= ~HCI_PERSISTENT_MASK;
@@ -208,8 +205,6 @@
hdev->le_scan_type = LE_SCAN_PASSIVE;
hdev->ssp_debug_mode = 0;
-
- hci_bdaddr_list_clear(&hdev->le_white_list);
}
static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
@@ -257,8 +252,6 @@
if (!sent)
return;
- hci_dev_lock(hdev);
-
if (!status) {
__u8 param = *((__u8 *) sent);
@@ -270,8 +263,6 @@
if (test_bit(HCI_MGMT, &hdev->dev_flags))
mgmt_auth_enable_complete(hdev, status);
-
- hci_dev_unlock(hdev);
}
static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb)
@@ -447,8 +438,6 @@
if (!sent)
return;
- hci_dev_lock(hdev);
-
if (!status) {
if (sent->mode)
hdev->features[1][0] |= LMP_HOST_SSP;
@@ -464,8 +453,6 @@
else
clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags);
}
-
- hci_dev_unlock(hdev);
}
static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb)
@@ -479,8 +466,6 @@
if (!sent)
return;
- hci_dev_lock(hdev);
-
if (!status) {
if (sent->support)
hdev->features[1][0] |= LMP_HOST_SC;
@@ -496,8 +481,6 @@
else
clear_bit(HCI_SC_ENABLED, &hdev->dev_flags);
}
-
- hci_dev_unlock(hdev);
}
static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1006,8 +989,8 @@
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
hci_dev_lock(hdev);
- mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->rand, NULL, NULL,
- rp->status);
+ mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer,
+ NULL, NULL, rp->status);
hci_dev_unlock(hdev);
}
@@ -1019,8 +1002,8 @@
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
hci_dev_lock(hdev);
- mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->rand192,
- rp->hash256, rp->rand256,
+ mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192,
+ rp->hash256, rp->randomizer256,
rp->status);
hci_dev_unlock(hdev);
}
@@ -1062,7 +1045,7 @@
hci_dev_lock(hdev);
- /* If we're doing connection initiation as peripheral. Set a
+ /* If we're doing connection initation as peripheral. Set a
* timeout in case something goes wrong.
*/
if (*sent) {
@@ -1147,8 +1130,6 @@
if (!cp)
return;
- hci_dev_lock(hdev);
-
switch (cp->enable) {
case LE_SCAN_ENABLE:
set_bit(HCI_LE_SCAN, &hdev->dev_flags);
@@ -1198,8 +1179,6 @@
BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable);
break;
}
-
- hci_dev_unlock(hdev);
}
static void hci_cc_le_read_white_list_size(struct hci_dev *hdev,
@@ -1294,8 +1273,6 @@
if (!sent)
return;
- hci_dev_lock(hdev);
-
if (sent->le) {
hdev->features[1][0] |= LMP_HOST_LE;
set_bit(HCI_LE_ENABLED, &hdev->dev_flags);
@@ -1309,8 +1286,6 @@
hdev->features[1][0] |= LMP_HOST_LE_BREDR;
else
hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
-
- hci_dev_unlock(hdev);
}
static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb)
@@ -1601,15 +1576,9 @@
struct discovery_state *discov = &hdev->discovery;
struct inquiry_entry *e;
- /* Update the mgmt connected state if necessary. Be careful with
- * conn objects that exist but are not (yet) connected however.
- * Only those in BT_CONFIG or BT_CONNECTED states can be
- * considered connected.
- */
- if (conn &&
- (conn->state == BT_CONFIG || conn->state == BT_CONNECTED) &&
- !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
- mgmt_device_connected(hdev, conn, 0, name, name_len);
+ if (conn && !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
+ mgmt_device_connected(hdev, bdaddr, ACL_LINK, 0x00, 0, name,
+ name_len, conn->dev_class);
if (discov->state == DISCOVERY_STOPPED)
return;
@@ -1974,29 +1943,6 @@
hci_dev_unlock(hdev);
}
-static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
-{
- struct hci_cp_switch_role *cp;
- struct hci_conn *conn;
-
- BT_DBG("%s status 0x%2.2x", hdev->name, status);
-
- if (!status)
- return;
-
- cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE);
- if (!cp)
- return;
-
- hci_dev_lock(hdev);
-
- conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
- if (conn)
- clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
-
- hci_dev_unlock(hdev);
-}
-
static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
__u8 status = *((__u8 *) skb->data);
@@ -2063,14 +2009,13 @@
data.pscan_mode = info->pscan_mode;
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
- data.rssi = HCI_RSSI_INVALID;
+ data.rssi = 0x00;
data.ssp_mode = 0x00;
flags = hci_inquiry_cache_update(hdev, &data, false);
mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
- info->dev_class, HCI_RSSI_INVALID,
- flags, NULL, 0, NULL, 0);
+ info->dev_class, 0, flags, NULL, 0, NULL, 0);
}
hci_dev_unlock(hdev);
@@ -2591,7 +2536,9 @@
cp.pscan_rep_mode = 0x02;
hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
- mgmt_device_connected(hdev, conn, 0, NULL, 0);
+ mgmt_device_connected(hdev, &conn->dst, conn->type,
+ conn->dst_type, 0, NULL, 0,
+ conn->dev_class);
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
@@ -2901,10 +2848,6 @@
hci_cs_create_conn(hdev, ev->status);
break;
- case HCI_OP_DISCONNECT:
- hci_cs_disconnect(hdev, ev->status);
- break;
-
case HCI_OP_ADD_SCO:
hci_cs_add_sco(hdev, ev->status);
break;
@@ -2933,14 +2876,6 @@
hci_cs_setup_sync_conn(hdev, ev->status);
break;
- case HCI_OP_CREATE_PHY_LINK:
- hci_cs_create_phylink(hdev, ev->status);
- break;
-
- case HCI_OP_ACCEPT_PHY_LINK:
- hci_cs_accept_phylink(hdev, ev->status);
- break;
-
case HCI_OP_SNIFF_MODE:
hci_cs_sniff_mode(hdev, ev->status);
break;
@@ -2949,8 +2884,16 @@
hci_cs_exit_sniff_mode(hdev, ev->status);
break;
- case HCI_OP_SWITCH_ROLE:
- hci_cs_switch_role(hdev, ev->status);
+ case HCI_OP_DISCONNECT:
+ hci_cs_disconnect(hdev, ev->status);
+ break;
+
+ case HCI_OP_CREATE_PHY_LINK:
+ hci_cs_create_phylink(hdev, ev->status);
+ break;
+
+ case HCI_OP_ACCEPT_PHY_LINK:
+ hci_cs_accept_phylink(hdev, ev->status);
break;
case HCI_OP_LE_CREATE_CONN:
@@ -2980,13 +2923,6 @@
}
}
-static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb)
-{
- struct hci_ev_hardware_error *ev = (void *) skb->data;
-
- BT_ERR("%s hardware error 0x%2.2x", hdev->name, ev->code);
-}
-
static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_role_change *ev = (void *) skb->data;
@@ -3212,38 +3148,6 @@
hci_dev_unlock(hdev);
}
-static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
-{
- if (key_type == HCI_LK_CHANGED_COMBINATION)
- return;
-
- conn->pin_length = pin_len;
- conn->key_type = key_type;
-
- switch (key_type) {
- case HCI_LK_LOCAL_UNIT:
- case HCI_LK_REMOTE_UNIT:
- case HCI_LK_DEBUG_COMBINATION:
- return;
- case HCI_LK_COMBINATION:
- if (pin_len == 16)
- conn->pending_sec_level = BT_SECURITY_HIGH;
- else
- conn->pending_sec_level = BT_SECURITY_MEDIUM;
- break;
- case HCI_LK_UNAUTH_COMBINATION_P192:
- case HCI_LK_UNAUTH_COMBINATION_P256:
- conn->pending_sec_level = BT_SECURITY_MEDIUM;
- break;
- case HCI_LK_AUTH_COMBINATION_P192:
- conn->pending_sec_level = BT_SECURITY_HIGH;
- break;
- case HCI_LK_AUTH_COMBINATION_P256:
- conn->pending_sec_level = BT_SECURITY_FIPS;
- break;
- }
-}
-
static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_link_key_req *ev = (void *) skb->data;
@@ -3270,8 +3174,6 @@
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) {
- clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
-
if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
@@ -3287,7 +3189,8 @@
goto not_found;
}
- conn_set_key(conn, key->type, key->pin_len);
+ conn->key_type = key->type;
+ conn->pin_length = key->pin_len;
}
bacpy(&cp.bdaddr, &ev->bdaddr);
@@ -3317,15 +3220,16 @@
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
- if (!conn)
- goto unlock;
+ if (conn) {
+ hci_conn_hold(conn);
+ conn->disc_timeout = HCI_DISCONN_TIMEOUT;
+ pin_len = conn->pin_length;
- hci_conn_hold(conn);
- conn->disc_timeout = HCI_DISCONN_TIMEOUT;
- hci_conn_drop(conn);
+ if (ev->key_type != HCI_LK_CHANGED_COMBINATION)
+ conn->key_type = ev->key_type;
- set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
- conn_set_key(conn, ev->key_type, conn->pin_length);
+ hci_conn_drop(conn);
+ }
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
goto unlock;
@@ -3335,12 +3239,6 @@
if (!key)
goto unlock;
- /* Update connection information since adding the key will have
- * fixed up the type in the case of changed combination keys.
- */
- if (ev->key_type == HCI_LK_CHANGED_COMBINATION)
- conn_set_key(conn, key->type, key->pin_len);
-
mgmt_new_link_key(hdev, key, persistent);
/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
@@ -3350,16 +3248,15 @@
*/
if (key->type == HCI_LK_DEBUG_COMBINATION &&
!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) {
- list_del_rcu(&key->list);
- kfree_rcu(key, rcu);
- goto unlock;
+ list_del(&key->list);
+ kfree(key);
+ } else if (conn) {
+ if (persistent)
+ clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
+ else
+ set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
}
- if (persistent)
- clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
- else
- set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
-
unlock:
hci_dev_unlock(hdev);
}
@@ -3537,7 +3434,9 @@
cp.pscan_rep_mode = 0x02;
hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
- mgmt_device_connected(hdev, conn, 0, NULL, 0);
+ mgmt_device_connected(hdev, &conn->dst, conn->type,
+ conn->dst_type, 0, NULL, 0,
+ conn->dev_class);
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
@@ -3794,7 +3693,7 @@
cp.authentication = conn->auth_type;
- if (hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR) &&
+ if (hci_find_remote_oob_data(hdev, &conn->dst) &&
(conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags)))
cp.oob_data = 0x01;
else
@@ -4049,16 +3948,18 @@
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
goto unlock;
- data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR);
+ data = hci_find_remote_oob_data(hdev, &ev->bdaddr);
if (data) {
- if (bredr_sc_enabled(hdev)) {
+ if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) {
struct hci_cp_remote_oob_ext_data_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
- memcpy(cp.rand192, data->rand192, sizeof(cp.rand192));
+ memcpy(cp.randomizer192, data->randomizer192,
+ sizeof(cp.randomizer192));
memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
- memcpy(cp.rand256, data->rand256, sizeof(cp.rand256));
+ memcpy(cp.randomizer256, data->randomizer256,
+ sizeof(cp.randomizer256));
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
sizeof(cp), &cp);
@@ -4067,7 +3968,8 @@
bacpy(&cp.bdaddr, &ev->bdaddr);
memcpy(cp.hash, data->hash192, sizeof(cp.hash));
- memcpy(cp.rand, data->rand192, sizeof(cp.rand));
+ memcpy(cp.randomizer, data->randomizer192,
+ sizeof(cp.randomizer));
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
sizeof(cp), &cp);
@@ -4312,7 +4214,8 @@
}
if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
- mgmt_device_connected(hdev, conn, 0, NULL, 0);
+ mgmt_device_connected(hdev, &conn->dst, conn->type,
+ conn->dst_type, 0, NULL, 0, NULL);
conn->sec_level = BT_SECURITY_LOW;
conn->handle = __le16_to_cpu(ev->handle);
@@ -4366,26 +4269,25 @@
}
/* This function requires the caller holds hdev->lock */
-static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
- bdaddr_t *addr,
- u8 addr_type, u8 adv_type)
+static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr,
+ u8 addr_type, u8 adv_type)
{
struct hci_conn *conn;
struct hci_conn_params *params;
/* If the event is not connectable don't proceed further */
if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
- return NULL;
+ return;
/* Ignore if the device is blocked */
if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type))
- return NULL;
+ return;
/* Most controller will fail if we try to create new connections
* while we have an existing one in slave role.
*/
if (hdev->conn_hash.le_num_slave > 0)
- return NULL;
+ return;
/* If we're not connectable only connect devices that we have in
* our pend_le_conns list.
@@ -4393,7 +4295,7 @@
params = hci_pend_le_action_lookup(&hdev->pend_le_conns,
addr, addr_type);
if (!params)
- return NULL;
+ return;
switch (params->auto_connect) {
case HCI_AUTO_CONN_DIRECT:
@@ -4402,7 +4304,7 @@
* incoming connections from slave devices.
*/
if (adv_type != LE_ADV_DIRECT_IND)
- return NULL;
+ return;
break;
case HCI_AUTO_CONN_ALWAYS:
/* Devices advertising with ADV_IND or ADV_DIRECT_IND
@@ -4413,7 +4315,7 @@
*/
break;
default:
- return NULL;
+ return;
}
conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
@@ -4426,7 +4328,7 @@
* count consistent once the connection is established.
*/
params->conn = hci_conn_get(conn);
- return conn;
+ return;
}
switch (PTR_ERR(conn)) {
@@ -4439,48 +4341,17 @@
break;
default:
BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
- return NULL;
}
-
- return NULL;
}
static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
- u8 bdaddr_type, bdaddr_t *direct_addr,
- u8 direct_addr_type, s8 rssi, u8 *data, u8 len)
+ u8 bdaddr_type, s8 rssi, u8 *data, u8 len)
{
struct discovery_state *d = &hdev->discovery;
struct smp_irk *irk;
- struct hci_conn *conn;
bool match;
u32 flags;
- /* If the direct address is present, then this report is from
- * a LE Direct Advertising Report event. In that case it is
- * important to see if the address is matching the local
- * controller address.
- */
- if (direct_addr) {
- /* Only resolvable random addresses are valid for these
- * kind of reports and others can be ignored.
- */
- if (!hci_bdaddr_is_rpa(direct_addr, direct_addr_type))
- return;
-
- /* If the controller is not using resolvable random
- * addresses, then this report can be ignored.
- */
- if (!test_bit(HCI_PRIVACY, &hdev->dev_flags))
- return;
-
- /* If the local IRK of the controller does not match
- * with the resolvable random address provided, then
- * this report can be ignored.
- */
- if (!smp_irk_matches(hdev, hdev->irk, direct_addr))
- return;
- }
-
/* Check if we need to convert to identity address */
irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
if (irk) {
@@ -4489,14 +4360,7 @@
}
/* Check if we have been requested to connect to this device */
- conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);
- if (conn && type == LE_ADV_IND) {
- /* Store report for later inclusion by
- * mgmt_device_connected
- */
- memcpy(conn->le_adv_data, data, len);
- conn->le_adv_data_len = len;
- }
+ check_pending_le_conn(hdev, bdaddr, bdaddr_type, type);
/* Passive scanning shouldn't trigger any device found events,
* except for devices marked as CONN_REPORT for which we do send
@@ -4617,8 +4481,7 @@
rssi = ev->data[ev->length];
process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
- ev->bdaddr_type, NULL, 0, rssi,
- ev->data, ev->length);
+ ev->bdaddr_type, rssi, ev->data, ev->length);
ptr += sizeof(*ev) + ev->length + 1;
}
@@ -4642,20 +4505,10 @@
if (conn == NULL)
goto not_found;
- ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role);
- if (!ltk)
+ ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role);
+ if (ltk == NULL)
goto not_found;
- if (smp_ltk_is_sc(ltk)) {
- /* With SC both EDiv and Rand are set to zero */
- if (ev->ediv || ev->rand)
- goto not_found;
- } else {
- /* For non-SC keys check that EDiv and Rand match */
- if (ev->ediv != ltk->ediv || ev->rand != ltk->rand)
- goto not_found;
- }
-
memcpy(cp.ltk, ltk->val, sizeof(ltk->val));
cp.handle = cpu_to_le16(conn->handle);
@@ -4673,8 +4526,8 @@
*/
if (ltk->type == SMP_STK) {
set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
- list_del_rcu(<k->list);
- kfree_rcu(ltk, rcu);
+ list_del(<k->list);
+ kfree(ltk);
} else {
clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
}
@@ -4759,27 +4612,6 @@
hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
}
-static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
- struct sk_buff *skb)
-{
- u8 num_reports = skb->data[0];
- void *ptr = &skb->data[1];
-
- hci_dev_lock(hdev);
-
- while (num_reports--) {
- struct hci_ev_le_direct_adv_info *ev = ptr;
-
- process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
- ev->bdaddr_type, &ev->direct_addr,
- ev->direct_addr_type, ev->rssi, NULL, 0);
-
- ptr += sizeof(*ev);
- }
-
- hci_dev_unlock(hdev);
-}
-
static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_meta *le_ev = (void *) skb->data;
@@ -4807,10 +4639,6 @@
hci_le_remote_conn_param_req_evt(hdev, skb);
break;
- case HCI_EV_LE_DIRECT_ADV_REPORT:
- hci_le_direct_adv_report_evt(hdev, skb);
- break;
-
default:
break;
}
@@ -4907,10 +4735,6 @@
hci_cmd_status_evt(hdev, skb);
break;
- case HCI_EV_HARDWARE_ERROR:
- hci_hardware_error_evt(hdev, skb);
- break;
-
case HCI_EV_ROLE_CHANGE:
hci_role_change_evt(hdev, skb);
break;
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 2c245fd..115f149 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -878,7 +878,7 @@
}
skb_reset_transport_header(skb);
- err = skb_copy_datagram_msg(skb, 0, msg, copied);
+ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
switch (hci_pi(sk)->channel) {
case HCI_CHANNEL_RAW:
@@ -947,7 +947,7 @@
if (!skb)
goto done;
- if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+ if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
err = -EFAULT;
goto drop;
}
@@ -987,7 +987,7 @@
skb_queue_tail(&hdev->raw_q, skb);
queue_work(hdev->workqueue, &hdev->tx_work);
} else {
- /* Stand-alone HCI commands must be flagged as
+ /* Stand-alone HCI commands must be flaged as
* single-command requests.
*/
bt_cb(skb)->req.start = true;
diff --git a/net/bluetooth/hidp/Kconfig b/net/bluetooth/hidp/Kconfig
index d63ec58..869dd8b 100644
--- a/net/bluetooth/hidp/Kconfig
+++ b/net/bluetooth/hidp/Kconfig
@@ -1,7 +1,7 @@
config BT_HIDP
tristate "HIDP protocol support"
depends on m
- depends on BT_BREDR && INPUT
+ depends on BT && INPUT
depends on HID
help
HIDP (Human Interface Device Protocol) is a transport layer
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 867f53e..1687cc7 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -740,10 +740,14 @@
struct hid_device *hid;
int err;
- session->rd_data = memdup_user(req->rd_data, req->rd_size);
- if (IS_ERR(session->rd_data))
- return PTR_ERR(session->rd_data);
+ session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
+ if (!session->rd_data)
+ return -ENOMEM;
+ if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
+ err = -EFAULT;
+ goto fault;
+ }
session->rd_size = req->rd_size;
hid = hid_allocate_device();
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 3c6bfb1..b6f9777 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -46,6 +46,7 @@
bool disable_ertm;
static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD;
+static u8 l2cap_fixed_chan[8] = { L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS, };
static LIST_HEAD(chan_list);
static DEFINE_RWLOCK(chan_list_lock);
@@ -423,9 +424,6 @@
mutex_init(&chan->lock);
- /* Set default lock nesting level */
- atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL);
-
write_lock(&chan_list_lock);
list_add(&chan->global_l, &chan_list);
write_unlock(&chan_list_lock);
@@ -569,8 +567,7 @@
__clear_chan_timer(chan);
- BT_DBG("chan %p, conn %p, err %d, state %s", chan, conn, err,
- state_to_string(chan->state));
+ BT_DBG("chan %p, conn %p, err %d", chan, conn, err);
chan->ops->teardown(chan, err);
@@ -839,10 +836,7 @@
if (!skb)
return;
- /* Use NO_FLUSH if supported or we have an LE link (which does
- * not support auto-flushing packets) */
- if (lmp_no_flush_capable(conn->hcon->hdev) ||
- conn->hcon->type == LE_LINK)
+ if (lmp_no_flush_capable(conn->hcon->hdev))
flags = ACL_START_NO_FLUSH;
else
flags = ACL_START;
@@ -876,13 +870,8 @@
return;
}
- /* Use NO_FLUSH for LE links (where this is the only option) or
- * if the BR/EDR link supports it and flushing has not been
- * explicitly requested (through FLAG_FLUSHABLE).
- */
- if (hcon->type == LE_LINK ||
- (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
- lmp_no_flush_capable(hcon->hdev)))
+ if (!test_bit(FLAG_FLUSHABLE, &chan->flags) &&
+ lmp_no_flush_capable(hcon->hdev))
flags = ACL_START_NO_FLUSH;
else
flags = ACL_START;
@@ -1119,10 +1108,10 @@
struct hci_dev *hdev;
bool amp_available = false;
- if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
+ if (!conn->hs_enabled)
return false;
- if (!(conn->remote_fixed_chan & L2CAP_FC_A2MP))
+ if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP))
return false;
read_lock(&hci_dev_list_lock);
@@ -2103,12 +2092,8 @@
struct sk_buff **frag;
int sent = 0;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
- if (copy_from_iter(skb_put(skb, count), count, &msg->msg_iter) != count)
-#else
if (chan->ops->memcpy_fromiovec(chan, skb_put(skb, count),
msg->msg_iov, count))
-#endif
return -EFAULT;
sent += count;
@@ -2128,13 +2113,8 @@
*frag = tmp;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
- if (copy_from_iter(skb_put(*frag, count), count,
- &msg->msg_iter) != count)
-#else
if (chan->ops->memcpy_fromiovec(chan, skb_put(*frag, count),
msg->msg_iov, count))
-#endif
return -EFAULT;
sent += count;
@@ -3104,14 +3084,12 @@
static inline bool __l2cap_ews_supported(struct l2cap_conn *conn)
{
- return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
- (conn->feat_mask & L2CAP_FEAT_EXT_WINDOW));
+ return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_WINDOW;
}
static inline bool __l2cap_efs_supported(struct l2cap_conn *conn)
{
- return ((conn->local_fixed_chan & L2CAP_FC_A2MP) &&
- (conn->feat_mask & L2CAP_FEAT_EXT_FLOW));
+ return conn->hs_enabled && conn->feat_mask & L2CAP_FEAT_EXT_FLOW;
}
static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan,
@@ -3340,7 +3318,7 @@
break;
case L2CAP_CONF_EWS:
- if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP))
+ if (!chan->conn->hs_enabled)
return -ECONNREFUSED;
set_bit(FLAG_EXT_CTRL, &chan->flags);
@@ -3895,7 +3873,9 @@
hci_dev_lock(hdev);
if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
- mgmt_device_connected(hdev, hcon, 0, NULL, 0);
+ mgmt_device_connected(hdev, &hcon->dst, hcon->type,
+ hcon->dst_type, 0, NULL, 0,
+ hcon->dev_class);
hci_dev_unlock(hdev);
l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
@@ -4104,7 +4084,7 @@
chan->num_conf_req++;
}
- /* Got Conf Rsp PENDING from remote side and assume we sent
+ /* Got Conf Rsp PENDING from remote side and asume we sent
Conf Rsp PENDING in the code above */
if (test_bit(CONF_REM_CONF_PEND, &chan->conf_state) &&
test_bit(CONF_LOC_CONF_PEND, &chan->conf_state)) {
@@ -4344,7 +4324,7 @@
if (!disable_ertm)
feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING
| L2CAP_FEAT_FCS;
- if (conn->local_fixed_chan & L2CAP_FC_A2MP)
+ if (conn->hs_enabled)
feat_mask |= L2CAP_FEAT_EXT_FLOW
| L2CAP_FEAT_EXT_WINDOW;
@@ -4355,10 +4335,14 @@
u8 buf[12];
struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf;
+ if (conn->hs_enabled)
+ l2cap_fixed_chan[0] |= L2CAP_FC_A2MP;
+ else
+ l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP;
+
rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN);
rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS);
- rsp->data[0] = conn->local_fixed_chan;
- memset(rsp->data + 1, 0, 7);
+ memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan));
l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf),
buf);
} else {
@@ -4424,7 +4408,7 @@
break;
case L2CAP_IT_FIXED_CHAN:
- conn->remote_fixed_chan = rsp->data[0];
+ conn->fixed_chan_mask = rsp->data[0];
conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_DONE;
conn->info_ident = 0;
@@ -4448,7 +4432,7 @@
if (cmd_len != sizeof(*req))
return -EPROTO;
- if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
+ if (!conn->hs_enabled)
return -EINVAL;
psm = le16_to_cpu(req->psm);
@@ -4878,7 +4862,7 @@
BT_DBG("icid 0x%4.4x, dest_amp_id %d", icid, req->dest_amp_id);
- if (!(conn->local_fixed_chan & L2CAP_FC_A2MP))
+ if (!conn->hs_enabled)
return -EINVAL;
chan = l2cap_get_chan_by_dcid(conn, icid);
@@ -5233,10 +5217,9 @@
u8 *data)
{
struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data;
- struct hci_conn *hcon = conn->hcon;
u16 dcid, mtu, mps, credits, result;
struct l2cap_chan *chan;
- int err, sec_level;
+ int err;
if (cmd_len < sizeof(*rsp))
return -EPROTO;
@@ -5275,26 +5258,6 @@
l2cap_chan_ready(chan);
break;
- case L2CAP_CR_AUTHENTICATION:
- case L2CAP_CR_ENCRYPTION:
- /* If we already have MITM protection we can't do
- * anything.
- */
- if (hcon->sec_level > BT_SECURITY_MEDIUM) {
- l2cap_chan_del(chan, ECONNREFUSED);
- break;
- }
-
- sec_level = hcon->sec_level + 1;
- if (chan->sec_level < sec_level)
- chan->sec_level = sec_level;
-
- /* We'll need to send a new Connect Request */
- clear_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags);
-
- smp_conn_security(hcon, chan->sec_level);
- break;
-
default:
l2cap_chan_del(chan, ECONNREFUSED);
break;
@@ -5427,8 +5390,7 @@
mutex_lock(&conn->chan_lock);
l2cap_chan_lock(pchan);
- if (!smp_sufficient_security(conn->hcon, pchan->sec_level,
- SMP_ALLOW_STK)) {
+ if (!smp_sufficient_security(conn->hcon, pchan->sec_level)) {
result = L2CAP_CR_AUTHENTICATION;
chan = NULL;
goto response_unlock;
@@ -5532,7 +5494,6 @@
if (credits > max_credits) {
BT_ERR("LE credits overflow");
l2cap_send_disconn_req(chan, ECONNRESET);
- l2cap_chan_unlock(chan);
/* Return 0 so that we don't trigger an unnecessary
* command reject packet.
@@ -6970,16 +6931,9 @@
conn->feat_mask = 0;
- conn->local_fixed_chan = L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS;
-
- if (hcon->type == ACL_LINK &&
- test_bit(HCI_HS_ENABLED, &hcon->hdev->dev_flags))
- conn->local_fixed_chan |= L2CAP_FC_A2MP;
-
- if (test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags) &&
- (bredr_sc_enabled(hcon->hdev) ||
- test_bit(HCI_FORCE_LESC, &hcon->hdev->dbg_flags)))
- conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR;
+ if (hcon->type == ACL_LINK)
+ conn->hs_enabled = test_bit(HCI_HS_ENABLED,
+ &hcon->hdev->dev_flags);
mutex_init(&conn->ident_lock);
mutex_init(&conn->chan_lock);
@@ -7376,8 +7330,7 @@
l2cap_start_connection(chan);
else
__set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
- } else if (chan->state == BT_CONNECT2 &&
- chan->mode != L2CAP_MODE_LE_FLOWCTL) {
+ } else if (chan->state == BT_CONNECT2) {
struct l2cap_conn_rsp rsp;
__u16 res, stat;
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index b2ca901..c53387f 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -285,12 +285,6 @@
sk->sk_max_ack_backlog = backlog;
sk->sk_ack_backlog = 0;
- /* Listening channels need to use nested locking in order not to
- * cause lockdep warnings when the created child channels end up
- * being locked in the same thread as the parent channel.
- */
- atomic_set(&chan->nesting, L2CAP_NESTING_PARENT);
-
chan->state = BT_LISTEN;
sk->sk_state = BT_LISTEN;
@@ -307,7 +301,7 @@
long timeo;
int err = 0;
- lock_sock_nested(sk, L2CAP_NESTING_PARENT);
+ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK);
@@ -339,7 +333,7 @@
release_sock(sk);
timeo = schedule_timeout(timeo);
- lock_sock_nested(sk, L2CAP_NESTING_PARENT);
+ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
}
__set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(sk), &wait);
@@ -1102,8 +1096,6 @@
chan = l2cap_pi(sk)->chan;
conn = chan->conn;
- BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
-
if (conn)
mutex_lock(&conn->chan_lock);
@@ -1161,16 +1153,12 @@
{
struct sock *sk;
- BT_DBG("parent %p state %s", parent,
- state_to_string(parent->sk_state));
+ BT_DBG("parent %p", parent);
/* Close not yet accepted channels */
while ((sk = bt_accept_dequeue(parent, NULL))) {
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
- BT_DBG("child chan %p state %s", chan,
- state_to_string(chan->state));
-
l2cap_chan_lock(chan);
__clear_chan_timer(chan);
l2cap_chan_close(chan, ECONNRESET);
@@ -1258,16 +1246,7 @@
struct sock *sk = chan->data;
struct sock *parent;
- BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
-
- /* This callback can be called both for server (BT_LISTEN)
- * sockets as well as "normal" ones. To avoid lockdep warnings
- * with child socket locking (through l2cap_sock_cleanup_listen)
- * we need separation into separate nesting levels. The simplest
- * way to accomplish this is to inherit the nesting level used
- * for the channel.
- */
- lock_sock_nested(sk, atomic_read(&chan->nesting));
+ lock_sock(sk);
parent = bt_sk(sk)->parent;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 693ce8b..efb71b0 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -35,7 +35,7 @@
#include "smp.h"
#define MGMT_VERSION 1
-#define MGMT_REVISION 8
+#define MGMT_REVISION 7
static const u16 mgmt_commands[] = {
MGMT_OP_READ_INDEX_LIST,
@@ -93,7 +93,6 @@
MGMT_OP_READ_CONFIG_INFO,
MGMT_OP_SET_EXTERNAL_CONFIG,
MGMT_OP_SET_PUBLIC_ADDRESS,
- MGMT_OP_START_SERVICE_DISCOVERY,
};
static const u16 mgmt_events[] = {
@@ -135,10 +134,8 @@
u16 opcode;
int index;
void *param;
- size_t param_len;
struct sock *sk;
void *user_data;
- void (*cmd_complete)(struct pending_cmd *cmd, u8 status);
};
/* HCI to MGMT error code conversion table */
@@ -577,7 +574,6 @@
if (lmp_le_capable(hdev)) {
settings |= MGMT_SETTING_LE;
settings |= MGMT_SETTING_ADVERTISING;
- settings |= MGMT_SETTING_SECURE_CONN;
settings |= MGMT_SETTING_PRIVACY;
}
@@ -1206,13 +1202,14 @@
cmd->opcode = opcode;
cmd->index = hdev->id;
- cmd->param = kmemdup(data, len, GFP_KERNEL);
+ cmd->param = kmalloc(len, GFP_KERNEL);
if (!cmd->param) {
kfree(cmd);
return NULL;
}
- cmd->param_len = len;
+ if (data)
+ memcpy(cmd->param, data, len);
cmd->sk = sk;
sock_hold(sk);
@@ -1472,32 +1469,6 @@
mgmt_pending_remove(cmd);
}
-static void cmd_complete_rsp(struct pending_cmd *cmd, void *data)
-{
- if (cmd->cmd_complete) {
- u8 *status = data;
-
- cmd->cmd_complete(cmd, *status);
- mgmt_pending_remove(cmd);
-
- return;
- }
-
- cmd_status_rsp(cmd, data);
-}
-
-static void generic_cmd_complete(struct pending_cmd *cmd, u8 status)
-{
- cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
- cmd->param_len);
-}
-
-static void addr_cmd_complete(struct pending_cmd *cmd, u8 status)
-{
- cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param,
- sizeof(struct mgmt_addr_info));
-}
-
static u8 mgmt_bredr_support(struct hci_dev *hdev)
{
if (!lmp_bredr_capable(hdev))
@@ -2199,14 +2170,12 @@
{
struct cmd_lookup match = { NULL, hdev };
- hci_dev_lock(hdev);
-
if (status) {
u8 mgmt_err = mgmt_status(status);
mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
&mgmt_err);
- goto unlock;
+ return;
}
mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
@@ -2224,16 +2193,17 @@
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
struct hci_request req;
+ hci_dev_lock(hdev);
+
hci_req_init(&req, hdev);
update_adv_data(&req);
update_scan_rsp_data(&req);
hci_req_run(&req, NULL);
hci_update_background_scan(hdev);
- }
-unlock:
- hci_dev_unlock(hdev);
+ hci_dev_unlock(hdev);
+ }
}
static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
@@ -2755,40 +2725,10 @@
}
if (cp->addr.type == BDADDR_BREDR) {
- /* If disconnection is requested, then look up the
- * connection. If the remote device is connected, it
- * will be later used to terminate the link.
- *
- * Setting it to NULL explicitly will cause no
- * termination of the link.
- */
- if (cp->disconnect)
- conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
- &cp->addr.bdaddr);
- else
- conn = NULL;
-
err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
} else {
u8 addr_type;
- conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
- &cp->addr.bdaddr);
- if (conn) {
- /* Defer clearing up the connection parameters
- * until closing to give a chance of keeping
- * them if a repairing happens.
- */
- set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
-
- /* If disconnection is not requested, then
- * clear the connection variable so that the
- * link is not terminated.
- */
- if (!cp->disconnect)
- conn = NULL;
- }
-
if (cp->addr.type == BDADDR_LE_PUBLIC)
addr_type = ADDR_LE_DEV_PUBLIC;
else
@@ -2796,6 +2736,8 @@
hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type);
+ hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
+
err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type);
}
@@ -2805,9 +2747,17 @@
goto unlock;
}
- /* If the connection variable is set, then termination of the
- * link is requested.
- */
+ if (cp->disconnect) {
+ if (cp->addr.type == BDADDR_BREDR)
+ conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
+ &cp->addr.bdaddr);
+ else
+ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK,
+ &cp->addr.bdaddr);
+ } else {
+ conn = NULL;
+ }
+
if (!conn) {
err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
&rp, sizeof(rp));
@@ -2822,8 +2772,6 @@
goto unlock;
}
- cmd->cmd_complete = addr_cmd_complete;
-
dc.handle = cpu_to_le16(conn->handle);
dc.reason = 0x13; /* Remote User Terminated Connection */
err = hci_send_cmd(hdev, HCI_OP_DISCONNECT, sizeof(dc), &dc);
@@ -2887,8 +2835,6 @@
goto failed;
}
- cmd->cmd_complete = generic_cmd_complete;
-
err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
if (err < 0)
mgmt_pending_remove(cmd);
@@ -3041,8 +2987,6 @@
goto failed;
}
- cmd->cmd_complete = addr_cmd_complete;
-
bacpy(&reply.bdaddr, &cp->addr.bdaddr);
reply.pin_len = cp->pin_len;
memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
@@ -3115,13 +3059,9 @@
conn->disconn_cfm_cb = NULL;
hci_conn_drop(conn);
-
- /* The device is paired so there is no need to remove
- * its connection parameters anymore.
- */
- clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
-
hci_conn_put(conn);
+
+ mgmt_pending_remove(cmd);
}
void mgmt_smp_complete(struct hci_conn *conn, bool complete)
@@ -3130,10 +3070,8 @@
struct pending_cmd *cmd;
cmd = find_pairing(conn);
- if (cmd) {
- cmd->cmd_complete(cmd, status);
- mgmt_pending_remove(cmd);
- }
+ if (cmd)
+ pairing_complete(cmd, status);
}
static void pairing_complete_cb(struct hci_conn *conn, u8 status)
@@ -3143,13 +3081,10 @@
BT_DBG("status %u", status);
cmd = find_pairing(conn);
- if (!cmd) {
+ if (!cmd)
BT_DBG("Unable to find a pending command");
- return;
- }
-
- cmd->cmd_complete(cmd, mgmt_status(status));
- mgmt_pending_remove(cmd);
+ else
+ pairing_complete(cmd, mgmt_status(status));
}
static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
@@ -3162,13 +3097,10 @@
return;
cmd = find_pairing(conn);
- if (!cmd) {
+ if (!cmd)
BT_DBG("Unable to find a pending command");
- return;
- }
-
- cmd->cmd_complete(cmd, mgmt_status(status));
- mgmt_pending_remove(cmd);
+ else
+ pairing_complete(cmd, mgmt_status(status));
}
static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -3265,8 +3197,6 @@
goto unlock;
}
- cmd->cmd_complete = pairing_complete;
-
/* For LE, just connecting isn't a proof that the pairing finished */
if (cp->addr.type == BDADDR_BREDR) {
conn->connect_cfm_cb = pairing_complete_cb;
@@ -3282,10 +3212,8 @@
cmd->user_data = hci_conn_get(conn);
if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
- hci_conn_security(conn, sec_level, auth_type, true)) {
- cmd->cmd_complete(cmd, 0);
- mgmt_pending_remove(cmd);
- }
+ hci_conn_security(conn, sec_level, auth_type, true))
+ pairing_complete(cmd, 0);
err = 0;
@@ -3327,8 +3255,7 @@
goto unlock;
}
- cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
- mgmt_pending_remove(cmd);
+ pairing_complete(cmd, MGMT_STATUS_CANCELLED);
err = cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
addr, sizeof(*addr));
@@ -3386,8 +3313,6 @@
goto done;
}
- cmd->cmd_complete = addr_cmd_complete;
-
/* Continue with pairing via HCI */
if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
struct hci_cp_user_passkey_reply cp;
@@ -3612,7 +3537,7 @@
goto unlock;
}
- if (bredr_sc_enabled(hdev))
+ if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA,
0, NULL);
else
@@ -3639,17 +3564,8 @@
struct mgmt_cp_add_remote_oob_data *cp = data;
u8 status;
- if (cp->addr.type != BDADDR_BREDR) {
- err = cmd_complete(sk, hdev->id,
- MGMT_OP_ADD_REMOTE_OOB_DATA,
- MGMT_STATUS_INVALID_PARAMS,
- &cp->addr, sizeof(cp->addr));
- goto unlock;
- }
-
err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
- cp->addr.type, cp->hash,
- cp->rand, NULL, NULL);
+ cp->hash, cp->randomizer);
if (err < 0)
status = MGMT_STATUS_FAILED;
else
@@ -3659,28 +3575,13 @@
status, &cp->addr, sizeof(cp->addr));
} else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
struct mgmt_cp_add_remote_oob_ext_data *cp = data;
- u8 *rand192, *hash192;
u8 status;
- if (cp->addr.type != BDADDR_BREDR) {
- err = cmd_complete(sk, hdev->id,
- MGMT_OP_ADD_REMOTE_OOB_DATA,
- MGMT_STATUS_INVALID_PARAMS,
- &cp->addr, sizeof(cp->addr));
- goto unlock;
- }
-
- if (bdaddr_type_is_le(cp->addr.type)) {
- rand192 = NULL;
- hash192 = NULL;
- } else {
- rand192 = cp->rand192;
- hash192 = cp->hash192;
- }
-
- err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
- cp->addr.type, hash192, rand192,
- cp->hash256, cp->rand256);
+ err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr,
+ cp->hash192,
+ cp->randomizer192,
+ cp->hash256,
+ cp->randomizer256);
if (err < 0)
status = MGMT_STATUS_FAILED;
else
@@ -3694,7 +3595,6 @@
MGMT_STATUS_INVALID_PARAMS);
}
-unlock:
hci_dev_unlock(hdev);
return err;
}
@@ -3708,26 +3608,14 @@
BT_DBG("%s", hdev->name);
- if (cp->addr.type != BDADDR_BREDR)
- return cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
- MGMT_STATUS_INVALID_PARAMS,
- &cp->addr, sizeof(cp->addr));
-
hci_dev_lock(hdev);
- if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
- hci_remote_oob_data_clear(hdev);
- status = MGMT_STATUS_SUCCESS;
- goto done;
- }
-
- err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
+ err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr);
if (err < 0)
status = MGMT_STATUS_INVALID_PARAMS;
else
status = MGMT_STATUS_SUCCESS;
-done:
err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
status, &cp->addr, sizeof(cp->addr));
@@ -3735,26 +3623,127 @@
return err;
}
-static bool trigger_discovery(struct hci_request *req, u8 *status)
+static int mgmt_start_discovery_failed(struct hci_dev *hdev, u8 status)
{
- struct hci_dev *hdev = req->hdev;
+ struct pending_cmd *cmd;
+ u8 type;
+ int err;
+
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+
+ cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
+ if (!cmd)
+ return -ENOENT;
+
+ type = hdev->discovery.type;
+
+ err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
+ &type, sizeof(type));
+ mgmt_pending_remove(cmd);
+
+ return err;
+}
+
+static void start_discovery_complete(struct hci_dev *hdev, u8 status)
+{
+ unsigned long timeout = 0;
+
+ BT_DBG("status %d", status);
+
+ if (status) {
+ hci_dev_lock(hdev);
+ mgmt_start_discovery_failed(hdev, status);
+ hci_dev_unlock(hdev);
+ return;
+ }
+
+ hci_dev_lock(hdev);
+ hci_discovery_set_state(hdev, DISCOVERY_FINDING);
+ hci_dev_unlock(hdev);
+
+ switch (hdev->discovery.type) {
+ case DISCOV_TYPE_LE:
+ timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
+ break;
+
+ case DISCOV_TYPE_INTERLEAVED:
+ timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
+ break;
+
+ case DISCOV_TYPE_BREDR:
+ break;
+
+ default:
+ BT_ERR("Invalid discovery type %d", hdev->discovery.type);
+ }
+
+ if (!timeout)
+ return;
+
+ queue_delayed_work(hdev->workqueue, &hdev->le_scan_disable, timeout);
+}
+
+static int start_discovery(struct sock *sk, struct hci_dev *hdev,
+ void *data, u16 len)
+{
+ struct mgmt_cp_start_discovery *cp = data;
+ struct pending_cmd *cmd;
struct hci_cp_le_set_scan_param param_cp;
struct hci_cp_le_set_scan_enable enable_cp;
struct hci_cp_inquiry inq_cp;
+ struct hci_request req;
/* General inquiry access code (GIAC) */
u8 lap[3] = { 0x33, 0x8b, 0x9e };
- u8 own_addr_type;
+ u8 status, own_addr_type;
int err;
+ BT_DBG("%s", hdev->name);
+
+ hci_dev_lock(hdev);
+
+ if (!hdev_is_powered(hdev)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_NOT_POWERED);
+ goto failed;
+ }
+
+ if (test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_BUSY);
+ goto failed;
+ }
+
+ if (hdev->discovery.state != DISCOVERY_STOPPED) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_BUSY);
+ goto failed;
+ }
+
+ cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, NULL, 0);
+ if (!cmd) {
+ err = -ENOMEM;
+ goto failed;
+ }
+
+ hdev->discovery.type = cp->type;
+
+ hci_req_init(&req, hdev);
+
switch (hdev->discovery.type) {
case DISCOV_TYPE_BREDR:
- *status = mgmt_bredr_support(hdev);
- if (*status)
- return false;
+ status = mgmt_bredr_support(hdev);
+ if (status) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ status);
+ mgmt_pending_remove(cmd);
+ goto failed;
+ }
if (test_bit(HCI_INQUIRY, &hdev->flags)) {
- *status = MGMT_STATUS_BUSY;
- return false;
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_BUSY);
+ mgmt_pending_remove(cmd);
+ goto failed;
}
hci_inquiry_cache_flush(hdev);
@@ -3762,19 +3751,25 @@
memset(&inq_cp, 0, sizeof(inq_cp));
memcpy(&inq_cp.lap, lap, sizeof(inq_cp.lap));
inq_cp.length = DISCOV_BREDR_INQUIRY_LEN;
- hci_req_add(req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
+ hci_req_add(&req, HCI_OP_INQUIRY, sizeof(inq_cp), &inq_cp);
break;
case DISCOV_TYPE_LE:
case DISCOV_TYPE_INTERLEAVED:
- *status = mgmt_le_support(hdev);
- if (*status)
- return false;
+ status = mgmt_le_support(hdev);
+ if (status) {
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ status);
+ mgmt_pending_remove(cmd);
+ goto failed;
+ }
if (hdev->discovery.type == DISCOV_TYPE_INTERLEAVED &&
!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
- *status = MGMT_STATUS_NOT_SUPPORTED;
- return false;
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_NOT_SUPPORTED);
+ mgmt_pending_remove(cmd);
+ goto failed;
}
if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) {
@@ -3784,11 +3779,14 @@
*/
if (hci_conn_hash_lookup_state(hdev, LE_LINK,
BT_CONNECT)) {
- *status = MGMT_STATUS_REJECTED;
- return false;
+ err = cmd_status(sk, hdev->id,
+ MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_REJECTED);
+ mgmt_pending_remove(cmd);
+ goto failed;
}
- disable_advertising(req);
+ disable_advertising(&req);
}
/* If controller is scanning, it means the background scanning
@@ -3796,287 +3794,84 @@
* set the discovery scanning parameters.
*/
if (test_bit(HCI_LE_SCAN, &hdev->dev_flags))
- hci_req_add_le_scan_disable(req);
+ hci_req_add_le_scan_disable(&req);
memset(¶m_cp, 0, sizeof(param_cp));
/* All active scans will be done with either a resolvable
* private address (when privacy feature has been enabled)
- * or non-resolvable private address.
+ * or unresolvable private address.
*/
- err = hci_update_random_address(req, true, &own_addr_type);
+ err = hci_update_random_address(&req, true, &own_addr_type);
if (err < 0) {
- *status = MGMT_STATUS_FAILED;
- return false;
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_FAILED);
+ mgmt_pending_remove(cmd);
+ goto failed;
}
param_cp.type = LE_SCAN_ACTIVE;
param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
param_cp.own_address_type = own_addr_type;
- hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
¶m_cp);
memset(&enable_cp, 0, sizeof(enable_cp));
enable_cp.enable = LE_SCAN_ENABLE;
enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE;
- hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
+ hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp),
&enable_cp);
break;
default:
- *status = MGMT_STATUS_INVALID_PARAMS;
- return false;
- }
-
- return true;
-}
-
-static void start_discovery_complete(struct hci_dev *hdev, u8 status)
-{
- struct pending_cmd *cmd;
- unsigned long timeout;
-
- BT_DBG("status %d", status);
-
- hci_dev_lock(hdev);
-
- cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
- if (!cmd)
- cmd = mgmt_pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
-
- if (cmd) {
- cmd->cmd_complete(cmd, mgmt_status(status));
- mgmt_pending_remove(cmd);
- }
-
- if (status) {
- hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
- goto unlock;
- }
-
- hci_discovery_set_state(hdev, DISCOVERY_FINDING);
-
- switch (hdev->discovery.type) {
- case DISCOV_TYPE_LE:
- timeout = msecs_to_jiffies(DISCOV_LE_TIMEOUT);
- break;
- case DISCOV_TYPE_INTERLEAVED:
- timeout = msecs_to_jiffies(hdev->discov_interleaved_timeout);
- break;
- case DISCOV_TYPE_BREDR:
- timeout = 0;
- break;
- default:
- BT_ERR("Invalid discovery type %d", hdev->discovery.type);
- timeout = 0;
- break;
- }
-
- if (timeout)
- queue_delayed_work(hdev->workqueue,
- &hdev->le_scan_disable, timeout);
-
-unlock:
- hci_dev_unlock(hdev);
-}
-
-static int start_discovery(struct sock *sk, struct hci_dev *hdev,
- void *data, u16 len)
-{
- struct mgmt_cp_start_discovery *cp = data;
- struct pending_cmd *cmd;
- struct hci_request req;
- u8 status;
- int err;
-
- BT_DBG("%s", hdev->name);
-
- hci_dev_lock(hdev);
-
- if (!hdev_is_powered(hdev)) {
- err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
- MGMT_STATUS_NOT_POWERED,
- &cp->type, sizeof(cp->type));
- goto failed;
- }
-
- if (hdev->discovery.state != DISCOVERY_STOPPED ||
- test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
- err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
- MGMT_STATUS_BUSY, &cp->type,
- sizeof(cp->type));
- goto failed;
- }
-
- cmd = mgmt_pending_add(sk, MGMT_OP_START_DISCOVERY, hdev, data, len);
- if (!cmd) {
- err = -ENOMEM;
- goto failed;
- }
-
- cmd->cmd_complete = generic_cmd_complete;
-
- /* Clear the discovery filter first to free any previously
- * allocated memory for the UUID list.
- */
- hci_discovery_filter_clear(hdev);
-
- hdev->discovery.type = cp->type;
- hdev->discovery.report_invalid_rssi = false;
-
- hci_req_init(&req, hdev);
-
- if (!trigger_discovery(&req, &status)) {
- err = cmd_complete(sk, hdev->id, MGMT_OP_START_DISCOVERY,
- status, &cp->type, sizeof(cp->type));
+ err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY,
+ MGMT_STATUS_INVALID_PARAMS);
mgmt_pending_remove(cmd);
goto failed;
}
err = hci_req_run(&req, start_discovery_complete);
- if (err < 0) {
+ if (err < 0)
mgmt_pending_remove(cmd);
- goto failed;
- }
-
- hci_discovery_set_state(hdev, DISCOVERY_STARTING);
+ else
+ hci_discovery_set_state(hdev, DISCOVERY_STARTING);
failed:
hci_dev_unlock(hdev);
return err;
}
-static void service_discovery_cmd_complete(struct pending_cmd *cmd, u8 status)
+static int mgmt_stop_discovery_failed(struct hci_dev *hdev, u8 status)
{
- cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, cmd->param, 1);
-}
-
-static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
- void *data, u16 len)
-{
- struct mgmt_cp_start_service_discovery *cp = data;
struct pending_cmd *cmd;
- struct hci_request req;
- const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
- u16 uuid_count, expected_len;
- u8 status;
int err;
- BT_DBG("%s", hdev->name);
+ cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
+ if (!cmd)
+ return -ENOENT;
- hci_dev_lock(hdev);
+ err = cmd_complete(cmd->sk, hdev->id, cmd->opcode, mgmt_status(status),
+ &hdev->discovery.type, sizeof(hdev->discovery.type));
+ mgmt_pending_remove(cmd);
- if (!hdev_is_powered(hdev)) {
- err = cmd_complete(sk, hdev->id,
- MGMT_OP_START_SERVICE_DISCOVERY,
- MGMT_STATUS_NOT_POWERED,
- &cp->type, sizeof(cp->type));
- goto failed;
- }
-
- if (hdev->discovery.state != DISCOVERY_STOPPED ||
- test_bit(HCI_PERIODIC_INQ, &hdev->dev_flags)) {
- err = cmd_complete(sk, hdev->id,
- MGMT_OP_START_SERVICE_DISCOVERY,
- MGMT_STATUS_BUSY, &cp->type,
- sizeof(cp->type));
- goto failed;
- }
-
- uuid_count = __le16_to_cpu(cp->uuid_count);
- if (uuid_count > max_uuid_count) {
- BT_ERR("service_discovery: too big uuid_count value %u",
- uuid_count);
- err = cmd_complete(sk, hdev->id,
- MGMT_OP_START_SERVICE_DISCOVERY,
- MGMT_STATUS_INVALID_PARAMS, &cp->type,
- sizeof(cp->type));
- goto failed;
- }
-
- expected_len = sizeof(*cp) + uuid_count * 16;
- if (expected_len != len) {
- BT_ERR("service_discovery: expected %u bytes, got %u bytes",
- expected_len, len);
- err = cmd_complete(sk, hdev->id,
- MGMT_OP_START_SERVICE_DISCOVERY,
- MGMT_STATUS_INVALID_PARAMS, &cp->type,
- sizeof(cp->type));
- goto failed;
- }
-
- cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
- hdev, data, len);
- if (!cmd) {
- err = -ENOMEM;
- goto failed;
- }
-
- cmd->cmd_complete = service_discovery_cmd_complete;
-
- /* Clear the discovery filter first to free any previously
- * allocated memory for the UUID list.
- */
- hci_discovery_filter_clear(hdev);
-
- hdev->discovery.type = cp->type;
- hdev->discovery.rssi = cp->rssi;
- hdev->discovery.uuid_count = uuid_count;
-
- if (uuid_count > 0) {
- hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
- GFP_KERNEL);
- if (!hdev->discovery.uuids) {
- err = cmd_complete(sk, hdev->id,
- MGMT_OP_START_SERVICE_DISCOVERY,
- MGMT_STATUS_FAILED,
- &cp->type, sizeof(cp->type));
- mgmt_pending_remove(cmd);
- goto failed;
- }
- }
-
- hci_req_init(&req, hdev);
-
- if (!trigger_discovery(&req, &status)) {
- err = cmd_complete(sk, hdev->id,
- MGMT_OP_START_SERVICE_DISCOVERY,
- status, &cp->type, sizeof(cp->type));
- mgmt_pending_remove(cmd);
- goto failed;
- }
-
- err = hci_req_run(&req, start_discovery_complete);
- if (err < 0) {
- mgmt_pending_remove(cmd);
- goto failed;
- }
-
- hci_discovery_set_state(hdev, DISCOVERY_STARTING);
-
-failed:
- hci_dev_unlock(hdev);
return err;
}
static void stop_discovery_complete(struct hci_dev *hdev, u8 status)
{
- struct pending_cmd *cmd;
-
BT_DBG("status %d", status);
hci_dev_lock(hdev);
- cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
- if (cmd) {
- cmd->cmd_complete(cmd, mgmt_status(status));
- mgmt_pending_remove(cmd);
+ if (status) {
+ mgmt_stop_discovery_failed(hdev, status);
+ goto unlock;
}
- if (!status)
- hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+ hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
+unlock:
hci_dev_unlock(hdev);
}
@@ -4106,14 +3901,12 @@
goto unlock;
}
- cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, NULL, 0);
if (!cmd) {
err = -ENOMEM;
goto unlock;
}
- cmd->cmd_complete = generic_cmd_complete;
-
hci_req_init(&req, hdev);
hci_stop_discovery(&req);
@@ -4290,14 +4083,12 @@
{
struct cmd_lookup match = { NULL, hdev };
- hci_dev_lock(hdev);
-
if (status) {
u8 mgmt_err = mgmt_status(status);
mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
cmd_status_rsp, &mgmt_err);
- goto unlock;
+ return;
}
if (test_bit(HCI_LE_ADV, &hdev->dev_flags))
@@ -4312,9 +4103,6 @@
if (match.sk)
sock_put(match.sk);
-
-unlock:
- hci_dev_unlock(hdev);
}
static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -4718,13 +4506,18 @@
{
struct mgmt_mode *cp = data;
struct pending_cmd *cmd;
- u8 val;
+ u8 val, status;
int err;
BT_DBG("request for %s", hdev->name);
- if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
- !lmp_sc_capable(hdev) && !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
+ status = mgmt_bredr_support(hdev);
+ if (status)
+ return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
+ status);
+
+ if (!lmp_sc_capable(hdev) &&
+ !test_bit(HCI_FORCE_SC, &hdev->dbg_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_NOT_SUPPORTED);
@@ -4734,10 +4527,7 @@
hci_dev_lock(hdev);
- if (!hdev_is_powered(hdev) ||
- (!lmp_sc_capable(hdev) &&
- !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) ||
- !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
+ if (!hdev_is_powered(hdev)) {
bool changed;
if (cp->val) {
@@ -5054,26 +4844,18 @@
else
addr_type = ADDR_LE_DEV_RANDOM;
+ if (key->master)
+ type = SMP_LTK;
+ else
+ type = SMP_LTK_SLAVE;
+
switch (key->type) {
case MGMT_LTK_UNAUTHENTICATED:
authenticated = 0x00;
- type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
break;
case MGMT_LTK_AUTHENTICATED:
authenticated = 0x01;
- type = key->master ? SMP_LTK : SMP_LTK_SLAVE;
break;
- case MGMT_LTK_P256_UNAUTH:
- authenticated = 0x00;
- type = SMP_LTK_P256;
- break;
- case MGMT_LTK_P256_AUTH:
- authenticated = 0x01;
- type = SMP_LTK_P256;
- break;
- case MGMT_LTK_P256_DEBUG:
- authenticated = 0x00;
- type = SMP_LTK_P256_DEBUG;
default:
continue;
}
@@ -5091,42 +4873,67 @@
return err;
}
-static void conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
+struct cmd_conn_lookup {
+ struct hci_conn *conn;
+ bool valid_tx_power;
+ u8 mgmt_status;
+};
+
+static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
{
- struct hci_conn *conn = cmd->user_data;
+ struct cmd_conn_lookup *match = data;
+ struct mgmt_cp_get_conn_info *cp;
struct mgmt_rp_get_conn_info rp;
+ struct hci_conn *conn = cmd->user_data;
- memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
+ if (conn != match->conn)
+ return;
- if (status == MGMT_STATUS_SUCCESS) {
+ cp = (struct mgmt_cp_get_conn_info *) cmd->param;
+
+ memset(&rp, 0, sizeof(rp));
+ bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
+ rp.addr.type = cp->addr.type;
+
+ if (!match->mgmt_status) {
rp.rssi = conn->rssi;
- rp.tx_power = conn->tx_power;
- rp.max_tx_power = conn->max_tx_power;
- } else {
- rp.rssi = HCI_RSSI_INVALID;
- rp.tx_power = HCI_TX_POWER_INVALID;
- rp.max_tx_power = HCI_TX_POWER_INVALID;
+
+ if (match->valid_tx_power) {
+ rp.tx_power = conn->tx_power;
+ rp.max_tx_power = conn->max_tx_power;
+ } else {
+ rp.tx_power = HCI_TX_POWER_INVALID;
+ rp.max_tx_power = HCI_TX_POWER_INVALID;
+ }
}
- cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
- &rp, sizeof(rp));
+ cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO,
+ match->mgmt_status, &rp, sizeof(rp));
hci_conn_drop(conn);
hci_conn_put(conn);
+
+ mgmt_pending_remove(cmd);
}
-static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status)
+static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
{
struct hci_cp_read_rssi *cp;
- struct pending_cmd *cmd;
struct hci_conn *conn;
+ struct cmd_conn_lookup match;
u16 handle;
- u8 status;
- BT_DBG("status 0x%02x", hci_status);
+ BT_DBG("status 0x%02x", status);
hci_dev_lock(hdev);
+ /* TX power data is valid in case request completed successfully,
+ * otherwise we assume it's not valid. At the moment we assume that
+ * either both or none of current and max values are valid to keep code
+ * simple.
+ */
+ match.valid_tx_power = !status;
+
/* Commands sent in request are either Read RSSI or Read Transmit Power
* Level so we check which one was last sent to retrieve connection
* handle. Both commands have handle as first parameter so it's safe to
@@ -5139,29 +4946,29 @@
cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
if (!cp) {
cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
- status = MGMT_STATUS_SUCCESS;
- } else {
- status = mgmt_status(hci_status);
+ status = 0;
}
if (!cp) {
- BT_ERR("invalid sent_cmd in conn_info response");
+ BT_ERR("invalid sent_cmd in response");
goto unlock;
}
handle = __le16_to_cpu(cp->handle);
conn = hci_conn_hash_lookup_handle(hdev, handle);
if (!conn) {
- BT_ERR("unknown handle (%d) in conn_info response", handle);
+ BT_ERR("unknown handle (%d) in response", handle);
goto unlock;
}
- cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
- if (!cmd)
- goto unlock;
+ match.conn = conn;
+ match.mgmt_status = mgmt_status(status);
- cmd->cmd_complete(cmd, status);
- mgmt_pending_remove(cmd);
+ /* Cache refresh is complete, now reply for mgmt request for given
+ * connection only.
+ */
+ mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
+ get_conn_info_complete, &match);
unlock:
hci_dev_unlock(hdev);
@@ -5207,12 +5014,6 @@
goto unlock;
}
- if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
- err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
- MGMT_STATUS_BUSY, &rp, sizeof(rp));
- goto unlock;
- }
-
/* To avoid client trying to guess when to poll again for information we
* calculate conn info age as random value between min/max set in hdev.
*/
@@ -5268,7 +5069,6 @@
hci_conn_hold(conn);
cmd->user_data = hci_conn_get(conn);
- cmd->cmd_complete = conn_info_cmd_complete;
conn->conn_info_timestamp = jiffies;
} else {
@@ -5286,40 +5086,10 @@
return err;
}
-static void clock_info_cmd_complete(struct pending_cmd *cmd, u8 status)
-{
- struct hci_conn *conn = cmd->user_data;
- struct mgmt_rp_get_clock_info rp;
- struct hci_dev *hdev;
-
- memset(&rp, 0, sizeof(rp));
- memcpy(&rp.addr, &cmd->param, sizeof(rp.addr));
-
- if (status)
- goto complete;
-
- hdev = hci_dev_get(cmd->index);
- if (hdev) {
- rp.local_clock = cpu_to_le32(hdev->clock);
- hci_dev_put(hdev);
- }
-
- if (conn) {
- rp.piconet_clock = cpu_to_le32(conn->clock);
- rp.accuracy = cpu_to_le16(conn->clock_accuracy);
- }
-
-complete:
- cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp, sizeof(rp));
-
- if (conn) {
- hci_conn_drop(conn);
- hci_conn_put(conn);
- }
-}
-
static void get_clock_info_complete(struct hci_dev *hdev, u8 status)
{
+ struct mgmt_cp_get_clock_info *cp;
+ struct mgmt_rp_get_clock_info rp;
struct hci_cp_read_clock *hci_cp;
struct pending_cmd *cmd;
struct hci_conn *conn;
@@ -5343,8 +5113,29 @@
if (!cmd)
goto unlock;
- cmd->cmd_complete(cmd, mgmt_status(status));
+ cp = cmd->param;
+
+ memset(&rp, 0, sizeof(rp));
+ memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
+
+ if (status)
+ goto send_rsp;
+
+ rp.local_clock = cpu_to_le32(hdev->clock);
+
+ if (conn) {
+ rp.piconet_clock = cpu_to_le32(conn->clock);
+ rp.accuracy = cpu_to_le16(conn->clock_accuracy);
+ }
+
+send_rsp:
+ cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status),
+ &rp, sizeof(rp));
mgmt_pending_remove(cmd);
+ if (conn) {
+ hci_conn_drop(conn);
+ hci_conn_put(conn);
+ }
unlock:
hci_dev_unlock(hdev);
@@ -5400,8 +5191,6 @@
goto unlock;
}
- cmd->cmd_complete = clock_info_cmd_complete;
-
hci_req_init(&req, hdev);
memset(&hci_cp, 0, sizeof(hci_cp));
@@ -5891,7 +5680,6 @@
{ read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE },
{ set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE },
{ set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE },
- { start_service_discovery,true, MGMT_START_SERVICE_DISCOVERY_SIZE },
};
int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
@@ -5913,7 +5701,7 @@
if (!buf)
return -ENOMEM;
- if (memcpy_from_msg(buf, msg, msglen)) {
+ if (memcpy_fromiovec(buf, msg->msg_iov, msglen)) {
err = -EFAULT;
goto done;
}
@@ -6028,7 +5816,7 @@
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
return;
- mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
+ mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status);
if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags))
mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL);
@@ -6097,11 +5885,6 @@
hci_req_add(&req, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
}
- if (bredr_sc_enabled(hdev) && !lmp_host_sc_capable(hdev)) {
- u8 sc = 0x01;
- hci_req_add(&req, HCI_OP_WRITE_SC_SUPPORT, sizeof(sc), &sc);
- }
-
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
lmp_bredr_capable(hdev)) {
struct hci_cp_write_le_host_supported cp;
@@ -6151,7 +5934,8 @@
int mgmt_powered(struct hci_dev *hdev, u8 powered)
{
struct cmd_lookup match = { NULL, hdev };
- u8 status, zero_cod[] = { 0, 0, 0 };
+ u8 status_not_powered = MGMT_STATUS_NOT_POWERED;
+ u8 zero_cod[] = { 0, 0, 0 };
int err;
if (!test_bit(HCI_MGMT, &hdev->dev_flags))
@@ -6167,20 +5951,7 @@
}
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
-
- /* If the power off is because of hdev unregistration let
- * use the appropriate INVALID_INDEX status. Otherwise use
- * NOT_POWERED. We cover both scenarios here since later in
- * mgmt_index_removed() any hci_conn callbacks will have already
- * been triggered, potentially causing misleading DISCONNECTED
- * status responses.
- */
- if (test_bit(HCI_UNREGISTER, &hdev->dev_flags))
- status = MGMT_STATUS_INVALID_INDEX;
- else
- status = MGMT_STATUS_NOT_POWERED;
-
- mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
+ mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status_not_powered);
if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0)
mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
@@ -6264,19 +6035,8 @@
static u8 mgmt_ltk_type(struct smp_ltk *ltk)
{
- switch (ltk->type) {
- case SMP_LTK:
- case SMP_LTK_SLAVE:
- if (ltk->authenticated)
- return MGMT_LTK_AUTHENTICATED;
- return MGMT_LTK_UNAUTHENTICATED;
- case SMP_LTK_P256:
- if (ltk->authenticated)
- return MGMT_LTK_P256_AUTH;
- return MGMT_LTK_P256_UNAUTH;
- case SMP_LTK_P256_DEBUG:
- return MGMT_LTK_P256_DEBUG;
- }
+ if (ltk->authenticated)
+ return MGMT_LTK_AUTHENTICATED;
return MGMT_LTK_UNAUTHENTICATED;
}
@@ -6411,36 +6171,26 @@
return eir_len;
}
-void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
- u32 flags, u8 *name, u8 name_len)
+void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
+ u8 addr_type, u32 flags, u8 *name, u8 name_len,
+ u8 *dev_class)
{
char buf[512];
struct mgmt_ev_device_connected *ev = (void *) buf;
u16 eir_len = 0;
- bacpy(&ev->addr.bdaddr, &conn->dst);
- ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
+ bacpy(&ev->addr.bdaddr, bdaddr);
+ ev->addr.type = link_to_bdaddr(link_type, addr_type);
ev->flags = __cpu_to_le32(flags);
- /* We must ensure that the EIR Data fields are ordered and
- * unique. Keep it simple for now and avoid the problem by not
- * adding any BR/EDR data to the LE adv.
- */
- if (conn->le_adv_data_len > 0) {
- memcpy(&ev->eir[eir_len],
- conn->le_adv_data, conn->le_adv_data_len);
- eir_len = conn->le_adv_data_len;
- } else {
- if (name_len > 0)
- eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
- name, name_len);
+ if (name_len > 0)
+ eir_len = eir_append_data(ev->eir, 0, EIR_NAME_COMPLETE,
+ name, name_len);
- if (memcmp(conn->dev_class, "\0\0\0", 3) != 0)
- eir_len = eir_append_data(ev->eir, eir_len,
- EIR_CLASS_OF_DEV,
- conn->dev_class, 3);
- }
+ if (dev_class && memcmp(dev_class, "\0\0\0", 3) != 0)
+ eir_len = eir_append_data(ev->eir, eir_len,
+ EIR_CLASS_OF_DEV, dev_class, 3);
ev->eir_len = cpu_to_le16(eir_len);
@@ -6450,9 +6200,15 @@
static void disconnect_rsp(struct pending_cmd *cmd, void *data)
{
+ struct mgmt_cp_disconnect *cp = cmd->param;
struct sock **sk = data;
+ struct mgmt_rp_disconnect rp;
- cmd->cmd_complete(cmd, 0);
+ bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
+ rp.addr.type = cp->addr.type;
+
+ cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, 0, &rp,
+ sizeof(rp));
*sk = cmd->sk;
sock_hold(*sk);
@@ -6464,10 +6220,16 @@
{
struct hci_dev *hdev = data;
struct mgmt_cp_unpair_device *cp = cmd->param;
+ struct mgmt_rp_unpair_device rp;
+
+ memset(&rp, 0, sizeof(rp));
+ bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
+ rp.addr.type = cp->addr.type;
device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
- cmd->cmd_complete(cmd, 0);
+ cmd_complete(cmd->sk, cmd->index, cmd->opcode, 0, &rp, sizeof(rp));
+
mgmt_pending_remove(cmd);
}
@@ -6528,6 +6290,7 @@
{
u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
struct mgmt_cp_disconnect *cp;
+ struct mgmt_rp_disconnect rp;
struct pending_cmd *cmd;
mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
@@ -6545,7 +6308,12 @@
if (cp->addr.type != bdaddr_type)
return;
- cmd->cmd_complete(cmd, mgmt_status(status));
+ bacpy(&rp.addr.bdaddr, bdaddr);
+ rp.addr.type = bdaddr_type;
+
+ cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT,
+ mgmt_status(status), &rp, sizeof(rp));
+
mgmt_pending_remove(cmd);
}
@@ -6584,12 +6352,18 @@
u8 status)
{
struct pending_cmd *cmd;
+ struct mgmt_rp_pin_code_reply rp;
cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
if (!cmd)
return;
- cmd->cmd_complete(cmd, mgmt_status(status));
+ bacpy(&rp.addr.bdaddr, bdaddr);
+ rp.addr.type = BDADDR_BREDR;
+
+ cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
+ mgmt_status(status), &rp, sizeof(rp));
+
mgmt_pending_remove(cmd);
}
@@ -6597,12 +6371,18 @@
u8 status)
{
struct pending_cmd *cmd;
+ struct mgmt_rp_pin_code_reply rp;
cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
if (!cmd)
return;
- cmd->cmd_complete(cmd, mgmt_status(status));
+ bacpy(&rp.addr.bdaddr, bdaddr);
+ rp.addr.type = BDADDR_BREDR;
+
+ cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
+ mgmt_status(status), &rp, sizeof(rp));
+
mgmt_pending_remove(cmd);
}
@@ -6642,15 +6422,21 @@
u8 opcode)
{
struct pending_cmd *cmd;
+ struct mgmt_rp_user_confirm_reply rp;
+ int err;
cmd = mgmt_pending_find(opcode, hdev);
if (!cmd)
return -ENOENT;
- cmd->cmd_complete(cmd, mgmt_status(status));
+ bacpy(&rp.addr.bdaddr, bdaddr);
+ rp.addr.type = link_to_bdaddr(link_type, addr_type);
+ err = cmd_complete(cmd->sk, hdev->id, opcode, mgmt_status(status),
+ &rp, sizeof(rp));
+
mgmt_pending_remove(cmd);
- return 0;
+ return err;
}
int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
@@ -6714,10 +6500,8 @@
mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
cmd ? cmd->sk : NULL);
- if (cmd) {
- cmd->cmd_complete(cmd, status);
- mgmt_pending_remove(cmd);
- }
+ if (cmd)
+ pairing_complete(cmd, status);
}
void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
@@ -6909,8 +6693,8 @@
}
void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192,
- u8 *rand192, u8 *hash256, u8 *rand256,
- u8 status)
+ u8 *randomizer192, u8 *hash256,
+ u8 *randomizer256, u8 status)
{
struct pending_cmd *cmd;
@@ -6924,14 +6708,17 @@
cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
mgmt_status(status));
} else {
- if (bredr_sc_enabled(hdev) && hash256 && rand256) {
+ if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
+ hash256 && randomizer256) {
struct mgmt_rp_read_local_oob_ext_data rp;
memcpy(rp.hash192, hash192, sizeof(rp.hash192));
- memcpy(rp.rand192, rand192, sizeof(rp.rand192));
+ memcpy(rp.randomizer192, randomizer192,
+ sizeof(rp.randomizer192));
memcpy(rp.hash256, hash256, sizeof(rp.hash256));
- memcpy(rp.rand256, rand256, sizeof(rp.rand256));
+ memcpy(rp.randomizer256, randomizer256,
+ sizeof(rp.randomizer256));
cmd_complete(cmd->sk, hdev->id,
MGMT_OP_READ_LOCAL_OOB_DATA, 0,
@@ -6940,7 +6727,8 @@
struct mgmt_rp_read_local_oob_data rp;
memcpy(rp.hash, hash192, sizeof(rp.hash));
- memcpy(rp.rand, rand192, sizeof(rp.rand));
+ memcpy(rp.randomizer, randomizer192,
+ sizeof(rp.randomizer));
cmd_complete(cmd->sk, hdev->id,
MGMT_OP_READ_LOCAL_OOB_DATA, 0,
@@ -6951,73 +6739,6 @@
mgmt_pending_remove(cmd);
}
-static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
-{
- int i;
-
- for (i = 0; i < uuid_count; i++) {
- if (!memcmp(uuid, uuids[i], 16))
- return true;
- }
-
- return false;
-}
-
-static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
-{
- u16 parsed = 0;
-
- while (parsed < eir_len) {
- u8 field_len = eir[0];
- u8 uuid[16];
- int i;
-
- if (field_len == 0)
- break;
-
- if (eir_len - parsed < field_len + 1)
- break;
-
- switch (eir[1]) {
- case EIR_UUID16_ALL:
- case EIR_UUID16_SOME:
- for (i = 0; i + 3 <= field_len; i += 2) {
- memcpy(uuid, bluetooth_base_uuid, 16);
- uuid[13] = eir[i + 3];
- uuid[12] = eir[i + 2];
- if (has_uuid(uuid, uuid_count, uuids))
- return true;
- }
- break;
- case EIR_UUID32_ALL:
- case EIR_UUID32_SOME:
- for (i = 0; i + 5 <= field_len; i += 4) {
- memcpy(uuid, bluetooth_base_uuid, 16);
- uuid[15] = eir[i + 5];
- uuid[14] = eir[i + 4];
- uuid[13] = eir[i + 3];
- uuid[12] = eir[i + 2];
- if (has_uuid(uuid, uuid_count, uuids))
- return true;
- }
- break;
- case EIR_UUID128_ALL:
- case EIR_UUID128_SOME:
- for (i = 0; i + 17 <= field_len; i += 16) {
- memcpy(uuid, eir + i + 2, 16);
- if (has_uuid(uuid, uuid_count, uuids))
- return true;
- }
- break;
- }
-
- parsed += field_len + 1;
- eir += field_len + 1;
- }
-
- return false;
-}
-
void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
@@ -7025,7 +6746,6 @@
char buf[512];
struct mgmt_ev_device_found *ev = (void *) buf;
size_t ev_size;
- bool match;
/* Don't send events for a non-kernel initiated discovery. With
* LE one exception is if we have pend_le_reports > 0 in which
@@ -7038,18 +6758,6 @@
return;
}
- /* When using service discovery with a RSSI threshold, then check
- * if such a RSSI threshold is specified. If a RSSI threshold has
- * been specified, then all results with a RSSI smaller than the
- * RSSI threshold will be dropped.
- *
- * For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
- * the results are also dropped.
- */
- if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
- (rssi < hdev->discovery.rssi || rssi == HCI_RSSI_INVALID))
- return;
-
/* Make sure that the buffer is big enough. The 5 extra bytes
* are for the potential CoD field.
*/
@@ -7058,79 +6766,20 @@
memset(buf, 0, sizeof(buf));
- /* In case of device discovery with BR/EDR devices (pre 1.2), the
- * RSSI value was reported as 0 when not available. This behavior
- * is kept when using device discovery. This is required for full
- * backwards compatibility with the API.
- *
- * However when using service discovery, the value 127 will be
- * returned when the RSSI is not available.
- */
- if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi)
- rssi = 0;
-
bacpy(&ev->addr.bdaddr, bdaddr);
ev->addr.type = link_to_bdaddr(link_type, addr_type);
ev->rssi = rssi;
ev->flags = cpu_to_le32(flags);
- if (eir_len > 0) {
- /* When using service discovery and a list of UUID is
- * provided, results with no matching UUID should be
- * dropped. In case there is a match the result is
- * kept and checking possible scan response data
- * will be skipped.
- */
- if (hdev->discovery.uuid_count > 0)
- match = eir_has_uuids(eir, eir_len,
- hdev->discovery.uuid_count,
- hdev->discovery.uuids);
- else
- match = true;
-
- if (!match && !scan_rsp_len)
- return;
-
- /* Copy EIR or advertising data into event */
+ if (eir_len > 0)
memcpy(ev->eir, eir, eir_len);
- } else {
- /* When using service discovery and a list of UUID is
- * provided, results with empty EIR or advertising data
- * should be dropped since they do not match any UUID.
- */
- if (hdev->discovery.uuid_count > 0 && !scan_rsp_len)
- return;
-
- match = false;
- }
if (dev_class && !eir_has_data_type(ev->eir, eir_len, EIR_CLASS_OF_DEV))
eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV,
dev_class, 3);
- if (scan_rsp_len > 0) {
- /* When using service discovery and a list of UUID is
- * provided, results with no matching UUID should be
- * dropped if there is no previous match from the
- * advertising data.
- */
- if (hdev->discovery.uuid_count > 0) {
- if (!match && !eir_has_uuids(scan_rsp, scan_rsp_len,
- hdev->discovery.uuid_count,
- hdev->discovery.uuids))
- return;
- }
-
- /* Append scan response data to event */
+ if (scan_rsp_len > 0)
memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len);
- } else {
- /* When using service discovery and a list of UUID is
- * provided, results with empty scan response and no
- * previous matched advertising data should be dropped.
- */
- if (hdev->discovery.uuid_count > 0 && !match)
- return;
- }
ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
ev_size = sizeof(*ev) + eir_len + scan_rsp_len;
@@ -7164,9 +6813,23 @@
void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
{
struct mgmt_ev_discovering ev;
+ struct pending_cmd *cmd;
BT_DBG("%s discovering %u", hdev->name, discovering);
+ if (discovering)
+ cmd = mgmt_pending_find(MGMT_OP_START_DISCOVERY, hdev);
+ else
+ cmd = mgmt_pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
+
+ if (cmd != NULL) {
+ u8 type = hdev->discovery.type;
+
+ cmd_complete(cmd->sk, hdev->id, cmd->opcode, 0, &type,
+ sizeof(type));
+ mgmt_pending_remove(cmd);
+ }
+
memset(&ev, 0, sizeof(ev));
ev.type = hdev->discovery.type;
ev.discovering = discovering;
diff --git a/net/bluetooth/rfcomm/Kconfig b/net/bluetooth/rfcomm/Kconfig
index 073e07f..1ab7444 100644
--- a/net/bluetooth/rfcomm/Kconfig
+++ b/net/bluetooth/rfcomm/Kconfig
@@ -1,7 +1,7 @@
config BT_RFCOMM
tristate "RFCOMM protocol support"
depends on m
- depends on BT_BREDR
+ depends on BT
help
RFCOMM provides connection oriented stream transport. RFCOMM
support is required for Dialup Networking, OBEX and other Bluetooth
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index 8b5b653..aa3bee4 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -78,10 +78,8 @@
#define __get_type(b) ((b & 0xef))
#define __test_ea(b) ((b & 0x01))
-#define __test_cr(b) (!!(b & 0x02))
-#define __test_pf(b) (!!(b & 0x10))
-
-#define __session_dir(s) ((s)->initiator ? 0x00 : 0x01)
+#define __test_cr(b) ((b & 0x02))
+#define __test_pf(b) ((b & 0x10))
#define __addr(cr, dlci) (((dlci & 0x3f) << 2) | (cr << 1) | 0x01)
#define __ctrl(type, pf) (((type & 0xef) | (pf << 4)))
@@ -103,11 +101,11 @@
#define __get_rpn_stop_bits(line) (((line) >> 2) & 0x1)
#define __get_rpn_parity(line) (((line) >> 3) & 0x7)
-static DECLARE_WAIT_QUEUE_HEAD(rfcomm_wq);
-
static void rfcomm_schedule(void)
{
- wake_up_all(&rfcomm_wq);
+ if (!rfcomm_thread)
+ return;
+ wake_up_process(rfcomm_thread);
}
/* ---- RFCOMM FCS computation ---- */
@@ -398,7 +396,7 @@
return err;
}
- dlci = __dlci(__session_dir(s), channel);
+ dlci = __dlci(!s->initiator, channel);
/* Check if DLCI already exists */
if (rfcomm_dlc_get(s, dlci))
@@ -553,7 +551,7 @@
rfcomm_lock();
s = rfcomm_session_get(src, dst);
if (s) {
- dlci = __dlci(__session_dir(s), channel);
+ dlci = __dlci(!s->initiator, channel);
dlc = rfcomm_dlc_get(s, dlci);
}
rfcomm_unlock();
@@ -914,7 +912,7 @@
hdr->len = __len8(sizeof(*mcc) + 1);
mcc = (void *) ptr; ptr += sizeof(*mcc);
- mcc->type = __mcc_type(0, RFCOMM_NSC);
+ mcc->type = __mcc_type(cr, RFCOMM_NSC);
mcc->len = __len8(1);
/* Type that we didn't like */
@@ -2100,22 +2098,24 @@
static int rfcomm_run(void *unused)
{
- DEFINE_WAIT_FUNC(wait, woken_wake_function);
BT_DBG("");
set_user_nice(current, -10);
rfcomm_add_listener(BDADDR_ANY);
- add_wait_queue(&rfcomm_wq, &wait);
- while (!kthread_should_stop()) {
+ while (1) {
+ set_current_state(TASK_INTERRUPTIBLE);
+
+ if (kthread_should_stop())
+ break;
/* Process stuff */
rfcomm_process_sessions();
- wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
+ schedule();
}
- remove_wait_queue(&rfcomm_wq, &wait);
+ __set_current_state(TASK_RUNNING);
rfcomm_kill_listener();
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index acaac1b..4688936 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -596,7 +596,7 @@
}
skb_reserve(skb, RFCOMM_SKB_HEAD_RESERVE);
- err = memcpy_from_msg(skb_put(skb, size), msg, size);
+ err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
if (err) {
kfree_skb(skb);
if (sent == 0)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 73bc2c3..c4db547 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -285,7 +285,7 @@
if (!skb)
return err;
- if (memcpy_from_msg(skb_put(skb, len), msg, len)) {
+ if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) {
kfree_skb(skb);
return -EFAULT;
}
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index ef0de39..f09b6b6 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -29,34 +29,14 @@
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/mgmt.h>
-#include "ecc.h"
#include "smp.h"
-/* Low-level debug macros to be used for stuff that we don't want
- * accidentially in dmesg, i.e. the values of the various crypto keys
- * and the inputs & outputs of crypto functions.
- */
-#ifdef DEBUG
-#define SMP_DBG(fmt, ...) printk(KERN_DEBUG "%s: " fmt, __func__, \
- ##__VA_ARGS__)
-#else
-#define SMP_DBG(fmt, ...) no_printk(KERN_DEBUG "%s: " fmt, __func__, \
- ##__VA_ARGS__)
-#endif
-
#define SMP_ALLOW_CMD(smp, code) set_bit(code, &smp->allow_cmd)
-/* Keys which are not distributed with Secure Connections */
-#define SMP_SC_NO_DIST (SMP_DIST_ENC_KEY | SMP_DIST_LINK_KEY);
-
#define SMP_TIMEOUT msecs_to_jiffies(30000)
-#define AUTH_REQ_MASK(dev) (test_bit(HCI_SC_ENABLED, &(dev)->dev_flags) ? \
- 0x1f : 0x07)
-#define KEY_DIST_MASK 0x07
-
-/* Maximum message length that can be passed to aes_cmac */
-#define CMAC_MSG_MAX 80
+#define AUTH_REQ_MASK 0x07
+#define KEY_DIST_MASK 0x07
enum {
SMP_FLAG_TK_VALID,
@@ -64,12 +44,6 @@
SMP_FLAG_MITM_AUTH,
SMP_FLAG_COMPLETE,
SMP_FLAG_INITIATOR,
- SMP_FLAG_SC,
- SMP_FLAG_REMOTE_PK,
- SMP_FLAG_DEBUG_KEY,
- SMP_FLAG_WAIT_USER,
- SMP_FLAG_DHKEY_PENDING,
- SMP_FLAG_OOB,
};
struct smp_chan {
@@ -83,7 +57,6 @@
u8 rrnd[16]; /* SMP Pairing Random (remote) */
u8 pcnf[16]; /* SMP Pairing Confirm */
u8 tk[16]; /* SMP Temporary Key */
- u8 rr[16];
u8 enc_key_size;
u8 remote_key_dist;
bdaddr_t id_addr;
@@ -94,43 +67,9 @@
struct smp_ltk *ltk;
struct smp_ltk *slave_ltk;
struct smp_irk *remote_irk;
- u8 *link_key;
unsigned long flags;
- u8 method;
- u8 passkey_round;
-
- /* Secure Connections variables */
- u8 local_pk[64];
- u8 local_sk[32];
- u8 remote_pk[64];
- u8 dhkey[32];
- u8 mackey[16];
struct crypto_blkcipher *tfm_aes;
- struct crypto_hash *tfm_cmac;
-};
-
-/* These debug key values are defined in the SMP section of the core
- * specification. debug_pk is the public debug key and debug_sk the
- * private debug key.
- */
-static const u8 debug_pk[64] = {
- 0xe6, 0x9d, 0x35, 0x0e, 0x48, 0x01, 0x03, 0xcc,
- 0xdb, 0xfd, 0xf4, 0xac, 0x11, 0x91, 0xf4, 0xef,
- 0xb9, 0xa5, 0xf9, 0xe9, 0xa7, 0x83, 0x2c, 0x5e,
- 0x2c, 0xbe, 0x97, 0xf2, 0xd2, 0x03, 0xb0, 0x20,
-
- 0x8b, 0xd2, 0x89, 0x15, 0xd0, 0x8e, 0x1c, 0x74,
- 0x24, 0x30, 0xed, 0x8f, 0xc2, 0x45, 0x63, 0x76,
- 0x5c, 0x15, 0x52, 0x5a, 0xbf, 0x9a, 0x32, 0x63,
- 0x6d, 0xeb, 0x2a, 0x65, 0x49, 0x9c, 0x80, 0xdc,
-};
-
-static const u8 debug_sk[32] = {
- 0xbd, 0x1a, 0x3c, 0xcd, 0xa6, 0xb8, 0x99, 0x58,
- 0x99, 0xb7, 0x40, 0xeb, 0x7b, 0x60, 0xff, 0x4a,
- 0x50, 0x3f, 0x10, 0xd2, 0xe3, 0xb3, 0xc9, 0x74,
- 0x38, 0x5f, 0xc5, 0xa3, 0xd4, 0xf6, 0x49, 0x3f,
};
static inline void swap_buf(const u8 *src, u8 *dst, size_t len)
@@ -141,214 +80,6 @@
dst[len - 1 - i] = src[i];
}
-/* The following functions map to the LE SC SMP crypto functions
- * AES-CMAC, f4, f5, f6, g2 and h6.
- */
-
-static int aes_cmac(struct crypto_hash *tfm, const u8 k[16], const u8 *m,
- size_t len, u8 mac[16])
-{
- uint8_t tmp[16], mac_msb[16], msg_msb[CMAC_MSG_MAX];
- struct hash_desc desc;
- struct scatterlist sg;
- int err;
-
- if (len > CMAC_MSG_MAX)
- return -EFBIG;
-
- if (!tfm) {
- BT_ERR("tfm %p", tfm);
- return -EINVAL;
- }
-
- desc.tfm = tfm;
- desc.flags = 0;
-
- crypto_hash_init(&desc);
-
- /* Swap key and message from LSB to MSB */
- swap_buf(k, tmp, 16);
- swap_buf(m, msg_msb, len);
-
- SMP_DBG("msg (len %zu) %*phN", len, (int) len, m);
- SMP_DBG("key %16phN", k);
-
- err = crypto_hash_setkey(tfm, tmp, 16);
- if (err) {
- BT_ERR("cipher setkey failed: %d", err);
- return err;
- }
-
- sg_init_one(&sg, msg_msb, len);
-
- err = crypto_hash_update(&desc, &sg, len);
- if (err) {
- BT_ERR("Hash update error %d", err);
- return err;
- }
-
- err = crypto_hash_final(&desc, mac_msb);
- if (err) {
- BT_ERR("Hash final error %d", err);
- return err;
- }
-
- swap_buf(mac_msb, mac, 16);
-
- SMP_DBG("mac %16phN", mac);
-
- return 0;
-}
-
-static int smp_f4(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
- const u8 x[16], u8 z, u8 res[16])
-{
- u8 m[65];
- int err;
-
- SMP_DBG("u %32phN", u);
- SMP_DBG("v %32phN", v);
- SMP_DBG("x %16phN z %02x", x, z);
-
- m[0] = z;
- memcpy(m + 1, v, 32);
- memcpy(m + 33, u, 32);
-
- err = aes_cmac(tfm_cmac, x, m, sizeof(m), res);
- if (err)
- return err;
-
- SMP_DBG("res %16phN", res);
-
- return err;
-}
-
-static int smp_f5(struct crypto_hash *tfm_cmac, u8 w[32], u8 n1[16], u8 n2[16],
- u8 a1[7], u8 a2[7], u8 mackey[16], u8 ltk[16])
-{
- /* The btle, salt and length "magic" values are as defined in
- * the SMP section of the Bluetooth core specification. In ASCII
- * the btle value ends up being 'btle'. The salt is just a
- * random number whereas length is the value 256 in little
- * endian format.
- */
- const u8 btle[4] = { 0x65, 0x6c, 0x74, 0x62 };
- const u8 salt[16] = { 0xbe, 0x83, 0x60, 0x5a, 0xdb, 0x0b, 0x37, 0x60,
- 0x38, 0xa5, 0xf5, 0xaa, 0x91, 0x83, 0x88, 0x6c };
- const u8 length[2] = { 0x00, 0x01 };
- u8 m[53], t[16];
- int err;
-
- SMP_DBG("w %32phN", w);
- SMP_DBG("n1 %16phN n2 %16phN", n1, n2);
- SMP_DBG("a1 %7phN a2 %7phN", a1, a2);
-
- err = aes_cmac(tfm_cmac, salt, w, 32, t);
- if (err)
- return err;
-
- SMP_DBG("t %16phN", t);
-
- memcpy(m, length, 2);
- memcpy(m + 2, a2, 7);
- memcpy(m + 9, a1, 7);
- memcpy(m + 16, n2, 16);
- memcpy(m + 32, n1, 16);
- memcpy(m + 48, btle, 4);
-
- m[52] = 0; /* Counter */
-
- err = aes_cmac(tfm_cmac, t, m, sizeof(m), mackey);
- if (err)
- return err;
-
- SMP_DBG("mackey %16phN", mackey);
-
- m[52] = 1; /* Counter */
-
- err = aes_cmac(tfm_cmac, t, m, sizeof(m), ltk);
- if (err)
- return err;
-
- SMP_DBG("ltk %16phN", ltk);
-
- return 0;
-}
-
-static int smp_f6(struct crypto_hash *tfm_cmac, const u8 w[16],
- const u8 n1[16], u8 n2[16], const u8 r[16],
- const u8 io_cap[3], const u8 a1[7], const u8 a2[7],
- u8 res[16])
-{
- u8 m[65];
- int err;
-
- SMP_DBG("w %16phN", w);
- SMP_DBG("n1 %16phN n2 %16phN", n1, n2);
- SMP_DBG("r %16phN io_cap %3phN a1 %7phN a2 %7phN", r, io_cap, a1, a2);
-
- memcpy(m, a2, 7);
- memcpy(m + 7, a1, 7);
- memcpy(m + 14, io_cap, 3);
- memcpy(m + 17, r, 16);
- memcpy(m + 33, n2, 16);
- memcpy(m + 49, n1, 16);
-
- err = aes_cmac(tfm_cmac, w, m, sizeof(m), res);
- if (err)
- return err;
-
- BT_DBG("res %16phN", res);
-
- return err;
-}
-
-static int smp_g2(struct crypto_hash *tfm_cmac, const u8 u[32], const u8 v[32],
- const u8 x[16], const u8 y[16], u32 *val)
-{
- u8 m[80], tmp[16];
- int err;
-
- SMP_DBG("u %32phN", u);
- SMP_DBG("v %32phN", v);
- SMP_DBG("x %16phN y %16phN", x, y);
-
- memcpy(m, y, 16);
- memcpy(m + 16, v, 32);
- memcpy(m + 48, u, 32);
-
- err = aes_cmac(tfm_cmac, x, m, sizeof(m), tmp);
- if (err)
- return err;
-
- *val = get_unaligned_le32(tmp);
- *val %= 1000000;
-
- SMP_DBG("val %06u", *val);
-
- return 0;
-}
-
-static int smp_h6(struct crypto_hash *tfm_cmac, const u8 w[16],
- const u8 key_id[4], u8 res[16])
-{
- int err;
-
- SMP_DBG("w %16phN key_id %4phN", w, key_id);
-
- err = aes_cmac(tfm_cmac, w, key_id, 4, res);
- if (err)
- return err;
-
- SMP_DBG("res %16phN", res);
-
- return err;
-}
-
-/* The following functions map to the legacy SMP crypto functions e, c1,
- * s1 and ah.
- */
-
static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r)
{
struct blkcipher_desc desc;
@@ -356,7 +87,7 @@
uint8_t tmp[16], data[16];
int err;
- if (!tfm) {
+ if (tfm == NULL) {
BT_ERR("tfm %p", tfm);
return -EINVAL;
}
@@ -388,65 +119,7 @@
return err;
}
-static int smp_c1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
- const u8 r[16], const u8 preq[7], const u8 pres[7], u8 _iat,
- const bdaddr_t *ia, u8 _rat, const bdaddr_t *ra, u8 res[16])
-{
- u8 p1[16], p2[16];
- int err;
-
- memset(p1, 0, 16);
-
- /* p1 = pres || preq || _rat || _iat */
- p1[0] = _iat;
- p1[1] = _rat;
- memcpy(p1 + 2, preq, 7);
- memcpy(p1 + 9, pres, 7);
-
- /* p2 = padding || ia || ra */
- memcpy(p2, ra, 6);
- memcpy(p2 + 6, ia, 6);
- memset(p2 + 12, 0, 4);
-
- /* res = r XOR p1 */
- u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
-
- /* res = e(k, res) */
- err = smp_e(tfm_aes, k, res);
- if (err) {
- BT_ERR("Encrypt data error");
- return err;
- }
-
- /* res = res XOR p2 */
- u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
-
- /* res = e(k, res) */
- err = smp_e(tfm_aes, k, res);
- if (err)
- BT_ERR("Encrypt data error");
-
- return err;
-}
-
-static int smp_s1(struct crypto_blkcipher *tfm_aes, const u8 k[16],
- const u8 r1[16], const u8 r2[16], u8 _r[16])
-{
- int err;
-
- /* Just least significant octets from r1 and r2 are considered */
- memcpy(_r, r2, 8);
- memcpy(_r + 8, r1, 8);
-
- err = smp_e(tfm_aes, k, _r);
- if (err)
- BT_ERR("Encrypt data error");
-
- return err;
-}
-
-static int smp_ah(struct crypto_blkcipher *tfm, const u8 irk[16],
- const u8 r[3], u8 res[3])
+static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3])
{
u8 _res[16];
int err;
@@ -472,8 +145,7 @@
return 0;
}
-bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
- const bdaddr_t *bdaddr)
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr)
{
struct l2cap_chan *chan = hdev->smp_data;
struct crypto_blkcipher *tfm;
@@ -494,7 +166,7 @@
return !memcmp(bdaddr->b, hash, 3);
}
-int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa)
+int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa)
{
struct l2cap_chan *chan = hdev->smp_data;
struct crypto_blkcipher *tfm;
@@ -519,6 +191,69 @@
return 0;
}
+static int smp_c1(struct smp_chan *smp, u8 k[16], u8 r[16], u8 preq[7],
+ u8 pres[7], u8 _iat, bdaddr_t *ia, u8 _rat, bdaddr_t *ra,
+ u8 res[16])
+{
+ struct hci_dev *hdev = smp->conn->hcon->hdev;
+ u8 p1[16], p2[16];
+ int err;
+
+ BT_DBG("%s", hdev->name);
+
+ memset(p1, 0, 16);
+
+ /* p1 = pres || preq || _rat || _iat */
+ p1[0] = _iat;
+ p1[1] = _rat;
+ memcpy(p1 + 2, preq, 7);
+ memcpy(p1 + 9, pres, 7);
+
+ /* p2 = padding || ia || ra */
+ memcpy(p2, ra, 6);
+ memcpy(p2 + 6, ia, 6);
+ memset(p2 + 12, 0, 4);
+
+ /* res = r XOR p1 */
+ u128_xor((u128 *) res, (u128 *) r, (u128 *) p1);
+
+ /* res = e(k, res) */
+ err = smp_e(smp->tfm_aes, k, res);
+ if (err) {
+ BT_ERR("Encrypt data error");
+ return err;
+ }
+
+ /* res = res XOR p2 */
+ u128_xor((u128 *) res, (u128 *) res, (u128 *) p2);
+
+ /* res = e(k, res) */
+ err = smp_e(smp->tfm_aes, k, res);
+ if (err)
+ BT_ERR("Encrypt data error");
+
+ return err;
+}
+
+static int smp_s1(struct smp_chan *smp, u8 k[16], u8 r1[16], u8 r2[16],
+ u8 _r[16])
+{
+ struct hci_dev *hdev = smp->conn->hcon->hdev;
+ int err;
+
+ BT_DBG("%s", hdev->name);
+
+ /* Just least significant octets from r1 and r2 are considered */
+ memcpy(_r, r2, 8);
+ memcpy(_r + 8, r1, 8);
+
+ err = smp_e(smp->tfm_aes, k, _r);
+ if (err)
+ BT_ERR("Encrypt data error");
+
+ return err;
+}
+
static void smp_send_cmd(struct l2cap_conn *conn, u8 code, u16 len, void *data)
{
struct l2cap_chan *chan = conn->smp;
@@ -539,12 +274,8 @@
memset(&msg, 0, sizeof(msg));
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0)
- iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, iv, 2, 1 + len);
-#else
msg.msg_iov = (struct iovec *) &iv;
msg.msg_iovlen = 2;
-#endif
l2cap_chan_send(chan, &msg, 1 + len);
@@ -557,22 +288,17 @@
schedule_delayed_work(&smp->security_timer, SMP_TIMEOUT);
}
-static u8 authreq_to_seclevel(u8 authreq)
+static __u8 authreq_to_seclevel(__u8 authreq)
{
- if (authreq & SMP_AUTH_MITM) {
- if (authreq & SMP_AUTH_SC)
- return BT_SECURITY_FIPS;
- else
- return BT_SECURITY_HIGH;
- } else {
+ if (authreq & SMP_AUTH_MITM)
+ return BT_SECURITY_HIGH;
+ else
return BT_SECURITY_MEDIUM;
- }
}
static __u8 seclevel_to_authreq(__u8 sec_level)
{
switch (sec_level) {
- case BT_SECURITY_FIPS:
case BT_SECURITY_HIGH:
return SMP_AUTH_MITM | SMP_AUTH_BONDING;
case BT_SECURITY_MEDIUM:
@@ -590,7 +316,7 @@
struct smp_chan *smp = chan->data;
struct hci_conn *hcon = conn->hcon;
struct hci_dev *hdev = hcon->hdev;
- u8 local_dist = 0, remote_dist = 0, oob_flag = SMP_OOB_NOT_PRESENT;
+ u8 local_dist = 0, remote_dist = 0;
if (test_bit(HCI_BONDABLE, &conn->hcon->hdev->dev_flags)) {
local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
@@ -606,52 +332,24 @@
if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
local_dist |= SMP_DIST_ID_KEY;
- if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) &&
- (authreq & SMP_AUTH_SC)) {
- struct oob_data *oob_data;
- u8 bdaddr_type;
-
- if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
- local_dist |= SMP_DIST_LINK_KEY;
- remote_dist |= SMP_DIST_LINK_KEY;
- }
-
- if (hcon->dst_type == ADDR_LE_DEV_PUBLIC)
- bdaddr_type = BDADDR_LE_PUBLIC;
- else
- bdaddr_type = BDADDR_LE_RANDOM;
-
- oob_data = hci_find_remote_oob_data(hdev, &hcon->dst,
- bdaddr_type);
- if (oob_data) {
- set_bit(SMP_FLAG_OOB, &smp->flags);
- oob_flag = SMP_OOB_PRESENT;
- memcpy(smp->rr, oob_data->rand256, 16);
- memcpy(smp->pcnf, oob_data->hash256, 16);
- }
-
- } else {
- authreq &= ~SMP_AUTH_SC;
- }
-
if (rsp == NULL) {
req->io_capability = conn->hcon->io_capability;
- req->oob_flag = oob_flag;
+ req->oob_flag = SMP_OOB_NOT_PRESENT;
req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
req->init_key_dist = local_dist;
req->resp_key_dist = remote_dist;
- req->auth_req = (authreq & AUTH_REQ_MASK(hdev));
+ req->auth_req = (authreq & AUTH_REQ_MASK);
smp->remote_key_dist = remote_dist;
return;
}
rsp->io_capability = conn->hcon->io_capability;
- rsp->oob_flag = oob_flag;
+ rsp->oob_flag = SMP_OOB_NOT_PRESENT;
rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
rsp->init_key_dist = req->init_key_dist & remote_dist;
rsp->resp_key_dist = req->resp_key_dist & local_dist;
- rsp->auth_req = (authreq & AUTH_REQ_MASK(hdev));
+ rsp->auth_req = (authreq & AUTH_REQ_MASK);
smp->remote_key_dist = rsp->init_key_dist;
}
@@ -674,7 +372,6 @@
{
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
- struct hci_conn *hcon = conn->hcon;
bool complete;
BUG_ON(!smp);
@@ -682,46 +379,34 @@
cancel_delayed_work_sync(&smp->security_timer);
complete = test_bit(SMP_FLAG_COMPLETE, &smp->flags);
- mgmt_smp_complete(hcon, complete);
+ mgmt_smp_complete(conn->hcon, complete);
kfree(smp->csrk);
kfree(smp->slave_csrk);
- kfree(smp->link_key);
crypto_free_blkcipher(smp->tfm_aes);
- crypto_free_hash(smp->tfm_cmac);
-
- /* Ensure that we don't leave any debug key around if debug key
- * support hasn't been explicitly enabled.
- */
- if (smp->ltk && smp->ltk->type == SMP_LTK_P256_DEBUG &&
- !test_bit(HCI_KEEP_DEBUG_KEYS, &hcon->hdev->dev_flags)) {
- list_del_rcu(&smp->ltk->list);
- kfree_rcu(smp->ltk, rcu);
- smp->ltk = NULL;
- }
/* If pairing failed clean up any keys we might have */
if (!complete) {
if (smp->ltk) {
- list_del_rcu(&smp->ltk->list);
- kfree_rcu(smp->ltk, rcu);
+ list_del(&smp->ltk->list);
+ kfree(smp->ltk);
}
if (smp->slave_ltk) {
- list_del_rcu(&smp->slave_ltk->list);
- kfree_rcu(smp->slave_ltk, rcu);
+ list_del(&smp->slave_ltk->list);
+ kfree(smp->slave_ltk);
}
if (smp->remote_irk) {
- list_del_rcu(&smp->remote_irk->list);
- kfree_rcu(smp->remote_irk, rcu);
+ list_del(&smp->remote_irk->list);
+ kfree(smp->remote_irk);
}
}
chan->data = NULL;
kfree(smp);
- hci_conn_drop(hcon);
+ hci_conn_drop(conn->hcon);
}
static void smp_failure(struct l2cap_conn *conn, u8 reason)
@@ -745,7 +430,6 @@
#define REQ_PASSKEY 0x02
#define CFM_PASSKEY 0x03
#define REQ_OOB 0x04
-#define DSP_PASSKEY 0x05
#define OVERLAP 0xFF
static const u8 gen_method[5][5] = {
@@ -756,14 +440,6 @@
{ CFM_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, OVERLAP },
};
-static const u8 sc_method[5][5] = {
- { JUST_WORKS, JUST_CFM, REQ_PASSKEY, JUST_WORKS, REQ_PASSKEY },
- { JUST_WORKS, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
- { DSP_PASSKEY, DSP_PASSKEY, REQ_PASSKEY, JUST_WORKS, DSP_PASSKEY },
- { JUST_WORKS, JUST_CFM, JUST_WORKS, JUST_WORKS, JUST_CFM },
- { DSP_PASSKEY, CFM_PASSKEY, REQ_PASSKEY, JUST_WORKS, CFM_PASSKEY },
-};
-
static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io)
{
/* If either side has unknown io_caps, use JUST_CFM (which gets
@@ -773,9 +449,6 @@
remote_io > SMP_IO_KEYBOARD_DISPLAY)
return JUST_CFM;
- if (test_bit(SMP_FLAG_SC, &smp->flags))
- return sc_method[remote_io][local_io];
-
return gen_method[remote_io][local_io];
}
@@ -785,6 +458,7 @@
struct hci_conn *hcon = conn->hcon;
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
+ u8 method;
u32 passkey = 0;
int ret = 0;
@@ -801,28 +475,26 @@
* table.
*/
if (!(auth & SMP_AUTH_MITM))
- smp->method = JUST_CFM;
+ method = JUST_CFM;
else
- smp->method = get_auth_method(smp, local_io, remote_io);
+ method = get_auth_method(smp, local_io, remote_io);
/* Don't confirm locally initiated pairing attempts */
- if (smp->method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR,
- &smp->flags))
- smp->method = JUST_WORKS;
+ if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
+ method = JUST_WORKS;
/* Don't bother user space with no IO capabilities */
- if (smp->method == JUST_CFM &&
- hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
- smp->method = JUST_WORKS;
+ if (method == JUST_CFM && hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
+ method = JUST_WORKS;
/* If Just Works, Continue with Zero TK */
- if (smp->method == JUST_WORKS) {
+ if (method == JUST_WORKS) {
set_bit(SMP_FLAG_TK_VALID, &smp->flags);
return 0;
}
/* Not Just Works/Confirm results in MITM Authentication */
- if (smp->method != JUST_CFM) {
+ if (method != JUST_CFM) {
set_bit(SMP_FLAG_MITM_AUTH, &smp->flags);
if (hcon->pending_sec_level < BT_SECURITY_HIGH)
hcon->pending_sec_level = BT_SECURITY_HIGH;
@@ -831,15 +503,15 @@
/* If both devices have Keyoard-Display I/O, the master
* Confirms and the slave Enters the passkey.
*/
- if (smp->method == OVERLAP) {
+ if (method == OVERLAP) {
if (hcon->role == HCI_ROLE_MASTER)
- smp->method = CFM_PASSKEY;
+ method = CFM_PASSKEY;
else
- smp->method = REQ_PASSKEY;
+ method = REQ_PASSKEY;
}
/* Generate random passkey. */
- if (smp->method == CFM_PASSKEY) {
+ if (method == CFM_PASSKEY) {
memset(smp->tk, 0, sizeof(smp->tk));
get_random_bytes(&passkey, sizeof(passkey));
passkey %= 1000000;
@@ -848,10 +520,12 @@
set_bit(SMP_FLAG_TK_VALID, &smp->flags);
}
- if (smp->method == REQ_PASSKEY)
+ hci_dev_lock(hcon->hdev);
+
+ if (method == REQ_PASSKEY)
ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst,
hcon->type, hcon->dst_type);
- else if (smp->method == JUST_CFM)
+ else if (method == JUST_CFM)
ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst,
hcon->type, hcon->dst_type,
passkey, 1);
@@ -860,6 +534,8 @@
hcon->type, hcon->dst_type,
passkey, 0);
+ hci_dev_unlock(hcon->hdev);
+
return ret;
}
@@ -871,7 +547,7 @@
BT_DBG("conn %p", conn);
- ret = smp_c1(smp->tfm_aes, smp->tk, smp->prnd, smp->preq, smp->prsp,
+ ret = smp_c1(smp, smp->tk, smp->prnd, smp->preq, smp->prsp,
conn->hcon->init_addr_type, &conn->hcon->init_addr,
conn->hcon->resp_addr_type, &conn->hcon->resp_addr,
cp.confirm_val);
@@ -902,7 +578,7 @@
BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave");
- ret = smp_c1(smp->tfm_aes, smp->tk, smp->rrnd, smp->preq, smp->prsp,
+ ret = smp_c1(smp, smp->tk, smp->rrnd, smp->preq, smp->prsp,
hcon->init_addr_type, &hcon->init_addr,
hcon->resp_addr_type, &hcon->resp_addr, confirm);
if (ret)
@@ -918,7 +594,7 @@
__le64 rand = 0;
__le16 ediv = 0;
- smp_s1(smp->tfm_aes, smp->tk, smp->rrnd, smp->prnd, stk);
+ smp_s1(smp, smp->tk, smp->rrnd, smp->prnd, stk);
memset(stk + smp->enc_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
@@ -937,7 +613,7 @@
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
smp->prnd);
- smp_s1(smp->tfm_aes, smp->tk, smp->prnd, smp->rrnd, stk);
+ smp_s1(smp, smp->tk, smp->prnd, smp->rrnd, stk);
memset(stk + smp->enc_key_size, 0,
SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
@@ -972,13 +648,11 @@
mgmt_new_irk(hdev, smp->remote_irk);
/* Now that user space can be considered to know the
* identity address track the connection based on it
- * from now on (assuming this is an LE link).
+ * from now on.
*/
- if (hcon->type == LE_LINK) {
- bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
- hcon->dst_type = smp->remote_irk->addr_type;
- queue_work(hdev->workqueue, &conn->id_addr_update_work);
- }
+ bacpy(&hcon->dst, &smp->remote_irk->bdaddr);
+ hcon->dst_type = smp->remote_irk->addr_type;
+ queue_work(hdev->workqueue, &conn->id_addr_update_work);
/* When receiving an indentity resolving key for
* a remote device that does not use a resolvable
@@ -991,26 +665,16 @@
* just remove it.
*/
if (!bacmp(&smp->remote_irk->rpa, BDADDR_ANY)) {
- list_del_rcu(&smp->remote_irk->list);
- kfree_rcu(smp->remote_irk, rcu);
+ list_del(&smp->remote_irk->list);
+ kfree(smp->remote_irk);
smp->remote_irk = NULL;
}
}
- if (hcon->type == ACL_LINK) {
- if (hcon->key_type == HCI_LK_DEBUG_COMBINATION)
- persistent = false;
- else
- persistent = !test_bit(HCI_CONN_FLUSH_KEY,
- &hcon->flags);
- } else {
- /* The LTKs and CSRKs should be persistent only if both sides
- * had the bonding bit set in their authentication requests.
- */
- persistent = !!((req->auth_req & rsp->auth_req) &
- SMP_AUTH_BONDING);
- }
-
+ /* The LTKs and CSRKs should be persistent only if both sides
+ * had the bonding bit set in their authentication requests.
+ */
+ persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING);
if (smp->csrk) {
smp->csrk->bdaddr_type = hcon->dst_type;
@@ -1035,81 +699,6 @@
bacpy(&smp->slave_ltk->bdaddr, &hcon->dst);
mgmt_new_ltk(hdev, smp->slave_ltk, persistent);
}
-
- if (smp->link_key) {
- struct link_key *key;
- u8 type;
-
- if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
- type = HCI_LK_DEBUG_COMBINATION;
- else if (hcon->sec_level == BT_SECURITY_FIPS)
- type = HCI_LK_AUTH_COMBINATION_P256;
- else
- type = HCI_LK_UNAUTH_COMBINATION_P256;
-
- key = hci_add_link_key(hdev, smp->conn->hcon, &hcon->dst,
- smp->link_key, type, 0, &persistent);
- if (key) {
- mgmt_new_link_key(hdev, key, persistent);
-
- /* Don't keep debug keys around if the relevant
- * flag is not set.
- */
- if (!test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags) &&
- key->type == HCI_LK_DEBUG_COMBINATION) {
- list_del_rcu(&key->list);
- kfree_rcu(key, rcu);
- }
- }
- }
-}
-
-static void sc_add_ltk(struct smp_chan *smp)
-{
- struct hci_conn *hcon = smp->conn->hcon;
- u8 key_type, auth;
-
- if (test_bit(SMP_FLAG_DEBUG_KEY, &smp->flags))
- key_type = SMP_LTK_P256_DEBUG;
- else
- key_type = SMP_LTK_P256;
-
- if (hcon->pending_sec_level == BT_SECURITY_FIPS)
- auth = 1;
- else
- auth = 0;
-
- memset(smp->tk + smp->enc_key_size, 0,
- SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size);
-
- smp->ltk = hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type,
- key_type, auth, smp->tk, smp->enc_key_size,
- 0, 0);
-}
-
-static void sc_generate_link_key(struct smp_chan *smp)
-{
- /* These constants are as specified in the core specification.
- * In ASCII they spell out to 'tmp1' and 'lebr'.
- */
- const u8 tmp1[4] = { 0x31, 0x70, 0x6d, 0x74 };
- const u8 lebr[4] = { 0x72, 0x62, 0x65, 0x6c };
-
- smp->link_key = kzalloc(16, GFP_KERNEL);
- if (!smp->link_key)
- return;
-
- if (smp_h6(smp->tfm_cmac, smp->tk, tmp1, smp->link_key)) {
- kfree(smp->link_key);
- smp->link_key = NULL;
- return;
- }
-
- if (smp_h6(smp->tfm_cmac, smp->link_key, lebr, smp->link_key)) {
- kfree(smp->link_key);
- smp->link_key = NULL;
- return;
- }
}
static void smp_allow_key_dist(struct smp_chan *smp)
@@ -1126,35 +715,6 @@
SMP_ALLOW_CMD(smp, SMP_CMD_SIGN_INFO);
}
-static void sc_generate_ltk(struct smp_chan *smp)
-{
- /* These constants are as specified in the core specification.
- * In ASCII they spell out to 'tmp2' and 'brle'.
- */
- const u8 tmp2[4] = { 0x32, 0x70, 0x6d, 0x74 };
- const u8 brle[4] = { 0x65, 0x6c, 0x72, 0x62 };
- struct hci_conn *hcon = smp->conn->hcon;
- struct hci_dev *hdev = hcon->hdev;
- struct link_key *key;
-
- key = hci_find_link_key(hdev, &hcon->dst);
- if (!key) {
- BT_ERR("%s No Link Key found to generate LTK", hdev->name);
- return;
- }
-
- if (key->type == HCI_LK_DEBUG_COMBINATION)
- set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
-
- if (smp_h6(smp->tfm_cmac, key->val, tmp2, smp->tk))
- return;
-
- if (smp_h6(smp->tfm_cmac, smp->tk, brle, smp->tk))
- return;
-
- sc_add_ltk(smp);
-}
-
static void smp_distribute_keys(struct smp_chan *smp)
{
struct smp_cmd_pairing *req, *rsp;
@@ -1183,16 +743,6 @@
*keydist &= req->resp_key_dist;
}
- if (test_bit(SMP_FLAG_SC, &smp->flags)) {
- if (hcon->type == LE_LINK && (*keydist & SMP_DIST_LINK_KEY))
- sc_generate_link_key(smp);
- if (hcon->type == ACL_LINK && (*keydist & SMP_DIST_ENC_KEY))
- sc_generate_ltk(smp);
-
- /* Clear the keys which are generated but not distributed */
- *keydist &= ~SMP_SC_NO_DIST;
- }
-
BT_DBG("keydist 0x%x", *keydist);
if (*keydist & SMP_DIST_ENC_KEY) {
@@ -1304,14 +854,6 @@
return NULL;
}
- smp->tfm_cmac = crypto_alloc_hash("cmac(aes)", 0, CRYPTO_ALG_ASYNC);
- if (IS_ERR(smp->tfm_cmac)) {
- BT_ERR("Unable to create CMAC crypto context");
- crypto_free_blkcipher(smp->tfm_aes);
- kfree(smp);
- return NULL;
- }
-
smp->conn = conn;
chan->data = smp;
@@ -1324,213 +866,6 @@
return smp;
}
-static int sc_mackey_and_ltk(struct smp_chan *smp, u8 mackey[16], u8 ltk[16])
-{
- struct hci_conn *hcon = smp->conn->hcon;
- u8 *na, *nb, a[7], b[7];
-
- if (hcon->out) {
- na = smp->prnd;
- nb = smp->rrnd;
- } else {
- na = smp->rrnd;
- nb = smp->prnd;
- }
-
- memcpy(a, &hcon->init_addr, 6);
- memcpy(b, &hcon->resp_addr, 6);
- a[6] = hcon->init_addr_type;
- b[6] = hcon->resp_addr_type;
-
- return smp_f5(smp->tfm_cmac, smp->dhkey, na, nb, a, b, mackey, ltk);
-}
-
-static void sc_dhkey_check(struct smp_chan *smp)
-{
- struct hci_conn *hcon = smp->conn->hcon;
- struct smp_cmd_dhkey_check check;
- u8 a[7], b[7], *local_addr, *remote_addr;
- u8 io_cap[3], r[16];
-
- memcpy(a, &hcon->init_addr, 6);
- memcpy(b, &hcon->resp_addr, 6);
- a[6] = hcon->init_addr_type;
- b[6] = hcon->resp_addr_type;
-
- if (hcon->out) {
- local_addr = a;
- remote_addr = b;
- memcpy(io_cap, &smp->preq[1], 3);
- } else {
- local_addr = b;
- remote_addr = a;
- memcpy(io_cap, &smp->prsp[1], 3);
- }
-
- memset(r, 0, sizeof(r));
-
- if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
- put_unaligned_le32(hcon->passkey_notify, r);
-
- if (smp->method == REQ_OOB)
- memcpy(r, smp->rr, 16);
-
- smp_f6(smp->tfm_cmac, smp->mackey, smp->prnd, smp->rrnd, r, io_cap,
- local_addr, remote_addr, check.e);
-
- smp_send_cmd(smp->conn, SMP_CMD_DHKEY_CHECK, sizeof(check), &check);
-}
-
-static u8 sc_passkey_send_confirm(struct smp_chan *smp)
-{
- struct l2cap_conn *conn = smp->conn;
- struct hci_conn *hcon = conn->hcon;
- struct smp_cmd_pairing_confirm cfm;
- u8 r;
-
- r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
- r |= 0x80;
-
- get_random_bytes(smp->prnd, sizeof(smp->prnd));
-
- if (smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd, r,
- cfm.confirm_val))
- return SMP_UNSPECIFIED;
-
- smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm);
-
- return 0;
-}
-
-static u8 sc_passkey_round(struct smp_chan *smp, u8 smp_op)
-{
- struct l2cap_conn *conn = smp->conn;
- struct hci_conn *hcon = conn->hcon;
- struct hci_dev *hdev = hcon->hdev;
- u8 cfm[16], r;
-
- /* Ignore the PDU if we've already done 20 rounds (0 - 19) */
- if (smp->passkey_round >= 20)
- return 0;
-
- switch (smp_op) {
- case SMP_CMD_PAIRING_RANDOM:
- r = ((hcon->passkey_notify >> smp->passkey_round) & 0x01);
- r |= 0x80;
-
- if (smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
- smp->rrnd, r, cfm))
- return SMP_UNSPECIFIED;
-
- if (memcmp(smp->pcnf, cfm, 16))
- return SMP_CONFIRM_FAILED;
-
- smp->passkey_round++;
-
- if (smp->passkey_round == 20) {
- /* Generate MacKey and LTK */
- if (sc_mackey_and_ltk(smp, smp->mackey, smp->tk))
- return SMP_UNSPECIFIED;
- }
-
- /* The round is only complete when the initiator
- * receives pairing random.
- */
- if (!hcon->out) {
- smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
- sizeof(smp->prnd), smp->prnd);
- if (smp->passkey_round == 20)
- SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
- else
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
- return 0;
- }
-
- /* Start the next round */
- if (smp->passkey_round != 20)
- return sc_passkey_round(smp, 0);
-
- /* Passkey rounds are complete - start DHKey Check */
- sc_dhkey_check(smp);
- SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
-
- break;
-
- case SMP_CMD_PAIRING_CONFIRM:
- if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
- set_bit(SMP_FLAG_CFM_PENDING, &smp->flags);
- return 0;
- }
-
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
-
- if (hcon->out) {
- smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
- sizeof(smp->prnd), smp->prnd);
- return 0;
- }
-
- return sc_passkey_send_confirm(smp);
-
- case SMP_CMD_PUBLIC_KEY:
- default:
- /* Initiating device starts the round */
- if (!hcon->out)
- return 0;
-
- BT_DBG("%s Starting passkey round %u", hdev->name,
- smp->passkey_round + 1);
-
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
-
- return sc_passkey_send_confirm(smp);
- }
-
- return 0;
-}
-
-static int sc_user_reply(struct smp_chan *smp, u16 mgmt_op, __le32 passkey)
-{
- struct l2cap_conn *conn = smp->conn;
- struct hci_conn *hcon = conn->hcon;
- u8 smp_op;
-
- clear_bit(SMP_FLAG_WAIT_USER, &smp->flags);
-
- switch (mgmt_op) {
- case MGMT_OP_USER_PASSKEY_NEG_REPLY:
- smp_failure(smp->conn, SMP_PASSKEY_ENTRY_FAILED);
- return 0;
- case MGMT_OP_USER_CONFIRM_NEG_REPLY:
- smp_failure(smp->conn, SMP_NUMERIC_COMP_FAILED);
- return 0;
- case MGMT_OP_USER_PASSKEY_REPLY:
- hcon->passkey_notify = le32_to_cpu(passkey);
- smp->passkey_round = 0;
-
- if (test_and_clear_bit(SMP_FLAG_CFM_PENDING, &smp->flags))
- smp_op = SMP_CMD_PAIRING_CONFIRM;
- else
- smp_op = 0;
-
- if (sc_passkey_round(smp, smp_op))
- return -EIO;
-
- return 0;
- }
-
- /* Initiator sends DHKey check first */
- if (hcon->out) {
- sc_dhkey_check(smp);
- SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
- } else if (test_and_clear_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags)) {
- sc_dhkey_check(smp);
- sc_add_ltk(smp);
- }
-
- return 0;
-}
-
int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey)
{
struct l2cap_conn *conn = hcon->l2cap_data;
@@ -1556,11 +891,6 @@
smp = chan->data;
- if (test_bit(SMP_FLAG_SC, &smp->flags)) {
- err = sc_user_reply(smp, mgmt_op, passkey);
- goto unlock;
- }
-
switch (mgmt_op) {
case MGMT_OP_USER_PASSKEY_REPLY:
value = le32_to_cpu(passkey);
@@ -1596,46 +926,6 @@
return err;
}
-static void build_bredr_pairing_cmd(struct smp_chan *smp,
- struct smp_cmd_pairing *req,
- struct smp_cmd_pairing *rsp)
-{
- struct l2cap_conn *conn = smp->conn;
- struct hci_dev *hdev = conn->hcon->hdev;
- u8 local_dist = 0, remote_dist = 0;
-
- if (test_bit(HCI_BONDABLE, &hdev->dev_flags)) {
- local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
- remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN;
- }
-
- if (test_bit(HCI_RPA_RESOLVING, &hdev->dev_flags))
- remote_dist |= SMP_DIST_ID_KEY;
-
- if (test_bit(HCI_PRIVACY, &hdev->dev_flags))
- local_dist |= SMP_DIST_ID_KEY;
-
- if (!rsp) {
- memset(req, 0, sizeof(*req));
-
- req->init_key_dist = local_dist;
- req->resp_key_dist = remote_dist;
- req->max_key_size = SMP_MAX_ENC_KEY_SIZE;
-
- smp->remote_key_dist = remote_dist;
-
- return;
- }
-
- memset(rsp, 0, sizeof(*rsp));
-
- rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE;
- rsp->init_key_dist = req->init_key_dist & remote_dist;
- rsp->resp_key_dist = req->resp_key_dist & local_dist;
-
- smp->remote_key_dist = rsp->init_key_dist;
-}
-
static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing rsp, *req = (void *) skb->data;
@@ -1662,50 +952,16 @@
return SMP_UNSPECIFIED;
/* We didn't start the pairing, so match remote */
- auth = req->auth_req & AUTH_REQ_MASK(hdev);
+ auth = req->auth_req & AUTH_REQ_MASK;
if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) &&
(auth & SMP_AUTH_BONDING))
return SMP_PAIRING_NOTSUPP;
- if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
- return SMP_AUTH_REQUIREMENTS;
-
smp->preq[0] = SMP_CMD_PAIRING_REQ;
memcpy(&smp->preq[1], req, sizeof(*req));
skb_pull(skb, sizeof(*req));
- /* SMP over BR/EDR requires special treatment */
- if (conn->hcon->type == ACL_LINK) {
- /* We must have a BR/EDR SC link */
- if (!test_bit(HCI_CONN_AES_CCM, &conn->hcon->flags) &&
- !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
- return SMP_CROSS_TRANSP_NOT_ALLOWED;
-
- set_bit(SMP_FLAG_SC, &smp->flags);
-
- build_bredr_pairing_cmd(smp, req, &rsp);
-
- key_size = min(req->max_key_size, rsp.max_key_size);
- if (check_enc_key_size(conn, key_size))
- return SMP_ENC_KEY_SIZE;
-
- /* Clear bits which are generated but not distributed */
- smp->remote_key_dist &= ~SMP_SC_NO_DIST;
-
- smp->prsp[0] = SMP_CMD_PAIRING_RSP;
- memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
- smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
-
- smp_distribute_keys(smp);
- return 0;
- }
-
- build_pairing_cmd(conn, req, &rsp, auth);
-
- if (rsp.auth_req & SMP_AUTH_SC)
- set_bit(SMP_FLAG_SC, &smp->flags);
-
if (conn->hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
sec_level = BT_SECURITY_MEDIUM;
else
@@ -1714,7 +970,7 @@
if (sec_level > conn->hcon->pending_sec_level)
conn->hcon->pending_sec_level = sec_level;
- /* If we need MITM check that it can be achieved */
+ /* If we need MITM check that it can be acheived */
if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) {
u8 method;
@@ -1724,6 +980,8 @@
return SMP_AUTH_REQUIREMENTS;
}
+ build_pairing_cmd(conn, req, &rsp, auth);
+
key_size = min(req->max_key_size, rsp.max_key_size);
if (check_enc_key_size(conn, key_size))
return SMP_ENC_KEY_SIZE;
@@ -1734,18 +992,7 @@
memcpy(&smp->prsp[1], &rsp, sizeof(rsp));
smp_send_cmd(conn, SMP_CMD_PAIRING_RSP, sizeof(rsp), &rsp);
-
- clear_bit(SMP_FLAG_INITIATOR, &smp->flags);
-
- if (test_bit(SMP_FLAG_SC, &smp->flags)) {
- SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY);
- /* Clear bits which are generated but not distributed */
- smp->remote_key_dist &= ~SMP_SC_NO_DIST;
- /* Wait for Public Key from Initiating Device */
- return 0;
- } else {
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
- }
+ SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
/* Request setup of TK */
ret = tk_request(conn, 0, auth, rsp.io_capability, req->io_capability);
@@ -1755,46 +1002,11 @@
return 0;
}
-static u8 sc_send_public_key(struct smp_chan *smp)
-{
- struct hci_dev *hdev = smp->conn->hcon->hdev;
-
- BT_DBG("");
-
- if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags)) {
- BT_DBG("Using debug keys");
- memcpy(smp->local_pk, debug_pk, 64);
- memcpy(smp->local_sk, debug_sk, 32);
- set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
- } else {
- while (true) {
- /* Generate local key pair for Secure Connections */
- if (!ecc_make_key(smp->local_pk, smp->local_sk))
- return SMP_UNSPECIFIED;
-
- /* This is unlikely, but we need to check that
- * we didn't accidentially generate a debug key.
- */
- if (memcmp(smp->local_sk, debug_sk, 32))
- break;
- }
- }
-
- SMP_DBG("Local Public Key X: %32phN", smp->local_pk);
- SMP_DBG("Local Public Key Y: %32phN", &smp->local_pk[32]);
- SMP_DBG("Local Private Key: %32phN", smp->local_sk);
-
- smp_send_cmd(smp->conn, SMP_CMD_PUBLIC_KEY, 64, smp->local_pk);
-
- return 0;
-}
-
static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct smp_cmd_pairing *req, *rsp = (void *) skb->data;
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
- struct hci_dev *hdev = conn->hcon->hdev;
u8 key_size, auth;
int ret;
@@ -1814,33 +1026,9 @@
if (check_enc_key_size(conn, key_size))
return SMP_ENC_KEY_SIZE;
- auth = rsp->auth_req & AUTH_REQ_MASK(hdev);
+ auth = rsp->auth_req & AUTH_REQ_MASK;
- if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
- return SMP_AUTH_REQUIREMENTS;
-
- smp->prsp[0] = SMP_CMD_PAIRING_RSP;
- memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
-
- /* Update remote key distribution in case the remote cleared
- * some bits that we had enabled in our request.
- */
- smp->remote_key_dist &= rsp->resp_key_dist;
-
- /* For BR/EDR this means we're done and can start phase 3 */
- if (conn->hcon->type == ACL_LINK) {
- /* Clear bits which are generated but not distributed */
- smp->remote_key_dist &= ~SMP_SC_NO_DIST;
- smp_distribute_keys(smp);
- return 0;
- }
-
- if ((req->auth_req & SMP_AUTH_SC) && (auth & SMP_AUTH_SC))
- set_bit(SMP_FLAG_SC, &smp->flags);
- else if (conn->hcon->pending_sec_level > BT_SECURITY_HIGH)
- conn->hcon->pending_sec_level = BT_SECURITY_HIGH;
-
- /* If we need MITM check that it can be achieved */
+ /* If we need MITM check that it can be acheived */
if (conn->hcon->pending_sec_level >= BT_SECURITY_HIGH) {
u8 method;
@@ -1852,18 +1040,14 @@
get_random_bytes(smp->prnd, sizeof(smp->prnd));
+ smp->prsp[0] = SMP_CMD_PAIRING_RSP;
+ memcpy(&smp->prsp[1], rsp, sizeof(*rsp));
+
/* Update remote key distribution in case the remote cleared
* some bits that we had enabled in our request.
*/
smp->remote_key_dist &= rsp->resp_key_dist;
- if (test_bit(SMP_FLAG_SC, &smp->flags)) {
- /* Clear bits which are generated but not distributed */
- smp->remote_key_dist &= ~SMP_SC_NO_DIST;
- SMP_ALLOW_CMD(smp, SMP_CMD_PUBLIC_KEY);
- return sc_send_public_key(smp);
- }
-
auth |= req->auth_req;
ret = tk_request(conn, 0, auth, req->io_capability, rsp->io_capability);
@@ -1879,28 +1063,6 @@
return 0;
}
-static u8 sc_check_confirm(struct smp_chan *smp)
-{
- struct l2cap_conn *conn = smp->conn;
-
- BT_DBG("");
-
- /* Public Key exchange must happen before any other steps */
- if (!test_bit(SMP_FLAG_REMOTE_PK, &smp->flags))
- return SMP_UNSPECIFIED;
-
- if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
- return sc_passkey_round(smp, SMP_CMD_PAIRING_CONFIRM);
-
- if (conn->hcon->out) {
- smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
- smp->prnd);
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
- }
-
- return 0;
-}
-
static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb)
{
struct l2cap_chan *chan = conn->smp;
@@ -1914,9 +1076,6 @@
memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf));
skb_pull(skb, sizeof(smp->pcnf));
- if (test_bit(SMP_FLAG_SC, &smp->flags))
- return sc_check_confirm(smp);
-
if (conn->hcon->out) {
smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
smp->prnd);
@@ -1936,10 +1095,6 @@
{
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
- struct hci_conn *hcon = conn->hcon;
- u8 *pkax, *pkbx, *na, *nb;
- u32 passkey;
- int err;
BT_DBG("conn %p", conn);
@@ -1949,75 +1104,7 @@
memcpy(smp->rrnd, skb->data, sizeof(smp->rrnd));
skb_pull(skb, sizeof(smp->rrnd));
- if (!test_bit(SMP_FLAG_SC, &smp->flags))
- return smp_random(smp);
-
- if (hcon->out) {
- pkax = smp->local_pk;
- pkbx = smp->remote_pk;
- na = smp->prnd;
- nb = smp->rrnd;
- } else {
- pkax = smp->remote_pk;
- pkbx = smp->local_pk;
- na = smp->rrnd;
- nb = smp->prnd;
- }
-
- if (smp->method == REQ_OOB) {
- if (!hcon->out)
- smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
- sizeof(smp->prnd), smp->prnd);
- SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
- goto mackey_and_ltk;
- }
-
- /* Passkey entry has special treatment */
- if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
- return sc_passkey_round(smp, SMP_CMD_PAIRING_RANDOM);
-
- if (hcon->out) {
- u8 cfm[16];
-
- err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->local_pk,
- smp->rrnd, 0, cfm);
- if (err)
- return SMP_UNSPECIFIED;
-
- if (memcmp(smp->pcnf, cfm, 16))
- return SMP_CONFIRM_FAILED;
- } else {
- smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd),
- smp->prnd);
- SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
- }
-
-mackey_and_ltk:
- /* Generate MacKey and LTK */
- err = sc_mackey_and_ltk(smp, smp->mackey, smp->tk);
- if (err)
- return SMP_UNSPECIFIED;
-
- if (smp->method == JUST_WORKS || smp->method == REQ_OOB) {
- if (hcon->out) {
- sc_dhkey_check(smp);
- SMP_ALLOW_CMD(smp, SMP_CMD_DHKEY_CHECK);
- }
- return 0;
- }
-
- err = smp_g2(smp->tfm_cmac, pkax, pkbx, na, nb, &passkey);
- if (err)
- return SMP_UNSPECIFIED;
-
- err = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type,
- hcon->dst_type, passkey, 0);
- if (err)
- return SMP_UNSPECIFIED;
-
- set_bit(SMP_FLAG_WAIT_USER, &smp->flags);
-
- return 0;
+ return smp_random(smp);
}
static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level)
@@ -2025,7 +1112,8 @@
struct smp_ltk *key;
struct hci_conn *hcon = conn->hcon;
- key = hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role);
+ key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
+ hcon->role);
if (!key)
return false;
@@ -2044,21 +1132,20 @@
return true;
}
-bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
- enum smp_key_pref key_pref)
+bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level)
{
if (sec_level == BT_SECURITY_LOW)
return true;
- /* If we're encrypted with an STK but the caller prefers using
- * LTK claim insufficient security. This way we allow the
- * connection to be re-encrypted with an LTK, even if the LTK
- * provides the same level of security. Only exception is if we
- * don't have an LTK (e.g. because of key distribution bits).
+ /* If we're encrypted with an STK always claim insufficient
+ * security. This way we allow the connection to be re-encrypted
+ * with an LTK, even if the LTK provides the same level of
+ * security. Only exception is if we don't have an LTK (e.g.
+ * because of key distribution bits).
*/
- if (key_pref == SMP_USE_LTK &&
- test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
- hci_find_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, hcon->role))
+ if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) &&
+ hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type,
+ hcon->role))
return false;
if (hcon->sec_level >= sec_level)
@@ -2072,7 +1159,6 @@
struct smp_cmd_security_req *rp = (void *) skb->data;
struct smp_cmd_pairing cp;
struct hci_conn *hcon = conn->hcon;
- struct hci_dev *hdev = hcon->hdev;
struct smp_chan *smp;
u8 sec_level, auth;
@@ -2084,17 +1170,14 @@
if (hcon->role != HCI_ROLE_MASTER)
return SMP_CMD_NOTSUPP;
- auth = rp->auth_req & AUTH_REQ_MASK(hdev);
-
- if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && !(auth & SMP_AUTH_SC))
- return SMP_AUTH_REQUIREMENTS;
+ auth = rp->auth_req & AUTH_REQ_MASK;
if (hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT)
sec_level = BT_SECURITY_MEDIUM;
else
sec_level = authreq_to_seclevel(auth);
- if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK))
+ if (smp_sufficient_security(hcon, sec_level))
return 0;
if (sec_level > hcon->pending_sec_level)
@@ -2144,7 +1227,7 @@
if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags))
return 1;
- if (smp_sufficient_security(hcon, sec_level, SMP_USE_LTK))
+ if (smp_sufficient_security(hcon, sec_level))
return 1;
if (sec_level > hcon->pending_sec_level)
@@ -2170,9 +1253,6 @@
authreq = seclevel_to_authreq(sec_level);
- if (test_bit(HCI_SC_ENABLED, &hcon->hdev->dev_flags))
- authreq |= SMP_AUTH_SC;
-
/* Require MITM if IO Capability allows or the security level
* requires it.
*/
@@ -2249,6 +1329,7 @@
skb_pull(skb, sizeof(*rp));
+ hci_dev_lock(hdev);
authenticated = (hcon->sec_level == BT_SECURITY_HIGH);
ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, SMP_LTK,
authenticated, smp->tk, smp->enc_key_size,
@@ -2256,6 +1337,7 @@
smp->ltk = ltk;
if (!(smp->remote_key_dist & KEY_DIST_MASK))
smp_distribute_keys(smp);
+ hci_dev_unlock(hdev);
return 0;
}
@@ -2302,6 +1384,8 @@
skb_pull(skb, sizeof(*info));
+ hci_dev_lock(hcon->hdev);
+
/* Strictly speaking the Core Specification (4.1) allows sending
* an empty address which would force us to rely on just the IRK
* as "identity information". However, since such
@@ -2329,6 +1413,8 @@
if (!(smp->remote_key_dist & KEY_DIST_MASK))
smp_distribute_keys(smp);
+ hci_dev_unlock(hcon->hdev);
+
return 0;
}
@@ -2337,6 +1423,7 @@
struct smp_cmd_sign_info *rp = (void *) skb->data;
struct l2cap_chan *chan = conn->smp;
struct smp_chan *smp = chan->data;
+ struct hci_dev *hdev = conn->hcon->hdev;
struct smp_csrk *csrk;
BT_DBG("conn %p", conn);
@@ -2349,6 +1436,7 @@
skb_pull(skb, sizeof(*rp));
+ hci_dev_lock(hdev);
csrk = kzalloc(sizeof(*csrk), GFP_KERNEL);
if (csrk) {
csrk->master = 0x01;
@@ -2356,234 +1444,7 @@
}
smp->csrk = csrk;
smp_distribute_keys(smp);
-
- return 0;
-}
-
-static u8 sc_select_method(struct smp_chan *smp)
-{
- struct l2cap_conn *conn = smp->conn;
- struct hci_conn *hcon = conn->hcon;
- struct smp_cmd_pairing *local, *remote;
- u8 local_mitm, remote_mitm, local_io, remote_io, method;
-
- if (test_bit(SMP_FLAG_OOB, &smp->flags))
- return REQ_OOB;
-
- /* The preq/prsp contain the raw Pairing Request/Response PDUs
- * which are needed as inputs to some crypto functions. To get
- * the "struct smp_cmd_pairing" from them we need to skip the
- * first byte which contains the opcode.
- */
- if (hcon->out) {
- local = (void *) &smp->preq[1];
- remote = (void *) &smp->prsp[1];
- } else {
- local = (void *) &smp->prsp[1];
- remote = (void *) &smp->preq[1];
- }
-
- local_io = local->io_capability;
- remote_io = remote->io_capability;
-
- local_mitm = (local->auth_req & SMP_AUTH_MITM);
- remote_mitm = (remote->auth_req & SMP_AUTH_MITM);
-
- /* If either side wants MITM, look up the method from the table,
- * otherwise use JUST WORKS.
- */
- if (local_mitm || remote_mitm)
- method = get_auth_method(smp, local_io, remote_io);
- else
- method = JUST_WORKS;
-
- /* Don't confirm locally initiated pairing attempts */
- if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags))
- method = JUST_WORKS;
-
- return method;
-}
-
-static int smp_cmd_public_key(struct l2cap_conn *conn, struct sk_buff *skb)
-{
- struct smp_cmd_public_key *key = (void *) skb->data;
- struct hci_conn *hcon = conn->hcon;
- struct l2cap_chan *chan = conn->smp;
- struct smp_chan *smp = chan->data;
- struct hci_dev *hdev = hcon->hdev;
- struct smp_cmd_pairing_confirm cfm;
- int err;
-
- BT_DBG("conn %p", conn);
-
- if (skb->len < sizeof(*key))
- return SMP_INVALID_PARAMS;
-
- memcpy(smp->remote_pk, key, 64);
-
- /* Non-initiating device sends its public key after receiving
- * the key from the initiating device.
- */
- if (!hcon->out) {
- err = sc_send_public_key(smp);
- if (err)
- return err;
- }
-
- SMP_DBG("Remote Public Key X: %32phN", smp->remote_pk);
- SMP_DBG("Remote Public Key Y: %32phN", &smp->remote_pk[32]);
-
- if (!ecdh_shared_secret(smp->remote_pk, smp->local_sk, smp->dhkey))
- return SMP_UNSPECIFIED;
-
- SMP_DBG("DHKey %32phN", smp->dhkey);
-
- set_bit(SMP_FLAG_REMOTE_PK, &smp->flags);
-
- smp->method = sc_select_method(smp);
-
- BT_DBG("%s selected method 0x%02x", hdev->name, smp->method);
-
- /* JUST_WORKS and JUST_CFM result in an unauthenticated key */
- if (smp->method == JUST_WORKS || smp->method == JUST_CFM)
- hcon->pending_sec_level = BT_SECURITY_MEDIUM;
- else
- hcon->pending_sec_level = BT_SECURITY_FIPS;
-
- if (!memcmp(debug_pk, smp->remote_pk, 64))
- set_bit(SMP_FLAG_DEBUG_KEY, &smp->flags);
-
- if (smp->method == DSP_PASSKEY) {
- get_random_bytes(&hcon->passkey_notify,
- sizeof(hcon->passkey_notify));
- hcon->passkey_notify %= 1000000;
- hcon->passkey_entered = 0;
- smp->passkey_round = 0;
- if (mgmt_user_passkey_notify(hdev, &hcon->dst, hcon->type,
- hcon->dst_type,
- hcon->passkey_notify,
- hcon->passkey_entered))
- return SMP_UNSPECIFIED;
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
- return sc_passkey_round(smp, SMP_CMD_PUBLIC_KEY);
- }
-
- if (smp->method == REQ_OOB) {
- err = smp_f4(smp->tfm_cmac, smp->remote_pk, smp->remote_pk,
- smp->rr, 0, cfm.confirm_val);
- if (err)
- return SMP_UNSPECIFIED;
-
- if (memcmp(cfm.confirm_val, smp->pcnf, 16))
- return SMP_CONFIRM_FAILED;
-
- if (hcon->out)
- smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM,
- sizeof(smp->prnd), smp->prnd);
-
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
-
- return 0;
- }
-
- if (hcon->out)
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
-
- if (smp->method == REQ_PASSKEY) {
- if (mgmt_user_passkey_request(hdev, &hcon->dst, hcon->type,
- hcon->dst_type))
- return SMP_UNSPECIFIED;
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_CONFIRM);
- set_bit(SMP_FLAG_WAIT_USER, &smp->flags);
- return 0;
- }
-
- /* The Initiating device waits for the non-initiating device to
- * send the confirm value.
- */
- if (conn->hcon->out)
- return 0;
-
- err = smp_f4(smp->tfm_cmac, smp->local_pk, smp->remote_pk, smp->prnd,
- 0, cfm.confirm_val);
- if (err)
- return SMP_UNSPECIFIED;
-
- smp_send_cmd(conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cfm), &cfm);
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RANDOM);
-
- return 0;
-}
-
-static int smp_cmd_dhkey_check(struct l2cap_conn *conn, struct sk_buff *skb)
-{
- struct smp_cmd_dhkey_check *check = (void *) skb->data;
- struct l2cap_chan *chan = conn->smp;
- struct hci_conn *hcon = conn->hcon;
- struct smp_chan *smp = chan->data;
- u8 a[7], b[7], *local_addr, *remote_addr;
- u8 io_cap[3], r[16], e[16];
- int err;
-
- BT_DBG("conn %p", conn);
-
- if (skb->len < sizeof(*check))
- return SMP_INVALID_PARAMS;
-
- memcpy(a, &hcon->init_addr, 6);
- memcpy(b, &hcon->resp_addr, 6);
- a[6] = hcon->init_addr_type;
- b[6] = hcon->resp_addr_type;
-
- if (hcon->out) {
- local_addr = a;
- remote_addr = b;
- memcpy(io_cap, &smp->prsp[1], 3);
- } else {
- local_addr = b;
- remote_addr = a;
- memcpy(io_cap, &smp->preq[1], 3);
- }
-
- memset(r, 0, sizeof(r));
-
- if (smp->method == REQ_PASSKEY || smp->method == DSP_PASSKEY)
- put_unaligned_le32(hcon->passkey_notify, r);
-
- err = smp_f6(smp->tfm_cmac, smp->mackey, smp->rrnd, smp->prnd, r,
- io_cap, remote_addr, local_addr, e);
- if (err)
- return SMP_UNSPECIFIED;
-
- if (memcmp(check->e, e, 16))
- return SMP_DHKEY_CHECK_FAILED;
-
- if (!hcon->out) {
- if (test_bit(SMP_FLAG_WAIT_USER, &smp->flags)) {
- set_bit(SMP_FLAG_DHKEY_PENDING, &smp->flags);
- return 0;
- }
-
- /* Slave sends DHKey check as response to master */
- sc_dhkey_check(smp);
- }
-
- sc_add_ltk(smp);
-
- if (hcon->out) {
- hci_le_start_enc(hcon, 0, 0, smp->tk);
- hcon->enc_key_size = smp->enc_key_size;
- }
-
- return 0;
-}
-
-static int smp_cmd_keypress_notify(struct l2cap_conn *conn,
- struct sk_buff *skb)
-{
- struct smp_cmd_keypress_notify *kp = (void *) skb->data;
-
- BT_DBG("value 0x%02x", kp->value);
+ hci_dev_unlock(hdev);
return 0;
}
@@ -2596,6 +1457,11 @@
__u8 code, reason;
int err = 0;
+ if (hcon->type != LE_LINK) {
+ kfree_skb(skb);
+ return 0;
+ }
+
if (skb->len < 1)
return -EILSEQ;
@@ -2667,18 +1533,6 @@
reason = smp_cmd_sign_info(conn, skb);
break;
- case SMP_CMD_PUBLIC_KEY:
- reason = smp_cmd_public_key(conn, skb);
- break;
-
- case SMP_CMD_DHKEY_CHECK:
- reason = smp_cmd_dhkey_check(conn, skb);
- break;
-
- case SMP_CMD_KEYPRESS_NOTIFY:
- reason = smp_cmd_keypress_notify(conn, skb);
- break;
-
default:
BT_DBG("Unknown command code 0x%2.2x", code);
reason = SMP_CMD_NOTSUPP;
@@ -2714,74 +1568,6 @@
l2cap_chan_put(chan);
}
-static void bredr_pairing(struct l2cap_chan *chan)
-{
- struct l2cap_conn *conn = chan->conn;
- struct hci_conn *hcon = conn->hcon;
- struct hci_dev *hdev = hcon->hdev;
- struct smp_cmd_pairing req;
- struct smp_chan *smp;
-
- BT_DBG("chan %p", chan);
-
- /* Only new pairings are interesting */
- if (!test_bit(HCI_CONN_NEW_LINK_KEY, &hcon->flags))
- return;
-
- /* Don't bother if we're not encrypted */
- if (!test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
- return;
-
- /* Only master may initiate SMP over BR/EDR */
- if (hcon->role != HCI_ROLE_MASTER)
- return;
-
- /* Secure Connections support must be enabled */
- if (!test_bit(HCI_SC_ENABLED, &hdev->dev_flags))
- return;
-
- /* BR/EDR must use Secure Connections for SMP */
- if (!test_bit(HCI_CONN_AES_CCM, &hcon->flags) &&
- !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
- return;
-
- /* If our LE support is not enabled don't do anything */
- if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
- return;
-
- /* Don't bother if remote LE support is not enabled */
- if (!lmp_host_le_capable(hcon))
- return;
-
- /* Remote must support SMP fixed chan for BR/EDR */
- if (!(conn->remote_fixed_chan & L2CAP_FC_SMP_BREDR))
- return;
-
- /* Don't bother if SMP is already ongoing */
- if (chan->data)
- return;
-
- smp = smp_chan_create(conn);
- if (!smp) {
- BT_ERR("%s unable to create SMP context for BR/EDR",
- hdev->name);
- return;
- }
-
- set_bit(SMP_FLAG_SC, &smp->flags);
-
- BT_DBG("%s starting SMP over BR/EDR", hdev->name);
-
- /* Prepare and send the BR/EDR SMP Pairing Request */
- build_bredr_pairing_cmd(smp, &req, NULL);
-
- smp->preq[0] = SMP_CMD_PAIRING_REQ;
- memcpy(&smp->preq[1], &req, sizeof(req));
-
- smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(req), &req);
- SMP_ALLOW_CMD(smp, SMP_CMD_PAIRING_RSP);
-}
-
static void smp_resume_cb(struct l2cap_chan *chan)
{
struct smp_chan *smp = chan->data;
@@ -2790,11 +1576,6 @@
BT_DBG("chan %p", chan);
- if (hcon->type == ACL_LINK) {
- bredr_pairing(chan);
- return;
- }
-
if (!smp)
return;
@@ -2809,15 +1590,11 @@
static void smp_ready_cb(struct l2cap_chan *chan)
{
struct l2cap_conn *conn = chan->conn;
- struct hci_conn *hcon = conn->hcon;
BT_DBG("chan %p", chan);
conn->smp = chan;
l2cap_chan_hold(chan);
-
- if (hcon->type == ACL_LINK && test_bit(HCI_CONN_ENCRYPT, &hcon->flags))
- bredr_pairing(chan);
}
static int smp_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
@@ -2891,13 +1668,6 @@
chan->omtu = pchan->omtu;
chan->mode = pchan->mode;
- /* Other L2CAP channels may request SMP routines in order to
- * change the security level. This means that the SMP channel
- * lock must be considered in its own category to avoid lockdep
- * warnings.
- */
- atomic_set(&chan->nesting, L2CAP_NESTING_SMP);
-
BT_DBG("created chan %p", chan);
return chan;
@@ -2922,56 +1692,53 @@
.memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec,
};
-static struct l2cap_chan *smp_add_cid(struct hci_dev *hdev, u16 cid)
+int smp_register(struct hci_dev *hdev)
{
struct l2cap_chan *chan;
struct crypto_blkcipher *tfm_aes;
- if (cid == L2CAP_CID_SMP_BREDR) {
- tfm_aes = NULL;
- goto create_chan;
- }
+ BT_DBG("%s", hdev->name);
- tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, 0);
+ tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
if (IS_ERR(tfm_aes)) {
+ int err = PTR_ERR(tfm_aes);
BT_ERR("Unable to create crypto context");
- return ERR_CAST(tfm_aes);
+ return err;
}
-create_chan:
chan = l2cap_chan_create();
if (!chan) {
crypto_free_blkcipher(tfm_aes);
- return ERR_PTR(-ENOMEM);
+ return -ENOMEM;
}
chan->data = tfm_aes;
- l2cap_add_scid(chan, cid);
+ l2cap_add_scid(chan, L2CAP_CID_SMP);
l2cap_chan_set_defaults(chan);
bacpy(&chan->src, &hdev->bdaddr);
- if (cid == L2CAP_CID_SMP)
- chan->src_type = BDADDR_LE_PUBLIC;
- else
- chan->src_type = BDADDR_BREDR;
+ chan->src_type = BDADDR_LE_PUBLIC;
chan->state = BT_LISTEN;
chan->mode = L2CAP_MODE_BASIC;
chan->imtu = L2CAP_DEFAULT_MTU;
chan->ops = &smp_root_chan_ops;
- /* Set correct nesting level for a parent/listening channel */
- atomic_set(&chan->nesting, L2CAP_NESTING_PARENT);
+ hdev->smp_data = chan;
- return chan;
+ return 0;
}
-static void smp_del_chan(struct l2cap_chan *chan)
+void smp_unregister(struct hci_dev *hdev)
{
- struct crypto_blkcipher *tfm_aes;
+ struct l2cap_chan *chan = hdev->smp_data;
+ struct crypto_blkcipher *tfm_aes;
- BT_DBG("chan %p", chan);
+ if (!chan)
+ return;
+
+ BT_DBG("%s chan %p", hdev->name, chan);
tfm_aes = chan->data;
if (tfm_aes) {
@@ -2979,52 +1746,6 @@
crypto_free_blkcipher(tfm_aes);
}
+ hdev->smp_data = NULL;
l2cap_chan_put(chan);
}
-
-int smp_register(struct hci_dev *hdev)
-{
- struct l2cap_chan *chan;
-
- BT_DBG("%s", hdev->name);
-
- chan = smp_add_cid(hdev, L2CAP_CID_SMP);
- if (IS_ERR(chan))
- return PTR_ERR(chan);
-
- hdev->smp_data = chan;
-
- if (!lmp_sc_capable(hdev) &&
- !test_bit(HCI_FORCE_LESC, &hdev->dbg_flags))
- return 0;
-
- chan = smp_add_cid(hdev, L2CAP_CID_SMP_BREDR);
- if (IS_ERR(chan)) {
- int err = PTR_ERR(chan);
- chan = hdev->smp_data;
- hdev->smp_data = NULL;
- smp_del_chan(chan);
- return err;
- }
-
- hdev->smp_bredr_data = chan;
-
- return 0;
-}
-
-void smp_unregister(struct hci_dev *hdev)
-{
- struct l2cap_chan *chan;
-
- if (hdev->smp_bredr_data) {
- chan = hdev->smp_bredr_data;
- hdev->smp_bredr_data = NULL;
- smp_del_chan(chan);
- }
-
- if (hdev->smp_data) {
- chan = hdev->smp_data;
- hdev->smp_data = NULL;
- smp_del_chan(chan);
- }
-}
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h
index 3296bf4..86a683a 100644
--- a/net/bluetooth/smp.h
+++ b/net/bluetooth/smp.h
@@ -50,13 +50,10 @@
#define SMP_DIST_ENC_KEY 0x01
#define SMP_DIST_ID_KEY 0x02
#define SMP_DIST_SIGN 0x04
-#define SMP_DIST_LINK_KEY 0x08
#define SMP_AUTH_NONE 0x00
#define SMP_AUTH_BONDING 0x01
#define SMP_AUTH_MITM 0x04
-#define SMP_AUTH_SC 0x08
-#define SMP_AUTH_KEYPRESS 0x10
#define SMP_CMD_PAIRING_CONFIRM 0x03
struct smp_cmd_pairing_confirm {
@@ -105,23 +102,7 @@
__u8 auth_req;
} __packed;
-#define SMP_CMD_PUBLIC_KEY 0x0c
-struct smp_cmd_public_key {
- __u8 x[32];
- __u8 y[32];
-} __packed;
-
-#define SMP_CMD_DHKEY_CHECK 0x0d
-struct smp_cmd_dhkey_check {
- __u8 e[16];
-} __packed;
-
-#define SMP_CMD_KEYPRESS_NOTIFY 0x0e
-struct smp_cmd_keypress_notify {
- __u8 value;
-} __packed;
-
-#define SMP_CMD_MAX 0x0e
+#define SMP_CMD_MAX 0x0b
#define SMP_PASSKEY_ENTRY_FAILED 0x01
#define SMP_OOB_NOT_AVAIL 0x02
@@ -133,10 +114,6 @@
#define SMP_UNSPECIFIED 0x08
#define SMP_REPEATED_ATTEMPTS 0x09
#define SMP_INVALID_PARAMS 0x0a
-#define SMP_DHKEY_CHECK_FAILED 0x0b
-#define SMP_NUMERIC_COMP_FAILED 0x0c
-#define SMP_BREDR_PAIRING_IN_PROGRESS 0x0d
-#define SMP_CROSS_TRANSP_NOT_ALLOWED 0x0e
#define SMP_MIN_ENC_KEY_SIZE 7
#define SMP_MAX_ENC_KEY_SIZE 16
@@ -146,48 +123,23 @@
SMP_STK,
SMP_LTK,
SMP_LTK_SLAVE,
- SMP_LTK_P256,
- SMP_LTK_P256_DEBUG,
};
-static inline bool smp_ltk_is_sc(struct smp_ltk *key)
-{
- switch (key->type) {
- case SMP_LTK_P256:
- case SMP_LTK_P256_DEBUG:
- return true;
- }
-
- return false;
-}
-
static inline u8 smp_ltk_sec_level(struct smp_ltk *key)
{
- if (key->authenticated) {
- if (smp_ltk_is_sc(key))
- return BT_SECURITY_FIPS;
- else
- return BT_SECURITY_HIGH;
- }
+ if (key->authenticated)
+ return BT_SECURITY_HIGH;
return BT_SECURITY_MEDIUM;
}
-/* Key preferences for smp_sufficient security */
-enum smp_key_pref {
- SMP_ALLOW_STK,
- SMP_USE_LTK,
-};
-
/* SMP Commands */
-bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level,
- enum smp_key_pref key_pref);
+bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level);
int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
-bool smp_irk_matches(struct hci_dev *hdev, const u8 irk[16],
- const bdaddr_t *bdaddr);
-int smp_generate_rpa(struct hci_dev *hdev, const u8 irk[16], bdaddr_t *rpa);
+bool smp_irk_matches(struct hci_dev *hdev, u8 irk[16], bdaddr_t *bdaddr);
+int smp_generate_rpa(struct hci_dev *hdev, u8 irk[16], bdaddr_t *rpa);
int smp_register(struct hci_dev *hdev);
void smp_unregister(struct hci_dev *hdev);
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c
index dc34d84..69cbc62 100644
--- a/net/ieee802154/6lowpan_rtnl.c
+++ b/net/ieee802154/6lowpan_rtnl.c
@@ -49,8 +49,8 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
-#include <linux/ieee802154.h>
#include <net/af_ieee802154.h>
+#include <net/ieee802154.h>
#include <net/ieee802154_netdev.h>
#include <net/6lowpan.h>
#include <net/ipv6.h>
@@ -58,13 +58,12 @@
#include "reassembly.h"
static LIST_HEAD(lowpan_devices);
-static int lowpan_open_count;
/* private device info */
struct lowpan_dev_info {
struct net_device *real_dev; /* real WPAN device ptr */
struct mutex dev_list_mtx; /* mutex for list ops */
- u16 fragment_tag;
+ __be16 fragment_tag;
};
struct lowpan_dev_record {
@@ -141,33 +140,24 @@
struct sk_buff *skb_cp;
int stat = NET_RX_SUCCESS;
- skb->protocol = htons(ETH_P_IPV6);
- skb->pkt_type = PACKET_HOST;
-
rcu_read_lock();
list_for_each_entry_rcu(entry, &lowpan_devices, list)
if (lowpan_dev_info(entry->ldev)->real_dev == skb->dev) {
skb_cp = skb_copy(skb, GFP_ATOMIC);
if (!skb_cp) {
- kfree_skb(skb);
- rcu_read_unlock();
- return NET_RX_DROP;
+ stat = -ENOMEM;
+ break;
}
skb_cp->dev = entry->ldev;
stat = netif_rx(skb_cp);
- if (stat == NET_RX_DROP)
- break;
}
rcu_read_unlock();
- consume_skb(skb);
-
return stat;
}
-static int
-iphc_decompress(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
+static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr)
{
u8 iphc0, iphc1;
struct ieee802154_addr_sa sa, da;
@@ -176,13 +166,13 @@
raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len);
/* at least two bytes will be used for the encoding */
if (skb->len < 2)
- return -EINVAL;
+ goto drop;
if (lowpan_fetch_skb_u8(skb, &iphc0))
- return -EINVAL;
+ goto drop;
if (lowpan_fetch_skb_u8(skb, &iphc1))
- return -EINVAL;
+ goto drop;
ieee802154_addr_to_sa(&sa, &hdr->source);
ieee802154_addr_to_sa(&da, &hdr->dest);
@@ -197,9 +187,27 @@
else
dap = &da.hwaddr;
- return lowpan_header_decompress(skb, skb->dev, sap, sa.addr_type,
- IEEE802154_ADDR_LEN, dap, da.addr_type,
- IEEE802154_ADDR_LEN, iphc0, iphc1);
+ return lowpan_process_data(skb, skb->dev, sap, sa.addr_type,
+ IEEE802154_ADDR_LEN, dap, da.addr_type,
+ IEEE802154_ADDR_LEN, iphc0, iphc1,
+ lowpan_give_skb_to_devices);
+
+drop:
+ kfree_skb(skb);
+ return -EINVAL;
+}
+
+static int lowpan_set_address(struct net_device *dev, void *p)
+{
+ struct sockaddr *sa = p;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ /* TODO: validate addr */
+ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len);
+
+ return 0;
}
static struct sk_buff*
@@ -225,7 +233,7 @@
&master_hdr->source, size);
if (rc < 0) {
kfree_skb(frag);
- return ERR_PTR(rc);
+ return ERR_PTR(-rc);
}
} else {
frag = ERR_PTR(-ENOMEM);
@@ -267,8 +275,7 @@
dgram_size = lowpan_uncompress_size(skb, &dgram_offset) -
skb->mac_len;
- frag_tag = htons(lowpan_dev_info(dev)->fragment_tag);
- lowpan_dev_info(dev)->fragment_tag++;
+ frag_tag = lowpan_dev_info(dev)->fragment_tag++;
frag_hdr[0] = LOWPAN_DISPATCH_FRAG1 | ((dgram_size >> 8) & 0x07);
frag_hdr[1] = dgram_size & 0xff;
@@ -287,7 +294,7 @@
frag_len + skb_network_header_len(skb));
if (rc) {
pr_debug("%s unable to send FRAG1 packet (tag: %d)",
- __func__, ntohs(frag_tag));
+ __func__, frag_tag);
goto err;
}
@@ -308,7 +315,7 @@
frag_len);
if (rc) {
pr_debug("%s unable to send a FRAGN packet. (tag: %d, offset: %d)\n",
- __func__, ntohs(frag_tag), skb_offset);
+ __func__, frag_tag, skb_offset);
goto err;
}
} while (skb_unprocessed > frag_cap);
@@ -403,6 +410,13 @@
}
}
+static struct wpan_phy *lowpan_get_phy(const struct net_device *dev)
+{
+ struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
+
+ return ieee802154_mlme_ops(real_dev)->get_phy(real_dev);
+}
+
static __le16 lowpan_get_pan_id(const struct net_device *dev)
{
struct net_device *real_dev = lowpan_dev_info(dev)->real_dev;
@@ -441,6 +455,7 @@
&lowpan_netdev_xmit_lock_key);
}
+
static int lowpan_dev_init(struct net_device *dev)
{
netdev_for_each_tx_queue(dev, lowpan_set_lockdep_class_one, NULL);
@@ -453,10 +468,12 @@
static const struct net_device_ops lowpan_netdev_ops = {
.ndo_init = lowpan_dev_init,
.ndo_start_xmit = lowpan_xmit,
+ .ndo_set_mac_address = lowpan_set_address,
};
static struct ieee802154_mlme_ops lowpan_mlme = {
.get_pan_id = lowpan_get_pan_id,
+ .get_phy = lowpan_get_phy,
.get_short_addr = lowpan_get_short_addr,
.get_dsn = lowpan_get_dsn,
};
@@ -502,9 +519,6 @@
if (!netif_running(dev))
goto drop_skb;
- if (skb->pkt_type == PACKET_OTHERHOST)
- goto drop_skb;
-
if (dev->type != ARPHRD_IEEE802154)
goto drop_skb;
@@ -513,67 +527,55 @@
/* check that it's our buffer */
if (skb->data[0] == LOWPAN_DISPATCH_IPV6) {
+ skb->protocol = htons(ETH_P_IPV6);
+ skb->pkt_type = PACKET_HOST;
+
/* Pull off the 1-byte of 6lowpan header. */
skb_pull(skb, 1);
- return lowpan_give_skb_to_devices(skb, NULL);
+
+ ret = lowpan_give_skb_to_devices(skb, NULL);
+ if (ret == NET_RX_DROP)
+ goto drop;
} else {
switch (skb->data[0] & 0xe0) {
case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */
- ret = iphc_decompress(skb, &hdr);
- if (ret < 0)
- goto drop_skb;
-
- return lowpan_give_skb_to_devices(skb, NULL);
+ ret = process_data(skb, &hdr);
+ if (ret == NET_RX_DROP)
+ goto drop;
+ break;
case LOWPAN_DISPATCH_FRAG1: /* first fragment header */
ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1);
if (ret == 1) {
- ret = iphc_decompress(skb, &hdr);
- if (ret < 0)
- goto drop_skb;
-
- return lowpan_give_skb_to_devices(skb, NULL);
- } else if (ret == -1) {
- return NET_RX_DROP;
- } else {
- return NET_RX_SUCCESS;
+ ret = process_data(skb, &hdr);
+ if (ret == NET_RX_DROP)
+ goto drop;
}
+ break;
case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */
ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN);
if (ret == 1) {
- ret = iphc_decompress(skb, &hdr);
- if (ret < 0)
- goto drop_skb;
-
- return lowpan_give_skb_to_devices(skb, NULL);
- } else if (ret == -1) {
- return NET_RX_DROP;
- } else {
- return NET_RX_SUCCESS;
+ ret = process_data(skb, &hdr);
+ if (ret == NET_RX_DROP)
+ goto drop;
}
+ break;
default:
break;
}
}
+ return NET_RX_SUCCESS;
drop_skb:
kfree_skb(skb);
drop:
return NET_RX_DROP;
}
-static struct packet_type lowpan_packet_type = {
- .type = htons(ETH_P_IEEE802154),
- .func = lowpan_rcv,
-};
-
static int lowpan_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[])
{
struct net_device *real_dev;
struct lowpan_dev_record *entry;
- int ret;
-
- ASSERT_RTNL();
pr_debug("adding new link\n");
@@ -600,7 +602,7 @@
entry->ldev = dev;
- /* Set the lowpan hardware address to the wpan hardware address. */
+ /* Set the lowpan harware address to the wpan hardware address. */
memcpy(dev->dev_addr, real_dev->dev_addr, IEEE802154_ADDR_LEN);
mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
@@ -608,14 +610,9 @@
list_add_tail(&entry->list, &lowpan_devices);
mutex_unlock(&lowpan_dev_info(dev)->dev_list_mtx);
- ret = register_netdevice(dev);
- if (ret >= 0) {
- if (!lowpan_open_count)
- dev_add_pack(&lowpan_packet_type);
- lowpan_open_count++;
- }
+ register_netdevice(dev);
- return ret;
+ return 0;
}
static void lowpan_dellink(struct net_device *dev, struct list_head *head)
@@ -626,10 +623,6 @@
ASSERT_RTNL();
- lowpan_open_count--;
- if (!lowpan_open_count)
- dev_remove_pack(&lowpan_packet_type);
-
mutex_lock(&lowpan_dev_info(dev)->dev_list_mtx);
list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) {
if (entry->ldev == dev) {
@@ -692,6 +685,11 @@
.notifier_call = lowpan_device_event,
};
+static struct packet_type lowpan_packet_type = {
+ .type = htons(ETH_P_IEEE802154),
+ .func = lowpan_rcv,
+};
+
static int __init lowpan_init_module(void)
{
int err = 0;
@@ -704,6 +702,8 @@
if (err < 0)
goto out_frag;
+ dev_add_pack(&lowpan_packet_type);
+
err = register_netdevice_notifier(&lowpan_dev_notifier);
if (err < 0)
goto out_pack;
@@ -711,6 +711,7 @@
return 0;
out_pack:
+ dev_remove_pack(&lowpan_packet_type);
lowpan_netlink_fini();
out_frag:
lowpan_net_frag_exit();
@@ -722,6 +723,8 @@
{
lowpan_netlink_fini();
+ dev_remove_pack(&lowpan_packet_type);
+
lowpan_net_frag_exit();
unregister_netdevice_notifier(&lowpan_dev_notifier);
diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig
index c509e93..24fe2a5 100644
--- a/net/ieee802154/Kconfig
+++ b/net/ieee802154/Kconfig
@@ -1,5 +1,5 @@
config IEEE802154
- depends on !KERNEL_3_19
+ depends on !BACKPORT_KERNEL_3_1
tristate "IEEE Std 802.15.4 Low-Rate Wireless Personal Area Networks support"
depends on m
---help---
@@ -13,7 +13,7 @@
compile it as modules.
config IEEE802154_6LOWPAN
- depends on !KERNEL_3_5
+ depends on !BACKPORT_KERNEL_3_5
tristate "6lowpan support over IEEE 802.15.4"
depends on m
depends on IEEE802154 && 6LOWPAN
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile
index 9e6d3d6..57fdfef 100644
--- a/net/ieee802154/Makefile
+++ b/net/ieee802154/Makefile
@@ -2,8 +2,8 @@
obj-$(CPTCFG_IEEE802154_6LOWPAN) += ieee802154_6lowpan.o
ieee802154_6lowpan-y := 6lowpan_rtnl.o reassembly.o
-ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o core.o \
- header_ops.o sysfs.o nl802154.o
+ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o \
+ header_ops.o
af_802154-y := af_ieee802154.o raw.o dgram.o
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/ieee802154/af802154.h b/net/ieee802154/af802154.h
index 343b63e..8330a09 100644
--- a/net/ieee802154/af802154.h
+++ b/net/ieee802154/af802154.h
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c
index d0a1282..29e0de6 100644
--- a/net/ieee802154/af_ieee802154.c
+++ b/net/ieee802154/af_ieee802154.c
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Maxim Gorbachyov <maxim.gorbachev@siemens.com>
@@ -99,7 +103,6 @@
}
return 0;
}
-
static int ieee802154_sock_sendmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t len)
{
@@ -232,6 +235,7 @@
#endif
};
+
/* Create a socket. Initialise the socket, blank the addresses
* set the state.
*/
@@ -320,6 +324,7 @@
return NET_RX_DROP;
}
+
static struct packet_type ieee802154_packet_type = {
.type = htons(ETH_P_IEEE802154),
.func = ieee802154_rcv,
@@ -353,7 +358,6 @@
out:
return rc;
}
-
static void __exit af_ieee802154_remove(void)
{
dev_remove_pack(&ieee802154_packet_type);
diff --git a/net/ieee802154/core.c b/net/ieee802154/core.c
deleted file mode 100644
index 18bc7e7..0000000
--- a/net/ieee802154/core.c
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * Copyright (C) 2007, 2008, 2009 Siemens AG
- *
- * 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.
- *
- */
-
-#include <linux/slab.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/device.h>
-
-#include <net/cfg802154.h>
-#include <net/rtnetlink.h>
-
-#include "ieee802154.h"
-#include "nl802154.h"
-#include "sysfs.h"
-#include "core.h"
-
-/* RCU-protected (and RTNL for writers) */
-LIST_HEAD(cfg802154_rdev_list);
-int cfg802154_rdev_list_generation;
-
-static int wpan_phy_match(struct device *dev, const void *data)
-{
- return !strcmp(dev_name(dev), (const char *)data);
-}
-
-struct wpan_phy *wpan_phy_find(const char *str)
-{
- struct device *dev;
-
- if (WARN_ON(!str))
- return NULL;
-
- dev = class_find_device(&wpan_phy_class, NULL, str, wpan_phy_match);
- if (!dev)
- return NULL;
-
- return container_of(dev, struct wpan_phy, dev);
-}
-EXPORT_SYMBOL(wpan_phy_find);
-
-struct wpan_phy_iter_data {
- int (*fn)(struct wpan_phy *phy, void *data);
- void *data;
-};
-
-static int wpan_phy_iter(struct device *dev, void *_data)
-{
- struct wpan_phy_iter_data *wpid = _data;
- struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
-
- return wpid->fn(phy, wpid->data);
-}
-
-int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data),
- void *data)
-{
- struct wpan_phy_iter_data wpid = {
- .fn = fn,
- .data = data,
- };
-
- return class_for_each_device(&wpan_phy_class, NULL,
- &wpid, wpan_phy_iter);
-}
-EXPORT_SYMBOL(wpan_phy_for_each);
-
-struct cfg802154_registered_device *
-cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx)
-{
- struct cfg802154_registered_device *result = NULL, *rdev;
-
- ASSERT_RTNL();
-
- list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
- if (rdev->wpan_phy_idx == wpan_phy_idx) {
- result = rdev;
- break;
- }
- }
-
- return result;
-}
-
-struct wpan_phy *
-wpan_phy_new(const struct cfg802154_ops *ops, size_t priv_size)
-{
- static atomic_t wpan_phy_counter = ATOMIC_INIT(0);
- struct cfg802154_registered_device *rdev;
- size_t alloc_size;
-
- alloc_size = sizeof(*rdev) + priv_size;
- rdev = kzalloc(alloc_size, GFP_KERNEL);
- if (!rdev)
- return NULL;
-
- rdev->ops = ops;
-
- rdev->wpan_phy_idx = atomic_inc_return(&wpan_phy_counter);
-
- if (unlikely(rdev->wpan_phy_idx < 0)) {
- /* ugh, wrapped! */
- atomic_dec(&wpan_phy_counter);
- kfree(rdev);
- return NULL;
- }
-
- /* atomic_inc_return makes it start at 1, make it start at 0 */
- rdev->wpan_phy_idx--;
-
- mutex_init(&rdev->wpan_phy.pib_lock);
-
- INIT_LIST_HEAD(&rdev->wpan_dev_list);
- device_initialize(&rdev->wpan_phy.dev);
- dev_set_name(&rdev->wpan_phy.dev, "wpan-phy%d", rdev->wpan_phy_idx);
-
- rdev->wpan_phy.dev.class = &wpan_phy_class;
- rdev->wpan_phy.dev.platform_data = rdev;
-
- init_waitqueue_head(&rdev->dev_wait);
-
- return &rdev->wpan_phy;
-}
-EXPORT_SYMBOL(wpan_phy_new);
-
-int wpan_phy_register(struct wpan_phy *phy)
-{
- struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(phy);
- int ret;
-
- rtnl_lock();
- ret = device_add(&phy->dev);
- if (ret) {
- rtnl_unlock();
- return ret;
- }
-
- list_add_rcu(&rdev->list, &cfg802154_rdev_list);
- cfg802154_rdev_list_generation++;
-
- /* TODO phy registered lock */
- rtnl_unlock();
-
- /* TODO nl802154 phy notify */
-
- return 0;
-}
-EXPORT_SYMBOL(wpan_phy_register);
-
-void wpan_phy_unregister(struct wpan_phy *phy)
-{
- struct cfg802154_registered_device *rdev = wpan_phy_to_rdev(phy);
-
- wait_event(rdev->dev_wait, ({
- int __count;
- rtnl_lock();
- __count = rdev->opencount;
- rtnl_unlock();
- __count == 0; }));
-
- rtnl_lock();
- /* TODO nl802154 phy notify */
- /* TODO phy registered lock */
-
- WARN_ON(!list_empty(&rdev->wpan_dev_list));
-
- /* First remove the hardware from everywhere, this makes
- * it impossible to find from userspace.
- */
- list_del_rcu(&rdev->list);
- synchronize_rcu();
-
- cfg802154_rdev_list_generation++;
-
- device_del(&phy->dev);
-
- rtnl_unlock();
-}
-EXPORT_SYMBOL(wpan_phy_unregister);
-
-void wpan_phy_free(struct wpan_phy *phy)
-{
- put_device(&phy->dev);
-}
-EXPORT_SYMBOL(wpan_phy_free);
-
-void cfg802154_dev_free(struct cfg802154_registered_device *rdev)
-{
- kfree(rdev);
-}
-
-static void
-cfg802154_update_iface_num(struct cfg802154_registered_device *rdev,
- int iftype, int num)
-{
- ASSERT_RTNL();
-
- rdev->num_running_ifaces += num;
-}
-
-static int cfg802154_netdev_notifier_call(struct notifier_block *nb,
- unsigned long state, void *ptr)
-{
- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
- struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
- struct cfg802154_registered_device *rdev;
-
- if (!wpan_dev)
- return NOTIFY_DONE;
-
- rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
-
- /* TODO WARN_ON unspec type */
-
- switch (state) {
- /* TODO NETDEV_DEVTYPE */
- case NETDEV_REGISTER:
- wpan_dev->identifier = ++rdev->wpan_dev_id;
- list_add_rcu(&wpan_dev->list, &rdev->wpan_dev_list);
- rdev->devlist_generation++;
-
- wpan_dev->netdev = dev;
- break;
- case NETDEV_DOWN:
- cfg802154_update_iface_num(rdev, wpan_dev->iftype, -1);
-
- rdev->opencount--;
- wake_up(&rdev->dev_wait);
- break;
- case NETDEV_UP:
- cfg802154_update_iface_num(rdev, wpan_dev->iftype, 1);
-
- rdev->opencount++;
- break;
- case NETDEV_UNREGISTER:
- /* It is possible to get NETDEV_UNREGISTER
- * multiple times. To detect that, check
- * that the interface is still on the list
- * of registered interfaces, and only then
- * remove and clean it up.
- */
- if (!list_empty(&wpan_dev->list)) {
- list_del_rcu(&wpan_dev->list);
- rdev->devlist_generation++;
- }
- /* synchronize (so that we won't find this netdev
- * from other code any more) and then clear the list
- * head so that the above code can safely check for
- * !list_empty() to avoid double-cleanup.
- */
- synchronize_rcu();
- INIT_LIST_HEAD(&wpan_dev->list);
- break;
- default:
- return NOTIFY_DONE;
- }
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block cfg802154_netdev_notifier = {
- .notifier_call = cfg802154_netdev_notifier_call,
-};
-
-static int __init wpan_phy_class_init(void)
-{
- int rc;
-
- rc = wpan_phy_sysfs_init();
- if (rc)
- goto err;
-
- rc = register_netdevice_notifier(&cfg802154_netdev_notifier);
- if (rc)
- goto err_nl;
-
- rc = ieee802154_nl_init();
- if (rc)
- goto err_notifier;
-
- rc = nl802154_init();
- if (rc)
- goto err_ieee802154_nl;
-
- return 0;
-
-err_ieee802154_nl:
- ieee802154_nl_exit();
-
-err_notifier:
- unregister_netdevice_notifier(&cfg802154_netdev_notifier);
-err_nl:
- wpan_phy_sysfs_exit();
-err:
- return rc;
-}
-subsys_initcall(wpan_phy_class_init);
-
-static void __exit wpan_phy_class_exit(void)
-{
- nl802154_exit();
- ieee802154_nl_exit();
- unregister_netdevice_notifier(&cfg802154_netdev_notifier);
- wpan_phy_sysfs_exit();
-}
-module_exit(wpan_phy_class_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("IEEE 802.15.4 configuration interface");
-MODULE_AUTHOR("Dmitry Eremin-Solenikov");
-
diff --git a/net/ieee802154/core.h b/net/ieee802154/core.h
deleted file mode 100644
index f3e9558..0000000
--- a/net/ieee802154/core.h
+++ /dev/null
@@ -1,46 +0,0 @@
-#ifndef __IEEE802154_CORE_H
-#define __IEEE802154_CORE_H
-
-#include <net/cfg802154.h>
-
-struct cfg802154_registered_device {
- const struct cfg802154_ops *ops;
- struct list_head list;
-
- /* wpan_phy index, internal only */
- int wpan_phy_idx;
-
- /* also protected by devlist_mtx */
- int opencount;
- wait_queue_head_t dev_wait;
-
- /* protected by RTNL only */
- int num_running_ifaces;
-
- /* associated wpan interfaces, protected by rtnl or RCU */
- struct list_head wpan_dev_list;
- int devlist_generation, wpan_dev_id;
-
- /* must be last because of the way we do wpan_phy_priv(),
- * and it should at least be aligned to NETDEV_ALIGN
- */
- struct wpan_phy wpan_phy __aligned(NETDEV_ALIGN);
-};
-
-static inline struct cfg802154_registered_device *
-wpan_phy_to_rdev(struct wpan_phy *wpan_phy)
-{
- BUG_ON(!wpan_phy);
- return container_of(wpan_phy, struct cfg802154_registered_device,
- wpan_phy);
-}
-
-extern struct list_head cfg802154_rdev_list;
-extern int cfg802154_rdev_list_generation;
-
-/* free object */
-void cfg802154_dev_free(struct cfg802154_registered_device *rdev);
-struct cfg802154_registered_device *
-cfg802154_rdev_by_wpan_phy_idx(int wpan_phy_idx);
-
-#endif /* __IEEE802154_CORE_H */
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c
index a866820..0961336 100644
--- a/net/ieee802154/dgram.c
+++ b/net/ieee802154/dgram.c
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -23,9 +27,9 @@
#include <linux/if_arp.h>
#include <linux/list.h>
#include <linux/slab.h>
-#include <linux/ieee802154.h>
#include <net/sock.h>
#include <net/af_ieee802154.h>
+#include <net/ieee802154.h>
#include <net/ieee802154_netdev.h>
#include <asm/ioctls.h>
@@ -154,6 +158,7 @@
spin_unlock_bh(&sk->sk_receive_queue.lock);
return put_user(amount, (int __user *)arg);
}
+
}
return -ENOIOCTLCMD;
@@ -275,7 +280,7 @@
if (err < 0)
goto out_skb;
- err = memcpy_from_msg(skb_put(skb, size), msg, size);
+ err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
if (err < 0)
goto out_skb;
@@ -319,7 +324,7 @@
}
/* FIXME: skip headers if necessary ?! */
- err = skb_copy_datagram_msg(skb, 0, msg, copied);
+ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
if (err)
goto done;
diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c
index a051b69..c09294e 100644
--- a/net/ieee802154/header_ops.c
+++ b/net/ieee802154/header_ops.c
@@ -14,9 +14,8 @@
* Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
*/
-#include <linux/ieee802154.h>
-
#include <net/mac802154.h>
+#include <net/ieee802154.h>
#include <net/ieee802154_netdev.h>
static int
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h
index a5d7515..5d352f8 100644
--- a/net/ieee802154/ieee802154.h
+++ b/net/ieee802154/ieee802154.h
@@ -10,12 +10,16 @@
* 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 IEEE_802154_LOCAL_H
#define IEEE_802154_LOCAL_H
int __init ieee802154_nl_init(void);
-void ieee802154_nl_exit(void);
+void __exit ieee802154_nl_exit(void);
#define IEEE802154_OP(_cmd, _func) \
{ \
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c
index 78cc7cd..50a167a 100644
--- a/net/ieee802154/netlink.c
+++ b/net/ieee802154/netlink.c
@@ -1,5 +1,5 @@
/*
- * Netlink interface for IEEE 802.15.4 stack
+ * Netlink inteface for IEEE 802.15.4 stack
*
* Copyright 2007, 2008 Siemens AG
*
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -73,7 +77,7 @@
}
struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info,
- int flags, u8 req)
+ int flags, u8 req)
{
void *hdr;
struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
@@ -147,6 +151,7 @@
[IEEE802154_BEACON_MCGRP] = { .name = IEEE802154_MCAST_BEACON_NAME, },
};
+
int __init ieee802154_nl_init(void)
{
return genl_register_family_with_ops_groups(&nl802154_family,
@@ -154,7 +159,7 @@
ieee802154_mcgrps);
}
-void ieee802154_nl_exit(void)
+void __exit ieee802154_nl_exit(void)
{
genl_unregister_family(&nl802154_family);
}
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c
index 25ff57e..cd28596 100644
--- a/net/ieee802154/nl-mac.c
+++ b/net/ieee802154/nl-mac.c
@@ -1,5 +1,5 @@
/*
- * Netlink interface for IEEE 802.15.4 stack
+ * Netlink inteface for IEEE 802.15.4 stack
*
* Copyright 2007, 2008 Siemens AG
*
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -22,15 +26,16 @@
#include <linux/kernel.h>
#include <linux/if_arp.h>
#include <linux/netdevice.h>
-#include <linux/ieee802154.h>
#include <net/netlink.h>
#include <net/genetlink.h>
#include <net/sock.h>
#include <linux/nl802154.h>
#include <linux/export.h>
#include <net/af_ieee802154.h>
+#include <net/nl802154.h>
+#include <net/ieee802154.h>
#include <net/ieee802154_netdev.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
#include "ieee802154.h"
@@ -54,7 +59,186 @@
return cpu_to_le16(nla_get_u16(nla));
}
-static int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
+int ieee802154_nl_assoc_indic(struct net_device *dev,
+ struct ieee802154_addr *addr,
+ u8 cap)
+{
+ struct sk_buff *msg;
+
+ pr_debug("%s\n", __func__);
+
+ if (addr->mode != IEEE802154_ADDR_LONG) {
+ pr_err("%s: received non-long source address!\n", __func__);
+ return -EINVAL;
+ }
+
+ msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_INDIC);
+ if (!msg)
+ return -ENOBUFS;
+
+ if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+ nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+ nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+ dev->dev_addr) ||
+ nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
+ addr->extended_addr) ||
+ nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap))
+ goto nla_put_failure;
+
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_assoc_indic);
+
+int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr,
+ u8 status)
+{
+ struct sk_buff *msg;
+
+ pr_debug("%s\n", __func__);
+
+ msg = ieee802154_nl_create(0, IEEE802154_ASSOCIATE_CONF);
+ if (!msg)
+ return -ENOBUFS;
+
+ if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+ nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+ nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+ dev->dev_addr) ||
+ nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) ||
+ nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
+ goto nla_put_failure;
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_assoc_confirm);
+
+int ieee802154_nl_disassoc_indic(struct net_device *dev,
+ struct ieee802154_addr *addr,
+ u8 reason)
+{
+ struct sk_buff *msg;
+
+ pr_debug("%s\n", __func__);
+
+ msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_INDIC);
+ if (!msg)
+ return -ENOBUFS;
+
+ if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+ nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+ nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+ dev->dev_addr))
+ goto nla_put_failure;
+ if (addr->mode == IEEE802154_ADDR_LONG) {
+ if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR,
+ addr->extended_addr))
+ goto nla_put_failure;
+ } else {
+ if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR,
+ addr->short_addr))
+ goto nla_put_failure;
+ }
+ if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason))
+ goto nla_put_failure;
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_disassoc_indic);
+
+int ieee802154_nl_disassoc_confirm(struct net_device *dev, u8 status)
+{
+ struct sk_buff *msg;
+
+ pr_debug("%s\n", __func__);
+
+ msg = ieee802154_nl_create(0, IEEE802154_DISASSOCIATE_CONF);
+ if (!msg)
+ return -ENOBUFS;
+
+ if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+ nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+ nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+ dev->dev_addr) ||
+ nla_put_u8(msg, IEEE802154_ATTR_STATUS, status))
+ goto nla_put_failure;
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm);
+
+int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid,
+ __le16 coord_addr)
+{
+ struct sk_buff *msg;
+
+ pr_debug("%s\n", __func__);
+
+ msg = ieee802154_nl_create(0, IEEE802154_BEACON_NOTIFY_INDIC);
+ if (!msg)
+ return -ENOBUFS;
+
+ if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+ nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+ nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+ dev->dev_addr) ||
+ nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR,
+ coord_addr) ||
+ nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid))
+ goto nla_put_failure;
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_beacon_indic);
+
+int ieee802154_nl_scan_confirm(struct net_device *dev,
+ u8 status, u8 scan_type,
+ u32 unscanned, u8 page,
+ u8 *edl/* , struct list_head *pan_desc_list */)
+{
+ struct sk_buff *msg;
+
+ pr_debug("%s\n", __func__);
+
+ msg = ieee802154_nl_create(0, IEEE802154_SCAN_CONF);
+ if (!msg)
+ return -ENOBUFS;
+
+ if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) ||
+ nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) ||
+ nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN,
+ dev->dev_addr) ||
+ nla_put_u8(msg, IEEE802154_ATTR_STATUS, status) ||
+ nla_put_u8(msg, IEEE802154_ATTR_SCAN_TYPE, scan_type) ||
+ nla_put_u32(msg, IEEE802154_ATTR_CHANNELS, unscanned) ||
+ nla_put_u8(msg, IEEE802154_ATTR_PAGE, page) ||
+ (edl &&
+ nla_put(msg, IEEE802154_ATTR_ED_LIST, 27, edl)))
+ goto nla_put_failure;
+ return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP);
+
+nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+EXPORT_SYMBOL(ieee802154_nl_scan_confirm);
+
+int ieee802154_nl_start_confirm(struct net_device *dev, u8 status)
{
struct sk_buff *msg;
@@ -94,9 +278,8 @@
goto out;
ops = ieee802154_mlme_ops(dev);
- phy = dev->ieee802154_ptr->wpan_phy;
+ phy = ops->get_phy(dev);
BUG_ON(!phy);
- get_device(&phy->dev);
short_addr = ops->get_short_addr(dev);
pan_id = ops->get_pan_id(dev);
@@ -113,9 +296,7 @@
if (ops->get_mac_params) {
struct ieee802154_mac_params params;
- rtnl_lock();
ops->get_mac_params(dev, ¶ms);
- rtnl_unlock();
if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER,
params.transmit_power) ||
@@ -166,10 +347,7 @@
if (!dev)
return NULL;
- /* Check on mtu is currently a hacked solution because lowpan
- * and wpan have the same ARPHRD type.
- */
- if (dev->type != ARPHRD_IEEE802154 || dev->mtu != IEEE802154_MTU) {
+ if (dev->type != ARPHRD_IEEE802154) {
dev_put(dev);
return NULL;
}
@@ -303,7 +481,7 @@
u8 channel, bcn_ord, sf_ord;
u8 page;
int pan_coord, blx, coord_realign;
- int ret = -EBUSY;
+ int ret = -EOPNOTSUPP;
if (!info->attrs[IEEE802154_ATTR_COORD_PAN_ID] ||
!info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR] ||
@@ -319,15 +497,9 @@
dev = ieee802154_nl_get_dev(info);
if (!dev)
return -ENODEV;
-
- if (netif_running(dev))
+ if (!ieee802154_mlme_ops(dev)->start_req)
goto out;
- if (!ieee802154_mlme_ops(dev)->start_req) {
- ret = -EOPNOTSUPP;
- goto out;
- }
-
addr.mode = IEEE802154_ADDR_SHORT;
addr.short_addr = nla_get_shortaddr(
info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]);
@@ -346,21 +518,15 @@
else
page = 0;
+
if (addr.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) {
ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS);
dev_put(dev);
return -EINVAL;
}
- rtnl_lock();
ret = ieee802154_mlme_ops(dev)->start_req(dev, &addr, channel, page,
bcn_ord, sf_ord, pan_coord, blx, coord_realign);
- rtnl_unlock();
-
- /* FIXME: add validation for unused parameters to be sane
- * for SoftMAC
- */
- ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
out:
dev_put(dev);
@@ -396,6 +562,7 @@
else
page = 0;
+
ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels,
page, duration);
@@ -450,11 +617,7 @@
idx = 0;
for_each_netdev(net, dev) {
- /* Check on mtu is currently a hacked solution because lowpan
- * and wpan have the same ARPHRD type.
- */
- if (idx < s_idx || dev->type != ARPHRD_IEEE802154 ||
- dev->mtu != IEEE802154_MTU)
+ if (idx < s_idx || (dev->type != ARPHRD_IEEE802154))
goto cont;
if (ieee802154_nl_fill_iface(skb, NETLINK_CB_PORTID(cb->skb),
@@ -504,10 +667,22 @@
!info->attrs[IEEE802154_ATTR_FRAME_RETRIES])
goto out;
- phy = dev->ieee802154_ptr->wpan_phy;
- get_device(&phy->dev);
+ phy = ops->get_phy(dev);
- rtnl_lock();
+ if ((!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) ||
+ (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) ||
+ (!phy->set_cca_ed_level &&
+ info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) ||
+ (!phy->set_csma_params &&
+ (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] ||
+ info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] ||
+ info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])) ||
+ (!phy->set_frame_retries &&
+ info->attrs[IEEE802154_ATTR_FRAME_RETRIES])) {
+ rc = -EOPNOTSUPP;
+ goto out_phy;
+ }
+
ops->get_mac_params(dev, ¶ms);
if (info->attrs[IEEE802154_ATTR_TXPOWER])
@@ -535,18 +710,20 @@
params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]);
rc = ops->set_mac_params(dev, ¶ms);
- rtnl_unlock();
wpan_phy_put(phy);
dev_put(dev);
+ return rc;
- return 0;
-
+out_phy:
+ wpan_phy_put(phy);
out:
dev_put(dev);
return rc;
}
+
+
static int
ieee802154_llsec_parse_key_id(struct genl_info *info,
struct ieee802154_llsec_key_id *desc)
@@ -762,6 +939,8 @@
return rc;
}
+
+
struct llsec_dump_data {
struct sk_buff *skb;
int s_idx, s_idx2;
@@ -784,11 +963,7 @@
int rc;
for_each_netdev(net, dev) {
- /* Check on mtu is currently a hacked solution because lowpan
- * and wpan have the same ARPHRD type.
- */
- if (idx < first_dev || dev->type != ARPHRD_IEEE802154 ||
- dev->mtu != IEEE802154_MTU)
+ if (idx < first_dev || dev->type != ARPHRD_IEEE802154)
goto skip;
data.ops = ieee802154_mlme_ops(dev);
@@ -838,6 +1013,8 @@
return rc;
}
+
+
static int
ieee802154_llsec_parse_key(struct genl_info *info,
struct ieee802154_llsec_key *key)
@@ -982,6 +1159,8 @@
return ieee802154_llsec_dump_table(skb, cb, llsec_iter_keys);
}
+
+
static int
llsec_parse_dev(struct genl_info *info,
struct ieee802154_llsec_device *dev)
@@ -1112,6 +1291,8 @@
return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devs);
}
+
+
static int llsec_add_devkey(struct net_device *dev, struct genl_info *info)
{
struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
@@ -1226,6 +1407,8 @@
return ieee802154_llsec_dump_table(skb, cb, llsec_iter_devkeys);
}
+
+
static int
llsec_parse_seclevel(struct genl_info *info,
struct ieee802154_llsec_seclevel *sl)
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c
index 2b8b724..07c503f 100644
--- a/net/ieee802154/nl-phy.c
+++ b/net/ieee802154/nl-phy.c
@@ -1,5 +1,5 @@
/*
- * Netlink interface for IEEE 802.15.4 stack
+ * Netlink inteface for IEEE 802.15.4 stack
*
* Copyright 2007, 2008 Siemens AG
*
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -23,15 +27,13 @@
#include <linux/if_arp.h>
#include <net/netlink.h>
#include <net/genetlink.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
#include <net/af_ieee802154.h>
#include <net/ieee802154_netdev.h>
#include <net/rtnetlink.h> /* for rtnl_{un,}lock */
#include <linux/nl802154.h>
#include "ieee802154.h"
-#include "rdev-ops.h"
-#include "core.h"
static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid,
u32 seq, int flags, struct wpan_phy *phy)
@@ -94,6 +96,7 @@
if (name[nla_len(info->attrs[IEEE802154_ATTR_PHY_NAME]) - 1] != '\0')
return -EINVAL; /* phy name should be null-terminated */
+
phy = wpan_phy_find(name);
if (!phy)
return -ENODEV;
@@ -205,6 +208,11 @@
if (!msg)
goto out_dev;
+ if (!phy->add_iface) {
+ rc = -EINVAL;
+ goto nla_put_failure;
+ }
+
if (info->attrs[IEEE802154_ATTR_HW_ADDR] &&
nla_len(info->attrs[IEEE802154_ATTR_HW_ADDR]) !=
IEEE802154_ADDR_LEN) {
@@ -220,13 +228,11 @@
}
}
- dev = rdev_add_virtual_intf_deprecated(wpan_phy_to_rdev(phy), devname,
- type);
+ dev = phy->add_iface(phy, devname, type);
if (IS_ERR(dev)) {
rc = PTR_ERR(dev);
goto nla_put_failure;
}
- dev_hold(dev);
if (info->attrs[IEEE802154_ATTR_HW_ADDR]) {
struct sockaddr addr;
@@ -256,7 +262,7 @@
dev_unregister:
rtnl_lock(); /* del_iface must be called with RTNL lock */
- rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev);
+ phy->del_iface(phy, dev);
dev_put(dev);
rtnl_unlock();
nla_put_failure:
@@ -287,9 +293,8 @@
if (!dev)
return -ENODEV;
- phy = dev->ieee802154_ptr->wpan_phy;
+ phy = ieee802154_mlme_ops(dev)->get_phy(dev);
BUG_ON(!phy);
- get_device(&phy->dev);
rc = -EINVAL;
/* phy name is optional, but should be checked if it's given */
@@ -319,8 +324,13 @@
if (!msg)
goto out_dev;
+ if (!phy->del_iface) {
+ rc = -EINVAL;
+ goto nla_put_failure;
+ }
+
rtnl_lock();
- rdev_del_virtual_intf_deprecated(wpan_phy_to_rdev(phy), dev);
+ phy->del_iface(phy, dev);
/* We don't have device anymore */
dev_put(dev);
diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c
deleted file mode 100644
index 47be111..0000000
--- a/net/ieee802154/nl802154.c
+++ /dev/null
@@ -1,957 +0,0 @@
-/* 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.
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- *
- * Based on: net/wireless/nl80211.c
- */
-
-#include <linux/rtnetlink.h>
-
-#include <net/cfg802154.h>
-#include <net/genetlink.h>
-#include <net/mac802154.h>
-#include <net/netlink.h>
-#include <net/nl802154.h>
-#include <net/sock.h>
-
-#include "nl802154.h"
-#include "rdev-ops.h"
-#include "core.h"
-
-static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info);
-
-static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info);
-
-/* the netlink family */
-static struct genl_family nl802154_fam = {
- .id = GENL_ID_GENERATE, /* don't bother with a hardcoded ID */
- .name = NL802154_GENL_NAME, /* have users key off the name instead */
- .hdrsize = 0, /* no private header */
- .version = 1, /* no particular meaning now */
- .maxattr = NL802154_ATTR_MAX,
- .netnsok = true,
- .pre_doit = nl802154_pre_doit,
- .post_doit = nl802154_post_doit,
-};
-
-/* multicast groups */
-enum nl802154_multicast_groups {
- NL802154_MCGRP_CONFIG,
-};
-
-static const struct genl_multicast_group nl802154_mcgrps[] = {
- [NL802154_MCGRP_CONFIG] = { .name = "config", },
-};
-
-/* returns ERR_PTR values */
-static struct wpan_dev *
-__cfg802154_wpan_dev_from_attrs(struct net *netns, struct nlattr **attrs)
-{
- struct cfg802154_registered_device *rdev;
- struct wpan_dev *result = NULL;
- bool have_ifidx = attrs[NL802154_ATTR_IFINDEX];
- bool have_wpan_dev_id = attrs[NL802154_ATTR_WPAN_DEV];
- u64 wpan_dev_id;
- int wpan_phy_idx = -1;
- int ifidx = -1;
-
- ASSERT_RTNL();
-
- if (!have_ifidx && !have_wpan_dev_id)
- return ERR_PTR(-EINVAL);
-
- if (have_ifidx)
- ifidx = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
- if (have_wpan_dev_id) {
- wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
- wpan_phy_idx = wpan_dev_id >> 32;
- }
-
- list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
- struct wpan_dev *wpan_dev;
-
- /* TODO netns compare */
-
- if (have_wpan_dev_id && rdev->wpan_phy_idx != wpan_phy_idx)
- continue;
-
- list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
- if (have_ifidx && wpan_dev->netdev &&
- wpan_dev->netdev->ifindex == ifidx) {
- result = wpan_dev;
- break;
- }
- if (have_wpan_dev_id &&
- wpan_dev->identifier == (u32)wpan_dev_id) {
- result = wpan_dev;
- break;
- }
- }
-
- if (result)
- break;
- }
-
- if (result)
- return result;
-
- return ERR_PTR(-ENODEV);
-}
-
-static struct cfg802154_registered_device *
-__cfg802154_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
-{
- struct cfg802154_registered_device *rdev = NULL, *tmp;
- struct net_device *netdev;
-
- ASSERT_RTNL();
-
- if (!attrs[NL802154_ATTR_WPAN_PHY] &&
- !attrs[NL802154_ATTR_IFINDEX] &&
- !attrs[NL802154_ATTR_WPAN_DEV])
- return ERR_PTR(-EINVAL);
-
- if (attrs[NL802154_ATTR_WPAN_PHY])
- rdev = cfg802154_rdev_by_wpan_phy_idx(
- nla_get_u32(attrs[NL802154_ATTR_WPAN_PHY]));
-
- if (attrs[NL802154_ATTR_WPAN_DEV]) {
- u64 wpan_dev_id = nla_get_u64(attrs[NL802154_ATTR_WPAN_DEV]);
- struct wpan_dev *wpan_dev;
- bool found = false;
-
- tmp = cfg802154_rdev_by_wpan_phy_idx(wpan_dev_id >> 32);
- if (tmp) {
- /* make sure wpan_dev exists */
- list_for_each_entry(wpan_dev, &tmp->wpan_dev_list, list) {
- if (wpan_dev->identifier != (u32)wpan_dev_id)
- continue;
- found = true;
- break;
- }
-
- if (!found)
- tmp = NULL;
-
- if (rdev && tmp != rdev)
- return ERR_PTR(-EINVAL);
- rdev = tmp;
- }
- }
-
- if (attrs[NL802154_ATTR_IFINDEX]) {
- int ifindex = nla_get_u32(attrs[NL802154_ATTR_IFINDEX]);
-
- netdev = __dev_get_by_index(netns, ifindex);
- if (netdev) {
- if (netdev->ieee802154_ptr)
- tmp = wpan_phy_to_rdev(
- netdev->ieee802154_ptr->wpan_phy);
- else
- tmp = NULL;
-
- /* not wireless device -- return error */
- if (!tmp)
- return ERR_PTR(-EINVAL);
-
- /* mismatch -- return error */
- if (rdev && tmp != rdev)
- return ERR_PTR(-EINVAL);
-
- rdev = tmp;
- }
- }
-
- if (!rdev)
- return ERR_PTR(-ENODEV);
-
- /* TODO netns compare */
-
- return rdev;
-}
-
-/* This function returns a pointer to the driver
- * that the genl_info item that is passed refers to.
- *
- * The result of this can be a PTR_ERR and hence must
- * be checked with IS_ERR() for errors.
- */
-static struct cfg802154_registered_device *
-cfg802154_get_dev_from_info(struct net *netns, struct genl_info *info)
-{
- return __cfg802154_rdev_from_attrs(netns, info->attrs);
-}
-
-/* policy for the attributes */
-static const struct nla_policy nl802154_policy[NL802154_ATTR_MAX+1] = {
- [NL802154_ATTR_WPAN_PHY] = { .type = NLA_U32 },
- [NL802154_ATTR_WPAN_PHY_NAME] = { .type = NLA_NUL_STRING,
- .len = 20-1 },
-
- [NL802154_ATTR_IFINDEX] = { .type = NLA_U32 },
- [NL802154_ATTR_IFTYPE] = { .type = NLA_U32 },
- [NL802154_ATTR_IFNAME] = { .type = NLA_NUL_STRING, .len = IFNAMSIZ-1 },
-
- [NL802154_ATTR_WPAN_DEV] = { .type = NLA_U64 },
-
- [NL802154_ATTR_PAGE] = { .type = NLA_U8, },
- [NL802154_ATTR_CHANNEL] = { .type = NLA_U8, },
-
- [NL802154_ATTR_TX_POWER] = { .type = NLA_S8, },
-
- [NL802154_ATTR_CCA_MODE] = { .type = NLA_U8, },
-
- [NL802154_ATTR_SUPPORTED_CHANNEL] = { .type = NLA_U32, },
-
- [NL802154_ATTR_PAN_ID] = { .type = NLA_U16, },
- [NL802154_ATTR_EXTENDED_ADDR] = { .type = NLA_U64 },
- [NL802154_ATTR_SHORT_ADDR] = { .type = NLA_U16, },
-
- [NL802154_ATTR_MIN_BE] = { .type = NLA_U8, },
- [NL802154_ATTR_MAX_BE] = { .type = NLA_U8, },
- [NL802154_ATTR_MAX_CSMA_BACKOFFS] = { .type = NLA_U8, },
-
- [NL802154_ATTR_MAX_FRAME_RETRIES] = { .type = NLA_S8, },
-
- [NL802154_ATTR_LBT_MODE] = { .type = NLA_U8, },
-};
-
-/* message building helper */
-static inline void *nl802154hdr_put(struct sk_buff *skb, u32 portid, u32 seq,
- int flags, u8 cmd)
-{
- /* since there is no private header just add the generic one */
- return genlmsg_put(skb, portid, seq, &nl802154_fam, flags, cmd);
-}
-
-static int
-nl802154_send_wpan_phy_channels(struct cfg802154_registered_device *rdev,
- struct sk_buff *msg)
-{
- struct nlattr *nl_page;
- unsigned long page;
-
- nl_page = nla_nest_start(msg, NL802154_ATTR_CHANNELS_SUPPORTED);
- if (!nl_page)
- return -ENOBUFS;
-
- for (page = 0; page <= IEEE802154_MAX_PAGE; page++) {
- if (nla_put_u32(msg, NL802154_ATTR_SUPPORTED_CHANNEL,
- rdev->wpan_phy.channels_supported[page]))
- return -ENOBUFS;
- }
- nla_nest_end(msg, nl_page);
-
- return 0;
-}
-
-static int nl802154_send_wpan_phy(struct cfg802154_registered_device *rdev,
- enum nl802154_commands cmd,
- struct sk_buff *msg, u32 portid, u32 seq,
- int flags)
-{
- void *hdr;
-
- hdr = nl802154hdr_put(msg, portid, seq, flags, cmd);
- if (!hdr)
- return -ENOBUFS;
-
- if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
- nla_put_string(msg, NL802154_ATTR_WPAN_PHY_NAME,
- wpan_phy_name(&rdev->wpan_phy)) ||
- nla_put_u32(msg, NL802154_ATTR_GENERATION,
- cfg802154_rdev_list_generation))
- goto nla_put_failure;
-
- if (cmd != NL802154_CMD_NEW_WPAN_PHY)
- goto finish;
-
- /* DUMP PHY PIB */
-
- /* current channel settings */
- if (nla_put_u8(msg, NL802154_ATTR_PAGE,
- rdev->wpan_phy.current_page) ||
- nla_put_u8(msg, NL802154_ATTR_CHANNEL,
- rdev->wpan_phy.current_channel))
- goto nla_put_failure;
-
- /* supported channels array */
- if (nl802154_send_wpan_phy_channels(rdev, msg))
- goto nla_put_failure;
-
- /* cca mode */
- if (nla_put_u8(msg, NL802154_ATTR_CCA_MODE,
- rdev->wpan_phy.cca_mode))
- goto nla_put_failure;
-
- if (nla_put_s8(msg, NL802154_ATTR_TX_POWER,
- rdev->wpan_phy.transmit_power))
- goto nla_put_failure;
-
-finish:
- return genlmsg_end(msg, hdr);
-
-nla_put_failure:
- genlmsg_cancel(msg, hdr);
- return -EMSGSIZE;
-}
-
-struct nl802154_dump_wpan_phy_state {
- s64 filter_wpan_phy;
- long start;
-
-};
-
-static int nl802154_dump_wpan_phy_parse(struct sk_buff *skb,
- struct netlink_callback *cb,
- struct nl802154_dump_wpan_phy_state *state)
-{
- struct nlattr **tb = nl802154_fam.attrbuf;
- int ret = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl802154_fam.hdrsize,
- tb, nl802154_fam.maxattr, nl802154_policy);
-
- /* TODO check if we can handle error here,
- * we have no backward compatibility
- */
- if (ret)
- return 0;
-
- if (tb[NL802154_ATTR_WPAN_PHY])
- state->filter_wpan_phy = nla_get_u32(tb[NL802154_ATTR_WPAN_PHY]);
- if (tb[NL802154_ATTR_WPAN_DEV])
- state->filter_wpan_phy = nla_get_u64(tb[NL802154_ATTR_WPAN_DEV]) >> 32;
- if (tb[NL802154_ATTR_IFINDEX]) {
- struct net_device *netdev;
- struct cfg802154_registered_device *rdev;
- int ifidx = nla_get_u32(tb[NL802154_ATTR_IFINDEX]);
-
- /* TODO netns */
- netdev = __dev_get_by_index(&init_net, ifidx);
- if (!netdev)
- return -ENODEV;
- if (netdev->ieee802154_ptr) {
- rdev = wpan_phy_to_rdev(
- netdev->ieee802154_ptr->wpan_phy);
- state->filter_wpan_phy = rdev->wpan_phy_idx;
- }
- }
-
- return 0;
-}
-
-static int
-nl802154_dump_wpan_phy(struct sk_buff *skb, struct netlink_callback *cb)
-{
- int idx = 0, ret;
- struct nl802154_dump_wpan_phy_state *state = (void *)cb->args[0];
- struct cfg802154_registered_device *rdev;
-
- rtnl_lock();
- if (!state) {
- state = kzalloc(sizeof(*state), GFP_KERNEL);
- if (!state) {
- rtnl_unlock();
- return -ENOMEM;
- }
- state->filter_wpan_phy = -1;
- ret = nl802154_dump_wpan_phy_parse(skb, cb, state);
- if (ret) {
- kfree(state);
- rtnl_unlock();
- return ret;
- }
- cb->args[0] = (long)state;
- }
-
- list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
- /* TODO net ns compare */
- if (++idx <= state->start)
- continue;
- if (state->filter_wpan_phy != -1 &&
- state->filter_wpan_phy != rdev->wpan_phy_idx)
- continue;
- /* attempt to fit multiple wpan_phy data chunks into the skb */
- ret = nl802154_send_wpan_phy(rdev,
- NL802154_CMD_NEW_WPAN_PHY,
- skb,
- NETLINK_CB_PORTID(cb->skb),
- cb->nlh->nlmsg_seq, NLM_F_MULTI);
- if (ret < 0) {
- if ((ret == -ENOBUFS || ret == -EMSGSIZE) &&
- !skb->len && cb->min_dump_alloc < 4096) {
- cb->min_dump_alloc = 4096;
- rtnl_unlock();
- return 1;
- }
- idx--;
- break;
- }
- break;
- }
- rtnl_unlock();
-
- state->start = idx;
-
- return skb->len;
-}
-
-static int nl802154_dump_wpan_phy_done(struct netlink_callback *cb)
-{
- kfree((void *)cb->args[0]);
- return 0;
-}
-
-static int nl802154_get_wpan_phy(struct sk_buff *skb, struct genl_info *info)
-{
- struct sk_buff *msg;
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg)
- return -ENOMEM;
-
- if (nl802154_send_wpan_phy(rdev, NL802154_CMD_NEW_WPAN_PHY, msg,
- genl_info_snd_portid(info), info->snd_seq, 0) < 0) {
- nlmsg_free(msg);
- return -ENOBUFS;
- }
-
- return genlmsg_reply(msg, info);
-}
-
-static inline u64 wpan_dev_id(struct wpan_dev *wpan_dev)
-{
- return (u64)wpan_dev->identifier |
- ((u64)wpan_phy_to_rdev(wpan_dev->wpan_phy)->wpan_phy_idx << 32);
-}
-
-static int
-nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
- struct cfg802154_registered_device *rdev,
- struct wpan_dev *wpan_dev)
-{
- struct net_device *dev = wpan_dev->netdev;
- void *hdr;
-
- hdr = nl802154hdr_put(msg, portid, seq, flags,
- NL802154_CMD_NEW_INTERFACE);
- if (!hdr)
- return -1;
-
- if (dev &&
- (nla_put_u32(msg, NL802154_ATTR_IFINDEX, dev->ifindex) ||
- nla_put_string(msg, NL802154_ATTR_IFNAME, dev->name)))
- goto nla_put_failure;
-
- if (nla_put_u32(msg, NL802154_ATTR_WPAN_PHY, rdev->wpan_phy_idx) ||
- nla_put_u32(msg, NL802154_ATTR_IFTYPE, wpan_dev->iftype) ||
- nla_put_u64(msg, NL802154_ATTR_WPAN_DEV, wpan_dev_id(wpan_dev)) ||
- nla_put_u32(msg, NL802154_ATTR_GENERATION,
- rdev->devlist_generation ^
- (cfg802154_rdev_list_generation << 2)))
- goto nla_put_failure;
-
- /* address settings */
- if (nla_put_le64(msg, NL802154_ATTR_EXTENDED_ADDR,
- wpan_dev->extended_addr) ||
- nla_put_le16(msg, NL802154_ATTR_SHORT_ADDR,
- wpan_dev->short_addr) ||
- nla_put_le16(msg, NL802154_ATTR_PAN_ID, wpan_dev->pan_id))
- goto nla_put_failure;
-
- /* ARET handling */
- if (nla_put_s8(msg, NL802154_ATTR_MAX_FRAME_RETRIES,
- wpan_dev->frame_retries) ||
- nla_put_u8(msg, NL802154_ATTR_MAX_BE, wpan_dev->max_be) ||
- nla_put_u8(msg, NL802154_ATTR_MAX_CSMA_BACKOFFS,
- wpan_dev->csma_retries) ||
- nla_put_u8(msg, NL802154_ATTR_MIN_BE, wpan_dev->min_be))
- goto nla_put_failure;
-
- /* listen before transmit */
- if (nla_put_u8(msg, NL802154_ATTR_LBT_MODE, wpan_dev->lbt))
- goto nla_put_failure;
-
- return genlmsg_end(msg, hdr);
-
-nla_put_failure:
- genlmsg_cancel(msg, hdr);
- return -EMSGSIZE;
-}
-
-static int
-nl802154_dump_interface(struct sk_buff *skb, struct netlink_callback *cb)
-{
- int wp_idx = 0;
- int if_idx = 0;
- int wp_start = cb->args[0];
- int if_start = cb->args[1];
- struct cfg802154_registered_device *rdev;
- struct wpan_dev *wpan_dev;
-
- rtnl_lock();
- list_for_each_entry(rdev, &cfg802154_rdev_list, list) {
- /* TODO netns compare */
- if (wp_idx < wp_start) {
- wp_idx++;
- continue;
- }
- if_idx = 0;
-
- list_for_each_entry(wpan_dev, &rdev->wpan_dev_list, list) {
- if (if_idx < if_start) {
- if_idx++;
- continue;
- }
- if (nl802154_send_iface(skb, NETLINK_CB_PORTID(cb->skb),
- cb->nlh->nlmsg_seq, NLM_F_MULTI,
- rdev, wpan_dev) < 0) {
- goto out;
- }
- if_idx++;
- }
-
- wp_idx++;
- }
-out:
- rtnl_unlock();
-
- cb->args[0] = wp_idx;
- cb->args[1] = if_idx;
-
- return skb->len;
-}
-
-static int nl802154_get_interface(struct sk_buff *skb, struct genl_info *info)
-{
- struct sk_buff *msg;
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- struct wpan_dev *wdev = info->user_ptr[1];
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg)
- return -ENOMEM;
-
- if (nl802154_send_iface(msg, genl_info_snd_portid(info), info->snd_seq, 0,
- rdev, wdev) < 0) {
- nlmsg_free(msg);
- return -ENOBUFS;
- }
-
- return genlmsg_reply(msg, info);
-}
-
-static int nl802154_new_interface(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- enum nl802154_iftype type = NL802154_IFTYPE_UNSPEC;
- __le64 extended_addr = cpu_to_le64(0x0000000000000000ULL);
-
- /* TODO avoid failing a new interface
- * creation due to pending removal?
- */
-
- if (!info->attrs[NL802154_ATTR_IFNAME])
- return -EINVAL;
-
- if (info->attrs[NL802154_ATTR_IFTYPE]) {
- type = nla_get_u32(info->attrs[NL802154_ATTR_IFTYPE]);
- if (type > NL802154_IFTYPE_MAX)
- return -EINVAL;
- }
-
- /* TODO add nla_get_le64 to netlink */
- if (info->attrs[NL802154_ATTR_EXTENDED_ADDR])
- extended_addr = (__force __le64)nla_get_u64(
- info->attrs[NL802154_ATTR_EXTENDED_ADDR]);
-
- if (!rdev->ops->add_virtual_intf)
- return -EOPNOTSUPP;
-
- return rdev_add_virtual_intf(rdev,
- nla_data(info->attrs[NL802154_ATTR_IFNAME]),
- type, extended_addr);
-}
-
-static int nl802154_del_interface(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- struct wpan_dev *wpan_dev = info->user_ptr[1];
-
- if (!rdev->ops->del_virtual_intf)
- return -EOPNOTSUPP;
-
- /* If we remove a wpan device without a netdev then clear
- * user_ptr[1] so that nl802154_post_doit won't dereference it
- * to check if it needs to do dev_put(). Otherwise it crashes
- * since the wpan_dev has been freed, unlike with a netdev where
- * we need the dev_put() for the netdev to really be freed.
- */
- if (!wpan_dev->netdev)
- info->user_ptr[1] = NULL;
-
- return rdev_del_virtual_intf(rdev, wpan_dev);
-}
-
-static int nl802154_set_channel(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- u8 channel, page;
-
- if (!info->attrs[NL802154_ATTR_PAGE] ||
- !info->attrs[NL802154_ATTR_CHANNEL])
- return -EINVAL;
-
- page = nla_get_u8(info->attrs[NL802154_ATTR_PAGE]);
- channel = nla_get_u8(info->attrs[NL802154_ATTR_CHANNEL]);
-
- /* check 802.15.4 constraints */
- if (page > IEEE802154_MAX_PAGE || channel > IEEE802154_MAX_CHANNEL)
- return -EINVAL;
-
- return rdev_set_channel(rdev, page, channel);
-}
-
-static int nl802154_set_pan_id(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
- __le16 pan_id;
-
- /* conflict here while tx/rx calls */
- if (netif_running(dev))
- return -EBUSY;
-
- /* don't change address fields on monitor */
- if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
- return -EINVAL;
-
- if (!info->attrs[NL802154_ATTR_PAN_ID])
- return -EINVAL;
-
- pan_id = nla_get_le16(info->attrs[NL802154_ATTR_PAN_ID]);
-
- return rdev_set_pan_id(rdev, wpan_dev, pan_id);
-}
-
-static int nl802154_set_short_addr(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
- __le16 short_addr;
-
- /* conflict here while tx/rx calls */
- if (netif_running(dev))
- return -EBUSY;
-
- /* don't change address fields on monitor */
- if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR)
- return -EINVAL;
-
- if (!info->attrs[NL802154_ATTR_SHORT_ADDR])
- return -EINVAL;
-
- short_addr = nla_get_le16(info->attrs[NL802154_ATTR_SHORT_ADDR]);
-
- return rdev_set_short_addr(rdev, wpan_dev, short_addr);
-}
-
-static int
-nl802154_set_backoff_exponent(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
- u8 min_be, max_be;
-
- /* should be set on netif open inside phy settings */
- if (netif_running(dev))
- return -EBUSY;
-
- if (!info->attrs[NL802154_ATTR_MIN_BE] ||
- !info->attrs[NL802154_ATTR_MAX_BE])
- return -EINVAL;
-
- min_be = nla_get_u8(info->attrs[NL802154_ATTR_MIN_BE]);
- max_be = nla_get_u8(info->attrs[NL802154_ATTR_MAX_BE]);
-
- /* check 802.15.4 constraints */
- if (max_be < 3 || max_be > 8 || min_be > max_be)
- return -EINVAL;
-
- return rdev_set_backoff_exponent(rdev, wpan_dev, min_be, max_be);
-}
-
-static int
-nl802154_set_max_csma_backoffs(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
- u8 max_csma_backoffs;
-
- /* conflict here while other running iface settings */
- if (netif_running(dev))
- return -EBUSY;
-
- if (!info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS])
- return -EINVAL;
-
- max_csma_backoffs = nla_get_u8(
- info->attrs[NL802154_ATTR_MAX_CSMA_BACKOFFS]);
-
- /* check 802.15.4 constraints */
- if (max_csma_backoffs > 5)
- return -EINVAL;
-
- return rdev_set_max_csma_backoffs(rdev, wpan_dev, max_csma_backoffs);
-}
-
-static int
-nl802154_set_max_frame_retries(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
- s8 max_frame_retries;
-
- if (netif_running(dev))
- return -EBUSY;
-
- if (!info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES])
- return -EINVAL;
-
- max_frame_retries = nla_get_s8(
- info->attrs[NL802154_ATTR_MAX_FRAME_RETRIES]);
-
- /* check 802.15.4 constraints */
- if (max_frame_retries < -1 || max_frame_retries > 7)
- return -EINVAL;
-
- return rdev_set_max_frame_retries(rdev, wpan_dev, max_frame_retries);
-}
-
-static int nl802154_set_lbt_mode(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wpan_dev *wpan_dev = dev->ieee802154_ptr;
- bool mode;
-
- if (netif_running(dev))
- return -EBUSY;
-
- if (!info->attrs[NL802154_ATTR_LBT_MODE])
- return -EINVAL;
-
- mode = !!nla_get_u8(info->attrs[NL802154_ATTR_LBT_MODE]);
- return rdev_set_lbt_mode(rdev, wpan_dev, mode);
-}
-
-#define NL802154_FLAG_NEED_WPAN_PHY 0x01
-#define NL802154_FLAG_NEED_NETDEV 0x02
-#define NL802154_FLAG_NEED_RTNL 0x04
-#define NL802154_FLAG_CHECK_NETDEV_UP 0x08
-#define NL802154_FLAG_NEED_NETDEV_UP (NL802154_FLAG_NEED_NETDEV |\
- NL802154_FLAG_CHECK_NETDEV_UP)
-#define NL802154_FLAG_NEED_WPAN_DEV 0x10
-#define NL802154_FLAG_NEED_WPAN_DEV_UP (NL802154_FLAG_NEED_WPAN_DEV |\
- NL802154_FLAG_CHECK_NETDEV_UP)
-
-static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info)
-{
- struct cfg802154_registered_device *rdev;
- struct wpan_dev *wpan_dev;
- struct net_device *dev;
- bool rtnl = ops->internal_flags & NL802154_FLAG_NEED_RTNL;
-
- if (rtnl)
- rtnl_lock();
-
- if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_PHY) {
- rdev = cfg802154_get_dev_from_info(genl_info_net(info), info);
- if (IS_ERR(rdev)) {
- if (rtnl)
- rtnl_unlock();
- return PTR_ERR(rdev);
- }
- info->user_ptr[0] = rdev;
- } else if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV ||
- ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
- ASSERT_RTNL();
- wpan_dev = __cfg802154_wpan_dev_from_attrs(genl_info_net(info),
- info->attrs);
- if (IS_ERR(wpan_dev)) {
- if (rtnl)
- rtnl_unlock();
- return PTR_ERR(wpan_dev);
- }
-
- dev = wpan_dev->netdev;
- rdev = wpan_phy_to_rdev(wpan_dev->wpan_phy);
-
- if (ops->internal_flags & NL802154_FLAG_NEED_NETDEV) {
- if (!dev) {
- if (rtnl)
- rtnl_unlock();
- return -EINVAL;
- }
-
- info->user_ptr[1] = dev;
- } else {
- info->user_ptr[1] = wpan_dev;
- }
-
- if (dev) {
- if (ops->internal_flags & NL802154_FLAG_CHECK_NETDEV_UP &&
- !netif_running(dev)) {
- if (rtnl)
- rtnl_unlock();
- return -ENETDOWN;
- }
-
- dev_hold(dev);
- }
-
- info->user_ptr[0] = rdev;
- }
-
- return 0;
-}
-
-static void nl802154_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
- struct genl_info *info)
-{
- if (info->user_ptr[1]) {
- if (ops->internal_flags & NL802154_FLAG_NEED_WPAN_DEV) {
- struct wpan_dev *wpan_dev = info->user_ptr[1];
-
- if (wpan_dev->netdev)
- dev_put(wpan_dev->netdev);
- } else {
- dev_put(info->user_ptr[1]);
- }
- }
-
- if (ops->internal_flags & NL802154_FLAG_NEED_RTNL)
- rtnl_unlock();
-}
-
-static const struct genl_ops nl802154_ops[] = {
- {
- .cmd = NL802154_CMD_GET_WPAN_PHY,
- .doit = nl802154_get_wpan_phy,
- .dumpit = nl802154_dump_wpan_phy,
- .done = nl802154_dump_wpan_phy_done,
- .policy = nl802154_policy,
- /* can be retrieved by unprivileged users */
- .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_GET_INTERFACE,
- .doit = nl802154_get_interface,
- .dumpit = nl802154_dump_interface,
- .policy = nl802154_policy,
- /* can be retrieved by unprivileged users */
- .internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_NEW_INTERFACE,
- .doit = nl802154_new_interface,
- .policy = nl802154_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_DEL_INTERFACE,
- .doit = nl802154_del_interface,
- .policy = nl802154_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL802154_FLAG_NEED_WPAN_DEV |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_SET_CHANNEL,
- .doit = nl802154_set_channel,
- .policy = nl802154_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL802154_FLAG_NEED_WPAN_PHY |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_SET_PAN_ID,
- .doit = nl802154_set_pan_id,
- .policy = nl802154_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL802154_FLAG_NEED_NETDEV |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_SET_SHORT_ADDR,
- .doit = nl802154_set_short_addr,
- .policy = nl802154_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL802154_FLAG_NEED_NETDEV |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_SET_BACKOFF_EXPONENT,
- .doit = nl802154_set_backoff_exponent,
- .policy = nl802154_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL802154_FLAG_NEED_NETDEV |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_SET_MAX_CSMA_BACKOFFS,
- .doit = nl802154_set_max_csma_backoffs,
- .policy = nl802154_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL802154_FLAG_NEED_NETDEV |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_SET_MAX_FRAME_RETRIES,
- .doit = nl802154_set_max_frame_retries,
- .policy = nl802154_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL802154_FLAG_NEED_NETDEV |
- NL802154_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL802154_CMD_SET_LBT_MODE,
- .doit = nl802154_set_lbt_mode,
- .policy = nl802154_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL802154_FLAG_NEED_NETDEV |
- NL802154_FLAG_NEED_RTNL,
- },
-};
-
-/* initialisation/exit functions */
-int nl802154_init(void)
-{
- return genl_register_family_with_ops_groups(&nl802154_fam, nl802154_ops,
- nl802154_mcgrps);
-}
-
-void nl802154_exit(void)
-{
- genl_unregister_family(&nl802154_fam);
-}
diff --git a/net/ieee802154/nl802154.h b/net/ieee802154/nl802154.h
deleted file mode 100644
index 3846a89..0000000
--- a/net/ieee802154/nl802154.h
+++ /dev/null
@@ -1,7 +0,0 @@
-#ifndef __IEEE802154_NL802154_H
-#define __IEEE802154_NL802154_H
-
-int nl802154_init(void);
-void nl802154_exit(void);
-
-#endif /* __IEEE802154_NL802154_H */
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c
index 35c4326..3a703ab 100644
--- a/net/ieee802154/nl_policy.c
+++ b/net/ieee802154/nl_policy.c
@@ -12,6 +12,10 @@
* 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 <linux/kernel.h>
diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c
index 1674b11..9d1f648 100644
--- a/net/ieee802154/raw.c
+++ b/net/ieee802154/raw.c
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -150,7 +154,7 @@
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
- err = memcpy_from_msg(skb_put(skb, size), msg, size);
+ err = memcpy_fromiovec(skb_put(skb, size), msg->msg_iov, size);
if (err < 0)
goto out_skb;
@@ -191,7 +195,7 @@
copied = len;
}
- err = skb_copy_datagram_msg(skb, 0, msg, copied);
+ err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
if (err)
goto done;
@@ -221,6 +225,7 @@
return NET_RX_SUCCESS;
}
+
void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb)
{
struct sock *sk;
diff --git a/net/ieee802154/rdev-ops.h b/net/ieee802154/rdev-ops.h
deleted file mode 100644
index aff54fb..0000000
--- a/net/ieee802154/rdev-ops.h
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef __CFG802154_RDEV_OPS
-#define __CFG802154_RDEV_OPS
-
-#include <net/cfg802154.h>
-
-#include "core.h"
-
-static inline struct net_device *
-rdev_add_virtual_intf_deprecated(struct cfg802154_registered_device *rdev,
- const char *name, int type)
-{
- return rdev->ops->add_virtual_intf_deprecated(&rdev->wpan_phy, name,
- type);
-}
-
-static inline void
-rdev_del_virtual_intf_deprecated(struct cfg802154_registered_device *rdev,
- struct net_device *dev)
-{
- rdev->ops->del_virtual_intf_deprecated(&rdev->wpan_phy, dev);
-}
-
-static inline int
-rdev_add_virtual_intf(struct cfg802154_registered_device *rdev, char *name,
- enum nl802154_iftype type, __le64 extended_addr)
-{
- return rdev->ops->add_virtual_intf(&rdev->wpan_phy, name, type,
- extended_addr);
-}
-
-static inline int
-rdev_del_virtual_intf(struct cfg802154_registered_device *rdev,
- struct wpan_dev *wpan_dev)
-{
- return rdev->ops->del_virtual_intf(&rdev->wpan_phy, wpan_dev);
-}
-
-static inline int
-rdev_set_channel(struct cfg802154_registered_device *rdev, u8 page, u8 channel)
-{
- return rdev->ops->set_channel(&rdev->wpan_phy, page, channel);
-}
-
-static inline int
-rdev_set_pan_id(struct cfg802154_registered_device *rdev,
- struct wpan_dev *wpan_dev, __le16 pan_id)
-{
- return rdev->ops->set_pan_id(&rdev->wpan_phy, wpan_dev, pan_id);
-}
-
-static inline int
-rdev_set_short_addr(struct cfg802154_registered_device *rdev,
- struct wpan_dev *wpan_dev, __le16 short_addr)
-{
- return rdev->ops->set_short_addr(&rdev->wpan_phy, wpan_dev, short_addr);
-}
-
-static inline int
-rdev_set_backoff_exponent(struct cfg802154_registered_device *rdev,
- struct wpan_dev *wpan_dev, u8 min_be, u8 max_be)
-{
- return rdev->ops->set_backoff_exponent(&rdev->wpan_phy, wpan_dev,
- min_be, max_be);
-}
-
-static inline int
-rdev_set_max_csma_backoffs(struct cfg802154_registered_device *rdev,
- struct wpan_dev *wpan_dev, u8 max_csma_backoffs)
-{
- return rdev->ops->set_max_csma_backoffs(&rdev->wpan_phy, wpan_dev,
- max_csma_backoffs);
-}
-
-static inline int
-rdev_set_max_frame_retries(struct cfg802154_registered_device *rdev,
- struct wpan_dev *wpan_dev, s8 max_frame_retries)
-{
- return rdev->ops->set_max_frame_retries(&rdev->wpan_phy, wpan_dev,
- max_frame_retries);
-}
-
-static inline int
-rdev_set_lbt_mode(struct cfg802154_registered_device *rdev,
- struct wpan_dev *wpan_dev, bool mode)
-{
- return rdev->ops->set_lbt_mode(&rdev->wpan_phy, wpan_dev, mode);
-}
-
-#endif /* __CFG802154_RDEV_OPS */
diff --git a/net/ieee802154/reassembly.c b/net/ieee802154/reassembly.c
index f133b62..4862bb5 100644
--- a/net/ieee802154/reassembly.c
+++ b/net/ieee802154/reassembly.c
@@ -33,7 +33,7 @@
static const char lowpan_frags_cache_name[] = "lowpan-frags";
struct lowpan_frag_info {
- u16 d_tag;
+ __be16 d_tag;
u16 d_size;
u8 d_offset;
};
@@ -48,7 +48,7 @@
static int lowpan_frag_reasm(struct lowpan_frag_queue *fq,
struct sk_buff *prev, struct net_device *dev);
-static unsigned int lowpan_hash_frag(u16 tag, u16 d_size,
+static unsigned int lowpan_hash_frag(__be16 tag, u16 d_size,
const struct ieee802154_addr *saddr,
const struct ieee802154_addr *daddr)
{
@@ -337,13 +337,11 @@
{
bool fail;
u8 pattern = 0, low = 0;
- __be16 d_tag = 0;
fail = lowpan_fetch_skb(skb, &pattern, 1);
fail |= lowpan_fetch_skb(skb, &low, 1);
frag_info->d_size = (pattern & 7) << 8 | low;
- fail |= lowpan_fetch_skb(skb, &d_tag, 2);
- frag_info->d_tag = ntohs(d_tag);
+ fail |= lowpan_fetch_skb(skb, &frag_info->d_tag, 2);
if (frag_type == LOWPAN_DISPATCH_FRAGN) {
fail |= lowpan_fetch_skb(skb, &frag_info->d_offset, 1);
diff --git a/net/ieee802154/reassembly.h b/net/ieee802154/reassembly.h
index 082e9d4..32797ac 100644
--- a/net/ieee802154/reassembly.h
+++ b/net/ieee802154/reassembly.h
@@ -5,7 +5,7 @@
#include <linux/spinlock.h>
struct lowpan_create_arg {
- u16 tag;
+ __be16 tag;
u16 d_size;
const struct ieee802154_addr *src;
const struct ieee802154_addr *dst;
@@ -16,7 +16,7 @@
struct lowpan_frag_queue {
struct inet_frag_queue q;
- u16 tag;
+ __be16 tag;
u16 d_size;
struct ieee802154_addr saddr;
struct ieee802154_addr daddr;
diff --git a/net/ieee802154/sysfs.c b/net/ieee802154/sysfs.c
deleted file mode 100644
index 2aec368..0000000
--- a/net/ieee802154/sysfs.c
+++ /dev/null
@@ -1,138 +0,0 @@
-/* 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.
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- *
- * Based on: net/wireless/sysfs.c
- */
-
-#include <linux/device.h>
-
-#include <net/cfg802154.h>
-
-#include "core.h"
-#include "sysfs.h"
-
-static inline struct cfg802154_registered_device *
-dev_to_rdev(struct device *dev)
-{
- return container_of(dev, struct cfg802154_registered_device,
- wpan_phy.dev);
-}
-
-#define SHOW_FMT(name, fmt, member) \
-static ssize_t name ## _show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- return sprintf(buf, fmt "\n", dev_to_rdev(dev)->member); \
-} \
-static DEVICE_ATTR_RO(name)
-
-SHOW_FMT(index, "%d", wpan_phy_idx);
-
-static ssize_t name_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct wpan_phy *wpan_phy = &dev_to_rdev(dev)->wpan_phy;
-
- return sprintf(buf, "%s\n", dev_name(&wpan_phy->dev));
-}
-static DEVICE_ATTR_RO(name);
-
-#define MASTER_SHOW_COMPLEX(name, format_string, args...) \
-static ssize_t name ## _show(struct device *dev, \
- struct device_attribute *attr, char *buf) \
-{ \
- struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev); \
- int ret; \
- \
- mutex_lock(&phy->pib_lock); \
- ret = snprintf(buf, PAGE_SIZE, format_string "\n", args); \
- mutex_unlock(&phy->pib_lock); \
- return ret; \
-} \
-static DEVICE_ATTR_RO(name)
-
-#define MASTER_SHOW(field, format_string) \
- MASTER_SHOW_COMPLEX(field, format_string, phy->field)
-
-MASTER_SHOW(current_channel, "%d");
-MASTER_SHOW(current_page, "%d");
-MASTER_SHOW(transmit_power, "%d +- 1 dB");
-MASTER_SHOW(cca_mode, "%d");
-
-static ssize_t channels_supported_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
- int ret;
- int i, len = 0;
-
- mutex_lock(&phy->pib_lock);
- for (i = 0; i < 32; i++) {
- ret = snprintf(buf + len, PAGE_SIZE - len,
- "%#09x\n", phy->channels_supported[i]);
- if (ret < 0)
- break;
- len += ret;
- }
- mutex_unlock(&phy->pib_lock);
- return len;
-}
-static DEVICE_ATTR_RO(channels_supported);
-
-static void wpan_phy_release(struct device *dev)
-{
- struct cfg802154_registered_device *rdev = dev_to_rdev(dev);
-
- cfg802154_dev_free(rdev);
-}
-
-static struct attribute *pmib_attrs[] = {
- &dev_attr_index.attr,
- &dev_attr_name.attr,
- /* below will be removed soon */
- &dev_attr_current_channel.attr,
- &dev_attr_current_page.attr,
- &dev_attr_channels_supported.attr,
- &dev_attr_transmit_power.attr,
- &dev_attr_cca_mode.attr,
- NULL,
-};
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
-ATTRIBUTE_GROUPS(pmib);
-#else
-#define BP_ATTR_GRP_STRUCT device_attribute
-ATTRIBUTE_GROUPS_BACKPORT(pmib);
-#endif
-
-struct class wpan_phy_class = {
- .name = "ieee802154",
- .dev_release = wpan_phy_release,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
- .dev_groups = pmib_groups,
-#else
- .dev_attrs = pmib_dev_attrs,
-#endif
-};
-
-int wpan_phy_sysfs_init(void)
-{
- init_pmib_attrs();
- return class_register(&wpan_phy_class);
-}
-
-void wpan_phy_sysfs_exit(void)
-{
- class_unregister(&wpan_phy_class);
-}
diff --git a/net/ieee802154/sysfs.h b/net/ieee802154/sysfs.h
deleted file mode 100644
index aa42e39..0000000
--- a/net/ieee802154/sysfs.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __IEEE802154_SYSFS_H
-#define __IEEE802154_SYSFS_H
-
-int wpan_phy_sysfs_init(void);
-void wpan_phy_sysfs_exit(void);
-
-extern struct class wpan_phy_class;
-
-#endif /* __IEEE802154_SYSFS_H */
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c
new file mode 100644
index 0000000..06ca147
--- /dev/null
+++ b/net/ieee802154/wpan-class.c
@@ -0,0 +1,240 @@
+/*
+ * Copyright (C) 2007, 2008, 2009 Siemens AG
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+
+#include <net/wpan-phy.h>
+
+#include "ieee802154.h"
+
+#define MASTER_SHOW_COMPLEX(name, format_string, args...) \
+static ssize_t name ## _show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev); \
+ int ret; \
+ \
+ mutex_lock(&phy->pib_lock); \
+ ret = snprintf(buf, PAGE_SIZE, format_string "\n", args); \
+ mutex_unlock(&phy->pib_lock); \
+ return ret; \
+} \
+static DEVICE_ATTR_RO(name);
+
+#define MASTER_SHOW(field, format_string) \
+ MASTER_SHOW_COMPLEX(field, format_string, phy->field)
+
+MASTER_SHOW(current_channel, "%d");
+MASTER_SHOW(current_page, "%d");
+MASTER_SHOW(transmit_power, "%d +- 1 dB");
+MASTER_SHOW(cca_mode, "%d");
+
+static ssize_t channels_supported_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
+ int ret;
+ int i, len = 0;
+
+ mutex_lock(&phy->pib_lock);
+ for (i = 0; i < 32; i++) {
+ ret = snprintf(buf + len, PAGE_SIZE - len,
+ "%#09x\n", phy->channels_supported[i]);
+ if (ret < 0)
+ break;
+ len += ret;
+ }
+ mutex_unlock(&phy->pib_lock);
+ return len;
+}
+static DEVICE_ATTR_RO(channels_supported);
+
+static struct attribute *pmib_attrs[] = {
+ &dev_attr_current_channel.attr,
+ &dev_attr_current_page.attr,
+ &dev_attr_channels_supported.attr,
+ &dev_attr_transmit_power.attr,
+ &dev_attr_cca_mode.attr,
+ NULL,
+};
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
+ATTRIBUTE_GROUPS(pmib);
+#else
+#define BP_ATTR_GRP_STRUCT device_attribute
+ATTRIBUTE_GROUPS_BACKPORT(pmib);
+#endif
+
+static void wpan_phy_release(struct device *d)
+{
+ struct wpan_phy *phy = container_of(d, struct wpan_phy, dev);
+
+ kfree(phy);
+}
+
+static struct class wpan_phy_class = {
+ .name = "ieee802154",
+ .dev_release = wpan_phy_release,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0)
+ .dev_groups = pmib_groups,
+#else
+ .dev_attrs = pmib_dev_attrs,
+#endif
+};
+
+static DEFINE_MUTEX(wpan_phy_mutex);
+static int wpan_phy_idx;
+
+static int wpan_phy_match(struct device *dev, const void *data)
+{
+ return !strcmp(dev_name(dev), (const char *)data);
+}
+
+struct wpan_phy *wpan_phy_find(const char *str)
+{
+ struct device *dev;
+
+ if (WARN_ON(!str))
+ return NULL;
+
+ dev = class_find_device(&wpan_phy_class, NULL, str, wpan_phy_match);
+ if (!dev)
+ return NULL;
+
+ return container_of(dev, struct wpan_phy, dev);
+}
+EXPORT_SYMBOL(wpan_phy_find);
+
+struct wpan_phy_iter_data {
+ int (*fn)(struct wpan_phy *phy, void *data);
+ void *data;
+};
+
+static int wpan_phy_iter(struct device *dev, void *_data)
+{
+ struct wpan_phy_iter_data *wpid = _data;
+ struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev);
+
+ return wpid->fn(phy, wpid->data);
+}
+
+int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data),
+ void *data)
+{
+ struct wpan_phy_iter_data wpid = {
+ .fn = fn,
+ .data = data,
+ };
+
+ return class_for_each_device(&wpan_phy_class, NULL,
+ &wpid, wpan_phy_iter);
+}
+EXPORT_SYMBOL(wpan_phy_for_each);
+
+static int wpan_phy_idx_valid(int idx)
+{
+ return idx >= 0;
+}
+
+struct wpan_phy *wpan_phy_alloc(size_t priv_size)
+{
+ struct wpan_phy *phy = kzalloc(sizeof(*phy) + priv_size,
+ GFP_KERNEL);
+
+ if (!phy)
+ goto out;
+ mutex_lock(&wpan_phy_mutex);
+ phy->idx = wpan_phy_idx++;
+ if (unlikely(!wpan_phy_idx_valid(phy->idx))) {
+ wpan_phy_idx--;
+ mutex_unlock(&wpan_phy_mutex);
+ kfree(phy);
+ goto out;
+ }
+ mutex_unlock(&wpan_phy_mutex);
+
+ mutex_init(&phy->pib_lock);
+
+ device_initialize(&phy->dev);
+ dev_set_name(&phy->dev, "wpan-phy%d", phy->idx);
+
+ phy->dev.class = &wpan_phy_class;
+
+ phy->current_channel = -1; /* not initialised */
+ phy->current_page = 0; /* for compatibility */
+
+ return phy;
+
+out:
+ return NULL;
+}
+EXPORT_SYMBOL(wpan_phy_alloc);
+
+int wpan_phy_register(struct wpan_phy *phy)
+{
+ return device_add(&phy->dev);
+}
+EXPORT_SYMBOL(wpan_phy_register);
+
+void wpan_phy_unregister(struct wpan_phy *phy)
+{
+ device_del(&phy->dev);
+}
+EXPORT_SYMBOL(wpan_phy_unregister);
+
+void wpan_phy_free(struct wpan_phy *phy)
+{
+ put_device(&phy->dev);
+}
+EXPORT_SYMBOL(wpan_phy_free);
+
+static int __init wpan_phy_class_init(void)
+{
+ int rc;
+
+ init_pmib_attrs();
+ rc = class_register(&wpan_phy_class);
+ if (rc)
+ goto err;
+
+ rc = ieee802154_nl_init();
+ if (rc)
+ goto err_nl;
+
+ return 0;
+err_nl:
+ class_unregister(&wpan_phy_class);
+err:
+ return rc;
+}
+subsys_initcall(wpan_phy_class_init);
+
+static void __exit wpan_phy_class_exit(void)
+{
+ ieee802154_nl_exit();
+ class_unregister(&wpan_phy_class);
+}
+module_exit(wpan_phy_class_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("IEEE 802.15.4 configuration interface");
+MODULE_AUTHOR("Dmitry Eremin-Solenikov");
+
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 543f13a..60677e1 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -5,9 +5,9 @@
depends on CRYPTO
depends on CRYPTO_ARC4
depends on CRYPTO_AES
- select BPAUTO_CRYPTO_CCM
+ select BACKPORT_CRYPTO_CCM
depends on CRC32
- select BPAUTO_AVERAGE
+ select BACKPORT_AVERAGE
---help---
This option enables the hardware independent IEEE 802.11
networking stack.
@@ -34,13 +34,6 @@
---help---
This option enables the 'minstrel_ht' TX rate control algorithm
-config MAC80211_RC_MINSTREL_VHT
- bool "Minstrel 802.11ac support" if EXPERT
- depends on MAC80211_RC_MINSTREL_HT
- default n
- ---help---
- This option enables VHT in the 'minstrel_ht' TX rate control algorithm
-
choice
prompt "Default rate control algorithm"
depends on MAC80211_HAS_RC
@@ -85,7 +78,7 @@
bool "Enable LED triggers"
depends on MAC80211
depends on LEDS_CLASS
- select BPAUTO_LEDS_TRIGGERS
+ select BACKPORT_LEDS_TRIGGERS
---help---
This option enables a few LED triggers for different
packet receive/transmit events.
@@ -177,17 +170,6 @@
Do not select this option.
-config MAC80211_OCB_DEBUG
- bool "Verbose OCB debugging"
- depends on MAC80211_DEBUG_MENU
- ---help---
- Selecting this option causes mac80211 to print out
- very verbose OCB debugging messages. It should not
- be selected on production systems as those messages
- are remotely triggerable.
-
- Do not select this option.
-
config MAC80211_IBSS_DEBUG
bool "Verbose IBSS debugging"
depends on MAC80211_DEBUG_MENU
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index c09aa25..285af62 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -27,8 +27,7 @@
event.o \
chan.o \
trace.o mlme.o \
- tdls.o \
- ocb.o
+ tdls.o
mac80211-$(CPTCFG_MAC80211_LEDS) += led.o
mac80211-$(CPTCFG_MAC80211_DEBUGFS) += \
diff --git a/net/mac80211/aes_ccm.c b/net/mac80211/aes_ccm.c
index 09d9caa..ec24378 100644
--- a/net/mac80211/aes_ccm.c
+++ b/net/mac80211/aes_ccm.c
@@ -53,9 +53,6 @@
__aligned(__alignof__(struct aead_request));
struct aead_request *aead_req = (void *) aead_req_data;
- if (data_len == 0)
- return -EINVAL;
-
memset(aead_req, 0, sizeof(aead_req_data));
sg_init_one(&pt, data, data_len);
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index a360c15..d6986f3 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -149,6 +149,11 @@
rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx);
}
+static inline int ieee80211_ac_from_tid(int tid)
+{
+ return ieee802_1d_to_ac[tid & 7];
+}
+
/*
* When multiple aggregation sessions on multiple stations
* are being created/destroyed simultaneously, we need to
@@ -509,10 +514,6 @@
struct tid_ampdu_tx *tid_tx;
int ret = 0;
- if (WARN(sta->reserved_tid == tid,
- "Requested to start BA session on reserved tid=%d", tid))
- return -EINVAL;
-
trace_api_start_tx_ba_session(pubsta, tid);
if (WARN_ON_ONCE(!local->ops->ampdu_action))
@@ -769,9 +770,6 @@
goto unlock;
}
- WARN(sta->reserved_tid == tid,
- "Requested to stop BA session on reserved tid=%d", tid);
-
if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
/* already in progress stopping it */
ret = 0;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a527ac3..a46ff74 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -20,7 +20,6 @@
#include "cfg.h"
#include "rate.h"
#include "mesh.h"
-#include "wme.h"
static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
const char *name,
@@ -191,7 +190,7 @@
* receive the key. When wpa_supplicant has roamed
* using FT, it attempts to set the key before
* association has completed, this rejects that attempt
- * so it will set the key again after association.
+ * so it will set the key again after assocation.
*
* TODO: accept the key if we have a station entry and
* add it to the device after the station.
@@ -230,7 +229,6 @@
case NUM_NL80211_IFTYPES:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_P2P_GO:
- case NL80211_IFTYPE_OCB:
/* shouldn't happen */
WARN_ON_ONCE(1);
break;
@@ -1042,13 +1040,6 @@
clear_sta_flag(sta, WLAN_STA_TDLS_PEER);
}
- /* mark TDLS channel switch support, if the AP allows it */
- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
- !sdata->u.mgd.tdls_chan_switch_prohibited &&
- params->ext_capab_len >= 4 &&
- params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)
- set_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH);
-
if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
sta->sta.uapsd_queues = params->uapsd_queues;
sta->sta.max_sp = params->max_sp;
@@ -1234,14 +1225,14 @@
}
static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
- struct station_del_parameters *params)
+ const u8 *mac)
{
struct ieee80211_sub_if_data *sdata;
sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- if (params->mac)
- return sta_info_destroy_addr_bss(sdata, params->mac);
+ if (mac)
+ return sta_info_destroy_addr_bss(sdata, mac);
sta_info_flush(sdata);
return 0;
@@ -1525,57 +1516,6 @@
return 0;
}
-static void mpp_set_pinfo(struct mesh_path *mpath, u8 *mpp,
- struct mpath_info *pinfo)
-{
- memset(pinfo, 0, sizeof(*pinfo));
- memcpy(mpp, mpath->mpp, ETH_ALEN);
-
- pinfo->generation = mpp_paths_generation;
-}
-
-static int ieee80211_get_mpp(struct wiphy *wiphy, struct net_device *dev,
- u8 *dst, u8 *mpp, struct mpath_info *pinfo)
-
-{
- struct ieee80211_sub_if_data *sdata;
- struct mesh_path *mpath;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- rcu_read_lock();
- mpath = mpp_path_lookup(sdata, dst);
- if (!mpath) {
- rcu_read_unlock();
- return -ENOENT;
- }
- memcpy(dst, mpath->dst, ETH_ALEN);
- mpp_set_pinfo(mpath, mpp, pinfo);
- rcu_read_unlock();
- return 0;
-}
-
-static int ieee80211_dump_mpp(struct wiphy *wiphy, struct net_device *dev,
- int idx, u8 *dst, u8 *mpp,
- struct mpath_info *pinfo)
-{
- struct ieee80211_sub_if_data *sdata;
- struct mesh_path *mpath;
-
- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
- rcu_read_lock();
- mpath = mpp_path_lookup_by_idx(sdata, idx);
- if (!mpath) {
- rcu_read_unlock();
- return -ENOENT;
- }
- memcpy(dst, mpath->dst, ETH_ALEN);
- mpp_set_pinfo(mpath, mpp, pinfo);
- rcu_read_unlock();
- return 0;
-}
-
static int ieee80211_get_mesh_config(struct wiphy *wiphy,
struct net_device *dev,
struct mesh_config *conf)
@@ -2026,17 +1966,6 @@
return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev));
}
-static int ieee80211_join_ocb(struct wiphy *wiphy, struct net_device *dev,
- struct ocb_setup *setup)
-{
- return ieee80211_ocb_join(IEEE80211_DEV_TO_SUB_IF(dev), setup);
-}
-
-static int ieee80211_leave_ocb(struct wiphy *wiphy, struct net_device *dev)
-{
- return ieee80211_ocb_leave(IEEE80211_DEV_TO_SUB_IF(dev));
-}
-
static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
int rate[IEEE80211_NUM_BANDS])
{
@@ -2152,9 +2081,6 @@
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
- if (local->ops->get_txpower)
- return drv_get_txpower(local, sdata, dbm);
-
if (!local->use_chanctx)
*dbm = local->hw.conf.power_level;
else
@@ -2924,7 +2850,11 @@
if (sdata->reserved_ready)
return 0;
- return ieee80211_vif_use_reserved_context(sdata);
+ err = ieee80211_vif_use_reserved_context(sdata);
+ if (err)
+ return err;
+
+ return 0;
}
if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
@@ -2938,6 +2868,7 @@
return err;
ieee80211_bss_info_change_notify(sdata, changed);
+ cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
if (sdata->csa_block_tx) {
ieee80211_wake_vif_queues(local, sdata,
@@ -2945,12 +2876,6 @@
sdata->csa_block_tx = false;
}
- err = drv_post_channel_switch(sdata);
- if (err)
- return err;
-
- cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
-
return 0;
}
@@ -3128,11 +3053,9 @@
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
- struct ieee80211_channel_switch ch_switch;
struct ieee80211_chanctx_conf *conf;
struct ieee80211_chanctx *chanctx;
- u32 changed = 0;
- int err;
+ int err, changed = 0;
sdata_assert_lock(sdata);
lockdep_assert_held(&local->mtx);
@@ -3165,16 +3088,6 @@
goto out;
}
- ch_switch.timestamp = 0;
- ch_switch.device_timestamp = 0;
- ch_switch.block_tx = params->block_tx;
- ch_switch.chandef = params->chandef;
- ch_switch.count = params->count;
-
- err = drv_pre_channel_switch(sdata, &ch_switch);
- if (err)
- goto out;
-
err = ieee80211_vif_reserve_chanctx(sdata, ¶ms->chandef,
chanctx->mode,
params->radar_required);
@@ -3202,9 +3115,6 @@
ieee80211_stop_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_CSA);
- cfg80211_ch_switch_started_notify(sdata->dev, &sdata->csa_chandef,
- params->count);
-
if (changed) {
ieee80211_bss_info_change_notify(sdata, changed);
drv_channel_switch_beacon(sdata, ¶ms->chandef);
@@ -3521,7 +3431,6 @@
info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
IEEE80211_TX_INTFL_NL80211_FRAME_TX;
- info->band = band;
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
skb->priority = 7;
@@ -3529,7 +3438,7 @@
nullfunc->qos_ctrl = cpu_to_le16(7);
local_bh_disable();
- ieee80211_xmit(sdata, skb);
+ ieee80211_xmit(sdata, skb, band);
local_bh_enable();
rcu_read_unlock();
@@ -3549,7 +3458,7 @@
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (chanctx_conf) {
- *chandef = sdata->vif.bss_conf.chandef;
+ *chandef = chanctx_conf->def;
ret = 0;
} else if (local->open_count > 0 &&
local->open_count == local->monitors &&
@@ -3612,76 +3521,6 @@
return ret;
}
-static int ieee80211_add_tx_ts(struct wiphy *wiphy, struct net_device *dev,
- u8 tsid, const u8 *peer, u8 up,
- u16 admitted_time)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- int ac = ieee802_1d_to_ac[up];
-
- if (sdata->vif.type != NL80211_IFTYPE_STATION)
- return -EOPNOTSUPP;
-
- if (!(sdata->wmm_acm & BIT(up)))
- return -EINVAL;
-
- if (ifmgd->tx_tspec[ac].admitted_time)
- return -EBUSY;
-
- if (admitted_time) {
- ifmgd->tx_tspec[ac].admitted_time = 32 * admitted_time;
- ifmgd->tx_tspec[ac].tsid = tsid;
- ifmgd->tx_tspec[ac].up = up;
- }
-
- return 0;
-}
-
-static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
- u8 tsid, const u8 *peer)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- struct ieee80211_local *local = wiphy_priv(wiphy);
- int ac;
-
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
-
- /* skip unused entries */
- if (!tx_tspec->admitted_time)
- continue;
-
- if (tx_tspec->tsid != tsid)
- continue;
-
- /* due to this new packets will be reassigned to non-ACM ACs */
- tx_tspec->up = -1;
-
- /* Make sure that all packets have been sent to avoid to
- * restore the QoS params on packets that are still on the
- * queues.
- */
- synchronize_net();
- ieee80211_flush_queues(local, sdata);
-
- /* restore the normal QoS parameters
- * (unconditionally to avoid races)
- */
- tx_tspec->action = TX_TSPEC_ACTION_STOP_DOWNGRADE;
- tx_tspec->downgraded = false;
- ieee80211_sta_handle_tspec_ac_params(sdata);
-
- /* finally clear all the data */
- memset(tx_tspec, 0, sizeof(*tx_tspec));
-
- return 0;
- }
-
- return -ENOENT;
-}
-
const struct cfg80211_ops mac80211_config_ops = {
.add_virtual_intf = ieee80211_add_iface,
.del_virtual_intf = ieee80211_del_iface,
@@ -3708,15 +3547,11 @@
.change_mpath = ieee80211_change_mpath,
.get_mpath = ieee80211_get_mpath,
.dump_mpath = ieee80211_dump_mpath,
- .get_mpp = ieee80211_get_mpp,
- .dump_mpp = ieee80211_dump_mpp,
.update_mesh_config = ieee80211_update_mesh_config,
.get_mesh_config = ieee80211_get_mesh_config,
.join_mesh = ieee80211_join_mesh,
.leave_mesh = ieee80211_leave_mesh,
#endif
- .join_ocb = ieee80211_join_ocb,
- .leave_ocb = ieee80211_leave_ocb,
.change_bss = ieee80211_change_bss,
.set_txq_params = ieee80211_set_txq_params,
.set_monitor_channel = ieee80211_set_monitor_channel,
@@ -3752,8 +3587,6 @@
.set_rekey_data = ieee80211_set_rekey_data,
.tdls_oper = ieee80211_tdls_oper,
.tdls_mgmt = ieee80211_tdls_mgmt,
- .tdls_channel_switch = ieee80211_tdls_channel_switch,
- .tdls_cancel_channel_switch = ieee80211_tdls_cancel_channel_switch,
.probe_client = ieee80211_probe_client,
.set_noack_map = ieee80211_set_noack_map,
#ifdef CONFIG_PM
@@ -3764,6 +3597,4 @@
.channel_switch = ieee80211_channel_switch,
.set_qos_map = ieee80211_set_qos_map,
.set_ap_chanwidth = ieee80211_set_ap_chanwidth,
- .add_tx_ts = ieee80211_add_tx_ts,
- .del_tx_ts = ieee80211_del_tx_ts,
};
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index da1c12c..4c74e8d 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -270,7 +270,6 @@
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MESH_POINT:
- case NL80211_IFTYPE_OCB:
width = vif->bss_conf.chandef.width;
break;
case NL80211_IFTYPE_UNSPECIFIED:
@@ -675,7 +674,6 @@
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_WDS:
case NL80211_IFTYPE_MESH_POINT:
- case NL80211_IFTYPE_OCB:
break;
default:
WARN_ON_ONCE(1);
@@ -911,7 +909,6 @@
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
- case NL80211_IFTYPE_OCB:
ieee80211_queue_work(&sdata->local->hw,
&sdata->csa_finalize_work);
break;
@@ -932,21 +929,6 @@
}
}
-static void
-ieee80211_vif_update_chandef(struct ieee80211_sub_if_data *sdata,
- const struct cfg80211_chan_def *chandef)
-{
- struct ieee80211_sub_if_data *vlan;
-
- sdata->vif.bss_conf.chandef = *chandef;
-
- if (sdata->vif.type != NL80211_IFTYPE_AP)
- return;
-
- list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
- vlan->vif.bss_conf.chandef = *chandef;
-}
-
static int
ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata)
{
@@ -1009,11 +991,7 @@
if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width)
changed = BSS_CHANGED_BANDWIDTH;
- ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef);
-
- ieee80211_recalc_smps_chanctx(local, new_ctx);
- ieee80211_recalc_radar_chanctx(local, new_ctx);
- ieee80211_recalc_chanctx_min_def(local, new_ctx);
+ sdata->vif.bss_conf.chandef = sdata->reserved_chandef;
if (changed)
ieee80211_bss_info_change_notify(sdata, changed);
@@ -1355,7 +1333,7 @@
sdata->reserved_chandef.width)
changed = BSS_CHANGED_BANDWIDTH;
- ieee80211_vif_update_chandef(sdata, &sdata->reserved_chandef);
+ sdata->vif.bss_conf.chandef = sdata->reserved_chandef;
if (changed)
ieee80211_bss_info_change_notify(sdata,
changed);
@@ -1526,7 +1504,7 @@
goto out;
}
- ieee80211_vif_update_chandef(sdata, chandef);
+ sdata->vif.bss_conf.chandef = *chandef;
ret = ieee80211_assign_vif_chanctx(sdata, ctx);
if (ret) {
@@ -1656,7 +1634,7 @@
}
break;
case IEEE80211_CHANCTX_WILL_BE_REPLACED:
- /* TODO: Perhaps the bandwidth change could be treated as a
+ /* TODO: Perhaps the bandwith change could be treated as a
* reservation itself? */
ret = -EBUSY;
goto out;
@@ -1668,7 +1646,7 @@
break;
}
- ieee80211_vif_update_chandef(sdata, chandef);
+ sdata->vif.bss_conf.chandef = *chandef;
ieee80211_recalc_chanctx_chantype(local, ctx);
diff --git a/net/mac80211/debug.h b/net/mac80211/debug.h
index c0ba105..ddbc904 100644
--- a/net/mac80211/debug.h
+++ b/net/mac80211/debug.h
@@ -2,12 +2,6 @@
#define __MAC80211_DEBUG_H
#include <net/cfg80211.h>
-#ifdef CPTCFG_MAC80211_OCB_DEBUG
-#define MAC80211_OCB_DEBUG 1
-#else
-#define MAC80211_OCB_DEBUG 0
-#endif
-
#ifdef CPTCFG_MAC80211_IBSS_DEBUG
#define MAC80211_IBSS_DEBUG 1
#else
@@ -137,10 +131,6 @@
_sdata_dbg(MAC80211_HT_DEBUG && net_ratelimit(), \
sdata, fmt, ##__VA_ARGS__)
-#define ocb_dbg(sdata, fmt, ...) \
- _sdata_dbg(MAC80211_OCB_DEBUG, \
- sdata, fmt, ##__VA_ARGS__)
-
#define ibss_dbg(sdata, fmt, ...) \
_sdata_dbg(MAC80211_IBSS_DEBUG, \
sdata, fmt, ##__VA_ARGS__)
diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c
index 5523b94..1521cab 100644
--- a/net/mac80211/debugfs_key.c
+++ b/net/mac80211/debugfs_key.c
@@ -300,8 +300,10 @@
lockdep_assert_held(&sdata->local->key_mtx);
- debugfs_remove(sdata->debugfs.default_unicast_key);
- sdata->debugfs.default_unicast_key = NULL;
+ if (sdata->debugfs.default_unicast_key) {
+ debugfs_remove(sdata->debugfs.default_unicast_key);
+ sdata->debugfs.default_unicast_key = NULL;
+ }
if (sdata->default_unicast_key) {
key = key_mtx_dereference(sdata->local,
@@ -312,8 +314,10 @@
sdata->vif.debugfs_dir, buf);
}
- debugfs_remove(sdata->debugfs.default_multicast_key);
- sdata->debugfs.default_multicast_key = NULL;
+ if (sdata->debugfs.default_multicast_key) {
+ debugfs_remove(sdata->debugfs.default_multicast_key);
+ sdata->debugfs.default_multicast_key = NULL;
+ }
if (sdata->default_multicast_key) {
key = key_mtx_dereference(sdata->local,
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 94c7009..bafe489 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -74,7 +74,7 @@
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%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),
@@ -82,11 +82,10 @@
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_INITIATOR),
- TEST(TDLS_CHAN_SWITCH), TEST(TDLS_OFF_CHANNEL),
- TEST(4ADDR_EVENT), TEST(INSERTED),
- TEST(RATE_CONTROL), TEST(TOFFSET_KNOWN),
- TEST(MPSP_OWNER), TEST(MPSP_RECIPIENT));
+ TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
+ TEST(INSERTED), TEST(RATE_CONTROL),
+ TEST(TOFFSET_KNOWN), TEST(MPSP_OWNER),
+ TEST(MPSP_RECIPIENT));
#undef TEST
return simple_read_from_buffer(userbuf, count, ppos, buf, res);
}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 754c893..6da526b 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -214,8 +214,7 @@
BSS_CHANGED_BEACON_ENABLED) &&
sdata->vif.type != NL80211_IFTYPE_AP &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
- sdata->vif.type != NL80211_IFTYPE_MESH_POINT &&
- sdata->vif.type != NL80211_IFTYPE_OCB))
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT))
return;
if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE ||
@@ -380,26 +379,23 @@
return ret;
}
-static inline void drv_sw_scan_start(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- const u8 *mac_addr)
+static inline void drv_sw_scan_start(struct ieee80211_local *local)
{
might_sleep();
- trace_drv_sw_scan_start(local, sdata, mac_addr);
+ trace_drv_sw_scan_start(local);
if (local->ops->sw_scan_start)
- local->ops->sw_scan_start(&local->hw, &sdata->vif, mac_addr);
+ local->ops->sw_scan_start(&local->hw);
trace_drv_return_void(local);
}
-static inline void drv_sw_scan_complete(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata)
+static inline void drv_sw_scan_complete(struct ieee80211_local *local)
{
might_sleep();
- trace_drv_sw_scan_complete(local, sdata);
+ trace_drv_sw_scan_complete(local);
if (local->ops->sw_scan_complete)
- local->ops->sw_scan_complete(&local->hw, &sdata->vif);
+ local->ops->sw_scan_complete(&local->hw);
trace_drv_return_void(local);
}
@@ -624,21 +620,6 @@
trace_drv_return_void(local);
}
-static inline void drv_sta_rate_tbl_update(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta)
-{
- sdata = get_bss_sdata(sdata);
- if (!check_sdata_in_driver(sdata))
- return;
-
- trace_drv_sta_rate_tbl_update(local, sdata, sta);
- if (local->ops->sta_rate_tbl_update)
- local->ops->sta_rate_tbl_update(&local->hw, &sdata->vif, sta);
-
- trace_drv_return_void(local);
-}
-
static inline int drv_conf_tx(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata, u16 ac,
const struct ieee80211_tx_queue_params *params)
@@ -650,12 +631,6 @@
if (!check_sdata_in_driver(sdata))
return -EIO;
- if (WARN_ONCE(params->cw_min == 0 ||
- params->cw_min > params->cw_max,
- "%s: invalid CW_min/CW_max: %d/%d\n",
- sdata->name, params->cw_min, params->cw_max))
- return -EINVAL;
-
trace_drv_conf_tx(local, sdata, ac, params);
if (local->ops->conf_tx)
ret = local->ops->conf_tx(&local->hw, &sdata->vif,
@@ -789,13 +764,12 @@
}
static inline void drv_channel_switch(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_channel_switch *ch_switch)
+ struct ieee80211_channel_switch *ch_switch)
{
might_sleep();
- trace_drv_channel_switch(local, sdata, ch_switch);
- local->ops->channel_switch(&local->hw, &sdata->vif, ch_switch);
+ trace_drv_channel_switch(local, ch_switch);
+ local->ops->channel_switch(&local->hw, ch_switch);
trace_drv_return_void(local);
}
@@ -1170,15 +1144,13 @@
trace_drv_return_void(local);
}
-static inline void
-drv_reconfig_complete(struct ieee80211_local *local,
- enum ieee80211_reconfig_type reconfig_type)
+static inline void drv_restart_complete(struct ieee80211_local *local)
{
might_sleep();
- trace_drv_reconfig_complete(local, reconfig_type);
- if (local->ops->reconfig_complete)
- local->ops->reconfig_complete(&local->hw, reconfig_type);
+ trace_drv_restart_complete(local);
+ if (local->ops->restart_complete)
+ local->ops->restart_complete(&local->hw);
trace_drv_return_void(local);
}
@@ -1224,40 +1196,6 @@
}
}
-static inline int
-drv_pre_channel_switch(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_channel_switch *ch_switch)
-{
- struct ieee80211_local *local = sdata->local;
- int ret = 0;
-
- if (!check_sdata_in_driver(sdata))
- return -EIO;
-
- trace_drv_pre_channel_switch(local, sdata, ch_switch);
- if (local->ops->pre_channel_switch)
- ret = local->ops->pre_channel_switch(&local->hw, &sdata->vif,
- ch_switch);
- trace_drv_return_int(local, ret);
- return ret;
-}
-
-static inline int
-drv_post_channel_switch(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_local *local = sdata->local;
- int ret = 0;
-
- if (!check_sdata_in_driver(sdata))
- return -EIO;
-
- trace_drv_post_channel_switch(local, sdata);
- if (local->ops->post_channel_switch)
- ret = local->ops->post_channel_switch(&local->hw, &sdata->vif);
- trace_drv_return_int(local, ret);
- return ret;
-}
-
static inline int drv_join_ibss(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
@@ -1300,71 +1238,4 @@
return ret;
}
-static inline int drv_get_txpower(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata, int *dbm)
-{
- int ret;
-
- if (!local->ops->get_txpower)
- return -EOPNOTSUPP;
-
- ret = local->ops->get_txpower(&local->hw, &sdata->vif, dbm);
- trace_drv_get_txpower(local, sdata, *dbm, ret);
-
- return ret;
-}
-
-static inline int
-drv_tdls_channel_switch(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta, u8 oper_class,
- struct cfg80211_chan_def *chandef,
- struct sk_buff *tmpl_skb, u32 ch_sw_tm_ie)
-{
- int ret;
-
- might_sleep();
- if (!check_sdata_in_driver(sdata))
- return -EIO;
-
- if (!local->ops->tdls_channel_switch)
- return -EOPNOTSUPP;
-
- trace_drv_tdls_channel_switch(local, sdata, sta, oper_class, chandef);
- ret = local->ops->tdls_channel_switch(&local->hw, &sdata->vif, sta,
- oper_class, chandef, tmpl_skb,
- ch_sw_tm_ie);
- trace_drv_return_int(local, ret);
- return ret;
-}
-
-static inline void
-drv_tdls_cancel_channel_switch(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta)
-{
- might_sleep();
- if (!check_sdata_in_driver(sdata))
- return;
-
- if (!local->ops->tdls_cancel_channel_switch)
- return;
-
- trace_drv_tdls_cancel_channel_switch(local, sdata, sta);
- local->ops->tdls_cancel_channel_switch(&local->hw, &sdata->vif, sta);
- trace_drv_return_void(local);
-}
-
-static inline void
-drv_tdls_recv_channel_switch(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_tdls_ch_sw_params *params)
-{
- trace_drv_tdls_recv_channel_switch(local, sdata, params);
- if (local->ops->tdls_recv_channel_switch)
- local->ops->tdls_recv_channel_switch(&local->hw, &sdata->vif,
- params);
- trace_drv_return_void(local);
-}
-
#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 509bc15..56b5357 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -805,7 +805,7 @@
memset(¶ms, 0, sizeof(params));
memset(&csa_ie, 0, sizeof(csa_ie));
- err = ieee80211_parse_ch_switch_ie(sdata, elems,
+ err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon,
ifibss->chandef.chan->band,
sta_flags, ifibss->bssid, &csa_ie);
/* can't switch to destination channel, fail */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f08f4b9..a02fa58 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -131,7 +131,7 @@
*
* These are bss flags that are attached to a bss in the
* @valid_data field of &struct ieee80211_bss. They show which parts
- * of the data structure were received as a result of an un-corrupted
+ * of the data structure were recieved as a result of an un-corrupted
* beacon/probe response.
*/
enum ieee80211_bss_valid_data_flags {
@@ -399,24 +399,6 @@
u8 ie[];
};
-struct ieee80211_sta_tx_tspec {
- /* timestamp of the first packet in the time slice */
- unsigned long time_slice_start;
-
- u32 admitted_time; /* in usecs, unlike over the air */
- u8 tsid;
- s8 up; /* signed to be able to invalidate with -1 during teardown */
-
- /* consumed TX time in microseconds in the time slice */
- u32 consumed_tx_time;
- enum {
- TX_TSPEC_ACTION_NONE = 0,
- TX_TSPEC_ACTION_DOWNGRADE,
- TX_TSPEC_ACTION_STOP_DOWNGRADE,
- } action;
- bool downgraded;
-};
-
struct ieee80211_if_managed {
struct timer_list timer;
struct timer_list conn_mon_timer;
@@ -452,8 +434,6 @@
unsigned int flags;
- bool csa_waiting_bcn;
-
bool beacon_crc_valid;
u32 beacon_crc;
@@ -525,23 +505,8 @@
struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */
struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */
- /* TDLS support */
u8 tdls_peer[ETH_ALEN] __aligned(2);
struct delayed_work tdls_peer_del_work;
- struct sk_buff *orig_teardown_skb; /* The original teardown skb */
- struct sk_buff *teardown_skb; /* A copy to send through the AP */
- spinlock_t teardown_lock; /* To lock changing teardown_skb */
- bool tdls_chan_switch_prohibited;
-
- /* WMM-AC TSPEC support */
- struct ieee80211_sta_tx_tspec tx_tspec[IEEE80211_NUM_ACS];
- /* Use a separate work struct so that we can do something here
- * while the sdata->work is flushing the queues, for example.
- * otherwise, in scenarios where we hardly get any traffic out
- * on the BE queue, but there's a lot of VO traffic, we might
- * get stuck in a downgraded situation and flush takes forever.
- */
- struct delayed_work tx_tspec_wk;
};
struct ieee80211_if_ibss {
@@ -582,25 +547,6 @@
};
/**
- * struct ieee80211_if_ocb - OCB mode state
- *
- * @housekeeping_timer: timer for periodic invocation of a housekeeping task
- * @wrkq_flags: OCB deferred task action
- * @incomplete_lock: delayed STA insertion lock
- * @incomplete_stations: list of STAs waiting for delayed insertion
- * @joined: indication if the interface is connected to an OCB network
- */
-struct ieee80211_if_ocb {
- struct timer_list housekeeping_timer;
- unsigned long wrkq_flags;
-
- spinlock_t incomplete_lock;
- struct list_head incomplete_stations;
-
- bool joined;
-};
-
-/**
* struct ieee80211_mesh_sync_ops - Extensible synchronization framework interface
*
* these declarations define the interface, which enables
@@ -893,7 +839,6 @@
struct ieee80211_if_managed mgd;
struct ieee80211_if_ibss ibss;
struct ieee80211_if_mesh mesh;
- struct ieee80211_if_ocb ocb;
u32 mntr_flags;
} u;
@@ -993,7 +938,6 @@
IEEE80211_SDATA_QUEUE_AGG_STOP = 2,
IEEE80211_SDATA_QUEUE_RX_AGG_START = 3,
IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4,
- IEEE80211_SDATA_QUEUE_TDLS_CHSW = 5,
};
enum {
@@ -1011,7 +955,6 @@
IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL,
IEEE80211_QUEUE_STOP_REASON_FLUSH,
IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN,
- IEEE80211_QUEUE_STOP_REASON_RESERVE_TID,
IEEE80211_QUEUE_STOP_REASONS,
};
@@ -1238,7 +1181,7 @@
unsigned long scanning;
struct cfg80211_ssid scan_ssid;
struct cfg80211_scan_request *int_scan_req;
- struct cfg80211_scan_request __rcu *scan_req;
+ struct cfg80211_scan_request *scan_req;
struct ieee80211_scan_request *hw_scan_req;
struct cfg80211_chan_def scan_chandef;
enum ieee80211_band hw_scan_band;
@@ -1248,8 +1191,7 @@
struct work_struct sched_scan_stopped_work;
struct ieee80211_sub_if_data __rcu *sched_scan_sdata;
- struct cfg80211_sched_scan_request __rcu *sched_scan_req;
- u8 scan_addr[ETH_ALEN];
+ struct cfg80211_sched_scan_request *sched_scan_req;
unsigned long leave_oper_channel_time;
enum mac80211_scan_state next_scan_state;
@@ -1368,9 +1310,6 @@
/* virtual monitor interface */
struct ieee80211_sub_if_data __rcu *monitor_sdata;
struct cfg80211_chan_def monitor_chandef;
-
- /* extended capabilities provided by mac80211 */
- u8 ext_capa[8];
};
static inline struct ieee80211_sub_if_data *
@@ -1406,9 +1345,6 @@
size_t total_len;
/* pointers to IEs */
- const struct ieee80211_tdls_lnkie *lnk_id;
- const struct ieee80211_ch_switch_timing *ch_sw_timing;
- const u8 *ext_capab;
const u8 *ssid;
const u8 *supp_rates;
const u8 *ds_params;
@@ -1443,7 +1379,6 @@
const struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie;
/* length of them, respectively */
- u8 ext_capab_len;
u8 ssid_len;
u8 supp_rates_len;
u8 tim_len;
@@ -1522,7 +1457,6 @@
__le16 fc, bool acked);
void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
-void ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata);
/* IBSS code */
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
@@ -1540,15 +1474,6 @@
int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata);
-/* OCB code */
-void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata);
-void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
- const u8 *bssid, const u8 *addr, u32 supp_rates);
-void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata);
-int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
- struct ocb_setup *setup);
-int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata);
-
/* mesh code */
void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata);
void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
@@ -1640,14 +1565,8 @@
struct net_device *dev);
netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
struct net_device *dev);
-void __ieee80211_subif_start_xmit(struct sk_buff *skb,
- struct net_device *dev,
- u32 info_flags);
void ieee80211_purge_tx_queue(struct ieee80211_hw *hw,
struct sk_buff_head *skbs);
-struct sk_buff *
-ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, u32 info_flags);
/* HT */
void ieee80211_apply_htcap_overrides(struct ieee80211_sub_if_data *sdata,
@@ -1726,6 +1645,7 @@
* ieee80211_parse_ch_switch_ie - parses channel switch IEs
* @sdata: the sdata of the interface which has received the frame
* @elems: parsed 802.11 elements received with the frame
+ * @beacon: indicates if the frame was a beacon or probe response
* @current_band: indicates the current band
* @sta_flags: contains information about own capabilities and restrictions
* to decide which channel switch announcements can be accepted. Only the
@@ -1739,7 +1659,7 @@
* Return: 0 on success, <0 on error and >0 if there is nothing to parse.
*/
int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
- struct ieee802_11_elems *elems,
+ struct ieee802_11_elems *elems, bool beacon,
enum ieee80211_band current_band,
u32 sta_flags, u8 *bssid,
struct ieee80211_csa_ie *csa_ie);
@@ -1774,7 +1694,8 @@
gfp_t gfp);
void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
bool bss_notify);
-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
+ enum ieee80211_band band);
void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, int tid,
@@ -1840,13 +1761,6 @@
return true;
}
-extern const int ieee802_1d_to_ac[8];
-
-static inline int ieee80211_ac_from_tid(int tid)
-{
- return ieee802_1d_to_ac[tid & 7];
-}
-
void ieee80211_dynamic_ps_enable_work(struct work_struct *work);
void ieee80211_dynamic_ps_disable_work(struct work_struct *work);
void ieee80211_dynamic_ps_timer(unsigned long data);
@@ -1856,7 +1770,7 @@
void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
struct ieee80211_hdr *hdr);
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
+ struct ieee80211_hdr *hdr, bool ack);
void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
unsigned long queues,
@@ -1885,9 +1799,6 @@
struct sk_buff_head *skbs);
void ieee80211_flush_queues(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
-void __ieee80211_flush_queues(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- unsigned int queues);
void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
u16 transaction, u16 auth_alg, u16 status,
@@ -1904,14 +1815,12 @@
u8 bands_used, u32 *rate_masks,
struct cfg80211_chan_def *chandef);
struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
- const u8 *src, const u8 *dst,
- u32 ratemask,
+ u8 *dst, u32 ratemask,
struct ieee80211_channel *chan,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len,
bool directed);
-void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
- const u8 *src, const u8 *dst,
+void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len,
u32 ratemask, bool directed, u32 tx_flags,
@@ -1927,10 +1836,8 @@
void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata);
void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata);
-size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
- const u8 *ids, int n_ids,
- const u8 *after_ric, int n_after_ric,
- size_t offset);
+size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
+ const u8 *ids, int n_ids, size_t offset);
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset);
u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
u16 cap);
@@ -2017,14 +1924,6 @@
int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
const u8 *peer, enum nl80211_tdls_operation oper);
void ieee80211_tdls_peer_del_work(struct work_struct *wk);
-int ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
- const u8 *addr, u8 oper_class,
- struct cfg80211_chan_def *chandef);
-void ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
- struct net_device *dev,
- const u8 *addr);
-void ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb);
extern const struct ethtool_ops ieee80211_ethtool_ops;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index f7c759a..b7402fe 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -259,15 +259,6 @@
list_for_each_entry(nsdata, &local->interfaces, list) {
if (nsdata != sdata && ieee80211_sdata_running(nsdata)) {
/*
- * Only OCB and monitor mode may coexist
- */
- if ((sdata->vif.type == NL80211_IFTYPE_OCB &&
- nsdata->vif.type != NL80211_IFTYPE_MONITOR) ||
- (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
- nsdata->vif.type == NL80211_IFTYPE_OCB))
- return -EBUSY;
-
- /*
* Allow only a single IBSS interface to be up at any
* time. This is restricted because beacon distribution
* cannot work properly if both are in the same IBSS.
@@ -520,7 +511,6 @@
sdata->vif.cab_queue = master->vif.cab_queue;
memcpy(sdata->vif.hw_queue, master->vif.hw_queue,
sizeof(sdata->vif.hw_queue));
- sdata->vif.bss_conf.chandef = master->vif.bss_conf.chandef;
break;
}
case NL80211_IFTYPE_AP:
@@ -531,7 +521,6 @@
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_P2P_DEVICE:
- case NL80211_IFTYPE_OCB:
/* no special treatment */
break;
case NL80211_IFTYPE_UNSPECIFIED:
@@ -642,7 +631,6 @@
case NL80211_IFTYPE_ADHOC:
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_MESH_POINT:
- case NL80211_IFTYPE_OCB:
netif_carrier_off(dev);
break;
case NL80211_IFTYPE_WDS:
@@ -778,12 +766,10 @@
int i, flushed;
struct ps_data *ps;
struct cfg80211_chan_def chandef;
- bool cancel_scan;
clear_bit(SDATA_STATE_RUNNING, &sdata->state);
- cancel_scan = rcu_access_pointer(local->scan_sdata) == sdata;
- if (cancel_scan)
+ if (rcu_access_pointer(local->scan_sdata) == sdata)
ieee80211_scan_cancel(local);
/*
@@ -856,8 +842,6 @@
sdata_lock(sdata);
mutex_lock(&local->mtx);
sdata->vif.csa_active = false;
- if (sdata->vif.type == NL80211_IFTYPE_STATION)
- sdata->u.mgd.csa_waiting_bcn = false;
if (sdata->csa_block_tx) {
ieee80211_wake_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -914,8 +898,6 @@
list_del(&sdata->u.vlan.list);
mutex_unlock(&local->mtx);
RCU_INIT_POINTER(sdata->vif.chanctx_conf, NULL);
- /* see comment in the default case below */
- ieee80211_free_keys(sdata, true);
/* no need to tell driver */
break;
case NL80211_IFTYPE_MONITOR:
@@ -941,16 +923,17 @@
/*
* When we get here, the interface is marked down.
* Free the remaining keys, if there are any
- * (which can happen in AP mode if userspace sets
- * keys before the interface is operating, and maybe
- * also in WDS mode)
+ * (shouldn't be, except maybe in WDS mode?)
*
* Force the key freeing to always synchronize_net()
* to wait for the RX path in case it is using this
- * interface enqueuing frames at this very time on
+ * interface enqueuing frames * at this very time on
* another CPU.
*/
ieee80211_free_keys(sdata, true);
+
+ /* fall through */
+ case NL80211_IFTYPE_AP:
skb_queue_purge(&sdata->skb_queue);
}
@@ -1008,9 +991,6 @@
ieee80211_recalc_ps(local, -1);
- if (cancel_scan)
- flush_delayed_work(&local->scan_work);
-
if (local->open_count == 0) {
ieee80211_stop_device(local);
@@ -1229,8 +1209,6 @@
WLAN_BACK_RECIPIENT, 0,
false);
mutex_unlock(&local->sta_mtx);
- } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_TDLS_CHSW) {
- ieee80211_process_tdls_channel_switch(sdata, skb);
} else if (ieee80211_is_action(mgmt->frame_control) &&
mgmt->u.action.category == WLAN_CATEGORY_BACK) {
int len = skb->len;
@@ -1321,9 +1299,6 @@
break;
ieee80211_mesh_work(sdata);
break;
- case NL80211_IFTYPE_OCB:
- ieee80211_ocb_work(sdata);
- break;
default:
break;
}
@@ -1343,9 +1318,6 @@
static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
enum nl80211_iftype type)
{
- static const u8 bssid_wildcard[ETH_ALEN] = {0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff};
-
/* clear type-dependent union */
memset(&sdata->u, 0, sizeof(sdata->u));
@@ -1397,10 +1369,6 @@
sdata->vif.bss_conf.bssid = sdata->u.mgd.bssid;
ieee80211_sta_setup_sdata(sdata);
break;
- case NL80211_IFTYPE_OCB:
- sdata->vif.bss_conf.bssid = bssid_wildcard;
- ieee80211_ocb_setup_sdata(sdata);
- break;
case NL80211_IFTYPE_ADHOC:
sdata->vif.bss_conf.bssid = sdata->u.ibss.bssid;
ieee80211_ibss_setup_sdata(sdata);
@@ -1448,7 +1416,6 @@
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_OCB:
/*
* Could maybe also all others here?
* Just not sure how that interacts
@@ -1464,7 +1431,6 @@
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_ADHOC:
- case NL80211_IFTYPE_OCB:
/*
* Could probably support everything
* but WDS here (WDS do_open can fail
@@ -1723,10 +1689,7 @@
}
ieee80211_assign_perm_addr(local, ndev->perm_addr, type);
- if (params && is_valid_ether_addr(params->macaddr))
- memcpy(ndev->dev_addr, params->macaddr, ETH_ALEN);
- else
- memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
+ memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN);
SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
/* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 0bb7038..4712150 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -94,17 +94,8 @@
might_sleep();
- if (key->flags & KEY_FLAG_TAINTED) {
- /* If we get here, it's during resume and the key is
- * tainted so shouldn't be used/programmed any more.
- * However, its flags may still indicate that it was
- * programmed into the device (since we're in resume)
- * so clear that flag now to avoid trying to remove
- * it again later.
- */
- key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
+ if (key->flags & KEY_FLAG_TAINTED)
return -EINVAL;
- }
if (!key->local->ops->set_key)
goto out_unsupported;
@@ -656,7 +647,7 @@
int i;
mutex_lock(&local->key_mtx);
- for (i = 0; i < ARRAY_SIZE(sta->gtk); i++) {
+ for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
key = key_mtx_dereference(local, sta->gtk[i]);
if (!key)
continue;
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 8c5a3cf..bc8ae88 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -478,9 +478,13 @@
},
};
-struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
- const struct ieee80211_ops *ops,
- const char *requested_name)
+static const u8 extended_capabilities[] = {
+ 0, 0, 0, 0, 0, 0, 0,
+ WLAN_EXT_CAPA8_OPMODE_NOTIF,
+};
+
+struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len,
+ const struct ieee80211_ops *ops)
{
struct ieee80211_local *local;
int priv_size, i;
@@ -520,7 +524,7 @@
*/
priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
- wiphy = wiphy_new_nm(&mac80211_config_ops, priv_size, requested_name);
+ wiphy = wiphy_new(&mac80211_config_ops, priv_size);
if (!wiphy)
return NULL;
@@ -535,6 +539,10 @@
WIPHY_FLAG_REPORTS_OBSS |
WIPHY_FLAG_OFFCHAN_TX;
+ wiphy->extended_capabilities = extended_capabilities;
+ wiphy->extended_capabilities_mask = extended_capabilities;
+ wiphy->extended_capabilities_len = ARRAY_SIZE(extended_capabilities);
+
if (ops->remain_on_channel)
wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
@@ -542,7 +550,6 @@
NL80211_FEATURE_SAE |
NL80211_FEATURE_HT_IBSS |
NL80211_FEATURE_VIF_TXPOWER |
- NL80211_FEATURE_MAC_ON_CREATE |
NL80211_FEATURE_USERSPACE_MPM;
if (!ops->hw_scan)
@@ -584,13 +591,6 @@
wiphy->ht_capa_mod_mask = &mac80211_ht_capa_mod_mask;
wiphy->vht_capa_mod_mask = &mac80211_vht_capa_mod_mask;
- local->ext_capa[7] = WLAN_EXT_CAPA8_OPMODE_NOTIF;
-
- wiphy->extended_capabilities = local->ext_capa;
- wiphy->extended_capabilities_mask = local->ext_capa;
- wiphy->extended_capabilities_len =
- ARRAY_SIZE(local->ext_capa);
-
INIT_LIST_HEAD(&local->interfaces);
__hw_addr_init(&local->mc_list);
@@ -651,7 +651,7 @@
return &local->hw;
}
-EXPORT_SYMBOL(ieee80211_alloc_hw_nm);
+EXPORT_SYMBOL(ieee80211_alloc_hw);
static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
{
@@ -764,12 +764,6 @@
local->hw.offchannel_tx_hw_queue >= local->hw.queues))
return -EINVAL;
- if ((hw->wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) &&
- (!local->ops->tdls_channel_switch ||
- !local->ops->tdls_cancel_channel_switch ||
- !local->ops->tdls_recv_channel_switch))
- return -EOPNOTSUPP;
-
#ifdef CONFIG_PM
if (hw->wiphy->wowlan && (!local->ops->suspend || !local->ops->resume))
return -EINVAL;
@@ -793,14 +787,13 @@
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_WDS))
return -EINVAL;
- /* DFS is not supported with multi-channel combinations yet */
+ /* DFS currently not supported with channel context drivers */
for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
const struct ieee80211_iface_combination *comb;
comb = &local->hw.wiphy->iface_combinations[i];
- if (comb->radar_detect_widths &&
- comb->num_different_channels > 1)
+ if (comb->radar_detect_widths)
return -EINVAL;
}
}
@@ -965,10 +958,6 @@
if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
- /* mac80211 supports eCSA, if the driver supports STA CSA at all */
- if (local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)
- local->ext_capa[0] |= WLAN_EXT_CAPA1_EXT_CHANNEL_SWITCHING;
-
local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
result = wiphy_register(local->hw.wiphy);
@@ -1030,8 +1019,7 @@
}
/* add one default STA interface if supported */
- if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION) &&
- !(hw->flags & IEEE80211_HW_NO_AUTO_VIF)) {
+ if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
result = ieee80211_if_add(local, "wlan%d", NULL,
NL80211_IFTYPE_STATION, NULL);
if (result)
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 0c8b2a7..e9f99c1 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -874,7 +874,7 @@
memset(¶ms, 0, sizeof(params));
memset(&csa_ie, 0, sizeof(csa_ie));
- err = ieee80211_parse_ch_switch_ie(sdata, elems, band,
+ err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band,
sta_flags, sdata->vif.addr,
&csa_ie);
if (err < 0)
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index b718db3..af9cb55 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -270,8 +270,6 @@
const u8 *dst, const u8 *mpp);
struct mesh_path *
mesh_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx);
-struct mesh_path *
-mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx);
void mesh_path_fix_nexthop(struct mesh_path *mpath, struct sta_info *next_hop);
void mesh_path_expire(struct ieee80211_sub_if_data *sdata);
void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
@@ -319,7 +317,6 @@
bool mesh_action_is_path_sel(struct ieee80211_mgmt *mgmt);
extern int mesh_paths_generation;
-extern int mpp_paths_generation;
#ifdef CPTCFG_MAC80211_MESH
static inline
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c
index b890e22..a6699dc 100644
--- a/net/mac80211/mesh_pathtbl.c
+++ b/net/mac80211/mesh_pathtbl.c
@@ -44,7 +44,6 @@
static struct mesh_table __rcu *mpp_paths; /* Store paths for MPP&MAP */
int mesh_paths_generation;
-int mpp_paths_generation;
/* This lock will have the grow table function as writer and add / delete nodes
* as readers. RCU provides sufficient protection only when reading the table
@@ -411,33 +410,6 @@
}
/**
- * mpp_path_lookup_by_idx - look up a path in the proxy path table by its index
- * @idx: index
- * @sdata: local subif, or NULL for all entries
- *
- * Returns: pointer to the proxy path structure, or NULL if not found.
- *
- * Locking: must be called within a read rcu section.
- */
-struct mesh_path *
-mpp_path_lookup_by_idx(struct ieee80211_sub_if_data *sdata, int idx)
-{
- struct mesh_table *tbl = rcu_dereference(mpp_paths);
- struct mpath_node *node;
- int i;
- int j = 0;
-
- for_each_mesh_entry(tbl, node, i) {
- if (sdata && node->mpath->sdata != sdata)
- continue;
- if (j++ == idx)
- return node->mpath;
- }
-
- return NULL;
-}
-
-/**
* mesh_path_add_gate - add the given mpath to a mesh gate to our path table
* @mpath: gate path to add to table
*/
@@ -719,9 +691,6 @@
spin_unlock(&tbl->hashwlock[hash_idx]);
read_unlock_bh(&pathtbl_resize_lock);
-
- mpp_paths_generation++;
-
if (grow) {
set_bit(MESH_WORK_GROW_MPP_TABLE, &ifmsh->wrkq_flags);
ieee80211_queue_work(&local->hw, &sdata->work);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2c36c47..2de8870 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -174,7 +174,6 @@
if (!(ht_cap->cap_info &
cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40))) {
ret = IEEE80211_STA_DISABLE_40MHZ;
- vht_chandef = *chandef;
goto out;
}
@@ -553,17 +552,13 @@
cap = vht_cap.cap;
if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_80P80MHZ) {
- u32 bw = cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
-
- cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
- if (bw == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ||
- bw == IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
- cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ;
+ cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
}
if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_160MHZ) {
cap &= ~IEEE80211_VHT_CAP_SHORT_GI_160;
- cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
+ cap &= ~IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
}
/*
@@ -780,30 +775,11 @@
WLAN_EID_QOS_CAPA,
WLAN_EID_RRM_ENABLED_CAPABILITIES,
WLAN_EID_MOBILITY_DOMAIN,
- WLAN_EID_FAST_BSS_TRANSITION, /* reassoc only */
- WLAN_EID_RIC_DATA, /* reassoc only */
WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
};
- static const u8 after_ric[] = {
- WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
- WLAN_EID_HT_CAPABILITY,
- WLAN_EID_BSS_COEX_2040,
- WLAN_EID_EXT_CAPABILITY,
- WLAN_EID_QOS_TRAFFIC_CAPA,
- WLAN_EID_TIM_BCAST_REQ,
- WLAN_EID_INTERWORKING,
- /* 60GHz doesn't happen right now */
- WLAN_EID_VHT_CAPABILITY,
- WLAN_EID_OPMODE_NOTIF,
- };
-
- noffset = ieee80211_ie_split_ric(assoc_data->ie,
- assoc_data->ie_len,
- before_ht,
- ARRAY_SIZE(before_ht),
- after_ric,
- ARRAY_SIZE(after_ric),
- offset);
+ noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
+ before_ht, ARRAY_SIZE(before_ht),
+ offset);
pos = skb_put(skb, noffset - offset);
memcpy(pos, assoc_data->ie + offset, noffset - offset);
offset = noffset;
@@ -837,8 +813,6 @@
WLAN_EID_TIM_BCAST_REQ,
WLAN_EID_INTERWORKING,
};
-
- /* RIC already taken above, so no need to handle here anymore */
noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len,
before_vht, ARRAY_SIZE(before_vht),
offset);
@@ -1027,7 +1001,14 @@
/* XXX: shouldn't really modify cfg80211-owned data! */
ifmgd->associated->channel = sdata->csa_chandef.chan;
- ifmgd->csa_waiting_bcn = true;
+ sdata->vif.csa_active = false;
+
+ /* XXX: wait for a beacon first? */
+ if (sdata->csa_block_tx) {
+ ieee80211_wake_vif_queues(local, sdata,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
+ sdata->csa_block_tx = false;
+ }
ieee80211_sta_reset_beacon_monitor(sdata);
ieee80211_sta_reset_conn_monitor(sdata);
@@ -1038,37 +1019,6 @@
sdata_unlock(sdata);
}
-static void ieee80211_chswitch_post_beacon(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- int ret;
-
- sdata_assert_lock(sdata);
-
- WARN_ON(!sdata->vif.csa_active);
-
- if (sdata->csa_block_tx) {
- ieee80211_wake_vif_queues(local, sdata,
- IEEE80211_QUEUE_STOP_REASON_CSA);
- sdata->csa_block_tx = false;
- }
-
- cfg80211_ch_switch_notify(sdata->dev, &sdata->reserved_chandef);
-
- sdata->vif.csa_active = false;
- ifmgd->csa_waiting_bcn = false;
-
- ret = drv_post_channel_switch(sdata);
- if (ret) {
- sdata_info(sdata,
- "driver post channel switch failed, disconnecting\n");
- ieee80211_queue_work(&local->hw,
- &ifmgd->csa_connection_drop_work);
- return;
- }
-}
-
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
@@ -1096,8 +1046,7 @@
static void
ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
- u64 timestamp, u32 device_timestamp,
- struct ieee802_11_elems *elems,
+ u64 timestamp, struct ieee802_11_elems *elems,
bool beacon)
{
struct ieee80211_local *local = sdata->local;
@@ -1107,7 +1056,6 @@
struct ieee80211_chanctx *chanctx;
enum ieee80211_band current_band;
struct ieee80211_csa_ie csa_ie;
- struct ieee80211_channel_switch ch_switch;
int res;
sdata_assert_lock(sdata);
@@ -1124,7 +1072,7 @@
current_band = cbss->channel->band;
memset(&csa_ie, 0, sizeof(csa_ie));
- res = ieee80211_parse_ch_switch_ie(sdata, elems, current_band,
+ res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band,
ifmgd->flags,
ifmgd->associated->bssid, &csa_ie);
if (res < 0)
@@ -1162,31 +1110,21 @@
chanctx = container_of(conf, struct ieee80211_chanctx, conf);
- if (local->use_chanctx &&
- !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) {
- sdata_info(sdata,
- "driver doesn't support chan-switch with channel contexts\n");
- ieee80211_queue_work(&local->hw,
- &ifmgd->csa_connection_drop_work);
- mutex_unlock(&local->chanctx_mtx);
- mutex_unlock(&local->mtx);
- return;
- }
+ if (local->use_chanctx) {
+ u32 num_chanctx = 0;
+ list_for_each_entry(chanctx, &local->chanctx_list, list)
+ num_chanctx++;
- ch_switch.timestamp = timestamp;
- ch_switch.device_timestamp = device_timestamp;
- ch_switch.block_tx = csa_ie.mode;
- ch_switch.chandef = csa_ie.chandef;
- ch_switch.count = csa_ie.count;
-
- if (drv_pre_channel_switch(sdata, &ch_switch)) {
- sdata_info(sdata,
- "preparing for channel switch failed, disconnecting\n");
- ieee80211_queue_work(&local->hw,
- &ifmgd->csa_connection_drop_work);
- mutex_unlock(&local->chanctx_mtx);
- mutex_unlock(&local->mtx);
- return;
+ if (num_chanctx > 1 ||
+ !(local->hw.flags & IEEE80211_HW_CHANCTX_STA_CSA)) {
+ sdata_info(sdata,
+ "not handling chan-switch with channel contexts\n");
+ ieee80211_queue_work(&local->hw,
+ &ifmgd->csa_connection_drop_work);
+ mutex_unlock(&local->chanctx_mtx);
+ mutex_unlock(&local->mtx);
+ return;
+ }
}
res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef,
@@ -1212,12 +1150,16 @@
IEEE80211_QUEUE_STOP_REASON_CSA);
mutex_unlock(&local->mtx);
- cfg80211_ch_switch_started_notify(sdata->dev, &csa_ie.chandef,
- csa_ie.count);
-
if (local->ops->channel_switch) {
/* use driver's channel switch callback */
- drv_channel_switch(local, sdata, &ch_switch);
+ struct ieee80211_channel_switch ch_switch = {
+ .timestamp = timestamp,
+ .block_tx = csa_ie.mode,
+ .chandef = csa_ie.chandef,
+ .count = csa_ie.count,
+ };
+
+ drv_channel_switch(local, &ch_switch);
return;
}
@@ -1226,8 +1168,7 @@
ieee80211_queue_work(&local->hw, &ifmgd->chswitch_work);
else
mod_timer(&ifmgd->chswitch_timer,
- TU_TO_EXP_TIME((csa_ie.count - 1) *
- cbss->beacon_interval));
+ TU_TO_EXP_TIME(csa_ie.count * cbss->beacon_interval));
}
static bool
@@ -1638,95 +1579,6 @@
mutex_unlock(&sdata->local->mtx);
}
-static bool
-__ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- bool ret;
- int ac;
-
- if (local->hw.queues < IEEE80211_NUM_ACS)
- return false;
-
- for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
- struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
- int non_acm_ac;
- unsigned long now = jiffies;
-
- if (tx_tspec->action == TX_TSPEC_ACTION_NONE &&
- tx_tspec->admitted_time &&
- time_after(now, tx_tspec->time_slice_start + HZ)) {
- tx_tspec->consumed_tx_time = 0;
- tx_tspec->time_slice_start = now;
-
- if (tx_tspec->downgraded)
- tx_tspec->action =
- TX_TSPEC_ACTION_STOP_DOWNGRADE;
- }
-
- switch (tx_tspec->action) {
- case TX_TSPEC_ACTION_STOP_DOWNGRADE:
- /* take the original parameters */
- if (drv_conf_tx(local, sdata, ac, &sdata->tx_conf[ac]))
- sdata_err(sdata,
- "failed to set TX queue parameters for queue %d\n",
- ac);
- tx_tspec->action = TX_TSPEC_ACTION_NONE;
- tx_tspec->downgraded = false;
- ret = true;
- break;
- case TX_TSPEC_ACTION_DOWNGRADE:
- if (time_after(now, tx_tspec->time_slice_start + HZ)) {
- tx_tspec->action = TX_TSPEC_ACTION_NONE;
- ret = true;
- break;
- }
- /* downgrade next lower non-ACM AC */
- for (non_acm_ac = ac + 1;
- non_acm_ac < IEEE80211_NUM_ACS;
- non_acm_ac++)
- if (!(sdata->wmm_acm & BIT(7 - 2 * non_acm_ac)))
- break;
- /* The loop will result in using BK even if it requires
- * admission control, such configuration makes no sense
- * and we have to transmit somehow - the AC selection
- * does the same thing.
- */
- if (drv_conf_tx(local, sdata, ac,
- &sdata->tx_conf[non_acm_ac]))
- sdata_err(sdata,
- "failed to set TX queue parameters for queue %d\n",
- ac);
- tx_tspec->action = TX_TSPEC_ACTION_NONE;
- ret = true;
- schedule_delayed_work(&ifmgd->tx_tspec_wk,
- tx_tspec->time_slice_start + HZ - now + 1);
- break;
- case TX_TSPEC_ACTION_NONE:
- /* nothing now */
- break;
- }
- }
-
- return ret;
-}
-
-void ieee80211_sta_handle_tspec_ac_params(struct ieee80211_sub_if_data *sdata)
-{
- if (__ieee80211_sta_handle_tspec_ac_params(sdata))
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
-}
-
-static void ieee80211_sta_handle_tspec_ac_params_wk(struct work_struct *work)
-{
- struct ieee80211_sub_if_data *sdata;
-
- sdata = container_of(work, struct ieee80211_sub_if_data,
- u.mgd.tx_tspec_wk.work);
- ieee80211_sta_handle_tspec_ac_params(sdata);
-}
-
/* MLME */
static bool ieee80211_sta_wmm_params(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
@@ -1811,14 +1663,12 @@
params.uapsd = uapsd;
mlme_dbg(sdata,
- "WMM queue=%d aci=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d, downgraded=%d\n",
+ "WMM queue=%d aci=%d acm=%d aifs=%d cWmin=%d cWmax=%d txop=%d uapsd=%d\n",
queue, aci, acm,
params.aifs, params.cw_min, params.cw_max,
- params.txop, params.uapsd,
- ifmgd->tx_tspec[queue].downgraded);
+ params.txop, params.uapsd);
sdata->tx_conf[queue] = params;
- if (!ifmgd->tx_tspec[queue].downgraded &&
- drv_conf_tx(local, sdata, queue, ¶ms))
+ if (drv_conf_tx(local, sdata, queue, ¶ms))
sdata_err(sdata,
"failed to set TX queue parameters for queue %d\n",
queue);
@@ -2073,7 +1923,6 @@
ieee80211_vif_release_channel(sdata);
sdata->vif.csa_active = false;
- ifmgd->csa_waiting_bcn = false;
if (sdata->csa_block_tx) {
ieee80211_wake_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -2081,10 +1930,6 @@
}
mutex_unlock(&local->mtx);
- /* existing TX TSPEC sessions no longer exist */
- memset(ifmgd->tx_tspec, 0, sizeof(ifmgd->tx_tspec));
- cancel_delayed_work_sync(&ifmgd->tx_tspec_wk);
-
sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM;
}
@@ -2137,46 +1982,9 @@
mutex_unlock(&local->mtx);
}
-static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_hdr *hdr,
- u16 tx_time)
-{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- u16 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
- int ac = ieee80211_ac_from_tid(tid);
- struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
- unsigned long now = jiffies;
-
- if (likely(!tx_tspec->admitted_time))
- return;
-
- if (time_after(now, tx_tspec->time_slice_start + HZ)) {
- tx_tspec->consumed_tx_time = 0;
- tx_tspec->time_slice_start = now;
-
- if (tx_tspec->downgraded) {
- tx_tspec->action = TX_TSPEC_ACTION_STOP_DOWNGRADE;
- schedule_delayed_work(&ifmgd->tx_tspec_wk, 0);
- }
- }
-
- if (tx_tspec->downgraded)
- return;
-
- tx_tspec->consumed_tx_time += tx_time;
-
- if (tx_tspec->consumed_tx_time >= tx_tspec->admitted_time) {
- tx_tspec->downgraded = true;
- tx_tspec->action = TX_TSPEC_ACTION_DOWNGRADE;
- schedule_delayed_work(&ifmgd->tx_tspec_wk, 0);
- }
-}
-
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_hdr *hdr, bool ack, u16 tx_time)
+ struct ieee80211_hdr *hdr, bool ack)
{
- ieee80211_sta_tx_wmm_ac_notify(sdata, hdr, tx_time);
-
if (!ieee80211_is_data(hdr->frame_control))
return;
@@ -2231,8 +2039,7 @@
else
ssid_len = ssid[1];
- ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
- ssid + 2, ssid_len, NULL,
+ ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
0, (u32) -1, true, 0,
ifmgd->associated->channel, false);
rcu_read_unlock();
@@ -2240,6 +2047,8 @@
ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
run_again(sdata, ifmgd->probe_timeout);
+ if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
+ ieee80211_flush_queues(sdata->local, sdata);
}
static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
@@ -2268,7 +2077,9 @@
"detected beacon loss from AP (missed %d beacons) - probing\n",
beacon_loss_count);
- ieee80211_cqm_beacon_loss_notify(&sdata->vif, GFP_KERNEL);
+ ieee80211_cqm_rssi_notify(&sdata->vif,
+ NL80211_CQM_RSSI_BEACON_LOSS_EVENT,
+ GFP_KERNEL);
}
/*
@@ -2333,7 +2144,7 @@
else
ssid_len = ssid[1];
- skb = ieee80211_build_probe_req(sdata, sdata->vif.addr, cbss->bssid,
+ skb = ieee80211_build_probe_req(sdata, cbss->bssid,
(u32) -1, cbss->channel,
ssid + 2, ssid_len,
NULL, 0, true);
@@ -2360,7 +2171,6 @@
true, frame_buf);
mutex_lock(&local->mtx);
sdata->vif.csa_active = false;
- ifmgd->csa_waiting_bcn = false;
if (sdata->csa_block_tx) {
ieee80211_wake_vif_queues(local, sdata,
IEEE80211_QUEUE_STOP_REASON_CSA);
@@ -2807,9 +2617,6 @@
}
ifmgd->aid = aid;
- ifmgd->tdls_chan_switch_prohibited =
- elems.ext_capab && elems.ext_capab_len >= 5 &&
- (elems.ext_capab[4] & WLAN_EXT_CAPA5_TDLS_CH_SW_PROHIBITED);
/*
* Some APs are erroneously not including some information in their
@@ -3388,9 +3195,6 @@
}
}
- if (ifmgd->csa_waiting_bcn)
- ieee80211_chswitch_post_beacon(sdata);
-
if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
return;
ifmgd->beacon_crc = ncrc;
@@ -3399,7 +3203,6 @@
ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems);
ieee80211_sta_process_chanswitch(sdata, rx_status->mactime,
- rx_status->device_timestamp,
&elems, true);
if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) &&
@@ -3531,9 +3334,8 @@
break;
ieee80211_sta_process_chanswitch(sdata,
- rx_status->mactime,
- rx_status->device_timestamp,
- &elems, false);
+ rx_status->mactime,
+ &elems, false);
} else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
ies_len = skb->len -
offsetof(struct ieee80211_mgmt,
@@ -3554,9 +3356,8 @@
&mgmt->u.action.u.ext_chan_switch.data;
ieee80211_sta_process_chanswitch(sdata,
- rx_status->mactime,
- rx_status->device_timestamp,
- &elems, false);
+ rx_status->mactime,
+ &elems, false);
}
break;
}
@@ -3654,8 +3455,7 @@
* Direct probe is sent to broadcast address as some APs
* will not answer to direct packet in unassociated state.
*/
- ieee80211_send_probe_req(sdata, sdata->vif.addr, NULL,
- ssidie + 2, ssidie[1],
+ ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1],
NULL, 0, (u32) -1, true, 0,
auth_data->bss->channel, false);
rcu_read_unlock();
@@ -3864,12 +3664,11 @@
struct ieee80211_sub_if_data *sdata =
(struct ieee80211_sub_if_data *) data;
struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
if (local->quiescing)
return;
- if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
+ if (sdata->vif.csa_active)
return;
sdata->u.mgd.connection_loss = false;
@@ -3887,7 +3686,7 @@
if (local->quiescing)
return;
- if (sdata->vif.csa_active && !ifmgd->csa_waiting_bcn)
+ if (sdata->vif.csa_active)
return;
ieee80211_queue_work(&local->hw, &ifmgd->monitor_work);
@@ -3999,8 +3798,6 @@
(unsigned long) sdata);
setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
(unsigned long) sdata);
- INIT_DELAYED_WORK(&ifmgd->tx_tspec_wk,
- ieee80211_sta_handle_tspec_ac_params_wk);
ifmgd->flags = 0;
ifmgd->powersave = sdata->wdev.ps;
@@ -4012,11 +3809,6 @@
ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
else
ifmgd->req_smps = IEEE80211_SMPS_OFF;
-
- /* Setup TDLS data */
- spin_lock_init(&ifmgd->teardown_lock);
- ifmgd->teardown_skb = NULL;
- ifmgd->orig_teardown_skb = NULL;
}
/* scan finished notification */
@@ -4879,13 +4671,6 @@
}
if (ifmgd->auth_data)
ieee80211_destroy_auth_data(sdata, false);
- spin_lock_bh(&ifmgd->teardown_lock);
- if (ifmgd->teardown_skb) {
- kfree_skb(ifmgd->teardown_skb);
- ifmgd->teardown_skb = NULL;
- ifmgd->orig_teardown_skb = NULL;
- }
- spin_unlock_bh(&ifmgd->teardown_lock);
del_timer_sync(&ifmgd->timer);
sdata_unlock(sdata);
}
@@ -4901,13 +4686,3 @@
cfg80211_cqm_rssi_notify(sdata->dev, rssi_event, gfp);
}
EXPORT_SYMBOL(ieee80211_cqm_rssi_notify);
-
-void ieee80211_cqm_beacon_loss_notify(struct ieee80211_vif *vif, gfp_t gfp)
-{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-
- trace_api_cqm_beacon_loss_notify(sdata->local, sdata);
-
- cfg80211_cqm_beacon_loss_notify(sdata->dev, gfp);
-}
-EXPORT_SYMBOL(ieee80211_cqm_beacon_loss_notify);
diff --git a/net/mac80211/ocb.c b/net/mac80211/ocb.c
deleted file mode 100644
index 358d5f9..0000000
--- a/net/mac80211/ocb.c
+++ /dev/null
@@ -1,250 +0,0 @@
-/*
- * OCB mode implementation
- *
- * Copyright: (c) 2014 Czech Technical University in Prague
- * (c) 2014 Volkswagen Group Research
- * Author: Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
- * Funded by: Volkswagen Group Research
- *
- * 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.
- */
-
-#include <linux/delay.h>
-#include <linux/if_ether.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-#include <linux/rtnetlink.h>
-#include <net/mac80211.h>
-#include <asm/unaligned.h>
-
-#include "ieee80211_i.h"
-#include "driver-ops.h"
-#include "rate.h"
-
-#define IEEE80211_OCB_HOUSEKEEPING_INTERVAL (60 * HZ)
-#define IEEE80211_OCB_PEER_INACTIVITY_LIMIT (240 * HZ)
-#define IEEE80211_OCB_MAX_STA_ENTRIES 128
-
-/**
- * enum ocb_deferred_task_flags - mac80211 OCB deferred tasks
- * @OCB_WORK_HOUSEKEEPING: run the periodic OCB housekeeping tasks
- *
- * These flags are used in @wrkq_flags field of &struct ieee80211_if_ocb
- */
-enum ocb_deferred_task_flags {
- OCB_WORK_HOUSEKEEPING,
-};
-
-void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
- const u8 *bssid, const u8 *addr,
- u32 supp_rates)
-{
- struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_chanctx_conf *chanctx_conf;
- struct ieee80211_supported_band *sband;
- enum nl80211_bss_scan_width scan_width;
- struct sta_info *sta;
- int band;
-
- /* XXX: Consider removing the least recently used entry and
- * allow new one to be added.
- */
- if (local->num_sta >= IEEE80211_OCB_MAX_STA_ENTRIES) {
- net_info_ratelimited("%s: No room for a new OCB STA entry %pM\n",
- sdata->name, addr);
- return;
- }
-
- ocb_dbg(sdata, "Adding new OCB station %pM\n", addr);
-
- rcu_read_lock();
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (WARN_ON_ONCE(!chanctx_conf)) {
- rcu_read_unlock();
- return;
- }
- band = chanctx_conf->def.chan->band;
- scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
- rcu_read_unlock();
-
- sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
- if (!sta)
- return;
-
- sta->last_rx = jiffies;
-
- /* Add only mandatory rates for now */
- sband = local->hw.wiphy->bands[band];
- sta->sta.supp_rates[band] =
- ieee80211_mandatory_rates(sband, scan_width);
-
- spin_lock(&ifocb->incomplete_lock);
- list_add(&sta->list, &ifocb->incomplete_stations);
- spin_unlock(&ifocb->incomplete_lock);
- ieee80211_queue_work(&local->hw, &sdata->work);
-}
-
-static struct sta_info *ieee80211_ocb_finish_sta(struct sta_info *sta)
- __acquires(RCU)
-{
- struct ieee80211_sub_if_data *sdata = sta->sdata;
- u8 addr[ETH_ALEN];
-
- memcpy(addr, sta->sta.addr, ETH_ALEN);
-
- ocb_dbg(sdata, "Adding new IBSS station %pM (dev=%s)\n",
- addr, sdata->name);
-
- sta_info_move_state(sta, IEEE80211_STA_AUTH);
- sta_info_move_state(sta, IEEE80211_STA_ASSOC);
- sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
-
- rate_control_rate_init(sta);
-
- /* If it fails, maybe we raced another insertion? */
- if (sta_info_insert_rcu(sta))
- return sta_info_get(sdata, addr);
- return sta;
-}
-
-static void ieee80211_ocb_housekeeping(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-
- ocb_dbg(sdata, "Running ocb housekeeping\n");
-
- ieee80211_sta_expire(sdata, IEEE80211_OCB_PEER_INACTIVITY_LIMIT);
-
- mod_timer(&ifocb->housekeeping_timer,
- round_jiffies(jiffies + IEEE80211_OCB_HOUSEKEEPING_INTERVAL));
-}
-
-void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
- struct sta_info *sta;
-
- if (ifocb->joined != true)
- return;
-
- sdata_lock(sdata);
-
- spin_lock_bh(&ifocb->incomplete_lock);
- while (!list_empty(&ifocb->incomplete_stations)) {
- sta = list_first_entry(&ifocb->incomplete_stations,
- struct sta_info, list);
- list_del(&sta->list);
- spin_unlock_bh(&ifocb->incomplete_lock);
-
- ieee80211_ocb_finish_sta(sta);
- rcu_read_unlock();
- spin_lock_bh(&ifocb->incomplete_lock);
- }
- spin_unlock_bh(&ifocb->incomplete_lock);
-
- if (test_and_clear_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags))
- ieee80211_ocb_housekeeping(sdata);
-
- sdata_unlock(sdata);
-}
-
-static void ieee80211_ocb_housekeeping_timer(unsigned long data)
-{
- struct ieee80211_sub_if_data *sdata = (void *)data;
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-
- set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
-
- ieee80211_queue_work(&local->hw, &sdata->work);
-}
-
-void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
-
- setup_timer(&ifocb->housekeeping_timer,
- ieee80211_ocb_housekeeping_timer,
- (unsigned long)sdata);
- INIT_LIST_HEAD(&ifocb->incomplete_stations);
- spin_lock_init(&ifocb->incomplete_lock);
-}
-
-int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
- struct ocb_setup *setup)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
- u32 changed = BSS_CHANGED_OCB;
- int err;
-
- if (ifocb->joined == true)
- return -EINVAL;
-
- sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
- sdata->smps_mode = IEEE80211_SMPS_OFF;
- sdata->needed_rx_chains = sdata->local->rx_chains;
-
- mutex_lock(&sdata->local->mtx);
- err = ieee80211_vif_use_channel(sdata, &setup->chandef,
- IEEE80211_CHANCTX_SHARED);
- mutex_unlock(&sdata->local->mtx);
- if (err)
- return err;
-
- ieee80211_bss_info_change_notify(sdata, changed);
-
- ifocb->joined = true;
-
- set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
- ieee80211_queue_work(&local->hw, &sdata->work);
-
- netif_carrier_on(sdata->dev);
- return 0;
-}
-
-int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata)
-{
- struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
-
- ifocb->joined = false;
- sta_info_flush(sdata);
-
- spin_lock_bh(&ifocb->incomplete_lock);
- while (!list_empty(&ifocb->incomplete_stations)) {
- sta = list_first_entry(&ifocb->incomplete_stations,
- struct sta_info, list);
- list_del(&sta->list);
- spin_unlock_bh(&ifocb->incomplete_lock);
-
- sta_info_free(local, sta);
- spin_lock_bh(&ifocb->incomplete_lock);
- }
- spin_unlock_bh(&ifocb->incomplete_lock);
-
- netif_carrier_off(sdata->dev);
- clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_OCB);
-
- mutex_lock(&sdata->local->mtx);
- ieee80211_vif_release_channel(sdata);
- mutex_unlock(&sdata->local->mtx);
-
- skb_queue_purge(&sdata->skb_queue);
-
- del_timer_sync(&sdata->u.ocb.housekeeping_timer);
- /* If the timer fired while we waited for it, it will have
- * requeued the work. Now the work will be running again
- * but will not rearm the timer again because it checks
- * whether we are connected to the network or not -- at this
- * point we shouldn't be anymore.
- */
-
- return 0;
-}
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index bc5270e..2c70248 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -385,7 +385,7 @@
*rate = alt_rate;
return;
}
- } else if (!(rate->flags & IEEE80211_TX_RC_VHT_MCS)) {
+ } else {
/* handle legacy rates */
if (rate_idx_match_legacy_mask(rate, sband->n_bitrates, mask))
return;
@@ -446,10 +446,9 @@
*
* XXX: Should this check all retry rates?
*/
- if (!(rates[0].flags &
- (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))) {
+ if (!(rates[0].flags & IEEE80211_TX_RC_MCS)) {
u32 basic_rates = vif->bss_conf.basic_rates;
- s8 baserate = basic_rates ? ffs(basic_rates) - 1 : 0;
+ s8 baserate = basic_rates ? ffs(basic_rates - 1) : 0;
rate = &sband->bitrates[rates[0].idx];
@@ -697,7 +696,6 @@
struct ieee80211_sta *pubsta,
struct ieee80211_sta_rates *rates)
{
- struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
struct ieee80211_sta_rates *old;
/*
@@ -711,8 +709,6 @@
if (old)
kfree_rcu(old, rcu_head);
- drv_sta_rate_tbl_update(hw_to_local(hw), sta->sdata, pubsta);
-
return 0;
}
EXPORT_SYMBOL(rate_control_set_rates);
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h
index a7d5439..d75147c 100644
--- a/net/mac80211/rate.h
+++ b/net/mac80211/rate.h
@@ -37,35 +37,13 @@
struct rate_control_ref *ref = local->rate_ctrl;
struct ieee80211_sta *ista = &sta->sta;
void *priv_sta = sta->rate_ctrl_priv;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
return;
- if (ref->ops->tx_status)
- ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
- else
- ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
+ ref->ops->tx_status(ref->priv, sband, ista, priv_sta, skb);
}
-static inline void
-rate_control_tx_status_noskb(struct ieee80211_local *local,
- struct ieee80211_supported_band *sband,
- struct sta_info *sta,
- struct ieee80211_tx_info *info)
-{
- struct rate_control_ref *ref = local->rate_ctrl;
- struct ieee80211_sta *ista = &sta->sta;
- void *priv_sta = sta->rate_ctrl_priv;
-
- if (!ref || !test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
- return;
-
- if (WARN_ON_ONCE(!ref->ops->tx_status_noskb))
- return;
-
- ref->ops->tx_status_noskb(ref->priv, sband, ista, priv_sta, info);
-}
static inline void rate_control_rate_init(struct sta_info *sta)
{
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c
index 217e379..2cd8250 100644
--- a/net/mac80211/rc80211_minstrel.c
+++ b/net/mac80211/rc80211_minstrel.c
@@ -191,7 +191,7 @@
* (1) if any success probabilitiy >= 95%, out of those rates
* choose the maximum throughput rate as max_prob_rate
* (2) if all success probabilities < 95%, the rate with
- * highest success probability is chosen as max_prob_rate */
+ * highest success probability is choosen as max_prob_rate */
if (mrs->probability >= MINSTREL_FRAC(95, 100)) {
if (mrs->cur_tp >= mi->r[tmp_prob_rate].stats.cur_tp)
tmp_prob_rate = i;
@@ -223,10 +223,11 @@
static void
minstrel_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
- struct ieee80211_tx_info *info)
+ struct sk_buff *skb)
{
struct minstrel_priv *mp = priv;
struct minstrel_sta_info *mi = priv_sta;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info->status.rates;
int i, ndx;
int success;
@@ -673,7 +674,7 @@
const struct rate_control_ops mac80211_minstrel = {
.name = "minstrel",
- .tx_status_noskb = minstrel_tx_status,
+ .tx_status = minstrel_tx_status,
.get_rate = minstrel_get_rate,
.rate_init = minstrel_rate_init,
.alloc = minstrel_alloc,
diff --git a/net/mac80211/rc80211_minstrel_debugfs.c b/net/mac80211/rc80211_minstrel_debugfs.c
index 2acab1b..edde723 100644
--- a/net/mac80211/rc80211_minstrel_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_debugfs.c
@@ -62,14 +62,14 @@
unsigned int i, tp, prob, eprob;
char *p;
- ms = kmalloc(2048, GFP_KERNEL);
+ ms = kmalloc(sizeof(*ms) + 4096, GFP_KERNEL);
if (!ms)
return -ENOMEM;
file->private_data = ms;
p = ms->buf;
- p += sprintf(p, "rate tpt eprob *prob"
- " *ok(*cum) ok( cum)\n");
+ p += sprintf(p, "rate throughput ewma prob this prob "
+ "this succ/attempt success attempts\n");
for (i = 0; i < mi->n_rates; i++) {
struct minstrel_rate *mr = &mi->r[i];
struct minstrel_rate_stats *mrs = &mi->r[i].stats;
@@ -86,8 +86,8 @@
prob = MINSTREL_TRUNC(mrs->cur_prob * 1000);
eprob = MINSTREL_TRUNC(mrs->probability * 1000);
- p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u"
- " %4u(%4u) %9llu(%9llu)\n",
+ p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
+ " %3u(%3u) %8llu %8llu\n",
tp / 10, tp % 10,
eprob / 10, eprob % 10,
prob / 10, prob % 10,
@@ -102,8 +102,6 @@
mi->sample_packets);
ms->len = p - ms->buf;
- WARN_ON(ms->len + sizeof(*ms) > 2048);
-
return 0;
}
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index e8d8bec..08f80e8 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -10,7 +10,6 @@
#include <linux/skbuff.h>
#include <linux/debugfs.h>
#include <linux/random.h>
-#include <linux/moduleparam.h>
#include <linux/ieee80211.h>
#include <net/mac80211.h>
#include "rate.h"
@@ -35,17 +34,12 @@
/* Transmit duration for the raw data part of an average sized packet */
#define MCS_DURATION(streams, sgi, bps) MCS_SYMBOL_TIME(sgi, MCS_NSYMS((streams) * (bps)))
-#define BW_20 0
-#define BW_40 1
-#define BW_80 2
-
/*
* Define group sort order: HT40 -> SGI -> #streams
*/
#define GROUP_IDX(_streams, _sgi, _ht40) \
- MINSTREL_HT_GROUP_0 + \
MINSTREL_MAX_STREAMS * 2 * _ht40 + \
- MINSTREL_MAX_STREAMS * _sgi + \
+ MINSTREL_MAX_STREAMS * _sgi + \
_streams - 1
/* MCS rate information for an MCS group */
@@ -53,7 +47,6 @@
[GROUP_IDX(_streams, _sgi, _ht40)] = { \
.streams = _streams, \
.flags = \
- IEEE80211_TX_RC_MCS | \
(_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
(_ht40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
.duration = { \
@@ -68,47 +61,6 @@
} \
}
-#define VHT_GROUP_IDX(_streams, _sgi, _bw) \
- (MINSTREL_VHT_GROUP_0 + \
- MINSTREL_MAX_STREAMS * 2 * (_bw) + \
- MINSTREL_MAX_STREAMS * (_sgi) + \
- (_streams) - 1)
-
-#define BW2VBPS(_bw, r3, r2, r1) \
- (_bw == BW_80 ? r3 : _bw == BW_40 ? r2 : r1)
-
-#define VHT_GROUP(_streams, _sgi, _bw) \
- [VHT_GROUP_IDX(_streams, _sgi, _bw)] = { \
- .streams = _streams, \
- .flags = \
- IEEE80211_TX_RC_VHT_MCS | \
- (_sgi ? IEEE80211_TX_RC_SHORT_GI : 0) | \
- (_bw == BW_80 ? IEEE80211_TX_RC_80_MHZ_WIDTH : \
- _bw == BW_40 ? IEEE80211_TX_RC_40_MHZ_WIDTH : 0), \
- .duration = { \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 117, 54, 26)), \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 234, 108, 52)), \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 351, 162, 78)), \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 468, 216, 104)), \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 702, 324, 156)), \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 936, 432, 208)), \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 1053, 486, 234)), \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 1170, 540, 260)), \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 1404, 648, 312)), \
- MCS_DURATION(_streams, _sgi, \
- BW2VBPS(_bw, 1560, 720, 346)) \
- } \
-}
-
#define CCK_DURATION(_bitrate, _short, _len) \
(1000 * (10 /* SIFS */ + \
(_short ? 72 + 24 : 144 + 48) + \
@@ -124,161 +76,70 @@
CCK_ACK_DURATION(55, _short), \
CCK_ACK_DURATION(110, _short)
-#define CCK_GROUP \
- [MINSTREL_CCK_GROUP] = { \
- .streams = 0, \
- .flags = 0, \
- .duration = { \
- CCK_DURATION_LIST(false), \
- CCK_DURATION_LIST(true) \
- } \
+#define CCK_GROUP \
+ [MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS] = { \
+ .streams = 0, \
+ .duration = { \
+ CCK_DURATION_LIST(false), \
+ CCK_DURATION_LIST(true) \
+ } \
}
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
-static bool minstrel_vht_only = true;
-module_param(minstrel_vht_only, bool, 0644);
-MODULE_PARM_DESC(minstrel_vht_only,
- "Use only VHT rates when VHT is supported by sta.");
-#endif
-
/*
* To enable sufficiently targeted rate sampling, MCS rates are divided into
* groups, based on the number of streams and flags (HT40, SGI) that they
* use.
*
* Sortorder has to be fixed for GROUP_IDX macro to be applicable:
- * BW -> SGI -> #streams
+ * HT40 -> SGI -> #streams
*/
const struct mcs_group minstrel_mcs_groups[] = {
- MCS_GROUP(1, 0, BW_20),
- MCS_GROUP(2, 0, BW_20),
+ MCS_GROUP(1, 0, 0),
+ MCS_GROUP(2, 0, 0),
#if MINSTREL_MAX_STREAMS >= 3
- MCS_GROUP(3, 0, BW_20),
+ MCS_GROUP(3, 0, 0),
#endif
- MCS_GROUP(1, 1, BW_20),
- MCS_GROUP(2, 1, BW_20),
+ MCS_GROUP(1, 1, 0),
+ MCS_GROUP(2, 1, 0),
#if MINSTREL_MAX_STREAMS >= 3
- MCS_GROUP(3, 1, BW_20),
+ MCS_GROUP(3, 1, 0),
#endif
- MCS_GROUP(1, 0, BW_40),
- MCS_GROUP(2, 0, BW_40),
+ MCS_GROUP(1, 0, 1),
+ MCS_GROUP(2, 0, 1),
#if MINSTREL_MAX_STREAMS >= 3
- MCS_GROUP(3, 0, BW_40),
+ MCS_GROUP(3, 0, 1),
#endif
- MCS_GROUP(1, 1, BW_40),
- MCS_GROUP(2, 1, BW_40),
+ MCS_GROUP(1, 1, 1),
+ MCS_GROUP(2, 1, 1),
#if MINSTREL_MAX_STREAMS >= 3
- MCS_GROUP(3, 1, BW_40),
+ MCS_GROUP(3, 1, 1),
#endif
- CCK_GROUP,
-
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
- VHT_GROUP(1, 0, BW_20),
- VHT_GROUP(2, 0, BW_20),
-#if MINSTREL_MAX_STREAMS >= 3
- VHT_GROUP(3, 0, BW_20),
-#endif
-
- VHT_GROUP(1, 1, BW_20),
- VHT_GROUP(2, 1, BW_20),
-#if MINSTREL_MAX_STREAMS >= 3
- VHT_GROUP(3, 1, BW_20),
-#endif
-
- VHT_GROUP(1, 0, BW_40),
- VHT_GROUP(2, 0, BW_40),
-#if MINSTREL_MAX_STREAMS >= 3
- VHT_GROUP(3, 0, BW_40),
-#endif
-
- VHT_GROUP(1, 1, BW_40),
- VHT_GROUP(2, 1, BW_40),
-#if MINSTREL_MAX_STREAMS >= 3
- VHT_GROUP(3, 1, BW_40),
-#endif
-
- VHT_GROUP(1, 0, BW_80),
- VHT_GROUP(2, 0, BW_80),
-#if MINSTREL_MAX_STREAMS >= 3
- VHT_GROUP(3, 0, BW_80),
-#endif
-
- VHT_GROUP(1, 1, BW_80),
- VHT_GROUP(2, 1, BW_80),
-#if MINSTREL_MAX_STREAMS >= 3
- VHT_GROUP(3, 1, BW_80),
-#endif
-#endif
+ /* must be last */
+ CCK_GROUP
};
+#define MINSTREL_CCK_GROUP (ARRAY_SIZE(minstrel_mcs_groups) - 1)
+
static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly;
static void
minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi);
/*
- * Some VHT MCSes are invalid (when Ndbps / Nes is not an integer)
- * e.g for MCS9@20MHzx1Nss: Ndbps=8x52*(5/6) Nes=1
- *
- * Returns the valid mcs map for struct minstrel_mcs_group_data.supported
- */
-static u16
-minstrel_get_valid_vht_rates(int bw, int nss, __le16 mcs_map)
-{
- u16 mask = 0;
-
- if (bw == BW_20) {
- if (nss != 3 && nss != 6)
- mask = BIT(9);
- } else if (bw == BW_80) {
- if (nss == 3 || nss == 7)
- mask = BIT(6);
- else if (nss == 6)
- mask = BIT(9);
- } else {
- WARN_ON(bw != BW_40);
- }
-
- switch ((le16_to_cpu(mcs_map) >> (2 * (nss - 1))) & 3) {
- case IEEE80211_VHT_MCS_SUPPORT_0_7:
- mask |= 0x300;
- break;
- case IEEE80211_VHT_MCS_SUPPORT_0_8:
- mask |= 0x200;
- break;
- case IEEE80211_VHT_MCS_SUPPORT_0_9:
- break;
- default:
- mask = 0x3ff;
- }
-
- return 0x3ff & ~mask;
-}
-
-/*
* Look up an MCS group index based on mac80211 rate information
*/
static int
minstrel_ht_get_group_idx(struct ieee80211_tx_rate *rate)
{
- return GROUP_IDX((rate->idx / 8) + 1,
+ return GROUP_IDX((rate->idx / MCS_GROUP_RATES) + 1,
!!(rate->flags & IEEE80211_TX_RC_SHORT_GI),
!!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH));
}
-static int
-minstrel_vht_get_group_idx(struct ieee80211_tx_rate *rate)
-{
- return VHT_GROUP_IDX(ieee80211_rate_get_vht_nss(rate),
- !!(rate->flags & IEEE80211_TX_RC_SHORT_GI),
- !!(rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) +
- 2*!!(rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH));
-}
-
static struct minstrel_rate_stats *
minstrel_ht_get_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi,
struct ieee80211_tx_rate *rate)
@@ -288,9 +149,6 @@
if (rate->flags & IEEE80211_TX_RC_MCS) {
group = minstrel_ht_get_group_idx(rate);
idx = rate->idx % 8;
- } else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
- group = minstrel_vht_get_group_idx(rate);
- idx = ieee80211_rate_get_vht_mcs(rate);
} else {
group = MINSTREL_CCK_GROUP;
@@ -382,8 +240,8 @@
* MCS groups, CCK rates do not provide aggregation and are therefore at last.
*/
static void
-minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u16 index,
- u16 *tp_list)
+minstrel_ht_sort_best_tp_rates(struct minstrel_ht_sta *mi, u8 index,
+ u8 *tp_list)
{
int cur_group, cur_idx, cur_thr, cur_prob;
int tmp_group, tmp_idx, tmp_thr, tmp_prob;
@@ -394,16 +252,19 @@
cur_thr = mi->groups[cur_group].rates[cur_idx].cur_tp;
cur_prob = mi->groups[cur_group].rates[cur_idx].probability;
- do {
+ tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
+ tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
+ tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
+ tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
+
+ while (j > 0 && (cur_thr > tmp_thr ||
+ (cur_thr == tmp_thr && cur_prob > tmp_prob))) {
+ j--;
tmp_group = tp_list[j - 1] / MCS_GROUP_RATES;
tmp_idx = tp_list[j - 1] % MCS_GROUP_RATES;
tmp_thr = mi->groups[tmp_group].rates[tmp_idx].cur_tp;
tmp_prob = mi->groups[tmp_group].rates[tmp_idx].probability;
- if (cur_thr < tmp_thr ||
- (cur_thr == tmp_thr && cur_prob <= tmp_prob))
- break;
- j--;
- } while (j > 0);
+ }
if (j < MAX_THR_RATES - 1) {
memmove(&tp_list[j + 1], &tp_list[j], (sizeof(*tp_list) *
@@ -417,7 +278,7 @@
* Find and set the topmost probability rate per sta and per group
*/
static void
-minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u16 index)
+minstrel_ht_set_best_prob_rate(struct minstrel_ht_sta *mi, u8 index)
{
struct minstrel_mcs_group_data *mg;
struct minstrel_rate_stats *mr;
@@ -460,8 +321,8 @@
*/
static void
minstrel_ht_assign_best_tp_rates(struct minstrel_ht_sta *mi,
- u16 tmp_mcs_tp_rate[MAX_THR_RATES],
- u16 tmp_cck_tp_rate[MAX_THR_RATES])
+ u8 tmp_mcs_tp_rate[MAX_THR_RATES],
+ u8 tmp_cck_tp_rate[MAX_THR_RATES])
{
unsigned int tmp_group, tmp_idx, tmp_cck_tp, tmp_mcs_tp;
int i;
@@ -525,8 +386,8 @@
struct minstrel_mcs_group_data *mg;
struct minstrel_rate_stats *mr;
int group, i, j;
- u16 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
- u16 tmp_cck_tp_rate[MAX_THR_RATES], index;
+ u8 tmp_mcs_tp_rate[MAX_THR_RATES], tmp_group_tp_rate[MAX_THR_RATES];
+ u8 tmp_cck_tp_rate[MAX_THR_RATES], index;
if (mi->ampdu_packets > 0) {
mi->avg_ampdu_len = minstrel_ewma(mi->avg_ampdu_len,
@@ -624,8 +485,7 @@
if (!rate->count)
return false;
- if (rate->flags & IEEE80211_TX_RC_MCS ||
- rate->flags & IEEE80211_TX_RC_VHT_MCS)
+ if (rate->flags & IEEE80211_TX_RC_MCS)
return true;
return rate->idx == mp->cck_rates[0] ||
@@ -657,7 +517,7 @@
}
static void
-minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u16 *idx, bool primary)
+minstrel_downgrade_rate(struct minstrel_ht_sta *mi, u8 *idx, bool primary)
{
int group, orig_group;
@@ -687,9 +547,6 @@
struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
u16 tid;
- if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
- return;
-
if (unlikely(!ieee80211_is_data_qos(hdr->frame_control)))
return;
@@ -700,16 +557,20 @@
if (likely(sta->ampdu_mlme.tid_tx[tid]))
return;
+ if (skb_get_queue_mapping(skb) == IEEE80211_AC_VO)
+ return;
+
ieee80211_start_tx_ba_session(pubsta, tid, 5000);
}
static void
minstrel_ht_tx_status(void *priv, struct ieee80211_supported_band *sband,
struct ieee80211_sta *sta, void *priv_sta,
- struct ieee80211_tx_info *info)
+ struct sk_buff *skb)
{
struct minstrel_ht_sta_priv *msp = priv_sta;
struct minstrel_ht_sta *mi = &msp->ht;
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_tx_rate *ar = info->status.rates;
struct minstrel_rate_stats *rate, *rate2;
struct minstrel_priv *mp = priv;
@@ -717,8 +578,7 @@
int i;
if (!msp->is_ht)
- return mac80211_minstrel.tx_status_noskb(priv, sband, sta,
- &msp->legacy, info);
+ return mac80211_minstrel.tx_status(priv, sband, sta, &msp->legacy, skb);
/* This packet was aggregated but doesn't carry status info */
if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
@@ -779,6 +639,9 @@
if (time_after(jiffies, mi->stats_update + (mp->update_interval / 2 * HZ) / 1000)) {
update = true;
minstrel_ht_update_stats(mp, mi);
+ if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
+ mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
+ minstrel_aggr_check(sta, skb);
}
if (update)
@@ -851,7 +714,7 @@
const struct mcs_group *group = &minstrel_mcs_groups[index / MCS_GROUP_RATES];
struct minstrel_rate_stats *mr;
u8 idx;
- u16 flags = group->flags;
+ u16 flags;
mr = minstrel_get_ratestats(mi, index);
if (!mr->retry_updated)
@@ -867,13 +730,13 @@
ratetbl->rate[offset].count_rts = mr->retry_count_rtscts;
}
- if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP)
+ if (index / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
idx = mp->cck_rates[index % ARRAY_SIZE(mp->cck_rates)];
- else if (flags & IEEE80211_TX_RC_VHT_MCS)
- idx = ((group->streams - 1) << 4) |
- ((index % MCS_GROUP_RATES) & 0xF);
- else
+ flags = 0;
+ } else {
idx = index % MCS_GROUP_RATES + (group->streams - 1) * 8;
+ flags = IEEE80211_TX_RC_MCS | group->flags;
+ }
if (offset > 0) {
ratetbl->rate[offset].count = ratetbl->rate[offset].count_rts;
@@ -1020,10 +883,6 @@
if (!msp->is_ht)
return mac80211_minstrel.get_rate(priv, sta, &msp->legacy, txrc);
- if (!(info->flags & IEEE80211_TX_CTL_AMPDU) &&
- mi->max_prob_rate / MCS_GROUP_RATES != MINSTREL_CCK_GROUP)
- minstrel_aggr_check(sta, txrc->skb);
-
info->flags |= mi->tx_flags;
minstrel_ht_check_cck_shortpreamble(mp, mi, txrc->short_preamble);
@@ -1057,15 +916,13 @@
if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
rate->idx = mp->cck_rates[idx];
- } else if (sample_group->flags & IEEE80211_TX_RC_VHT_MCS) {
- ieee80211_rate_set_vht(rate, sample_idx % MCS_GROUP_RATES,
- sample_group->streams);
- } else {
- rate->idx = sample_idx % MCS_GROUP_RATES +
- (sample_group->streams - 1) * 8;
+ rate->flags = 0;
+ return;
}
- rate->flags = sample_group->flags;
+ rate->idx = sample_idx % MCS_GROUP_RATES +
+ (sample_group->streams - 1) * 8;
+ rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
}
static void
@@ -1105,8 +962,6 @@
struct minstrel_ht_sta *mi = &msp->ht;
struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs;
u16 sta_cap = sta->ht_cap.cap;
- struct ieee80211_sta_vht_cap *vht_cap = &sta->vht_cap;
- int use_vht;
int n_supported = 0;
int ack_dur;
int stbc;
@@ -1116,14 +971,8 @@
if (!sta->ht_cap.ht_supported)
goto use_legacy;
- BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) != MINSTREL_GROUPS_NB);
-
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
- if (vht_cap->vht_supported)
- use_vht = vht_cap->vht_mcs.tx_mcs_map != cpu_to_le16(~0);
- else
-#endif
- use_vht = 0;
+ BUILD_BUG_ON(ARRAY_SIZE(minstrel_mcs_groups) !=
+ MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS + 1);
msp->is_ht = true;
memset(mi, 0, sizeof(*mi));
@@ -1148,28 +997,22 @@
}
mi->sample_tries = 4;
- /* TODO tx_flags for vht - ATM the RC API is not fine-grained enough */
- if (!use_vht) {
- stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>
- IEEE80211_HT_CAP_RX_STBC_SHIFT;
- mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
+ stbc = (sta_cap & IEEE80211_HT_CAP_RX_STBC) >>
+ IEEE80211_HT_CAP_RX_STBC_SHIFT;
+ mi->tx_flags |= stbc << IEEE80211_TX_CTL_STBC_SHIFT;
- if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)
- mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
- }
+ if (sta_cap & IEEE80211_HT_CAP_LDPC_CODING)
+ mi->tx_flags |= IEEE80211_TX_CTL_LDPC;
for (i = 0; i < ARRAY_SIZE(mi->groups); i++) {
- u32 gflags = minstrel_mcs_groups[i].flags;
- int bw, nss;
-
mi->groups[i].supported = 0;
if (i == MINSTREL_CCK_GROUP) {
minstrel_ht_update_cck(mp, mi, sband, sta);
continue;
}
- if (gflags & IEEE80211_TX_RC_SHORT_GI) {
- if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
+ if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_SHORT_GI) {
+ if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
if (!(sta_cap & IEEE80211_HT_CAP_SGI_40))
continue;
} else {
@@ -1178,51 +1021,17 @@
}
}
- if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH &&
+ if (minstrel_mcs_groups[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH &&
sta->bandwidth < IEEE80211_STA_RX_BW_40)
continue;
- nss = minstrel_mcs_groups[i].streams;
-
/* Mark MCS > 7 as unsupported if STA is in static SMPS mode */
- if (sta->smps_mode == IEEE80211_SMPS_STATIC && nss > 1)
+ if (sta->smps_mode == IEEE80211_SMPS_STATIC &&
+ minstrel_mcs_groups[i].streams > 1)
continue;
- /* HT rate */
- if (gflags & IEEE80211_TX_RC_MCS) {
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
- if (use_vht && minstrel_vht_only)
- continue;
-#endif
- mi->groups[i].supported = mcs->rx_mask[nss - 1];
- if (mi->groups[i].supported)
- n_supported++;
- continue;
- }
-
- /* VHT rate */
- if (!vht_cap->vht_supported ||
- WARN_ON(!(gflags & IEEE80211_TX_RC_VHT_MCS)) ||
- WARN_ON(gflags & IEEE80211_TX_RC_160_MHZ_WIDTH))
- continue;
-
- if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH) {
- if (sta->bandwidth < IEEE80211_STA_RX_BW_80 ||
- ((gflags & IEEE80211_TX_RC_SHORT_GI) &&
- !(vht_cap->cap & IEEE80211_VHT_CAP_SHORT_GI_80))) {
- continue;
- }
- }
-
- if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
- bw = BW_40;
- else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
- bw = BW_80;
- else
- bw = BW_20;
-
- mi->groups[i].supported = minstrel_get_valid_vht_rates(bw, nss,
- vht_cap->vht_mcs.tx_mcs_map);
+ mi->groups[i].supported =
+ mcs->rx_mask[minstrel_mcs_groups[i].streams - 1];
if (mi->groups[i].supported)
n_supported++;
@@ -1340,7 +1149,7 @@
static const struct rate_control_ops mac80211_minstrel_ht = {
.name = "minstrel_ht",
- .tx_status_noskb = minstrel_ht_tx_status,
+ .tx_status = minstrel_ht_tx_status,
.get_rate = minstrel_ht_get_rate,
.rate_init = minstrel_ht_rate_init,
.rate_update = minstrel_ht_rate_update,
diff --git a/net/mac80211/rc80211_minstrel_ht.h b/net/mac80211/rc80211_minstrel_ht.h
index a1f74f5..0a76823 100644
--- a/net/mac80211/rc80211_minstrel_ht.h
+++ b/net/mac80211/rc80211_minstrel_ht.h
@@ -13,32 +13,10 @@
* The number of streams can be changed to 2 to reduce code
* size and memory footprint.
*/
-#define MINSTREL_MAX_STREAMS 3
-#define MINSTREL_HT_STREAM_GROUPS 4 /* BW(=2) * SGI(=2) */
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
-#define MINSTREL_VHT_STREAM_GROUPS 6 /* BW(=3) * SGI(=2) */
-#else
-#define MINSTREL_VHT_STREAM_GROUPS 0
-#endif
+#define MINSTREL_MAX_STREAMS 3
+#define MINSTREL_STREAM_GROUPS 4
-#define MINSTREL_HT_GROUPS_NB (MINSTREL_MAX_STREAMS * \
- MINSTREL_HT_STREAM_GROUPS)
-#define MINSTREL_VHT_GROUPS_NB (MINSTREL_MAX_STREAMS * \
- MINSTREL_VHT_STREAM_GROUPS)
-#define MINSTREL_CCK_GROUPS_NB 1
-#define MINSTREL_GROUPS_NB (MINSTREL_HT_GROUPS_NB + \
- MINSTREL_VHT_GROUPS_NB + \
- MINSTREL_CCK_GROUPS_NB)
-
-#define MINSTREL_HT_GROUP_0 0
-#define MINSTREL_CCK_GROUP (MINSTREL_HT_GROUP_0 + MINSTREL_HT_GROUPS_NB)
-#define MINSTREL_VHT_GROUP_0 (MINSTREL_CCK_GROUP + 1)
-
-#ifdef CPTCFG_MAC80211_RC_MINSTREL_VHT
-#define MCS_GROUP_RATES 10
-#else
-#define MCS_GROUP_RATES 8
-#endif
+#define MCS_GROUP_RATES 8
struct mcs_group {
u32 flags;
@@ -53,11 +31,11 @@
u8 column;
/* bitfield of supported MCS rates of this group */
- u16 supported;
+ u8 supported;
/* sorted rate set within a MCS group*/
- u16 max_group_tp_rate[MAX_THR_RATES];
- u16 max_group_prob_rate;
+ u8 max_group_tp_rate[MAX_THR_RATES];
+ u8 max_group_prob_rate;
/* MCS rate statistics */
struct minstrel_rate_stats rates[MCS_GROUP_RATES];
@@ -74,8 +52,8 @@
unsigned int avg_ampdu_len;
/* overall sorted rate set */
- u16 max_tp_rate[MAX_THR_RATES];
- u16 max_prob_rate;
+ u8 max_tp_rate[MAX_THR_RATES];
+ u8 max_prob_rate;
/* time of last status update */
unsigned long stats_update;
@@ -102,7 +80,7 @@
u8 cck_supported_short;
/* MCS rate group info and statistics */
- struct minstrel_mcs_group_data groups[MINSTREL_GROUPS_NB];
+ struct minstrel_mcs_group_data groups[MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS + 1];
};
struct minstrel_ht_sta_priv {
diff --git a/net/mac80211/rc80211_minstrel_ht_debugfs.c b/net/mac80211/rc80211_minstrel_ht_debugfs.c
index 20c676b..a72ad46 100644
--- a/net/mac80211/rc80211_minstrel_ht_debugfs.c
+++ b/net/mac80211/rc80211_minstrel_ht_debugfs.c
@@ -18,23 +18,19 @@
static char *
minstrel_ht_stats_dump(struct minstrel_ht_sta *mi, int i, char *p)
{
+ unsigned int max_mcs = MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS;
const struct mcs_group *mg;
unsigned int j, tp, prob, eprob;
char htmode = '2';
char gimode = 'L';
- u32 gflags;
if (!mi->groups[i].supported)
return p;
mg = &minstrel_mcs_groups[i];
- gflags = mg->flags;
-
- if (gflags & IEEE80211_TX_RC_40_MHZ_WIDTH)
+ if (mg->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
htmode = '4';
- else if (gflags & IEEE80211_TX_RC_80_MHZ_WIDTH)
- htmode = '8';
- if (gflags & IEEE80211_TX_RC_SHORT_GI)
+ if (mg->flags & IEEE80211_TX_RC_SHORT_GI)
gimode = 'S';
for (j = 0; j < MCS_GROUP_RATES; j++) {
@@ -45,12 +41,10 @@
if (!(mi->groups[i].supported & BIT(j)))
continue;
- if (gflags & IEEE80211_TX_RC_MCS)
- p += sprintf(p, " HT%c0/%cGI ", htmode, gimode);
- else if (gflags & IEEE80211_TX_RC_VHT_MCS)
- p += sprintf(p, "VHT%c0/%cGI ", htmode, gimode);
+ if (i == max_mcs)
+ p += sprintf(p, "CCK/%cP ", j < 4 ? 'L' : 'S');
else
- p += sprintf(p, " CCK/%cP ", j < 4 ? 'L' : 'S');
+ p += sprintf(p, "HT%c0/%cGI ", htmode, gimode);
*(p++) = (idx == mi->max_tp_rate[0]) ? 'A' : ' ';
*(p++) = (idx == mi->max_tp_rate[1]) ? 'B' : ' ';
@@ -58,22 +52,19 @@
*(p++) = (idx == mi->max_tp_rate[3]) ? 'D' : ' ';
*(p++) = (idx == mi->max_prob_rate) ? 'P' : ' ';
- if (gflags & IEEE80211_TX_RC_MCS) {
- p += sprintf(p, " MCS%-2u ", (mg->streams - 1) * 8 + j);
- } else if (gflags & IEEE80211_TX_RC_VHT_MCS) {
- p += sprintf(p, " MCS%-1u/%1u", j, mg->streams);
- } else {
+ if (i == max_mcs) {
int r = bitrates[j % 4];
-
- p += sprintf(p, " %2u.%1uM ", r / 10, r % 10);
+ p += sprintf(p, " %2u.%1uM", r / 10, r % 10);
+ } else {
+ p += sprintf(p, " MCS%-2u", (mg->streams - 1) * 8 + j);
}
tp = mr->cur_tp / 10;
prob = MINSTREL_TRUNC(mr->cur_prob * 1000);
eprob = MINSTREL_TRUNC(mr->probability * 1000);
- p += sprintf(p, " %4u.%1u %3u.%1u %3u.%1u "
- "%3u %4u(%4u) %9llu(%9llu)\n",
+ p += sprintf(p, " %6u.%1u %6u.%1u %6u.%1u "
+ "%3u %3u(%3u) %8llu %8llu\n",
tp / 10, tp % 10,
eprob / 10, eprob % 10,
prob / 10, prob % 10,
@@ -94,6 +85,7 @@
struct minstrel_ht_sta *mi = &msp->ht;
struct minstrel_debugfs_info *ms;
unsigned int i;
+ unsigned int max_mcs = MINSTREL_MAX_STREAMS * MINSTREL_STREAM_GROUPS;
char *p;
int ret;
@@ -104,19 +96,17 @@
return ret;
}
- ms = kmalloc(32768, GFP_KERNEL);
+ ms = kmalloc(sizeof(*ms) + 8192, GFP_KERNEL);
if (!ms)
return -ENOMEM;
file->private_data = ms;
p = ms->buf;
- p += sprintf(p, " type rate tpt eprob *prob "
- "ret *ok(*cum) ok( cum)\n");
+ p += sprintf(p, "type rate throughput ewma prob "
+ "this prob retry this succ/attempt success attempts\n");
- p = minstrel_ht_stats_dump(mi, MINSTREL_CCK_GROUP, p);
- for (i = 0; i < MINSTREL_CCK_GROUP; i++)
- p = minstrel_ht_stats_dump(mi, i, p);
- for (i++; i < ARRAY_SIZE(mi->groups); i++)
+ p = minstrel_ht_stats_dump(mi, max_mcs, p);
+ for (i = 0; i < max_mcs; i++)
p = minstrel_ht_stats_dump(mi, i, p);
p += sprintf(p, "\nTotal packet count:: ideal %d "
@@ -128,8 +118,6 @@
MINSTREL_TRUNC(mi->avg_ampdu_len * 10) % 10);
ms->len = p - ms->buf;
- WARN_ON(ms->len + sizeof(*ms) > 32768);
-
return nonseekable_open(inode, file);
}
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 7560231..21d7259 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -39,8 +39,7 @@
* only useful for monitoring.
*/
static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
- struct sk_buff *skb,
- unsigned int rtap_vendor_space)
+ struct sk_buff *skb)
{
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
if (likely(skb->len > FCS_LEN))
@@ -53,25 +52,20 @@
}
}
- __pskb_pull(skb, rtap_vendor_space);
-
return skb;
}
-static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len,
- unsigned int rtap_vendor_space)
+static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len)
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
- struct ieee80211_hdr *hdr;
-
- hdr = (void *)(skb->data + rtap_vendor_space);
+ struct ieee80211_hdr *hdr = (void *)skb->data;
if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
RX_FLAG_FAILED_PLCP_CRC |
RX_FLAG_AMPDU_IS_ZEROLEN))
return true;
- if (unlikely(skb->len < 16 + present_fcs_len + rtap_vendor_space))
+ if (unlikely(skb->len < 16 + present_fcs_len))
return true;
if (ieee80211_is_ctl(hdr->frame_control) &&
@@ -83,9 +77,8 @@
}
static int
-ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
- struct ieee80211_rx_status *status,
- struct sk_buff *skb)
+ieee80211_rx_radiotap_space(struct ieee80211_local *local,
+ struct ieee80211_rx_status *status)
{
int len;
@@ -128,21 +121,6 @@
len += 2 * hweight8(status->chains);
}
- if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
- struct ieee80211_vendor_radiotap *rtap = (void *)skb->data;
-
- /* vendor presence bitmap */
- len += 4;
- /* alignment for fixed 6-byte vendor data header */
- len = ALIGN(len, 2);
- /* vendor data header */
- len += 6;
- if (WARN_ON(rtap->align == 0))
- rtap->align = 1;
- len = ALIGN(len, rtap->align);
- len += rtap->len + rtap->pad;
- }
-
return len;
}
@@ -166,20 +144,13 @@
u16 channel_flags = 0;
int mpdulen, chain;
unsigned long chains = status->chains;
- struct ieee80211_vendor_radiotap rtap = {};
-
- if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
- rtap = *(struct ieee80211_vendor_radiotap *)skb->data;
- /* rtap.len and rtap.pad are undone immediately */
- skb_pull(skb, sizeof(rtap) + rtap.len + rtap.pad);
- }
mpdulen = skb->len;
if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)))
mpdulen += FCS_LEN;
rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
- memset(rthdr, 0, rtap_len - rtap.len - rtap.pad);
+ memset(rthdr, 0, rtap_len);
it_present = &rthdr->it_present;
/* radiotap header, set always present flags */
@@ -201,14 +172,6 @@
BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
}
- if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
- it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) |
- BIT(IEEE80211_RADIOTAP_EXT);
- put_unaligned_le32(it_present_val, it_present);
- it_present++;
- it_present_val = rtap.present;
- }
-
put_unaligned_le32(it_present_val, it_present);
pos = (void *)(it_present + 1);
@@ -403,22 +366,6 @@
*pos++ = status->chain_signal[chain];
*pos++ = chain;
}
-
- if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
- /* ensure 2 byte alignment for the vendor field as required */
- if ((pos - (u8 *)rthdr) & 1)
- *pos++ = 0;
- *pos++ = rtap.oui[0];
- *pos++ = rtap.oui[1];
- *pos++ = rtap.oui[2];
- *pos++ = rtap.subns;
- put_unaligned_le16(rtap.len, pos);
- pos += 2;
- /* align the actual payload as requested */
- while ((pos - (u8 *)rthdr) & (rtap.align - 1))
- *pos++ = 0;
- /* data (and possible padding) already follows */
- }
}
/*
@@ -432,17 +379,10 @@
{
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(origskb);
struct ieee80211_sub_if_data *sdata;
- int rt_hdrlen, needed_headroom;
+ int needed_headroom;
struct sk_buff *skb, *skb2;
struct net_device *prev_dev = NULL;
int present_fcs_len = 0;
- unsigned int rtap_vendor_space = 0;
-
- if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) {
- struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data;
-
- rtap_vendor_space = sizeof(*rtap) + rtap->len + rtap->pad;
- }
/*
* First, we may need to make a copy of the skb because
@@ -456,27 +396,25 @@
if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
present_fcs_len = FCS_LEN;
- /* ensure hdr->frame_control and vendor radiotap data are in skb head */
- if (!pskb_may_pull(origskb, 2 + rtap_vendor_space)) {
+ /* ensure hdr->frame_control is in skb head */
+ if (!pskb_may_pull(origskb, 2)) {
dev_kfree_skb(origskb);
return NULL;
}
if (!local->monitors) {
- if (should_drop_frame(origskb, present_fcs_len,
- rtap_vendor_space)) {
+ if (should_drop_frame(origskb, present_fcs_len)) {
dev_kfree_skb(origskb);
return NULL;
}
- return remove_monitor_info(local, origskb, rtap_vendor_space);
+ return remove_monitor_info(local, origskb);
}
/* room for the radiotap header based on driver features */
- rt_hdrlen = ieee80211_rx_radiotap_hdrlen(local, status, origskb);
- needed_headroom = rt_hdrlen - rtap_vendor_space;
+ needed_headroom = ieee80211_rx_radiotap_space(local, status);
- if (should_drop_frame(origskb, present_fcs_len, rtap_vendor_space)) {
+ if (should_drop_frame(origskb, present_fcs_len)) {
/* only need to expand headroom if necessary */
skb = origskb;
origskb = NULL;
@@ -500,15 +438,15 @@
*/
skb = skb_copy_expand(origskb, needed_headroom, 0, GFP_ATOMIC);
- origskb = remove_monitor_info(local, origskb,
- rtap_vendor_space);
+ origskb = remove_monitor_info(local, origskb);
if (!skb)
return origskb;
}
/* prepend radiotap information */
- ieee80211_add_rx_radiotap_header(local, skb, rate, rt_hdrlen, true);
+ ieee80211_add_rx_radiotap_header(local, skb, rate, needed_headroom,
+ true);
skb_reset_mac_header(skb);
skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1047,7 +985,7 @@
}
static ieee80211_rx_result debug_noinline
-ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
+ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
@@ -1056,16 +994,10 @@
* Drop duplicate 802.11 retransmissions
* (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
*/
-
- if (rx->skb->len < 24)
- return RX_CONTINUE;
-
- if (ieee80211_is_ctl(hdr->frame_control) ||
- ieee80211_is_qos_nullfunc(hdr->frame_control) ||
- is_multicast_ether_addr(hdr->addr1))
- return RX_CONTINUE;
-
- if (rx->sta) {
+ if (rx->skb->len >= 24 && rx->sta &&
+ !ieee80211_is_ctl(hdr->frame_control) &&
+ !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
+ !is_multicast_ether_addr(hdr->addr1)) {
if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
rx->sta->last_seq_ctrl[rx->seqno_idx] ==
hdr->seq_ctrl)) {
@@ -1079,14 +1011,6 @@
}
}
- return RX_CONTINUE;
-}
-
-static ieee80211_rx_result debug_noinline
-ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
-
if (unlikely(rx->skb->len < 16)) {
I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
return RX_DROP_MONITOR;
@@ -1108,7 +1032,6 @@
ieee80211_is_pspoll(hdr->frame_control)) &&
rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
rx->sdata->vif.type != NL80211_IFTYPE_WDS &&
- rx->sdata->vif.type != NL80211_IFTYPE_OCB &&
(!rx->sta || !test_sta_flag(rx->sta, WLAN_STA_ASSOC)))) {
/*
* accept port control frames from the AP even when it's not
@@ -1349,12 +1272,6 @@
sta->last_rx_rate_vht_nss = status->vht_nss;
}
}
- } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
- u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
- NL80211_IFTYPE_OCB);
- /* OCB uses wild-card BSSID */
- if (is_broadcast_ether_addr(bssid))
- sta->last_rx = jiffies;
} else if (!is_multicast_ether_addr(hdr->addr1)) {
/*
* Mesh beacons will update last_rx when if they are found to
@@ -1761,14 +1678,11 @@
sc = le16_to_cpu(hdr->seq_ctrl);
frag = sc & IEEE80211_SCTL_FRAG;
- if (is_multicast_ether_addr(hdr->addr1)) {
- rx->local->dot11MulticastReceivedFrameCount++;
- goto out_no_led;
- }
-
- if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
+ if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
+ is_multicast_ether_addr(hdr->addr1))) {
+ /* not fragmented */
goto out;
-
+ }
I802_DEBUG_INC(rx->local->rx_handlers_fragments);
if (skb_linearize(rx->skb))
@@ -1859,10 +1773,12 @@
status->rx_flags |= IEEE80211_RX_FRAGMENTED;
out:
- ieee80211_led_rx(rx->local);
- out_no_led:
if (rx->sta)
rx->sta->rx_packets++;
+ if (is_multicast_ether_addr(hdr->addr1))
+ rx->local->dot11MulticastReceivedFrameCount++;
+ else
+ ieee80211_led_rx(rx->local);
return RX_CONTINUE;
}
@@ -2345,27 +2261,6 @@
if (!ieee80211_frame_allowed(rx, fc))
return RX_DROP_MONITOR;
- /* directly handle TDLS channel switch requests/responses */
- if (unlikely(((struct ethhdr *)rx->skb->data)->h_proto ==
- cpu_to_be16(ETH_P_TDLS))) {
- struct ieee80211_tdls_data *tf = (void *)rx->skb->data;
-
- if (pskb_may_pull(rx->skb,
- offsetof(struct ieee80211_tdls_data, u)) &&
- tf->payload_type == WLAN_TDLS_SNAP_RFTYPE &&
- tf->category == WLAN_CATEGORY_TDLS &&
- (tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST ||
- tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE)) {
- rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TDLS_CHSW;
- skb_queue_tail(&sdata->skb_queue, rx->skb);
- ieee80211_queue_work(&rx->local->hw, &sdata->work);
- if (rx->sta)
- rx->sta->rx_packets++;
-
- return RX_QUEUED;
- }
- }
-
if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
unlikely(port_control) && sdata->bss) {
sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
@@ -2936,7 +2831,6 @@
if (!ieee80211_vif_is_mesh(&sdata->vif) &&
sdata->vif.type != NL80211_IFTYPE_ADHOC &&
- sdata->vif.type != NL80211_IFTYPE_OCB &&
sdata->vif.type != NL80211_IFTYPE_STATION)
return RX_DROP_MONITOR;
@@ -3001,10 +2895,8 @@
if (!local->cooked_mntrs)
goto out_free_skb;
- /* vendor data is long removed here */
- status->flag &= ~RX_FLAG_RADIOTAP_VENDOR_DATA;
/* room for the radiotap header based on driver features */
- needed_headroom = ieee80211_rx_radiotap_hdrlen(local, status, skb);
+ needed_headroom = ieee80211_rx_radiotap_space(local, status);
if (skb_headroom(skb) < needed_headroom &&
pskb_expand_head(skb, needed_headroom, 0, GFP_ATOMIC))
@@ -3157,7 +3049,6 @@
goto rxh_next; \
} while (0);
- CALL_RXH(ieee80211_rx_h_check_dup)
CALL_RXH(ieee80211_rx_h_check)
ieee80211_rx_reorder_ampdu(rx, &reorder_release);
@@ -3250,33 +3141,6 @@
BIT(rate_idx));
}
break;
- case NL80211_IFTYPE_OCB:
- if (!bssid)
- return false;
- if (ieee80211_is_beacon(hdr->frame_control)) {
- return false;
- } else if (!is_broadcast_ether_addr(bssid)) {
- ocb_dbg(sdata, "BSSID mismatch in OCB mode!\n");
- return false;
- } else if (!multicast &&
- !ether_addr_equal(sdata->dev->dev_addr,
- hdr->addr1)) {
- /* if we are in promisc mode we also accept
- * packets not destined for us
- */
- if (!(sdata->dev->flags & IFF_PROMISC))
- return false;
- rx->flags &= ~IEEE80211_RX_RA_MATCH;
- } else if (!rx->sta) {
- int rate_idx;
- if (status->flag & RX_FLAG_HT)
- rate_idx = 0; /* TODO: HT rates */
- else
- rate_idx = status->rate_idx;
- ieee80211_ocb_rx_no_sta(sdata, bssid, hdr->addr2,
- BIT(rate_idx));
- }
- break;
case NL80211_IFTYPE_MESH_POINT:
if (!multicast &&
!ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index ae84267..af0d094 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -184,21 +184,9 @@
return;
if (ieee80211_is_probe_resp(mgmt->frame_control)) {
- struct cfg80211_scan_request *scan_req;
- struct cfg80211_sched_scan_request *sched_scan_req;
-
- scan_req = rcu_dereference(local->scan_req);
- sched_scan_req = rcu_dereference(local->sched_scan_req);
-
- /* ignore ProbeResp to foreign address unless scanning
- * with randomised address
- */
- if (!(sdata1 &&
- (ether_addr_equal(mgmt->da, sdata1->vif.addr) ||
- scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)) &&
- !(sdata2 &&
- (ether_addr_equal(mgmt->da, sdata2->vif.addr) ||
- sched_scan_req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)))
+ /* ignore ProbeResp to foreign address */
+ if ((!sdata1 || !ether_addr_equal(mgmt->da, sdata1->vif.addr)) &&
+ (!sdata2 || !ether_addr_equal(mgmt->da, sdata2->vif.addr)))
return;
elements = mgmt->u.probe_resp.variable;
@@ -246,14 +234,11 @@
/* return false if no more work */
static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
{
- struct cfg80211_scan_request *req;
+ struct cfg80211_scan_request *req = local->scan_req;
struct cfg80211_chan_def chandef;
u8 bands_used = 0;
int i, ielen, n_chans;
- req = rcu_dereference_protected(local->scan_req,
- lockdep_is_held(&local->mtx));
-
if (test_bit(SCAN_HW_CANCELLED, &local->scanning))
return false;
@@ -296,9 +281,6 @@
bands_used, req->rates, &chandef);
local->hw_scan_req->req.ie_len = ielen;
local->hw_scan_req->req.no_cck = req->no_cck;
- ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr);
- ether_addr_copy(local->hw_scan_req->req.mac_addr_mask,
- req->mac_addr_mask);
return true;
}
@@ -308,8 +290,6 @@
struct ieee80211_local *local = hw_to_local(hw);
bool hw_scan = local->ops->hw_scan;
bool was_scanning = local->scanning;
- struct cfg80211_scan_request *scan_req;
- struct ieee80211_sub_if_data *scan_sdata;
lockdep_assert_held(&local->mtx);
@@ -342,15 +322,9 @@
kfree(local->hw_scan_req);
local->hw_scan_req = NULL;
- scan_req = rcu_dereference_protected(local->scan_req,
- lockdep_is_held(&local->mtx));
-
- if (scan_req != local->int_scan_req)
- cfg80211_scan_done(scan_req, aborted);
- RCU_INIT_POINTER(local->scan_req, NULL);
-
- scan_sdata = rcu_dereference_protected(local->scan_sdata,
- lockdep_is_held(&local->mtx));
+ if (local->scan_req != local->int_scan_req)
+ cfg80211_scan_done(local->scan_req, aborted);
+ local->scan_req = NULL;
RCU_INIT_POINTER(local->scan_sdata, NULL);
local->scanning = 0;
@@ -361,7 +335,7 @@
if (!hw_scan) {
ieee80211_configure_filter(local);
- drv_sw_scan_complete(local, scan_sdata);
+ drv_sw_scan_complete(local);
ieee80211_offchannel_return(local);
}
@@ -387,8 +361,7 @@
}
EXPORT_SYMBOL(ieee80211_scan_completed);
-static int ieee80211_start_sw_scan(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata)
+static int ieee80211_start_sw_scan(struct ieee80211_local *local)
{
/* Software scan is not supported in multi-channel cases */
if (local->use_chanctx)
@@ -407,7 +380,7 @@
* nullfunc frames and probe requests will be dropped in
* ieee80211_tx_h_check_assoc().
*/
- drv_sw_scan_start(local, sdata, local->scan_addr);
+ drv_sw_scan_start(local);
local->leave_oper_channel_time = jiffies;
local->next_scan_state = SCAN_DECISION;
@@ -467,26 +440,23 @@
{
int i;
struct ieee80211_sub_if_data *sdata;
- struct cfg80211_scan_request *scan_req;
enum ieee80211_band band = local->hw.conf.chandef.chan->band;
u32 tx_flags;
- scan_req = rcu_dereference_protected(local->scan_req,
- lockdep_is_held(&local->mtx));
-
tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
- if (scan_req->no_cck)
+ if (local->scan_req->no_cck)
tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
sdata = rcu_dereference_protected(local->scan_sdata,
lockdep_is_held(&local->mtx));
- for (i = 0; i < scan_req->n_ssids; i++)
+ for (i = 0; i < local->scan_req->n_ssids; i++)
ieee80211_send_probe_req(
- sdata, local->scan_addr, NULL,
- scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len,
- scan_req->ie, scan_req->ie_len,
- scan_req->rates[band], false,
+ sdata, NULL,
+ local->scan_req->ssids[i].ssid,
+ local->scan_req->ssids[i].ssid_len,
+ local->scan_req->ie, local->scan_req->ie_len,
+ local->scan_req->rates[band], false,
tx_flags, local->hw.conf.chandef.chan, true);
/*
@@ -510,7 +480,7 @@
if (!ieee80211_can_scan(local, sdata)) {
/* wait for the work to finish/time out */
- rcu_assign_pointer(local->scan_req, req);
+ local->scan_req = req;
rcu_assign_pointer(local->scan_sdata, sdata);
return 0;
}
@@ -560,16 +530,9 @@
*/
}
- rcu_assign_pointer(local->scan_req, req);
+ local->scan_req = req;
rcu_assign_pointer(local->scan_sdata, sdata);
- if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
- get_random_mask_addr(local->scan_addr,
- req->mac_addr,
- req->mac_addr_mask);
- else
- memcpy(local->scan_addr, sdata->vif.addr, ETH_ALEN);
-
if (local->ops->hw_scan) {
__set_bit(SCAN_HW_SCANNING, &local->scanning);
} else if ((req->n_channels == 1) &&
@@ -586,7 +549,7 @@
/* Notify driver scan is starting, keep order of operations
* same as normal software scan, in case that matters. */
- drv_sw_scan_start(local, sdata, local->scan_addr);
+ drv_sw_scan_start(local);
ieee80211_configure_filter(local); /* accept probe-responses */
@@ -595,7 +558,7 @@
if ((req->channels[0]->flags &
IEEE80211_CHAN_NO_IR) ||
- !req->n_ssids) {
+ !local->scan_req->n_ssids) {
next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
} else {
ieee80211_scan_state_send_probe(local, &next_delay);
@@ -616,9 +579,8 @@
if (local->ops->hw_scan) {
WARN_ON(!ieee80211_prep_hw_scan(local));
rc = drv_hw_scan(local, sdata, local->hw_scan_req);
- } else {
- rc = ieee80211_start_sw_scan(local, sdata);
- }
+ } else
+ rc = ieee80211_start_sw_scan(local);
if (rc) {
kfree(local->hw_scan_req);
@@ -655,7 +617,6 @@
struct ieee80211_sub_if_data *sdata;
struct ieee80211_channel *next_chan;
enum mac80211_scan_state next_scan_state;
- struct cfg80211_scan_request *scan_req;
/*
* check if at least one STA interface is associated,
@@ -680,10 +641,7 @@
}
mutex_unlock(&local->iflist_mtx);
- scan_req = rcu_dereference_protected(local->scan_req,
- lockdep_is_held(&local->mtx));
-
- next_chan = scan_req->channels[local->scan_channel_idx];
+ next_chan = local->scan_req->channels[local->scan_channel_idx];
/*
* we're currently scanning a different channel, let's
@@ -698,7 +656,7 @@
local->leave_oper_channel_time + HZ / 8);
if (associated && !tx_empty) {
- if (scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
+ if (local->scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
next_scan_state = SCAN_ABORT;
else
next_scan_state = SCAN_SUSPEND;
@@ -719,18 +677,14 @@
int skip;
struct ieee80211_channel *chan;
enum nl80211_bss_scan_width oper_scan_width;
- struct cfg80211_scan_request *scan_req;
-
- scan_req = rcu_dereference_protected(local->scan_req,
- lockdep_is_held(&local->mtx));
skip = 0;
- chan = scan_req->channels[local->scan_channel_idx];
+ chan = local->scan_req->channels[local->scan_channel_idx];
local->scan_chandef.chan = chan;
local->scan_chandef.center_freq1 = chan->center_freq;
local->scan_chandef.center_freq2 = 0;
- switch (scan_req->scan_width) {
+ switch (local->scan_req->scan_width) {
case NL80211_BSS_CHAN_WIDTH_5:
local->scan_chandef.width = NL80211_CHAN_WIDTH_5;
break;
@@ -744,7 +698,7 @@
oper_scan_width = cfg80211_chandef_to_scan_width(
&local->_oper_chandef);
if (chan == local->_oper_chandef.chan &&
- oper_scan_width == scan_req->scan_width)
+ oper_scan_width == local->scan_req->scan_width)
local->scan_chandef = local->_oper_chandef;
else
local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
@@ -773,7 +727,8 @@
*
* In any case, it is not necessary for a passive scan.
*/
- if (chan->flags & IEEE80211_CHAN_NO_IR || !scan_req->n_ssids) {
+ if (chan->flags & IEEE80211_CHAN_NO_IR ||
+ !local->scan_req->n_ssids) {
*next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
local->next_scan_state = SCAN_DECISION;
return;
@@ -822,7 +777,6 @@
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, scan_work.work);
struct ieee80211_sub_if_data *sdata;
- struct cfg80211_scan_request *scan_req;
unsigned long next_delay = 0;
bool aborted;
@@ -830,8 +784,6 @@
sdata = rcu_dereference_protected(local->scan_sdata,
lockdep_is_held(&local->mtx));
- scan_req = rcu_dereference_protected(local->scan_req,
- lockdep_is_held(&local->mtx));
/* When scanning on-channel, the first-callback means completed. */
if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
@@ -844,19 +796,20 @@
goto out_complete;
}
- if (!sdata || !scan_req)
+ if (!sdata || !local->scan_req)
goto out;
- if (!local->scanning) {
+ if (local->scan_req && !local->scanning) {
+ struct cfg80211_scan_request *req = local->scan_req;
int rc;
- RCU_INIT_POINTER(local->scan_req, NULL);
+ local->scan_req = NULL;
RCU_INIT_POINTER(local->scan_sdata, NULL);
- rc = __ieee80211_start_scan(sdata, scan_req);
+ rc = __ieee80211_start_scan(sdata, req);
if (rc) {
/* need to complete scan in cfg80211 */
- rcu_assign_pointer(local->scan_req, scan_req);
+ local->scan_req = req;
aborted = true;
goto out_complete;
} else
@@ -876,7 +829,7 @@
switch (local->next_scan_state) {
case SCAN_DECISION:
/* if no more bands/channels left, complete scan */
- if (local->scan_channel_idx >= scan_req->n_channels) {
+ if (local->scan_channel_idx >= local->scan_req->n_channels) {
aborted = false;
goto out_complete;
}
@@ -1090,7 +1043,7 @@
ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
if (ret == 0) {
rcu_assign_pointer(local->sched_scan_sdata, sdata);
- rcu_assign_pointer(local->sched_scan_req, req);
+ local->sched_scan_req = req;
}
kfree(ie);
@@ -1099,7 +1052,7 @@
if (ret) {
/* Clean in case of failure after HW restart or upon resume. */
RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
- RCU_INIT_POINTER(local->sched_scan_req, NULL);
+ local->sched_scan_req = NULL;
}
return ret;
@@ -1137,7 +1090,7 @@
}
/* We don't want to restart sched scan anymore. */
- RCU_INIT_POINTER(local->sched_scan_req, NULL);
+ local->sched_scan_req = NULL;
if (rcu_access_pointer(local->sched_scan_sdata)) {
ret = drv_sched_scan_stop(local, sdata);
@@ -1172,7 +1125,7 @@
RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
/* If sched scan was aborted by the driver. */
- RCU_INIT_POINTER(local->sched_scan_req, NULL);
+ local->sched_scan_req = NULL;
mutex_unlock(&local->mtx);
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index efeba56..6ab0090 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -22,7 +22,7 @@
#include "wme.h"
int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
- struct ieee802_11_elems *elems,
+ struct ieee802_11_elems *elems, bool beacon,
enum ieee80211_band current_band,
u32 sta_flags, u8 *bssid,
struct ieee80211_csa_ie *csa_ie)
@@ -91,13 +91,19 @@
return -EINVAL;
}
- if (sec_chan_offs) {
+ if (!beacon && sec_chan_offs) {
secondary_channel_offset = sec_chan_offs->sec_chan_offs;
+ } else if (beacon && ht_oper) {
+ secondary_channel_offset =
+ ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET;
} else if (!(sta_flags & IEEE80211_STA_DISABLE_HT)) {
- /* If the secondary channel offset IE is not present,
- * we can't know what's the post-CSA offset, so the
- * best we can do is use 20MHz.
- */
+ /* If it's not a beacon, HT is enabled and the IE not present,
+ * it's 20 MHz, 802.11-2012 8.5.2.6:
+ * This element [the Secondary Channel Offset Element] is
+ * present when switching to a 40 MHz channel. It may be
+ * present when switching to a 20 MHz channel (in which
+ * case the secondary channel offset is set to SCN).
+ */
secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE;
}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index ca80ce0..9cefdbd 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -351,9 +351,6 @@
sta->sta_state = IEEE80211_STA_NONE;
- /* Mark TID as unreserved */
- sta->reserved_tid = IEEE80211_TID_UNRESERVED;
-
ktime_get_ts(&uptime);
sta->last_connected = uptime.tv_sec;
ewma_init(&sta->avg_signal, 1024, 8);
@@ -504,7 +501,7 @@
/* make the station visible */
sta_info_hash_add(local, sta);
- list_add_tail_rcu(&sta->list, &local->sta_list);
+ list_add_rcu(&sta->list, &local->sta_list);
/* notify driver */
err = sta_info_insert_drv_state(local, sdata, sta);
@@ -850,15 +847,6 @@
if (WARN_ON(ret))
return ret;
- /*
- * for TDLS peers, make sure to return to the base channel before
- * removal.
- */
- if (test_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL)) {
- drv_tdls_cancel_channel_switch(local, sdata, &sta->sta);
- clear_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL);
- }
-
list_del_rcu(&sta->list);
drv_sta_pre_rcu_remove(local, sta->sdata, sta);
@@ -1261,8 +1249,7 @@
return;
}
- info->band = chanctx_conf->def.chan->band;
- ieee80211_xmit(sdata, skb);
+ ieee80211_xmit(sdata, skb, chanctx_conf->def.chan->band);
rcu_read_unlock();
}
@@ -1544,7 +1531,7 @@
break;
case 0:
/* XXX: what is a good value? */
- n_frames = 128;
+ n_frames = 8;
break;
}
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 4370931..3aabd74 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -49,9 +49,6 @@
* packets. This means the link is enabled.
* @WLAN_STA_TDLS_INITIATOR: We are the initiator of the TDLS link with this
* station.
- * @WLAN_STA_TDLS_CHAN_SWITCH: This TDLS peer supports TDLS channel-switching
- * @WLAN_STA_TDLS_OFF_CHANNEL: The local STA is currently off-channel with this
- * TDLS peer
* @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was
* keeping station in power-save mode, reply when the driver
* unblocks the station.
@@ -81,8 +78,6 @@
WLAN_STA_TDLS_PEER,
WLAN_STA_TDLS_PEER_AUTH,
WLAN_STA_TDLS_INITIATOR,
- WLAN_STA_TDLS_CHAN_SWITCH,
- WLAN_STA_TDLS_OFF_CHANNEL,
WLAN_STA_UAPSD,
WLAN_STA_SP,
WLAN_STA_4ADDR_EVENT,
@@ -254,9 +249,6 @@
u32 bin_count;
};
-/* Value to indicate no TID reservation */
-#define IEEE80211_TID_UNRESERVED 0xff
-
/**
* struct sta_info - STA information
*
@@ -344,8 +336,6 @@
* @known_smps_mode: the smps_mode the client thinks we are in. Relevant for
* AP only.
* @cipher_scheme: optional cipher scheme for this station
- * @last_tdls_pkt_time: holds the time in jiffies of last TDLS pkt ACKed
- * @reserved_tid: reserved TID (if any, otherwise IEEE80211_TID_UNRESERVED)
*/
struct sta_info {
/* General information, mostly static */
@@ -463,8 +453,6 @@
/* TDLS timeout data */
unsigned long last_tdls_pkt_time;
- u8 reserved_tid;
-
/* keep last! */
struct ieee80211_sta sta;
};
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index bb146f3..89290e3 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -390,46 +390,6 @@
}
}
-/*
- * Handles the tx for TDLS teardown frames.
- * If the frame wasn't ACKed by the peer - it will be re-sent through the AP
- */
-static void ieee80211_tdls_td_tx_handle(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, u32 flags)
-{
- struct sk_buff *teardown_skb;
- struct sk_buff *orig_teardown_skb;
- bool is_teardown = false;
-
- /* Get the teardown data we need and free the lock */
- spin_lock(&sdata->u.mgd.teardown_lock);
- teardown_skb = sdata->u.mgd.teardown_skb;
- orig_teardown_skb = sdata->u.mgd.orig_teardown_skb;
- if ((skb == orig_teardown_skb) && teardown_skb) {
- sdata->u.mgd.teardown_skb = NULL;
- sdata->u.mgd.orig_teardown_skb = NULL;
- is_teardown = true;
- }
- spin_unlock(&sdata->u.mgd.teardown_lock);
-
- if (is_teardown) {
- /* This mechanism relies on being able to get ACKs */
- WARN_ON(!(local->hw.flags &
- IEEE80211_HW_REPORTS_TX_ACK_STATUS));
-
- /* Check if peer has ACKed */
- if (flags & IEEE80211_TX_STAT_ACK) {
- dev_kfree_skb_any(teardown_skb);
- } else {
- tdls_dbg(sdata,
- "TDLS Resending teardown through AP\n");
-
- ieee80211_subif_start_xmit(teardown_skb, skb->dev);
- }
- }
-}
-
static void ieee80211_report_used_skb(struct ieee80211_local *local,
struct sk_buff *skb, bool dropped)
{
@@ -466,19 +426,8 @@
if (!sdata) {
skb->dev = NULL;
} else if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) {
- unsigned int hdr_size =
- ieee80211_hdrlen(hdr->frame_control);
-
- /* Check to see if packet is a TDLS teardown packet */
- if (ieee80211_is_data(hdr->frame_control) &&
- (ieee80211_get_tdls_action(skb, hdr_size) ==
- WLAN_TDLS_TEARDOWN))
- ieee80211_tdls_td_tx_handle(local, sdata, skb,
- info->flags);
- else
- ieee80211_mgd_conn_tx_status(sdata,
- hdr->frame_control,
- acked);
+ ieee80211_mgd_conn_tx_status(sdata, hdr->frame_control,
+ acked);
} else if (ieee80211_is_nullfunc(hdr->frame_control) ||
ieee80211_is_qos_nullfunc(hdr->frame_control)) {
cfg80211_probe_status(sdata->dev, hdr->addr1,
@@ -592,9 +541,10 @@
#define STA_LOST_TDLS_PKT_THRESHOLD 10
#define STA_LOST_TDLS_PKT_TIME (10*HZ) /* 10secs since last ACK */
-static void ieee80211_lost_packet(struct sta_info *sta,
- struct ieee80211_tx_info *info)
+static void ieee80211_lost_packet(struct sta_info *sta, struct sk_buff *skb)
{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
/* This packet was aggregated but doesn't carry status info */
if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
!(info->flags & IEEE80211_TX_STAT_AMPDU))
@@ -621,13 +571,24 @@
sta->lost_packets = 0;
}
-static int ieee80211_tx_get_rates(struct ieee80211_hw *hw,
- struct ieee80211_tx_info *info,
- int *retry_count)
+void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
{
+ struct sk_buff *skb2;
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ __le16 fc;
+ struct ieee80211_supported_band *sband;
+ struct ieee80211_sub_if_data *sdata;
+ struct net_device *prev_dev = NULL;
+ struct sta_info *sta, *tmp;
+ int retry_count = -1, i;
int rates_idx = -1;
- int count = -1;
- int i;
+ bool send_to_cooked;
+ bool acked;
+ struct ieee80211_bar *bar;
+ int rtap_len;
+ int shift = 0;
for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
@@ -645,91 +606,12 @@
break;
}
- count += info->status.rates[i].count;
+ retry_count += info->status.rates[i].count;
}
rates_idx = i - 1;
- if (count < 0)
- count = 0;
-
- *retry_count = count;
- return rates_idx;
-}
-
-void ieee80211_tx_status_noskb(struct ieee80211_hw *hw,
- struct ieee80211_sta *pubsta,
- struct ieee80211_tx_info *info)
-{
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_supported_band *sband;
- int retry_count;
- int rates_idx;
- bool acked;
-
- rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
-
- sband = hw->wiphy->bands[info->band];
-
- acked = !!(info->flags & IEEE80211_TX_STAT_ACK);
- if (pubsta) {
- struct sta_info *sta;
-
- sta = container_of(pubsta, struct sta_info, sta);
-
- if (!acked)
- sta->tx_retry_failed++;
- sta->tx_retry_count += retry_count;
-
- if (acked) {
- sta->last_rx = jiffies;
-
- if (sta->lost_packets)
- sta->lost_packets = 0;
-
- /* Track when last TDLS packet was ACKed */
- if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
- sta->last_tdls_pkt_time = jiffies;
- } else {
- ieee80211_lost_packet(sta, info);
- }
-
- rate_control_tx_status_noskb(local, sband, sta, info);
- }
-
- if (acked) {
- local->dot11TransmittedFrameCount++;
- if (!pubsta)
- local->dot11MulticastTransmittedFrameCount++;
- if (retry_count > 0)
- local->dot11RetryCount++;
- if (retry_count > 1)
- local->dot11MultipleRetryCount++;
- } else {
- local->dot11FailedCount++;
- }
-}
-EXPORT_SYMBOL(ieee80211_tx_status_noskb);
-
-void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
- struct sk_buff *skb2;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
- struct ieee80211_local *local = hw_to_local(hw);
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- __le16 fc;
- struct ieee80211_supported_band *sband;
- struct ieee80211_sub_if_data *sdata;
- struct net_device *prev_dev = NULL;
- struct sta_info *sta, *tmp;
- int retry_count;
- int rates_idx;
- bool send_to_cooked;
- bool acked;
- struct ieee80211_bar *bar;
- int rtap_len;
- int shift = 0;
-
- rates_idx = ieee80211_tx_get_rates(hw, info, &retry_count);
+ if (retry_count < 0)
+ retry_count = 0;
rcu_read_lock();
@@ -822,8 +704,7 @@
if ((sta->sdata->vif.type == NL80211_IFTYPE_STATION) &&
(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS))
- ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data,
- acked, info->status.tx_time);
+ ieee80211_sta_tx_notify(sta->sdata, (void *) skb->data, acked);
if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
if (info->flags & IEEE80211_TX_STAT_ACK) {
@@ -834,7 +715,7 @@
if (test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH))
sta->last_tdls_pkt_time = jiffies;
} else {
- ieee80211_lost_packet(sta, info);
+ ieee80211_lost_packet(sta, skb);
}
}
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index 55ddd77..4ea25de 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -35,101 +35,19 @@
mutex_unlock(&local->mtx);
}
-static void ieee80211_tdls_add_ext_capab(struct ieee80211_local *local,
- struct sk_buff *skb)
+static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
{
u8 *pos = (void *)skb_put(skb, 7);
- bool chan_switch = local->hw.wiphy->features &
- NL80211_FEATURE_TDLS_CHANNEL_SWITCH;
*pos++ = WLAN_EID_EXT_CAPABILITY;
*pos++ = 5; /* len */
*pos++ = 0x0;
*pos++ = 0x0;
*pos++ = 0x0;
- *pos++ = chan_switch ? WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH : 0;
+ *pos++ = 0x0;
*pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED;
}
-static u8
-ieee80211_tdls_add_subband(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, u16 start, u16 end,
- u16 spacing)
-{
- u8 subband_cnt = 0, ch_cnt = 0;
- struct ieee80211_channel *ch;
- struct cfg80211_chan_def chandef;
- int i, subband_start;
-
- for (i = start; i <= end; i += spacing) {
- if (!ch_cnt)
- subband_start = i;
-
- ch = ieee80211_get_channel(sdata->local->hw.wiphy, i);
- if (ch) {
- /* we will be active on the channel */
- u32 flags = IEEE80211_CHAN_DISABLED |
- IEEE80211_CHAN_NO_IR;
- cfg80211_chandef_create(&chandef, ch,
- NL80211_CHAN_HT20);
- if (cfg80211_chandef_usable(sdata->local->hw.wiphy,
- &chandef, flags)) {
- ch_cnt++;
- continue;
- }
- }
-
- if (ch_cnt) {
- u8 *pos = skb_put(skb, 2);
- *pos++ = ieee80211_frequency_to_channel(subband_start);
- *pos++ = ch_cnt;
-
- subband_cnt++;
- ch_cnt = 0;
- }
- }
-
- return subband_cnt;
-}
-
-static void
-ieee80211_tdls_add_supp_channels(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
-{
- /*
- * Add possible channels for TDLS. These are channels that are allowed
- * to be active.
- */
- u8 subband_cnt;
- u8 *pos = skb_put(skb, 2);
-
- *pos++ = WLAN_EID_SUPPORTED_CHANNELS;
-
- /*
- * 5GHz and 2GHz channels numbers can overlap. Ignore this for now, as
- * this doesn't happen in real world scenarios.
- */
-
- /* 2GHz, with 5MHz spacing */
- subband_cnt = ieee80211_tdls_add_subband(sdata, skb, 2412, 2472, 5);
-
- /* 5GHz, with 20MHz spacing */
- subband_cnt += ieee80211_tdls_add_subband(sdata, skb, 5000, 5825, 20);
-
- /* length */
- *pos = 2 * subband_cnt;
-}
-
-static void ieee80211_tdls_add_bss_coex_ie(struct sk_buff *skb)
-{
- u8 *pos = (void *)skb_put(skb, 3);
-
- *pos++ = WLAN_EID_BSS_COEX_2040;
- *pos++ = 1; /* len */
-
- *pos++ = WLAN_BSS_COEX_INFORMATION_REQUEST;
-}
-
static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
u16 status_code)
{
@@ -272,7 +190,6 @@
ieee80211_add_srates_ie(sdata, skb, false, band);
ieee80211_add_ext_srates_ie(sdata, skb, false, band);
- ieee80211_tdls_add_supp_channels(sdata, skb);
/* add any custom IEs that go before Extended Capabilities */
if (extra_ies_len) {
@@ -292,7 +209,7 @@
offset = noffset;
}
- ieee80211_tdls_add_ext_capab(local, skb);
+ ieee80211_tdls_add_ext_capab(skb);
/* add the QoS element if we support it */
if (local->hw.queues >= IEEE80211_NUM_ACS &&
@@ -354,10 +271,6 @@
rcu_read_unlock();
- if (ht_cap.ht_supported &&
- (ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40))
- ieee80211_tdls_add_bss_coex_ie(skb);
-
/* add any remaining IEs */
if (extra_ies_len) {
noffset = extra_ies_len;
@@ -449,68 +362,11 @@
ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
}
-static void
-ieee80211_tdls_add_chan_switch_req_ies(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, const u8 *peer,
- bool initiator, const u8 *extra_ies,
- size_t extra_ies_len, u8 oper_class,
- struct cfg80211_chan_def *chandef)
-{
- struct ieee80211_tdls_data *tf;
- size_t offset = 0, noffset;
- u8 *pos;
-
- if (WARN_ON_ONCE(!chandef))
- return;
-
- tf = (void *)skb->data;
- tf->u.chan_switch_req.target_channel =
- ieee80211_frequency_to_channel(chandef->chan->center_freq);
- tf->u.chan_switch_req.oper_class = oper_class;
-
- if (extra_ies_len) {
- static const u8 before_lnkie[] = {
- WLAN_EID_SECONDARY_CHANNEL_OFFSET,
- };
- noffset = ieee80211_ie_split(extra_ies, extra_ies_len,
- before_lnkie,
- ARRAY_SIZE(before_lnkie),
- offset);
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
- offset = noffset;
- }
-
- ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
-
- /* add any remaining IEs */
- if (extra_ies_len) {
- noffset = extra_ies_len;
- pos = skb_put(skb, noffset - offset);
- memcpy(pos, extra_ies + offset, noffset - offset);
- }
-}
-
-static void
-ieee80211_tdls_add_chan_switch_resp_ies(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, const u8 *peer,
- u16 status_code, bool initiator,
- const u8 *extra_ies,
- size_t extra_ies_len)
-{
- if (status_code == 0)
- ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
-
- if (extra_ies_len)
- memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
-}
-
static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, const u8 *peer,
u8 action_code, u16 status_code,
bool initiator, const u8 *extra_ies,
- size_t extra_ies_len, u8 oper_class,
- struct cfg80211_chan_def *chandef)
+ size_t extra_ies_len)
{
switch (action_code) {
case WLAN_TDLS_SETUP_REQUEST:
@@ -537,18 +393,6 @@
if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN)
ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator);
break;
- case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
- ieee80211_tdls_add_chan_switch_req_ies(sdata, skb, peer,
- initiator, extra_ies,
- extra_ies_len,
- oper_class, chandef);
- break;
- case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
- ieee80211_tdls_add_chan_switch_resp_ies(sdata, skb, peer,
- status_code,
- initiator, extra_ies,
- extra_ies_len);
- break;
}
}
@@ -615,19 +459,6 @@
skb_put(skb, sizeof(tf->u.discover_req));
tf->u.discover_req.dialog_token = dialog_token;
break;
- case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
- tf->category = WLAN_CATEGORY_TDLS;
- tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_REQUEST;
-
- skb_put(skb, sizeof(tf->u.chan_switch_req));
- break;
- case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
- tf->category = WLAN_CATEGORY_TDLS;
- tf->action_code = WLAN_TDLS_CHANNEL_SWITCH_RESPONSE;
-
- skb_put(skb, sizeof(tf->u.chan_switch_resp));
- tf->u.chan_switch_resp.status_code = cpu_to_le16(status_code);
- break;
default:
return -EINVAL;
}
@@ -671,33 +502,32 @@
return 0;
}
-static struct sk_buff *
-ieee80211_tdls_build_mgmt_packet_data(struct ieee80211_sub_if_data *sdata,
- const u8 *peer, u8 action_code,
- u8 dialog_token, u16 status_code,
- bool initiator, const u8 *extra_ies,
- size_t extra_ies_len, u8 oper_class,
- struct cfg80211_chan_def *chandef)
+static int
+ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
+ const u8 *peer, u8 action_code,
+ u8 dialog_token, u16 status_code,
+ u32 peer_capability, bool initiator,
+ const u8 *extra_ies, size_t extra_ies_len)
{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
- struct sk_buff *skb;
+ struct sk_buff *skb = NULL;
+ bool send_direct;
+ struct sta_info *sta;
int ret;
- skb = netdev_alloc_skb(sdata->dev,
- local->hw.extra_tx_headroom +
- max(sizeof(struct ieee80211_mgmt),
- sizeof(struct ieee80211_tdls_data)) +
- 50 + /* supported rates */
- 7 + /* ext capab */
- 26 + /* max(WMM-info, WMM-param) */
- 2 + max(sizeof(struct ieee80211_ht_cap),
- sizeof(struct ieee80211_ht_operation)) +
- 50 + /* supported channels */
- 3 + /* 40/20 BSS coex */
- extra_ies_len +
- sizeof(struct ieee80211_tdls_lnkie));
+ skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+ max(sizeof(struct ieee80211_mgmt),
+ sizeof(struct ieee80211_tdls_data)) +
+ 50 + /* supported rates */
+ 7 + /* ext capab */
+ 26 + /* max(WMM-info, WMM-param) */
+ 2 + max(sizeof(struct ieee80211_ht_cap),
+ sizeof(struct ieee80211_ht_operation)) +
+ extra_ies_len +
+ sizeof(struct ieee80211_tdls_lnkie));
if (!skb)
- return NULL;
+ return -ENOMEM;
skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -707,18 +537,16 @@
case WLAN_TDLS_SETUP_CONFIRM:
case WLAN_TDLS_TEARDOWN:
case WLAN_TDLS_DISCOVERY_REQUEST:
- case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
- case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
- ret = ieee80211_prep_tdls_encap_data(local->hw.wiphy,
- sdata->dev, peer,
+ ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
action_code, dialog_token,
status_code, skb);
+ send_direct = false;
break;
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
- ret = ieee80211_prep_tdls_direct(local->hw.wiphy, sdata->dev,
- peer, action_code,
+ ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
dialog_token, status_code,
skb);
+ send_direct = true;
break;
default:
ret = -ENOTSUPP;
@@ -728,40 +556,14 @@
if (ret < 0)
goto fail;
- ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code,
- initiator, extra_ies, extra_ies_len, oper_class,
- chandef);
- return skb;
-
-fail:
- dev_kfree_skb(skb);
- return NULL;
-}
-
-static int
-ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev,
- const u8 *peer, u8 action_code, u8 dialog_token,
- u16 status_code, u32 peer_capability,
- bool initiator, const u8 *extra_ies,
- size_t extra_ies_len, u8 oper_class,
- struct cfg80211_chan_def *chandef)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct sk_buff *skb = NULL;
- struct sta_info *sta;
- u32 flags = 0;
- int ret = 0;
-
rcu_read_lock();
sta = sta_info_get(sdata, peer);
/* infer the initiator if we can, to support old userspace */
switch (action_code) {
case WLAN_TDLS_SETUP_REQUEST:
- if (sta) {
+ if (sta)
set_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
- sta->sta.tdls_initiator = false;
- }
/* fall-through */
case WLAN_TDLS_SETUP_CONFIRM:
case WLAN_TDLS_DISCOVERY_REQUEST:
@@ -773,17 +575,13 @@
* Make the last packet sent take effect for the initiator
* value.
*/
- if (sta) {
+ if (sta)
clear_sta_flag(sta, WLAN_STA_TDLS_INITIATOR);
- sta->sta.tdls_initiator = true;
- }
/* fall-through */
case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
initiator = false;
break;
case WLAN_TDLS_TEARDOWN:
- case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
- case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
/* any value is ok */
break;
default:
@@ -798,17 +596,9 @@
if (ret < 0)
goto fail;
- skb = ieee80211_tdls_build_mgmt_packet_data(sdata, peer, action_code,
- dialog_token, status_code,
- initiator, extra_ies,
- extra_ies_len, oper_class,
- chandef);
- if (!skb) {
- ret = -EINVAL;
- goto fail;
- }
-
- if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) {
+ ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code,
+ initiator, extra_ies, extra_ies_len);
+ if (send_direct) {
ieee80211_tx_skb(sdata, skb);
return 0;
}
@@ -829,44 +619,9 @@
break;
}
- /*
- * Set the WLAN_TDLS_TEARDOWN flag to indicate a teardown in progress.
- * Later, if no ACK is returned from peer, we will re-send the teardown
- * packet through the AP.
- */
- if ((action_code == WLAN_TDLS_TEARDOWN) &&
- (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
- struct sta_info *sta = NULL;
- bool try_resend; /* Should we keep skb for possible resend */
-
- /* If not sending directly to peer - no point in keeping skb */
- rcu_read_lock();
- sta = sta_info_get(sdata, peer);
- try_resend = sta && test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH);
- rcu_read_unlock();
-
- spin_lock_bh(&sdata->u.mgd.teardown_lock);
- if (try_resend && !sdata->u.mgd.teardown_skb) {
- /* Mark it as requiring TX status callback */
- flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
- IEEE80211_TX_INTFL_MLME_CONN_TX;
-
- /*
- * skb is copied since mac80211 will later set
- * properties that might not be the same as the AP,
- * such as encryption, QoS, addresses, etc.
- *
- * No problem if skb_copy() fails, so no need to check.
- */
- sdata->u.mgd.teardown_skb = skb_copy(skb, GFP_ATOMIC);
- sdata->u.mgd.orig_teardown_skb = skb;
- }
- spin_unlock_bh(&sdata->u.mgd.teardown_lock);
- }
-
/* disable bottom halves when entering the Tx path */
local_bh_disable();
- __ieee80211_subif_start_xmit(skb, dev, flags);
+ ret = ieee80211_subif_start_xmit(skb, dev);
local_bh_enable();
return ret;
@@ -917,8 +672,7 @@
ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
dialog_token, status_code,
peer_capability, initiator,
- extra_ies, extra_ies_len, 0,
- NULL);
+ extra_ies, extra_ies_len);
if (ret < 0)
goto exit;
@@ -957,8 +711,7 @@
ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code,
dialog_token, status_code,
peer_capability, initiator,
- extra_ies, extra_ies_len, 0,
- NULL);
+ extra_ies, extra_ies_len);
if (ret < 0)
sdata_err(sdata, "Failed sending TDLS teardown packet %d\n",
ret);
@@ -1028,7 +781,7 @@
status_code,
peer_capability,
initiator, extra_ies,
- extra_ies_len, 0, NULL);
+ extra_ies_len);
break;
default:
ret = -EOPNOTSUPP;
@@ -1131,480 +884,3 @@
cfg80211_tdls_oper_request(sdata->dev, peer, oper, reason_code, gfp);
}
EXPORT_SYMBOL(ieee80211_tdls_oper_request);
-
-static void
-iee80211_tdls_add_ch_switch_timing(u8 *buf, u16 switch_time, u16 switch_timeout)
-{
- struct ieee80211_ch_switch_timing *ch_sw;
-
- *buf++ = WLAN_EID_CHAN_SWITCH_TIMING;
- *buf++ = sizeof(struct ieee80211_ch_switch_timing);
-
- ch_sw = (void *)buf;
- ch_sw->switch_time = cpu_to_le16(switch_time);
- ch_sw->switch_timeout = cpu_to_le16(switch_timeout);
-}
-
-/* find switch timing IE in SKB ready for Tx */
-static const u8 *ieee80211_tdls_find_sw_timing_ie(struct sk_buff *skb)
-{
- struct ieee80211_tdls_data *tf;
- const u8 *ie_start;
-
- /*
- * Get the offset for the new location of the switch timing IE.
- * The SKB network header will now point to the "payload_type"
- * element of the TDLS data frame struct.
- */
- tf = container_of(skb->data + skb_network_offset(skb),
- struct ieee80211_tdls_data, payload_type);
- ie_start = tf->u.chan_switch_req.variable;
- return cfg80211_find_ie(WLAN_EID_CHAN_SWITCH_TIMING, ie_start,
- skb->len - (ie_start - skb->data));
-}
-
-static struct sk_buff *
-ieee80211_tdls_ch_sw_tmpl_get(struct sta_info *sta, u8 oper_class,
- struct cfg80211_chan_def *chandef,
- u32 *ch_sw_tm_ie_offset)
-{
- struct ieee80211_sub_if_data *sdata = sta->sdata;
- u8 extra_ies[2 + sizeof(struct ieee80211_sec_chan_offs_ie) +
- 2 + sizeof(struct ieee80211_ch_switch_timing)];
- int extra_ies_len = 2 + sizeof(struct ieee80211_ch_switch_timing);
- u8 *pos = extra_ies;
- struct sk_buff *skb;
-
- /*
- * if chandef points to a wide channel add a Secondary-Channel
- * Offset information element
- */
- if (chandef->width == NL80211_CHAN_WIDTH_40) {
- struct ieee80211_sec_chan_offs_ie *sec_chan_ie;
- bool ht40plus;
-
- *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
- *pos++ = sizeof(*sec_chan_ie);
- sec_chan_ie = (void *)pos;
-
- ht40plus = cfg80211_get_chandef_type(chandef) ==
- NL80211_CHAN_HT40PLUS;
- sec_chan_ie->sec_chan_offs = ht40plus ?
- IEEE80211_HT_PARAM_CHA_SEC_ABOVE :
- IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- pos += sizeof(*sec_chan_ie);
-
- extra_ies_len += 2 + sizeof(struct ieee80211_sec_chan_offs_ie);
- }
-
- /* just set the values to 0, this is a template */
- iee80211_tdls_add_ch_switch_timing(pos, 0, 0);
-
- skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr,
- WLAN_TDLS_CHANNEL_SWITCH_REQUEST,
- 0, 0, !sta->sta.tdls_initiator,
- extra_ies, extra_ies_len,
- oper_class, chandef);
- if (!skb)
- return NULL;
-
- skb = ieee80211_build_data_template(sdata, skb, 0);
- if (IS_ERR(skb)) {
- tdls_dbg(sdata, "Failed building TDLS channel switch frame\n");
- return NULL;
- }
-
- if (ch_sw_tm_ie_offset) {
- const u8 *tm_ie = ieee80211_tdls_find_sw_timing_ie(skb);
-
- if (!tm_ie) {
- tdls_dbg(sdata, "No switch timing IE in TDLS switch\n");
- dev_kfree_skb_any(skb);
- return NULL;
- }
-
- *ch_sw_tm_ie_offset = tm_ie - skb->data;
- }
-
- tdls_dbg(sdata,
- "TDLS channel switch request template for %pM ch %d width %d\n",
- sta->sta.addr, chandef->chan->center_freq, chandef->width);
- return skb;
-}
-
-int
-ieee80211_tdls_channel_switch(struct wiphy *wiphy, struct net_device *dev,
- const u8 *addr, u8 oper_class,
- struct cfg80211_chan_def *chandef)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
- struct sk_buff *skb = NULL;
- u32 ch_sw_tm_ie;
- int ret;
-
- mutex_lock(&local->sta_mtx);
- sta = sta_info_get(sdata, addr);
- if (!sta) {
- tdls_dbg(sdata,
- "Invalid TDLS peer %pM for channel switch request\n",
- addr);
- ret = -ENOENT;
- goto out;
- }
-
- if (!test_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH)) {
- tdls_dbg(sdata, "TDLS channel switch unsupported by %pM\n",
- addr);
- ret = -ENOTSUPP;
- goto out;
- }
-
- skb = ieee80211_tdls_ch_sw_tmpl_get(sta, oper_class, chandef,
- &ch_sw_tm_ie);
- if (!skb) {
- ret = -ENOENT;
- goto out;
- }
-
- ret = drv_tdls_channel_switch(local, sdata, &sta->sta, oper_class,
- chandef, skb, ch_sw_tm_ie);
- if (!ret)
- set_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL);
-
-out:
- mutex_unlock(&local->sta_mtx);
- dev_kfree_skb_any(skb);
- return ret;
-}
-
-void
-ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
- struct net_device *dev,
- const u8 *addr)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = sdata->local;
- struct sta_info *sta;
-
- mutex_lock(&local->sta_mtx);
- sta = sta_info_get(sdata, addr);
- if (!sta) {
- tdls_dbg(sdata,
- "Invalid TDLS peer %pM for channel switch cancel\n",
- addr);
- goto out;
- }
-
- if (!test_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL)) {
- tdls_dbg(sdata, "TDLS channel switch not initiated by %pM\n",
- addr);
- goto out;
- }
-
- drv_tdls_cancel_channel_switch(local, sdata, &sta->sta);
- clear_sta_flag(sta, WLAN_STA_TDLS_OFF_CHANNEL);
-
-out:
- mutex_unlock(&local->sta_mtx);
-}
-
-static struct sk_buff *
-ieee80211_tdls_ch_sw_resp_tmpl_get(struct sta_info *sta,
- u32 *ch_sw_tm_ie_offset)
-{
- struct ieee80211_sub_if_data *sdata = sta->sdata;
- struct sk_buff *skb;
- u8 extra_ies[2 + sizeof(struct ieee80211_ch_switch_timing)];
-
- /* initial timing are always zero in the template */
- iee80211_tdls_add_ch_switch_timing(extra_ies, 0, 0);
-
- skb = ieee80211_tdls_build_mgmt_packet_data(sdata, sta->sta.addr,
- WLAN_TDLS_CHANNEL_SWITCH_RESPONSE,
- 0, 0, !sta->sta.tdls_initiator,
- extra_ies, sizeof(extra_ies), 0, NULL);
- if (!skb)
- return NULL;
-
- skb = ieee80211_build_data_template(sdata, skb, 0);
- if (IS_ERR(skb)) {
- tdls_dbg(sdata,
- "Failed building TDLS channel switch resp frame\n");
- return NULL;
- }
-
- if (ch_sw_tm_ie_offset) {
- const u8 *tm_ie = ieee80211_tdls_find_sw_timing_ie(skb);
-
- if (!tm_ie) {
- tdls_dbg(sdata,
- "No switch timing IE in TDLS switch resp\n");
- dev_kfree_skb_any(skb);
- return NULL;
- }
-
- *ch_sw_tm_ie_offset = tm_ie - skb->data;
- }
-
- tdls_dbg(sdata, "TDLS get channel switch response template for %pM\n",
- sta->sta.addr);
- return skb;
-}
-
-static int
-ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee802_11_elems elems;
- struct sta_info *sta;
- struct ieee80211_tdls_data *tf = (void *)skb->data;
- bool local_initiator;
- struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
- int baselen = offsetof(typeof(*tf), u.chan_switch_resp.variable);
- struct ieee80211_tdls_ch_sw_params params = {};
- int ret;
-
- params.action_code = WLAN_TDLS_CHANNEL_SWITCH_RESPONSE;
- params.timestamp = rx_status->device_timestamp;
-
- if (skb->len < baselen) {
- tdls_dbg(sdata, "TDLS channel switch resp too short: %d\n",
- skb->len);
- return -EINVAL;
- }
-
- mutex_lock(&local->sta_mtx);
- sta = sta_info_get(sdata, tf->sa);
- if (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) {
- tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n",
- tf->sa);
- ret = -EINVAL;
- goto out;
- }
-
- params.sta = &sta->sta;
- params.status = le16_to_cpu(tf->u.chan_switch_resp.status_code);
- if (params.status != 0) {
- ret = 0;
- goto call_drv;
- }
-
- ieee802_11_parse_elems(tf->u.chan_switch_resp.variable,
- skb->len - baselen, false, &elems);
- if (elems.parse_error) {
- tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n");
- ret = -EINVAL;
- goto out;
- }
-
- if (!elems.ch_sw_timing || !elems.lnk_id) {
- tdls_dbg(sdata, "TDLS channel switch resp - missing IEs\n");
- ret = -EINVAL;
- goto out;
- }
-
- /* validate the initiator is set correctly */
- local_initiator =
- !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
- if (local_initiator == sta->sta.tdls_initiator) {
- tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
- ret = -EINVAL;
- goto out;
- }
-
- params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
- params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
-
- params.tmpl_skb =
- ieee80211_tdls_ch_sw_resp_tmpl_get(sta, ¶ms.ch_sw_tm_ie);
- if (!params.tmpl_skb) {
- ret = -ENOENT;
- goto out;
- }
-
-call_drv:
- drv_tdls_recv_channel_switch(sdata->local, sdata, ¶ms);
-
- tdls_dbg(sdata,
- "TDLS channel switch response received from %pM status %d\n",
- tf->sa, params.status);
-
-out:
- mutex_unlock(&local->sta_mtx);
- dev_kfree_skb_any(params.tmpl_skb);
- return ret;
-}
-
-static int
-ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
-{
- struct ieee80211_local *local = sdata->local;
- struct ieee802_11_elems elems;
- struct cfg80211_chan_def chandef;
- struct ieee80211_channel *chan;
- enum nl80211_channel_type chan_type;
- int freq;
- u8 target_channel, oper_class;
- bool local_initiator;
- struct sta_info *sta;
- enum ieee80211_band band;
- struct ieee80211_tdls_data *tf = (void *)skb->data;
- struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
- int baselen = offsetof(typeof(*tf), u.chan_switch_req.variable);
- struct ieee80211_tdls_ch_sw_params params = {};
- int ret = 0;
-
- params.action_code = WLAN_TDLS_CHANNEL_SWITCH_REQUEST;
- params.timestamp = rx_status->device_timestamp;
-
- if (skb->len < baselen) {
- tdls_dbg(sdata, "TDLS channel switch req too short: %d\n",
- skb->len);
- return -EINVAL;
- }
-
- target_channel = tf->u.chan_switch_req.target_channel;
- oper_class = tf->u.chan_switch_req.oper_class;
-
- /*
- * We can't easily infer the channel band. The operating class is
- * ambiguous - there are multiple tables (US/Europe/JP/Global). The
- * solution here is to treat channels with number >14 as 5GHz ones,
- * and specifically check for the (oper_class, channel) combinations
- * where this doesn't hold. These are thankfully unique according to
- * IEEE802.11-2012.
- * We consider only the 2GHz and 5GHz bands and 20MHz+ channels as
- * valid here.
- */
- if ((oper_class == 112 || oper_class == 2 || oper_class == 3 ||
- oper_class == 4 || oper_class == 5 || oper_class == 6) &&
- target_channel < 14)
- band = IEEE80211_BAND_5GHZ;
- else
- band = target_channel < 14 ? IEEE80211_BAND_2GHZ :
- IEEE80211_BAND_5GHZ;
-
- freq = ieee80211_channel_to_frequency(target_channel, band);
- if (freq == 0) {
- tdls_dbg(sdata, "Invalid channel in TDLS chan switch: %d\n",
- target_channel);
- return -EINVAL;
- }
-
- chan = ieee80211_get_channel(sdata->local->hw.wiphy, freq);
- if (!chan) {
- tdls_dbg(sdata,
- "Unsupported channel for TDLS chan switch: %d\n",
- target_channel);
- return -EINVAL;
- }
-
- ieee802_11_parse_elems(tf->u.chan_switch_req.variable,
- skb->len - baselen, false, &elems);
- if (elems.parse_error) {
- tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n");
- return -EINVAL;
- }
-
- if (!elems.ch_sw_timing || !elems.lnk_id) {
- tdls_dbg(sdata, "TDLS channel switch req - missing IEs\n");
- return -EINVAL;
- }
-
- mutex_lock(&local->sta_mtx);
- sta = sta_info_get(sdata, tf->sa);
- if (!sta || !test_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH)) {
- tdls_dbg(sdata, "TDLS chan switch from non-peer sta %pM\n",
- tf->sa);
- ret = -EINVAL;
- goto out;
- }
-
- params.sta = &sta->sta;
-
- /* validate the initiator is set correctly */
- local_initiator =
- !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN);
- if (local_initiator == sta->sta.tdls_initiator) {
- tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n");
- ret = -EINVAL;
- goto out;
- }
-
- if (!sta->sta.ht_cap.ht_supported) {
- chan_type = NL80211_CHAN_NO_HT;
- } else if (!elems.sec_chan_offs) {
- chan_type = NL80211_CHAN_HT20;
- } else {
- switch (elems.sec_chan_offs->sec_chan_offs) {
- case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
- chan_type = NL80211_CHAN_HT40PLUS;
- break;
- case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
- chan_type = NL80211_CHAN_HT40MINUS;
- break;
- default:
- chan_type = NL80211_CHAN_HT20;
- break;
- }
- }
-
- cfg80211_chandef_create(&chandef, chan, chan_type);
- params.chandef = &chandef;
-
- params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time);
- params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout);
-
- params.tmpl_skb =
- ieee80211_tdls_ch_sw_resp_tmpl_get(sta,
- ¶ms.ch_sw_tm_ie);
- if (!params.tmpl_skb) {
- ret = -ENOENT;
- goto out;
- }
-
- drv_tdls_recv_channel_switch(sdata->local, sdata, ¶ms);
-
- tdls_dbg(sdata,
- "TDLS ch switch request received from %pM ch %d width %d\n",
- tf->sa, params.chandef->chan->center_freq,
- params.chandef->width);
-out:
- mutex_unlock(&local->sta_mtx);
- dev_kfree_skb_any(params.tmpl_skb);
- return ret;
-}
-
-void ieee80211_process_tdls_channel_switch(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb)
-{
- struct ieee80211_tdls_data *tf = (void *)skb->data;
- struct wiphy *wiphy = sdata->local->hw.wiphy;
-
- /* make sure the driver supports it */
- if (!(wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
- return;
-
- /* we want to access the entire packet */
- if (skb_linearize(skb))
- return;
- /*
- * The packet/size was already validated by mac80211 Rx path, only look
- * at the action type.
- */
- switch (tf->action_code) {
- case WLAN_TDLS_CHANNEL_SWITCH_REQUEST:
- ieee80211_process_tdls_channel_switch_req(sdata, skb);
- break;
- case WLAN_TDLS_CHANNEL_SWITCH_RESPONSE:
- ieee80211_process_tdls_channel_switch_resp(sdata, skb);
- break;
- default:
- WARN_ON_ONCE(1);
- return;
- }
-}
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 3991437..5153d12 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -16,7 +16,6 @@
#define STA_ENTRY __array(char, sta_addr, ETH_ALEN)
#define STA_ASSIGN (sta ? memcpy(__entry->sta_addr, sta->addr, ETH_ALEN) : memset(__entry->sta_addr, 0, ETH_ALEN))
-#define STA_NAMED_ASSIGN(s) memcpy(__entry->sta_addr, (s)->addr, ETH_ALEN)
#define STA_PR_FMT " sta:%pM"
#define STA_PR_ARG __entry->sta_addr
@@ -596,33 +595,14 @@
TP_ARGS(local, sdata)
);
-TRACE_EVENT(drv_sw_scan_start,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- const u8 *mac_addr),
-
- TP_ARGS(local, sdata, mac_addr),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- VIF_ENTRY
- __array(char, mac_addr, ETH_ALEN)
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- VIF_ASSIGN;
- memcpy(__entry->mac_addr, mac_addr, ETH_ALEN);
- ),
-
- TP_printk(LOCAL_PR_FMT ", " VIF_PR_FMT ", addr:%pM",
- LOCAL_PR_ARG, VIF_PR_ARG, __entry->mac_addr)
+DEFINE_EVENT(local_only_evt, drv_sw_scan_start,
+ TP_PROTO(struct ieee80211_local *local),
+ TP_ARGS(local)
);
-DEFINE_EVENT(local_sdata_evt, drv_sw_scan_complete,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata),
- TP_ARGS(local, sdata)
+DEFINE_EVENT(local_only_evt, drv_sw_scan_complete,
+ TP_PROTO(struct ieee80211_local *local),
+ TP_ARGS(local)
);
TRACE_EVENT(drv_get_stats,
@@ -846,13 +826,6 @@
TP_ARGS(local, sdata, sta)
);
-DEFINE_EVENT(sta_event, drv_sta_rate_tbl_update,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta),
- TP_ARGS(local, sdata, sta)
-);
-
TRACE_EVENT(drv_conf_tx,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
@@ -1014,34 +987,29 @@
TRACE_EVENT(drv_channel_switch,
TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel_switch *ch_switch),
- TP_ARGS(local, sdata, ch_switch),
+ TP_ARGS(local, ch_switch),
TP_STRUCT__entry(
LOCAL_ENTRY
- VIF_ENTRY
CHANDEF_ENTRY
__field(u64, timestamp)
- __field(u32, device_timestamp)
__field(bool, block_tx)
__field(u8, count)
),
TP_fast_assign(
LOCAL_ASSIGN;
- VIF_ASSIGN;
CHANDEF_ASSIGN(&ch_switch->chandef)
__entry->timestamp = ch_switch->timestamp;
- __entry->device_timestamp = ch_switch->device_timestamp;
__entry->block_tx = ch_switch->block_tx;
__entry->count = ch_switch->count;
),
TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT " new " CHANDEF_PR_FMT " count:%d",
- LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG, __entry->count
+ LOCAL_PR_FMT " new " CHANDEF_PR_FMT " count:%d",
+ LOCAL_PR_ARG, CHANDEF_PR_ARG, __entry->count
)
);
@@ -1589,26 +1557,9 @@
TP_ARGS(local, sdata)
);
-TRACE_EVENT(drv_reconfig_complete,
- TP_PROTO(struct ieee80211_local *local,
- enum ieee80211_reconfig_type reconfig_type),
- TP_ARGS(local, reconfig_type),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- __field(u8, reconfig_type)
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- __entry->reconfig_type = reconfig_type;
- ),
-
- TP_printk(
- LOCAL_PR_FMT " reconfig_type:%d",
- LOCAL_PR_ARG, __entry->reconfig_type
- )
-
+DEFINE_EVENT(local_only_evt, drv_restart_complete,
+ TP_PROTO(struct ieee80211_local *local),
+ TP_ARGS(local)
);
#if IS_ENABLED(CONFIG_IPV6)
@@ -1829,12 +1780,6 @@
)
);
-DEFINE_EVENT(local_sdata_evt, api_cqm_beacon_loss_notify,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata),
- TP_ARGS(local, sdata)
-);
-
TRACE_EVENT(api_scan_completed,
TP_PROTO(struct ieee80211_local *local, bool aborted),
@@ -2161,175 +2106,6 @@
)
);
-TRACE_EVENT(drv_pre_channel_switch,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_channel_switch *ch_switch),
-
- TP_ARGS(local, sdata, ch_switch),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- VIF_ENTRY
- CHANDEF_ENTRY
- __field(u64, timestamp)
- __field(u32, device_timestamp)
- __field(bool, block_tx)
- __field(u8, count)
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- VIF_ASSIGN;
- CHANDEF_ASSIGN(&ch_switch->chandef)
- __entry->timestamp = ch_switch->timestamp;
- __entry->device_timestamp = ch_switch->device_timestamp;
- __entry->block_tx = ch_switch->block_tx;
- __entry->count = ch_switch->count;
- ),
-
- TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT " prepare channel switch to "
- CHANDEF_PR_FMT " count:%d block_tx:%d timestamp:%llu",
- LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG, __entry->count,
- __entry->block_tx, __entry->timestamp
- )
-);
-
-DEFINE_EVENT(local_sdata_evt, drv_post_channel_switch,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata),
- TP_ARGS(local, sdata)
-);
-
-TRACE_EVENT(drv_get_txpower,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- int dbm, int ret),
-
- TP_ARGS(local, sdata, dbm, ret),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- VIF_ENTRY
- __field(int, dbm)
- __field(int, ret)
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- VIF_ASSIGN;
- __entry->dbm = dbm;
- __entry->ret = ret;
- ),
-
- TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT " dbm:%d ret:%d",
- LOCAL_PR_ARG, VIF_PR_ARG, __entry->dbm, __entry->ret
- )
-);
-
-TRACE_EVENT(drv_tdls_channel_switch,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta, u8 oper_class,
- struct cfg80211_chan_def *chandef),
-
- TP_ARGS(local, sdata, sta, oper_class, chandef),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- VIF_ENTRY
- STA_ENTRY
- __field(u8, oper_class)
- CHANDEF_ENTRY
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- VIF_ASSIGN;
- STA_ASSIGN;
- __entry->oper_class = oper_class;
- CHANDEF_ASSIGN(chandef)
- ),
-
- TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT " tdls channel switch to"
- CHANDEF_PR_FMT " oper_class:%d " STA_PR_FMT,
- LOCAL_PR_ARG, VIF_PR_ARG, CHANDEF_PR_ARG, __entry->oper_class,
- STA_PR_ARG
- )
-);
-
-TRACE_EVENT(drv_tdls_cancel_channel_switch,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_sta *sta),
-
- TP_ARGS(local, sdata, sta),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- VIF_ENTRY
- STA_ENTRY
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- VIF_ASSIGN;
- STA_ASSIGN;
- ),
-
- TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT
- " tdls cancel channel switch with " STA_PR_FMT,
- LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG
- )
-);
-
-TRACE_EVENT(drv_tdls_recv_channel_switch,
- TP_PROTO(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- struct ieee80211_tdls_ch_sw_params *params),
-
- TP_ARGS(local, sdata, params),
-
- TP_STRUCT__entry(
- LOCAL_ENTRY
- VIF_ENTRY
- __field(u8, action_code)
- STA_ENTRY
- CHANDEF_ENTRY
- __field(u32, status)
- __field(bool, peer_initiator)
- __field(u32, timestamp)
- __field(u16, switch_time)
- __field(u16, switch_timeout)
- ),
-
- TP_fast_assign(
- LOCAL_ASSIGN;
- VIF_ASSIGN;
- STA_NAMED_ASSIGN(params->sta);
- CHANDEF_ASSIGN(params->chandef)
- __entry->peer_initiator = params->sta->tdls_initiator;
- __entry->action_code = params->action_code;
- __entry->status = params->status;
- __entry->timestamp = params->timestamp;
- __entry->switch_time = params->switch_time;
- __entry->switch_timeout = params->switch_timeout;
- ),
-
- TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT " received tdls channel switch packet"
- " action:%d status:%d time:%d switch time:%d switch"
- " timeout:%d initiator: %d chan:" CHANDEF_PR_FMT STA_PR_FMT,
- LOCAL_PR_ARG, VIF_PR_ARG, __entry->action_code, __entry->status,
- __entry->timestamp, __entry->switch_time,
- __entry->switch_timeout, __entry->peer_initiator,
- CHANDEF_PR_ARG, STA_PR_ARG
- )
-);
#ifdef CPTCFG_MAC80211_MESSAGE_TRACING
#undef TRACE_SYSTEM
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 002f28d..86ea121 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -60,7 +60,7 @@
rcu_read_unlock();
/* assume HW handles this */
- if (tx->rate.flags & (IEEE80211_TX_RC_MCS | IEEE80211_TX_RC_VHT_MCS))
+ if (tx->rate.flags & IEEE80211_TX_RC_MCS)
return 0;
/* uh huh? */
@@ -296,9 +296,6 @@
*/
return TX_DROP;
- if (tx->sdata->vif.type == NL80211_IFTYPE_OCB)
- return TX_CONTINUE;
-
if (tx->sdata->vif.type == NL80211_IFTYPE_WDS)
return TX_CONTINUE;
@@ -1426,7 +1423,8 @@
* Returns false if the frame couldn't be transmitted but was queued instead.
*/
static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, bool txpending)
+ struct sk_buff *skb, bool txpending,
+ enum ieee80211_band band)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_data tx;
@@ -1451,6 +1449,8 @@
return true;
}
+ info->band = band;
+
/* set up hw_queue value early */
if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) ||
!(local->hw.flags & IEEE80211_HW_QUEUE_CONTROL))
@@ -1498,7 +1498,8 @@
return 0;
}
-void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+void ieee80211_xmit(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
+ enum ieee80211_band band)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -1533,7 +1534,7 @@
}
ieee80211_set_qos_hdr(sdata, skb);
- ieee80211_tx(sdata, skb, false);
+ ieee80211_tx(sdata, skb, false, band);
}
static bool ieee80211_parse_tx_radiotap(struct sk_buff *skb)
@@ -1753,8 +1754,7 @@
sdata->vif.type))
goto fail_rcu;
- info->band = chandef->chan->band;
- ieee80211_xmit(sdata, skb);
+ ieee80211_xmit(sdata, skb, chandef->chan->band);
rcu_read_unlock();
return NETDEV_TX_OK;
@@ -1784,26 +1784,23 @@
}
/**
- * ieee80211_build_hdr - build 802.11 header in the given frame
- * @sdata: virtual interface to build the header for
- * @skb: the skb to build the header in
- * @info_flags: skb flags to set
+ * ieee80211_subif_start_xmit - netif start_xmit function for Ethernet-type
+ * subinterfaces (wlan#, WDS, and VLAN interfaces)
+ * @skb: packet to be sent
+ * @dev: incoming interface
*
- * This function takes the skb with 802.3 header and reformats the header to
- * the appropriate IEEE 802.11 header based on which interface the packet is
- * being transmitted on.
+ * Returns: NETDEV_TX_OK both on success and on failure. On failure skb will
+ * be freed.
*
- * Note that this function also takes care of the TX status request and
- * potential unsharing of the SKB - this needs to be interleaved with the
- * header building.
- *
- * The function requires the read-side RCU lock held
- *
- * Returns: the (possibly reallocated) skb or an ERR_PTR() code
+ * This function takes in an Ethernet header and encapsulates it with suitable
+ * IEEE 802.11 header based on which interface the packet is coming in. The
+ * encapsulated packet will then be passed to master interface, wlan#.11, for
+ * transmission (through low-level driver).
*/
-static struct sk_buff *ieee80211_build_hdr(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, u32 info_flags)
+netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
+ struct net_device *dev)
{
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct ieee80211_tx_info *info;
int head_need;
@@ -1819,17 +1816,25 @@
bool wme_sta = false, authorized = false, tdls_auth = false;
bool tdls_peer = false, tdls_setup_frame = false;
bool multicast;
+ u32 info_flags = 0;
u16 info_id = 0;
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_sub_if_data *ap_sdata;
enum ieee80211_band band;
- int ret;
+
+ if (unlikely(skb->len < ETH_HLEN))
+ goto fail;
/* convert Ethernet header to proper 802.11 header (based on
* operation mode) */
ethertype = (skb->data[12] << 8) | skb->data[13];
fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA);
+ rcu_read_lock();
+
+ /* Measure frame arrival for Tx latency statistics calculation */
+ ieee80211_tx_latency_start_msrmnt(local, skb);
+
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
sta = rcu_dereference(sdata->u.vlan.sta);
@@ -1847,10 +1852,8 @@
ap_sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
u.ap);
chanctx_conf = rcu_dereference(ap_sdata->vif.chanctx_conf);
- if (!chanctx_conf) {
- ret = -ENOTCONN;
- goto free;
- }
+ if (!chanctx_conf)
+ goto fail_rcu;
band = chanctx_conf->def.chan->band;
if (sta)
break;
@@ -1858,10 +1861,8 @@
case NL80211_IFTYPE_AP:
if (sdata->vif.type == NL80211_IFTYPE_AP)
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (!chanctx_conf) {
- ret = -ENOTCONN;
- goto free;
- }
+ if (!chanctx_conf)
+ goto fail_rcu;
fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS);
/* DA BSSID SA */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -1948,10 +1949,8 @@
}
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (!chanctx_conf) {
- ret = -ENOTCONN;
- goto free;
- }
+ if (!chanctx_conf)
+ goto fail_rcu;
band = chanctx_conf->def.chan->band;
break;
#endif
@@ -1981,10 +1980,8 @@
* of a link teardown after a TDLS sta is removed due to being
* unreachable.
*/
- if (tdls_peer && !tdls_auth && !tdls_setup_frame) {
- ret = -EINVAL;
- goto free;
- }
+ if (tdls_peer && !tdls_auth && !tdls_setup_frame)
+ goto fail_rcu;
/* send direct packets to authorized TDLS peers */
if (tdls_peer && tdls_auth) {
@@ -2012,23 +2009,8 @@
hdrlen = 24;
}
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (!chanctx_conf) {
- ret = -ENOTCONN;
- goto free;
- }
- band = chanctx_conf->def.chan->band;
- break;
- case NL80211_IFTYPE_OCB:
- /* DA SA BSSID */
- memcpy(hdr.addr1, skb->data, ETH_ALEN);
- memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
- eth_broadcast_addr(hdr.addr3);
- hdrlen = 24;
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (!chanctx_conf) {
- ret = -ENOTCONN;
- goto free;
- }
+ if (!chanctx_conf)
+ goto fail_rcu;
band = chanctx_conf->def.chan->band;
break;
case NL80211_IFTYPE_ADHOC:
@@ -2038,15 +2020,12 @@
memcpy(hdr.addr3, sdata->u.ibss.bssid, ETH_ALEN);
hdrlen = 24;
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (!chanctx_conf) {
- ret = -ENOTCONN;
- goto free;
- }
+ if (!chanctx_conf)
+ goto fail_rcu;
band = chanctx_conf->def.chan->band;
break;
default:
- ret = -EINVAL;
- goto free;
+ goto fail_rcu;
}
/*
@@ -2078,19 +2057,17 @@
* EAPOL frames from the local station.
*/
if (unlikely(!ieee80211_vif_is_mesh(&sdata->vif) &&
- (sdata->vif.type != NL80211_IFTYPE_OCB) &&
!multicast && !authorized &&
(cpu_to_be16(ethertype) != sdata->control_port_protocol ||
!ether_addr_equal(sdata->vif.addr, skb->data + ETH_ALEN)))) {
#ifdef CPTCFG_MAC80211_VERBOSE_DEBUG
net_info_ratelimited("%s: dropped frame to %pM (unauthorized port)\n",
- sdata->name, hdr.addr1);
+ dev->name, hdr.addr1);
#endif
I802_DEBUG_INC(local->tx_handlers_drop_unauth_port);
- ret = -EPERM;
- goto free;
+ goto fail_rcu;
}
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,3,0))
@@ -2129,10 +2106,8 @@
skb = skb_clone(skb, GFP_ATOMIC);
kfree_skb(tmp_skb);
- if (!skb) {
- ret = -ENOMEM;
- goto free;
- }
+ if (!skb)
+ goto fail_rcu;
}
hdr.frame_control = fc;
@@ -2181,7 +2156,7 @@
if (ieee80211_skb_resize(sdata, skb, head_need, true)) {
ieee80211_free_txskb(&local->hw, skb);
skb = NULL;
- return ERR_PTR(-ENOMEM);
+ goto fail_rcu;
}
}
@@ -2215,6 +2190,9 @@
nh_pos += hdrlen;
h_pos += hdrlen;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
/* Update skb pointers to various headers since this modified frame
* is going to go through Linux networking code that may potentially
* need things like pointer to IP header. */
@@ -2225,90 +2203,23 @@
info = IEEE80211_SKB_CB(skb);
memset(info, 0, sizeof(*info));
- info->flags = info_flags;
- info->ack_frame_id = info_id;
- info->band = band;
-
- return skb;
- free:
- kfree_skb(skb);
- return ERR_PTR(ret);
-}
-
-void __ieee80211_subif_start_xmit(struct sk_buff *skb,
- struct net_device *dev,
- u32 info_flags)
-{
- struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
- struct ieee80211_local *local = sdata->local;
-
- if (unlikely(skb->len < ETH_HLEN)) {
- kfree_skb(skb);
- return;
- }
-
- rcu_read_lock();
-
- /* Measure frame arrival for Tx latency statistics calculation */
- ieee80211_tx_latency_start_msrmnt(local, skb);
-
- skb = ieee80211_build_hdr(sdata, skb, info_flags);
- if (IS_ERR(skb))
- goto out;
-
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
dev->trans_start = jiffies;
- ieee80211_xmit(sdata, skb);
- out:
- rcu_read_unlock();
-}
+ info->flags = info_flags;
+ info->ack_frame_id = info_id;
-/**
- * ieee80211_subif_start_xmit - netif start_xmit function for 802.3 vifs
- * @skb: packet to be sent
- * @dev: incoming interface
- *
- * On failure skb will be freed.
- */
-netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
- struct net_device *dev)
-{
- __ieee80211_subif_start_xmit(skb, dev, 0);
+ ieee80211_xmit(sdata, skb, band);
+ rcu_read_unlock();
+
+ return NETDEV_TX_OK;
+
+ fail_rcu:
+ rcu_read_unlock();
+ fail:
+ dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
-struct sk_buff *
-ieee80211_build_data_template(struct ieee80211_sub_if_data *sdata,
- struct sk_buff *skb, u32 info_flags)
-{
- struct ieee80211_hdr *hdr;
- struct ieee80211_tx_data tx = {
- .local = sdata->local,
- .sdata = sdata,
- };
-
- rcu_read_lock();
-
- skb = ieee80211_build_hdr(sdata, skb, info_flags);
- if (IS_ERR(skb))
- goto out;
-
- hdr = (void *)skb->data;
- tx.sta = sta_info_get(sdata, hdr->addr1);
- tx.skb = skb;
-
- if (ieee80211_tx_h_select_key(&tx) != TX_CONTINUE) {
- rcu_read_unlock();
- kfree_skb(skb);
- return ERR_PTR(-EINVAL);
- }
-
-out:
- rcu_read_unlock();
- return skb;
-}
/*
* ieee80211_clear_tx_pending may not be called in a context where
@@ -2348,8 +2259,8 @@
dev_kfree_skb(skb);
return true;
}
- info->band = chanctx_conf->def.chan->band;
- result = ieee80211_tx(sdata, skb, true);
+ result = ieee80211_tx(sdata, skb, true,
+ chanctx_conf->def.chan->band);
} else {
struct sk_buff_head skbs;
@@ -2963,16 +2874,19 @@
EXPORT_SYMBOL(ieee80211_nullfunc_get);
struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw,
- const u8 *src_addr,
+ struct ieee80211_vif *vif,
const u8 *ssid, size_t ssid_len,
size_t tailroom)
{
- struct ieee80211_local *local = hw_to_local(hw);
+ struct ieee80211_sub_if_data *sdata;
+ struct ieee80211_local *local;
struct ieee80211_hdr_3addr *hdr;
struct sk_buff *skb;
size_t ie_ssid_len;
u8 *pos;
+ sdata = vif_to_sdata(vif);
+ local = sdata->local;
ie_ssid_len = 2 + ssid_len;
skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*hdr) +
@@ -2987,7 +2901,7 @@
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_REQ);
eth_broadcast_addr(hdr->addr1);
- memcpy(hdr->addr2, src_addr, ETH_ALEN);
+ memcpy(hdr->addr2, vif->addr, ETH_ALEN);
eth_broadcast_addr(hdr->addr3);
pos = skb_put(skb, ie_ssid_len);
@@ -3106,97 +3020,6 @@
}
EXPORT_SYMBOL(ieee80211_get_buffered_bc);
-int ieee80211_reserve_tid(struct ieee80211_sta *pubsta, u8 tid)
-{
- struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
- struct ieee80211_sub_if_data *sdata = sta->sdata;
- struct ieee80211_local *local = sdata->local;
- int ret;
- u32 queues;
-
- lockdep_assert_held(&local->sta_mtx);
-
- /* only some cases are supported right now */
- switch (sdata->vif.type) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_AP_VLAN:
- break;
- default:
- WARN_ON(1);
- return -EINVAL;
- }
-
- if (WARN_ON(tid >= IEEE80211_NUM_UPS))
- return -EINVAL;
-
- if (sta->reserved_tid == tid) {
- ret = 0;
- goto out;
- }
-
- if (sta->reserved_tid != IEEE80211_TID_UNRESERVED) {
- sdata_err(sdata, "TID reservation already active\n");
- ret = -EALREADY;
- goto out;
- }
-
- ieee80211_stop_vif_queues(sdata->local, sdata,
- IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
-
- synchronize_net();
-
- /* Tear down BA sessions so we stop aggregating on this TID */
- if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) {
- set_sta_flag(sta, WLAN_STA_BLOCK_BA);
- __ieee80211_stop_tx_ba_session(sta, tid,
- AGG_STOP_LOCAL_REQUEST);
- }
-
- queues = BIT(sdata->vif.hw_queue[ieee802_1d_to_ac[tid]]);
- __ieee80211_flush_queues(local, sdata, queues);
-
- sta->reserved_tid = tid;
-
- ieee80211_wake_vif_queues(local, sdata,
- IEEE80211_QUEUE_STOP_REASON_RESERVE_TID);
-
- if (local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)
- clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
-
- ret = 0;
- out:
- return ret;
-}
-EXPORT_SYMBOL(ieee80211_reserve_tid);
-
-void ieee80211_unreserve_tid(struct ieee80211_sta *pubsta, u8 tid)
-{
- struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
- struct ieee80211_sub_if_data *sdata = sta->sdata;
-
- lockdep_assert_held(&sdata->local->sta_mtx);
-
- /* only some cases are supported right now */
- switch (sdata->vif.type) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_AP_VLAN:
- break;
- default:
- WARN_ON(1);
- return;
- }
-
- if (tid != sta->reserved_tid) {
- sdata_err(sdata, "TID to unreserve (%d) isn't reserved\n", tid);
- return;
- }
-
- sta->reserved_tid = IEEE80211_TID_UNRESERVED;
-}
-EXPORT_SYMBOL(ieee80211_unreserve_tid);
-
void __ieee80211_tx_skb_tid_band(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb, int tid,
enum ieee80211_band band)
@@ -3218,7 +3041,6 @@
* requirements are that we do not come into tx with bhs on.
*/
local_bh_disable();
- IEEE80211_SKB_CB(skb)->band = band;
- ieee80211_xmit(sdata, skb);
+ ieee80211_xmit(sdata, skb, band);
local_bh_enable();
}
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 974ebe7..3c61060 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -576,19 +576,15 @@
return queues;
}
-void __ieee80211_flush_queues(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- unsigned int queues)
+void ieee80211_flush_queues(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata)
{
+ unsigned int queues;
+
if (!local->ops->flush)
return;
- /*
- * If no queue was set, or if the HW doesn't support
- * IEEE80211_HW_QUEUE_CONTROL - flush all queues
- */
- if (!queues || !(local->hw.flags & IEEE80211_HW_QUEUE_CONTROL))
- queues = ieee80211_get_vif_queues(local, sdata);
+ queues = ieee80211_get_vif_queues(local, sdata);
ieee80211_stop_queues_by_reason(&local->hw, queues,
IEEE80211_QUEUE_STOP_REASON_FLUSH,
@@ -601,12 +597,6 @@
false);
}
-void ieee80211_flush_queues(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata)
-{
- __ieee80211_flush_queues(local, sdata, 0);
-}
-
void ieee80211_stop_vif_queues(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
enum queue_stop_reason reason)
@@ -703,34 +693,6 @@
}
EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl);
-static void __iterate_stations(struct ieee80211_local *local,
- void (*iterator)(void *data,
- struct ieee80211_sta *sta),
- void *data)
-{
- struct sta_info *sta;
-
- list_for_each_entry_rcu(sta, &local->sta_list, list) {
- if (!sta->uploaded)
- continue;
-
- iterator(data, &sta->sta);
- }
-}
-
-void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
- void (*iterator)(void *data,
- struct ieee80211_sta *sta),
- void *data)
-{
- struct ieee80211_local *local = hw_to_local(hw);
-
- rcu_read_lock();
- __iterate_stations(local, iterator, data);
- rcu_read_unlock();
-}
-EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_atomic);
-
struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
@@ -841,9 +803,6 @@
case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
case WLAN_EID_CHAN_SWITCH_PARAM:
- case WLAN_EID_EXT_CAPABILITY:
- case WLAN_EID_CHAN_SWITCH_TIMING:
- case WLAN_EID_LINK_ID:
/*
* not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
* that if the content gets bigger it might be needed more than once
@@ -863,24 +822,6 @@
elem_parse_failed = false;
switch (id) {
- case WLAN_EID_LINK_ID:
- if (elen + 2 != sizeof(struct ieee80211_tdls_lnkie)) {
- elem_parse_failed = true;
- break;
- }
- elems->lnk_id = (void *)(pos - 2);
- break;
- case WLAN_EID_CHAN_SWITCH_TIMING:
- if (elen != sizeof(struct ieee80211_ch_switch_timing)) {
- elem_parse_failed = true;
- break;
- }
- elems->ch_sw_timing = (void *)pos;
- break;
- case WLAN_EID_EXT_CAPABILITY:
- elems->ext_capab = pos;
- elems->ext_capab_len = elen;
- break;
case WLAN_EID_SSID:
elems->ssid = pos;
elems->ssid_len = elen;
@@ -1132,7 +1073,6 @@
struct ieee80211_chanctx_conf *chanctx_conf;
int ac;
bool use_11b, enable_qos;
- bool is_ocb; /* Use another EDCA parameters if dot11OCBActivated=true */
int aCWmin, aCWmax;
if (!local->ops->conf_tx)
@@ -1157,8 +1097,6 @@
*/
enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION);
- is_ocb = (sdata->vif.type == NL80211_IFTYPE_OCB);
-
/* Set defaults according to 802.11-2007 Table 7-37 */
aCWmax = 1023;
if (use_11b)
@@ -1180,10 +1118,7 @@
qparam.cw_max = aCWmax;
qparam.cw_min = aCWmin;
qparam.txop = 0;
- if (is_ocb)
- qparam.aifs = 9;
- else
- qparam.aifs = 7;
+ qparam.aifs = 7;
break;
/* never happens but let's not leave undefined */
default:
@@ -1191,32 +1126,21 @@
qparam.cw_max = aCWmax;
qparam.cw_min = aCWmin;
qparam.txop = 0;
- if (is_ocb)
- qparam.aifs = 6;
- else
- qparam.aifs = 3;
+ qparam.aifs = 3;
break;
case IEEE80211_AC_VI:
qparam.cw_max = aCWmin;
qparam.cw_min = (aCWmin + 1) / 2 - 1;
- if (is_ocb)
- qparam.txop = 0;
- else if (use_11b)
+ if (use_11b)
qparam.txop = 6016/32;
else
qparam.txop = 3008/32;
-
- if (is_ocb)
- qparam.aifs = 3;
- else
- qparam.aifs = 2;
+ qparam.aifs = 2;
break;
case IEEE80211_AC_VO:
qparam.cw_max = (aCWmin + 1) / 2 - 1;
qparam.cw_min = (aCWmin + 1) / 4 - 1;
- if (is_ocb)
- qparam.txop = 0;
- else if (use_11b)
+ if (use_11b)
qparam.txop = 3264/32;
else
qparam.txop = 1504/32;
@@ -1339,7 +1263,6 @@
int ext_rates_len;
int shift;
u32 rate_flags;
- bool have_80mhz = false;
*offset = 0;
@@ -1468,15 +1391,7 @@
*offset = noffset;
}
- /* Check if any channel in this sband supports at least 80 MHz */
- for (i = 0; i < sband->n_channels; i++) {
- if (!(sband->channels[i].flags & IEEE80211_CHAN_NO_80MHZ)) {
- have_80mhz = true;
- break;
- }
- }
-
- if (sband->vht_cap.vht_supported && have_80mhz) {
+ if (sband->vht_cap.vht_supported) {
if (end - pos < 2 + sizeof(struct ieee80211_vht_cap))
goto out_err;
pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
@@ -1532,8 +1447,7 @@
};
struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
- const u8 *src, const u8 *dst,
- u32 ratemask,
+ u8 *dst, u32 ratemask,
struct ieee80211_channel *chan,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len,
@@ -1558,8 +1472,8 @@
else
chandef.chan = chan;
- skb = ieee80211_probereq_get(&local->hw, src, ssid, ssid_len,
- 100 + ie_len);
+ skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
+ ssid, ssid_len, 100 + ie_len);
if (!skb)
return NULL;
@@ -1581,8 +1495,7 @@
return skb;
}
-void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata,
- const u8 *src, const u8 *dst,
+void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len,
u32 ratemask, bool directed, u32 tx_flags,
@@ -1590,7 +1503,7 @@
{
struct sk_buff *skb;
- skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel,
+ skb = ieee80211_build_probe_req(sdata, dst, ratemask, channel,
ssid, ssid_len,
ie, ie_len, directed);
if (skb) {
@@ -1732,7 +1645,6 @@
int res, i;
bool reconfig_due_to_wowlan = false;
struct ieee80211_sub_if_data *sched_scan_sdata;
- struct cfg80211_sched_scan_request *sched_scan_req;
bool sched_scan_stopped = false;
#ifdef CONFIG_PM
@@ -1901,10 +1813,6 @@
ieee80211_bss_info_change_notify(sdata, changed);
sdata_unlock(sdata);
break;
- case NL80211_IFTYPE_OCB:
- changed |= BSS_CHANGED_OCB;
- ieee80211_bss_info_change_notify(sdata, changed);
- break;
case NL80211_IFTYPE_ADHOC:
changed |= BSS_CHANGED_IBSS;
/* fall through */
@@ -2023,15 +1931,13 @@
mutex_lock(&local->mtx);
sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
lockdep_is_held(&local->mtx));
- sched_scan_req = rcu_dereference_protected(local->sched_scan_req,
- lockdep_is_held(&local->mtx));
- if (sched_scan_sdata && sched_scan_req)
+ if (sched_scan_sdata && local->sched_scan_req)
/*
* Sched scan stopped, but we don't want to report it. Instead,
* we're trying to reschedule.
*/
if (__ieee80211_request_sched_scan_start(sched_scan_sdata,
- sched_scan_req))
+ local->sched_scan_req))
sched_scan_stopped = true;
mutex_unlock(&local->mtx);
@@ -2043,7 +1949,7 @@
* We may want to change that later, however.
*/
if (!local->suspended || reconfig_due_to_wowlan)
- drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
+ drv_restart_complete(local);
if (!local->suspended)
return 0;
@@ -2054,9 +1960,6 @@
mb();
local->resuming = false;
- if (!reconfig_due_to_wowlan)
- drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
-
list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata))
continue;
@@ -2149,35 +2052,41 @@
return false;
}
-size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
- const u8 *ids, int n_ids,
- const u8 *after_ric, int n_after_ric,
- size_t offset)
-{
- size_t pos = offset;
-
- while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
- if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
- pos += 2 + ies[pos + 1];
-
- while (pos < ielen &&
- !ieee80211_id_in_list(after_ric, n_after_ric,
- ies[pos]))
- pos += 2 + ies[pos + 1];
- } else {
- pos += 2 + ies[pos + 1];
- }
- }
-
- return pos;
-}
-
+/**
+ * ieee80211_ie_split - split an IE buffer according to ordering
+ *
+ * @ies: the IE buffer
+ * @ielen: the length of the IE buffer
+ * @ids: an array with element IDs that are allowed before
+ * the split
+ * @n_ids: the size of the element ID array
+ * @offset: offset where to start splitting in the buffer
+ *
+ * This function splits an IE buffer by updating the @offset
+ * variable to point to the location where the buffer should be
+ * split.
+ *
+ * It assumes that the given IE buffer is well-formed, this
+ * has to be guaranteed by the caller!
+ *
+ * It also assumes that the IEs in the buffer are ordered
+ * correctly, if not the result of using this function will not
+ * be ordered correctly either, i.e. it does no reordering.
+ *
+ * The function returns the offset where the next part of the
+ * buffer starts, which may be @ielen if the entire (remainder)
+ * of the buffer should be used.
+ */
size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
const u8 *ids, int n_ids, size_t offset)
{
- return ieee80211_ie_split_ric(ies, ielen, ids, n_ids, NULL, 0, offset);
+ size_t pos = offset;
+
+ while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos]))
+ pos += 2 + ies[pos + 1];
+
+ return pos;
}
-EXPORT_SYMBOL(ieee80211_ie_split);
size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
{
@@ -2617,23 +2526,11 @@
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, radar_detected_work);
struct cfg80211_chan_def chandef = local->hw.conf.chandef;
- struct ieee80211_chanctx *ctx;
- int num_chanctx = 0;
-
- mutex_lock(&local->chanctx_mtx);
- list_for_each_entry(ctx, &local->chanctx_list, list) {
- if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
- continue;
-
- num_chanctx++;
- chandef = ctx->conf.def;
- }
- mutex_unlock(&local->chanctx_mtx);
ieee80211_dfs_cac_cancel(local);
- if (num_chanctx > 1)
- /* XXX: multi-channel is not supported yet */
+ if (local->use_chanctx)
+ /* currently not handled */
WARN_ON(1);
else
cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c
index bc9e8fc..671ce0d 100644
--- a/net/mac80211/vht.c
+++ b/net/mac80211/vht.c
@@ -287,8 +287,6 @@
/* fall through */
case NL80211_CHAN_WIDTH_20_NOHT:
case NL80211_CHAN_WIDTH_20:
- bw = IEEE80211_STA_RX_BW_20;
- break;
case NL80211_CHAN_WIDTH_40:
bw = sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 ?
IEEE80211_STA_RX_BW_40 : IEEE80211_STA_RX_BW_20;
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c
index a4220e9..9181fb6 100644
--- a/net/mac80211/wep.c
+++ b/net/mac80211/wep.c
@@ -111,6 +111,8 @@
(info->control.hw_key->flags & IEEE80211_KEY_FLAG_PUT_IV_SPACE))
return newhdr + hdrlen;
+ skb_set_network_header(skb, skb_network_offset(skb) +
+ IEEE80211_WEP_IV_LEN);
ieee80211_wep_get_iv(local, keylen, keyidx, newhdr + hdrlen);
return newhdr + hdrlen;
}
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index c04e74d..77509d8 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -53,49 +53,11 @@
}
}
-/**
- * ieee80211_fix_reserved_tid - return the TID to use if this one is reserved
- * @tid: the assumed-reserved TID
- *
- * Returns: the alternative TID to use, or 0 on error
- */
-static inline u8 ieee80211_fix_reserved_tid(u8 tid)
-{
- switch (tid) {
- case 0:
- return 3;
- case 1:
- return 2;
- case 2:
- return 1;
- case 3:
- return 0;
- case 4:
- return 5;
- case 5:
- return 4;
- case 6:
- return 7;
- case 7:
- return 6;
- }
-
- return 0;
-}
-
static u16 ieee80211_downgrade_queue(struct ieee80211_sub_if_data *sdata,
- struct sta_info *sta, struct sk_buff *skb)
+ struct sk_buff *skb)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-
/* in case we are a client verify acm is not set for this ac */
- while (sdata->wmm_acm & BIT(skb->priority)) {
- int ac = ieee802_1d_to_ac[skb->priority];
-
- if (ifmgd->tx_tspec[ac].admitted_time &&
- skb->priority == ifmgd->tx_tspec[ac].up)
- return ac;
-
+ while (unlikely(sdata->wmm_acm & BIT(skb->priority))) {
if (wme_downgrade_ac(skb)) {
/*
* This should not really happen. The AP has marked all
@@ -107,10 +69,6 @@
}
}
- /* Check to see if this is a reserved TID */
- if (sta && sta->reserved_tid == skb->priority)
- skb->priority = ieee80211_fix_reserved_tid(skb->priority);
-
/* look up which queue to use for frames with this 1d tag */
return ieee802_1d_to_ac[skb->priority];
}
@@ -138,7 +96,7 @@
p = ieee80211_get_qos_ctl(hdr);
skb->priority = *p & IEEE80211_QOS_CTL_TAG1D_MASK;
- return ieee80211_downgrade_queue(sdata, NULL, skb);
+ return ieee80211_downgrade_queue(sdata, skb);
}
/* Indicate which queue to use. */
@@ -150,7 +108,6 @@
const u8 *ra = NULL;
bool qos = false;
struct mac80211_qos_map *qos_map;
- u16 ret;
if (local->hw.queues < IEEE80211_NUM_ACS || skb->len < 6) {
skb->priority = 0; /* required for correct WPA/11i MIC */
@@ -177,20 +134,11 @@
break;
#endif
case NL80211_IFTYPE_STATION:
- /* might be a TDLS station */
- sta = sta_info_get(sdata, skb->data);
- if (sta)
- qos = sta->sta.wme;
-
ra = sdata->u.mgd.bssid;
break;
case NL80211_IFTYPE_ADHOC:
ra = skb->data;
break;
- case NL80211_IFTYPE_OCB:
- /* all stations are required to support WME */
- qos = true;
- break;
default:
break;
}
@@ -200,29 +148,27 @@
if (sta)
qos = sta->sta.wme;
}
+ rcu_read_unlock();
if (!qos) {
skb->priority = 0; /* required for correct WPA/11i MIC */
- ret = IEEE80211_AC_BE;
- goto out;
+ return IEEE80211_AC_BE;
}
if (skb->protocol == sdata->control_port_protocol) {
skb->priority = 7;
- goto downgrade;
+ return ieee80211_downgrade_queue(sdata, skb);
}
/* use the data classifier to determine what 802.1d tag the
* data frame has */
+ rcu_read_lock();
qos_map = rcu_dereference(sdata->qos_map);
skb->priority = cfg80211_classify8021d(skb, qos_map ?
&qos_map->qos_map : NULL);
-
- downgrade:
- ret = ieee80211_downgrade_queue(sdata, sta, skb);
- out:
rcu_read_unlock();
- return ret;
+
+ return ieee80211_downgrade_queue(sdata, skb);
}
/**
diff --git a/net/mac80211/wme.h b/net/mac80211/wme.h
index 80151ed..7fea4bb 100644
--- a/net/mac80211/wme.h
+++ b/net/mac80211/wme.h
@@ -13,6 +13,8 @@
#include <linux/netdevice.h>
#include "ieee80211_i.h"
+extern const int ieee802_1d_to_ac[8];
+
u16 ieee80211_select_queue_80211(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb,
struct ieee80211_hdr *hdr);
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c
index 12398fd..983527a 100644
--- a/net/mac80211/wpa.c
+++ b/net/mac80211/wpa.c
@@ -209,6 +209,8 @@
pos = skb_push(skb, IEEE80211_TKIP_IV_LEN);
memmove(pos, pos + IEEE80211_TKIP_IV_LEN, hdrlen);
+ skb_set_network_header(skb, skb_network_offset(skb) +
+ IEEE80211_TKIP_IV_LEN);
pos += hdrlen;
/* the HW only needs room for the IV, but not the actual IV */
@@ -432,6 +434,8 @@
pos = skb_push(skb, IEEE80211_CCMP_HDR_LEN);
memmove(pos, pos + IEEE80211_CCMP_HDR_LEN, hdrlen);
+ skb_set_network_header(skb, skb_network_offset(skb) +
+ IEEE80211_CCMP_HDR_LEN);
/* the HW only needs room for the IV, but not the actual IV */
if (info->control.hw_key &&
@@ -571,6 +575,7 @@
pos = skb_push(skb, cs->hdr_len);
memmove(pos, pos + cs->hdr_len, hdrlen);
+ skb_set_network_header(skb, skb_network_offset(skb) + cs->hdr_len);
return TX_CONTINUE;
}
diff --git a/net/mac802154/Kconfig b/net/mac802154/Kconfig
index 4621ecb..e62e73f 100644
--- a/net/mac802154/Kconfig
+++ b/net/mac802154/Kconfig
@@ -4,7 +4,7 @@
depends on IEEE802154
depends on CRC_CCITT
depends on CRYPTO_AUTHENC
- select BPAUTO_CRYPTO_CCM
+ select BACKPORT_CRYPTO_CCM
depends on CRYPTO_CTR
depends on CRYPTO_AES
---help---
@@ -17,5 +17,5 @@
been tested yet!
If you plan to use HardMAC IEEE 802.15.4 devices, you can
- say N here. Alternatively you can say M to compile it as
+ say N here. Alternatievly you can say M to compile it as
module.
diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile
index 4ea25d0..562844a 100644
--- a/net/mac802154/Makefile
+++ b/net/mac802154/Makefile
@@ -1,5 +1,5 @@
obj-$(CPTCFG_MAC802154) += mac802154.o
-mac802154-objs := main.o rx.o tx.o mac_cmd.o mib.o \
- iface.o llsec.o util.o cfg.o
+mac802154-objs := ieee802154_dev.o rx.o tx.o mac_cmd.o mib.o \
+ monitor.o wpan.o llsec.o
ccflags-y += -D__CHECK_ENDIAN__
diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c
deleted file mode 100644
index c035708..0000000
--- a/net/mac802154/cfg.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/* 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.
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- *
- * Based on: net/mac80211/cfg.c
- */
-
-#include <net/rtnetlink.h>
-#include <net/cfg802154.h>
-
-#include "ieee802154_i.h"
-#include "driver-ops.h"
-#include "cfg.h"
-
-static struct net_device *
-ieee802154_add_iface_deprecated(struct wpan_phy *wpan_phy,
- const char *name, int type)
-{
- struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
- struct net_device *dev;
-
- rtnl_lock();
- dev = ieee802154_if_add(local, name, type,
- cpu_to_le64(0x0000000000000000ULL));
- rtnl_unlock();
-
- return dev;
-}
-
-static void ieee802154_del_iface_deprecated(struct wpan_phy *wpan_phy,
- struct net_device *dev)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-
- ieee802154_if_remove(sdata);
-}
-
-static int
-ieee802154_add_iface(struct wpan_phy *phy, const char *name,
- enum nl802154_iftype type, __le64 extended_addr)
-{
- struct ieee802154_local *local = wpan_phy_priv(phy);
- struct net_device *err;
-
- err = ieee802154_if_add(local, name, type, extended_addr);
- if (IS_ERR(err))
- return PTR_ERR(err);
-
- return 0;
-}
-
-static int
-ieee802154_del_iface(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev)
-{
- ieee802154_if_remove(IEEE802154_WPAN_DEV_TO_SUB_IF(wpan_dev));
-
- return 0;
-}
-
-static int
-ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel)
-{
- struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
- int ret;
-
- ASSERT_RTNL();
-
- /* check if phy support this setting */
- if (!(wpan_phy->channels_supported[page] & BIT(channel)))
- return -EINVAL;
-
- ret = drv_set_channel(local, page, channel);
- if (!ret) {
- wpan_phy->current_page = page;
- wpan_phy->current_channel = channel;
- }
-
- return ret;
-}
-
-static int
-ieee802154_set_pan_id(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
- __le16 pan_id)
-{
- ASSERT_RTNL();
-
- /* TODO
- * I am not sure about to check here on broadcast pan_id.
- * Broadcast is a valid setting, comment from 802.15.4:
- * If this value is 0xffff, the device is not associated.
- *
- * This could useful to simple deassociate an device.
- */
- if (pan_id == cpu_to_le16(IEEE802154_PAN_ID_BROADCAST))
- return -EINVAL;
-
- wpan_dev->pan_id = pan_id;
- return 0;
-}
-
-static int
-ieee802154_set_backoff_exponent(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev,
- u8 min_be, u8 max_be)
-{
- struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-
- ASSERT_RTNL();
-
- if (!(local->hw.flags & IEEE802154_HW_CSMA_PARAMS))
- return -EOPNOTSUPP;
-
- wpan_dev->min_be = min_be;
- wpan_dev->max_be = max_be;
- return 0;
-}
-
-static int
-ieee802154_set_short_addr(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
- __le16 short_addr)
-{
- ASSERT_RTNL();
-
- /* TODO
- * I am not sure about to check here on broadcast short_addr.
- * Broadcast is a valid setting, comment from 802.15.4:
- * A value of 0xfffe indicates that the device has
- * associated but has not been allocated an address. A
- * value of 0xffff indicates that the device does not
- * have a short address.
- *
- * I think we should allow to set these settings but
- * don't allow to allow socket communication with it.
- */
- if (short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC) ||
- short_addr == cpu_to_le16(IEEE802154_ADDR_SHORT_BROADCAST))
- return -EINVAL;
-
- wpan_dev->short_addr = short_addr;
- return 0;
-}
-
-static int
-ieee802154_set_max_csma_backoffs(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev,
- u8 max_csma_backoffs)
-{
- struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-
- ASSERT_RTNL();
-
- if (!(local->hw.flags & IEEE802154_HW_CSMA_PARAMS))
- return -EOPNOTSUPP;
-
- wpan_dev->csma_retries = max_csma_backoffs;
- return 0;
-}
-
-static int
-ieee802154_set_max_frame_retries(struct wpan_phy *wpan_phy,
- struct wpan_dev *wpan_dev,
- s8 max_frame_retries)
-{
- struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-
- ASSERT_RTNL();
-
- if (!(local->hw.flags & IEEE802154_HW_FRAME_RETRIES))
- return -EOPNOTSUPP;
-
- wpan_dev->frame_retries = max_frame_retries;
- return 0;
-}
-
-static int
-ieee802154_set_lbt_mode(struct wpan_phy *wpan_phy, struct wpan_dev *wpan_dev,
- bool mode)
-{
- struct ieee802154_local *local = wpan_phy_priv(wpan_phy);
-
- ASSERT_RTNL();
-
- if (!(local->hw.flags & IEEE802154_HW_LBT))
- return -EOPNOTSUPP;
-
- wpan_dev->lbt = mode;
- return 0;
-}
-
-const struct cfg802154_ops mac802154_config_ops = {
- .add_virtual_intf_deprecated = ieee802154_add_iface_deprecated,
- .del_virtual_intf_deprecated = ieee802154_del_iface_deprecated,
- .add_virtual_intf = ieee802154_add_iface,
- .del_virtual_intf = ieee802154_del_iface,
- .set_channel = ieee802154_set_channel,
- .set_pan_id = ieee802154_set_pan_id,
- .set_short_addr = ieee802154_set_short_addr,
- .set_backoff_exponent = ieee802154_set_backoff_exponent,
- .set_max_csma_backoffs = ieee802154_set_max_csma_backoffs,
- .set_max_frame_retries = ieee802154_set_max_frame_retries,
- .set_lbt_mode = ieee802154_set_lbt_mode,
-};
diff --git a/net/mac802154/cfg.h b/net/mac802154/cfg.h
deleted file mode 100644
index e2718f9..0000000
--- a/net/mac802154/cfg.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/* mac802154 configuration hooks for cfg802154
- */
-
-#ifndef __CFG_H
-#define __CFG_H
-
-extern const struct cfg802154_ops mac802154_config_ops;
-
-#endif /* __CFG_H */
diff --git a/net/mac802154/driver-ops.h b/net/mac802154/driver-ops.h
deleted file mode 100644
index f21e864..0000000
--- a/net/mac802154/driver-ops.h
+++ /dev/null
@@ -1,222 +0,0 @@
-#ifndef __MAC802154_DRVIER_OPS
-#define __MAC802154_DRIVER_OPS
-
-#include <linux/types.h>
-#include <linux/rtnetlink.h>
-
-#include <net/mac802154.h>
-
-#include "ieee802154_i.h"
-
-static inline int
-drv_xmit_async(struct ieee802154_local *local, struct sk_buff *skb)
-{
- return local->ops->xmit_async(&local->hw, skb);
-}
-
-static inline int
-drv_xmit_sync(struct ieee802154_local *local, struct sk_buff *skb)
-{
- /* don't allow other operations while sync xmit */
- ASSERT_RTNL();
-
- might_sleep();
-
- return local->ops->xmit_sync(&local->hw, skb);
-}
-
-static inline int drv_start(struct ieee802154_local *local)
-{
- might_sleep();
-
- local->started = true;
- smp_mb();
-
- return local->ops->start(&local->hw);
-}
-
-static inline void drv_stop(struct ieee802154_local *local)
-{
- might_sleep();
-
- local->ops->stop(&local->hw);
-
- /* sync away all work on the tasklet before clearing started */
- tasklet_disable(&local->tasklet);
- tasklet_enable(&local->tasklet);
-
- barrier();
-
- local->started = false;
-}
-
-static inline int
-drv_set_channel(struct ieee802154_local *local, u8 page, u8 channel)
-{
- might_sleep();
-
- return local->ops->set_channel(&local->hw, page, channel);
-}
-
-static inline int drv_set_tx_power(struct ieee802154_local *local, s8 dbm)
-{
- might_sleep();
-
- if (!local->ops->set_txpower) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- return local->ops->set_txpower(&local->hw, dbm);
-}
-
-static inline int drv_set_cca_mode(struct ieee802154_local *local, u8 cca_mode)
-{
- might_sleep();
-
- if (!local->ops->set_cca_mode) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- return local->ops->set_cca_mode(&local->hw, cca_mode);
-}
-
-static inline int drv_set_lbt_mode(struct ieee802154_local *local, bool mode)
-{
- might_sleep();
-
- if (!local->ops->set_lbt) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- return local->ops->set_lbt(&local->hw, mode);
-}
-
-static inline int
-drv_set_cca_ed_level(struct ieee802154_local *local, s32 ed_level)
-{
- might_sleep();
-
- if (!local->ops->set_cca_ed_level) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- return local->ops->set_cca_ed_level(&local->hw, ed_level);
-}
-
-static inline int drv_set_pan_id(struct ieee802154_local *local, __le16 pan_id)
-{
- struct ieee802154_hw_addr_filt filt;
-
- might_sleep();
-
- if (!local->ops->set_hw_addr_filt) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- filt.pan_id = pan_id;
-
- return local->ops->set_hw_addr_filt(&local->hw, &filt,
- IEEE802154_AFILT_PANID_CHANGED);
-}
-
-static inline int
-drv_set_extended_addr(struct ieee802154_local *local, __le64 extended_addr)
-{
- struct ieee802154_hw_addr_filt filt;
-
- might_sleep();
-
- if (!local->ops->set_hw_addr_filt) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- filt.ieee_addr = extended_addr;
-
- return local->ops->set_hw_addr_filt(&local->hw, &filt,
- IEEE802154_AFILT_IEEEADDR_CHANGED);
-}
-
-static inline int
-drv_set_short_addr(struct ieee802154_local *local, __le16 short_addr)
-{
- struct ieee802154_hw_addr_filt filt;
-
- might_sleep();
-
- if (!local->ops->set_hw_addr_filt) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- filt.short_addr = short_addr;
-
- return local->ops->set_hw_addr_filt(&local->hw, &filt,
- IEEE802154_AFILT_SADDR_CHANGED);
-}
-
-static inline int
-drv_set_pan_coord(struct ieee802154_local *local, bool is_coord)
-{
- struct ieee802154_hw_addr_filt filt;
-
- might_sleep();
-
- if (!local->ops->set_hw_addr_filt) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- filt.pan_coord = is_coord;
-
- return local->ops->set_hw_addr_filt(&local->hw, &filt,
- IEEE802154_AFILT_PANC_CHANGED);
-}
-
-static inline int
-drv_set_csma_params(struct ieee802154_local *local, u8 min_be, u8 max_be,
- u8 max_csma_backoffs)
-{
- might_sleep();
-
- if (!local->ops->set_csma_params) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- return local->ops->set_csma_params(&local->hw, min_be, max_be,
- max_csma_backoffs);
-}
-
-static inline int
-drv_set_max_frame_retries(struct ieee802154_local *local, s8 max_frame_retries)
-{
- might_sleep();
-
- if (!local->ops->set_frame_retries) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- return local->ops->set_frame_retries(&local->hw, max_frame_retries);
-}
-
-static inline int
-drv_set_promiscuous_mode(struct ieee802154_local *local, bool on)
-{
- might_sleep();
-
- if (!local->ops->set_promiscuous_mode) {
- WARN_ON(1);
- return -EOPNOTSUPP;
- }
-
- return local->ops->set_promiscuous_mode(&local->hw, on);
-}
-
-#endif /* __MAC802154_DRVIER_OPS */
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c
new file mode 100644
index 0000000..b36b2b9
--- /dev/null
+++ b/net/mac802154/ieee802154_dev.c
@@ -0,0 +1,415 @@
+/*
+ * Copyright (C) 2007-2012 Siemens AG
+ *
+ * Written by:
+ * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ *
+ * Based on the code from 'linux-zigbee.sourceforge.net' project.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+
+#include <net/netlink.h>
+#include <linux/nl802154.h>
+#include <net/mac802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/route.h>
+#include <net/wpan-phy.h>
+
+#include "mac802154.h"
+
+int mac802154_slave_open(struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct mac802154_sub_if_data *subif;
+ struct mac802154_priv *ipriv = priv->hw;
+ int res = 0;
+
+ ASSERT_RTNL();
+
+ if (priv->type == IEEE802154_DEV_WPAN) {
+ mutex_lock(&priv->hw->slaves_mtx);
+ list_for_each_entry(subif, &priv->hw->slaves, list) {
+ if (subif != priv && subif->type == priv->type &&
+ subif->running) {
+ mutex_unlock(&priv->hw->slaves_mtx);
+ return -EBUSY;
+ }
+ }
+ mutex_unlock(&priv->hw->slaves_mtx);
+ }
+
+ mutex_lock(&priv->hw->slaves_mtx);
+ priv->running = true;
+ mutex_unlock(&priv->hw->slaves_mtx);
+
+ if (ipriv->open_count++ == 0) {
+ res = ipriv->ops->start(&ipriv->hw);
+ WARN_ON(res);
+ if (res)
+ goto err;
+ }
+
+ if (ipriv->ops->ieee_addr) {
+ __le64 addr = ieee802154_devaddr_from_raw(dev->dev_addr);
+
+ res = ipriv->ops->ieee_addr(&ipriv->hw, addr);
+ WARN_ON(res);
+ if (res)
+ goto err;
+ mac802154_dev_set_ieee_addr(dev);
+ }
+
+ netif_start_queue(dev);
+ return 0;
+err:
+ priv->hw->open_count--;
+
+ return res;
+}
+
+int mac802154_slave_close(struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct mac802154_priv *ipriv = priv->hw;
+
+ ASSERT_RTNL();
+
+ netif_stop_queue(dev);
+
+ mutex_lock(&priv->hw->slaves_mtx);
+ priv->running = false;
+ mutex_unlock(&priv->hw->slaves_mtx);
+
+ if (!--ipriv->open_count)
+ ipriv->ops->stop(&ipriv->hw);
+
+ return 0;
+}
+
+static int
+mac802154_netdev_register(struct wpan_phy *phy, struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv;
+ struct mac802154_priv *ipriv;
+ int err;
+
+ ipriv = wpan_phy_priv(phy);
+
+ priv = netdev_priv(dev);
+ priv->dev = dev;
+ priv->hw = ipriv;
+
+ dev->needed_headroom = ipriv->hw.extra_tx_headroom;
+
+ SET_NETDEV_DEV(dev, &ipriv->phy->dev);
+
+ mutex_lock(&ipriv->slaves_mtx);
+ if (!ipriv->running) {
+ mutex_unlock(&ipriv->slaves_mtx);
+ return -ENODEV;
+ }
+ mutex_unlock(&ipriv->slaves_mtx);
+
+ err = register_netdev(dev);
+ if (err < 0)
+ return err;
+
+ rtnl_lock();
+ mutex_lock(&ipriv->slaves_mtx);
+ list_add_tail_rcu(&priv->list, &ipriv->slaves);
+ mutex_unlock(&ipriv->slaves_mtx);
+ rtnl_unlock();
+
+ return 0;
+}
+
+static void
+mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev)
+{
+ struct mac802154_sub_if_data *sdata;
+
+ ASSERT_RTNL();
+
+ sdata = netdev_priv(dev);
+
+ BUG_ON(sdata->hw->phy != phy);
+
+ mutex_lock(&sdata->hw->slaves_mtx);
+ list_del_rcu(&sdata->list);
+ mutex_unlock(&sdata->hw->slaves_mtx);
+
+ synchronize_rcu();
+ unregister_netdevice(sdata->dev);
+}
+
+static struct net_device *
+mac802154_add_iface(struct wpan_phy *phy, const char *name, int type)
+{
+ struct net_device *dev;
+ int err = -ENOMEM;
+
+ switch (type) {
+ case IEEE802154_DEV_MONITOR:
+ dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
+ name, NET_NAME_UNKNOWN,
+ mac802154_monitor_setup);
+ break;
+ case IEEE802154_DEV_WPAN:
+ dev = alloc_netdev(sizeof(struct mac802154_sub_if_data),
+ name, NET_NAME_UNKNOWN,
+ mac802154_wpan_setup);
+ break;
+ default:
+ dev = NULL;
+ err = -EINVAL;
+ break;
+ }
+ if (!dev)
+ goto err;
+
+ err = mac802154_netdev_register(phy, dev);
+ if (err)
+ goto err_free;
+
+ dev_hold(dev); /* we return an incremented device refcount */
+ return dev;
+
+err_free:
+ free_netdev(dev);
+err:
+ return ERR_PTR(err);
+}
+
+static int mac802154_set_txpower(struct wpan_phy *phy, int db)
+{
+ struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+ return priv->ops->set_txpower(&priv->hw, db);
+}
+
+static int mac802154_set_lbt(struct wpan_phy *phy, bool on)
+{
+ struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+ return priv->ops->set_lbt(&priv->hw, on);
+}
+
+static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode)
+{
+ struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+ return priv->ops->set_cca_mode(&priv->hw, mode);
+}
+
+static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level)
+{
+ struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+ return priv->ops->set_cca_ed_level(&priv->hw, level);
+}
+
+static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be,
+ u8 max_be, u8 retries)
+{
+ struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+ return priv->ops->set_csma_params(&priv->hw, min_be, max_be, retries);
+}
+
+static int mac802154_set_frame_retries(struct wpan_phy *phy, s8 retries)
+{
+ struct mac802154_priv *priv = wpan_phy_priv(phy);
+
+ return priv->ops->set_frame_retries(&priv->hw, retries);
+}
+
+struct ieee802154_dev *
+ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops)
+{
+ struct wpan_phy *phy;
+ struct mac802154_priv *priv;
+ size_t priv_size;
+
+ if (!ops || !ops->xmit || !ops->ed || !ops->start ||
+ !ops->stop || !ops->set_channel) {
+ pr_err("undefined IEEE802.15.4 device operations\n");
+ return NULL;
+ }
+
+ /* Ensure 32-byte alignment of our private data and hw private data.
+ * We use the wpan_phy priv data for both our mac802154_priv and for
+ * the driver's private data
+ *
+ * in memory it'll be like this:
+ *
+ * +-----------------------+
+ * | struct wpan_phy |
+ * +-----------------------+
+ * | struct mac802154_priv |
+ * +-----------------------+
+ * | driver's private data |
+ * +-----------------------+
+ *
+ * Due to ieee802154 layer isn't aware of driver and MAC structures,
+ * so lets allign them here.
+ */
+
+ priv_size = ALIGN(sizeof(*priv), NETDEV_ALIGN) + priv_data_len;
+
+ phy = wpan_phy_alloc(priv_size);
+ if (!phy) {
+ pr_err("failure to allocate master IEEE802.15.4 device\n");
+ return NULL;
+ }
+
+ priv = wpan_phy_priv(phy);
+ priv->phy = phy;
+ priv->hw.phy = priv->phy;
+ priv->hw.priv = (char *)priv + ALIGN(sizeof(*priv), NETDEV_ALIGN);
+ priv->ops = ops;
+
+ INIT_LIST_HEAD(&priv->slaves);
+ mutex_init(&priv->slaves_mtx);
+
+ return &priv->hw;
+}
+EXPORT_SYMBOL(ieee802154_alloc_device);
+
+void ieee802154_free_device(struct ieee802154_dev *hw)
+{
+ struct mac802154_priv *priv = mac802154_to_priv(hw);
+
+ BUG_ON(!list_empty(&priv->slaves));
+
+ mutex_destroy(&priv->slaves_mtx);
+
+ wpan_phy_free(priv->phy);
+}
+EXPORT_SYMBOL(ieee802154_free_device);
+
+int ieee802154_register_device(struct ieee802154_dev *dev)
+{
+ struct mac802154_priv *priv = mac802154_to_priv(dev);
+ int rc = -ENOSYS;
+
+ if (dev->flags & IEEE802154_HW_TXPOWER) {
+ if (!priv->ops->set_txpower)
+ goto out;
+
+ priv->phy->set_txpower = mac802154_set_txpower;
+ }
+
+ if (dev->flags & IEEE802154_HW_LBT) {
+ if (!priv->ops->set_lbt)
+ goto out;
+
+ priv->phy->set_lbt = mac802154_set_lbt;
+ }
+
+ if (dev->flags & IEEE802154_HW_CCA_MODE) {
+ if (!priv->ops->set_cca_mode)
+ goto out;
+
+ priv->phy->set_cca_mode = mac802154_set_cca_mode;
+ }
+
+ if (dev->flags & IEEE802154_HW_CCA_ED_LEVEL) {
+ if (!priv->ops->set_cca_ed_level)
+ goto out;
+
+ priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level;
+ }
+
+ if (dev->flags & IEEE802154_HW_CSMA_PARAMS) {
+ if (!priv->ops->set_csma_params)
+ goto out;
+
+ priv->phy->set_csma_params = mac802154_set_csma_params;
+ }
+
+ if (dev->flags & IEEE802154_HW_FRAME_RETRIES) {
+ if (!priv->ops->set_frame_retries)
+ goto out;
+
+ priv->phy->set_frame_retries = mac802154_set_frame_retries;
+ }
+
+ priv->dev_workqueue =
+ create_singlethread_workqueue(wpan_phy_name(priv->phy));
+ if (!priv->dev_workqueue) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ wpan_phy_set_dev(priv->phy, priv->hw.parent);
+
+ priv->phy->add_iface = mac802154_add_iface;
+ priv->phy->del_iface = mac802154_del_iface;
+
+ rc = wpan_phy_register(priv->phy);
+ if (rc < 0)
+ goto out_wq;
+
+ rtnl_lock();
+
+ mutex_lock(&priv->slaves_mtx);
+ priv->running = MAC802154_DEVICE_RUN;
+ mutex_unlock(&priv->slaves_mtx);
+
+ rtnl_unlock();
+
+ return 0;
+
+out_wq:
+ destroy_workqueue(priv->dev_workqueue);
+out:
+ return rc;
+}
+EXPORT_SYMBOL(ieee802154_register_device);
+
+void ieee802154_unregister_device(struct ieee802154_dev *dev)
+{
+ struct mac802154_priv *priv = mac802154_to_priv(dev);
+ struct mac802154_sub_if_data *sdata, *next;
+
+ flush_workqueue(priv->dev_workqueue);
+ destroy_workqueue(priv->dev_workqueue);
+
+ rtnl_lock();
+
+ mutex_lock(&priv->slaves_mtx);
+ priv->running = MAC802154_DEVICE_STOPPED;
+ mutex_unlock(&priv->slaves_mtx);
+
+ list_for_each_entry_safe(sdata, next, &priv->slaves, list) {
+ mutex_lock(&sdata->hw->slaves_mtx);
+ list_del(&sdata->list);
+ mutex_unlock(&sdata->hw->slaves_mtx);
+
+ unregister_netdevice(sdata->dev);
+ }
+
+ rtnl_unlock();
+
+ wpan_phy_unregister(priv->phy);
+}
+EXPORT_SYMBOL(ieee802154_unregister_device);
+
+MODULE_DESCRIPTION("IEEE 802.15.4 implementation");
+MODULE_LICENSE("GPL v2");
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
deleted file mode 100644
index 9ae8930..0000000
--- a/net/mac802154/iface.c
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * Copyright 2007-2012 Siemens AG
- *
- * 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.
- *
- * Written by:
- * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
- * Sergey Lapin <slapin@ossfans.org>
- * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
- * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
- */
-
-#include <linux/netdevice.h>
-#include <linux/module.h>
-#include <linux/if_arp.h>
-#include <linux/ieee802154.h>
-
-#include <net/nl802154.h>
-#include <net/mac802154.h>
-#include <net/ieee802154_netdev.h>
-#include <net/cfg802154.h>
-
-#include "ieee802154_i.h"
-#include "driver-ops.h"
-
-static int mac802154_wpan_update_llsec(struct net_device *dev)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
- struct wpan_dev *wpan_dev = &sdata->wpan_dev;
- int rc = 0;
-
- if (ops->llsec) {
- struct ieee802154_llsec_params params;
- int changed = 0;
-
- params.pan_id = wpan_dev->pan_id;
- changed |= IEEE802154_LLSEC_PARAM_PAN_ID;
-
- params.hwaddr = wpan_dev->extended_addr;
- changed |= IEEE802154_LLSEC_PARAM_HWADDR;
-
- rc = ops->llsec->set_params(dev, ¶ms, changed);
- }
-
- return rc;
-}
-
-static int
-mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct wpan_dev *wpan_dev = &sdata->wpan_dev;
- struct sockaddr_ieee802154 *sa =
- (struct sockaddr_ieee802154 *)&ifr->ifr_addr;
- int err = -ENOIOCTLCMD;
-
- ASSERT_RTNL();
-
- spin_lock_bh(&sdata->mib_lock);
-
- switch (cmd) {
- case SIOCGIFADDR:
- {
- u16 pan_id, short_addr;
-
- pan_id = le16_to_cpu(wpan_dev->pan_id);
- short_addr = le16_to_cpu(wpan_dev->short_addr);
- if (pan_id == IEEE802154_PANID_BROADCAST ||
- short_addr == IEEE802154_ADDR_BROADCAST) {
- err = -EADDRNOTAVAIL;
- break;
- }
-
- sa->family = AF_IEEE802154;
- sa->addr.addr_type = IEEE802154_ADDR_SHORT;
- sa->addr.pan_id = pan_id;
- sa->addr.short_addr = short_addr;
-
- err = 0;
- break;
- }
- case SIOCSIFADDR:
- if (netif_running(dev)) {
- spin_unlock_bh(&sdata->mib_lock);
- return -EBUSY;
- }
-
- dev_warn(&dev->dev,
- "Using DEBUGing ioctl SIOCSIFADDR isn't recommended!\n");
- if (sa->family != AF_IEEE802154 ||
- sa->addr.addr_type != IEEE802154_ADDR_SHORT ||
- sa->addr.pan_id == IEEE802154_PANID_BROADCAST ||
- sa->addr.short_addr == IEEE802154_ADDR_BROADCAST ||
- sa->addr.short_addr == IEEE802154_ADDR_UNDEF) {
- err = -EINVAL;
- break;
- }
-
- wpan_dev->pan_id = cpu_to_le16(sa->addr.pan_id);
- wpan_dev->short_addr = cpu_to_le16(sa->addr.short_addr);
-
- err = mac802154_wpan_update_llsec(dev);
- break;
- }
-
- spin_unlock_bh(&sdata->mib_lock);
- return err;
-}
-
-static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct sockaddr *addr = p;
- __le64 extended_addr;
-
- if (netif_running(dev))
- return -EBUSY;
-
- ieee802154_be64_to_le64(&extended_addr, addr->sa_data);
- if (!ieee802154_is_valid_extended_addr(extended_addr))
- return -EINVAL;
-
- memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
- sdata->wpan_dev.extended_addr = extended_addr;
-
- return mac802154_wpan_update_llsec(dev);
-}
-
-static int mac802154_slave_open(struct net_device *dev)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct ieee802154_sub_if_data *subif;
- struct ieee802154_local *local = sdata->local;
- int res = 0;
-
- ASSERT_RTNL();
-
- if (sdata->vif.type == NL802154_IFTYPE_NODE) {
- mutex_lock(&sdata->local->iflist_mtx);
- list_for_each_entry(subif, &sdata->local->interfaces, list) {
- if (subif != sdata &&
- subif->vif.type == sdata->vif.type &&
- ieee802154_sdata_running(subif)) {
- mutex_unlock(&sdata->local->iflist_mtx);
- return -EBUSY;
- }
- }
- mutex_unlock(&sdata->local->iflist_mtx);
- }
-
- set_bit(SDATA_STATE_RUNNING, &sdata->state);
-
- if (!local->open_count) {
- res = drv_start(local);
- WARN_ON(res);
- if (res)
- goto err;
- }
-
- local->open_count++;
- netif_start_queue(dev);
- return 0;
-err:
- /* might already be clear but that doesn't matter */
- clear_bit(SDATA_STATE_RUNNING, &sdata->state);
-
- return res;
-}
-
-static int mac802154_wpan_open(struct net_device *dev)
-{
- int rc;
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct ieee802154_local *local = sdata->local;
- struct wpan_dev *wpan_dev = &sdata->wpan_dev;
- struct wpan_phy *phy = sdata->local->phy;
-
- rc = mac802154_slave_open(dev);
- if (rc < 0)
- return rc;
-
- mutex_lock(&phy->pib_lock);
-
- if (local->hw.flags & IEEE802154_HW_PROMISCUOUS) {
- rc = drv_set_promiscuous_mode(local,
- wpan_dev->promiscuous_mode);
- if (rc < 0)
- goto out;
- }
-
- if (local->hw.flags & IEEE802154_HW_AFILT) {
- rc = drv_set_pan_id(local, wpan_dev->pan_id);
- if (rc < 0)
- goto out;
-
- rc = drv_set_extended_addr(local, wpan_dev->extended_addr);
- if (rc < 0)
- goto out;
-
- rc = drv_set_short_addr(local, wpan_dev->short_addr);
- if (rc < 0)
- goto out;
- }
-
- if (local->hw.flags & IEEE802154_HW_LBT) {
- rc = drv_set_lbt_mode(local, wpan_dev->lbt);
- if (rc < 0)
- goto out;
- }
-
- if (local->hw.flags & IEEE802154_HW_CSMA_PARAMS) {
- rc = drv_set_csma_params(local, wpan_dev->min_be,
- wpan_dev->max_be,
- wpan_dev->csma_retries);
- if (rc < 0)
- goto out;
- }
-
- if (local->hw.flags & IEEE802154_HW_FRAME_RETRIES) {
- rc = drv_set_max_frame_retries(local, wpan_dev->frame_retries);
- if (rc < 0)
- goto out;
- }
-
- mutex_unlock(&phy->pib_lock);
- return 0;
-
-out:
- mutex_unlock(&phy->pib_lock);
- return rc;
-}
-
-static int mac802154_slave_close(struct net_device *dev)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct ieee802154_local *local = sdata->local;
-
- ASSERT_RTNL();
-
- hrtimer_cancel(&local->ifs_timer);
-
- netif_stop_queue(dev);
- local->open_count--;
-
- clear_bit(SDATA_STATE_RUNNING, &sdata->state);
-
- if (!local->open_count)
- drv_stop(local);
-
- return 0;
-}
-
-static int mac802154_set_header_security(struct ieee802154_sub_if_data *sdata,
- struct ieee802154_hdr *hdr,
- const struct ieee802154_mac_cb *cb)
-{
- struct ieee802154_llsec_params params;
- u8 level;
-
- mac802154_llsec_get_params(&sdata->sec, ¶ms);
-
- if (!params.enabled && cb->secen_override && cb->secen)
- return -EINVAL;
- if (!params.enabled ||
- (cb->secen_override && !cb->secen) ||
- !params.out_level)
- return 0;
- if (cb->seclevel_override && !cb->seclevel)
- return -EINVAL;
-
- level = cb->seclevel_override ? cb->seclevel : params.out_level;
-
- hdr->fc.security_enabled = 1;
- hdr->sec.level = level;
- hdr->sec.key_id_mode = params.out_key.mode;
- if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX)
- hdr->sec.short_src = params.out_key.short_source;
- else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX)
- hdr->sec.extended_src = params.out_key.extended_source;
- hdr->sec.key_id = params.out_key.id;
-
- return 0;
-}
-
-static int mac802154_header_create(struct sk_buff *skb,
- struct net_device *dev,
- unsigned short type,
- const void *daddr,
- const void *saddr,
- unsigned len)
-{
- struct ieee802154_hdr hdr;
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct wpan_dev *wpan_dev = &sdata->wpan_dev;
- struct ieee802154_mac_cb *cb = mac_cb(skb);
- int hlen;
-
- if (!daddr)
- return -EINVAL;
-
- memset(&hdr.fc, 0, sizeof(hdr.fc));
- hdr.fc.type = cb->type;
- hdr.fc.security_enabled = cb->secen;
- hdr.fc.ack_request = cb->ackreq;
- hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
-
- if (mac802154_set_header_security(sdata, &hdr, cb) < 0)
- return -EINVAL;
-
- if (!saddr) {
- spin_lock_bh(&sdata->mib_lock);
-
- if (wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) ||
- wpan_dev->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
- wpan_dev->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) {
- hdr.source.mode = IEEE802154_ADDR_LONG;
- hdr.source.extended_addr = wpan_dev->extended_addr;
- } else {
- hdr.source.mode = IEEE802154_ADDR_SHORT;
- hdr.source.short_addr = wpan_dev->short_addr;
- }
-
- hdr.source.pan_id = wpan_dev->pan_id;
-
- spin_unlock_bh(&sdata->mib_lock);
- } else {
- hdr.source = *(const struct ieee802154_addr *)saddr;
- }
-
- hdr.dest = *(const struct ieee802154_addr *)daddr;
-
- hlen = ieee802154_hdr_push(skb, &hdr);
- if (hlen < 0)
- return -EINVAL;
-
- skb_reset_mac_header(skb);
- skb->mac_len = hlen;
-
- if (len > ieee802154_max_payload(&hdr))
- return -EMSGSIZE;
-
- return hlen;
-}
-
-static int
-mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
-{
- struct ieee802154_hdr hdr;
- struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
-
- if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) {
- pr_debug("malformed packet\n");
- return 0;
- }
-
- *addr = hdr.source;
- return sizeof(*addr);
-}
-
-static struct header_ops mac802154_header_ops = {
- .create = mac802154_header_create,
- .parse = mac802154_header_parse,
-};
-
-static const struct net_device_ops mac802154_wpan_ops = {
- .ndo_open = mac802154_wpan_open,
- .ndo_stop = mac802154_slave_close,
- .ndo_start_xmit = ieee802154_subif_start_xmit,
- .ndo_do_ioctl = mac802154_wpan_ioctl,
- .ndo_set_mac_address = mac802154_wpan_mac_addr,
-};
-
-static const struct net_device_ops mac802154_monitor_ops = {
- .ndo_open = mac802154_wpan_open,
- .ndo_stop = mac802154_slave_close,
- .ndo_start_xmit = ieee802154_monitor_start_xmit,
-};
-
-static void mac802154_wpan_free(struct net_device *dev)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-
- mac802154_llsec_destroy(&sdata->sec);
-
- free_netdev(dev);
-}
-
-static void ieee802154_if_setup(struct net_device *dev)
-{
- dev->addr_len = IEEE802154_EXTENDED_ADDR_LEN;
- memset(dev->broadcast, 0xff, IEEE802154_EXTENDED_ADDR_LEN);
-
- dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN;
- dev->needed_tailroom = 2 + 16; /* FCS + MIC */
- dev->mtu = IEEE802154_MTU;
- dev->tx_queue_len = 300;
- dev->flags = IFF_NOARP | IFF_BROADCAST;
-}
-
-static int
-ieee802154_setup_sdata(struct ieee802154_sub_if_data *sdata,
- enum nl802154_iftype type)
-{
- struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-
- /* set some type-dependent values */
- sdata->vif.type = type;
- sdata->wpan_dev.iftype = type;
-
- get_random_bytes(&wpan_dev->bsn, 1);
- get_random_bytes(&wpan_dev->dsn, 1);
-
- /* defaults per 802.15.4-2011 */
- wpan_dev->min_be = 3;
- wpan_dev->max_be = 5;
- wpan_dev->csma_retries = 4;
- /* for compatibility, actual default is 3 */
- wpan_dev->frame_retries = -1;
-
- wpan_dev->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
- wpan_dev->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
-
- switch (type) {
- case NL802154_IFTYPE_NODE:
- ieee802154_be64_to_le64(&wpan_dev->extended_addr,
- sdata->dev->dev_addr);
-
- sdata->dev->header_ops = &mac802154_header_ops;
- sdata->dev->destructor = mac802154_wpan_free;
- sdata->dev->netdev_ops = &mac802154_wpan_ops;
- sdata->dev->ml_priv = &mac802154_mlme_wpan;
- wpan_dev->promiscuous_mode = false;
-
- spin_lock_init(&sdata->mib_lock);
- mutex_init(&sdata->sec_mtx);
-
- mac802154_llsec_init(&sdata->sec);
- break;
- case NL802154_IFTYPE_MONITOR:
- sdata->dev->destructor = free_netdev;
- sdata->dev->netdev_ops = &mac802154_monitor_ops;
- wpan_dev->promiscuous_mode = true;
- break;
- default:
- BUG();
- }
-
- return 0;
-}
-
-struct net_device *
-ieee802154_if_add(struct ieee802154_local *local, const char *name,
- enum nl802154_iftype type, __le64 extended_addr)
-{
- struct net_device *ndev = NULL;
- struct ieee802154_sub_if_data *sdata = NULL;
- int ret = -ENOMEM;
-
- ASSERT_RTNL();
-
- ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size, name,
- NET_NAME_UNKNOWN, ieee802154_if_setup);
- if (!ndev)
- return ERR_PTR(-ENOMEM);
-
- ndev->needed_headroom = local->hw.extra_tx_headroom;
-
- ret = dev_alloc_name(ndev, ndev->name);
- if (ret < 0)
- goto err;
-
- ieee802154_le64_to_be64(ndev->perm_addr,
- &local->hw.phy->perm_extended_addr);
- switch (type) {
- case NL802154_IFTYPE_NODE:
- ndev->type = ARPHRD_IEEE802154;
- if (ieee802154_is_valid_extended_addr(extended_addr))
- ieee802154_le64_to_be64(ndev->dev_addr, &extended_addr);
- else
- memcpy(ndev->dev_addr, ndev->perm_addr,
- IEEE802154_EXTENDED_ADDR_LEN);
- break;
- case NL802154_IFTYPE_MONITOR:
- ndev->type = ARPHRD_IEEE802154_MONITOR;
- break;
- default:
- ret = -EINVAL;
- goto err;
- }
-
- /* TODO check this */
- SET_NETDEV_DEV(ndev, &local->phy->dev);
- sdata = netdev_priv(ndev);
- ndev->ieee802154_ptr = &sdata->wpan_dev;
- memcpy(sdata->name, ndev->name, IFNAMSIZ);
- sdata->dev = ndev;
- sdata->wpan_dev.wpan_phy = local->hw.phy;
- sdata->local = local;
-
- /* setup type-dependent data */
- ret = ieee802154_setup_sdata(sdata, type);
- if (ret)
- goto err;
-
- ret = register_netdevice(ndev);
- if (ret < 0)
- goto err;
-
- mutex_lock(&local->iflist_mtx);
- list_add_tail_rcu(&sdata->list, &local->interfaces);
- mutex_unlock(&local->iflist_mtx);
-
- return ndev;
-
-err:
- free_netdev(ndev);
- return ERR_PTR(ret);
-}
-
-void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata)
-{
- ASSERT_RTNL();
-
- mutex_lock(&sdata->local->iflist_mtx);
- list_del_rcu(&sdata->list);
- mutex_unlock(&sdata->local->iflist_mtx);
-
- synchronize_rcu();
- unregister_netdevice(sdata->dev);
-}
-
-void ieee802154_remove_interfaces(struct ieee802154_local *local)
-{
- struct ieee802154_sub_if_data *sdata, *tmp;
-
- mutex_lock(&local->iflist_mtx);
- list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
- list_del(&sdata->list);
-
- unregister_netdevice(sdata->dev);
- }
- mutex_unlock(&local->iflist_mtx);
-}
-
-static int netdev_notify(struct notifier_block *nb,
- unsigned long state, void *ptr)
-{
- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
- struct ieee802154_sub_if_data *sdata;
-
- if (state != NETDEV_CHANGENAME)
- return NOTIFY_DONE;
-
- if (!dev->ieee802154_ptr || !dev->ieee802154_ptr->wpan_phy)
- return NOTIFY_DONE;
-
- if (dev->ieee802154_ptr->wpan_phy->privid != mac802154_wpan_phy_privid)
- return NOTIFY_DONE;
-
- sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- memcpy(sdata->name, dev->name, IFNAMSIZ);
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block mac802154_netdev_notifier = {
- .notifier_call = netdev_notify,
-};
-
-int ieee802154_iface_init(void)
-{
- return register_netdevice_notifier(&mac802154_netdev_notifier);
-}
-
-void ieee802154_iface_exit(void)
-{
- unregister_netdevice_notifier(&mac802154_netdev_notifier);
-}
diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c
index dcf7395..4570581 100644
--- a/net/mac802154/llsec.c
+++ b/net/mac802154/llsec.c
@@ -17,10 +17,10 @@
#include <linux/err.h>
#include <linux/bug.h>
#include <linux/completion.h>
-#include <linux/ieee802154.h>
+#include <net/ieee802154.h>
#include <crypto/algapi.h>
-#include "ieee802154_i.h"
+#include "mac802154.h"
#include "llsec.h"
static void llsec_key_put(struct mac802154_llsec_key *key);
@@ -75,6 +75,8 @@
}
}
+
+
int mac802154_llsec_get_params(struct mac802154_llsec *sec,
struct ieee802154_llsec_params *params)
{
@@ -115,6 +117,8 @@
return 0;
}
+
+
static struct mac802154_llsec_key*
llsec_key_alloc(const struct ieee802154_llsec_key *template)
{
@@ -290,6 +294,8 @@
return -ENOENT;
}
+
+
static bool llsec_dev_use_shortaddr(__le16 short_addr)
{
return short_addr != cpu_to_le16(IEEE802154_ADDR_UNDEF) &&
@@ -298,12 +304,12 @@
static u32 llsec_dev_hash_short(__le16 short_addr, __le16 pan_id)
{
- return ((__force u16)short_addr) << 16 | (__force u16)pan_id;
+ return ((__force u16) short_addr) << 16 | (__force u16) pan_id;
}
static u64 llsec_dev_hash_long(__le64 hwaddr)
{
- return (__force u64)hwaddr;
+ return (__force u64) hwaddr;
}
static struct mac802154_llsec_device*
@@ -405,6 +411,8 @@
return 0;
}
+
+
static struct mac802154_llsec_device_key*
llsec_devkey_find(struct mac802154_llsec_device *dev,
const struct ieee802154_llsec_key_id *key)
@@ -467,6 +475,8 @@
return 0;
}
+
+
static struct mac802154_llsec_seclevel*
llsec_find_seclevel(const struct mac802154_llsec *sec,
const struct ieee802154_llsec_seclevel *sl)
@@ -522,6 +532,8 @@
return 0;
}
+
+
static int llsec_recover_addr(struct mac802154_llsec *sec,
struct ieee802154_addr *addr)
{
@@ -597,6 +609,7 @@
return llsec_key_get(key);
}
+
static void llsec_geniv(u8 iv[16], __le64 addr,
const struct ieee802154_sechdr *sec)
{
@@ -773,6 +786,8 @@
return rc;
}
+
+
static struct mac802154_llsec_device*
llsec_lookup_dev(struct mac802154_llsec *sec,
const struct ieee802154_addr *addr)
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/mac802154.h
similarity index 63%
rename from net/mac802154/ieee802154_i.h
rename to net/mac802154/mac802154.h
index bebd70f..762a6f8 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/mac802154.h
@@ -10,28 +10,29 @@
* 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.
+ *
* Written by:
* Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
* Maxim Gorbachyov <maxim.gorbachev@siemens.com>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
*/
-#ifndef __IEEE802154_I_H
-#define __IEEE802154_I_H
+#ifndef MAC802154_H
+#define MAC802154_H
#include <linux/mutex.h>
-#include <linux/hrtimer.h>
-#include <net/cfg802154.h>
#include <net/mac802154.h>
-#include <net/nl802154.h>
#include <net/ieee802154_netdev.h>
#include "llsec.h"
/* mac802154 device private data */
-struct ieee802154_local {
- struct ieee802154_hw hw;
- const struct ieee802154_ops *ops;
+struct mac802154_priv {
+ struct ieee802154_dev hw;
+ struct ieee802154_ops *ops;
/* ieee802154 phy */
struct wpan_phy *phy;
@@ -45,29 +46,23 @@
*
* So atomic readers can use any of this protection methods.
*/
- struct list_head interfaces;
- struct mutex iflist_mtx;
+ struct list_head slaves;
+ struct mutex slaves_mtx;
/* This one is used for scanning and other jobs not to be interfered
* with serial driver.
*/
- struct workqueue_struct *workqueue;
+ struct workqueue_struct *dev_workqueue;
- struct hrtimer ifs_timer;
-
- bool started;
-
- struct tasklet_struct tasklet;
- struct sk_buff_head skb_queue;
+ /* SoftMAC device is registered and running. One can add subinterfaces.
+ * This flag should be modified under slaves_mtx and RTNL, so you can
+ * read them using any of protection methods.
+ */
+ bool running;
};
-enum {
- IEEE802154_RX_MSG = 1,
-};
-
-enum ieee802154_sdata_state_bits {
- SDATA_STATE_RUNNING,
-};
+#define MAC802154_DEVICE_STOPPED 0x00
+#define MAC802154_DEVICE_RUN 0x01
/* Slave interface definition.
*
@@ -75,74 +70,72 @@
* Each ieee802154 device/transceiver may have several slaves and able
* to be associated with several networks at the same time.
*/
-struct ieee802154_sub_if_data {
+struct mac802154_sub_if_data {
struct list_head list; /* the ieee802154_priv->slaves list */
- struct wpan_dev wpan_dev;
-
- struct ieee802154_local *local;
+ struct mac802154_priv *hw;
struct net_device *dev;
- unsigned long state;
- char name[IFNAMSIZ];
+ int type;
+ bool running;
spinlock_t mib_lock;
+ __le16 pan_id;
+ __le16 short_addr;
+ __le64 extended_addr;
+
+ u8 chan;
+ u8 page;
+
+ struct ieee802154_mac_params mac_params;
+
+ /* MAC BSN field */
+ u8 bsn;
+ /* MAC DSN field */
+ u8 dsn;
+
/* protects sec from concurrent access by netlink. access by
* encrypt/decrypt/header_create safe without additional protection.
*/
struct mutex sec_mtx;
struct mac802154_llsec sec;
- /* must be last, dynamically sized area in this! */
- struct ieee802154_vif vif;
};
+#define mac802154_to_priv(_hw) container_of(_hw, struct mac802154_priv, hw)
+
#define MAC802154_CHAN_NONE 0xff /* No channel is assigned */
-/* utility functions/constants */
-extern const void *const mac802154_wpan_phy_privid; /* for wpan_phy privid */
-
-static inline struct ieee802154_local *
-hw_to_local(struct ieee802154_hw *hw)
-{
- return container_of(hw, struct ieee802154_local, hw);
-}
-
-static inline struct ieee802154_sub_if_data *
-IEEE802154_DEV_TO_SUB_IF(const struct net_device *dev)
-{
- return netdev_priv(dev);
-}
-
-static inline struct ieee802154_sub_if_data *
-IEEE802154_WPAN_DEV_TO_SUB_IF(struct wpan_dev *wpan_dev)
-{
- return container_of(wpan_dev, struct ieee802154_sub_if_data, wpan_dev);
-}
-
-static inline bool
-ieee802154_sdata_running(struct ieee802154_sub_if_data *sdata)
-{
- return test_bit(SDATA_STATE_RUNNING, &sdata->state);
-}
-
+extern struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced;
extern struct ieee802154_mlme_ops mac802154_mlme_wpan;
-netdev_tx_t
-ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev);
-netdev_tx_t
-ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev);
-enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer);
+int mac802154_slave_open(struct net_device *dev);
+int mac802154_slave_close(struct net_device *dev);
+
+void mac802154_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb);
+void mac802154_monitor_setup(struct net_device *dev);
+
+void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb);
+void mac802154_wpan_setup(struct net_device *dev);
+
+netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
+ u8 page, u8 chan);
/* MIB callbacks */
void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val);
__le16 mac802154_dev_get_short_addr(const struct net_device *dev);
+void mac802154_dev_set_ieee_addr(struct net_device *dev);
__le16 mac802154_dev_get_pan_id(const struct net_device *dev);
void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val);
void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan);
u8 mac802154_dev_get_dsn(const struct net_device *dev);
+int mac802154_set_mac_params(struct net_device *dev,
+ const struct ieee802154_mac_params *params);
+void mac802154_get_mac_params(struct net_device *dev,
+ struct ieee802154_mac_params *params);
+
int mac802154_get_params(struct net_device *dev,
struct ieee802154_llsec_params *params);
int mac802154_set_params(struct net_device *dev,
@@ -176,13 +169,4 @@
struct ieee802154_llsec_table **t);
void mac802154_unlock_table(struct net_device *dev);
-/* interface handling */
-int ieee802154_iface_init(void);
-void ieee802154_iface_exit(void);
-void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata);
-struct net_device *
-ieee802154_if_add(struct ieee802154_local *local, const char *name,
- enum nl802154_iftype type, __le64 extended_addr);
-void ieee802154_remove_interfaces(struct ieee802154_local *local);
-
-#endif /* __IEEE802154_I_H */
+#endif /* MAC802154_H */
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c
index 6aacb18..bf80913 100644
--- a/net/mac802154/mac_cmd.c
+++ b/net/mac802154/mac_cmd.c
@@ -12,6 +12,10 @@
* 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.
+ *
* Written by:
* Sergey Lapin <slapin@ossfans.org>
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
@@ -20,14 +24,14 @@
#include <linux/skbuff.h>
#include <linux/if_arp.h>
-#include <linux/ieee802154.h>
+#include <net/ieee802154.h>
#include <net/ieee802154_netdev.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
#include <net/mac802154.h>
+#include <net/nl802154.h>
-#include "ieee802154_i.h"
-#include "driver-ops.h"
+#include "mac802154.h"
static int mac802154_mlme_start_req(struct net_device *dev,
struct ieee802154_addr *addr,
@@ -39,12 +43,11 @@
struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
int rc = 0;
- ASSERT_RTNL();
-
BUG_ON(addr->mode != IEEE802154_ADDR_SHORT);
mac802154_dev_set_pan_id(dev, addr->pan_id);
mac802154_dev_set_short_addr(dev, addr->short_addr);
+ mac802154_dev_set_ieee_addr(dev);
mac802154_dev_set_page_channel(dev, page, channel);
if (ops->llsec) {
@@ -66,71 +69,21 @@
rc = ops->llsec->set_params(dev, ¶ms, changed);
}
+ /* FIXME: add validation for unused parameters to be sane
+ * for SoftMAC
+ */
+ ieee802154_nl_start_confirm(dev, IEEE802154_SUCCESS);
+
return rc;
}
-static int mac802154_set_mac_params(struct net_device *dev,
- const struct ieee802154_mac_params *params)
+static struct wpan_phy *mac802154_get_phy(const struct net_device *dev)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct ieee802154_local *local = sdata->local;
- struct wpan_dev *wpan_dev = &sdata->wpan_dev;
- int ret;
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
- ASSERT_RTNL();
+ BUG_ON(dev->type != ARPHRD_IEEE802154);
- /* PHY */
- wpan_dev->wpan_phy->transmit_power = params->transmit_power;
- wpan_dev->wpan_phy->cca_mode = params->cca_mode;
- wpan_dev->wpan_phy->cca_ed_level = params->cca_ed_level;
-
- /* MAC */
- wpan_dev->min_be = params->min_be;
- wpan_dev->max_be = params->max_be;
- wpan_dev->csma_retries = params->csma_retries;
- wpan_dev->frame_retries = params->frame_retries;
- wpan_dev->lbt = params->lbt;
-
- if (local->hw.flags & IEEE802154_HW_TXPOWER) {
- ret = drv_set_tx_power(local, params->transmit_power);
- if (ret < 0)
- return ret;
- }
-
- if (local->hw.flags & IEEE802154_HW_CCA_MODE) {
- ret = drv_set_cca_mode(local, params->cca_mode);
- if (ret < 0)
- return ret;
- }
-
- if (local->hw.flags & IEEE802154_HW_CCA_ED_LEVEL) {
- ret = drv_set_cca_ed_level(local, params->cca_ed_level);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-static void mac802154_get_mac_params(struct net_device *dev,
- struct ieee802154_mac_params *params)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct wpan_dev *wpan_dev = &sdata->wpan_dev;
-
- ASSERT_RTNL();
-
- /* PHY */
- params->transmit_power = wpan_dev->wpan_phy->transmit_power;
- params->cca_mode = wpan_dev->wpan_phy->cca_mode;
- params->cca_ed_level = wpan_dev->wpan_phy->cca_ed_level;
-
- /* MAC */
- params->min_be = wpan_dev->min_be;
- params->max_be = wpan_dev->max_be;
- params->csma_retries = wpan_dev->csma_retries;
- params->frame_retries = wpan_dev->frame_retries;
- params->lbt = wpan_dev->lbt;
+ return to_phy(get_device(&priv->hw->phy->dev));
}
static struct ieee802154_llsec_ops mac802154_llsec_ops = {
@@ -149,7 +102,12 @@
.unlock_table = mac802154_unlock_table,
};
+struct ieee802154_reduced_mlme_ops mac802154_mlme_reduced = {
+ .get_phy = mac802154_get_phy,
+};
+
struct ieee802154_mlme_ops mac802154_mlme_wpan = {
+ .get_phy = mac802154_get_phy,
.start_req = mac802154_mlme_start_req,
.get_pan_id = mac802154_dev_get_pan_id,
.get_short_addr = mac802154_dev_get_short_addr,
diff --git a/net/mac802154/main.c b/net/mac802154/main.c
deleted file mode 100644
index 8500378..0000000
--- a/net/mac802154/main.c
+++ /dev/null
@@ -1,217 +0,0 @@
-/*
- * Copyright (C) 2007-2012 Siemens AG
- *
- * Written by:
- * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
- *
- * 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.
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/netdevice.h>
-
-#include <net/netlink.h>
-#include <net/nl802154.h>
-#include <net/mac802154.h>
-#include <net/ieee802154_netdev.h>
-#include <net/route.h>
-#include <net/cfg802154.h>
-
-#include "ieee802154_i.h"
-#include "cfg.h"
-
-static void ieee802154_tasklet_handler(unsigned long data)
-{
- struct ieee802154_local *local = (struct ieee802154_local *)data;
- struct sk_buff *skb;
-
- while ((skb = skb_dequeue(&local->skb_queue))) {
- switch (skb->pkt_type) {
- case IEEE802154_RX_MSG:
- /* Clear skb->pkt_type in order to not confuse kernel
- * netstack.
- */
- skb->pkt_type = 0;
- ieee802154_rx(&local->hw, skb);
- break;
- default:
- WARN(1, "mac802154: Packet is of unknown type %d\n",
- skb->pkt_type);
- kfree_skb(skb);
- break;
- }
- }
-}
-
-struct ieee802154_hw *
-ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops)
-{
- struct wpan_phy *phy;
- struct ieee802154_local *local;
- size_t priv_size;
-
- if (!ops || !(ops->xmit_async || ops->xmit_sync) || !ops->ed ||
- !ops->start || !ops->stop || !ops->set_channel) {
- pr_err("undefined IEEE802.15.4 device operations\n");
- return NULL;
- }
-
- /* Ensure 32-byte alignment of our private data and hw private data.
- * We use the wpan_phy priv data for both our ieee802154_local and for
- * the driver's private data
- *
- * in memory it'll be like this:
- *
- * +-------------------------+
- * | struct wpan_phy |
- * +-------------------------+
- * | struct ieee802154_local |
- * +-------------------------+
- * | driver's private data |
- * +-------------------------+
- *
- * Due to ieee802154 layer isn't aware of driver and MAC structures,
- * so lets align them here.
- */
-
- priv_size = ALIGN(sizeof(*local), NETDEV_ALIGN) + priv_data_len;
-
- phy = wpan_phy_new(&mac802154_config_ops, priv_size);
- if (!phy) {
- pr_err("failure to allocate master IEEE802.15.4 device\n");
- return NULL;
- }
-
- phy->privid = mac802154_wpan_phy_privid;
-
- local = wpan_phy_priv(phy);
- local->phy = phy;
- local->hw.phy = local->phy;
- local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN);
- local->ops = ops;
-
- INIT_LIST_HEAD(&local->interfaces);
- mutex_init(&local->iflist_mtx);
-
- tasklet_init(&local->tasklet,
- ieee802154_tasklet_handler,
- (unsigned long)local);
-
- skb_queue_head_init(&local->skb_queue);
-
- return &local->hw;
-}
-EXPORT_SYMBOL(ieee802154_alloc_hw);
-
-void ieee802154_free_hw(struct ieee802154_hw *hw)
-{
- struct ieee802154_local *local = hw_to_local(hw);
-
- BUG_ON(!list_empty(&local->interfaces));
-
- mutex_destroy(&local->iflist_mtx);
-
- wpan_phy_free(local->phy);
-}
-EXPORT_SYMBOL(ieee802154_free_hw);
-
-static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy)
-{
- /* TODO warn on empty symbol_duration
- * Should be done when all drivers sets this value.
- */
-
- wpan_phy->lifs_period = IEEE802154_LIFS_PERIOD *
- wpan_phy->symbol_duration;
- wpan_phy->sifs_period = IEEE802154_SIFS_PERIOD *
- wpan_phy->symbol_duration;
-}
-
-int ieee802154_register_hw(struct ieee802154_hw *hw)
-{
- struct ieee802154_local *local = hw_to_local(hw);
- struct net_device *dev;
- int rc = -ENOSYS;
-
- local->workqueue =
- create_singlethread_workqueue(wpan_phy_name(local->phy));
- if (!local->workqueue) {
- rc = -ENOMEM;
- goto out;
- }
-
- hrtimer_init(&local->ifs_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- local->ifs_timer.function = ieee802154_xmit_ifs_timer;
-
- wpan_phy_set_dev(local->phy, local->hw.parent);
-
- ieee802154_setup_wpan_phy_pib(local->phy);
-
- rc = wpan_phy_register(local->phy);
- if (rc < 0)
- goto out_wq;
-
- rtnl_lock();
-
- dev = ieee802154_if_add(local, "wpan%d", NL802154_IFTYPE_NODE,
- cpu_to_le64(0x0000000000000000ULL));
- if (IS_ERR(dev)) {
- rtnl_unlock();
- rc = PTR_ERR(dev);
- goto out_wq;
- }
-
- rtnl_unlock();
-
- return 0;
-
-out_wq:
- destroy_workqueue(local->workqueue);
-out:
- return rc;
-}
-EXPORT_SYMBOL(ieee802154_register_hw);
-
-void ieee802154_unregister_hw(struct ieee802154_hw *hw)
-{
- struct ieee802154_local *local = hw_to_local(hw);
-
- tasklet_kill(&local->tasklet);
- flush_workqueue(local->workqueue);
- destroy_workqueue(local->workqueue);
-
- rtnl_lock();
-
- ieee802154_remove_interfaces(local);
-
- rtnl_unlock();
-
- wpan_phy_unregister(local->phy);
-}
-EXPORT_SYMBOL(ieee802154_unregister_hw);
-
-static int __init ieee802154_init(void)
-{
- return ieee802154_iface_init();
-}
-
-static void __exit ieee802154_exit(void)
-{
- ieee802154_iface_exit();
-
- rcu_barrier();
-}
-
-subsys_initcall(ieee802154_init);
-module_exit(ieee802154_exit);
-
-MODULE_DESCRIPTION("IEEE 802.15.4 subsystem");
-MODULE_LICENSE("GPL v2");
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c
index 5cf019a..868a040 100644
--- a/net/mac802154/mib.c
+++ b/net/mac802154/mib.c
@@ -10,6 +10,10 @@
* 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.
+ *
* Written by:
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Sergey Lapin <slapin@ossfans.org>
@@ -21,100 +25,208 @@
#include <net/mac802154.h>
#include <net/ieee802154_netdev.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
-#include "ieee802154_i.h"
-#include "driver-ops.h"
+#include "mac802154.h"
-void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
+struct phy_chan_notify_work {
+ struct work_struct work;
+ struct net_device *dev;
+};
+
+struct hw_addr_filt_notify_work {
+ struct work_struct work;
+ struct net_device *dev;
+ unsigned long changed;
+};
+
+static struct mac802154_priv *mac802154_slave_get_priv(struct net_device *dev)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
BUG_ON(dev->type != ARPHRD_IEEE802154);
- spin_lock_bh(&sdata->mib_lock);
- sdata->wpan_dev.short_addr = val;
- spin_unlock_bh(&sdata->mib_lock);
+ return priv->hw;
+}
+
+static void hw_addr_notify(struct work_struct *work)
+{
+ struct hw_addr_filt_notify_work *nw = container_of(work,
+ struct hw_addr_filt_notify_work, work);
+ struct mac802154_priv *hw = mac802154_slave_get_priv(nw->dev);
+ int res;
+
+ res = hw->ops->set_hw_addr_filt(&hw->hw,
+ &hw->hw.hw_filt,
+ nw->changed);
+ if (res)
+ pr_debug("failed changed mask %lx\n", nw->changed);
+
+ kfree(nw);
+}
+
+static void set_hw_addr_filt(struct net_device *dev, unsigned long changed)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct hw_addr_filt_notify_work *work;
+
+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
+ if (!work)
+ return;
+
+ INIT_WORK(&work->work, hw_addr_notify);
+ work->dev = dev;
+ work->changed = changed;
+ queue_work(priv->hw->dev_workqueue, &work->work);
+}
+
+void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+ BUG_ON(dev->type != ARPHRD_IEEE802154);
+
+ spin_lock_bh(&priv->mib_lock);
+ priv->short_addr = val;
+ spin_unlock_bh(&priv->mib_lock);
+
+ if ((priv->hw->ops->set_hw_addr_filt) &&
+ (priv->hw->hw.hw_filt.short_addr != priv->short_addr)) {
+ priv->hw->hw.hw_filt.short_addr = priv->short_addr;
+ set_hw_addr_filt(dev, IEEE802515_AFILT_SADDR_CHANGED);
+ }
}
__le16 mac802154_dev_get_short_addr(const struct net_device *dev)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
__le16 ret;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- spin_lock_bh(&sdata->mib_lock);
- ret = sdata->wpan_dev.short_addr;
- spin_unlock_bh(&sdata->mib_lock);
+ spin_lock_bh(&priv->mib_lock);
+ ret = priv->short_addr;
+ spin_unlock_bh(&priv->mib_lock);
return ret;
}
+void mac802154_dev_set_ieee_addr(struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct mac802154_priv *mac = priv->hw;
+
+ priv->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
+
+ if (mac->ops->set_hw_addr_filt &&
+ mac->hw.hw_filt.ieee_addr != priv->extended_addr) {
+ mac->hw.hw_filt.ieee_addr = priv->extended_addr;
+ set_hw_addr_filt(dev, IEEE802515_AFILT_IEEEADDR_CHANGED);
+ }
+}
+
__le16 mac802154_dev_get_pan_id(const struct net_device *dev)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
__le16 ret;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- spin_lock_bh(&sdata->mib_lock);
- ret = sdata->wpan_dev.pan_id;
- spin_unlock_bh(&sdata->mib_lock);
+ spin_lock_bh(&priv->mib_lock);
+ ret = priv->pan_id;
+ spin_unlock_bh(&priv->mib_lock);
return ret;
}
void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
BUG_ON(dev->type != ARPHRD_IEEE802154);
- spin_lock_bh(&sdata->mib_lock);
- sdata->wpan_dev.pan_id = val;
- spin_unlock_bh(&sdata->mib_lock);
+ spin_lock_bh(&priv->mib_lock);
+ priv->pan_id = val;
+ spin_unlock_bh(&priv->mib_lock);
+
+ if ((priv->hw->ops->set_hw_addr_filt) &&
+ (priv->hw->hw.hw_filt.pan_id != priv->pan_id)) {
+ priv->hw->hw.hw_filt.pan_id = priv->pan_id;
+ set_hw_addr_filt(dev, IEEE802515_AFILT_PANID_CHANGED);
+ }
}
u8 mac802154_dev_get_dsn(const struct net_device *dev)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
BUG_ON(dev->type != ARPHRD_IEEE802154);
- return sdata->wpan_dev.dsn++;
+ return priv->dsn++;
+}
+
+static void phy_chan_notify(struct work_struct *work)
+{
+ struct phy_chan_notify_work *nw = container_of(work,
+ struct phy_chan_notify_work, work);
+ struct mac802154_priv *hw = mac802154_slave_get_priv(nw->dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(nw->dev);
+ int res;
+
+ mutex_lock(&priv->hw->phy->pib_lock);
+ res = hw->ops->set_channel(&hw->hw, priv->page, priv->chan);
+ if (res) {
+ pr_debug("set_channel failed\n");
+ } else {
+ priv->hw->phy->current_channel = priv->chan;
+ priv->hw->phy->current_page = priv->page;
+ }
+ mutex_unlock(&priv->hw->phy->pib_lock);
+
+ kfree(nw);
}
void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- struct ieee802154_local *local = sdata->local;
- int res;
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct phy_chan_notify_work *work;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- res = drv_set_channel(local, page, chan);
- if (res) {
- pr_debug("set_channel failed\n");
+ spin_lock_bh(&priv->mib_lock);
+ priv->page = page;
+ priv->chan = chan;
+ spin_unlock_bh(&priv->mib_lock);
+
+ mutex_lock(&priv->hw->phy->pib_lock);
+ if (priv->hw->phy->current_channel != priv->chan ||
+ priv->hw->phy->current_page != priv->page) {
+ mutex_unlock(&priv->hw->phy->pib_lock);
+
+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
+ if (!work)
+ return;
+
+ INIT_WORK(&work->work, phy_chan_notify);
+ work->dev = dev;
+ queue_work(priv->hw->dev_workqueue, &work->work);
} else {
- mutex_lock(&local->phy->pib_lock);
- local->phy->current_channel = chan;
- local->phy->current_page = page;
- mutex_unlock(&local->phy->pib_lock);
+ mutex_unlock(&priv->hw->phy->pib_lock);
}
}
+
int mac802154_get_params(struct net_device *dev,
struct ieee802154_llsec_params *params)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_get_params(&sdata->sec, params);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_get_params(&priv->sec, params);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
@@ -123,30 +235,31 @@
const struct ieee802154_llsec_params *params,
int changed)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_set_params(&sdata->sec, params, changed);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_set_params(&priv->sec, params, changed);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
+
int mac802154_add_key(struct net_device *dev,
const struct ieee802154_llsec_key_id *id,
const struct ieee802154_llsec_key *key)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_key_add(&sdata->sec, id, key);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_key_add(&priv->sec, id, key);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
@@ -154,59 +267,61 @@
int mac802154_del_key(struct net_device *dev,
const struct ieee802154_llsec_key_id *id)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_key_del(&sdata->sec, id);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_key_del(&priv->sec, id);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
+
int mac802154_add_dev(struct net_device *dev,
const struct ieee802154_llsec_device *llsec_dev)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_dev_add(&sdata->sec, llsec_dev);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_dev_add(&priv->sec, llsec_dev);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
int mac802154_del_dev(struct net_device *dev, __le64 dev_addr)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_dev_del(&sdata->sec, dev_addr);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_dev_del(&priv->sec, dev_addr);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
+
int mac802154_add_devkey(struct net_device *dev,
__le64 device_addr,
const struct ieee802154_llsec_device_key *key)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_devkey_add(&sdata->sec, device_addr, key);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_devkey_add(&priv->sec, device_addr, key);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
@@ -215,29 +330,30 @@
__le64 device_addr,
const struct ieee802154_llsec_device_key *key)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_devkey_del(&sdata->sec, device_addr, key);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_devkey_del(&priv->sec, device_addr, key);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
+
int mac802154_add_seclevel(struct net_device *dev,
const struct ieee802154_llsec_seclevel *sl)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_seclevel_add(&sdata->sec, sl);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_seclevel_add(&priv->sec, sl);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
@@ -245,42 +361,43 @@
int mac802154_del_seclevel(struct net_device *dev,
const struct ieee802154_llsec_seclevel *sl)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
int res;
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
- res = mac802154_llsec_seclevel_del(&sdata->sec, sl);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
+ res = mac802154_llsec_seclevel_del(&priv->sec, sl);
+ mutex_unlock(&priv->sec_mtx);
return res;
}
+
void mac802154_lock_table(struct net_device *dev)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_lock(&sdata->sec_mtx);
+ mutex_lock(&priv->sec_mtx);
}
void mac802154_get_table(struct net_device *dev,
struct ieee802154_llsec_table **t)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
BUG_ON(dev->type != ARPHRD_IEEE802154);
- *t = &sdata->sec.table;
+ *t = &priv->sec.table;
}
void mac802154_unlock_table(struct net_device *dev)
{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
BUG_ON(dev->type != ARPHRD_IEEE802154);
- mutex_unlock(&sdata->sec_mtx);
+ mutex_unlock(&priv->sec_mtx);
}
diff --git a/net/mac802154/monitor.c b/net/mac802154/monitor.c
new file mode 100644
index 0000000..a68230e
--- /dev/null
+++ b/net/mac802154/monitor.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2007, 2008, 2009 Siemens AG
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ * Sergey Lapin <slapin@ossfans.org>
+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
+ * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/crc-ccitt.h>
+
+#include <net/ieee802154.h>
+#include <net/mac802154.h>
+#include <net/netlink.h>
+#include <net/wpan-phy.h>
+#include <linux/nl802154.h>
+
+#include "mac802154.h"
+
+static netdev_tx_t mac802154_monitor_xmit(struct sk_buff *skb,
+ struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv;
+ u8 chan, page;
+
+ priv = netdev_priv(dev);
+
+ /* FIXME: locking */
+ chan = priv->hw->phy->current_channel;
+ page = priv->hw->phy->current_page;
+
+ if (chan == MAC802154_CHAN_NONE) /* not initialized */
+ return NETDEV_TX_OK;
+
+ if (WARN_ON(page >= WPAN_NUM_PAGES) ||
+ WARN_ON(chan >= WPAN_NUM_CHANNELS))
+ return NETDEV_TX_OK;
+
+ skb->skb_iif = dev->ifindex;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
+ return mac802154_tx(priv->hw, skb, page, chan);
+}
+
+
+void mac802154_monitors_rx(struct mac802154_priv *priv, struct sk_buff *skb)
+{
+ struct sk_buff *skb2;
+ struct mac802154_sub_if_data *sdata;
+ u16 crc = crc_ccitt(0, skb->data, skb->len);
+ u8 *data;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &priv->slaves, list) {
+ if (sdata->type != IEEE802154_DEV_MONITOR ||
+ !netif_running(sdata->dev))
+ continue;
+
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ skb2->dev = sdata->dev;
+ skb2->pkt_type = PACKET_HOST;
+ data = skb_put(skb2, 2);
+ data[0] = crc & 0xff;
+ data[1] = crc >> 8;
+
+ netif_rx_ni(skb2);
+ }
+ rcu_read_unlock();
+}
+
+static const struct net_device_ops mac802154_monitor_ops = {
+ .ndo_open = mac802154_slave_open,
+ .ndo_stop = mac802154_slave_close,
+ .ndo_start_xmit = mac802154_monitor_xmit,
+};
+
+void mac802154_monitor_setup(struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv;
+
+ dev->addr_len = 0;
+ dev->hard_header_len = 0;
+ dev->needed_tailroom = 2; /* room for FCS */
+ dev->mtu = IEEE802154_MTU;
+ dev->tx_queue_len = 10;
+ dev->type = ARPHRD_IEEE802154_MONITOR;
+ dev->flags = IFF_NOARP | IFF_BROADCAST;
+ dev->watchdog_timeo = 0;
+
+ dev->destructor = free_netdev;
+ dev->netdev_ops = &mac802154_monitor_ops;
+ dev->ml_priv = &mac802154_mlme_reduced;
+
+ priv = netdev_priv(dev);
+ priv->type = IEEE802154_DEV_MONITOR;
+
+ priv->chan = MAC802154_CHAN_NONE; /* not initialized */
+ priv->page = 0;
+}
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c
index c0d67b2..a14cf9e 100644
--- a/net/mac802154/rx.c
+++ b/net/mac802154/rx.c
@@ -10,6 +10,10 @@
* 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.
+ *
* Written by:
* Pavel Smolenskiy <pavel.smolenskiy@gmail.com>
* Maxim Gorbachyov <maxim.gorbachev@siemens.com>
@@ -19,284 +23,92 @@
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/workqueue.h>
#include <linux/netdevice.h>
#include <linux/crc-ccitt.h>
-#include <asm/unaligned.h>
#include <net/mac802154.h>
#include <net/ieee802154_netdev.h>
-#include <net/nl802154.h>
-#include "ieee802154_i.h"
+#include "mac802154.h"
-static int ieee802154_deliver_skb(struct sk_buff *skb)
+/* The IEEE 802.15.4 standard defines 4 MAC packet types:
+ * - beacon frame
+ * - MAC command frame
+ * - acknowledgement frame
+ * - data frame
+ *
+ * and only the data frame should be pushed to the upper layers, other types
+ * are just internal MAC layer management information. So only data packets
+ * are going to be sent to the networking queue, all other will be processed
+ * right here by using the device workqueue.
+ */
+struct rx_work {
+ struct sk_buff *skb;
+ struct work_struct work;
+ struct ieee802154_dev *dev;
+ u8 lqi;
+};
+
+static void
+mac802154_subif_rx(struct ieee802154_dev *hw, struct sk_buff *skb, u8 lqi)
{
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ struct mac802154_priv *priv = mac802154_to_priv(hw);
+
+ mac_cb(skb)->lqi = lqi;
skb->protocol = htons(ETH_P_IEEE802154);
+ skb_reset_mac_header(skb);
- return netif_receive_skb(skb);
-}
+ if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
+ u16 crc;
-static int
-ieee802154_subif_frame(struct ieee802154_sub_if_data *sdata,
- struct sk_buff *skb, const struct ieee802154_hdr *hdr)
-{
- struct wpan_dev *wpan_dev = &sdata->wpan_dev;
- __le16 span, sshort;
- int rc;
-
- pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
-
- spin_lock_bh(&sdata->mib_lock);
-
- span = wpan_dev->pan_id;
- sshort = wpan_dev->short_addr;
-
- switch (mac_cb(skb)->dest.mode) {
- case IEEE802154_ADDR_NONE:
- if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
- /* FIXME: check if we are PAN coordinator */
- skb->pkt_type = PACKET_OTHERHOST;
- else
- /* ACK comes with both addresses empty */
- skb->pkt_type = PACKET_HOST;
- break;
- case IEEE802154_ADDR_LONG:
- if (mac_cb(skb)->dest.pan_id != span &&
- mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
- skb->pkt_type = PACKET_OTHERHOST;
- else if (mac_cb(skb)->dest.extended_addr == wpan_dev->extended_addr)
- skb->pkt_type = PACKET_HOST;
- else
- skb->pkt_type = PACKET_OTHERHOST;
- break;
- case IEEE802154_ADDR_SHORT:
- if (mac_cb(skb)->dest.pan_id != span &&
- mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
- skb->pkt_type = PACKET_OTHERHOST;
- else if (mac_cb(skb)->dest.short_addr == sshort)
- skb->pkt_type = PACKET_HOST;
- else if (mac_cb(skb)->dest.short_addr ==
- cpu_to_le16(IEEE802154_ADDR_BROADCAST))
- skb->pkt_type = PACKET_BROADCAST;
- else
- skb->pkt_type = PACKET_OTHERHOST;
- break;
- default:
- spin_unlock_bh(&sdata->mib_lock);
- pr_debug("invalid dest mode\n");
- goto fail;
+ if (skb->len < 2) {
+ pr_debug("got invalid frame\n");
+ goto fail;
+ }
+ crc = crc_ccitt(0, skb->data, skb->len);
+ if (crc) {
+ pr_debug("CRC mismatch\n");
+ goto fail;
+ }
+ skb_trim(skb, skb->len - 2); /* CRC */
}
- spin_unlock_bh(&sdata->mib_lock);
+ mac802154_monitors_rx(priv, skb);
+ mac802154_wpans_rx(priv, skb);
- skb->dev = sdata->dev;
-
- rc = mac802154_llsec_decrypt(&sdata->sec, skb);
- if (rc) {
- pr_debug("decryption failed: %i\n", rc);
- goto fail;
- }
-
- sdata->dev->stats.rx_packets++;
- sdata->dev->stats.rx_bytes += skb->len;
-
- switch (mac_cb(skb)->type) {
- case IEEE802154_FC_TYPE_DATA:
- return ieee802154_deliver_skb(skb);
- default:
- pr_warn("ieee802154: bad frame received (type = %d)\n",
- mac_cb(skb)->type);
- goto fail;
- }
+ return;
fail:
kfree_skb(skb);
- return NET_RX_DROP;
}
-static void
-ieee802154_print_addr(const char *name, const struct ieee802154_addr *addr)
+static void mac802154_rx_worker(struct work_struct *work)
{
- if (addr->mode == IEEE802154_ADDR_NONE)
- pr_debug("%s not present\n", name);
+ struct rx_work *rw = container_of(work, struct rx_work, work);
- pr_debug("%s PAN ID: %04x\n", name, le16_to_cpu(addr->pan_id));
- if (addr->mode == IEEE802154_ADDR_SHORT) {
- pr_debug("%s is short: %04x\n", name,
- le16_to_cpu(addr->short_addr));
- } else {
- u64 hw = swab64((__force u64)addr->extended_addr);
-
- pr_debug("%s is hardware: %8phC\n", name, &hw);
- }
+ mac802154_subif_rx(rw->dev, rw->skb, rw->lqi);
+ kfree(rw);
}
-static int
-ieee802154_parse_frame_start(struct sk_buff *skb, struct ieee802154_hdr *hdr)
-{
- int hlen;
- struct ieee802154_mac_cb *cb = mac_cb_init(skb);
-
- skb_reset_mac_header(skb);
-
- hlen = ieee802154_hdr_pull(skb, hdr);
- if (hlen < 0)
- return -EINVAL;
-
- skb->mac_len = hlen;
-
- pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc),
- hdr->seq);
-
- cb->type = hdr->fc.type;
- cb->ackreq = hdr->fc.ack_request;
- cb->secen = hdr->fc.security_enabled;
-
- ieee802154_print_addr("destination", &hdr->dest);
- ieee802154_print_addr("source", &hdr->source);
-
- cb->source = hdr->source;
- cb->dest = hdr->dest;
-
- if (hdr->fc.security_enabled) {
- u64 key;
-
- pr_debug("seclevel %i\n", hdr->sec.level);
-
- switch (hdr->sec.key_id_mode) {
- case IEEE802154_SCF_KEY_IMPLICIT:
- pr_debug("implicit key\n");
- break;
-
- case IEEE802154_SCF_KEY_INDEX:
- pr_debug("key %02x\n", hdr->sec.key_id);
- break;
-
- case IEEE802154_SCF_KEY_SHORT_INDEX:
- pr_debug("key %04x:%04x %02x\n",
- le32_to_cpu(hdr->sec.short_src) >> 16,
- le32_to_cpu(hdr->sec.short_src) & 0xffff,
- hdr->sec.key_id);
- break;
-
- case IEEE802154_SCF_KEY_HW_INDEX:
- key = swab64((__force u64)hdr->sec.extended_src);
- pr_debug("key source %8phC %02x\n", &key,
- hdr->sec.key_id);
- break;
- }
- }
-
- return 0;
-}
-
-static void
-__ieee802154_rx_handle_packet(struct ieee802154_local *local,
- struct sk_buff *skb)
-{
- int ret;
- struct ieee802154_sub_if_data *sdata;
- struct ieee802154_hdr hdr;
-
- ret = ieee802154_parse_frame_start(skb, &hdr);
- if (ret) {
- pr_debug("got invalid frame\n");
- kfree_skb(skb);
- return;
- }
-
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (sdata->vif.type != NL802154_IFTYPE_NODE ||
- !netif_running(sdata->dev))
- continue;
-
- ieee802154_subif_frame(sdata, skb, &hdr);
- skb = NULL;
- break;
- }
-
- if (skb)
- kfree_skb(skb);
-}
-
-static void
-ieee802154_monitors_rx(struct ieee802154_local *local, struct sk_buff *skb)
-{
- struct sk_buff *skb2;
- struct ieee802154_sub_if_data *sdata;
-
- skb_reset_mac_header(skb);
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- skb->pkt_type = PACKET_OTHERHOST;
- skb->protocol = htons(ETH_P_IEEE802154);
-
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (sdata->vif.type != NL802154_IFTYPE_MONITOR)
- continue;
-
- if (!ieee802154_sdata_running(sdata))
- continue;
-
- skb2 = skb_clone(skb, GFP_ATOMIC);
- if (skb2) {
- skb2->dev = sdata->dev;
- ieee802154_deliver_skb(skb2);
-
- sdata->dev->stats.rx_packets++;
- sdata->dev->stats.rx_bytes += skb->len;
- }
- }
-}
-
-void ieee802154_rx(struct ieee802154_hw *hw, struct sk_buff *skb)
-{
- struct ieee802154_local *local = hw_to_local(hw);
- u16 crc;
-
- WARN_ON_ONCE(softirq_count() == 0);
-
- /* TODO: When a transceiver omits the checksum here, we
- * add an own calculated one. This is currently an ugly
- * solution because the monitor needs a crc here.
- */
- if (local->hw.flags & IEEE802154_HW_RX_OMIT_CKSUM) {
- crc = crc_ccitt(0, skb->data, skb->len);
- put_unaligned_le16(crc, skb_put(skb, 2));
- }
-
- rcu_read_lock();
-
- ieee802154_monitors_rx(local, skb);
-
- /* Check if transceiver doesn't validate the checksum.
- * If not we validate the checksum here.
- */
- if (local->hw.flags & IEEE802154_HW_RX_DROP_BAD_CKSUM) {
- crc = crc_ccitt(0, skb->data, skb->len);
- if (crc) {
- rcu_read_unlock();
- kfree_skb(skb);
- return;
- }
- }
- /* remove crc */
- skb_trim(skb, skb->len - 2);
-
- __ieee802154_rx_handle_packet(local, skb);
-
- rcu_read_unlock();
-}
-EXPORT_SYMBOL(ieee802154_rx);
-
void
-ieee802154_rx_irqsafe(struct ieee802154_hw *hw, struct sk_buff *skb, u8 lqi)
+ieee802154_rx_irqsafe(struct ieee802154_dev *dev, struct sk_buff *skb, u8 lqi)
{
- struct ieee802154_local *local = hw_to_local(hw);
+ struct mac802154_priv *priv = mac802154_to_priv(dev);
+ struct rx_work *work;
- mac_cb(skb)->lqi = lqi;
- skb->pkt_type = IEEE802154_RX_MSG;
- skb_queue_tail(&local->skb_queue, skb);
- tasklet_schedule(&local->tasklet);
+ if (!skb)
+ return;
+
+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
+ if (!work)
+ return;
+
+ INIT_WORK(&work->work, mac802154_rx_worker);
+ work->skb = skb;
+ work->dev = dev;
+ work->lqi = lqi;
+
+ queue_work(priv->dev_workqueue, &work->work);
}
EXPORT_SYMBOL(ieee802154_rx_irqsafe);
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index c62e956..fdf4c0e 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -10,6 +10,10 @@
* 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.
+ *
* Written by:
* Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
* Sergey Lapin <slapin@ossfans.org>
@@ -20,130 +24,110 @@
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <linux/crc-ccitt.h>
-#include <asm/unaligned.h>
-#include <net/rtnetlink.h>
#include <net/ieee802154_netdev.h>
#include <net/mac802154.h>
-#include <net/cfg802154.h>
+#include <net/wpan-phy.h>
-#include "ieee802154_i.h"
-#include "driver-ops.h"
+#include "mac802154.h"
/* IEEE 802.15.4 transceivers can sleep during the xmit session, so process
* packets through the workqueue.
*/
-struct ieee802154_xmit_cb {
+struct xmit_work {
struct sk_buff *skb;
struct work_struct work;
- struct ieee802154_local *local;
+ struct mac802154_priv *priv;
+ u8 chan;
+ u8 page;
};
-static struct ieee802154_xmit_cb ieee802154_xmit_cb;
-
-static void ieee802154_xmit_worker(struct work_struct *work)
+static void mac802154_xmit_worker(struct work_struct *work)
{
- struct ieee802154_xmit_cb *cb =
- container_of(work, struct ieee802154_xmit_cb, work);
- struct ieee802154_local *local = cb->local;
- struct sk_buff *skb = cb->skb;
- struct net_device *dev = skb->dev;
+ struct xmit_work *xw = container_of(work, struct xmit_work, work);
+ struct mac802154_sub_if_data *sdata;
int res;
- rtnl_lock();
-
- /* check if ifdown occurred while schedule */
- if (!netif_running(dev))
- goto err_tx;
-
- res = drv_xmit_sync(local, skb);
- if (res)
- goto err_tx;
-
- ieee802154_xmit_complete(&local->hw, skb, false);
-
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
-
- rtnl_unlock();
-
- return;
-
-err_tx:
- /* Restart the netif queue on each sub_if_data object. */
- ieee802154_wake_queue(&local->hw);
- rtnl_unlock();
- kfree_skb(skb);
- netdev_dbg(dev, "transmission failed\n");
-}
-
-static netdev_tx_t
-ieee802154_tx(struct ieee802154_local *local, struct sk_buff *skb)
-{
- struct net_device *dev = skb->dev;
- int ret;
-
- if (!(local->hw.flags & IEEE802154_HW_TX_OMIT_CKSUM)) {
- u16 crc = crc_ccitt(0, skb->data, skb->len);
-
- put_unaligned_le16(crc, skb_put(skb, 2));
- }
-
- if (skb_cow_head(skb, local->hw.extra_tx_headroom))
- goto err_tx;
-
- /* Stop the netif queue on each sub_if_data object. */
- ieee802154_stop_queue(&local->hw);
-
- /* async is priority, otherwise sync is fallback */
- if (local->ops->xmit_async) {
- ret = drv_xmit_async(local, skb);
- if (ret) {
- ieee802154_wake_queue(&local->hw);
- goto err_tx;
+ mutex_lock(&xw->priv->phy->pib_lock);
+ if (xw->priv->phy->current_channel != xw->chan ||
+ xw->priv->phy->current_page != xw->page) {
+ res = xw->priv->ops->set_channel(&xw->priv->hw,
+ xw->page,
+ xw->chan);
+ if (res) {
+ pr_debug("set_channel failed\n");
+ goto out;
}
- dev->stats.tx_packets++;
- dev->stats.tx_bytes += skb->len;
- } else {
- INIT_WORK(&ieee802154_xmit_cb.work, ieee802154_xmit_worker);
- ieee802154_xmit_cb.skb = skb;
- ieee802154_xmit_cb.local = local;
-
- queue_work(local->workqueue, &ieee802154_xmit_cb.work);
+ xw->priv->phy->current_channel = xw->chan;
+ xw->priv->phy->current_page = xw->page;
}
+ res = xw->priv->ops->xmit(&xw->priv->hw, xw->skb);
+ if (res)
+ pr_debug("transmission failed\n");
+
+out:
+ mutex_unlock(&xw->priv->phy->pib_lock);
+
+ /* Restart the netif queue on each sub_if_data object. */
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &xw->priv->slaves, list)
+ netif_wake_queue(sdata->dev);
+ rcu_read_unlock();
+
+ dev_kfree_skb(xw->skb);
+
+ kfree(xw);
+}
+
+netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb,
+ u8 page, u8 chan)
+{
+ struct xmit_work *work;
+ struct mac802154_sub_if_data *sdata;
+
+ if (!(priv->phy->channels_supported[page] & (1 << chan))) {
+ WARN_ON(1);
+ goto err_tx;
+ }
+
+ mac802154_monitors_rx(mac802154_to_priv(&priv->hw), skb);
+
+ if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) {
+ u16 crc = crc_ccitt(0, skb->data, skb->len);
+ u8 *data = skb_put(skb, 2);
+
+ data[0] = crc & 0xff;
+ data[1] = crc >> 8;
+ }
+
+ if (skb_cow_head(skb, priv->hw.extra_tx_headroom))
+ goto err_tx;
+
+ work = kzalloc(sizeof(*work), GFP_ATOMIC);
+ if (!work) {
+ kfree_skb(skb);
+ return NETDEV_TX_BUSY;
+ }
+
+ /* Stop the netif queue on each sub_if_data object. */
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &priv->slaves, list)
+ netif_stop_queue(sdata->dev);
+ rcu_read_unlock();
+
+ INIT_WORK(&work->work, mac802154_xmit_worker);
+ work->skb = skb;
+ work->priv = priv;
+ work->page = page;
+ work->chan = chan;
+
+ queue_work(priv->dev_workqueue, &work->work);
+
return NETDEV_TX_OK;
err_tx:
kfree_skb(skb);
return NETDEV_TX_OK;
}
-
-netdev_tx_t
-ieee802154_monitor_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
-
- skb->skb_iif = dev->ifindex;
-
- return ieee802154_tx(sdata->local, skb);
-}
-
-netdev_tx_t
-ieee802154_subif_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
- struct ieee802154_sub_if_data *sdata = IEEE802154_DEV_TO_SUB_IF(dev);
- int rc;
-
- rc = mac802154_llsec_encrypt(&sdata->sec, skb);
- if (rc) {
- netdev_warn(dev, "encryption failed: %i\n", rc);
- kfree_skb(skb);
- return NETDEV_TX_OK;
- }
-
- skb->skb_iif = dev->ifindex;
-
- return ieee802154_tx(sdata->local, skb);
-}
diff --git a/net/mac802154/util.c b/net/mac802154/util.c
deleted file mode 100644
index 5fc9790..0000000
--- a/net/mac802154/util.c
+++ /dev/null
@@ -1,84 +0,0 @@
-/* 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.
- *
- * Authors:
- * Alexander Aring <aar@pengutronix.de>
- *
- * Based on: net/mac80211/util.c
- */
-
-#include "ieee802154_i.h"
-
-/* privid for wpan_phys to determine whether they belong to us or not */
-const void *const mac802154_wpan_phy_privid = &mac802154_wpan_phy_privid;
-
-void ieee802154_wake_queue(struct ieee802154_hw *hw)
-{
- struct ieee802154_local *local = hw_to_local(hw);
- struct ieee802154_sub_if_data *sdata;
-
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (!sdata->dev)
- continue;
-
- netif_wake_queue(sdata->dev);
- }
- rcu_read_unlock();
-}
-EXPORT_SYMBOL(ieee802154_wake_queue);
-
-void ieee802154_stop_queue(struct ieee802154_hw *hw)
-{
- struct ieee802154_local *local = hw_to_local(hw);
- struct ieee802154_sub_if_data *sdata;
-
- rcu_read_lock();
- list_for_each_entry_rcu(sdata, &local->interfaces, list) {
- if (!sdata->dev)
- continue;
-
- netif_stop_queue(sdata->dev);
- }
- rcu_read_unlock();
-}
-EXPORT_SYMBOL(ieee802154_stop_queue);
-
-enum hrtimer_restart ieee802154_xmit_ifs_timer(struct hrtimer *timer)
-{
- struct ieee802154_local *local =
- container_of(timer, struct ieee802154_local, ifs_timer);
-
- ieee802154_wake_queue(&local->hw);
-
- return HRTIMER_NORESTART;
-}
-
-void ieee802154_xmit_complete(struct ieee802154_hw *hw, struct sk_buff *skb,
- bool ifs_handling)
-{
- if (ifs_handling) {
- struct ieee802154_local *local = hw_to_local(hw);
-
- if (skb->len > 18)
- hrtimer_start(&local->ifs_timer,
- ktime_set(0, hw->phy->lifs_period * NSEC_PER_USEC),
- HRTIMER_MODE_REL);
- else
- hrtimer_start(&local->ifs_timer,
- ktime_set(0, hw->phy->sifs_period * NSEC_PER_USEC),
- HRTIMER_MODE_REL);
-
- consume_skb(skb);
- } else {
- ieee802154_wake_queue(hw);
- consume_skb(skb);
- }
-}
-EXPORT_SYMBOL(ieee802154_xmit_complete);
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c
new file mode 100644
index 0000000..4ab86a5
--- /dev/null
+++ b/net/mac802154/wpan.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright 2007-2012 Siemens AG
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Written by:
+ * Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
+ * Sergey Lapin <slapin@ossfans.org>
+ * Maxim Gorbachyov <maxim.gorbachev@siemens.com>
+ * Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
+ */
+
+#include <linux/netdevice.h>
+#include <linux/module.h>
+#include <linux/if_arp.h>
+
+#include <net/rtnetlink.h>
+#include <linux/nl802154.h>
+#include <net/af_ieee802154.h>
+#include <net/mac802154.h>
+#include <net/ieee802154_netdev.h>
+#include <net/ieee802154.h>
+#include <net/wpan-phy.h>
+
+#include "mac802154.h"
+
+static int mac802154_wpan_update_llsec(struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct ieee802154_mlme_ops *ops = ieee802154_mlme_ops(dev);
+ int rc = 0;
+
+ if (ops->llsec) {
+ struct ieee802154_llsec_params params;
+ int changed = 0;
+
+ params.pan_id = priv->pan_id;
+ changed |= IEEE802154_LLSEC_PARAM_PAN_ID;
+
+ params.hwaddr = priv->extended_addr;
+ changed |= IEEE802154_LLSEC_PARAM_HWADDR;
+
+ rc = ops->llsec->set_params(dev, ¶ms, changed);
+ }
+
+ return rc;
+}
+
+static int
+mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct sockaddr_ieee802154 *sa =
+ (struct sockaddr_ieee802154 *)&ifr->ifr_addr;
+ int err = -ENOIOCTLCMD;
+
+ spin_lock_bh(&priv->mib_lock);
+
+ switch (cmd) {
+ case SIOCGIFADDR:
+ {
+ u16 pan_id, short_addr;
+
+ pan_id = le16_to_cpu(priv->pan_id);
+ short_addr = le16_to_cpu(priv->short_addr);
+ if (pan_id == IEEE802154_PANID_BROADCAST ||
+ short_addr == IEEE802154_ADDR_BROADCAST) {
+ err = -EADDRNOTAVAIL;
+ break;
+ }
+
+ sa->family = AF_IEEE802154;
+ sa->addr.addr_type = IEEE802154_ADDR_SHORT;
+ sa->addr.pan_id = pan_id;
+ sa->addr.short_addr = short_addr;
+
+ err = 0;
+ break;
+ }
+ case SIOCSIFADDR:
+ dev_warn(&dev->dev,
+ "Using DEBUGing ioctl SIOCSIFADDR isn't recommended!\n");
+ if (sa->family != AF_IEEE802154 ||
+ sa->addr.addr_type != IEEE802154_ADDR_SHORT ||
+ sa->addr.pan_id == IEEE802154_PANID_BROADCAST ||
+ sa->addr.short_addr == IEEE802154_ADDR_BROADCAST ||
+ sa->addr.short_addr == IEEE802154_ADDR_UNDEF) {
+ err = -EINVAL;
+ break;
+ }
+
+ priv->pan_id = cpu_to_le16(sa->addr.pan_id);
+ priv->short_addr = cpu_to_le16(sa->addr.short_addr);
+
+ err = mac802154_wpan_update_llsec(dev);
+ break;
+ }
+
+ spin_unlock_bh(&priv->mib_lock);
+ return err;
+}
+
+static int mac802154_wpan_mac_addr(struct net_device *dev, void *p)
+{
+ struct sockaddr *addr = p;
+
+ if (netif_running(dev))
+ return -EBUSY;
+
+ /* FIXME: validate addr */
+ memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+ mac802154_dev_set_ieee_addr(dev);
+ return mac802154_wpan_update_llsec(dev);
+}
+
+int mac802154_set_mac_params(struct net_device *dev,
+ const struct ieee802154_mac_params *params)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+ mutex_lock(&priv->hw->slaves_mtx);
+ priv->mac_params = *params;
+ mutex_unlock(&priv->hw->slaves_mtx);
+
+ return 0;
+}
+
+void mac802154_get_mac_params(struct net_device *dev,
+ struct ieee802154_mac_params *params)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+ mutex_lock(&priv->hw->slaves_mtx);
+ *params = priv->mac_params;
+ mutex_unlock(&priv->hw->slaves_mtx);
+}
+
+static int mac802154_wpan_open(struct net_device *dev)
+{
+ int rc;
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct wpan_phy *phy = priv->hw->phy;
+
+ rc = mac802154_slave_open(dev);
+ if (rc < 0)
+ return rc;
+
+ mutex_lock(&phy->pib_lock);
+
+ if (phy->set_txpower) {
+ rc = phy->set_txpower(phy, priv->mac_params.transmit_power);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_lbt) {
+ rc = phy->set_lbt(phy, priv->mac_params.lbt);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_cca_mode) {
+ rc = phy->set_cca_mode(phy, priv->mac_params.cca_mode);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_cca_ed_level) {
+ rc = phy->set_cca_ed_level(phy, priv->mac_params.cca_ed_level);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_csma_params) {
+ rc = phy->set_csma_params(phy, priv->mac_params.min_be,
+ priv->mac_params.max_be,
+ priv->mac_params.csma_retries);
+ if (rc < 0)
+ goto out;
+ }
+
+ if (phy->set_frame_retries) {
+ rc = phy->set_frame_retries(phy,
+ priv->mac_params.frame_retries);
+ if (rc < 0)
+ goto out;
+ }
+
+ mutex_unlock(&phy->pib_lock);
+ return 0;
+
+out:
+ mutex_unlock(&phy->pib_lock);
+ return rc;
+}
+
+static int mac802154_set_header_security(struct mac802154_sub_if_data *priv,
+ struct ieee802154_hdr *hdr,
+ const struct ieee802154_mac_cb *cb)
+{
+ struct ieee802154_llsec_params params;
+ u8 level;
+
+ mac802154_llsec_get_params(&priv->sec, ¶ms);
+
+ if (!params.enabled && cb->secen_override && cb->secen)
+ return -EINVAL;
+ if (!params.enabled ||
+ (cb->secen_override && !cb->secen) ||
+ !params.out_level)
+ return 0;
+ if (cb->seclevel_override && !cb->seclevel)
+ return -EINVAL;
+
+ level = cb->seclevel_override ? cb->seclevel : params.out_level;
+
+ hdr->fc.security_enabled = 1;
+ hdr->sec.level = level;
+ hdr->sec.key_id_mode = params.out_key.mode;
+ if (params.out_key.mode == IEEE802154_SCF_KEY_SHORT_INDEX)
+ hdr->sec.short_src = params.out_key.short_source;
+ else if (params.out_key.mode == IEEE802154_SCF_KEY_HW_INDEX)
+ hdr->sec.extended_src = params.out_key.extended_source;
+ hdr->sec.key_id = params.out_key.id;
+
+ return 0;
+}
+
+static int mac802154_header_create(struct sk_buff *skb,
+ struct net_device *dev,
+ unsigned short type,
+ const void *daddr,
+ const void *saddr,
+ unsigned len)
+{
+ struct ieee802154_hdr hdr;
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+ struct ieee802154_mac_cb *cb = mac_cb(skb);
+ int hlen;
+
+ if (!daddr)
+ return -EINVAL;
+
+ memset(&hdr.fc, 0, sizeof(hdr.fc));
+ hdr.fc.type = cb->type;
+ hdr.fc.security_enabled = cb->secen;
+ hdr.fc.ack_request = cb->ackreq;
+ hdr.seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
+
+ if (mac802154_set_header_security(priv, &hdr, cb) < 0)
+ return -EINVAL;
+
+ if (!saddr) {
+ spin_lock_bh(&priv->mib_lock);
+
+ if (priv->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) ||
+ priv->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
+ priv->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) {
+ hdr.source.mode = IEEE802154_ADDR_LONG;
+ hdr.source.extended_addr = priv->extended_addr;
+ } else {
+ hdr.source.mode = IEEE802154_ADDR_SHORT;
+ hdr.source.short_addr = priv->short_addr;
+ }
+
+ hdr.source.pan_id = priv->pan_id;
+
+ spin_unlock_bh(&priv->mib_lock);
+ } else {
+ hdr.source = *(const struct ieee802154_addr *)saddr;
+ }
+
+ hdr.dest = *(const struct ieee802154_addr *)daddr;
+
+ hlen = ieee802154_hdr_push(skb, &hdr);
+ if (hlen < 0)
+ return -EINVAL;
+
+ skb_reset_mac_header(skb);
+ skb->mac_len = hlen;
+
+ if (len > ieee802154_max_payload(&hdr))
+ return -EMSGSIZE;
+
+ return hlen;
+}
+
+static int
+mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr)
+{
+ struct ieee802154_hdr hdr;
+ struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr;
+
+ if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) {
+ pr_debug("malformed packet\n");
+ return 0;
+ }
+
+ *addr = hdr.source;
+ return sizeof(*addr);
+}
+
+static netdev_tx_t
+mac802154_wpan_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv;
+ u8 chan, page;
+ int rc;
+
+ priv = netdev_priv(dev);
+
+ spin_lock_bh(&priv->mib_lock);
+ chan = priv->chan;
+ page = priv->page;
+ spin_unlock_bh(&priv->mib_lock);
+
+ if (chan == MAC802154_CHAN_NONE ||
+ page >= WPAN_NUM_PAGES ||
+ chan >= WPAN_NUM_CHANNELS) {
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ rc = mac802154_llsec_encrypt(&priv->sec, skb);
+ if (rc) {
+ pr_warn("encryption failed: %i\n", rc);
+ kfree_skb(skb);
+ return NETDEV_TX_OK;
+ }
+
+ skb->skb_iif = dev->ifindex;
+ dev->stats.tx_packets++;
+ dev->stats.tx_bytes += skb->len;
+
+ return mac802154_tx(priv->hw, skb, page, chan);
+}
+
+static struct header_ops mac802154_header_ops = {
+ .create = mac802154_header_create,
+ .parse = mac802154_header_parse,
+};
+
+static const struct net_device_ops mac802154_wpan_ops = {
+ .ndo_open = mac802154_wpan_open,
+ .ndo_stop = mac802154_slave_close,
+ .ndo_start_xmit = mac802154_wpan_xmit,
+ .ndo_do_ioctl = mac802154_wpan_ioctl,
+ .ndo_set_mac_address = mac802154_wpan_mac_addr,
+};
+
+static void mac802154_wpan_free(struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv = netdev_priv(dev);
+
+ mac802154_llsec_destroy(&priv->sec);
+
+ free_netdev(dev);
+}
+
+void mac802154_wpan_setup(struct net_device *dev)
+{
+ struct mac802154_sub_if_data *priv;
+
+ dev->addr_len = IEEE802154_ADDR_LEN;
+ memset(dev->broadcast, 0xff, IEEE802154_ADDR_LEN);
+
+ dev->hard_header_len = MAC802154_FRAME_HARD_HEADER_LEN;
+ dev->header_ops = &mac802154_header_ops;
+ dev->needed_tailroom = 2 + 16; /* FCS + MIC */
+ dev->mtu = IEEE802154_MTU;
+ dev->tx_queue_len = 300;
+ dev->type = ARPHRD_IEEE802154;
+ dev->flags = IFF_NOARP | IFF_BROADCAST;
+ dev->watchdog_timeo = 0;
+
+ dev->destructor = mac802154_wpan_free;
+ dev->netdev_ops = &mac802154_wpan_ops;
+ dev->ml_priv = &mac802154_mlme_wpan;
+
+ priv = netdev_priv(dev);
+ priv->type = IEEE802154_DEV_WPAN;
+
+ priv->chan = MAC802154_CHAN_NONE;
+ priv->page = 0;
+
+ spin_lock_init(&priv->mib_lock);
+ mutex_init(&priv->sec_mtx);
+
+ get_random_bytes(&priv->bsn, 1);
+ get_random_bytes(&priv->dsn, 1);
+
+ /* defaults per 802.15.4-2011 */
+ priv->mac_params.min_be = 3;
+ priv->mac_params.max_be = 5;
+ priv->mac_params.csma_retries = 4;
+ priv->mac_params.frame_retries = -1; /* for compatibility, actual default is 3 */
+
+ priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST);
+ priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
+
+ mac802154_llsec_init(&priv->sec);
+}
+
+static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb)
+{
+ return netif_rx_ni(skb);
+}
+
+static int
+mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb,
+ const struct ieee802154_hdr *hdr)
+{
+ __le16 span, sshort;
+ int rc;
+
+ pr_debug("getting packet via slave interface %s\n", sdata->dev->name);
+
+ spin_lock_bh(&sdata->mib_lock);
+
+ span = sdata->pan_id;
+ sshort = sdata->short_addr;
+
+ switch (mac_cb(skb)->dest.mode) {
+ case IEEE802154_ADDR_NONE:
+ if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE)
+ /* FIXME: check if we are PAN coordinator */
+ skb->pkt_type = PACKET_OTHERHOST;
+ else
+ /* ACK comes with both addresses empty */
+ skb->pkt_type = PACKET_HOST;
+ break;
+ case IEEE802154_ADDR_LONG:
+ if (mac_cb(skb)->dest.pan_id != span &&
+ mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
+ skb->pkt_type = PACKET_OTHERHOST;
+ else if (mac_cb(skb)->dest.extended_addr == sdata->extended_addr)
+ skb->pkt_type = PACKET_HOST;
+ else
+ skb->pkt_type = PACKET_OTHERHOST;
+ break;
+ case IEEE802154_ADDR_SHORT:
+ if (mac_cb(skb)->dest.pan_id != span &&
+ mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST))
+ skb->pkt_type = PACKET_OTHERHOST;
+ else if (mac_cb(skb)->dest.short_addr == sshort)
+ skb->pkt_type = PACKET_HOST;
+ else if (mac_cb(skb)->dest.short_addr ==
+ cpu_to_le16(IEEE802154_ADDR_BROADCAST))
+ skb->pkt_type = PACKET_BROADCAST;
+ else
+ skb->pkt_type = PACKET_OTHERHOST;
+ break;
+ default:
+ spin_unlock_bh(&sdata->mib_lock);
+ pr_debug("invalid dest mode\n");
+ kfree_skb(skb);
+ return NET_RX_DROP;
+ }
+
+ spin_unlock_bh(&sdata->mib_lock);
+
+ skb->dev = sdata->dev;
+
+ rc = mac802154_llsec_decrypt(&sdata->sec, skb);
+ if (rc) {
+ pr_debug("decryption failed: %i\n", rc);
+ goto fail;
+ }
+
+ sdata->dev->stats.rx_packets++;
+ sdata->dev->stats.rx_bytes += skb->len;
+
+ switch (mac_cb(skb)->type) {
+ case IEEE802154_FC_TYPE_DATA:
+ return mac802154_process_data(sdata->dev, skb);
+ default:
+ pr_warn("ieee802154: bad frame received (type = %d)\n",
+ mac_cb(skb)->type);
+ goto fail;
+ }
+
+fail:
+ kfree_skb(skb);
+ return NET_RX_DROP;
+}
+
+static void mac802154_print_addr(const char *name,
+ const struct ieee802154_addr *addr)
+{
+ if (addr->mode == IEEE802154_ADDR_NONE)
+ pr_debug("%s not present\n", name);
+
+ pr_debug("%s PAN ID: %04x\n", name, le16_to_cpu(addr->pan_id));
+ if (addr->mode == IEEE802154_ADDR_SHORT) {
+ pr_debug("%s is short: %04x\n", name,
+ le16_to_cpu(addr->short_addr));
+ } else {
+ u64 hw = swab64((__force u64) addr->extended_addr);
+
+ pr_debug("%s is hardware: %8phC\n", name, &hw);
+ }
+}
+
+static int mac802154_parse_frame_start(struct sk_buff *skb,
+ struct ieee802154_hdr *hdr)
+{
+ int hlen;
+ struct ieee802154_mac_cb *cb = mac_cb_init(skb);
+
+ hlen = ieee802154_hdr_pull(skb, hdr);
+ if (hlen < 0)
+ return -EINVAL;
+
+ skb->mac_len = hlen;
+
+ pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr->fc),
+ hdr->seq);
+
+ cb->type = hdr->fc.type;
+ cb->ackreq = hdr->fc.ack_request;
+ cb->secen = hdr->fc.security_enabled;
+
+ mac802154_print_addr("destination", &hdr->dest);
+ mac802154_print_addr("source", &hdr->source);
+
+ cb->source = hdr->source;
+ cb->dest = hdr->dest;
+
+ if (hdr->fc.security_enabled) {
+ u64 key;
+
+ pr_debug("seclevel %i\n", hdr->sec.level);
+
+ switch (hdr->sec.key_id_mode) {
+ case IEEE802154_SCF_KEY_IMPLICIT:
+ pr_debug("implicit key\n");
+ break;
+
+ case IEEE802154_SCF_KEY_INDEX:
+ pr_debug("key %02x\n", hdr->sec.key_id);
+ break;
+
+ case IEEE802154_SCF_KEY_SHORT_INDEX:
+ pr_debug("key %04x:%04x %02x\n",
+ le32_to_cpu(hdr->sec.short_src) >> 16,
+ le32_to_cpu(hdr->sec.short_src) & 0xffff,
+ hdr->sec.key_id);
+ break;
+
+ case IEEE802154_SCF_KEY_HW_INDEX:
+ key = swab64((__force u64) hdr->sec.extended_src);
+ pr_debug("key source %8phC %02x\n", &key,
+ hdr->sec.key_id);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb)
+{
+ int ret;
+ struct mac802154_sub_if_data *sdata;
+ struct ieee802154_hdr hdr;
+
+ ret = mac802154_parse_frame_start(skb, &hdr);
+ if (ret) {
+ pr_debug("got invalid frame\n");
+ kfree_skb(skb);
+ return;
+ }
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(sdata, &priv->slaves, list) {
+ if (sdata->type != IEEE802154_DEV_WPAN ||
+ !netif_running(sdata->dev))
+ continue;
+
+ mac802154_subif_frame(sdata, skb, &hdr);
+ skb = NULL;
+ break;
+ }
+ rcu_read_unlock();
+
+ if (skb)
+ kfree_skb(skb);
+}
diff --git a/net/nfc/Kconfig b/net/nfc/Kconfig
index 5e54818..314f31c 100644
--- a/net/nfc/Kconfig
+++ b/net/nfc/Kconfig
@@ -3,7 +3,7 @@
#
menuconfig NFC
- depends on !KERNEL_3_1
+ depends on !BACKPORT_KERNEL_3_1
depends on NET
depends on RFKILL || !RFKILL
tristate "NFC subsystem support"
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c
index f72be74..b60aa35 100644
--- a/net/nfc/digital_dep.c
+++ b/net/nfc/digital_dep.c
@@ -17,9 +17,6 @@
#include "digital.h"
-#define DIGITAL_NFC_DEP_N_RETRY_NACK 2
-#define DIGITAL_NFC_DEP_N_RETRY_ATN 2
-
#define DIGITAL_NFC_DEP_FRAME_DIR_OUT 0xD4
#define DIGITAL_NFC_DEP_FRAME_DIR_IN 0xD5
@@ -35,32 +32,20 @@
#define DIGITAL_ATR_REQ_MIN_SIZE 16
#define DIGITAL_ATR_REQ_MAX_SIZE 64
-#define DIGITAL_DID_MAX 14
-
-#define DIGITAL_PAYLOAD_SIZE_MAX 254
-#define DIGITAL_PAYLOAD_BITS_TO_PP(s) (((s) & 0x3) << 4)
-#define DIGITAL_PAYLOAD_PP_TO_BITS(s) (((s) >> 4) & 0x3)
-#define DIGITAL_PAYLOAD_BITS_TO_FSL(s) ((s) & 0x3)
-#define DIGITAL_PAYLOAD_FSL_TO_BITS(s) ((s) & 0x3)
-
+#define DIGITAL_LR_BITS_PAYLOAD_SIZE_254B 0x30
+#define DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B \
+ (DIGITAL_LR_BITS_PAYLOAD_SIZE_254B >> 4)
#define DIGITAL_GB_BIT 0x02
-#define DIGITAL_NFC_DEP_REQ_RES_HEADROOM 2 /* SoD: [SB (NFC-A)] + LEN */
-#define DIGITAL_NFC_DEP_REQ_RES_TAILROOM 2 /* EoD: 2-byte CRC */
-
#define DIGITAL_NFC_DEP_PFB_TYPE(pfb) ((pfb) & 0xE0)
#define DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT 0x10
-#define DIGITAL_NFC_DEP_PFB_MI_BIT 0x10
-#define DIGITAL_NFC_DEP_PFB_NACK_BIT 0x10
-#define DIGITAL_NFC_DEP_PFB_DID_BIT 0x04
#define DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb) \
((pfb) & DIGITAL_NFC_DEP_PFB_TIMEOUT_BIT)
-#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_MI_BIT)
-#define DIGITAL_NFC_DEP_NACK_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_NACK_BIT)
+#define DIGITAL_NFC_DEP_MI_BIT_SET(pfb) ((pfb) & 0x10)
#define DIGITAL_NFC_DEP_NAD_BIT_SET(pfb) ((pfb) & 0x08)
-#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & DIGITAL_NFC_DEP_PFB_DID_BIT)
+#define DIGITAL_NFC_DEP_DID_BIT_SET(pfb) ((pfb) & 0x04)
#define DIGITAL_NFC_DEP_PFB_PNI(pfb) ((pfb) & 0x03)
#define DIGITAL_NFC_DEP_PFB_I_PDU 0x00
@@ -112,34 +97,6 @@
static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
struct sk_buff *resp);
-static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
- struct sk_buff *resp);
-
-static const u8 digital_payload_bits_map[4] = {
- [0] = 64,
- [1] = 128,
- [2] = 192,
- [3] = 254
-};
-
-static u8 digital_payload_bits_to_size(u8 payload_bits)
-{
- if (payload_bits >= ARRAY_SIZE(digital_payload_bits_map))
- return 0;
-
- return digital_payload_bits_map[payload_bits];
-}
-
-static u8 digital_payload_size_to_bits(u8 payload_size)
-{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(digital_payload_bits_map); i++)
- if (digital_payload_bits_map[i] == payload_size)
- return i;
-
- return 0xff;
-}
static void digital_skb_push_dep_sod(struct nfc_digital_dev *ddev,
struct sk_buff *skb)
@@ -172,106 +129,6 @@
return 0;
}
-static struct sk_buff *
-digital_send_dep_data_prep(struct nfc_digital_dev *ddev, struct sk_buff *skb,
- struct digital_dep_req_res *dep_req_res,
- struct digital_data_exch *data_exch)
-{
- struct sk_buff *new_skb;
-
- if (skb->len > ddev->remote_payload_max) {
- dep_req_res->pfb |= DIGITAL_NFC_DEP_PFB_MI_BIT;
-
- new_skb = digital_skb_alloc(ddev, ddev->remote_payload_max);
- if (!new_skb) {
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = NULL;
-
- return ERR_PTR(-ENOMEM);
- }
-
- skb_reserve(new_skb, ddev->tx_headroom + NFC_HEADER_SIZE +
- DIGITAL_NFC_DEP_REQ_RES_HEADROOM);
- memcpy(skb_put(new_skb, ddev->remote_payload_max), skb->data,
- ddev->remote_payload_max);
- skb_pull(skb, ddev->remote_payload_max);
-
- ddev->chaining_skb = skb;
- ddev->data_exch = data_exch;
- } else {
- ddev->chaining_skb = NULL;
- new_skb = skb;
- }
-
- return new_skb;
-}
-
-static struct sk_buff *
-digital_recv_dep_data_gather(struct nfc_digital_dev *ddev, u8 pfb,
- struct sk_buff *resp,
- int (*send_ack)(struct nfc_digital_dev *ddev,
- struct digital_data_exch
- *data_exch),
- struct digital_data_exch *data_exch)
-{
- struct sk_buff *new_skb;
- int rc;
-
- if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb) && (!ddev->chaining_skb)) {
- ddev->chaining_skb =
- nfc_alloc_recv_skb(8 * ddev->local_payload_max,
- GFP_KERNEL);
- if (!ddev->chaining_skb) {
- rc = -ENOMEM;
- goto error;
- }
- }
-
- if (ddev->chaining_skb) {
- if (resp->len > skb_tailroom(ddev->chaining_skb)) {
- new_skb = skb_copy_expand(ddev->chaining_skb,
- skb_headroom(
- ddev->chaining_skb),
- 8 * ddev->local_payload_max,
- GFP_KERNEL);
- if (!new_skb) {
- rc = -ENOMEM;
- goto error;
- }
-
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = new_skb;
- }
-
- memcpy(skb_put(ddev->chaining_skb, resp->len), resp->data,
- resp->len);
-
- kfree_skb(resp);
- resp = NULL;
-
- if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
- rc = send_ack(ddev, data_exch);
- if (rc)
- goto error;
-
- return NULL;
- }
-
- resp = ddev->chaining_skb;
- ddev->chaining_skb = NULL;
- }
-
- return resp;
-
-error:
- kfree_skb(resp);
-
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = NULL;
-
- return ERR_PTR(rc);
-}
-
static void digital_in_recv_psl_res(struct nfc_digital_dev *ddev, void *arg,
struct sk_buff *resp)
{
@@ -341,8 +198,6 @@
{
struct sk_buff *skb;
struct digital_psl_req *psl_req;
- int rc;
- u8 payload_size, payload_bits;
skb = digital_skb_alloc(ddev, sizeof(*psl_req));
if (!skb)
@@ -356,24 +211,14 @@
psl_req->cmd = DIGITAL_CMD_PSL_REQ;
psl_req->did = 0;
psl_req->brs = (0x2 << 3) | 0x2; /* 424F both directions */
-
- payload_size = min(ddev->local_payload_max, ddev->remote_payload_max);
- payload_bits = digital_payload_size_to_bits(payload_size);
- psl_req->fsl = DIGITAL_PAYLOAD_BITS_TO_FSL(payload_bits);
-
- ddev->local_payload_max = payload_size;
- ddev->remote_payload_max = payload_size;
+ psl_req->fsl = DIGITAL_FSL_BITS_PAYLOAD_SIZE_254B;
digital_skb_push_dep_sod(ddev, skb);
ddev->skb_add_crc(skb);
- rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_psl_res,
- target);
- if (rc)
- kfree_skb(skb);
-
- return rc;
+ return digital_in_send_cmd(ddev, skb, 500, digital_in_recv_psl_res,
+ target);
}
static void digital_in_recv_atr_res(struct nfc_digital_dev *ddev, void *arg,
@@ -381,7 +226,7 @@
{
struct nfc_target *target = arg;
struct digital_atr_res *atr_res;
- u8 gb_len, payload_bits;
+ u8 gb_len;
int rc;
if (IS_ERR(resp)) {
@@ -411,14 +256,6 @@
atr_res = (struct digital_atr_res *)resp->data;
- payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_res->pp);
- ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
-
- if (!ddev->remote_payload_max) {
- rc = -EINVAL;
- goto exit;
- }
-
rc = nfc_set_remote_general_bytes(ddev->nfc_dev, atr_res->gb, gb_len);
if (rc)
goto exit;
@@ -449,8 +286,6 @@
struct sk_buff *skb;
struct digital_atr_req *atr_req;
uint size;
- int rc;
- u8 payload_bits;
size = DIGITAL_ATR_REQ_MIN_SIZE + gb_len;
@@ -479,9 +314,7 @@
atr_req->bs = 0;
atr_req->br = 0;
- ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
- payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
- atr_req->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
+ atr_req->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
if (gb_len) {
atr_req->pp |= DIGITAL_GB_BIT;
@@ -492,113 +325,8 @@
ddev->skb_add_crc(skb);
- rc = digital_in_send_cmd(ddev, skb, 500, digital_in_recv_atr_res,
- target);
- if (rc)
- kfree_skb(skb);
-
- return rc;
-}
-
-static int digital_in_send_ack(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
-{
- struct digital_dep_req_res *dep_req;
- struct sk_buff *skb;
- int rc;
-
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
-
- skb_push(skb, sizeof(struct digital_dep_req_res));
-
- dep_req = (struct digital_dep_req_res *)skb->data;
-
- dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- dep_req->cmd = DIGITAL_CMD_DEP_REQ;
- dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
- ddev->curr_nfc_dep_pni;
-
- digital_skb_push_dep_sod(ddev, skb);
-
- ddev->skb_add_crc(skb);
-
- ddev->saved_skb = skb_get(skb);
- ddev->saved_skb_len = skb->len;
-
- rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
- data_exch);
- if (rc) {
- kfree_skb(skb);
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- }
-
- return rc;
-}
-
-static int digital_in_send_nack(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
-{
- struct digital_dep_req_res *dep_req;
- struct sk_buff *skb;
- int rc;
-
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
-
- skb_push(skb, sizeof(struct digital_dep_req_res));
-
- dep_req = (struct digital_dep_req_res *)skb->data;
-
- dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- dep_req->cmd = DIGITAL_CMD_DEP_REQ;
- dep_req->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
- DIGITAL_NFC_DEP_PFB_NACK_BIT | ddev->curr_nfc_dep_pni;
-
- digital_skb_push_dep_sod(ddev, skb);
-
- ddev->skb_add_crc(skb);
-
- rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
- data_exch);
- if (rc)
- kfree_skb(skb);
-
- return rc;
-}
-
-static int digital_in_send_atn(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
-{
- struct digital_dep_req_res *dep_req;
- struct sk_buff *skb;
- int rc;
-
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
-
- skb_push(skb, sizeof(struct digital_dep_req_res));
-
- dep_req = (struct digital_dep_req_res *)skb->data;
-
- dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
- dep_req->cmd = DIGITAL_CMD_DEP_REQ;
- dep_req->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
-
- digital_skb_push_dep_sod(ddev, skb);
-
- ddev->skb_add_crc(skb);
-
- rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
- data_exch);
- if (rc)
- kfree_skb(skb);
-
- return rc;
+ return digital_in_send_cmd(ddev, skb, 500, digital_in_recv_atr_res,
+ target);
}
static int digital_in_send_rtox(struct nfc_digital_dev *ddev,
@@ -627,30 +355,12 @@
ddev->skb_add_crc(skb);
- ddev->saved_skb = skb_get(skb);
- ddev->saved_skb_len = skb->len;
-
rc = digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
data_exch);
- if (rc) {
- kfree_skb(skb);
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- }
return rc;
}
-static int digital_in_send_saved_skb(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
-{
- skb_get(ddev->saved_skb);
- skb_push(ddev->saved_skb, ddev->saved_skb_len);
-
- return digital_in_send_cmd(ddev, ddev->saved_skb, 1500,
- digital_in_recv_dep_res, data_exch);
-}
-
static void digital_in_recv_dep_res(struct nfc_digital_dev *ddev, void *arg,
struct sk_buff *resp)
{
@@ -663,67 +373,25 @@
if (IS_ERR(resp)) {
rc = PTR_ERR(resp);
resp = NULL;
-
- if (((rc != -ETIMEDOUT) || ddev->nack_count) &&
- (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
- ddev->atn_count = 0;
-
- rc = digital_in_send_nack(ddev, data_exch);
- if (rc)
- goto error;
-
- return;
- } else if ((rc == -ETIMEDOUT) &&
- (ddev->atn_count++ < DIGITAL_NFC_DEP_N_RETRY_ATN)) {
- ddev->nack_count = 0;
-
- rc = digital_in_send_atn(ddev, data_exch);
- if (rc)
- goto error;
-
- return;
- }
-
goto exit;
}
+ rc = ddev->skb_check_crc(resp);
+ if (rc) {
+ PROTOCOL_ERR("14.4.1.6");
+ goto error;
+ }
+
rc = digital_skb_pull_dep_sod(ddev, resp);
if (rc) {
PROTOCOL_ERR("14.4.1.2");
goto exit;
}
- rc = ddev->skb_check_crc(resp);
- if (rc) {
- if ((resp->len >= 4) &&
- (ddev->nack_count++ < DIGITAL_NFC_DEP_N_RETRY_NACK)) {
- ddev->atn_count = 0;
-
- rc = digital_in_send_nack(ddev, data_exch);
- if (rc)
- goto error;
-
- kfree_skb(resp);
-
- return;
- }
-
- PROTOCOL_ERR("14.4.1.6");
- goto error;
- }
-
- ddev->atn_count = 0;
- ddev->nack_count = 0;
-
- if (resp->len > ddev->local_payload_max) {
- rc = -EMSGSIZE;
- goto exit;
- }
-
- size = sizeof(struct digital_dep_req_res);
dep_res = (struct digital_dep_req_res *)resp->data;
- if (resp->len < size || dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
+ if (resp->len < sizeof(struct digital_dep_req_res) ||
+ dep_res->dir != DIGITAL_NFC_DEP_FRAME_DIR_IN ||
dep_res->cmd != DIGITAL_CMD_DEP_RES) {
rc = -EIO;
goto error;
@@ -731,24 +399,6 @@
pfb = dep_res->pfb;
- if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
- PROTOCOL_ERR("14.8.2.1");
- rc = -EIO;
- goto error;
- }
-
- if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
- rc = -EIO;
- goto exit;
- }
-
- if (size > resp->len) {
- rc = -EIO;
- goto error;
- }
-
- skb_pull(resp, size);
-
switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
case DIGITAL_NFC_DEP_PFB_I_PDU:
if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
@@ -759,71 +409,21 @@
ddev->curr_nfc_dep_pni =
DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
-
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
-
- resp = digital_recv_dep_data_gather(ddev, pfb, resp,
- digital_in_send_ack,
- data_exch);
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- goto error;
- }
-
- /* If resp is NULL then we're still chaining so return and
- * wait for the next part of the PDU. Else, the PDU is
- * complete so pass it up.
- */
- if (!resp)
- return;
-
rc = 0;
break;
case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
- if (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni) {
- PROTOCOL_ERR("14.12.3.3");
- rc = -EIO;
- goto exit;
- }
-
- ddev->curr_nfc_dep_pni =
- DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
-
- if (ddev->chaining_skb && !DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) {
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
-
- rc = digital_in_send_dep_req(ddev, NULL,
- ddev->chaining_skb,
- ddev->data_exch);
- if (rc)
- goto error;
-
- return;
- }
-
pr_err("Received a ACK/NACK PDU\n");
- rc = -EINVAL;
- goto exit;
+ rc = -EIO;
+ goto error;
case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
- if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) { /* ATN */
- rc = digital_in_send_saved_skb(ddev, data_exch);
- if (rc) {
- kfree_skb(ddev->saved_skb);
- goto error;
- }
-
- return;
+ if (!DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
+ rc = -EINVAL;
+ goto error;
}
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
-
- rc = digital_in_send_rtox(ddev, data_exch, resp->data[0]);
+ rc = digital_in_send_rtox(ddev, data_exch, resp->data[3]);
if (rc)
goto error;
@@ -831,18 +431,30 @@
return;
}
+ if (DIGITAL_NFC_DEP_MI_BIT_SET(pfb)) {
+ pr_err("MI bit set. Chained PDU not supported\n");
+ rc = -EIO;
+ goto error;
+ }
+
+ size = sizeof(struct digital_dep_req_res);
+
+ if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb))
+ size++;
+
+ if (size > resp->len) {
+ rc = -EIO;
+ goto error;
+ }
+
+ skb_pull(resp, size);
+
exit:
data_exch->cb(data_exch->cb_context, resp, rc);
error:
kfree(data_exch);
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = NULL;
-
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
-
if (rc)
kfree_skb(resp);
}
@@ -852,47 +464,20 @@
struct digital_data_exch *data_exch)
{
struct digital_dep_req_res *dep_req;
- struct sk_buff *chaining_skb, *tmp_skb;
- int rc;
skb_push(skb, sizeof(struct digital_dep_req_res));
dep_req = (struct digital_dep_req_res *)skb->data;
-
dep_req->dir = DIGITAL_NFC_DEP_FRAME_DIR_OUT;
dep_req->cmd = DIGITAL_CMD_DEP_REQ;
dep_req->pfb = ddev->curr_nfc_dep_pni;
- ddev->atn_count = 0;
- ddev->nack_count = 0;
+ digital_skb_push_dep_sod(ddev, skb);
- chaining_skb = ddev->chaining_skb;
+ ddev->skb_add_crc(skb);
- tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_req, data_exch);
- if (IS_ERR(tmp_skb))
- return PTR_ERR(tmp_skb);
-
- digital_skb_push_dep_sod(ddev, tmp_skb);
-
- ddev->skb_add_crc(tmp_skb);
-
- ddev->saved_skb = skb_get(tmp_skb);
- ddev->saved_skb_len = tmp_skb->len;
-
- rc = digital_in_send_cmd(ddev, tmp_skb, 1500, digital_in_recv_dep_res,
- data_exch);
- if (rc) {
- if (tmp_skb != skb)
- kfree_skb(tmp_skb);
-
- kfree_skb(chaining_skb);
- ddev->chaining_skb = NULL;
-
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- }
-
- return rc;
+ return digital_in_send_cmd(ddev, skb, 1500, digital_in_recv_dep_res,
+ data_exch);
}
static void digital_tg_set_rf_tech(struct nfc_digital_dev *ddev, u8 rf_tech)
@@ -922,106 +507,11 @@
}
}
-static int digital_tg_send_ack(struct nfc_digital_dev *ddev,
- struct digital_data_exch *data_exch)
-{
- struct digital_dep_req_res *dep_res;
- struct sk_buff *skb;
- int rc;
-
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
-
- skb_push(skb, sizeof(struct digital_dep_req_res));
-
- dep_res = (struct digital_dep_req_res *)skb->data;
-
- dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
- dep_res->cmd = DIGITAL_CMD_DEP_RES;
- dep_res->pfb = DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU |
- ddev->curr_nfc_dep_pni;
-
- if (ddev->did) {
- dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
-
- memcpy(skb_put(skb, sizeof(ddev->did)), &ddev->did,
- sizeof(ddev->did));
- }
-
- ddev->curr_nfc_dep_pni =
- DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
-
- digital_skb_push_dep_sod(ddev, skb);
-
- ddev->skb_add_crc(skb);
-
- ddev->saved_skb = skb_get(skb);
- ddev->saved_skb_len = skb->len;
-
- rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
- data_exch);
- if (rc) {
- kfree_skb(skb);
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- }
-
- return rc;
-}
-
-static int digital_tg_send_atn(struct nfc_digital_dev *ddev)
-{
- struct digital_dep_req_res *dep_res;
- struct sk_buff *skb;
- int rc;
-
- skb = digital_skb_alloc(ddev, 1);
- if (!skb)
- return -ENOMEM;
-
- skb_push(skb, sizeof(struct digital_dep_req_res));
-
- dep_res = (struct digital_dep_req_res *)skb->data;
-
- dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
- dep_res->cmd = DIGITAL_CMD_DEP_RES;
- dep_res->pfb = DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU;
-
- if (ddev->did) {
- dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
-
- memcpy(skb_put(skb, sizeof(ddev->did)), &ddev->did,
- sizeof(ddev->did));
- }
-
- digital_skb_push_dep_sod(ddev, skb);
-
- ddev->skb_add_crc(skb);
-
- rc = digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
- NULL);
- if (rc)
- kfree_skb(skb);
-
- return rc;
-}
-
-static int digital_tg_send_saved_skb(struct nfc_digital_dev *ddev)
-{
- skb_get(ddev->saved_skb);
- skb_push(ddev->saved_skb, ddev->saved_skb_len);
-
- return digital_tg_send_cmd(ddev, ddev->saved_skb, 1500,
- digital_tg_recv_dep_req, NULL);
-}
-
static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg,
struct sk_buff *resp)
{
int rc;
struct digital_dep_req_res *dep_req;
- u8 pfb;
size_t size;
if (IS_ERR(resp)) {
@@ -1042,11 +532,6 @@
goto exit;
}
- if (resp->len > ddev->local_payload_max) {
- rc = -EMSGSIZE;
- goto exit;
- }
-
size = sizeof(struct digital_dep_req_res);
dep_req = (struct digital_dep_req_res *)resp->data;
@@ -1056,147 +541,34 @@
goto exit;
}
- pfb = dep_req->pfb;
+ if (DIGITAL_NFC_DEP_DID_BIT_SET(dep_req->pfb))
+ size++;
- if (DIGITAL_NFC_DEP_DID_BIT_SET(pfb)) {
- if (ddev->did && (ddev->did == resp->data[3])) {
- size++;
- } else {
- rc = -EIO;
- goto exit;
- }
- } else if (ddev->did) {
+ if (resp->len < size) {
rc = -EIO;
goto exit;
}
- if (DIGITAL_NFC_DEP_NAD_BIT_SET(pfb)) {
- rc = -EIO;
+ switch (DIGITAL_NFC_DEP_PFB_TYPE(dep_req->pfb)) {
+ case DIGITAL_NFC_DEP_PFB_I_PDU:
+ pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
+ ddev->curr_nfc_dep_pni = DIGITAL_NFC_DEP_PFB_PNI(dep_req->pfb);
+ break;
+ case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
+ pr_err("Received a ACK/NACK PDU\n");
+ rc = -EINVAL;
goto exit;
- }
-
- if (size > resp->len) {
- rc = -EIO;
+ case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
+ pr_err("Received a SUPERVISOR PDU\n");
+ rc = -EINVAL;
goto exit;
}
skb_pull(resp, size);
- switch (DIGITAL_NFC_DEP_PFB_TYPE(pfb)) {
- case DIGITAL_NFC_DEP_PFB_I_PDU:
- pr_debug("DIGITAL_NFC_DEP_PFB_I_PDU\n");
-
- if ((ddev->atn_count && (DIGITAL_NFC_DEP_PFB_PNI(pfb - 1) !=
- ddev->curr_nfc_dep_pni)) ||
- (DIGITAL_NFC_DEP_PFB_PNI(pfb) != ddev->curr_nfc_dep_pni)) {
- PROTOCOL_ERR("14.12.3.4");
- rc = -EIO;
- goto exit;
- }
-
- if (ddev->atn_count) {
- ddev->atn_count = 0;
-
- rc = digital_tg_send_saved_skb(ddev);
- if (rc)
- goto exit;
-
- return;
- }
-
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
-
- resp = digital_recv_dep_data_gather(ddev, pfb, resp,
- digital_tg_send_ack, NULL);
- if (IS_ERR(resp)) {
- rc = PTR_ERR(resp);
- resp = NULL;
- goto exit;
- }
-
- /* If resp is NULL then we're still chaining so return and
- * wait for the next part of the PDU. Else, the PDU is
- * complete so pass it up.
- */
- if (!resp)
- return;
-
- rc = 0;
- break;
- case DIGITAL_NFC_DEP_PFB_ACK_NACK_PDU:
- if (!DIGITAL_NFC_DEP_NACK_BIT_SET(pfb)) { /* ACK */
- if ((ddev->atn_count &&
- (DIGITAL_NFC_DEP_PFB_PNI(pfb - 1) !=
- ddev->curr_nfc_dep_pni)) ||
- (DIGITAL_NFC_DEP_PFB_PNI(pfb) !=
- ddev->curr_nfc_dep_pni) ||
- !ddev->chaining_skb || !ddev->saved_skb) {
- rc = -EIO;
- goto exit;
- }
-
- if (ddev->atn_count) {
- ddev->atn_count = 0;
-
- rc = digital_tg_send_saved_skb(ddev);
- if (rc)
- goto exit;
-
- return;
- }
-
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
-
- rc = digital_tg_send_dep_res(ddev, ddev->chaining_skb);
- if (rc)
- goto exit;
- } else { /* NACK */
- if ((DIGITAL_NFC_DEP_PFB_PNI(pfb + 1) !=
- ddev->curr_nfc_dep_pni) ||
- !ddev->saved_skb) {
- rc = -EIO;
- goto exit;
- }
-
- ddev->atn_count = 0;
-
- rc = digital_tg_send_saved_skb(ddev);
- if (rc) {
- kfree_skb(ddev->saved_skb);
- goto exit;
- }
- }
-
- return;
- case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU:
- if (DIGITAL_NFC_DEP_PFB_IS_TIMEOUT(pfb)) {
- rc = -EINVAL;
- goto exit;
- }
-
- rc = digital_tg_send_atn(ddev);
- if (rc)
- goto exit;
-
- ddev->atn_count++;
-
- kfree_skb(resp);
- return;
- }
-
rc = nfc_tm_data_received(ddev->nfc_dev, resp);
exit:
- kfree_skb(ddev->chaining_skb);
- ddev->chaining_skb = NULL;
-
- ddev->atn_count = 0;
-
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
-
if (rc)
kfree_skb(resp);
}
@@ -1204,54 +576,20 @@
int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb)
{
struct digital_dep_req_res *dep_res;
- struct sk_buff *chaining_skb, *tmp_skb;
- int rc;
skb_push(skb, sizeof(struct digital_dep_req_res));
-
dep_res = (struct digital_dep_req_res *)skb->data;
dep_res->dir = DIGITAL_NFC_DEP_FRAME_DIR_IN;
dep_res->cmd = DIGITAL_CMD_DEP_RES;
dep_res->pfb = ddev->curr_nfc_dep_pni;
- if (ddev->did) {
- dep_res->pfb |= DIGITAL_NFC_DEP_PFB_DID_BIT;
+ digital_skb_push_dep_sod(ddev, skb);
- memcpy(skb_put(skb, sizeof(ddev->did)), &ddev->did,
- sizeof(ddev->did));
- }
+ ddev->skb_add_crc(skb);
- ddev->curr_nfc_dep_pni =
- DIGITAL_NFC_DEP_PFB_PNI(ddev->curr_nfc_dep_pni + 1);
-
- chaining_skb = ddev->chaining_skb;
-
- tmp_skb = digital_send_dep_data_prep(ddev, skb, dep_res, NULL);
- if (IS_ERR(tmp_skb))
- return PTR_ERR(tmp_skb);
-
- digital_skb_push_dep_sod(ddev, tmp_skb);
-
- ddev->skb_add_crc(tmp_skb);
-
- ddev->saved_skb = skb_get(tmp_skb);
- ddev->saved_skb_len = tmp_skb->len;
-
- rc = digital_tg_send_cmd(ddev, tmp_skb, 1500, digital_tg_recv_dep_req,
- NULL);
- if (rc) {
- if (tmp_skb != skb)
- kfree_skb(tmp_skb);
-
- kfree_skb(chaining_skb);
- ddev->chaining_skb = NULL;
-
- kfree_skb(ddev->saved_skb);
- ddev->saved_skb = NULL;
- }
-
- return rc;
+ return digital_tg_send_cmd(ddev, skb, 1500, digital_tg_recv_dep_req,
+ NULL);
}
static void digital_tg_send_psl_res_complete(struct nfc_digital_dev *ddev,
@@ -1294,10 +632,9 @@
ddev->skb_add_crc(skb);
- ddev->curr_nfc_dep_pni = 0;
-
rc = digital_tg_send_cmd(ddev, skb, 0, digital_tg_send_psl_res_complete,
(void *)(unsigned long)rf_tech);
+
if (rc)
kfree_skb(skb);
@@ -1310,7 +647,7 @@
int rc;
struct digital_psl_req *psl_req;
u8 rf_tech;
- u8 dsi, payload_size, payload_bits;
+ u8 dsi;
if (IS_ERR(resp)) {
rc = PTR_ERR(resp);
@@ -1355,18 +692,6 @@
goto exit;
}
- payload_bits = DIGITAL_PAYLOAD_FSL_TO_BITS(psl_req->fsl);
- payload_size = digital_payload_bits_to_size(payload_bits);
-
- if (!payload_size || (payload_size > min(ddev->local_payload_max,
- ddev->remote_payload_max))) {
- rc = -EINVAL;
- goto exit;
- }
-
- ddev->local_payload_max = payload_size;
- ddev->remote_payload_max = payload_size;
-
rc = digital_tg_send_psl_res(ddev, psl_req->did, rf_tech);
exit:
@@ -1387,8 +712,6 @@
if (resp->data[0] == DIGITAL_NFC_DEP_NFCA_SOD_SB)
offset++;
- ddev->atn_count = 0;
-
if (resp->data[offset] == DIGITAL_CMD_PSL_REQ)
digital_tg_recv_psl_req(ddev, arg, resp);
else
@@ -1400,7 +723,7 @@
{
struct digital_atr_res *atr_res;
struct sk_buff *skb;
- u8 *gb, payload_bits;
+ u8 *gb;
size_t gb_len;
int rc;
@@ -1421,11 +744,7 @@
atr_res->cmd = DIGITAL_CMD_ATR_RES;
memcpy(atr_res->nfcid3, atr_req->nfcid3, sizeof(atr_req->nfcid3));
atr_res->to = 8;
-
- ddev->local_payload_max = DIGITAL_PAYLOAD_SIZE_MAX;
- payload_bits = digital_payload_size_to_bits(ddev->local_payload_max);
- atr_res->pp = DIGITAL_PAYLOAD_BITS_TO_PP(payload_bits);
-
+ atr_res->pp = DIGITAL_LR_BITS_PAYLOAD_SIZE_254B;
if (gb_len) {
skb_put(skb, gb_len);
@@ -1437,12 +756,12 @@
ddev->skb_add_crc(skb);
- ddev->curr_nfc_dep_pni = 0;
-
rc = digital_tg_send_cmd(ddev, skb, 999,
digital_tg_send_atr_res_complete, NULL);
- if (rc)
+ if (rc) {
kfree_skb(skb);
+ return rc;
+ }
return rc;
}
@@ -1453,7 +772,7 @@
int rc;
struct digital_atr_req *atr_req;
size_t gb_len, min_size;
- u8 poll_tech_count, payload_bits;
+ u8 poll_tech_count;
if (IS_ERR(resp)) {
rc = PTR_ERR(resp);
@@ -1496,22 +815,11 @@
atr_req = (struct digital_atr_req *)resp->data;
if (atr_req->dir != DIGITAL_NFC_DEP_FRAME_DIR_OUT ||
- atr_req->cmd != DIGITAL_CMD_ATR_REQ ||
- atr_req->did > DIGITAL_DID_MAX) {
+ atr_req->cmd != DIGITAL_CMD_ATR_REQ) {
rc = -EINVAL;
goto exit;
}
- payload_bits = DIGITAL_PAYLOAD_PP_TO_BITS(atr_req->pp);
- ddev->remote_payload_max = digital_payload_bits_to_size(payload_bits);
-
- if (!ddev->remote_payload_max) {
- rc = -EINVAL;
- goto exit;
- }
-
- ddev->did = atr_req->did;
-
rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING,
NFC_DIGITAL_FRAMING_NFC_DEP_ACTIVATED);
if (rc)
diff --git a/net/nfc/hci/command.c b/net/nfc/hci/command.c
index 91df487..677d24b 100644
--- a/net/nfc/hci/command.c
+++ b/net/nfc/hci/command.c
@@ -345,9 +345,6 @@
pr_debug("\n");
- if (hdev->gate2pipe[dest_gate] == NFC_HCI_DO_NOT_CREATE_PIPE)
- return 0;
-
if (hdev->gate2pipe[dest_gate] != NFC_HCI_INVALID_PIPE)
return -EADDRINUSE;
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c
index ef50e77..1177082 100644
--- a/net/nfc/hci/core.c
+++ b/net/nfc/hci/core.c
@@ -167,48 +167,6 @@
void nfc_hci_cmd_received(struct nfc_hci_dev *hdev, u8 pipe, u8 cmd,
struct sk_buff *skb)
{
- int r = 0;
- u8 gate = nfc_hci_pipe2gate(hdev, pipe);
- u8 local_gate, new_pipe;
- u8 gate_opened = 0x00;
-
- pr_debug("from gate %x pipe %x cmd %x\n", gate, pipe, cmd);
-
- switch (cmd) {
- case NFC_HCI_ADM_NOTIFY_PIPE_CREATED:
- if (skb->len != 5) {
- r = -EPROTO;
- break;
- }
-
- local_gate = skb->data[3];
- new_pipe = skb->data[4];
- nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0);
-
- /* save the new created pipe and bind with local gate,
- * the description for skb->data[3] is destination gate id
- * but since we received this cmd from host controller, we
- * are the destination and it is our local gate
- */
- hdev->gate2pipe[local_gate] = new_pipe;
- break;
- case NFC_HCI_ANY_OPEN_PIPE:
- /* if the pipe is already created, we allow remote host to
- * open it
- */
- if (gate != 0xff)
- nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK,
- &gate_opened, 1);
- break;
- case NFC_HCI_ADM_NOTIFY_ALL_PIPE_CLEARED:
- nfc_hci_send_response(hdev, gate, NFC_HCI_ANY_OK, NULL, 0);
- break;
- default:
- pr_info("Discarded unknown cmd %x to gate %x\n", cmd, gate);
- r = -EINVAL;
- break;
- }
-
kfree_skb(skb);
}
@@ -759,19 +717,6 @@
return 0;
}
-static int hci_se_io(struct nfc_dev *nfc_dev, u32 se_idx,
- u8 *apdu, size_t apdu_length,
- se_io_cb_t cb, void *cb_context)
-{
- struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev);
-
- if (hdev->ops->se_io)
- return hdev->ops->se_io(hdev, se_idx, apdu,
- apdu_length, cb, cb_context);
-
- return 0;
-}
-
static void nfc_hci_failure(struct nfc_hci_dev *hdev, int err)
{
mutex_lock(&hdev->msg_tx_mutex);
@@ -885,7 +830,6 @@
.discover_se = hci_discover_se,
.enable_se = hci_enable_se,
.disable_se = hci_disable_se,
- .se_io = hci_se_io,
};
struct nfc_hci_dev *nfc_hci_allocate_device(struct nfc_hci_ops *ops,
diff --git a/net/nfc/llcp_commands.c b/net/nfc/llcp_commands.c
index 3621a90..a3ad69a 100644
--- a/net/nfc/llcp_commands.c
+++ b/net/nfc/llcp_commands.c
@@ -401,8 +401,7 @@
u8 *miux_tlv = NULL, miux_tlv_length;
u8 *rw_tlv = NULL, rw_tlv_length, rw;
int err;
- u16 size = 0;
- __be16 miux;
+ u16 size = 0, miux;
pr_debug("Sending CONNECT\n");
@@ -466,8 +465,7 @@
u8 *miux_tlv = NULL, miux_tlv_length;
u8 *rw_tlv = NULL, rw_tlv_length, rw;
int err;
- u16 size = 0;
- __be16 miux;
+ u16 size = 0, miux;
pr_debug("Sending CC\n");
@@ -667,7 +665,7 @@
if (msg_data == NULL)
return -ENOMEM;
- if (memcpy_from_msg(msg_data, msg, len)) {
+ if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
kfree(msg_data);
return -EFAULT;
}
@@ -733,7 +731,7 @@
if (msg_data == NULL)
return -ENOMEM;
- if (memcpy_from_msg(msg_data, msg, len)) {
+ if (memcpy_fromiovec(msg_data, msg->msg_iov, len)) {
kfree(msg_data);
return -EFAULT;
}
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c
index ecf84de..5d9a9d8 100644
--- a/net/nfc/llcp_core.c
+++ b/net/nfc/llcp_core.c
@@ -1,6 +1,5 @@
/*
* Copyright (C) 2011 Intel Corporation. All rights reserved.
- * Copyright (C) 2014 Marvell International Ltd.
*
* 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
@@ -1516,10 +1515,8 @@
struct nfc_llcp_local *local;
local = nfc_llcp_find_local(dev);
- if (local == NULL) {
- kfree_skb(skb);
+ if (local == NULL)
return -ENODEV;
- }
__nfc_llcp_recv(local, skb);
diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c
index e181e29..51f077a 100644
--- a/net/nfc/llcp_sock.c
+++ b/net/nfc/llcp_sock.c
@@ -524,13 +524,13 @@
static inline unsigned int llcp_accept_poll(struct sock *parent)
{
- struct nfc_llcp_sock *llcp_sock, *parent_sock;
+ struct nfc_llcp_sock *llcp_sock, *n, *parent_sock;
struct sock *sk;
parent_sock = nfc_llcp_sock(parent);
- list_for_each_entry(llcp_sock, &parent_sock->accept_queue,
- accept_queue) {
+ list_for_each_entry_safe(llcp_sock, n, &parent_sock->accept_queue,
+ accept_queue) {
sk = &llcp_sock->sk;
if (sk->sk_state == LLCP_CONNECTED)
@@ -832,7 +832,7 @@
copied = min_t(unsigned int, rlen, len);
cskb = skb;
- if (skb_copy_datagram_msg(cskb, 0, msg, copied)) {
+ if (skb_copy_datagram_iovec(cskb, 0, msg->msg_iov, copied)) {
if (!(flags & MSG_PEEK))
skb_queue_head(&sk->sk_receive_queue, skb);
return -EFAULT;
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c
index 51feb5e..90b16cb 100644
--- a/net/nfc/nci/core.c
+++ b/net/nfc/nci/core.c
@@ -3,7 +3,6 @@
* NFC Controller (NFCC) and a Device Host (DH).
*
* Copyright (C) 2011 Texas Instruments, Inc.
- * Copyright (C) 2014 Marvell International Ltd.
*
* Written by Ilan Elias <ilane@ti.com>
*
@@ -197,24 +196,18 @@
nci_send_cmd(ndev, NCI_OP_CORE_SET_CONFIG_CMD, (3 + param->len), &cmd);
}
-struct nci_rf_discover_param {
- __u32 im_protocols;
- __u32 tm_protocols;
-};
-
static void nci_rf_discover_req(struct nci_dev *ndev, unsigned long opt)
{
- struct nci_rf_discover_param *param =
- (struct nci_rf_discover_param *)opt;
struct nci_rf_disc_cmd cmd;
+ __u32 protocols = opt;
cmd.num_disc_configs = 0;
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (param->im_protocols & NFC_PROTO_JEWEL_MASK ||
- param->im_protocols & NFC_PROTO_MIFARE_MASK ||
- param->im_protocols & NFC_PROTO_ISO14443_MASK ||
- param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) {
+ (protocols & NFC_PROTO_JEWEL_MASK ||
+ protocols & NFC_PROTO_MIFARE_MASK ||
+ protocols & NFC_PROTO_ISO14443_MASK ||
+ protocols & NFC_PROTO_NFC_DEP_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_A_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -222,7 +215,7 @@
}
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (param->im_protocols & NFC_PROTO_ISO14443_B_MASK)) {
+ (protocols & NFC_PROTO_ISO14443_B_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_B_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -230,8 +223,8 @@
}
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (param->im_protocols & NFC_PROTO_FELICA_MASK ||
- param->im_protocols & NFC_PROTO_NFC_DEP_MASK)) {
+ (protocols & NFC_PROTO_FELICA_MASK ||
+ protocols & NFC_PROTO_NFC_DEP_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_F_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
@@ -239,25 +232,13 @@
}
if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS) &&
- (param->im_protocols & NFC_PROTO_ISO15693_MASK)) {
+ (protocols & NFC_PROTO_ISO15693_MASK)) {
cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
NCI_NFC_V_PASSIVE_POLL_MODE;
cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
cmd.num_disc_configs++;
}
- if ((cmd.num_disc_configs < NCI_MAX_NUM_RF_CONFIGS - 1) &&
- (param->tm_protocols & NFC_PROTO_NFC_DEP_MASK)) {
- cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
- NCI_NFC_A_PASSIVE_LISTEN_MODE;
- cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
- cmd.num_disc_configs++;
- cmd.disc_configs[cmd.num_disc_configs].rf_tech_and_mode =
- NCI_NFC_F_PASSIVE_LISTEN_MODE;
- cmd.disc_configs[cmd.num_disc_configs].frequency = 1;
- cmd.num_disc_configs++;
- }
-
nci_send_cmd(ndev, NCI_OP_RF_DISCOVER_CMD,
(1 + (cmd.num_disc_configs * sizeof(struct disc_config))),
&cmd);
@@ -299,7 +280,7 @@
{
struct nci_rf_deactivate_cmd cmd;
- cmd.type = opt;
+ cmd.type = NCI_DEACTIVATE_TYPE_IDLE_MODE;
nci_send_cmd(ndev, NCI_OP_RF_DEACTIVATE_CMD,
sizeof(struct nci_rf_deactivate_cmd), &cmd);
@@ -460,7 +441,6 @@
{
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
struct nci_set_config_param param;
- int rc;
param.val = nfc_get_local_general_bytes(nfc_dev, ¶m.len);
if ((param.val == NULL) || (param.len == 0))
@@ -471,45 +451,14 @@
param.id = NCI_PN_ATR_REQ_GEN_BYTES;
- rc = nci_request(ndev, nci_set_config_req, (unsigned long)¶m,
- msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
- if (rc)
- return rc;
-
- param.id = NCI_LN_ATR_RES_GEN_BYTES;
-
return nci_request(ndev, nci_set_config_req, (unsigned long)¶m,
msecs_to_jiffies(NCI_SET_CONFIG_TIMEOUT));
}
-static int nci_set_listen_parameters(struct nfc_dev *nfc_dev)
-{
- struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
- int rc;
- __u8 val;
-
- val = NCI_LA_SEL_INFO_NFC_DEP_MASK;
-
- rc = nci_set_config(ndev, NCI_LA_SEL_INFO, 1, &val);
- if (rc)
- return rc;
-
- val = NCI_LF_PROTOCOL_TYPE_NFC_DEP_MASK;
-
- rc = nci_set_config(ndev, NCI_LF_PROTOCOL_TYPE, 1, &val);
- if (rc)
- return rc;
-
- val = NCI_LF_CON_BITR_F_212 | NCI_LF_CON_BITR_F_424;
-
- return nci_set_config(ndev, NCI_LF_CON_BITR_F, 1, &val);
-}
-
static int nci_start_poll(struct nfc_dev *nfc_dev,
__u32 im_protocols, __u32 tm_protocols)
{
struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
- struct nci_rf_discover_param param;
int rc;
if ((atomic_read(&ndev->state) == NCI_DISCOVERY) ||
@@ -527,14 +476,13 @@
(atomic_read(&ndev->state) == NCI_POLL_ACTIVE)) {
pr_debug("target active or w4 select, implicitly deactivate\n");
- rc = nci_request(ndev, nci_rf_deactivate_req,
- NCI_DEACTIVATE_TYPE_IDLE_MODE,
+ rc = nci_request(ndev, nci_rf_deactivate_req, 0,
msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
if (rc)
return -EBUSY;
}
- if ((im_protocols | tm_protocols) & NFC_PROTO_NFC_DEP_MASK) {
+ if (im_protocols & NFC_PROTO_NFC_DEP_MASK) {
rc = nci_set_local_general_bytes(nfc_dev);
if (rc) {
pr_err("failed to set local general bytes\n");
@@ -542,15 +490,7 @@
}
}
- if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) {
- rc = nci_set_listen_parameters(nfc_dev);
- if (rc)
- pr_err("failed to set listen parameters\n");
- }
-
- param.im_protocols = im_protocols;
- param.tm_protocols = tm_protocols;
- rc = nci_request(ndev, nci_rf_discover_req, (unsigned long)¶m,
+ rc = nci_request(ndev, nci_rf_discover_req, im_protocols,
msecs_to_jiffies(NCI_RF_DISC_TIMEOUT));
if (!rc)
@@ -569,7 +509,7 @@
return;
}
- nci_request(ndev, nci_rf_deactivate_req, NCI_DEACTIVATE_TYPE_IDLE_MODE,
+ nci_request(ndev, nci_rf_deactivate_req, 0,
msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
}
@@ -654,8 +594,7 @@
ndev->target_active_prot = 0;
if (atomic_read(&ndev->state) == NCI_POLL_ACTIVE) {
- nci_request(ndev, nci_rf_deactivate_req,
- NCI_DEACTIVATE_TYPE_SLEEP_MODE,
+ nci_request(ndev, nci_rf_deactivate_req, 0,
msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
}
}
@@ -683,24 +622,9 @@
static int nci_dep_link_down(struct nfc_dev *nfc_dev)
{
- struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
- int rc;
-
pr_debug("entry\n");
- if (nfc_dev->rf_mode == NFC_RF_INITIATOR) {
- nci_deactivate_target(nfc_dev, NULL);
- } else {
- if (atomic_read(&ndev->state) == NCI_LISTEN_ACTIVE ||
- atomic_read(&ndev->state) == NCI_DISCOVERY) {
- nci_request(ndev, nci_rf_deactivate_req, 0,
- msecs_to_jiffies(NCI_RF_DEACTIVATE_TIMEOUT));
- }
-
- rc = nfc_tm_deactivated(nfc_dev);
- if (rc)
- pr_err("error when signaling tm deactivation\n");
- }
+ nci_deactivate_target(nfc_dev, NULL);
return 0;
}
@@ -734,58 +658,18 @@
return rc;
}
-static int nci_tm_send(struct nfc_dev *nfc_dev, struct sk_buff *skb)
-{
- struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
- int rc;
-
- rc = nci_send_data(ndev, NCI_STATIC_RF_CONN_ID, skb);
- if (rc)
- pr_err("unable to send data\n");
-
- return rc;
-}
-
static int nci_enable_se(struct nfc_dev *nfc_dev, u32 se_idx)
{
- struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-
- if (ndev->ops->enable_se)
- return ndev->ops->enable_se(ndev, se_idx);
-
return 0;
}
static int nci_disable_se(struct nfc_dev *nfc_dev, u32 se_idx)
{
- struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-
- if (ndev->ops->disable_se)
- return ndev->ops->disable_se(ndev, se_idx);
-
return 0;
}
static int nci_discover_se(struct nfc_dev *nfc_dev)
{
- struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-
- if (ndev->ops->discover_se)
- return ndev->ops->discover_se(ndev);
-
- return 0;
-}
-
-static int nci_se_io(struct nfc_dev *nfc_dev, u32 se_idx,
- u8 *apdu, size_t apdu_length,
- se_io_cb_t cb, void *cb_context)
-{
- struct nci_dev *ndev = nfc_get_drvdata(nfc_dev);
-
- if (ndev->ops->se_io)
- return ndev->ops->se_io(ndev, se_idx, apdu,
- apdu_length, cb, cb_context);
-
return 0;
}
@@ -799,11 +683,9 @@
.activate_target = nci_activate_target,
.deactivate_target = nci_deactivate_target,
.im_transceive = nci_transceive,
- .tm_send = nci_tm_send,
.enable_se = nci_enable_se,
.disable_se = nci_disable_se,
.discover_se = nci_discover_se,
- .se_io = nci_se_io,
};
/* ---- Interface to NCI drivers ---- */
diff --git a/net/nfc/nci/data.c b/net/nfc/nci/data.c
index a2de2a8..427ef2c 100644
--- a/net/nfc/nci/data.c
+++ b/net/nfc/nci/data.c
@@ -3,7 +3,6 @@
* NFC Controller (NFCC) and a Device Host (DH).
*
* Copyright (C) 2011 Texas Instruments, Inc.
- * Copyright (C) 2014 Marvell International Ltd.
*
* Written by Ilan Elias <ilane@ti.com>
*
@@ -185,16 +184,11 @@
static void nci_add_rx_data_frag(struct nci_dev *ndev,
struct sk_buff *skb,
- __u8 pbf, __u8 status)
+ __u8 pbf)
{
int reassembly_len;
int err = 0;
- if (status) {
- err = status;
- goto exit;
- }
-
if (ndev->rx_data_reassembly) {
reassembly_len = ndev->rx_data_reassembly->len;
@@ -229,24 +223,13 @@
}
exit:
- if (ndev->nfc_dev->rf_mode == NFC_RF_INITIATOR) {
- nci_data_exchange_complete(ndev, skb, err);
- } else if (ndev->nfc_dev->rf_mode == NFC_RF_TARGET) {
- /* Data received in Target mode, forward to nfc core */
- err = nfc_tm_data_received(ndev->nfc_dev, skb);
- if (err)
- pr_err("unable to handle received data\n");
- } else {
- pr_err("rf mode unknown\n");
- kfree_skb(skb);
- }
+ nci_data_exchange_complete(ndev, skb, err);
}
/* Rx Data packet */
void nci_rx_data_packet(struct nci_dev *ndev, struct sk_buff *skb)
{
__u8 pbf = nci_pbf(skb->data);
- __u8 status = 0;
pr_debug("len %d\n", skb->len);
@@ -264,9 +247,8 @@
ndev->target_active_prot == NFC_PROTO_ISO15693) {
/* frame I/F => remove the status byte */
pr_debug("frame I/F => remove the status byte\n");
- status = skb->data[skb->len - 1];
skb_trim(skb, (skb->len - 1));
}
- nci_add_rx_data_frag(ndev, skb, pbf, nci_to_errno(status));
+ nci_add_rx_data_frag(ndev, skb, pbf);
}
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c
index 22e453c..205b35f 100644
--- a/net/nfc/nci/ntf.c
+++ b/net/nfc/nci/ntf.c
@@ -103,7 +103,7 @@
struct rf_tech_specific_params_nfca_poll *nfca_poll,
__u8 *data)
{
- nfca_poll->sens_res = __le16_to_cpu(*((__le16 *)data));
+ nfca_poll->sens_res = __le16_to_cpu(*((__u16 *)data));
data += 2;
nfca_poll->nfcid1_len = min_t(__u8, *data++, NFC_NFCID1_MAXSIZE);
@@ -167,19 +167,7 @@
return data;
}
-static __u8 *nci_extract_rf_params_nfcf_passive_listen(struct nci_dev *ndev,
- struct rf_tech_specific_params_nfcf_listen *nfcf_listen,
- __u8 *data)
-{
- nfcf_listen->local_nfcid2_len = min_t(__u8, *data++,
- NFC_NFCID2_MAXSIZE);
- memcpy(nfcf_listen->local_nfcid2, data, nfcf_listen->local_nfcid2_len);
- data += nfcf_listen->local_nfcid2_len;
-
- return data;
-}
-
-static __u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol)
+__u32 nci_get_prop_rf_protocol(struct nci_dev *ndev, __u8 rf_protocol)
{
if (ndev->ops->get_rfprotocol)
return ndev->ops->get_rfprotocol(ndev, rf_protocol);
@@ -413,29 +401,17 @@
struct nci_rf_intf_activated_ntf *ntf, __u8 *data)
{
struct activation_params_poll_nfc_dep *poll;
- struct activation_params_listen_nfc_dep *listen;
switch (ntf->activation_rf_tech_and_mode) {
case NCI_NFC_A_PASSIVE_POLL_MODE:
case NCI_NFC_F_PASSIVE_POLL_MODE:
poll = &ntf->activation_params.poll_nfc_dep;
- poll->atr_res_len = min_t(__u8, *data++,
- NFC_ATR_RES_MAXSIZE - 2);
+ poll->atr_res_len = min_t(__u8, *data++, 63);
pr_debug("atr_res_len %d\n", poll->atr_res_len);
if (poll->atr_res_len > 0)
memcpy(poll->atr_res, data, poll->atr_res_len);
break;
- case NCI_NFC_A_PASSIVE_LISTEN_MODE:
- case NCI_NFC_F_PASSIVE_LISTEN_MODE:
- listen = &ntf->activation_params.listen_nfc_dep;
- listen->atr_req_len = min_t(__u8, *data++,
- NFC_ATR_REQ_MAXSIZE - 2);
- pr_debug("atr_req_len %d\n", listen->atr_req_len);
- if (listen->atr_req_len > 0)
- memcpy(listen->atr_req, data, listen->atr_req_len);
- break;
-
default:
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
ntf->activation_rf_tech_and_mode);
@@ -468,48 +444,6 @@
nfc_targets_found(ndev->nfc_dev, ndev->targets, ndev->n_targets);
}
-static int nci_store_general_bytes_nfc_dep(struct nci_dev *ndev,
- struct nci_rf_intf_activated_ntf *ntf)
-{
- ndev->remote_gb_len = 0;
-
- if (ntf->activation_params_len <= 0)
- return NCI_STATUS_OK;
-
- switch (ntf->activation_rf_tech_and_mode) {
- case NCI_NFC_A_PASSIVE_POLL_MODE:
- case NCI_NFC_F_PASSIVE_POLL_MODE:
- ndev->remote_gb_len = min_t(__u8,
- (ntf->activation_params.poll_nfc_dep.atr_res_len
- - NFC_ATR_RES_GT_OFFSET),
- NFC_ATR_RES_GB_MAXSIZE);
- memcpy(ndev->remote_gb,
- (ntf->activation_params.poll_nfc_dep.atr_res
- + NFC_ATR_RES_GT_OFFSET),
- ndev->remote_gb_len);
- break;
-
- case NCI_NFC_A_PASSIVE_LISTEN_MODE:
- case NCI_NFC_F_PASSIVE_LISTEN_MODE:
- ndev->remote_gb_len = min_t(__u8,
- (ntf->activation_params.listen_nfc_dep.atr_req_len
- - NFC_ATR_REQ_GT_OFFSET),
- NFC_ATR_REQ_GB_MAXSIZE);
- memcpy(ndev->remote_gb,
- (ntf->activation_params.listen_nfc_dep.atr_req
- + NFC_ATR_REQ_GT_OFFSET),
- ndev->remote_gb_len);
- break;
-
- default:
- pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
- ntf->activation_rf_tech_and_mode);
- return NCI_STATUS_RF_PROTOCOL_ERROR;
- }
-
- return NCI_STATUS_OK;
-}
-
static void nci_rf_intf_activated_ntf_packet(struct nci_dev *ndev,
struct sk_buff *skb)
{
@@ -559,16 +493,6 @@
&(ntf.rf_tech_specific_params.nfcv_poll), data);
break;
- case NCI_NFC_A_PASSIVE_LISTEN_MODE:
- /* no RF technology specific parameters */
- break;
-
- case NCI_NFC_F_PASSIVE_LISTEN_MODE:
- data = nci_extract_rf_params_nfcf_passive_listen(ndev,
- &(ntf.rf_tech_specific_params.nfcf_listen),
- data);
- break;
-
default:
pr_err("unsupported activation_rf_tech_and_mode 0x%x\n",
ntf.activation_rf_tech_and_mode);
@@ -622,39 +546,32 @@
/* store general bytes to be reported later in dep_link_up */
if (ntf.rf_interface == NCI_RF_INTERFACE_NFC_DEP) {
- err = nci_store_general_bytes_nfc_dep(ndev, &ntf);
- if (err != NCI_STATUS_OK)
- pr_err("unable to store general bytes\n");
+ ndev->remote_gb_len = 0;
+
+ if (ntf.activation_params_len > 0) {
+ /* ATR_RES general bytes at offset 15 */
+ ndev->remote_gb_len = min_t(__u8,
+ (ntf.activation_params
+ .poll_nfc_dep.atr_res_len
+ - NFC_ATR_RES_GT_OFFSET),
+ NFC_MAX_GT_LEN);
+ memcpy(ndev->remote_gb,
+ (ntf.activation_params.poll_nfc_dep
+ .atr_res + NFC_ATR_RES_GT_OFFSET),
+ ndev->remote_gb_len);
+ }
}
}
- if (!(ntf.activation_rf_tech_and_mode & NCI_RF_TECH_MODE_LISTEN_MASK)) {
- /* Poll mode */
- if (atomic_read(&ndev->state) == NCI_DISCOVERY) {
- /* A single target was found and activated
- * automatically */
- atomic_set(&ndev->state, NCI_POLL_ACTIVE);
- if (err == NCI_STATUS_OK)
- nci_target_auto_activated(ndev, &ntf);
- } else { /* ndev->state == NCI_W4_HOST_SELECT */
- /* A selected target was activated, so complete the
- * request */
- atomic_set(&ndev->state, NCI_POLL_ACTIVE);
- nci_req_complete(ndev, err);
- }
- } else {
- /* Listen mode */
- atomic_set(&ndev->state, NCI_LISTEN_ACTIVE);
- if (err == NCI_STATUS_OK &&
- ntf.rf_protocol == NCI_RF_PROTOCOL_NFC_DEP) {
- err = nfc_tm_activated(ndev->nfc_dev,
- NFC_PROTO_NFC_DEP_MASK,
- NFC_COMM_PASSIVE,
- ndev->remote_gb,
- ndev->remote_gb_len);
- if (err != NCI_STATUS_OK)
- pr_err("error when signaling tm activation\n");
- }
+ if (atomic_read(&ndev->state) == NCI_DISCOVERY) {
+ /* A single target was found and activated automatically */
+ atomic_set(&ndev->state, NCI_POLL_ACTIVE);
+ if (err == NCI_STATUS_OK)
+ nci_target_auto_activated(ndev, &ntf);
+ } else { /* ndev->state == NCI_W4_HOST_SELECT */
+ /* A selected target was activated, so complete the request */
+ atomic_set(&ndev->state, NCI_POLL_ACTIVE);
+ nci_req_complete(ndev, err);
}
}
@@ -678,21 +595,8 @@
if (test_bit(NCI_DATA_EXCHANGE, &ndev->flags))
nci_data_exchange_complete(ndev, NULL, -EIO);
- switch (ntf->type) {
- case NCI_DEACTIVATE_TYPE_IDLE_MODE:
- nci_clear_target_list(ndev);
- atomic_set(&ndev->state, NCI_IDLE);
- break;
- case NCI_DEACTIVATE_TYPE_SLEEP_MODE:
- case NCI_DEACTIVATE_TYPE_SLEEP_AF_MODE:
- atomic_set(&ndev->state, NCI_W4_HOST_SELECT);
- break;
- case NCI_DEACTIVATE_TYPE_DISCOVERY:
- nci_clear_target_list(ndev);
- atomic_set(&ndev->state, NCI_DISCOVERY);
- break;
- }
-
+ nci_clear_target_list(ndev);
+ atomic_set(&ndev->state, NCI_IDLE);
nci_req_complete(ndev, NCI_STATUS_OK);
}
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c
index 99c7065..f91cff1 100644
--- a/net/nfc/netlink.c
+++ b/net/nfc/netlink.c
@@ -813,31 +813,6 @@
return rc;
}
-static int nfc_genl_activate_target(struct sk_buff *skb, struct genl_info *info)
-{
- struct nfc_dev *dev;
- u32 device_idx, target_idx, protocol;
- int rc;
-
- if (!info->attrs[NFC_ATTR_DEVICE_INDEX])
- return -EINVAL;
-
- device_idx = nla_get_u32(info->attrs[NFC_ATTR_DEVICE_INDEX]);
-
- dev = nfc_get_device(device_idx);
- if (!dev)
- return -ENODEV;
-
- target_idx = nla_get_u32(info->attrs[NFC_ATTR_TARGET_INDEX]);
- protocol = nla_get_u32(info->attrs[NFC_ATTR_PROTOCOLS]);
-
- nfc_deactivate_target(dev, target_idx);
- rc = nfc_activate_target(dev, target_idx, protocol);
-
- nfc_put_device(dev);
- return 0;
-}
-
static int nfc_genl_dep_link_up(struct sk_buff *skb, struct genl_info *info)
{
struct nfc_dev *dev;
@@ -1314,51 +1289,6 @@
return 0;
}
-static int nfc_se_io(struct nfc_dev *dev, u32 se_idx,
- u8 *apdu, size_t apdu_length,
- se_io_cb_t cb, void *cb_context)
-{
- struct nfc_se *se;
- int rc;
-
- pr_debug("%s se index %d\n", dev_name(&dev->dev), se_idx);
-
- device_lock(&dev->dev);
-
- if (!device_is_registered(&dev->dev)) {
- rc = -ENODEV;
- goto error;
- }
-
- if (!dev->dev_up) {
- rc = -ENODEV;
- goto error;
- }
-
- if (!dev->ops->se_io) {
- rc = -EOPNOTSUPP;
- goto error;
- }
-
- se = nfc_find_se(dev, se_idx);
- if (!se) {
- rc = -EINVAL;
- goto error;
- }
-
- if (se->state != NFC_SE_ENABLED) {
- rc = -ENODEV;
- goto error;
- }
-
- rc = dev->ops->se_io(dev, se_idx, apdu,
- apdu_length, cb, cb_context);
-
-error:
- device_unlock(&dev->dev);
- return rc;
-}
-
struct se_io_ctx {
u32 dev_idx;
u32 se_idx;
@@ -1441,7 +1371,7 @@
ctx->dev_idx = dev_idx;
ctx->se_idx = se_idx;
- return nfc_se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx);
+ return dev->ops->se_io(dev, se_idx, apdu, apdu_len, se_io_cb, ctx);
}
static __genl_const struct genl_ops nfc_genl_ops[] = {
@@ -1529,11 +1459,6 @@
.doit = nfc_genl_se_io,
.policy = nfc_genl_policy,
},
- {
- .cmd = NFC_CMD_ACTIVATE_TARGET,
- .doit = nfc_genl_activate_target,
- .policy = nfc_genl_policy,
- },
};
diff --git a/net/nfc/rawsock.c b/net/nfc/rawsock.c
index 373e138..11c3544 100644
--- a/net/nfc/rawsock.c
+++ b/net/nfc/rawsock.c
@@ -231,7 +231,7 @@
if (skb == NULL)
return rc;
- rc = memcpy_from_msg(skb_put(skb, len), msg, len);
+ rc = memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len);
if (rc < 0) {
kfree_skb(skb);
return rc;
@@ -269,7 +269,7 @@
copied = len;
}
- rc = skb_copy_datagram_msg(skb, 0, msg, copied);
+ rc = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
skb_free_datagram(sk, skb);
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index bc4e435..b292436 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -158,7 +158,7 @@
Most distributions have a CRDA package. So if unsure, say N.
config CFG80211_WEXT
- bool
+ bool "cfg80211 wireless extensions compatibility"
depends on CFG80211
depends on WEXT_CORE
help
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index bbc27ab..7730221 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -10,7 +10,7 @@
obj-$(CONFIG_WEXT_PRIV) += wext-priv.o
cfg80211-y += core.o sysfs.o radiotap.o util.o reg.o scan.o nl80211.o
-cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o
+cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o
cfg80211-$(CPTCFG_CFG80211_DEBUGFS) += debugfs.o
cfg80211-$(CPTCFG_CFG80211_WEXT) += wext-compat.o wext-sme.o
cfg80211-$(CPTCFG_CFG80211_INTERNAL_REGDB) += regdb.o
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 7f9fa4d..8f21d4e 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -115,7 +115,7 @@
EXPORT_SYMBOL(cfg80211_chandef_valid);
static void chandef_primary_freqs(const struct cfg80211_chan_def *c,
- u32 *pri40, u32 *pri80)
+ int *pri40, int *pri80)
{
int tmp;
@@ -366,7 +366,6 @@
break;
case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP_VLAN:
@@ -603,7 +602,7 @@
{
struct ieee80211_sta_ht_cap *ht_cap;
struct ieee80211_sta_vht_cap *vht_cap;
- u32 width, control_freq, cap;
+ u32 width, control_freq;
if (WARN_ON(!cfg80211_chandef_valid(chandef)))
return false;
@@ -643,8 +642,7 @@
return false;
break;
case NL80211_CHAN_WIDTH_80P80:
- cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
- if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+ if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))
return false;
case NL80211_CHAN_WIDTH_80:
if (!vht_cap->vht_supported)
@@ -655,9 +653,7 @@
case NL80211_CHAN_WIDTH_160:
if (!vht_cap->vht_supported)
return false;
- cap = vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK;
- if (cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
- cap != IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)
+ if (!(vht_cap->cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ))
return false;
prohibited_flags |= IEEE80211_CHAN_NO_160MHZ;
width = 160;
@@ -896,13 +892,6 @@
*radar_detect |= BIT(wdev->chandef.width);
}
return;
- case NL80211_IFTYPE_OCB:
- if (wdev->chandef.chan) {
- *chan = wdev->chandef.chan;
- *chanmode = CHAN_MODE_SHARED;
- return;
- }
- break;
case NL80211_IFTYPE_MONITOR:
case NL80211_IFTYPE_AP_VLAN:
case NL80211_IFTYPE_WDS:
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 073bfe4..45d0435 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -86,11 +86,11 @@
return &rdev->wiphy;
}
-static int cfg80211_dev_check_name(struct cfg80211_registered_device *rdev,
- const char *newname)
+int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
+ char *newname)
{
struct cfg80211_registered_device *rdev2;
- int wiphy_idx, taken = -1, digits;
+ int wiphy_idx, taken = -1, result, digits;
ASSERT_RTNL();
@@ -109,28 +109,15 @@
return -EINVAL;
}
- /* Ensure another device does not already have this name. */
- list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
- if (strcmp(newname, wiphy_name(&rdev2->wiphy)) == 0)
- return -EINVAL;
-
- return 0;
-}
-
-int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
- char *newname)
-{
- int result;
-
- ASSERT_RTNL();
/* Ignore nop renames */
- if (strcmp(newname, wiphy_name(&rdev->wiphy)) == 0)
+ if (strcmp(newname, dev_name(&rdev->wiphy.dev)) == 0)
return 0;
- result = cfg80211_dev_check_name(rdev, newname);
- if (result < 0)
- return result;
+ /* Ensure another device does not already have this name. */
+ list_for_each_entry(rdev2, &cfg80211_rdev_list, list)
+ if (strcmp(newname, dev_name(&rdev2->wiphy.dev)) == 0)
+ return -EINVAL;
result = device_rename(&rdev->wiphy.dev, newname);
if (result)
@@ -322,8 +309,7 @@
/* exported functions */
-struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv,
- const char *requested_name)
+struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
{
static atomic_t wiphy_counter = ATOMIC_INIT(0);
@@ -371,31 +357,7 @@
rdev->wiphy_idx--;
/* give it a proper name */
- if (requested_name && requested_name[0]) {
- int rv;
-
- rtnl_lock();
- rv = cfg80211_dev_check_name(rdev, requested_name);
-
- if (rv < 0) {
- rtnl_unlock();
- goto use_default_name;
- }
-
- rv = dev_set_name(&rdev->wiphy.dev, "%s", requested_name);
- rtnl_unlock();
- if (rv)
- goto use_default_name;
- } else {
-use_default_name:
- /* NOTE: This is *probably* safe w/out holding rtnl because of
- * the restrictions on phy names. Probably this call could
- * fail if some other part of the kernel (re)named a device
- * phyX. But, might should add some locking and check return
- * value, and use a different name if this one exists?
- */
- dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
- }
+ dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
INIT_LIST_HEAD(&rdev->wdev_list);
INIT_LIST_HEAD(&rdev->beacon_registrations);
@@ -451,7 +413,7 @@
return &rdev->wiphy;
}
-EXPORT_SYMBOL(wiphy_new_nm);
+EXPORT_SYMBOL(wiphy_new);
static int wiphy_verify_combinations(struct wiphy *wiphy)
{
@@ -548,24 +510,6 @@
!wiphy->wowlan->tcp))
return -EINVAL;
#endif
- if (WARN_ON((wiphy->features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH) &&
- (!rdev->ops->tdls_channel_switch ||
- !rdev->ops->tdls_cancel_channel_switch)))
- return -EINVAL;
-
- /*
- * if a wiphy has unsupported modes for regulatory channel enforcement,
- * opt-out of enforcement checking
- */
- if (wiphy->interface_modes & ~(BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_P2P_CLIENT) |
- BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_P2P_GO) |
- BIT(NL80211_IFTYPE_ADHOC) |
- BIT(NL80211_IFTYPE_P2P_DEVICE) |
- BIT(NL80211_IFTYPE_AP_VLAN) |
- BIT(NL80211_IFTYPE_MONITOR)))
- wiphy->regulatory_flags |= REGULATORY_IGNORE_STALE_KICKOFF;
if (WARN_ON(wiphy->coalesce &&
(!wiphy->coalesce->n_rules ||
@@ -894,22 +838,7 @@
case NL80211_IFTYPE_P2P_GO:
__cfg80211_stop_ap(rdev, dev, true);
break;
- case NL80211_IFTYPE_OCB:
- __cfg80211_leave_ocb(rdev, dev);
- break;
- case NL80211_IFTYPE_WDS:
- /* must be handled by mac80211/driver, has no APIs */
- break;
- case NL80211_IFTYPE_P2P_DEVICE:
- /* cannot happen, has no netdev */
- break;
- case NL80211_IFTYPE_AP_VLAN:
- case NL80211_IFTYPE_MONITOR:
- /* nothing to do */
- break;
- case NL80211_IFTYPE_UNSPECIFIED:
- case NUM_NL80211_IFTYPES:
- /* invalid */
+ default:
break;
}
}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index df247e3..b27f044 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -111,7 +111,6 @@
rdev->wiphy.wowlan_config->tcp->sock)
sock_release(rdev->wiphy.wowlan_config->tcp->sock);
kfree(rdev->wiphy.wowlan_config->tcp);
- kfree(rdev->wiphy.wowlan_config->nd_config);
kfree(rdev->wiphy.wowlan_config);
#endif
}
@@ -291,18 +290,6 @@
struct wireless_dev *wdev,
struct cfg80211_chan_def *chandef);
-/* OCB */
-int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct ocb_setup *setup);
-int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct ocb_setup *setup);
-int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev);
-int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev);
-
/* AP */
int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
struct net_device *dev, bool notify);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index b800567..f84c236 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -209,7 +209,7 @@
}
/* policy for the attributes */
-static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
+static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[NL80211_ATTR_WIPHY] = { .type = NLA_U32 },
[NL80211_ATTR_WIPHY_NAME] = { .type = NLA_NUL_STRING,
.len = 20-1 },
@@ -388,14 +388,13 @@
[NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN },
[NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 },
[NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 },
- [NL80211_ATTR_SOCKET_OWNER] = { .type = NLA_FLAG },
+ [NL80211_ATTR_IFACE_SOCKET_OWNER] = { .type = NLA_FLAG },
[NL80211_ATTR_CSA_C_OFFSETS_TX] = { .type = NLA_BINARY },
[NL80211_ATTR_USE_RRM] = { .type = NLA_FLAG },
[NL80211_ATTR_TSID] = { .type = NLA_U8 },
[NL80211_ATTR_USER_PRIO] = { .type = NLA_U8 },
[NL80211_ATTR_ADMITTED_TIME] = { .type = NLA_U16 },
[NL80211_ATTR_SMPS_MODE] = { .type = NLA_U8 },
- [NL80211_ATTR_MAC_MASK] = { .len = ETH_ALEN },
};
/* policy for the key attributes */
@@ -429,7 +428,6 @@
[NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE] = { .type = NLA_FLAG },
[NL80211_WOWLAN_TRIG_RFKILL_RELEASE] = { .type = NLA_FLAG },
[NL80211_WOWLAN_TRIG_TCP_CONNECTION] = { .type = NLA_NESTED },
- [NL80211_WOWLAN_TRIG_NET_DETECT] = { .type = NLA_NESTED },
};
static const struct nla_policy
@@ -886,12 +884,7 @@
if (!wdev->current_bss)
return -ENOLINK;
break;
- case NL80211_IFTYPE_UNSPECIFIED:
- case NL80211_IFTYPE_OCB:
- case NL80211_IFTYPE_MONITOR:
- case NL80211_IFTYPE_P2P_DEVICE:
- case NL80211_IFTYPE_WDS:
- case NUM_NL80211_IFTYPES:
+ default:
return -EINVAL;
}
@@ -1090,8 +1083,6 @@
if (large && nl80211_send_wowlan_tcp_caps(rdev, msg))
return -ENOBUFS;
- /* TODO: send wowlan net detect */
-
nla_nest_end(msg, nl_wowlan);
return 0;
@@ -1523,8 +1514,8 @@
if (rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH)
CMD(channel_switch, CHANNEL_SWITCH);
CMD(set_qos_map, SET_QOS_MAP);
- if (rdev->wiphy.features &
- NL80211_FEATURE_SUPPORTS_WMM_ADMISSION)
+ if (rdev->wiphy.flags &
+ WIPHY_FLAG_SUPPORTS_WMM_ADMISSION)
CMD(add_tx_ts, ADD_TX_TS);
}
/* add into the if now */
@@ -2319,8 +2310,7 @@
static int nl80211_send_chandef(struct sk_buff *msg,
const struct cfg80211_chan_def *chandef)
{
- if (WARN_ON(!cfg80211_chandef_valid(chandef)))
- return -EINVAL;
+ WARN_ON(!cfg80211_chandef_valid(chandef));
if (nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ,
chandef->chan->center_freq))
@@ -2348,16 +2338,12 @@
static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags,
struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev, bool removal)
+ struct wireless_dev *wdev)
{
struct net_device *dev = wdev->netdev;
- u8 cmd = NL80211_CMD_NEW_INTERFACE;
void *hdr;
- if (removal)
- cmd = NL80211_CMD_DEL_INTERFACE;
-
- hdr = nl80211hdr_put(msg, portid, seq, flags, cmd);
+ hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_INTERFACE);
if (!hdr)
return -1;
@@ -2424,7 +2410,7 @@
}
if (nl80211_send_iface(skb, NETLINK_CB_PORTID(cb->skb),
cb->nlh->nlmsg_seq, NLM_F_MULTI,
- rdev, wdev, false) < 0) {
+ rdev, wdev) < 0) {
goto out;
}
if_idx++;
@@ -2452,7 +2438,7 @@
return -ENOMEM;
if (nl80211_send_iface(msg, genl_info_snd_portid(info), info->snd_seq, 0,
- rdev, wdev, false) < 0) {
+ rdev, wdev) < 0) {
nlmsg_free(msg);
return -ENOBUFS;
}
@@ -2598,7 +2584,7 @@
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct vif_params params;
struct wireless_dev *wdev;
- struct sk_buff *msg, *event;
+ struct sk_buff *msg;
int err;
enum nl80211_iftype type = NL80211_IFTYPE_UNSPECIFIED;
u32 flags;
@@ -2621,9 +2607,7 @@
!(rdev->wiphy.interface_modes & (1 << type)))
return -EOPNOTSUPP;
- if ((type == NL80211_IFTYPE_P2P_DEVICE ||
- rdev->wiphy.features & NL80211_FEATURE_MAC_ON_CREATE) &&
- info->attrs[NL80211_ATTR_MAC]) {
+ if (type == NL80211_IFTYPE_P2P_DEVICE && info->attrs[NL80211_ATTR_MAC]) {
nla_memcpy(params.macaddr, info->attrs[NL80211_ATTR_MAC],
ETH_ALEN);
if (!is_valid_ether_addr(params.macaddr))
@@ -2652,15 +2636,12 @@
wdev = rdev_add_virtual_intf(rdev,
nla_data(info->attrs[NL80211_ATTR_IFNAME]),
type, err ? NULL : &flags, ¶ms);
- if (WARN_ON(!wdev)) {
- nlmsg_free(msg);
- return -EPROTO;
- } else if (IS_ERR(wdev)) {
+ if (IS_ERR(wdev)) {
nlmsg_free(msg);
return PTR_ERR(wdev);
}
- if (info->attrs[NL80211_ATTR_SOCKET_OWNER])
+ if (info->attrs[NL80211_ATTR_IFACE_SOCKET_OWNER])
wdev->owner_nlportid = genl_info_snd_portid(info);
switch (type) {
@@ -2696,25 +2677,11 @@
}
if (nl80211_send_iface(msg, genl_info_snd_portid(info), info->snd_seq, 0,
- rdev, wdev, false) < 0) {
+ rdev, wdev) < 0) {
nlmsg_free(msg);
return -ENOBUFS;
}
- event = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (event) {
- if (nl80211_send_iface(event, 0, 0, 0,
- rdev, wdev, false) < 0) {
- nlmsg_free(event);
- goto out;
- }
-
- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
- event, 0, NL80211_MCGRP_CONFIG,
- GFP_KERNEL);
- }
-
-out:
return genlmsg_reply(msg, info);
}
@@ -2722,18 +2689,10 @@
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct wireless_dev *wdev = info->user_ptr[1];
- struct sk_buff *msg;
- int status;
if (!rdev->ops->del_virtual_intf)
return -EOPNOTSUPP;
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (msg && nl80211_send_iface(msg, 0, 0, 0, rdev, wdev, true) < 0) {
- nlmsg_free(msg);
- msg = NULL;
- }
-
/*
* If we remove a wireless device without a netdev then clear
* user_ptr[1] so that nl80211_post_doit won't dereference it
@@ -2744,15 +2703,7 @@
if (!wdev->netdev)
info->user_ptr[1] = NULL;
- status = rdev_del_virtual_intf(rdev, wdev);
- if (status >= 0 && msg)
- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy),
- msg, 0, NL80211_MCGRP_CONFIG,
- GFP_KERNEL);
- else
- nlmsg_free(msg);
-
- return status;
+ return rdev_del_virtual_intf(rdev, wdev);
}
static int nl80211_set_noack_map(struct sk_buff *skb, struct genl_info *info)
@@ -4450,12 +4401,10 @@
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
struct net_device *dev = info->user_ptr[1];
- struct station_del_parameters params;
-
- memset(¶ms, 0, sizeof(params));
+ u8 *mac_addr = NULL;
if (info->attrs[NL80211_ATTR_MAC])
- params.mac = nla_data(info->attrs[NL80211_ATTR_MAC]);
+ mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
@@ -4466,28 +4415,7 @@
if (!rdev->ops->del_station)
return -EOPNOTSUPP;
- if (info->attrs[NL80211_ATTR_MGMT_SUBTYPE]) {
- params.subtype =
- nla_get_u8(info->attrs[NL80211_ATTR_MGMT_SUBTYPE]);
- if (params.subtype != IEEE80211_STYPE_DISASSOC >> 4 &&
- params.subtype != IEEE80211_STYPE_DEAUTH >> 4)
- return -EINVAL;
- } else {
- /* Default to Deauthentication frame */
- params.subtype = IEEE80211_STYPE_DEAUTH >> 4;
- }
-
- if (info->attrs[NL80211_ATTR_REASON_CODE]) {
- params.reason_code =
- nla_get_u16(info->attrs[NL80211_ATTR_REASON_CODE]);
- if (params.reason_code == 0)
- return -EINVAL; /* 0 is reserved */
- } else {
- /* Default to reason code 2 */
- params.reason_code = WLAN_REASON_PREV_AUTH_NOT_VALID;
- }
-
- return rdev_del_station(rdev, dev, ¶ms);
+ return rdev_del_station(rdev, dev, mac_addr);
}
static int nl80211_send_mpath(struct sk_buff *msg, u32 portid, u32 seq,
@@ -4498,7 +4426,7 @@
void *hdr;
struct nlattr *pinfoattr;
- hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_MPATH);
+ hdr = nl80211hdr_put(msg, portid, seq, flags, NL80211_CMD_NEW_STATION);
if (!hdr)
return -1;
@@ -4699,96 +4627,6 @@
return rdev_del_mpath(rdev, dev, dst);
}
-static int nl80211_get_mpp(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev = info->user_ptr[0];
- int err;
- struct net_device *dev = info->user_ptr[1];
- struct mpath_info pinfo;
- struct sk_buff *msg;
- u8 *dst = NULL;
- u8 mpp[ETH_ALEN];
-
- memset(&pinfo, 0, sizeof(pinfo));
-
- if (!info->attrs[NL80211_ATTR_MAC])
- return -EINVAL;
-
- dst = nla_data(info->attrs[NL80211_ATTR_MAC]);
-
- if (!rdev->ops->get_mpp)
- return -EOPNOTSUPP;
-
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT)
- return -EOPNOTSUPP;
-
- err = rdev_get_mpp(rdev, dev, dst, mpp, &pinfo);
- if (err)
- return err;
-
- msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg)
- return -ENOMEM;
-
- if (nl80211_send_mpath(msg, genl_info_snd_portid(info), info->snd_seq, 0,
- dev, dst, mpp, &pinfo) < 0) {
- nlmsg_free(msg);
- return -ENOBUFS;
- }
-
- return genlmsg_reply(msg, info);
-}
-
-static int nl80211_dump_mpp(struct sk_buff *skb,
- struct netlink_callback *cb)
-{
- struct mpath_info pinfo;
- struct cfg80211_registered_device *rdev;
- struct wireless_dev *wdev;
- u8 dst[ETH_ALEN];
- u8 mpp[ETH_ALEN];
- int path_idx = cb->args[2];
- int err;
-
- err = nl80211_prepare_wdev_dump(skb, cb, &rdev, &wdev);
- if (err)
- return err;
-
- if (!rdev->ops->dump_mpp) {
- err = -EOPNOTSUPP;
- goto out_err;
- }
-
- if (wdev->iftype != NL80211_IFTYPE_MESH_POINT) {
- err = -EOPNOTSUPP;
- goto out_err;
- }
-
- while (1) {
- err = rdev_dump_mpp(rdev, wdev->netdev, path_idx, dst,
- mpp, &pinfo);
- if (err == -ENOENT)
- break;
- if (err)
- goto out_err;
-
- if (nl80211_send_mpath(skb, NETLINK_CB_PORTID(cb->skb),
- cb->nlh->nlmsg_seq, NLM_F_MULTI,
- wdev->netdev, dst, mpp,
- &pinfo) < 0)
- goto out;
-
- path_idx++;
- }
-
- out:
- cb->args[2] = path_idx;
- err = skb->len;
- out_err:
- nl80211_finish_wdev_dump(rdev);
- return err;
-}
-
static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -5427,11 +5265,11 @@
{
struct nlattr *tb[NL80211_REG_RULE_ATTR_MAX + 1];
struct nlattr *nl_reg_rule;
- char *alpha2;
- int rem_reg_rules, r;
+ char *alpha2 = NULL;
+ int rem_reg_rules = 0, r = 0;
u32 num_rules = 0, rule_idx = 0, size_of_regd;
enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
- struct ieee80211_regdomain *rd;
+ struct ieee80211_regdomain *rd = NULL;
if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
return -EINVAL;
@@ -5525,43 +5363,6 @@
return n_channels;
}
-static int nl80211_parse_random_mac(struct nlattr **attrs,
- u8 *mac_addr, u8 *mac_addr_mask)
-{
- int i;
-
- if (!attrs[NL80211_ATTR_MAC] && !attrs[NL80211_ATTR_MAC_MASK]) {
- memset(mac_addr, 0, ETH_ALEN);
- memset(mac_addr_mask, 0, ETH_ALEN);
- mac_addr[0] = 0x2;
- mac_addr_mask[0] = 0x3;
-
- return 0;
- }
-
- /* need both or none */
- if (!attrs[NL80211_ATTR_MAC] || !attrs[NL80211_ATTR_MAC_MASK])
- return -EINVAL;
-
- memcpy(mac_addr, nla_data(attrs[NL80211_ATTR_MAC]), ETH_ALEN);
- memcpy(mac_addr_mask, nla_data(attrs[NL80211_ATTR_MAC_MASK]), ETH_ALEN);
-
- /* don't allow or configure an mcast address */
- if (!is_multicast_ether_addr(mac_addr_mask) ||
- is_multicast_ether_addr(mac_addr))
- return -EINVAL;
-
- /*
- * allow users to pass a MAC address that has bits set outside
- * of the mask, but don't bother drivers with having to deal
- * with such bits
- */
- for (i = 0; i < ETH_ALEN; i++)
- mac_addr[i] &= mac_addr_mask[i];
-
- return 0;
-}
-
static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -5739,25 +5540,6 @@
err = -EOPNOTSUPP;
goto out_free;
}
-
- if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
- if (!(wiphy->features &
- NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR)) {
- err = -EOPNOTSUPP;
- goto out_free;
- }
-
- if (wdev->current_bss) {
- err = -EOPNOTSUPP;
- goto out_free;
- }
-
- err = nl80211_parse_random_mac(info->attrs,
- request->mac_addr,
- request->mac_addr_mask);
- if (err)
- goto out_free;
- }
}
request->no_cck =
@@ -5784,12 +5566,14 @@
return err;
}
-static struct cfg80211_sched_scan_request *
-nl80211_parse_sched_scan(struct wiphy *wiphy, struct wireless_dev *wdev,
- struct nlattr **attrs)
+static int nl80211_start_sched_scan(struct sk_buff *skb,
+ struct genl_info *info)
{
struct cfg80211_sched_scan_request *request;
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
struct nlattr *attr;
+ struct wiphy *wiphy;
int err, tmp, n_ssids = 0, n_match_sets = 0, n_channels, i;
u32 interval;
enum ieee80211_band band;
@@ -5797,32 +5581,38 @@
struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1];
s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF;
- if (!is_valid_ie_attr(attrs[NL80211_ATTR_IE]))
- return ERR_PTR(-EINVAL);
+ if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
+ !rdev->ops->sched_scan_start)
+ return -EOPNOTSUPP;
- if (!attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
- return ERR_PTR(-EINVAL);
+ if (!is_valid_ie_attr(info->attrs[NL80211_ATTR_IE]))
+ return -EINVAL;
- interval = nla_get_u32(attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
+ if (!info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL])
+ return -EINVAL;
+
+ interval = nla_get_u32(info->attrs[NL80211_ATTR_SCHED_SCAN_INTERVAL]);
if (interval == 0)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
- if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
+ wiphy = &rdev->wiphy;
+
+ if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
n_channels = validate_scan_freqs(
- attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
+ info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]);
if (!n_channels)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
} else {
n_channels = ieee80211_get_num_supported_channels(wiphy);
}
- if (attrs[NL80211_ATTR_SCAN_SSIDS])
- nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
+ if (info->attrs[NL80211_ATTR_SCAN_SSIDS])
+ nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
tmp)
n_ssids++;
if (n_ssids > wiphy->max_sched_scan_ssids)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
/*
* First, count the number of 'real' matchsets. Due to an issue with
@@ -5833,9 +5623,9 @@
* older userspace that treated a matchset with only the RSSI as the
* global RSSI for all other matchsets - if there are other matchsets.
*/
- if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
+ if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
nla_for_each_nested(attr,
- attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
+ info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
tmp) {
struct nlattr *rssi;
@@ -5843,7 +5633,7 @@
nla_data(attr), nla_len(attr),
nl80211_match_policy);
if (err)
- return ERR_PTR(err);
+ return err;
/* add other standalone attributes here */
if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) {
n_match_sets++;
@@ -5860,23 +5650,30 @@
n_match_sets = 1;
if (n_match_sets > wiphy->max_match_sets)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
- if (attrs[NL80211_ATTR_IE])
- ie_len = nla_len(attrs[NL80211_ATTR_IE]);
+ if (info->attrs[NL80211_ATTR_IE])
+ ie_len = nla_len(info->attrs[NL80211_ATTR_IE]);
else
ie_len = 0;
if (ie_len > wiphy->max_sched_scan_ie_len)
- return ERR_PTR(-EINVAL);
+ return -EINVAL;
+
+ if (rdev->sched_scan_req) {
+ err = -EINPROGRESS;
+ goto out;
+ }
request = kzalloc(sizeof(*request)
+ sizeof(*request->ssids) * n_ssids
+ sizeof(*request->match_sets) * n_match_sets
+ sizeof(*request->channels) * n_channels
+ ie_len, GFP_KERNEL);
- if (!request)
- return ERR_PTR(-ENOMEM);
+ if (!request) {
+ err = -ENOMEM;
+ goto out;
+ }
if (n_ssids)
request->ssids = (void *)&request->channels[n_channels];
@@ -5901,10 +5698,10 @@
request->n_match_sets = n_match_sets;
i = 0;
- if (attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
+ if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) {
/* user specified, bail out if channel not found */
nla_for_each_nested(attr,
- attrs[NL80211_ATTR_SCAN_FREQUENCIES],
+ info->attrs[NL80211_ATTR_SCAN_FREQUENCIES],
tmp) {
struct ieee80211_channel *chan;
@@ -5950,8 +5747,8 @@
request->n_channels = i;
i = 0;
- if (attrs[NL80211_ATTR_SCAN_SSIDS]) {
- nla_for_each_nested(attr, attrs[NL80211_ATTR_SCAN_SSIDS],
+ if (info->attrs[NL80211_ATTR_SCAN_SSIDS]) {
+ nla_for_each_nested(attr, info->attrs[NL80211_ATTR_SCAN_SSIDS],
tmp) {
if (nla_len(attr) > IEEE80211_MAX_SSID_LEN) {
err = -EINVAL;
@@ -5965,9 +5762,9 @@
}
i = 0;
- if (attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
+ if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) {
nla_for_each_nested(attr,
- attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
+ info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH],
tmp) {
struct nlattr *ssid, *rssi;
@@ -6007,7 +5804,7 @@
}
/* there was no other matchset, so the RSSI one is alone */
- if (i == 0 && n_match_sets)
+ if (i == 0)
request->match_sets[0].rssi_thold = default_match_rssi;
request->min_rssi_thold = INT_MAX;
@@ -6022,88 +5819,36 @@
if (ie_len) {
request->ie_len = ie_len;
memcpy((void *)request->ie,
- nla_data(attrs[NL80211_ATTR_IE]),
+ nla_data(info->attrs[NL80211_ATTR_IE]),
request->ie_len);
}
- if (attrs[NL80211_ATTR_SCAN_FLAGS]) {
+ if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
request->flags = nla_get_u32(
- attrs[NL80211_ATTR_SCAN_FLAGS]);
+ info->attrs[NL80211_ATTR_SCAN_FLAGS]);
if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
!(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
err = -EOPNOTSUPP;
goto out_free;
}
-
- if (request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
- u32 flg = NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR;
-
- if (!wdev) /* must be net-detect */
- flg = NL80211_FEATURE_ND_RANDOM_MAC_ADDR;
-
- if (!(wiphy->features & flg)) {
- err = -EOPNOTSUPP;
- goto out_free;
- }
-
- if (wdev && wdev->current_bss) {
- err = -EOPNOTSUPP;
- goto out_free;
- }
-
- err = nl80211_parse_random_mac(attrs, request->mac_addr,
- request->mac_addr_mask);
- if (err)
- goto out_free;
- }
}
+ request->dev = dev;
+ request->wiphy = &rdev->wiphy;
request->interval = interval;
request->scan_start = jiffies;
- return request;
+ err = rdev_sched_scan_start(rdev, dev, request);
+ if (!err) {
+ rdev->sched_scan_req = request;
+ nl80211_send_sched_scan(rdev, dev,
+ NL80211_CMD_START_SCHED_SCAN);
+ goto out;
+ }
out_free:
kfree(request);
- return ERR_PTR(err);
-}
-
-static int nl80211_start_sched_scan(struct sk_buff *skb,
- struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- int err;
-
- if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
- !rdev->ops->sched_scan_start)
- return -EOPNOTSUPP;
-
- if (rdev->sched_scan_req)
- return -EINPROGRESS;
-
- rdev->sched_scan_req = nl80211_parse_sched_scan(&rdev->wiphy, wdev,
- info->attrs);
- err = PTR_ERR_OR_ZERO(rdev->sched_scan_req);
- if (err)
- goto out_err;
-
- err = rdev_sched_scan_start(rdev, dev, rdev->sched_scan_req);
- if (err)
- goto out_free;
-
- rdev->sched_scan_req->dev = dev;
- rdev->sched_scan_req->wiphy = &rdev->wiphy;
-
- nl80211_send_sched_scan(rdev, dev,
- NL80211_CMD_START_SCHED_SCAN);
- return 0;
-
-out_free:
- kfree(rdev->sched_scan_req);
-out_err:
- rdev->sched_scan_req = NULL;
+out:
return err;
}
@@ -6183,10 +5928,10 @@
* function is called under RTNL lock, so this should not be a problem.
*/
static struct nlattr *csa_attrs[NL80211_ATTR_MAX+1];
+ u8 radar_detect_width = 0;
int err;
bool need_new_beacon = false;
int len, i;
- u32 cs_count;
if (!rdev->ops->channel_switch ||
!(rdev->wiphy.flags & WIPHY_FLAG_HAS_CHANNEL_SWITCH))
@@ -6223,14 +5968,7 @@
if (need_new_beacon && !info->attrs[NL80211_ATTR_CSA_IES])
return -EINVAL;
- /* Even though the attribute is u32, the specification says
- * u8, so let's make sure we don't overflow.
- */
- cs_count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
- if (cs_count > 255)
- return -EINVAL;
-
- params.count = cs_count;
+ params.count = nla_get_u32(info->attrs[NL80211_ATTR_CH_SWITCH_COUNT]);
if (!need_new_beacon)
goto skip_beacons;
@@ -6318,8 +6056,10 @@
if (err < 0)
return err;
- if (err > 0)
+ if (err > 0) {
+ radar_detect_width = BIT(params.chandef.width);
params.radar_required = true;
+ }
if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
params.block_tx = true;
@@ -6570,6 +6310,8 @@
}
while (1) {
+ struct ieee80211_channel *chan;
+
res = rdev_dump_survey(rdev, wdev->netdev, survey_idx, &survey);
if (res == -ENOENT)
break;
@@ -6582,7 +6324,9 @@
goto out;
}
- if (survey.channel->flags & IEEE80211_CHAN_DISABLED) {
+ chan = ieee80211_get_channel(&rdev->wiphy,
+ survey.channel->center_freq);
+ if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
survey_idx++;
continue;
}
@@ -8418,28 +8162,6 @@
return -EINVAL;
}
-static int nl80211_join_ocb(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct ocb_setup setup = {};
- int err;
-
- err = nl80211_parse_chandef(rdev, info, &setup.chandef);
- if (err)
- return err;
-
- return cfg80211_join_ocb(rdev, dev, &setup);
-}
-
-static int nl80211_leave_ocb(struct sk_buff *skb, struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
-
- return cfg80211_leave_ocb(rdev, dev);
-}
-
static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -8824,39 +8546,6 @@
return 0;
}
-static int nl80211_parse_wowlan_nd(struct cfg80211_registered_device *rdev,
- const struct wiphy_wowlan_support *wowlan,
- struct nlattr *attr,
- struct cfg80211_wowlan *trig)
-{
- struct nlattr **tb;
- int err;
-
- tb = kzalloc(NUM_NL80211_ATTR * sizeof(*tb), GFP_KERNEL);
- if (!tb)
- return -ENOMEM;
-
- if (!(wowlan->flags & WIPHY_WOWLAN_NET_DETECT)) {
- err = -EOPNOTSUPP;
- goto out;
- }
-
- err = nla_parse(tb, NL80211_ATTR_MAX,
- nla_data(attr), nla_len(attr),
- nl80211_policy);
- if (err)
- goto out;
-
- trig->nd_config = nl80211_parse_sched_scan(&rdev->wiphy, NULL, tb);
- err = PTR_ERR_OR_ZERO(trig->nd_config);
- if (err)
- trig->nd_config = NULL;
-
-out:
- kfree(tb);
- return err;
-}
-
static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@ -9002,14 +8691,6 @@
goto error;
}
- if (tb[NL80211_WOWLAN_TRIG_NET_DETECT]) {
- err = nl80211_parse_wowlan_nd(
- rdev, wowlan, tb[NL80211_WOWLAN_TRIG_NET_DETECT],
- &new_triggers);
- if (err)
- goto error;
- }
-
ntrig = kmemdup(&new_triggers, sizeof(new_triggers), GFP_KERNEL);
if (!ntrig) {
err = -ENOMEM;
@@ -9770,7 +9451,7 @@
u16 admitted_time = 0;
int err;
- if (!(rdev->wiphy.features & NL80211_FEATURE_SUPPORTS_WMM_ADMISSION))
+ if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
return -EOPNOTSUPP;
if (!info->attrs[NL80211_ATTR_TSID] || !info->attrs[NL80211_ATTR_MAC] ||
@@ -9786,10 +9467,12 @@
return -EINVAL;
/* WMM uses TIDs 0-7 even for TSPEC */
- if (tsid >= IEEE80211_FIRST_TSPEC_TSID) {
+ if (tsid < IEEE80211_FIRST_TSPEC_TSID) {
+ if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_WMM_ADMISSION))
+ return -EINVAL;
+ } else {
/* TODO: handle 802.11 TSPEC/admission control
- * need more attributes for that (e.g. BA session requirement);
- * change the WMM adminssion test above to allow both then
+ * need more attributes for that (e.g. BA session requirement)
*/
return -EINVAL;
}
@@ -9845,98 +9528,6 @@
return err;
}
-static int nl80211_tdls_channel_switch(struct sk_buff *skb,
- struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct cfg80211_chan_def chandef = {};
- const u8 *addr;
- u8 oper_class;
- int err;
-
- if (!rdev->ops->tdls_channel_switch ||
- !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
- return -EOPNOTSUPP;
-
- switch (dev->ieee80211_ptr->iftype) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_P2P_CLIENT:
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- if (!info->attrs[NL80211_ATTR_MAC] ||
- !info->attrs[NL80211_ATTR_OPER_CLASS])
- return -EINVAL;
-
- err = nl80211_parse_chandef(rdev, info, &chandef);
- if (err)
- return err;
-
- /*
- * Don't allow wide channels on the 2.4Ghz band, as per IEEE802.11-2012
- * section 10.22.6.2.1. Disallow 5/10Mhz channels as well for now, the
- * specification is not defined for them.
- */
- if (chandef.chan->band == IEEE80211_BAND_2GHZ &&
- chandef.width != NL80211_CHAN_WIDTH_20_NOHT &&
- chandef.width != NL80211_CHAN_WIDTH_20)
- return -EINVAL;
-
- /* we will be active on the TDLS link */
- if (!cfg80211_reg_can_beacon(&rdev->wiphy, &chandef, wdev->iftype))
- return -EINVAL;
-
- /* don't allow switching to DFS channels */
- if (cfg80211_chandef_dfs_required(wdev->wiphy, &chandef, wdev->iftype))
- return -EINVAL;
-
- addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
- oper_class = nla_get_u8(info->attrs[NL80211_ATTR_OPER_CLASS]);
-
- wdev_lock(wdev);
- err = rdev_tdls_channel_switch(rdev, dev, addr, oper_class, &chandef);
- wdev_unlock(wdev);
-
- return err;
-}
-
-static int nl80211_tdls_cancel_channel_switch(struct sk_buff *skb,
- struct genl_info *info)
-{
- struct cfg80211_registered_device *rdev = info->user_ptr[0];
- struct net_device *dev = info->user_ptr[1];
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- const u8 *addr;
-
- if (!rdev->ops->tdls_channel_switch ||
- !rdev->ops->tdls_cancel_channel_switch ||
- !(rdev->wiphy.features & NL80211_FEATURE_TDLS_CHANNEL_SWITCH))
- return -EOPNOTSUPP;
-
- switch (dev->ieee80211_ptr->iftype) {
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_P2P_CLIENT:
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- if (!info->attrs[NL80211_ATTR_MAC])
- return -EINVAL;
-
- addr = nla_data(info->attrs[NL80211_ATTR_MAC]);
-
- wdev_lock(wdev);
- rdev_tdls_cancel_channel_switch(rdev, dev, addr);
- wdev_unlock(wdev);
-
- return 0;
-}
-
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -10198,15 +9789,6 @@
NL80211_FLAG_NEED_RTNL,
},
{
- .cmd = NL80211_CMD_GET_MPP,
- .doit = nl80211_get_mpp,
- .dumpit = nl80211_dump_mpp,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- NL80211_FLAG_NEED_RTNL,
- },
- {
.cmd = NL80211_CMD_SET_MPATH,
.doit = nl80211_set_mpath,
.policy = nl80211_policy,
@@ -10520,22 +10102,6 @@
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
- {
- .cmd = NL80211_CMD_JOIN_OCB,
- .doit = nl80211_join_ocb,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- NL80211_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL80211_CMD_LEAVE_OCB,
- .doit = nl80211_leave_ocb,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- NL80211_FLAG_NEED_RTNL,
- },
#ifdef CONFIG_PM
{
.cmd = NL80211_CMD_GET_WOWLAN,
@@ -10735,22 +10301,6 @@
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
- {
- .cmd = NL80211_CMD_TDLS_CHANNEL_SWITCH,
- .doit = nl80211_tdls_channel_switch,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- NL80211_FLAG_NEED_RTNL,
- },
- {
- .cmd = NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH,
- .doit = nl80211_tdls_cancel_channel_switch,
- .policy = nl80211_policy,
- .flags = GENL_ADMIN_PERM,
- .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
- NL80211_FLAG_NEED_RTNL,
- },
};
/* notification functions */
@@ -11782,155 +11332,55 @@
}
EXPORT_SYMBOL(cfg80211_mgmt_tx_status);
-static struct sk_buff *cfg80211_prepare_cqm(struct net_device *dev,
- const char *mac, gfp_t gfp)
+void cfg80211_cqm_rssi_notify(struct net_device *dev,
+ enum nl80211_cqm_rssi_threshold_event rssi_event,
+ gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- struct sk_buff *msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
- void **cb;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ struct sk_buff *msg;
+ struct nlattr *pinfoattr;
+ void *hdr;
+ trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
if (!msg)
- return NULL;
+ return;
- cb = (void **)msg->cb;
-
- cb[0] = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
- if (!cb[0]) {
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
+ if (!hdr) {
nlmsg_free(msg);
- return NULL;
+ return;
}
if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
goto nla_put_failure;
- if (mac && nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, mac))
+ pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM);
+ if (!pinfoattr)
goto nla_put_failure;
- cb[1] = nla_nest_start(msg, NL80211_ATTR_CQM);
- if (!cb[1])
- goto nla_put_failure;
-
- cb[2] = rdev;
-
- return msg;
- nla_put_failure:
- nlmsg_free(msg);
- return NULL;
-}
-
-static void cfg80211_send_cqm(struct sk_buff *msg, gfp_t gfp)
-{
- void **cb = (void **)msg->cb;
- struct cfg80211_registered_device *rdev = cb[2];
-
- nla_nest_end(msg, cb[1]);
- genlmsg_end(msg, cb[0]);
-
- memset(msg->cb, 0, sizeof(msg->cb));
-
- genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
- NL80211_MCGRP_MLME, gfp);
-}
-
-void cfg80211_cqm_rssi_notify(struct net_device *dev,
- enum nl80211_cqm_rssi_threshold_event rssi_event,
- gfp_t gfp)
-{
- struct sk_buff *msg;
-
- trace_cfg80211_cqm_rssi_notify(dev, rssi_event);
-
- if (WARN_ON(rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW &&
- rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH))
- return;
-
- msg = cfg80211_prepare_cqm(dev, NULL, gfp);
- if (!msg)
- return;
-
if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT,
rssi_event))
goto nla_put_failure;
- cfg80211_send_cqm(msg, gfp);
+ nla_nest_end(msg, pinfoattr);
+ genlmsg_end(msg, hdr);
+
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
return;
nla_put_failure:
+ genlmsg_cancel(msg, hdr);
nlmsg_free(msg);
}
EXPORT_SYMBOL(cfg80211_cqm_rssi_notify);
-void cfg80211_cqm_txe_notify(struct net_device *dev,
- const u8 *peer, u32 num_packets,
- u32 rate, u32 intvl, gfp_t gfp)
-{
- struct sk_buff *msg;
-
- msg = cfg80211_prepare_cqm(dev, peer, gfp);
- if (!msg)
- return;
-
- if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
- goto nla_put_failure;
-
- if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
- goto nla_put_failure;
-
- if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
- goto nla_put_failure;
-
- cfg80211_send_cqm(msg, gfp);
- return;
-
- nla_put_failure:
- nlmsg_free(msg);
-}
-EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
-
-void cfg80211_cqm_pktloss_notify(struct net_device *dev,
- const u8 *peer, u32 num_packets, gfp_t gfp)
-{
- struct sk_buff *msg;
-
- trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
-
- msg = cfg80211_prepare_cqm(dev, peer, gfp);
- if (!msg)
- return;
-
- if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
- goto nla_put_failure;
-
- cfg80211_send_cqm(msg, gfp);
- return;
-
- nla_put_failure:
- nlmsg_free(msg);
-}
-EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
-
-void cfg80211_cqm_beacon_loss_notify(struct net_device *dev, gfp_t gfp)
-{
- struct sk_buff *msg;
-
- msg = cfg80211_prepare_cqm(dev, NULL, gfp);
- if (!msg)
- return;
-
- if (nla_put_flag(msg, NL80211_ATTR_CQM_BEACON_LOSS_EVENT))
- goto nla_put_failure;
-
- cfg80211_send_cqm(msg, gfp);
- return;
-
- nla_put_failure:
- nlmsg_free(msg);
-}
-EXPORT_SYMBOL(cfg80211_cqm_beacon_loss_notify);
-
static void nl80211_gtk_rekey_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev, const u8 *bssid,
const u8 *replay_ctr, gfp_t gfp)
@@ -12048,9 +11498,7 @@
static void nl80211_ch_switch_notify(struct cfg80211_registered_device *rdev,
struct net_device *netdev,
struct cfg80211_chan_def *chandef,
- gfp_t gfp,
- enum nl80211_commands notif,
- u8 count)
+ gfp_t gfp)
{
struct sk_buff *msg;
void *hdr;
@@ -12059,7 +11507,7 @@
if (!msg)
return;
- hdr = nl80211hdr_put(msg, 0, 0, 0, notif);
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_CH_SWITCH_NOTIFY);
if (!hdr) {
nlmsg_free(msg);
return;
@@ -12071,10 +11519,6 @@
if (nl80211_send_chandef(msg, chandef))
goto nla_put_failure;
- if ((notif == NL80211_CMD_CH_SWITCH_STARTED_NOTIFY) &&
- (nla_put_u32(msg, NL80211_ATTR_CH_SWITCH_COUNT, count)))
- goto nla_put_failure;
-
genlmsg_end(msg, hdr);
genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
@@ -12097,27 +11541,70 @@
trace_cfg80211_ch_switch_notify(dev, chandef);
+ if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
+ wdev->iftype != NL80211_IFTYPE_P2P_GO &&
+ wdev->iftype != NL80211_IFTYPE_ADHOC &&
+ wdev->iftype != NL80211_IFTYPE_MESH_POINT))
+ return;
+
wdev->chandef = *chandef;
wdev->preset_chandef = *chandef;
- nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
- NL80211_CMD_CH_SWITCH_NOTIFY, 0);
+ nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
}
EXPORT_SYMBOL(cfg80211_ch_switch_notify);
-void cfg80211_ch_switch_started_notify(struct net_device *dev,
- struct cfg80211_chan_def *chandef,
- u8 count)
+void cfg80211_cqm_txe_notify(struct net_device *dev,
+ const u8 *peer, u32 num_packets,
+ u32 rate, u32 intvl, gfp_t gfp)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ struct sk_buff *msg;
+ struct nlattr *pinfoattr;
+ void *hdr;
- trace_cfg80211_ch_switch_started_notify(dev, chandef);
+ msg = nlmsg_new(NLMSG_GOODSIZE, gfp);
+ if (!msg)
+ return;
- nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL,
- NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, count);
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer))
+ goto nla_put_failure;
+
+ pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM);
+ if (!pinfoattr)
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_PKTS, num_packets))
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_RATE, rate))
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_CQM_TXE_INTVL, intvl))
+ goto nla_put_failure;
+
+ nla_nest_end(msg, pinfoattr);
+
+ genlmsg_end(msg, hdr);
+
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
}
-EXPORT_SYMBOL(cfg80211_ch_switch_started_notify);
+EXPORT_SYMBOL(cfg80211_cqm_txe_notify);
void
nl80211_radar_notify(struct cfg80211_registered_device *rdev,
@@ -12167,6 +11654,54 @@
nlmsg_free(msg);
}
+void cfg80211_cqm_pktloss_notify(struct net_device *dev,
+ const u8 *peer, u32 num_packets, gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct wiphy *wiphy = wdev->wiphy;
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
+ struct sk_buff *msg;
+ struct nlattr *pinfoattr;
+ void *hdr;
+
+ trace_cfg80211_cqm_pktloss_notify(dev, peer, num_packets);
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NOTIFY_CQM);
+ if (!hdr) {
+ nlmsg_free(msg);
+ return;
+ }
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+ nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, peer))
+ goto nla_put_failure;
+
+ pinfoattr = nla_nest_start(msg, NL80211_ATTR_CQM);
+ if (!pinfoattr)
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_CQM_PKT_LOSS_EVENT, num_packets))
+ goto nla_put_failure;
+
+ nla_nest_end(msg, pinfoattr);
+
+ genlmsg_end(msg, hdr);
+
+ genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
+ NL80211_MCGRP_MLME, gfp);
+ return;
+
+ nla_put_failure:
+ genlmsg_cancel(msg, hdr);
+ nlmsg_free(msg);
+}
+EXPORT_SYMBOL(cfg80211_cqm_pktloss_notify);
+
void cfg80211_probe_status(struct net_device *dev, const u8 *addr,
u64 cookie, bool acked, gfp_t gfp)
{
@@ -12254,67 +11789,6 @@
EXPORT_SYMBOL(cfg80211_report_obss_beacon);
#ifdef CONFIG_PM
-static int cfg80211_net_detect_results(struct sk_buff *msg,
- struct cfg80211_wowlan_wakeup *wakeup)
-{
- struct cfg80211_wowlan_nd_info *nd = wakeup->net_detect;
- struct nlattr *nl_results, *nl_match, *nl_freqs;
- int i, j;
-
- nl_results = nla_nest_start(
- msg, NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS);
- if (!nl_results)
- return -EMSGSIZE;
-
- for (i = 0; i < nd->n_matches; i++) {
- struct cfg80211_wowlan_nd_match *match = nd->matches[i];
-
- nl_match = nla_nest_start(msg, i);
- if (!nl_match)
- break;
-
- /* The SSID attribute is optional in nl80211, but for
- * simplicity reasons it's always present in the
- * cfg80211 structure. If a driver can't pass the
- * SSID, that needs to be changed. A zero length SSID
- * is still a valid SSID (wildcard), so it cannot be
- * used for this purpose.
- */
- if (nla_put(msg, NL80211_ATTR_SSID, match->ssid.ssid_len,
- match->ssid.ssid)) {
- nla_nest_cancel(msg, nl_match);
- goto out;
- }
-
- if (match->n_channels) {
- nl_freqs = nla_nest_start(
- msg, NL80211_ATTR_SCAN_FREQUENCIES);
- if (!nl_freqs) {
- nla_nest_cancel(msg, nl_match);
- goto out;
- }
-
- for (j = 0; j < match->n_channels; j++) {
- if (nla_put_u32(msg,
- NL80211_ATTR_WIPHY_FREQ,
- match->channels[j])) {
- nla_nest_cancel(msg, nl_freqs);
- nla_nest_cancel(msg, nl_match);
- goto out;
- }
- }
-
- nla_nest_end(msg, nl_freqs);
- }
-
- nla_nest_end(msg, nl_match);
- }
-
-out:
- nla_nest_end(msg, nl_results);
- return 0;
-}
-
void cfg80211_report_wowlan_wakeup(struct wireless_dev *wdev,
struct cfg80211_wowlan_wakeup *wakeup,
gfp_t gfp)
@@ -12409,10 +11883,6 @@
goto free_msg;
}
- if (wakeup->net_detect &&
- cfg80211_net_detect_results(msg, wakeup))
- goto free_msg;
-
nla_nest_end(msg, reasons);
}
diff --git a/net/wireless/ocb.c b/net/wireless/ocb.c
deleted file mode 100644
index c00d4a7..0000000
--- a/net/wireless/ocb.c
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * OCB mode implementation
- *
- * Copyright: (c) 2014 Czech Technical University in Prague
- * (c) 2014 Volkswagen Group Research
- * Author: Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
- * Funded by: Volkswagen Group Research
- *
- * 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.
- */
-
-#include <linux/ieee80211.h>
-#include <net/cfg80211.h>
-#include "nl80211.h"
-#include "core.h"
-#include "rdev-ops.h"
-
-int __cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct ocb_setup *setup)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- int err;
-
- ASSERT_WDEV_LOCK(wdev);
-
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
- return -EOPNOTSUPP;
-
- if (WARN_ON(!setup->chandef.chan))
- return -EINVAL;
-
- err = rdev_join_ocb(rdev, dev, setup);
- if (!err)
- wdev->chandef = setup->chandef;
-
- return err;
-}
-
-int cfg80211_join_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct ocb_setup *setup)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- int err;
-
- wdev_lock(wdev);
- err = __cfg80211_join_ocb(rdev, dev, setup);
- wdev_unlock(wdev);
-
- return err;
-}
-
-int __cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- int err;
-
- ASSERT_WDEV_LOCK(wdev);
-
- if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_OCB)
- return -EOPNOTSUPP;
-
- if (!rdev->ops->leave_ocb)
- return -EOPNOTSUPP;
-
- err = rdev_leave_ocb(rdev, dev);
- if (!err)
- memset(&wdev->chandef, 0, sizeof(wdev->chandef));
-
- return err;
-}
-
-int cfg80211_leave_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
- int err;
-
- wdev_lock(wdev);
- err = __cfg80211_leave_ocb(rdev, dev);
- wdev_unlock(wdev);
-
- return err;
-}
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 0336264..6a1867f 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -178,12 +178,11 @@
}
static inline int rdev_del_station(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct station_del_parameters *params)
+ struct net_device *dev, u8 *mac)
{
int ret;
- trace_rdev_del_station(&rdev->wiphy, dev, params);
- ret = rdev->ops->del_station(&rdev->wiphy, dev, params);
+ trace_rdev_del_station(&rdev->wiphy, dev, mac);
+ ret = rdev->ops->del_station(&rdev->wiphy, dev, mac);
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
@@ -264,18 +263,6 @@
}
-static inline int rdev_get_mpp(struct cfg80211_registered_device *rdev,
- struct net_device *dev, u8 *dst, u8 *mpp,
- struct mpath_info *pinfo)
-{
- int ret;
-
- trace_rdev_get_mpp(&rdev->wiphy, dev, dst, mpp);
- ret = rdev->ops->get_mpp(&rdev->wiphy, dev, dst, mpp, pinfo);
- trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
- return ret;
-}
-
static inline int rdev_dump_mpath(struct cfg80211_registered_device *rdev,
struct net_device *dev, int idx, u8 *dst,
u8 *next_hop, struct mpath_info *pinfo)
@@ -284,20 +271,7 @@
int ret;
trace_rdev_dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop);
ret = rdev->ops->dump_mpath(&rdev->wiphy, dev, idx, dst, next_hop,
- pinfo);
- trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
- return ret;
-}
-
-static inline int rdev_dump_mpp(struct cfg80211_registered_device *rdev,
- struct net_device *dev, int idx, u8 *dst,
- u8 *mpp, struct mpath_info *pinfo)
-
-{
- int ret;
-
- trace_rdev_dump_mpp(&rdev->wiphy, dev, idx, dst, mpp);
- ret = rdev->ops->dump_mpp(&rdev->wiphy, dev, idx, dst, mpp, pinfo);
+ pinfo);
trace_rdev_return_int_mpath_info(&rdev->wiphy, ret, pinfo);
return ret;
}
@@ -348,27 +322,6 @@
return ret;
}
-static inline int rdev_join_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev,
- struct ocb_setup *setup)
-{
- int ret;
- trace_rdev_join_ocb(&rdev->wiphy, dev, setup);
- ret = rdev->ops->join_ocb(&rdev->wiphy, dev, setup);
- trace_rdev_return_int(&rdev->wiphy, ret);
- return ret;
-}
-
-static inline int rdev_leave_ocb(struct cfg80211_registered_device *rdev,
- struct net_device *dev)
-{
- int ret;
- trace_rdev_leave_ocb(&rdev->wiphy, dev);
- ret = rdev->ops->leave_ocb(&rdev->wiphy, dev);
- trace_rdev_return_int(&rdev->wiphy, ret);
- return ret;
-}
-
static inline int rdev_change_bss(struct cfg80211_registered_device *rdev,
struct net_device *dev,
struct bss_parameters *params)
@@ -993,28 +946,4 @@
return ret;
}
-static inline int
-rdev_tdls_channel_switch(struct cfg80211_registered_device *rdev,
- struct net_device *dev, const u8 *addr,
- u8 oper_class, struct cfg80211_chan_def *chandef)
-{
- int ret;
-
- trace_rdev_tdls_channel_switch(&rdev->wiphy, dev, addr, oper_class,
- chandef);
- ret = rdev->ops->tdls_channel_switch(&rdev->wiphy, dev, addr,
- oper_class, chandef);
- trace_rdev_return_int(&rdev->wiphy, ret);
- return ret;
-}
-
-static inline void
-rdev_tdls_cancel_channel_switch(struct cfg80211_registered_device *rdev,
- struct net_device *dev, const u8 *addr)
-{
- trace_rdev_tdls_cancel_channel_switch(&rdev->wiphy, dev, addr);
- rdev->ops->tdls_cancel_channel_switch(&rdev->wiphy, dev, addr);
- trace_rdev_return_void(&rdev->wiphy);
-}
-
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index ec2e3b5..78d0648 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -56,7 +56,6 @@
#include <net/cfg80211.h>
#include "core.h"
#include "reg.h"
-#include "rdev-ops.h"
#include "regdb.h"
#include "nl80211.h"
@@ -67,12 +66,6 @@
#define REG_DBG_PRINT(args...)
#endif
-/*
- * Grace period we give before making sure all current interfaces reside on
- * channels allowed by the current regulatory domain.
- */
-#define REG_ENFORCE_GRACE_MS 60000
-
/**
* enum reg_request_treatment - regulatory request treatment
*
@@ -217,9 +210,6 @@
struct ieee80211_channel chan;
};
-static void reg_check_chans_work(struct work_struct *work);
-static DECLARE_DELAYED_WORK(reg_check_chans, reg_check_chans_work);
-
static void reg_todo(struct work_struct *work);
static DECLARE_WORK(reg_work, reg_todo);
@@ -583,9 +573,8 @@
return get_cfg80211_regdom();
}
-static unsigned int
-reg_get_max_bandwidth_from_range(const struct ieee80211_regdomain *rd,
- const struct ieee80211_reg_rule *rule)
+unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
+ const struct ieee80211_reg_rule *rule)
{
const struct ieee80211_freq_range *freq_range = &rule->freq_range;
const struct ieee80211_freq_range *freq_range_tmp;
@@ -633,27 +622,6 @@
return end_freq - start_freq;
}
-unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd,
- const struct ieee80211_reg_rule *rule)
-{
- unsigned int bw = reg_get_max_bandwidth_from_range(rd, rule);
-
- if (rule->flags & NL80211_RRF_NO_160MHZ)
- bw = min_t(unsigned int, bw, MHZ_TO_KHZ(80));
- if (rule->flags & NL80211_RRF_NO_80MHZ)
- bw = min_t(unsigned int, bw, MHZ_TO_KHZ(40));
-
- /*
- * HT40+/HT40- limits are handled per-channel. Only limit BW if both
- * are not allowed.
- */
- if (rule->flags & NL80211_RRF_NO_HT40MINUS &&
- rule->flags & NL80211_RRF_NO_HT40PLUS)
- bw = min_t(unsigned int, bw, MHZ_TO_KHZ(20));
-
- return bw;
-}
-
/* Sanity check on a regulatory rule */
static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule)
{
@@ -978,16 +946,6 @@
channel_flags |= IEEE80211_CHAN_NO_OFDM;
if (rd_flags & NL80211_RRF_NO_OUTDOOR)
channel_flags |= IEEE80211_CHAN_INDOOR_ONLY;
- if (rd_flags & NL80211_RRF_GO_CONCURRENT)
- channel_flags |= IEEE80211_CHAN_GO_CONCURRENT;
- if (rd_flags & NL80211_RRF_NO_HT40MINUS)
- channel_flags |= IEEE80211_CHAN_NO_HT40MINUS;
- if (rd_flags & NL80211_RRF_NO_HT40PLUS)
- channel_flags |= IEEE80211_CHAN_NO_HT40PLUS;
- if (rd_flags & NL80211_RRF_NO_80MHZ)
- channel_flags |= IEEE80211_CHAN_NO_80MHZ;
- if (rd_flags & NL80211_RRF_NO_160MHZ)
- channel_flags |= IEEE80211_CHAN_NO_160MHZ;
return channel_flags;
}
@@ -1528,102 +1486,6 @@
wiphy->reg_notifier(wiphy, request);
}
-static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
-{
- struct ieee80211_channel *ch;
- struct cfg80211_chan_def chandef;
- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
- bool ret = true;
-
- wdev_lock(wdev);
-
- if (!wdev->netdev || !netif_running(wdev->netdev))
- goto out;
-
- switch (wdev->iftype) {
- case NL80211_IFTYPE_AP:
- case NL80211_IFTYPE_P2P_GO:
- if (!wdev->beacon_interval)
- goto out;
-
- ret = cfg80211_reg_can_beacon(wiphy,
- &wdev->chandef, wdev->iftype);
- break;
- case NL80211_IFTYPE_ADHOC:
- if (!wdev->ssid_len)
- goto out;
-
- ret = cfg80211_reg_can_beacon(wiphy,
- &wdev->chandef, wdev->iftype);
- break;
- case NL80211_IFTYPE_STATION:
- case NL80211_IFTYPE_P2P_CLIENT:
- if (!wdev->current_bss ||
- !wdev->current_bss->pub.channel)
- goto out;
-
- ch = wdev->current_bss->pub.channel;
- if (rdev->ops->get_channel &&
- !rdev_get_channel(rdev, wdev, &chandef))
- ret = cfg80211_chandef_usable(wiphy, &chandef,
- IEEE80211_CHAN_DISABLED);
- else
- ret = !(ch->flags & IEEE80211_CHAN_DISABLED);
- break;
- case NL80211_IFTYPE_MONITOR:
- case NL80211_IFTYPE_AP_VLAN:
- case NL80211_IFTYPE_P2P_DEVICE:
- /* no enforcement required */
- break;
- default:
- /* others not implemented for now */
- WARN_ON(1);
- break;
- }
-
-out:
- wdev_unlock(wdev);
- return ret;
-}
-
-static void reg_leave_invalid_chans(struct wiphy *wiphy)
-{
- struct wireless_dev *wdev;
- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
-
- ASSERT_RTNL();
-
- list_for_each_entry(wdev, &rdev->wdev_list, list)
- if (!reg_wdev_chan_valid(wiphy, wdev))
- cfg80211_leave(rdev, wdev);
-}
-
-static void reg_check_chans_work(struct work_struct *work)
-{
- struct cfg80211_registered_device *rdev;
-
- REG_DBG_PRINT("Verifying active interfaces after reg change\n");
- rtnl_lock();
-
- list_for_each_entry(rdev, &cfg80211_rdev_list, list)
- if (!(rdev->wiphy.regulatory_flags &
- REGULATORY_IGNORE_STALE_KICKOFF))
- reg_leave_invalid_chans(&rdev->wiphy);
-
- rtnl_unlock();
-}
-
-static void reg_check_channels(void)
-{
- /*
- * Give usermode a chance to do something nicer (move to another
- * channel, orderly disconnection), before forcing a disconnection.
- */
- mod_delayed_work(system_power_efficient_wq,
- ®_check_chans,
- msecs_to_jiffies(REG_ENFORCE_GRACE_MS));
-}
-
static void wiphy_update_regulatory(struct wiphy *wiphy,
enum nl80211_reg_initiator initiator)
{
@@ -1663,8 +1525,6 @@
wiphy = &rdev->wiphy;
wiphy_update_regulatory(wiphy, initiator);
}
-
- reg_check_channels();
}
static void handle_channel_custom(struct wiphy *wiphy,
@@ -1705,23 +1565,10 @@
if (max_bandwidth_khz < MHZ_TO_KHZ(160))
bw_flags |= IEEE80211_CHAN_NO_160MHZ;
- chan->dfs_state_entered = jiffies;
- chan->dfs_state = NL80211_DFS_USABLE;
-
- chan->beacon_found = false;
chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags;
chan->max_antenna_gain = (int) MBI_TO_DBI(power_rule->max_antenna_gain);
chan->max_reg_power = chan->max_power =
(int) MBM_TO_DBM(power_rule->max_eirp);
-
- if (chan->flags & IEEE80211_CHAN_RADAR) {
- if (reg_rule->dfs_cac_ms)
- chan->dfs_cac_ms = reg_rule->dfs_cac_ms;
- else
- chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS;
- }
-
- chan->max_power = chan->max_reg_power;
}
static void handle_band_custom(struct wiphy *wiphy,
@@ -1913,7 +1760,7 @@
reg_process_hint_driver(struct wiphy *wiphy,
struct regulatory_request *driver_request)
{
- const struct ieee80211_regdomain *regd, *tmp;
+ const struct ieee80211_regdomain *regd;
enum reg_request_treatment treatment;
treatment = __reg_process_hint_driver(driver_request);
@@ -1933,10 +1780,7 @@
reg_free_request(driver_request);
return REG_REQ_IGNORE;
}
-
- tmp = get_wiphy_regdom(wiphy);
rcu_assign_pointer(wiphy->regd, regd);
- rcu_free_regdom(tmp);
}
@@ -1995,8 +1839,11 @@
return REG_REQ_IGNORE;
return REG_REQ_ALREADY_SET;
}
-
- if (regdom_changes(country_ie_request->alpha2))
+ /*
+ * Two consecutive Country IE hints on the same wiphy.
+ * This should be picked up early by the driver/stack
+ */
+ if (WARN_ON(regdom_changes(country_ie_request->alpha2)))
return REG_REQ_OK;
return REG_REQ_ALREADY_SET;
}
@@ -2084,10 +1931,8 @@
/* This is required so that the orig_* parameters are saved */
if (treatment == REG_REQ_ALREADY_SET && wiphy &&
- wiphy->regulatory_flags & REGULATORY_STRICT_REG) {
+ wiphy->regulatory_flags & REGULATORY_STRICT_REG)
wiphy_update_regulatory(wiphy, reg_request->initiator);
- reg_check_channels();
- }
return;
@@ -2968,7 +2813,6 @@
cancel_work_sync(®_work);
cancel_delayed_work_sync(®_timeout);
- cancel_delayed_work_sync(®_check_chans);
/* Lock to suppress warnings */
rtnl_lock();
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 969c09f..f365a0c 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -80,18 +80,9 @@
if (!request)
return -ENOMEM;
- if (wdev->conn->params.channel) {
- enum ieee80211_band band = wdev->conn->params.channel->band;
- struct ieee80211_supported_band *sband =
- wdev->wiphy->bands[band];
-
- if (!sband) {
- kfree(request);
- return -EINVAL;
- }
+ if (wdev->conn->params.channel)
request->channels[0] = wdev->conn->params.channel;
- request->rates[band] = (1 << sband->n_bitrates) - 1;
- } else {
+ else {
int i = 0, j;
enum ieee80211_band band;
struct ieee80211_supported_band *bands;
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index d9d146d..c9b6b8e 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -600,11 +600,6 @@
TP_ARGS(wiphy, netdev)
);
-DEFINE_EVENT(wiphy_netdev_evt, rdev_leave_ocb,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
- TP_ARGS(wiphy, netdev)
-);
-
DEFINE_EVENT(wiphy_netdev_evt, rdev_flush_pmksa,
TP_PROTO(struct wiphy *wiphy, struct net_device *netdev),
TP_ARGS(wiphy, netdev)
@@ -685,34 +680,9 @@
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac))
);
-DECLARE_EVENT_CLASS(station_del,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
- struct station_del_parameters *params),
- TP_ARGS(wiphy, netdev, params),
- TP_STRUCT__entry(
- WIPHY_ENTRY
- NETDEV_ENTRY
- MAC_ENTRY(sta_mac)
- __field(u8, subtype)
- __field(u16, reason_code)
- ),
- TP_fast_assign(
- WIPHY_ASSIGN;
- NETDEV_ASSIGN;
- MAC_ASSIGN(sta_mac, params->mac);
- __entry->subtype = params->subtype;
- __entry->reason_code = params->reason_code;
- ),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", station mac: " MAC_PR_FMT
- ", subtype: %u, reason_code: %u",
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(sta_mac),
- __entry->subtype, __entry->reason_code)
-);
-
-DEFINE_EVENT(station_del, rdev_del_station,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
- struct station_del_parameters *params),
- TP_ARGS(wiphy, netdev, params)
+DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_del_station,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, const u8 *mac),
+ TP_ARGS(wiphy, netdev, mac)
);
DEFINE_EVENT(wiphy_netdev_mac_evt, rdev_get_station,
@@ -831,51 +801,6 @@
MAC_PR_ARG(next_hop))
);
-TRACE_EVENT(rdev_get_mpp,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
- u8 *dst, u8 *mpp),
- TP_ARGS(wiphy, netdev, dst, mpp),
- TP_STRUCT__entry(
- WIPHY_ENTRY
- NETDEV_ENTRY
- MAC_ENTRY(dst)
- MAC_ENTRY(mpp)
- ),
- TP_fast_assign(
- WIPHY_ASSIGN;
- NETDEV_ASSIGN;
- MAC_ASSIGN(dst, dst);
- MAC_ASSIGN(mpp, mpp);
- ),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", destination: " MAC_PR_FMT
- ", mpp: " MAC_PR_FMT, WIPHY_PR_ARG, NETDEV_PR_ARG,
- MAC_PR_ARG(dst), MAC_PR_ARG(mpp))
-);
-
-TRACE_EVENT(rdev_dump_mpp,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int idx,
- u8 *dst, u8 *mpp),
- TP_ARGS(wiphy, netdev, idx, mpp, dst),
- TP_STRUCT__entry(
- WIPHY_ENTRY
- NETDEV_ENTRY
- MAC_ENTRY(dst)
- MAC_ENTRY(mpp)
- __field(int, idx)
- ),
- TP_fast_assign(
- WIPHY_ASSIGN;
- NETDEV_ASSIGN;
- MAC_ASSIGN(dst, dst);
- MAC_ASSIGN(mpp, mpp);
- __entry->idx = idx;
- ),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", index: %d, destination: "
- MAC_PR_FMT ", mpp: " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->idx, MAC_PR_ARG(dst),
- MAC_PR_ARG(mpp))
-);
-
TRACE_EVENT(rdev_return_int_mpath_info,
TP_PROTO(struct wiphy *wiphy, int ret, struct mpath_info *pinfo),
TP_ARGS(wiphy, ret, pinfo),
@@ -1321,22 +1246,6 @@
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(bssid), __entry->ssid)
);
-TRACE_EVENT(rdev_join_ocb,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
- const struct ocb_setup *setup),
- TP_ARGS(wiphy, netdev, setup),
- TP_STRUCT__entry(
- WIPHY_ENTRY
- NETDEV_ENTRY
- ),
- TP_fast_assign(
- WIPHY_ASSIGN;
- NETDEV_ASSIGN;
- ),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG)
-);
-
TRACE_EVENT(rdev_set_wiphy_params,
TP_PROTO(struct wiphy *wiphy, u32 changed),
TP_ARGS(wiphy, changed),
@@ -2032,48 +1941,6 @@
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), __entry->tsid)
);
-TRACE_EVENT(rdev_tdls_channel_switch,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
- const u8 *addr, u8 oper_class,
- struct cfg80211_chan_def *chandef),
- TP_ARGS(wiphy, netdev, addr, oper_class, chandef),
- TP_STRUCT__entry(
- WIPHY_ENTRY
- NETDEV_ENTRY
- MAC_ENTRY(addr)
- __field(u8, oper_class)
- CHAN_DEF_ENTRY
- ),
- TP_fast_assign(
- WIPHY_ASSIGN;
- NETDEV_ASSIGN;
- MAC_ASSIGN(addr, addr);
- CHAN_DEF_ASSIGN(chandef);
- ),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT
- " oper class %d, " CHAN_DEF_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr),
- __entry->oper_class, CHAN_DEF_PR_ARG)
-);
-
-TRACE_EVENT(rdev_tdls_cancel_channel_switch,
- TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
- const u8 *addr),
- TP_ARGS(wiphy, netdev, addr),
- TP_STRUCT__entry(
- WIPHY_ENTRY
- NETDEV_ENTRY
- MAC_ENTRY(addr)
- ),
- TP_fast_assign(
- WIPHY_ASSIGN;
- NETDEV_ASSIGN;
- MAC_ASSIGN(addr, addr);
- ),
- TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT,
- WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr))
-);
-
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/
@@ -2397,22 +2264,6 @@
NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
);
-TRACE_EVENT(cfg80211_ch_switch_started_notify,
- TP_PROTO(struct net_device *netdev,
- struct cfg80211_chan_def *chandef),
- TP_ARGS(netdev, chandef),
- TP_STRUCT__entry(
- NETDEV_ENTRY
- CHAN_DEF_ENTRY
- ),
- TP_fast_assign(
- NETDEV_ASSIGN;
- CHAN_DEF_ASSIGN(chandef);
- ),
- TP_printk(NETDEV_PR_FMT ", " CHAN_DEF_PR_FMT,
- NETDEV_PR_ARG, CHAN_DEF_PR_ARG)
-);
-
TRACE_EVENT(cfg80211_radar_event,
TP_PROTO(struct wiphy *wiphy, struct cfg80211_chan_def *chandef),
TP_ARGS(wiphy, chandef),
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 0b5bd58..2a1733a 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -442,8 +442,7 @@
break;
case cpu_to_le16(0):
if (iftype != NL80211_IFTYPE_ADHOC &&
- iftype != NL80211_IFTYPE_STATION &&
- iftype != NL80211_IFTYPE_OCB)
+ iftype != NL80211_IFTYPE_STATION)
return -1;
break;
}
@@ -520,7 +519,6 @@
memcpy(hdr.addr3, skb->data, ETH_ALEN);
hdrlen = 24;
break;
- case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_ADHOC:
/* DA SA BSSID */
memcpy(hdr.addr1, skb->data, ETH_ALEN);
@@ -940,7 +938,6 @@
if (dev->ieee80211_ptr->use_4addr)
break;
/* fall through */
- case NL80211_IFTYPE_OCB:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_ADHOC:
dev->priv_flags |= IFF_DONT_BRIDGE;
diff --git a/scripts/uninstall.sh b/scripts/uninstall.sh
index b46d3fe..1eb42b0 100755
--- a/scripts/uninstall.sh
+++ b/scripts/uninstall.sh
@@ -10,8 +10,8 @@
compr=""
fi
-for driver in $(find ${BACKPORT_DIR} -type f -name *.ko); do
- mod_name=${driver/${BACKPORT_DIR}/${KLIB}${KMODDIR}}${compr}
+for driver in $(find ${BACKPORT_PWD} -type f -name *.ko); do
+ mod_name=${driver/${BACKPORT_PWD}/${KLIB}${KMODDIR}}${compr}
echo " uninstall" $mod_name
rm -f $mod_name
done
diff --git a/versions b/versions
index 012034c..1be7d6d 100644
--- a/versions
+++ b/versions
@@ -1,3 +1,3 @@
-BACKPORTS_VERSION="v3.19-rc1-1-0-g74aaf28"
-BACKPORTED_KERNEL_VERSION="v3.19-rc1-0-g97bf6af"
+BACKPORTS_VERSION="v3.18-rc1-1-0-g1f4af51"
+BACKPORTED_KERNEL_VERSION="v3.18-rc1-0-gf114040"
BACKPORTED_KERNEL_NAME="Linux"