Update generic-x86-64 Linux kernel to 6.12 (#3767)

* Linux: Update kernel to 6.12.6

* Linux 6.12

* https://github.com/home-assistant/operating-system/pull/3767#discussion_r1899169881

* https://github.com/home-assistant/operating-system/pull/3767#discussion_r1899170543

* Add patch descriptions, kernel ver conditionals

Signed-off-by: Nick Venenga <nick@venenga.com>

* Remove extra zram compression algos

* Undo fragment files config change

...for platforms that didn't receive kernel updates

* Sort Dockerfile apt packages

* Add Upstream refs to patches

* Re-enable TC

* Restore v6.6.y kernel fragments

* Update buildroot to rebased branch

* Apply 6.12 migration only to generic-x86-64

* package/eq3_char_loop: port patch from RaspberryMatic by @jens-maus

* package/generic_raw_uart: port patch from RaspberryMatic by @jens-maus

* Restore buildroot-external/board/pc/patches/linux

It's used in ova and generic-aarch64 defconfigs. Keep the path removed from
generic-x86-64 defconfig.

* Split linux patches to be version-specific

The IPv6 reachability patch needs different context on 6.6.y and 6.12.y -
introduce version-specific linux directories. To avoid the need for extra
directory for version used in RPi, copy those patches to its patches directory.

* Replace removed Intel Skylake audio driver with Intel AVS

The Skylake driver was removed and should be now replaced either by Intel HD
Audio or Intel AVS. Remove the old options and enable AVS.

SND_SOC_INTEL_SKYLAKE=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:63)
SND_SOC_INTEL_SKL=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:64)
SND_SOC_INTEL_APL=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:65)
SND_SOC_INTEL_KBL=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:66)
SND_SOC_INTEL_GLK=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:67)
SND_SOC_INTEL_CNL=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:68)
SND_SOC_INTEL_CFL=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:69)
SND_SOC_INTEL_CML_H=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:70)
SND_SOC_INTEL_CML_LP=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:71)
SND_SOC_INTEL_SKYLAKE_FAMILY=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:72)
SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC=y not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:73)
SND_SOC_INTEL_SKYLAKE_COMMON=m not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:74)
-> a882f4d750

SND_SOC_INTEL_SST=m requested, actual = n (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:58)
-> 970d299b0a

* Remove I2C_COMPAT option

I2C_COMPAT=y not found (defined in /build/buildroot-external/board/pc/generic-x86-64/kernel.config:163)
-> 7e722083fc

* Correctly disable module compression after Kconfig change

The Kconfig structure was changed, there's now a top-level bool:
c7ff693fa2

---------

Signed-off-by: Nick Venenga <nick@venenga.com>
Co-authored-by: Jan Čermák <sairon@sairon.cz>
This commit is contained in:
Nick Venenga 2025-01-28 08:57:07 -05:00 committed by GitHub
parent 4919e4e26c
commit fbd5c2c751
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 6448 additions and 23 deletions

View File

@ -21,6 +21,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
# Build tools
RUN apt-get update && apt-get install -y --no-install-recommends \
automake \
bash \
bc \
binutils \
@ -30,6 +31,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
file \
git \
graphviz \
help2man \
jq \
make \
ncurses-dev \
@ -43,6 +45,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
rsync \
skopeo \
sudo \
texinfo \
unzip \
vim \
wget \

View File

@ -20,5 +20,5 @@
| ODROID-N2 | 6.6.73 |
| ODROID-XU4 | 6.6.73 |
| Generic aarch64 | 6.6.73 |
| Generic x86-64 | 6.6.73 |
| Generic x86-64 | 6.12.6 |
| Khadas VIM3 | 6.6.73 |

@ -1 +1 @@
Subproject commit 3784884466ddce383c02a467fed4a4334cba2c11
Subproject commit 71cba6c610ff6a6e7b07934a8e5587977f473d36

View File

@ -55,24 +55,12 @@ CONFIG_SND_HDA_I915=y
CONFIG_SND_SOC=m
CONFIG_SND_SOC_INTEL_SST_TOPLEVEL=y
CONFIG_SND_SOC_INTEL_SST=m
CONFIG_SND_SOC_INTEL_CATPT=m
CONFIG_SND_SST_ATOM_HIFI2_PLATFORM=m
CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_PCI=m
CONFIG_SND_SST_ATOM_HIFI2_PLATFORM_ACPI=m
CONFIG_SND_SOC_INTEL_SKYLAKE=m
CONFIG_SND_SOC_INTEL_SKL=m
CONFIG_SND_SOC_INTEL_APL=m
CONFIG_SND_SOC_INTEL_KBL=m
CONFIG_SND_SOC_INTEL_GLK=m
CONFIG_SND_SOC_INTEL_CNL=m
CONFIG_SND_SOC_INTEL_CFL=m
CONFIG_SND_SOC_INTEL_CML_H=m
CONFIG_SND_SOC_INTEL_CML_LP=m
CONFIG_SND_SOC_INTEL_SKYLAKE_FAMILY=m
CONFIG_SND_SOC_INTEL_SKYLAKE_HDAUDIO_CODEC=y
CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON=m
CONFIG_SND_SOC_ACPI_INTEL_MATCH=m
CONFIG_SND_SOC_INTEL_AVS=m
CONFIG_SND_SOC_INTEL_MACH=y
CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES=y
CONFIG_SND_SOC_INTEL_HDA_DSP_COMMON=m
@ -160,7 +148,6 @@ CONFIG_EDAC_IGEN6=m
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_COMPAT=y
CONFIG_I2C_CHARDEV=m
CONFIG_I2C_MUX=y
CONFIG_I2C_TINY_USB=m

View File

@ -4,7 +4,7 @@ BR2_DL_DIR="/cache/dl"
BR2_CCACHE=y
BR2_CCACHE_DIR="/cache/cc"
BR2_ENABLE_LTO=y
BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_HASSOS_PATH)/patches $(BR2_EXTERNAL_HASSOS_PATH)/board/pc/patches"
BR2_GLOBAL_PATCH_DIR="$(BR2_EXTERNAL_HASSOS_PATH)/patches"
BR2_SSP_REGULAR=y
BR2_TARGET_GENERIC_HOSTNAME="homeassistant"
BR2_TARGET_GENERIC_ISSUE="Welcome to Home Assistant"
@ -16,9 +16,9 @@ BR2_ROOTFS_POST_IMAGE_SCRIPT="$(BR2_EXTERNAL_HASSOS_PATH)/scripts/post-image.sh"
BR2_ROOTFS_POST_SCRIPT_ARGS="$(BR2_EXTERNAL_HASSOS_PATH)/board/pc/generic-x86-64 $(BR2_EXTERNAL_HASSOS_PATH)/board/pc/generic-x86-64/hassos-hook.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.6.73"
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.6"
BR2_LINUX_KERNEL_DEFCONFIG="x86_64"
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/hassos.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/docker.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/device-support.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/device-support-wireless.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/device-support-wireless-pci.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.6.y/device-support-pci.config $(BR2_EXTERNAL_HASSOS_PATH)/board/pc/generic-x86-64/kernel.config"
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.12.y/hassos.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.12.y/docker.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.12.y/device-support.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.12.y/device-support-wireless.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.12.y/device-support-wireless-pci.config $(BR2_EXTERNAL_HASSOS_PATH)/kernel/v6.12.y/device-support-pci.config $(BR2_EXTERNAL_HASSOS_PATH)/board/pc/generic-x86-64/kernel.config"
BR2_LINUX_KERNEL_LZ4=y
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y

View File

@ -0,0 +1,41 @@
CONFIG_IGB=y
CONFIG_IGC=m
CONFIG_NET_VENDOR_AQUANTIA=y
CONFIG_AQTION=m
CONFIG_NET_VENDOR_ATHEROS=y
CONFIG_ATL2=m
CONFIG_ATL1=m
CONFIG_ATL1C=m
CONFIG_ATL1E=m
CONFIG_ALX=m
CONFIG_NET_VENDOR_BROADCOM=y
CONFIG_B44=m
CONFIG_BCMGENET=m
CONFIG_BNX2=m
CONFIG_TIGON3=m
CONFIG_BNX2X=m
CONFIG_BNXT=m
CONFIG_BROADCOM_PHY=m
CONFIG_NET_VENDOR_STMICRO=y
CONFIG_STMMAC_ETH=m
CONFIG_STMMAC_PCI=m
CONFIG_MEDIA_PCI_SUPPORT=y
# PCI sound drivers
CONFIG_SND_PCI=y
CONFIG_SND_HDA_GENERIC=m
CONFIG_SND_HDA_INTEL=m
CONFIG_SND_HDA_CODEC_REALTEK=m
CONFIG_SND_HDA_CODEC_ANALOG=m
CONFIG_SND_HDA_CODEC_VIA=m
CONFIG_SND_HDA_CODEC_HDMI=m
# NVMe SSD support
CONFIG_NVME_CORE=y
CONFIG_BLK_DEV_NVME=y

View File

@ -0,0 +1,55 @@
# This fragment contains configuration options for WiFi drivers that are
# using PCI or PCIe bus. The device-support-wireless.config fragment must
# be included for this one to work as well as it contains common options.
# Atheros drivers
CONFIG_ATH5K=m
CONFIG_ATH5K_PCI=y
CONFIG_ATH10K_PCI=m
CONFIG_ATH11K=m
CONFIG_ATH11K_PCI=m
CONFIG_ATH12K=m
# Broadcom drivers
CONFIG_BRCMFMAC_PCIE=y
# Intel drivers
CONFIG_IWLEGACY=m
CONFIG_IWL3945=m
CONFIG_IWL4965=m
CONFIG_IWLWIFI=m
CONFIG_IWLDVM=m
CONFIG_IWLMVM=m
# Marvell drivers
CONFIG_MWIFIEX_PCIE=m
CONFIG_MWL8K=m
# Mediatek drivers
CONFIG_MT7603E=m
CONFIG_MT7615E=m
CONFIG_MT7915E=m
CONFIG_MT7921E=m
CONFIG_MT7996E=m
# Ralink drivers
CONFIG_RT2800PCI=m
# Realtek drivers
CONFIG_RTL8192CE=m
CONFIG_RTL8192SE=m
CONFIG_RTL8192DE=m
CONFIG_RTL8723AE=m
CONFIG_RTL8723BE=m
CONFIG_RTL8188EE=m
CONFIG_RTL8192EE=m
CONFIG_RTL8821AE=m
CONFIG_RTW88_8822BE=m
CONFIG_RTW88_8822CE=m
CONFIG_RTW88_8723DE=m
CONFIG_RTW88_8821CE=m
CONFIG_RTW89_8851BE=m
CONFIG_RTW89_8852AE=m
CONFIG_RTW89_8852BE=m
CONFIG_RTW89_8852CE=m

View File

@ -0,0 +1,81 @@
# This fragment contains configuration options for all platforms that
# should support WiFi connectivity over USB or SDIO. It does not contain
# drivers for PCI or PCIe devices - those need also inclusion of
# device-support-wireless-pci.config fragment.
# Atheros drivers
CONFIG_WLAN_VENDOR_ATH=y
CONFIG_ATH10K=m
CONFIG_ATH10K_SDIO=m
CONFIG_ATH10K_USB=m
CONFIG_ATH6KL=m
CONFIG_ATH6KL_SDIO=m
CONFIG_ATH6KL_USB=m
CONFIG_ATH9K=m
CONFIG_ATH9K_HTC=m
CONFIG_CARL9170=m
# Broadcom drivers
CONFIG_WLAN_VENDOR_BROADCOM=y
CONFIG_B43=m
CONFIG_B43_PHY_G=y
CONFIG_B43_PHY_N=y
CONFIG_B43_PHY_LP=y
CONFIG_B43_PHY_HT=y
CONFIG_BRCMSMAC=m
CONFIG_BRCMFMAC=m
CONFIG_BRCMFMAC_USB=y
# Intel drivers
# Note: enabling it here but Intel drivers are currently exclusively PCI
CONFIG_WLAN_VENDOR_INTEL=y
# Marvell drivers
CONFIG_WLAN_VENDOR_MARVELL=y
CONFIG_MWIFIEX=m
CONFIG_MWIFIEX_SDIO=m
CONFIG_MWIFIEX_USB=m
# Mediatek drivers
CONFIG_WLAN_VENDOR_MEDIATEK=y
CONFIG_MT7601U=m
CONFIG_MT7663U=m
CONFIG_MT7663S=m
CONFIG_MT76x0E=m
CONFIG_MT76x0U=m
CONFIG_MT76x2U=m
CONFIG_MT76x2E=m
CONFIG_MT7921S=m
CONFIG_MT7921U=m
# Ralink drivers
CONFIG_WLAN_VENDOR_RALINK=y
CONFIG_RT2500USB=m
CONFIG_RT73USB=m
CONFIG_RT2800USB=m
CONFIG_RT2800USB_RT3573=y
CONFIG_RT2800USB_RT53XX=y
CONFIG_RT2800USB_RT55XX=y
CONFIG_RT2800USB_UNKNOWN=y
CONFIG_RT2X00=m
# Realtek drivers
CONFIG_WLAN_VENDOR_REALTEK=y
CONFIG_RTL8XXXU=m
CONFIG_RTL8192CU=m
CONFIG_RTL_CARDS=m
CONFIG_RTW88=m
CONFIG_RTW88_8822BS=m
CONFIG_RTW88_8822BU=m
CONFIG_RTW88_8822CS=m
CONFIG_RTW88_8822CU=m
CONFIG_RTW88_8723DS=m
CONFIG_RTW88_8723DU=m
CONFIG_RTW88_8821CS=m
# Use OOT driver for 8821CU instead, see: https://github.com/home-assistant/operating-system/issues/3205
# CONFIG_RTW88_8821CU is not set
CONFIG_RTW89=m
# Staging drivers
CONFIG_STAGING=y
CONFIG_RTL8723BS=m

View File

@ -0,0 +1,182 @@
CONFIG_USB_GADGET=y
CONFIG_USBIP_CORE=m
CONFIG_USBIP_VHCI_HCD=m
CONFIG_USBIP_VHCI_HC_PORTS=8
CONFIG_USBIP_VHCI_NR_HCS=1
CONFIG_USBIP_HOST=m
CONFIG_USBIP_VUDC=m
CONFIG_USB_SERIAL=y
CONFIG_USB_SERIAL_CONSOLE=y
CONFIG_USB_SERIAL_GENERIC=y
CONFIG_USB_SERIAL_OPTION=m
CONFIG_USB_SERIAL_SIMPLE=m
CONFIG_USB_SERIAL_CP210X=m
CONFIG_USB_SERIAL_CYPRESS_M8=m
CONFIG_USB_SERIAL_FTDI_SIO=m
CONFIG_USB_SERIAL_PL2303=m
CONFIG_USB_SERIAL_CH341=m
CONFIG_USB_SERIAL_TI=m
CONFIG_USB_SERIAL_KEYSPAN=m
CONFIG_USB_ACM=m
# USB Network AdapterS
CONFIG_USB_NET_DRIVERS=m
CONFIG_USB_RTL8150=m
CONFIG_USB_RTL8152=m
CONFIG_USB_LAN78XX=m
CONFIG_USB_USBNET=m
CONFIG_USB_NET_AX8817X=m
CONFIG_USB_NET_AX88179_178A=m
CONFIG_USB_NET_CDCETHER=m
CONFIG_USB_NET_CDC_EEM=m
CONFIG_USB_NET_CDC_NCM=m
CONFIG_USB_NET_SMSC75XX=m
CONFIG_USB_NET_SMSC95XX=m
CONFIG_MEDIA_CEC_SUPPORT=y
# Required for BT drivers
CONFIG_SERIAL_DEV_BUS=y
# Bluetooth device drivers
CONFIG_BT_HCIBTUSB=m
CONFIG_BT_HCIBTUSB_BCM=y
CONFIG_BT_HCIBTUSB_MTK=y
CONFIG_BT_HCIBTUSB_RTL=y
CONFIG_BT_HCIBTSDIO=m
CONFIG_BT_HCIUART=m
CONFIG_BT_HCIUART_INTEL=y
CONFIG_BT_HCIUART_BCM=y
CONFIG_BT_HCIUART_RTL=y
CONFIG_BT_HCIUART_QCA=y
CONFIG_BT_HCIUART_AG6XX=y
CONFIG_BT_HCIUART_MRVL=y
CONFIG_BT_MRVL=m
CONFIG_BT_MRVL_SDIO=m
CONFIG_BT_MTKSDIO=m
CONFIG_BT_MTKUART=m
# Multimedia core support
CONFIG_MEDIA_SUPPORT=y
CONFIG_MEDIA_SUPPORT_FILTER=y
CONFIG_MEDIA_SUBDRV_AUTOSELECT=y
CONFIG_MEDIA_CONTROLLER=y
CONFIG_MEDIA_CONTROLLER_DVB=y
CONFIG_MEDIA_CAMERA_SUPPORT=y
CONFIG_MEDIA_ANALOG_TV_SUPPORT=y
CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y
CONFIG_MEDIA_USB_SUPPORT=y
CONFIG_VIDEO_DEV=y
CONFIG_VIDEO_V4L2_SUBDEV_API=y
CONFIG_VIDEO_TVEEPROM=m
CONFIG_VIDEOBUF2_CORE=m
CONFIG_VIDEOBUF2_V4L2=m
CONFIG_VIDEOBUF2_MEMOPS=m
CONFIG_VIDEOBUF2_VMALLOC=m
CONFIG_MEDIA_PLATFORM_SUPPORT=y
CONFIG_MEDIA_PLATFORM_DRIVERS=y
CONFIG_V4L_PLATFORM_DRIVERS=y
# Webcam devices
CONFIG_USB_VIDEO_CLASS=m
CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y
CONFIG_USB_GSPCA=m
CONFIG_USB_M5602=m
CONFIG_USB_STV06XX=m
CONFIG_USB_GL860=m
CONFIG_USB_GSPCA_BENQ=m
CONFIG_USB_GSPCA_CONEX=m
CONFIG_USB_GSPCA_CPIA1=m
CONFIG_USB_GSPCA_DTCS033=m
CONFIG_USB_GSPCA_ETOMS=m
CONFIG_USB_GSPCA_FINEPIX=m
CONFIG_USB_GSPCA_JEILINJ=m
CONFIG_USB_GSPCA_JL2005BCD=m
CONFIG_USB_GSPCA_KINECT=m
CONFIG_USB_GSPCA_KONICA=m
CONFIG_USB_GSPCA_MARS=m
CONFIG_USB_GSPCA_MR97310A=m
CONFIG_USB_GSPCA_NW80X=m
CONFIG_USB_GSPCA_OV519=m
CONFIG_USB_GSPCA_OV534=m
CONFIG_USB_GSPCA_OV534_9=m
CONFIG_USB_GSPCA_PAC207=m
CONFIG_USB_GSPCA_PAC7302=m
CONFIG_USB_GSPCA_PAC7311=m
CONFIG_USB_GSPCA_SE401=m
CONFIG_USB_GSPCA_SN9C2028=m
CONFIG_USB_GSPCA_SN9C20X=m
CONFIG_USB_GSPCA_SONIXB=m
CONFIG_USB_GSPCA_SONIXJ=m
CONFIG_USB_GSPCA_SPCA500=m
CONFIG_USB_GSPCA_SPCA501=m
CONFIG_USB_GSPCA_SPCA505=m
CONFIG_USB_GSPCA_SPCA506=m
CONFIG_USB_GSPCA_SPCA508=m
CONFIG_USB_GSPCA_SPCA561=m
CONFIG_USB_GSPCA_SPCA1528=m
CONFIG_USB_GSPCA_SQ905=m
CONFIG_USB_GSPCA_SQ905C=m
CONFIG_USB_GSPCA_SQ930X=m
CONFIG_USB_GSPCA_STK014=m
CONFIG_USB_GSPCA_STK1135=m
CONFIG_USB_GSPCA_STV0680=m
CONFIG_USB_GSPCA_SUNPLUS=m
CONFIG_USB_GSPCA_T613=m
CONFIG_USB_GSPCA_TOPRO=m
CONFIG_USB_GSPCA_TOUPTEK=m
CONFIG_USB_GSPCA_TV8532=m
CONFIG_USB_GSPCA_VC032X=m
CONFIG_USB_GSPCA_VICAM=m
CONFIG_USB_GSPCA_XIRLINK_CIT=m
CONFIG_USB_GSPCA_ZC3XX=m
CONFIG_USB_PWC=m
CONFIG_USB_PWC_INPUT_EVDEV=y
CONFIG_USB_S2255=m
# Analog capture USB devices
CONFIG_VIDEO_USBTV=m
CONFIG_VIDEO_PVRUSB2=m
CONFIG_VIDEO_PVRUSB2_SYSFS=y
CONFIG_VIDEO_PVRUSB2_DVB=y
CONFIG_VIDEO_HDPVR=m
CONFIG_VIDEO_STK1160=m
# Analog/digital capture USB devices
CONFIG_VIDEO_AU0828=m
CONFIG_VIDEO_AU0828_V4L2=y
CONFIG_VIDEO_CX231XX=m
CONFIG_VIDEO_CX231XX_ALSA=m
CONFIG_VIDEO_CX231XX_DVB=m
CONFIG_VIDEO_CX2341X=m
# Webcam/capture (analog/digital) USB devices
CONFIG_VIDEO_EM28XX=m
CONFIG_VIDEO_EM28XX_V4L2=m
CONFIG_VIDEO_EM28XX_ALSA=m
CONFIG_VIDEO_EM28XX_DVB=m
# Audio devices (USB/PCI)
CONFIG_SND_USB_AUDIO=m
# GPIO support
CONFIG_GPIOLIB=y
CONFIG_GPIO_SYSFS=y
# Can Bus support
CONFIG_CAN=m
CONFIG_CAN_RAW=m
CONFIG_CAN_VCAN=m
CONFIG_CAN_SLCAN=m
CONFIG_CAN_DEV=m
CONFIG_CAN_GS_USB=m
CONFIG_CAN_PEAK_USB=m
# 1-wire
CONFIG_W1=y
CONFIG_W1_MASTER_DS2490=m
CONFIG_W1_MASTER_DS2482=m
CONFIG_W1_MASTER_GPIO=m

View File

@ -0,0 +1,74 @@
CONFIG_POSIX_MQUEUE=y
CONFIG_CFS_BANDWIDTH=y
CONFIG_FAIR_GROUP_SCHED=y
CONFIG_NET_SCHED=y
# CONFIG_RT_GROUP_SCHED is not set
CONFIG_CGROUPS=y
CONFIG_CPUSETS=y
CONFIG_BLK_CGROUP=y
CONFIG_BLK_DEV_THROTTLING=y
CONFIG_CGROUP_SCHED=y
CONFIG_CGROUP_PIDS=y
CONFIG_CGROUP_FREEZER=y
CONFIG_CGROUP_DEVICE=y
CONFIG_CGROUP_CPUACCT=y
CONFIG_CGROUP_PERF=y
CONFIG_NET_CLS_CGROUP=y
CONFIG_CGROUP_NET_PRIO=y
CONFIG_CGROUP_BPF=y
CONFIG_BPF_SYSCALL=y
CONFIG_MEMCG=y
CONFIG_NAMESPACES=y
CONFIG_USER_NS=y
CONFIG_PID_NS=y
CONFIG_IPC_NS=y
CONFIG_UTS_NS=y
CONFIG_NETDEVICES=y
CONFIG_DUMMY=m
CONFIG_MACVLAN=m
CONFIG_IPVLAN=m
CONFIG_VXLAN=m
CONFIG_INET=y
CONFIG_IPV6=y
CONFIG_INET_ESP=m
CONFIG_NETCONSOLE=y
CONFIG_VETH=y
CONFIG_NETFILTER=y
CONFIG_NF_CONNTRACK=y
CONFIG_NF_NAT=y
CONFIG_IP6_NF_IPTABLES=y
CONFIG_IP6_NF_FILTER=y
CONFIG_IP6_NF_MANGLE=y
CONFIG_IP6_NF_NAT=y
CONFIG_NETFILTER_ADVANCED=y
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
CONFIG_NETFILTER_XT_MATCH_IPVS=y
CONFIG_IP_VS=y
CONFIG_IP_VS_RR=y
CONFIG_IP_VS_NFCT=y
CONFIG_IP_NF_IPTABLES=y
CONFIG_IP_NF_FILTER=y
CONFIG_IP_NF_NAT=y
CONFIG_IP_NF_TARGET_MASQUERADE=y
CONFIG_IP_NF_TARGET_REDIRECT=y
CONFIG_BRIDGE=y
CONFIG_BRIDGE_NETFILTER=y
CONFIG_XFRM_USER=m
CONFIG_NET_L3_MASTER_DEV=y
CONFIG_EXT4_FS=y
CONFIG_EXT4_FS_POSIX_ACL=y
CONFIG_EXT4_FS_SECURITY=y
CONFIG_OVERLAY_FS=y
# CONFIG_OVERLAY_FS_METACOPY is not set
# CONFIG_OVERLAY_FS_REDIRECT_DIR is not set
CONFIG_CRYPTO_CCM=y
CONFIG_CRYPTO_GCM=y
CONFIG_CRYPTO_CMAC=y

View File

@ -0,0 +1,210 @@
CONFIG_LOCALVERSION="-haos"
CONFIG_EXPERT=y
# GCC plugins are disabled by linux.mk, disable them here to reduce
# linux-diff-config noise
CONFIG_GCC_PLUGINS=n
CONFIG_CMDLINE=""
CONFIG_PANIC_TIMEOUT=5
CONFIG_PREEMPT=y
# CONFIG_PREEMPT_VOLUNTARY is not set
# CONFIG_DEBUG_PREEMPT is not set
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
# CONFIG_MODULE_COMPRESS is not set
CONFIG_FW_LOADER_COMPRESS=y
CONFIG_FW_LOADER_COMPRESS_ZSTD=y
CONFIG_ZRAM=y
CONFIG_ZRAM_BACKEND_LZ4=y
CONFIG_ZSWAP=y
CONFIG_ZSWAP_DEFAULT_ON=y
CONFIG_ZSWAP_COMPRESSOR_DEFAULT_LZ4=y
CONFIG_ZSWAP_ZPOOL_DEFAULT_ZSMALLOC=y
CONFIG_ZSMALLOC=y
CONFIG_LRU_GEN=y
CONFIG_LRU_GEN_ENABLED=y
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
CONFIG_MISC_FILESYSTEMS=y
CONFIG_BLOCK=y
CONFIG_EROFS_FS=y
CONFIG_EXT4_FS=y
CONFIG_MSDOS_FS=y
CONFIG_VFAT_FS=y
CONFIG_SQUASHFS=y
CONFIG_SQUASHFS_XATTR=y
CONFIG_SQUASHFS_LZ4=y
CONFIG_BTRFS_FS=m
CONFIG_NTFS3_FS=m
CONFIG_EXFAT_FS=m
CONFIG_MD=y
CONFIG_BLK_DEV_DM=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_DM_VERITY=y
CONFIG_SECCOMP=y
CONFIG_SECCOMP_FILTER=y
CONFIG_AUDIT=y
CONFIG_DEFAULT_SECURITY_APPARMOR=y
# CONFIG_DEFAULT_SECURITY_DAC is not set
# CONFIG_DEFAULT_SECURITY_SELINUX is not set
CONFIG_SECURITY=y
CONFIG_SECURITY_APPARMOR=y
# CONFIG_SECURITY_SELINUX is not set
CONFIG_LSM="apparmor"
CONFIG_CRYPTO=y
CONFIG_CRYPTO_LZ4=y
CONFIG_CRYPTO_MICHAEL_MIC=y
CONFIG_CRYPTO_USER=m
CONFIG_CRYPTO_USER_API_HASH=m
CONFIG_CRYPTO_USER_API_SKCIPHER=m
CONFIG_CRYPTO_USER_API_RNG=m
CONFIG_CRYPTO_USER_API_AEAD=m
CONFIG_PARTITION_ADVANCED=y
CONFIG_EFI_PARTITION=y
CONFIG_MSDOS_PARTITION=y
# CONFIG_LOGO is not set
# CONFIG_DEBUG_STACK_USAGE is not set
CONFIG_BT=m
CONFIG_BT_BREDR=y
CONFIG_BT_RFCOMM=m
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_LE=y
CONFIG_BT_BNEP=m
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=m
CONFIG_BT_LEDS=y
CONFIG_IPV6=y
CONFIG_IPV6_ROUTER_PREF=y
CONFIG_IPV6_REACHABILITY_PROBE=y
CONFIG_IPV6_SIT=m
CONFIG_IP_ADVANCED_ROUTER=y
CONFIG_IP_MULTIPLE_TABLES=y
CONFIG_IP_MROUTE=y
CONFIG_IPV6_MULTIPLE_TABLES=y
CONFIG_IPV6_MROUTE=y
CONFIG_MPTCP=y
CONFIG_MPTCP_IPV6=y
CONFIG_NF_TABLES=m
CONFIG_NF_TABLES_INET=y
CONFIG_NF_TABLES_NETDEV=y
CONFIG_NF_TPROXY_IPV4=m
CONFIG_NF_TABLES_IPV4=y
CONFIG_NF_TABLES_ARP=y
CONFIG_NF_TPROXY_IPV6=m
CONFIG_NF_TABLES_IPV6=y
CONFIG_NF_TABLES_BRIDGE=m
CONFIG_NF_FLOW_TABLE=m
CONFIG_NFT_NUMGEN=m
CONFIG_NFT_CT=m
CONFIG_NFT_FLOW_OFFLOAD=m
CONFIG_NFT_CONNLIMIT=m
CONFIG_NFT_LOG=m
CONFIG_NFT_LIMIT=m
CONFIG_NFT_MASQ=m
CONFIG_NFT_REDIR=m
CONFIG_NFT_NAT=m
CONFIG_NFT_TUNNEL=m
CONFIG_NFT_QUEUE=m
CONFIG_NFT_QUOTA=m
CONFIG_NFT_REJECT=m
CONFIG_NFT_REJECT_INET=m
CONFIG_NFT_COMPAT=m
CONFIG_NFT_HASH=m
CONFIG_NFT_FIB=m
CONFIG_NFT_FIB_INET=m
CONFIG_NFT_XFRM=m
CONFIG_NFT_SOCKET=m
CONFIG_NFT_OSF=m
CONFIG_NFT_TPROXY=m
CONFIG_NFT_SYNPROXY=m
CONFIG_NFT_DUP_NETDEV=m
CONFIG_NFT_FWD_NETDEV=m
CONFIG_NFT_FIB_NETDEV=m
CONFIG_NFT_REJECT_NETDEV=m
CONFIG_NFT_REJECT_IPV4=m
CONFIG_NFT_DUP_IPV4=m
CONFIG_NFT_FIB_IPV4=m
CONFIG_NFT_REJECT_IPV6=m
CONFIG_NFT_DUP_IPV6=m
CONFIG_NFT_FIB_IPV6=m
CONFIG_NFT_BRIDGE_META=m
CONFIG_NFT_BRIDGE_REJECT=m
CONFIG_NETFILTER_NETLINK_QUEUE=m
CONFIG_NETFILTER_XT_SET=m
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m
CONFIG_NETFILTER_XT_MARK=m
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
CONFIG_IP_SET=m
CONFIG_IP_SET_BITMAP_IP=m
CONFIG_IP_SET_BITMAP_IPMAC=m
CONFIG_IP_SET_BITMAP_PORT=m
CONFIG_IP_SET_HASH_IP=m
CONFIG_IP_SET_HASH_IPMARK=m
CONFIG_IP_SET_HASH_IPPORT=m
CONFIG_IP_SET_HASH_IPPORTIP=m
CONFIG_IP_SET_HASH_IPPORTNET=m
CONFIG_IP_SET_HASH_IPMAC=m
CONFIG_IP_SET_HASH_MAC=m
CONFIG_IP_SET_HASH_NETPORTNET=m
CONFIG_IP_SET_HASH_NET=m
CONFIG_IP_SET_HASH_NETNET=m
CONFIG_IP_SET_HASH_NETPORT=m
CONFIG_IP_SET_HASH_NETIFACE=m
CONFIG_IP_SET_LIST_SET=m
CONFIG_IP_VS=m
CONFIG_IP_VS_IPV6=y
CONFIG_TUN=y
CONFIG_VLAN_8021Q=m
CONFIG_VLAN_8021Q_GVRP=y
CONFIG_VLAN_8021Q_MVRP=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_FQ_CODEL=m
CONFIG_WIRELESS=y
CONFIG_WEXT_CORE=y
CONFIG_WEXT_PROC=y
CONFIG_CFG80211=m
CONFIG_CFG80211_WEXT=y
CONFIG_CIFS=m
CONFIG_CIFS_XATTR=y
CONFIG_CIFS_POSIX=y
CONFIG_CIFS_DFS_UPCALL=y
CONFIG_WIREGUARD=m
CONFIG_HID=y
CONFIG_HIDRAW=y
CONFIG_UHID=y
CONFIG_NLS=y
CONFIG_NLS_DEFAULT="utf8"
CONFIG_NLS_CODEPAGE_437=y
CONFIG_NLS_ASCII=y
CONFIG_NLS_ISO8859_1=y
CONFIG_NLS_UTF8=y

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
KernelDrivers/eq3_char_loop.c: updated to latest 1.1 version
Upstream: Not applicable
Signed-off-by: Jens Maus <mail@jens-maus.de>
--- ./KernelDrivers/eq3_char_loop.c.orig 2017-05-14 22:57:19.109181928 +0200
@ -42,7 +44,7 @@ Signed-off-by: Jens Maus <mail@jens-maus.de>
if(ret < 0)
{
- printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() retrun error:");
+ printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() return error: %ld", ret);
+ printk( KERN_INFO EQ3LOOP_DRIVER_NAME ": eq3loop_write_master() return error: %zd", ret);
}
if( ret > 0 || CIRC_CNT(channel->master2slave_buf.head,channel->master2slave_buf.tail,BUFSIZE) )
{
@ -110,4 +112,4 @@ Signed-off-by: Jens Maus <mail@jens-maus.de>
MODULE_DESCRIPTION("eQ-3 IPC loopback char driver");
MODULE_LICENSE("GPL");
-
+MODULE_VERSION("1.1");
+MODULE_VERSION("1.2");

View File

@ -0,0 +1,17 @@
Remove llseek NULL'd in 6.0 (868941b) removed in 6.12 (cb787f4)
Signed-off-by: Nick Venenga <nick@venenga.com>
Upstream: https://github.com/jens-maus/occu/pull/1
--- a/KernelDrivers/eq3_char_loop.c
+++ b/KernelDrivers/eq3_char_loop.c
@@ -898,7 +898,9 @@ static int eq3loop_open(struct inode *inode, struct file *filp)
static struct file_operations eq3loop_fops = {
.owner = THIS_MODULE,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
.llseek = no_llseek,
+#endif
.read = eq3loop_read,
.write = eq3loop_write,
.open = eq3loop_open,

View File

@ -0,0 +1,35 @@
From 4b2a1464f3b619daaf0f6c664c954a42c4b7ce00 Mon Sep 17 00:00:00 2001
From: Rudi Heitbaum <rudi@heitbaum.com>
Date: Sat, 26 Oct 2024 11:06:10 +0000
Subject: [PATCH] stop using no_llseek
Since commit 868941b ("fs: remove no_llseek"), no_llseek() is
simply defined to be NULL, and a NULL llseek means seeking is
unsupported.
refs:
- https://github.com/torvalds/linux/commit/cb787f4ac0c2e439ea8d7e6387b925f74576bdf8
- https://github.com/torvalds/linux/commit/868941b14441282ba08761b770fc6cad69d5bdb7
no_llseek has been hard dropped in linux-6.12
Signed-off-by: Rudi Heitbaum <rudi@heitbaum.com>
Upstream: https://github.com/google/gasket-driver/pull/35
---
src/gasket_core.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/gasket_core.c b/src/gasket_core.c
index b1c2726..5402e2a 100644
--- a/src/gasket_core.c
+++ b/src/gasket_core.c
@@ -1373,7 +1373,9 @@ static long gasket_ioctl(struct file *filp, uint cmd, ulong arg)
/* File operations for all Gasket devices. */
static const struct file_operations gasket_file_ops = {
.owner = THIS_MODULE,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
.llseek = no_llseek,
+#endif
.mmap = gasket_mmap,
.open = gasket_open,
.release = gasket_release,

View File

@ -1,4 +1,4 @@
GASKET_VERSION = 09385d485812088e04a98a6e1227bf92663e0b59
GASKET_VERSION = 5815ee3908a46a415aac616ac7b9aedcb98a504c
GASKET_SITE = $(call github,google,gasket-driver,$(GASKET_VERSION))
GASKET_LICENSE = GPL-2.0
GASKET_LICENSE_FILES = LICENSE

View File

@ -0,0 +1,17 @@
Remove llseek NULL'd in 6.0 (868941b) removed in 6.12 (cb787f4)
Signed-off-by: Nick Venenga <nick@venenga.com>
Upstream: https://github.com/alexreinert/piVCCU/pull/533
--- a/kernel/generic_raw_uart.c
+++ b/kernel/generic_raw_uart.c
@@ -147,7 +147,9 @@ static int generic_raw_uart_get_device_type(struct generic_raw_uart_instance *in
static struct file_operations generic_raw_uart_fops =
{
.owner = THIS_MODULE,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 0, 0)
.llseek = no_llseek,
+#endif
.read = generic_raw_uart_read,
.write = generic_raw_uart_write,
.open = generic_raw_uart_open,

View File

@ -0,0 +1,19 @@
Replace `gpiochip_add` removed in 6.11 (3ff1180) with `gpiochip_add_data` added in 4.5 (b08ea35)
Signed-off-by: Nick Venenga <nick@venenga.com>
Upstream: https://github.com/alexreinert/piVCCU/pull/533
--- a/kernel/hb_rf_eth.c
+++ b/kernel/hb_rf_eth.c
@@ -715,7 +715,11 @@ static int __init hb_rf_eth_init(void)
gc.base = -1;
gc.can_sleep = false;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 5, 0)
err = gpiochip_add(&gc);
+#else
+ err = gpiochip_add_data(&gc, NULL);
+#endif
if (err)
goto failed_gc_create;

View File

@ -0,0 +1,87 @@
Change raw_uart_driver remove macro to define the function as void as in kernel 6.11
the platform_device remove function was changed to void (0edb555).
Upstream: Not applicable
Signed-off-by: Jens Maus <mail@jens-maus.de>
diff --git a/kernel/generic_raw_uart.h b/kernel/generic_raw_uart.h
index b865e22..791e5d0 100644
--- a/kernel/generic_raw_uart.h 2025-01-10 13:19:08.697184514 +0100
+++ b/kernel/generic_raw_uart.h 2025-01-10 13:28:43.311159893 +0100
@@ -93,6 +93,8 @@
extern bool generic_raw_uart_verify_dkey(struct device *dev, unsigned char *dkey, int dkey_len, unsigned char *skey, uint32_t *pkey, int bytes);
+#if LINUX_VERSION_CODE < KERNEL_VERSION(6, 11, 0)
+
#define module_raw_uart_driver(__module_name, __raw_uart_driver, __of_match) \
static struct generic_raw_uart *__raw_uart_driver##_raw_uart; \
static int __##__raw_uart_driver##_probe(struct platform_device *pdev) \
@@ -121,7 +123,7 @@
int err; \
struct device *dev = &pdev->dev; \
\
- err = generic_raw_uart_remove(__raw_uart_driver##_raw_uart); \
+ err = generic_raw_uart_remove(__raw_uart_driver##_raw_uart); \
if (err) \
{ \
dev_err(dev, "failed to remove generic_raw_uart module"); \
@@ -143,3 +145,57 @@
\
module_platform_driver(__raw_uart_driver_platform_driver); \
MODULE_DEVICE_TABLE(of, __of_match);
+
+#else
+
+#define module_raw_uart_driver(__module_name, __raw_uart_driver, __of_match) \
+ static struct generic_raw_uart *__raw_uart_driver##_raw_uart; \
+ static int __##__raw_uart_driver##_probe(struct platform_device *pdev) \
+ { \
+ struct device *dev = &pdev->dev; \
+ int err = __raw_uart_driver##_probe(pdev); \
+ \
+ if (err) \
+ { \
+ dev_err(dev, "failed to initialize generic_raw_uart module"); \
+ return err; \
+ } \
+ \
+ __raw_uart_driver##_raw_uart = generic_raw_uart_probe(dev, &__raw_uart_driver, NULL); \
+ if (IS_ERR_OR_NULL(__raw_uart_driver##_raw_uart)) \
+ { \
+ dev_err(dev, "failed to initialize generic_raw_uart module"); \
+ return PTR_ERR(__raw_uart_driver##_raw_uart); \
+ } \
+ \
+ return 0; \
+ } \
+ \
+ static void __##__raw_uart_driver##_remove(struct platform_device *pdev) \
+ { \
+ int err; \
+ struct device *dev = &pdev->dev; \
+ \
+ err = generic_raw_uart_remove(__raw_uart_driver##_raw_uart); \
+ if (err) \
+ { \
+ dev_err(dev, "failed to remove generic_raw_uart module"); \
+ } \
+ \
+ __raw_uart_driver##_remove(pdev); \
+ } \
+ \
+ static struct platform_driver __raw_uart_driver_platform_driver = { \
+ .probe = __##__raw_uart_driver##_probe, \
+ .remove = __##__raw_uart_driver##_remove, \
+ .driver = { \
+ .owner = THIS_MODULE, \
+ .name = __module_name, \
+ .of_match_table = __of_match, \
+ }, \
+ }; \
+ \
+ module_platform_driver(__raw_uart_driver_platform_driver); \
+ MODULE_DEVICE_TABLE(of, __of_match);
+
+#endif

View File

@ -1,4 +1,4 @@
RTL88X2BU_VERSION = 476ef38727cb539d7987d0cd1da3a8842df7bc58
RTL88X2BU_VERSION = 45ca59c3dd14d287853142fe761b403330dbb32d
RTL88X2BU_SITE = $(call github,cilynx,rtl88x2bu,$(RTL88X2BU_VERSION))
RTL88X2BU_LICENSE = GPL-2.0
RTL88X2BU_LICENSE_FILES = LICENSE

View File

@ -0,0 +1,52 @@
From 76591e4075194cf717dc085b8285912f706bcd46 Mon Sep 17 00:00:00 2001
From: Stefan Agner <stefan@agner.ch>
Date: Tue, 28 Mar 2023 12:02:10 +0200
Subject: [PATCH] ipv6: add option to explicitly enable reachability test
Systems which act as host as well as router might prefer the host
behavior. Currently the kernel does not allow to use IPv6 forwarding
globally and at the same time use route reachability probing.
Add a compile time flag to enable route reachability probe in any
case.
Signed-off-by: Stefan Agner <stefan@agner.ch>
---
net/ipv6/Kconfig | 9 +++++++++
net/ipv6/route.c | 3 ++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 08d4b7132d4c..242bf2eeb7ae 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -48,6 +48,15 @@ config IPV6_OPTIMISTIC_DAD
If unsure, say N.
+config IPV6_REACHABILITY_PROBE
+ bool "IPv6: Always use reachability probing (RFC 4191)"
+ help
+ By default reachability probing is disabled on router devices (when
+ IPv6 forwarding is enabled). This option explicitly enables
+ reachability probing always.
+
+ If unsure, say N.
+
config INET6_AH
tristate "IPv6: AH transformation"
select XFRM_AH
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 56525b5b95a2..916769b9a772 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2211,7 +2211,8 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
strict |= flags & RT6_LOOKUP_F_IFACE;
strict |= flags & RT6_LOOKUP_F_IGNORE_LINKSTATE;
- if (READ_ONCE(net->ipv6.devconf_all->forwarding) == 0)
+ if (READ_ONCE(net->ipv6.devconf_all->forwarding) == 0 ||
+ IS_ENABLED(CONFIG_IPV6_REACHABILITY_PROBE))
strict |= RT6_LOOKUP_F_REACHABLE;
rcu_read_lock();

View File

@ -0,0 +1,650 @@
From f9037c133775498d0ff2f035a957ce4f294e4e81 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= <sairon@sairon.cz>
Date: Wed, 6 Mar 2024 13:25:41 +0100
Subject: [PATCH] Revert USB core changes causing issues with Z-Wave.me UZB
stick
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Workaround for issues described on GH [1] and reported in [2].
* Revert "USB: core: Fix oversight in SuperSpeed initialization"
This reverts commit 59cf445754566984fd55af19ba7146c76e6627bc.
* Revert "USB: core: Fix race by not overwriting udev->descriptor in hub_port_init()"
This reverts commit ff33299ec8bb80cdcc073ad9c506bd79bb2ed20b.
* Revert "USB: core: Change usb_get_device_descriptor() API"
This reverts commit de28e469da75359a2bb8cd8778b78aa64b1be1f4.
* Revert "USB: core: Unite old scheme and new scheme descriptor reads"
This reverts commit 85d07c55621676d47d873d2749b88f783cd4d5a1.
[1] https://github.com/home-assistant/operating-system/issues/2995
[2] https://lore.kernel.org/linux-usb/1e954652-dfb3-4248-beea-b8a449128ff0@sairon.cz/
Signed-off-by: Jan Čermák <sairon@sairon.cz>
---
drivers/usb/core/hcd.c | 10 +-
drivers/usb/core/hub.c | 336 ++++++++++++++++---------------------
drivers/usb/core/message.c | 29 ++--
drivers/usb/core/usb.h | 4 +-
4 files changed, 166 insertions(+), 213 deletions(-)
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 12b6dfeaf658c..d895f6ebbc400 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -958,7 +958,6 @@ static int register_root_hub(struct usb_hcd *hcd)
{
struct device *parent_dev = hcd->self.controller;
struct usb_device *usb_dev = hcd->self.root_hub;
- struct usb_device_descriptor *descr;
const int devnum = 1;
int retval;
@@ -970,16 +969,13 @@ static int register_root_hub(struct usb_hcd *hcd)
mutex_lock(&usb_bus_idr_lock);
usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
- descr = usb_get_device_descriptor(usb_dev);
- if (IS_ERR(descr)) {
- retval = PTR_ERR(descr);
+ retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
+ if (retval != sizeof usb_dev->descriptor) {
mutex_unlock(&usb_bus_idr_lock);
dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
dev_name(&usb_dev->dev), retval);
- return retval;
+ return (retval < 0) ? retval : -EMSGSIZE;
}
- usb_dev->descriptor = *descr;
- kfree(descr);
if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) {
retval = usb_get_bos_descriptor(usb_dev);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 1ba3feb5e1900..ef1d63537a9b7 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -4742,67 +4742,6 @@ static int hub_enable_device(struct usb_device *udev)
return hcd->driver->enable_device(hcd, udev);
}
-/*
- * Get the bMaxPacketSize0 value during initialization by reading the
- * device's device descriptor. Since we don't already know this value,
- * the transfer is unsafe and it ignores I/O errors, only testing for
- * reasonable received values.
- *
- * For "old scheme" initialization, size will be 8 so we read just the
- * start of the device descriptor, which should work okay regardless of
- * the actual bMaxPacketSize0 value. For "new scheme" initialization,
- * size will be 64 (and buf will point to a sufficiently large buffer),
- * which might not be kosher according to the USB spec but it's what
- * Windows does and what many devices expect.
- *
- * Returns: bMaxPacketSize0 or a negative error code.
- */
-static int get_bMaxPacketSize0(struct usb_device *udev,
- struct usb_device_descriptor *buf, int size, bool first_time)
-{
- int i, rc;
-
- /*
- * Retry on all errors; some devices are flakey.
- * 255 is for WUSB devices, we actually need to use
- * 512 (WUSB1.0[4.8.1]).
- */
- for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) {
- /* Start with invalid values in case the transfer fails */
- buf->bDescriptorType = buf->bMaxPacketSize0 = 0;
- rc = usb_control_msg(udev, usb_rcvaddr0pipe(),
- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- USB_DT_DEVICE << 8, 0,
- buf, size,
- initial_descriptor_timeout);
- switch (buf->bMaxPacketSize0) {
- case 8: case 16: case 32: case 64: case 9:
- if (buf->bDescriptorType == USB_DT_DEVICE) {
- rc = buf->bMaxPacketSize0;
- break;
- }
- fallthrough;
- default:
- if (rc >= 0)
- rc = -EPROTO;
- break;
- }
-
- /*
- * Some devices time out if they are powered on
- * when already connected. They need a second
- * reset, so return early. But only on the first
- * attempt, lest we get into a time-out/reset loop.
- */
- if (rc > 0 || (rc == -ETIMEDOUT && first_time &&
- udev->speed > USB_SPEED_FULL))
- break;
- }
- return rc;
-}
-
-#define GET_DESCRIPTOR_BUFSIZE 64
-
/* Reset device, (re)assign address, get device descriptor.
* Device connection must be stable, no more debouncing needed.
* Returns device in USB_STATE_ADDRESS, except on error.
@@ -4812,17 +4751,10 @@ static int get_bMaxPacketSize0(struct usb_device *udev,
* the port lock. For a newly detected device that is not accessible
* through any global pointers, it's not necessary to lock the device,
* but it is still necessary to lock the port.
- *
- * For a newly detected device, @dev_descr must be NULL. The device
- * descriptor retrieved from the device will then be stored in
- * @udev->descriptor. For an already existing device, @dev_descr
- * must be non-NULL. The device descriptor will be stored there,
- * not in @udev->descriptor, because descriptors for registered
- * devices are meant to be immutable.
*/
static int
hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
- int retry_counter, struct usb_device_descriptor *dev_descr)
+ int retry_counter)
{
struct usb_device *hdev = hub->hdev;
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
@@ -4834,13 +4766,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
int devnum = udev->devnum;
const char *driver_name;
bool do_new_scheme;
- const bool initial = !dev_descr;
- int maxp0;
- struct usb_device_descriptor *buf, *descr;
-
- buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
- if (!buf)
- return -ENOMEM;
/* root hub ports have a slightly longer reset period
* (from USB 2.0 spec, section 7.1.7.5)
@@ -4873,31 +4798,31 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
}
oldspeed = udev->speed;
- if (initial) {
- /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
- * it's fixed size except for full speed devices.
+ /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
+ * it's fixed size except for full speed devices.
+ * For Wireless USB devices, ep0 max packet is always 512 (tho
+ * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
+ */
+ switch (udev->speed) {
+ case USB_SPEED_SUPER_PLUS:
+ case USB_SPEED_SUPER:
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
+ break;
+ case USB_SPEED_HIGH: /* fixed at 64 */
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
+ break;
+ case USB_SPEED_FULL: /* 8, 16, 32, or 64 */
+ /* to determine the ep0 maxpacket size, try to read
+ * the device descriptor to get bMaxPacketSize0 and
+ * then correct our initial guess.
*/
- switch (udev->speed) {
- case USB_SPEED_SUPER_PLUS:
- case USB_SPEED_SUPER:
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
- break;
- case USB_SPEED_HIGH: /* fixed at 64 */
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
- break;
- case USB_SPEED_FULL: /* 8, 16, 32, or 64 */
- /* to determine the ep0 maxpacket size, try to read
- * the device descriptor to get bMaxPacketSize0 and
- * then correct our initial guess.
- */
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
- break;
- case USB_SPEED_LOW: /* fixed at 8 */
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
- break;
- default:
- goto fail;
- }
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
+ break;
+ case USB_SPEED_LOW: /* fixed at 8 */
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
+ break;
+ default:
+ goto fail;
}
speed = usb_speed_string(udev->speed);
@@ -4917,24 +4842,22 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
if (udev->speed < USB_SPEED_SUPER)
dev_info(&udev->dev,
"%s %s USB device number %d using %s\n",
- (initial ? "new" : "reset"), speed,
+ (udev->config) ? "reset" : "new", speed,
devnum, driver_name);
- if (initial) {
- /* Set up TT records, if needed */
- if (hdev->tt) {
- udev->tt = hdev->tt;
- udev->ttport = hdev->ttport;
- } else if (udev->speed != USB_SPEED_HIGH
- && hdev->speed == USB_SPEED_HIGH) {
- if (!hub->tt.hub) {
- dev_err(&udev->dev, "parent hub has no TT\n");
- retval = -EINVAL;
- goto fail;
- }
- udev->tt = &hub->tt;
- udev->ttport = port1;
+ /* Set up TT records, if needed */
+ if (hdev->tt) {
+ udev->tt = hdev->tt;
+ udev->ttport = hdev->ttport;
+ } else if (udev->speed != USB_SPEED_HIGH
+ && hdev->speed == USB_SPEED_HIGH) {
+ if (!hub->tt.hub) {
+ dev_err(&udev->dev, "parent hub has no TT\n");
+ retval = -EINVAL;
+ goto fail;
}
+ udev->tt = &hub->tt;
+ udev->ttport = port1;
}
/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
@@ -4958,6 +4881,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
}
if (do_new_scheme) {
+ struct usb_device_descriptor *buf;
+ int r = 0;
+
retval = hub_enable_device(udev);
if (retval < 0) {
dev_err(&udev->dev,
@@ -4966,14 +4892,52 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
goto fail;
}
- maxp0 = get_bMaxPacketSize0(udev, buf,
- GET_DESCRIPTOR_BUFSIZE, retries == 0);
- if (maxp0 > 0 && !initial &&
- maxp0 != udev->descriptor.bMaxPacketSize0) {
- dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n");
- retval = -ENODEV;
- goto fail;
+#define GET_DESCRIPTOR_BUFSIZE 64
+ buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
+ if (!buf) {
+ retval = -ENOMEM;
+ continue;
+ }
+
+ /* Retry on all errors; some devices are flakey.
+ * 255 is for WUSB devices, we actually need to use
+ * 512 (WUSB1.0[4.8.1]).
+ */
+ for (operations = 0; operations < GET_MAXPACKET0_TRIES;
+ ++operations) {
+ buf->bMaxPacketSize0 = 0;
+ r = usb_control_msg(udev, usb_rcvaddr0pipe(),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ USB_DT_DEVICE << 8, 0,
+ buf, GET_DESCRIPTOR_BUFSIZE,
+ initial_descriptor_timeout);
+ switch (buf->bMaxPacketSize0) {
+ case 8: case 16: case 32: case 64: case 255:
+ if (buf->bDescriptorType ==
+ USB_DT_DEVICE) {
+ r = 0;
+ break;
+ }
+ fallthrough;
+ default:
+ if (r == 0)
+ r = -EPROTO;
+ break;
+ }
+ /*
+ * Some devices time out if they are powered on
+ * when already connected. They need a second
+ * reset. But only on the first attempt,
+ * lest we get into a time out/reset loop
+ */
+ if (r == 0 || (r == -ETIMEDOUT &&
+ retries == 0 &&
+ udev->speed > USB_SPEED_FULL))
+ break;
}
+ udev->descriptor.bMaxPacketSize0 =
+ buf->bMaxPacketSize0;
+ kfree(buf);
retval = hub_port_reset(hub, port1, udev, delay, false);
if (retval < 0) /* error or disconnect */
@@ -4984,13 +4948,14 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
retval = -ENODEV;
goto fail;
}
- if (maxp0 < 0) {
- if (maxp0 != -ENODEV)
+ if (r) {
+ if (r != -ENODEV)
dev_err(&udev->dev, "device descriptor read/64, error %d\n",
- maxp0);
- retval = maxp0;
+ r);
+ retval = -EMSGSIZE;
continue;
}
+#undef GET_DESCRIPTOR_BUFSIZE
}
for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) {
@@ -5031,21 +4996,18 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
if (do_new_scheme)
break;
- maxp0 = get_bMaxPacketSize0(udev, buf, 8, retries == 0);
- if (maxp0 < 0) {
- retval = maxp0;
+ retval = usb_get_device_descriptor(udev, 8);
+ if (retval < 8) {
if (retval != -ENODEV)
dev_err(&udev->dev,
"device descriptor read/8, error %d\n",
retval);
+ if (retval >= 0)
+ retval = -EMSGSIZE;
} else {
u32 delay;
- if (!initial && maxp0 != udev->descriptor.bMaxPacketSize0) {
- dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n");
- retval = -ENODEV;
- goto fail;
- }
+ retval = 0;
delay = udev->parent->hub_delay;
udev->hub_delay = min_t(u32, delay,
@@ -5064,62 +5026,48 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
goto fail;
/*
- * Check the ep0 maxpacket guess and correct it if necessary.
- * maxp0 is the value stored in the device descriptor;
- * i is the value it encodes (logarithmic for SuperSpeed or greater).
+ * Some superspeed devices have finished the link training process
+ * and attached to a superspeed hub port, but the device descriptor
+ * got from those devices show they aren't superspeed devices. Warm
+ * reset the port attached by the devices can fix them.
*/
- i = maxp0;
- if (udev->speed >= USB_SPEED_SUPER) {
- if (maxp0 <= 16)
- i = 1 << maxp0;
- else
- i = 0; /* Invalid */
- }
- if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
- ; /* Initial ep0 maxpacket guess is right */
- } else if (((udev->speed == USB_SPEED_FULL ||
- udev->speed == USB_SPEED_HIGH) &&
- (i == 8 || i == 16 || i == 32 || i == 64)) ||
- (udev->speed >= USB_SPEED_SUPER && i > 0)) {
- /* Initial guess is wrong; use the descriptor's value */
+ if ((udev->speed >= USB_SPEED_SUPER) &&
+ (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
+ dev_err(&udev->dev, "got a wrong device descriptor, "
+ "warm reset device\n");
+ hub_port_reset(hub, port1, udev,
+ HUB_BH_RESET_TIME, true);
+ retval = -EINVAL;
+ goto fail;
+ }
+
+ if (udev->descriptor.bMaxPacketSize0 == 0xff ||
+ udev->speed >= USB_SPEED_SUPER)
+ i = 512;
+ else
+ i = udev->descriptor.bMaxPacketSize0;
+ if (usb_endpoint_maxp(&udev->ep0.desc) != i) {
+ if (udev->speed == USB_SPEED_LOW ||
+ !(i == 8 || i == 16 || i == 32 || i == 64)) {
+ dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
+ retval = -EMSGSIZE;
+ goto fail;
+ }
if (udev->speed == USB_SPEED_FULL)
dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
else
dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
usb_ep0_reinit(udev);
- } else {
- /* Initial guess is wrong and descriptor's value is invalid */
- dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", maxp0);
- retval = -EMSGSIZE;
- goto fail;
}
- descr = usb_get_device_descriptor(udev);
- if (IS_ERR(descr)) {
- retval = PTR_ERR(descr);
+ retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
+ if (retval < (signed)sizeof(udev->descriptor)) {
if (retval != -ENODEV)
dev_err(&udev->dev, "device descriptor read/all, error %d\n",
retval);
- goto fail;
- }
- if (initial)
- udev->descriptor = *descr;
- else
- *dev_descr = *descr;
- kfree(descr);
-
- /*
- * Some superspeed devices have finished the link training process
- * and attached to a superspeed hub port, but the device descriptor
- * got from those devices show they aren't superspeed devices. Warm
- * reset the port attached by the devices can fix them.
- */
- if ((udev->speed >= USB_SPEED_SUPER) &&
- (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
- dev_err(&udev->dev, "got a wrong device descriptor, warm reset device\n");
- hub_port_reset(hub, port1, udev, HUB_BH_RESET_TIME, true);
- retval = -EINVAL;
+ if (retval >= 0)
+ retval = -ENOMSG;
goto fail;
}
@@ -5145,7 +5093,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
hub_port_disable(hub, port1, 0);
update_devnum(udev, devnum); /* for disconnect processing */
}
- kfree(buf);
return retval;
}
@@ -5226,7 +5173,7 @@ hub_power_remaining(struct usb_hub *hub)
static int descriptors_changed(struct usb_device *udev,
- struct usb_device_descriptor *new_device_descriptor,
+ struct usb_device_descriptor *old_device_descriptor,
struct usb_host_bos *old_bos)
{
int changed = 0;
@@ -5237,8 +5184,8 @@ static int descriptors_changed(struct usb_device *udev,
int length;
char *buf;
- if (memcmp(&udev->descriptor, new_device_descriptor,
- sizeof(*new_device_descriptor)) != 0)
+ if (memcmp(&udev->descriptor, old_device_descriptor,
+ sizeof(*old_device_descriptor)) != 0)
return 1;
if ((old_bos && !udev->bos) || (!old_bos && udev->bos))
@@ -5415,7 +5362,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
}
/* reset (non-USB 3.0 devices) and get descriptor */
- status = hub_port_init(hub, udev, port1, i, NULL);
+ status = hub_port_init(hub, udev, port1, i);
if (status < 0)
goto loop;
@@ -5562,8 +5509,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
{
struct usb_port *port_dev = hub->ports[port1 - 1];
struct usb_device *udev = port_dev->child;
- struct usb_device_descriptor *descr;
+ struct usb_device_descriptor descriptor;
int status = -ENODEV;
+ int retval;
dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus,
portchange, portspeed(hub, portstatus));
@@ -5590,20 +5538,23 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
* changed device descriptors before resuscitating the
* device.
*/
- descr = usb_get_device_descriptor(udev);
- if (IS_ERR(descr)) {
+ descriptor = udev->descriptor;
+ retval = usb_get_device_descriptor(udev,
+ sizeof(udev->descriptor));
+ if (retval < 0) {
dev_dbg(&udev->dev,
- "can't read device descriptor %ld\n",
- PTR_ERR(descr));
+ "can't read device descriptor %d\n",
+ retval);
} else {
- if (descriptors_changed(udev, descr,
+ if (descriptors_changed(udev, &descriptor,
udev->bos)) {
dev_dbg(&udev->dev,
"device descriptor has changed\n");
+ /* for disconnect() calls */
+ udev->descriptor = descriptor;
} else {
status = 0; /* Nothing to do */
}
- kfree(descr);
}
#ifdef CONFIG_PM
} else if (udev->state == USB_STATE_SUSPENDED &&
@@ -6060,7 +6011,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
struct usb_device *parent_hdev = udev->parent;
struct usb_hub *parent_hub;
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
- struct usb_device_descriptor descriptor;
+ struct usb_device_descriptor descriptor = udev->descriptor;
struct usb_host_bos *bos;
int i, j, ret = 0;
int port1 = udev->portnum;
@@ -6096,7 +6047,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
/* ep0 maxpacket size may change; let the HCD know about it.
* Other endpoints will be handled by re-enumeration. */
usb_ep0_reinit(udev);
- ret = hub_port_init(parent_hub, udev, port1, i, &descriptor);
+ ret = hub_port_init(parent_hub, udev, port1, i);
if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
break;
}
@@ -6108,6 +6059,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
/* Device might have changed firmware (DFU or similar) */
if (descriptors_changed(udev, &descriptor, bos)) {
dev_info(&udev->dev, "device firmware changed\n");
+ udev->descriptor = descriptor; /* for disconnect() calls */
goto re_enumerate;
}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 077dfe48d01c1..0d2bfc909019b 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1041,35 +1041,40 @@ char *usb_cache_string(struct usb_device *udev, int index)
EXPORT_SYMBOL_GPL(usb_cache_string);
/*
- * usb_get_device_descriptor - read the device descriptor
- * @udev: the device whose device descriptor should be read
+ * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
+ * @dev: the device whose device descriptor is being updated
+ * @size: how much of the descriptor to read
*
* Context: task context, might sleep.
*
+ * Updates the copy of the device descriptor stored in the device structure,
+ * which dedicates space for this purpose.
+ *
* Not exported, only for use by the core. If drivers really want to read
* the device descriptor directly, they can call usb_get_descriptor() with
* type = USB_DT_DEVICE and index = 0.
*
- * Returns: a pointer to a dynamically allocated usb_device_descriptor
- * structure (which the caller must deallocate), or an ERR_PTR value.
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Return: The number of bytes received on success, or else the status code
+ * returned by the underlying usb_control_msg() call.
*/
-struct usb_device_descriptor *usb_get_device_descriptor(struct usb_device *udev)
+int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
{
struct usb_device_descriptor *desc;
int ret;
+ if (size > sizeof(*desc))
+ return -EINVAL;
desc = kmalloc(sizeof(*desc), GFP_NOIO);
if (!desc)
- return ERR_PTR(-ENOMEM);
-
- ret = usb_get_descriptor(udev, USB_DT_DEVICE, 0, desc, sizeof(*desc));
- if (ret == sizeof(*desc))
- return desc;
+ return -ENOMEM;
+ ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
if (ret >= 0)
- ret = -EMSGSIZE;
+ memcpy(&dev->descriptor, desc, size);
kfree(desc);
- return ERR_PTR(ret);
+ return ret;
}
/*
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 60363153fc3f3..69ca59841083b 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -43,8 +43,8 @@ extern bool usb_endpoint_is_ignored(struct usb_device *udev,
struct usb_endpoint_descriptor *epd);
extern int usb_remove_device(struct usb_device *udev);
-extern struct usb_device_descriptor *usb_get_device_descriptor(
- struct usb_device *udev);
+extern int usb_get_device_descriptor(struct usb_device *dev,
+ unsigned int size);
extern int usb_set_isoch_delay(struct usb_device *dev);
extern int usb_get_bos_descriptor(struct usb_device *dev);
extern void usb_release_bos_descriptor(struct usb_device *dev);

View File

@ -0,0 +1,52 @@
From 76591e4075194cf717dc085b8285912f706bcd46 Mon Sep 17 00:00:00 2001
From: Stefan Agner <stefan@agner.ch>
Date: Tue, 28 Mar 2023 12:02:10 +0200
Subject: [PATCH] ipv6: add option to explicitly enable reachability test
Systems which act as host as well as router might prefer the host
behavior. Currently the kernel does not allow to use IPv6 forwarding
globally and at the same time use route reachability probing.
Add a compile time flag to enable route reachability probe in any
case.
Signed-off-by: Stefan Agner <stefan@agner.ch>
---
net/ipv6/Kconfig | 9 +++++++++
net/ipv6/route.c | 3 ++-
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig
index 08d4b7132d4c..242bf2eeb7ae 100644
--- a/net/ipv6/Kconfig
+++ b/net/ipv6/Kconfig
@@ -48,6 +48,15 @@ config IPV6_OPTIMISTIC_DAD
If unsure, say N.
+config IPV6_REACHABILITY_PROBE
+ bool "IPv6: Always use reachability probing (RFC 4191)"
+ help
+ By default reachability probing is disabled on router devices (when
+ IPv6 forwarding is enabled). This option explicitly enables
+ reachability probing always.
+
+ If unsure, say N.
+
config INET6_AH
tristate "IPv6: AH transformation"
select XFRM_AH
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 56525b5b95a2..916769b9a772 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2211,7 +2211,8 @@ struct rt6_info *ip6_pol_route(struct net *net, struct fib6_table *table,
strict |= flags & RT6_LOOKUP_F_IFACE;
strict |= flags & RT6_LOOKUP_F_IGNORE_LINKSTATE;
- if (net->ipv6.devconf_all->forwarding == 0)
+ if (net->ipv6.devconf_all->forwarding == 0 ||
+ IS_ENABLED(CONFIG_IPV6_REACHABILITY_PROBE))
strict |= RT6_LOOKUP_F_REACHABLE;
rcu_read_lock();

View File

@ -0,0 +1,650 @@
From f9037c133775498d0ff2f035a957ce4f294e4e81 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20=C4=8Cerm=C3=A1k?= <sairon@sairon.cz>
Date: Wed, 6 Mar 2024 13:25:41 +0100
Subject: [PATCH] Revert USB core changes causing issues with Z-Wave.me UZB
stick
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Workaround for issues described on GH [1] and reported in [2].
* Revert "USB: core: Fix oversight in SuperSpeed initialization"
This reverts commit 59cf445754566984fd55af19ba7146c76e6627bc.
* Revert "USB: core: Fix race by not overwriting udev->descriptor in hub_port_init()"
This reverts commit ff33299ec8bb80cdcc073ad9c506bd79bb2ed20b.
* Revert "USB: core: Change usb_get_device_descriptor() API"
This reverts commit de28e469da75359a2bb8cd8778b78aa64b1be1f4.
* Revert "USB: core: Unite old scheme and new scheme descriptor reads"
This reverts commit 85d07c55621676d47d873d2749b88f783cd4d5a1.
[1] https://github.com/home-assistant/operating-system/issues/2995
[2] https://lore.kernel.org/linux-usb/1e954652-dfb3-4248-beea-b8a449128ff0@sairon.cz/
Signed-off-by: Jan Čermák <sairon@sairon.cz>
---
drivers/usb/core/hcd.c | 10 +-
drivers/usb/core/hub.c | 336 ++++++++++++++++---------------------
drivers/usb/core/message.c | 29 ++--
drivers/usb/core/usb.h | 4 +-
4 files changed, 166 insertions(+), 213 deletions(-)
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 12b6dfeaf658c..d895f6ebbc400 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -958,7 +958,6 @@ static int register_root_hub(struct usb_hcd *hcd)
{
struct device *parent_dev = hcd->self.controller;
struct usb_device *usb_dev = hcd->self.root_hub;
- struct usb_device_descriptor *descr;
const int devnum = 1;
int retval;
@@ -970,16 +969,13 @@ static int register_root_hub(struct usb_hcd *hcd)
mutex_lock(&usb_bus_idr_lock);
usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
- descr = usb_get_device_descriptor(usb_dev);
- if (IS_ERR(descr)) {
- retval = PTR_ERR(descr);
+ retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE);
+ if (retval != sizeof usb_dev->descriptor) {
mutex_unlock(&usb_bus_idr_lock);
dev_dbg (parent_dev, "can't read %s device descriptor %d\n",
dev_name(&usb_dev->dev), retval);
- return retval;
+ return (retval < 0) ? retval : -EMSGSIZE;
}
- usb_dev->descriptor = *descr;
- kfree(descr);
if (le16_to_cpu(usb_dev->descriptor.bcdUSB) >= 0x0201) {
retval = usb_get_bos_descriptor(usb_dev);
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 1ba3feb5e1900..ef1d63537a9b7 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -4742,67 +4742,6 @@ static int hub_enable_device(struct usb_device *udev)
return hcd->driver->enable_device(hcd, udev);
}
-/*
- * Get the bMaxPacketSize0 value during initialization by reading the
- * device's device descriptor. Since we don't already know this value,
- * the transfer is unsafe and it ignores I/O errors, only testing for
- * reasonable received values.
- *
- * For "old scheme" initialization, size will be 8 so we read just the
- * start of the device descriptor, which should work okay regardless of
- * the actual bMaxPacketSize0 value. For "new scheme" initialization,
- * size will be 64 (and buf will point to a sufficiently large buffer),
- * which might not be kosher according to the USB spec but it's what
- * Windows does and what many devices expect.
- *
- * Returns: bMaxPacketSize0 or a negative error code.
- */
-static int get_bMaxPacketSize0(struct usb_device *udev,
- struct usb_device_descriptor *buf, int size, bool first_time)
-{
- int i, rc;
-
- /*
- * Retry on all errors; some devices are flakey.
- * 255 is for WUSB devices, we actually need to use
- * 512 (WUSB1.0[4.8.1]).
- */
- for (i = 0; i < GET_MAXPACKET0_TRIES; ++i) {
- /* Start with invalid values in case the transfer fails */
- buf->bDescriptorType = buf->bMaxPacketSize0 = 0;
- rc = usb_control_msg(udev, usb_rcvaddr0pipe(),
- USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
- USB_DT_DEVICE << 8, 0,
- buf, size,
- initial_descriptor_timeout);
- switch (buf->bMaxPacketSize0) {
- case 8: case 16: case 32: case 64: case 9:
- if (buf->bDescriptorType == USB_DT_DEVICE) {
- rc = buf->bMaxPacketSize0;
- break;
- }
- fallthrough;
- default:
- if (rc >= 0)
- rc = -EPROTO;
- break;
- }
-
- /*
- * Some devices time out if they are powered on
- * when already connected. They need a second
- * reset, so return early. But only on the first
- * attempt, lest we get into a time-out/reset loop.
- */
- if (rc > 0 || (rc == -ETIMEDOUT && first_time &&
- udev->speed > USB_SPEED_FULL))
- break;
- }
- return rc;
-}
-
-#define GET_DESCRIPTOR_BUFSIZE 64
-
/* Reset device, (re)assign address, get device descriptor.
* Device connection must be stable, no more debouncing needed.
* Returns device in USB_STATE_ADDRESS, except on error.
@@ -4812,17 +4751,10 @@ static int get_bMaxPacketSize0(struct usb_device *udev,
* the port lock. For a newly detected device that is not accessible
* through any global pointers, it's not necessary to lock the device,
* but it is still necessary to lock the port.
- *
- * For a newly detected device, @dev_descr must be NULL. The device
- * descriptor retrieved from the device will then be stored in
- * @udev->descriptor. For an already existing device, @dev_descr
- * must be non-NULL. The device descriptor will be stored there,
- * not in @udev->descriptor, because descriptors for registered
- * devices are meant to be immutable.
*/
static int
hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
- int retry_counter, struct usb_device_descriptor *dev_descr)
+ int retry_counter)
{
struct usb_device *hdev = hub->hdev;
struct usb_hcd *hcd = bus_to_hcd(hdev->bus);
@@ -4834,13 +4766,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
int devnum = udev->devnum;
const char *driver_name;
bool do_new_scheme;
- const bool initial = !dev_descr;
- int maxp0;
- struct usb_device_descriptor *buf, *descr;
-
- buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
- if (!buf)
- return -ENOMEM;
/* root hub ports have a slightly longer reset period
* (from USB 2.0 spec, section 7.1.7.5)
@@ -4873,31 +4798,31 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
}
oldspeed = udev->speed;
- if (initial) {
- /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
- * it's fixed size except for full speed devices.
+ /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
+ * it's fixed size except for full speed devices.
+ * For Wireless USB devices, ep0 max packet is always 512 (tho
+ * reported as 0xff in the device descriptor). WUSB1.0[4.8.1].
+ */
+ switch (udev->speed) {
+ case USB_SPEED_SUPER_PLUS:
+ case USB_SPEED_SUPER:
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
+ break;
+ case USB_SPEED_HIGH: /* fixed at 64 */
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
+ break;
+ case USB_SPEED_FULL: /* 8, 16, 32, or 64 */
+ /* to determine the ep0 maxpacket size, try to read
+ * the device descriptor to get bMaxPacketSize0 and
+ * then correct our initial guess.
*/
- switch (udev->speed) {
- case USB_SPEED_SUPER_PLUS:
- case USB_SPEED_SUPER:
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512);
- break;
- case USB_SPEED_HIGH: /* fixed at 64 */
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
- break;
- case USB_SPEED_FULL: /* 8, 16, 32, or 64 */
- /* to determine the ep0 maxpacket size, try to read
- * the device descriptor to get bMaxPacketSize0 and
- * then correct our initial guess.
- */
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
- break;
- case USB_SPEED_LOW: /* fixed at 8 */
- udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
- break;
- default:
- goto fail;
- }
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64);
+ break;
+ case USB_SPEED_LOW: /* fixed at 8 */
+ udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8);
+ break;
+ default:
+ goto fail;
}
speed = usb_speed_string(udev->speed);
@@ -4917,24 +4842,22 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
if (udev->speed < USB_SPEED_SUPER)
dev_info(&udev->dev,
"%s %s USB device number %d using %s\n",
- (initial ? "new" : "reset"), speed,
+ (udev->config) ? "reset" : "new", speed,
devnum, driver_name);
- if (initial) {
- /* Set up TT records, if needed */
- if (hdev->tt) {
- udev->tt = hdev->tt;
- udev->ttport = hdev->ttport;
- } else if (udev->speed != USB_SPEED_HIGH
- && hdev->speed == USB_SPEED_HIGH) {
- if (!hub->tt.hub) {
- dev_err(&udev->dev, "parent hub has no TT\n");
- retval = -EINVAL;
- goto fail;
- }
- udev->tt = &hub->tt;
- udev->ttport = port1;
+ /* Set up TT records, if needed */
+ if (hdev->tt) {
+ udev->tt = hdev->tt;
+ udev->ttport = hdev->ttport;
+ } else if (udev->speed != USB_SPEED_HIGH
+ && hdev->speed == USB_SPEED_HIGH) {
+ if (!hub->tt.hub) {
+ dev_err(&udev->dev, "parent hub has no TT\n");
+ retval = -EINVAL;
+ goto fail;
}
+ udev->tt = &hub->tt;
+ udev->ttport = port1;
}
/* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way?
@@ -4958,6 +4881,9 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
}
if (do_new_scheme) {
+ struct usb_device_descriptor *buf;
+ int r = 0;
+
retval = hub_enable_device(udev);
if (retval < 0) {
dev_err(&udev->dev,
@@ -4966,14 +4892,52 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
goto fail;
}
- maxp0 = get_bMaxPacketSize0(udev, buf,
- GET_DESCRIPTOR_BUFSIZE, retries == 0);
- if (maxp0 > 0 && !initial &&
- maxp0 != udev->descriptor.bMaxPacketSize0) {
- dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n");
- retval = -ENODEV;
- goto fail;
+#define GET_DESCRIPTOR_BUFSIZE 64
+ buf = kmalloc(GET_DESCRIPTOR_BUFSIZE, GFP_NOIO);
+ if (!buf) {
+ retval = -ENOMEM;
+ continue;
+ }
+
+ /* Retry on all errors; some devices are flakey.
+ * 255 is for WUSB devices, we actually need to use
+ * 512 (WUSB1.0[4.8.1]).
+ */
+ for (operations = 0; operations < GET_MAXPACKET0_TRIES;
+ ++operations) {
+ buf->bMaxPacketSize0 = 0;
+ r = usb_control_msg(udev, usb_rcvaddr0pipe(),
+ USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
+ USB_DT_DEVICE << 8, 0,
+ buf, GET_DESCRIPTOR_BUFSIZE,
+ initial_descriptor_timeout);
+ switch (buf->bMaxPacketSize0) {
+ case 8: case 16: case 32: case 64: case 255:
+ if (buf->bDescriptorType ==
+ USB_DT_DEVICE) {
+ r = 0;
+ break;
+ }
+ fallthrough;
+ default:
+ if (r == 0)
+ r = -EPROTO;
+ break;
+ }
+ /*
+ * Some devices time out if they are powered on
+ * when already connected. They need a second
+ * reset. But only on the first attempt,
+ * lest we get into a time out/reset loop
+ */
+ if (r == 0 || (r == -ETIMEDOUT &&
+ retries == 0 &&
+ udev->speed > USB_SPEED_FULL))
+ break;
}
+ udev->descriptor.bMaxPacketSize0 =
+ buf->bMaxPacketSize0;
+ kfree(buf);
retval = hub_port_reset(hub, port1, udev, delay, false);
if (retval < 0) /* error or disconnect */
@@ -4984,13 +4948,14 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
retval = -ENODEV;
goto fail;
}
- if (maxp0 < 0) {
- if (maxp0 != -ENODEV)
+ if (r) {
+ if (r != -ENODEV)
dev_err(&udev->dev, "device descriptor read/64, error %d\n",
- maxp0);
- retval = maxp0;
+ r);
+ retval = -EMSGSIZE;
continue;
}
+#undef GET_DESCRIPTOR_BUFSIZE
}
for (operations = 0; operations < SET_ADDRESS_TRIES; ++operations) {
@@ -5031,21 +4996,18 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
if (do_new_scheme)
break;
- maxp0 = get_bMaxPacketSize0(udev, buf, 8, retries == 0);
- if (maxp0 < 0) {
- retval = maxp0;
+ retval = usb_get_device_descriptor(udev, 8);
+ if (retval < 8) {
if (retval != -ENODEV)
dev_err(&udev->dev,
"device descriptor read/8, error %d\n",
retval);
+ if (retval >= 0)
+ retval = -EMSGSIZE;
} else {
u32 delay;
- if (!initial && maxp0 != udev->descriptor.bMaxPacketSize0) {
- dev_err(&udev->dev, "device reset changed ep0 maxpacket size!\n");
- retval = -ENODEV;
- goto fail;
- }
+ retval = 0;
delay = udev->parent->hub_delay;
udev->hub_delay = min_t(u32, delay,
@@ -5064,62 +5026,48 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
goto fail;
/*
- * Check the ep0 maxpacket guess and correct it if necessary.
- * maxp0 is the value stored in the device descriptor;
- * i is the value it encodes (logarithmic for SuperSpeed or greater).
+ * Some superspeed devices have finished the link training process
+ * and attached to a superspeed hub port, but the device descriptor
+ * got from those devices show they aren't superspeed devices. Warm
+ * reset the port attached by the devices can fix them.
*/
- i = maxp0;
- if (udev->speed >= USB_SPEED_SUPER) {
- if (maxp0 <= 16)
- i = 1 << maxp0;
- else
- i = 0; /* Invalid */
- }
- if (usb_endpoint_maxp(&udev->ep0.desc) == i) {
- ; /* Initial ep0 maxpacket guess is right */
- } else if (((udev->speed == USB_SPEED_FULL ||
- udev->speed == USB_SPEED_HIGH) &&
- (i == 8 || i == 16 || i == 32 || i == 64)) ||
- (udev->speed >= USB_SPEED_SUPER && i > 0)) {
- /* Initial guess is wrong; use the descriptor's value */
+ if ((udev->speed >= USB_SPEED_SUPER) &&
+ (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
+ dev_err(&udev->dev, "got a wrong device descriptor, "
+ "warm reset device\n");
+ hub_port_reset(hub, port1, udev,
+ HUB_BH_RESET_TIME, true);
+ retval = -EINVAL;
+ goto fail;
+ }
+
+ if (udev->descriptor.bMaxPacketSize0 == 0xff ||
+ udev->speed >= USB_SPEED_SUPER)
+ i = 512;
+ else
+ i = udev->descriptor.bMaxPacketSize0;
+ if (usb_endpoint_maxp(&udev->ep0.desc) != i) {
+ if (udev->speed == USB_SPEED_LOW ||
+ !(i == 8 || i == 16 || i == 32 || i == 64)) {
+ dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", i);
+ retval = -EMSGSIZE;
+ goto fail;
+ }
if (udev->speed == USB_SPEED_FULL)
dev_dbg(&udev->dev, "ep0 maxpacket = %d\n", i);
else
dev_warn(&udev->dev, "Using ep0 maxpacket: %d\n", i);
udev->ep0.desc.wMaxPacketSize = cpu_to_le16(i);
usb_ep0_reinit(udev);
- } else {
- /* Initial guess is wrong and descriptor's value is invalid */
- dev_err(&udev->dev, "Invalid ep0 maxpacket: %d\n", maxp0);
- retval = -EMSGSIZE;
- goto fail;
}
- descr = usb_get_device_descriptor(udev);
- if (IS_ERR(descr)) {
- retval = PTR_ERR(descr);
+ retval = usb_get_device_descriptor(udev, USB_DT_DEVICE_SIZE);
+ if (retval < (signed)sizeof(udev->descriptor)) {
if (retval != -ENODEV)
dev_err(&udev->dev, "device descriptor read/all, error %d\n",
retval);
- goto fail;
- }
- if (initial)
- udev->descriptor = *descr;
- else
- *dev_descr = *descr;
- kfree(descr);
-
- /*
- * Some superspeed devices have finished the link training process
- * and attached to a superspeed hub port, but the device descriptor
- * got from those devices show they aren't superspeed devices. Warm
- * reset the port attached by the devices can fix them.
- */
- if ((udev->speed >= USB_SPEED_SUPER) &&
- (le16_to_cpu(udev->descriptor.bcdUSB) < 0x0300)) {
- dev_err(&udev->dev, "got a wrong device descriptor, warm reset device\n");
- hub_port_reset(hub, port1, udev, HUB_BH_RESET_TIME, true);
- retval = -EINVAL;
+ if (retval >= 0)
+ retval = -ENOMSG;
goto fail;
}
@@ -5145,7 +5093,6 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1,
hub_port_disable(hub, port1, 0);
update_devnum(udev, devnum); /* for disconnect processing */
}
- kfree(buf);
return retval;
}
@@ -5226,7 +5173,7 @@ hub_power_remaining(struct usb_hub *hub)
static int descriptors_changed(struct usb_device *udev,
- struct usb_device_descriptor *new_device_descriptor,
+ struct usb_device_descriptor *old_device_descriptor,
struct usb_host_bos *old_bos)
{
int changed = 0;
@@ -5237,8 +5184,8 @@ static int descriptors_changed(struct usb_device *udev,
int length;
char *buf;
- if (memcmp(&udev->descriptor, new_device_descriptor,
- sizeof(*new_device_descriptor)) != 0)
+ if (memcmp(&udev->descriptor, old_device_descriptor,
+ sizeof(*old_device_descriptor)) != 0)
return 1;
if ((old_bos && !udev->bos) || (!old_bos && udev->bos))
@@ -5415,7 +5362,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus,
}
/* reset (non-USB 3.0 devices) and get descriptor */
- status = hub_port_init(hub, udev, port1, i, NULL);
+ status = hub_port_init(hub, udev, port1, i);
if (status < 0)
goto loop;
@@ -5562,8 +5509,9 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
{
struct usb_port *port_dev = hub->ports[port1 - 1];
struct usb_device *udev = port_dev->child;
- struct usb_device_descriptor *descr;
+ struct usb_device_descriptor descriptor;
int status = -ENODEV;
+ int retval;
dev_dbg(&port_dev->dev, "status %04x, change %04x, %s\n", portstatus,
portchange, portspeed(hub, portstatus));
@@ -5590,20 +5538,23 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
* changed device descriptors before resuscitating the
* device.
*/
- descr = usb_get_device_descriptor(udev);
- if (IS_ERR(descr)) {
+ descriptor = udev->descriptor;
+ retval = usb_get_device_descriptor(udev,
+ sizeof(udev->descriptor));
+ if (retval < 0) {
dev_dbg(&udev->dev,
- "can't read device descriptor %ld\n",
- PTR_ERR(descr));
+ "can't read device descriptor %d\n",
+ retval);
} else {
- if (descriptors_changed(udev, descr,
+ if (descriptors_changed(udev, &descriptor,
udev->bos)) {
dev_dbg(&udev->dev,
"device descriptor has changed\n");
+ /* for disconnect() calls */
+ udev->descriptor = descriptor;
} else {
status = 0; /* Nothing to do */
}
- kfree(descr);
}
#ifdef CONFIG_PM
} else if (udev->state == USB_STATE_SUSPENDED &&
@@ -6060,7 +6011,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
struct usb_device *parent_hdev = udev->parent;
struct usb_hub *parent_hub;
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
- struct usb_device_descriptor descriptor;
+ struct usb_device_descriptor descriptor = udev->descriptor;
struct usb_host_bos *bos;
int i, j, ret = 0;
int port1 = udev->portnum;
@@ -6096,7 +6047,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
/* ep0 maxpacket size may change; let the HCD know about it.
* Other endpoints will be handled by re-enumeration. */
usb_ep0_reinit(udev);
- ret = hub_port_init(parent_hub, udev, port1, i, &descriptor);
+ ret = hub_port_init(parent_hub, udev, port1, i);
if (ret >= 0 || ret == -ENOTCONN || ret == -ENODEV)
break;
}
@@ -6108,6 +6059,7 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
/* Device might have changed firmware (DFU or similar) */
if (descriptors_changed(udev, &descriptor, bos)) {
dev_info(&udev->dev, "device firmware changed\n");
+ udev->descriptor = descriptor; /* for disconnect() calls */
goto re_enumerate;
}
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 077dfe48d01c1..0d2bfc909019b 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1041,35 +1041,40 @@ char *usb_cache_string(struct usb_device *udev, int index)
EXPORT_SYMBOL_GPL(usb_cache_string);
/*
- * usb_get_device_descriptor - read the device descriptor
- * @udev: the device whose device descriptor should be read
+ * usb_get_device_descriptor - (re)reads the device descriptor (usbcore)
+ * @dev: the device whose device descriptor is being updated
+ * @size: how much of the descriptor to read
*
* Context: task context, might sleep.
*
+ * Updates the copy of the device descriptor stored in the device structure,
+ * which dedicates space for this purpose.
+ *
* Not exported, only for use by the core. If drivers really want to read
* the device descriptor directly, they can call usb_get_descriptor() with
* type = USB_DT_DEVICE and index = 0.
*
- * Returns: a pointer to a dynamically allocated usb_device_descriptor
- * structure (which the caller must deallocate), or an ERR_PTR value.
+ * This call is synchronous, and may not be used in an interrupt context.
+ *
+ * Return: The number of bytes received on success, or else the status code
+ * returned by the underlying usb_control_msg() call.
*/
-struct usb_device_descriptor *usb_get_device_descriptor(struct usb_device *udev)
+int usb_get_device_descriptor(struct usb_device *dev, unsigned int size)
{
struct usb_device_descriptor *desc;
int ret;
+ if (size > sizeof(*desc))
+ return -EINVAL;
desc = kmalloc(sizeof(*desc), GFP_NOIO);
if (!desc)
- return ERR_PTR(-ENOMEM);
-
- ret = usb_get_descriptor(udev, USB_DT_DEVICE, 0, desc, sizeof(*desc));
- if (ret == sizeof(*desc))
- return desc;
+ return -ENOMEM;
+ ret = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, size);
if (ret >= 0)
- ret = -EMSGSIZE;
+ memcpy(&dev->descriptor, desc, size);
kfree(desc);
- return ERR_PTR(ret);
+ return ret;
}
/*
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index 60363153fc3f3..69ca59841083b 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -43,8 +43,8 @@ extern bool usb_endpoint_is_ignored(struct usb_device *udev,
struct usb_endpoint_descriptor *epd);
extern int usb_remove_device(struct usb_device *udev);
-extern struct usb_device_descriptor *usb_get_device_descriptor(
- struct usb_device *udev);
+extern int usb_get_device_descriptor(struct usb_device *dev,
+ unsigned int size);
extern int usb_set_isoch_delay(struct usb_device *dev);
extern int usb_get_bos_descriptor(struct usb_device *dev);
extern void usb_release_bos_descriptor(struct usb_device *dev);