diff --git a/android/GKI_VERSION b/android/GKI_VERSION index be7361f1f5ad..1d390b687298 100644 --- a/android/GKI_VERSION +++ b/android/GKI_VERSION @@ -1 +1 @@ -LTS_5.4.197_26eb689452c8 +LTS_5.4.210_7e6cbbe7e59a diff --git a/android/abi_gki_aarch64_3970bc62738d.xml b/android/abi_gki_aarch64_7e6cbbe7e59a.xml similarity index 99% rename from android/abi_gki_aarch64_3970bc62738d.xml rename to android/abi_gki_aarch64_7e6cbbe7e59a.xml index 89eaf389b101..4da433b94b90 100644 --- a/android/abi_gki_aarch64_3970bc62738d.xml +++ b/android/abi_gki_aarch64_7e6cbbe7e59a.xml @@ -1931,6 +1931,7 @@ + @@ -3337,7 +3338,7 @@ - + @@ -3542,9 +3543,9 @@ - + - + @@ -15372,57 +15373,57 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -17776,7 +17777,7 @@ - + @@ -18857,7 +18858,7 @@ - + @@ -20139,14 +20140,9 @@ - - - - - + - @@ -20267,7 +20263,7 @@ - + @@ -20296,7 +20292,7 @@ - + @@ -20929,7 +20925,7 @@ - + @@ -23579,7 +23575,7 @@ - + @@ -26299,25 +26295,25 @@ - - - - - - - - + + + + + + + + - - - - + + + + - - - + + + @@ -27893,12 +27889,12 @@ - - + + - - + + @@ -31102,12 +31098,12 @@ - - + + - - + + @@ -43054,6 +43050,11 @@ + + + + + @@ -43064,11 +43065,6 @@ - - - - - @@ -47476,21 +47472,21 @@ - + - + - + - + - + - + @@ -49167,7 +49163,7 @@ - + @@ -55433,7 +55429,7 @@ - + @@ -59361,18 +59357,18 @@ - + - + - + - + - + @@ -60824,45 +60820,45 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -61063,69 +61059,69 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -62868,42 +62864,42 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -63676,80 +63672,80 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -63945,48 +63941,48 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -64443,60 +64439,60 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -64980,12 +64976,12 @@ - + - + - + @@ -66598,105 +66594,105 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -66720,18 +66716,18 @@ - + - + - + - + - + @@ -66801,80 +66797,80 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -66894,24 +66890,24 @@ - + - + - + - + - + - + - + @@ -70384,39 +70380,39 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -71089,39 +71085,39 @@ - + - + - + - + - + - + - + - + - + - + - + - + @@ -73173,8 +73169,8 @@ - - + + @@ -73222,8 +73218,8 @@ - - + + @@ -73231,21 +73227,21 @@ - - - + + + - - + + - - + + - - + + @@ -76427,9 +76423,9 @@ - - - + + + @@ -76440,83 +76436,83 @@ - - - + + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - + + - - - - + + + + - - - - + + + + - - + + - - - + + + - - + + - - - + + + - - - + + + - - - + + + - - - - + + + + @@ -76524,16 +76520,16 @@ - - + + - - + + - - + + @@ -79310,12 +79306,12 @@ - - + + - - + + @@ -80927,28 +80923,28 @@ - - + + - - + + - - + + - - + + - - + + - - + + @@ -81034,52 +81030,52 @@ - - + + - - - + + + - - + + - - - - - - + + + + + + - - - - - - - + + + + + + + - - - - - - - - + + + + + + + + - - + + - - + + @@ -82045,11 +82041,11 @@ - - - - - + + + + + @@ -82057,16 +82053,16 @@ - - - + + + - - - - - + + + + + @@ -85315,21 +85311,21 @@ - - - - - + + + + + - - - - + + + + - - + + @@ -85697,12 +85693,12 @@ - - + + - - + + @@ -85749,100 +85745,100 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -85872,156 +85868,156 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -86481,252 +86477,252 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -87029,7 +87025,7 @@ - + @@ -89556,73 +89552,73 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -89821,48 +89817,48 @@ - - - - - + + + + + - + - + - + - + - + - + - - + + - + - + - + - + - + - + @@ -90109,24 +90105,24 @@ - + - + - + - + - + - + - + @@ -90251,7 +90247,7 @@ - + @@ -90666,72 +90662,72 @@ - - + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - - + + + + - - - + + + - - + + - - - - + + + + - - + + - - + + - - + + @@ -91391,9 +91387,9 @@ - - - + + + @@ -91439,27 +91435,27 @@ - - - + + + - - - + + + - - + + - - - + + + - - + + @@ -93940,10 +93936,6 @@ - - - - @@ -93979,10 +93971,10 @@ - - - - + + + + @@ -94281,13 +94273,30 @@ - + + + + + + + + + + + + + + + + + + @@ -94438,17 +94447,17 @@ - - - - - + + + + + - - - - + + + + @@ -97183,14 +97192,6 @@ - - - - - - - - @@ -97307,6 +97308,14 @@ + + + + + + + + @@ -99340,10 +99349,10 @@ - - + + - + @@ -101234,57 +101243,57 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -105239,60 +105248,60 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -107689,7 +107698,7 @@ - + @@ -110304,6 +110313,14 @@ + + + + + + + + @@ -111208,12 +111225,7 @@ - - - - - - + @@ -111296,8 +111308,9 @@ - + + @@ -113262,22 +113275,6 @@ - - - - - - - - - - - - - - - - @@ -113313,7 +113310,7 @@ - + @@ -113503,7 +113500,7 @@ - + @@ -118477,91 +118474,91 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -118581,164 +118578,164 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -118824,113 +118821,113 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -119183,12 +119180,12 @@ - + - + - + @@ -120712,7 +120709,7 @@ - + @@ -122243,11 +122240,11 @@ - - - - - + + + + + @@ -122268,10 +122265,10 @@ - + - + @@ -122285,12 +122282,12 @@ - - + + - - + + @@ -122312,30 +122309,30 @@ - - - - + + + + - - - - - - - + + + + + + + - - - - + + + + - - - + + + @@ -122544,7 +122541,7 @@ - + @@ -122741,7 +122738,7 @@ - + @@ -122780,6 +122777,11 @@ + + + + + @@ -123294,15 +123296,15 @@ - + - + - + - + @@ -125867,10 +125869,6 @@ - - - - @@ -126226,7 +126224,7 @@ - + @@ -130191,7 +130189,7 @@ - + @@ -130972,15 +130970,15 @@ - - + + - + - - + + @@ -131028,7 +131026,7 @@ - + @@ -131265,12 +131263,12 @@ - - + + - - + + @@ -132376,6 +132374,25 @@ + + + + + + + + + + + + + + + + + + + @@ -132631,7 +132648,7 @@ - + @@ -132648,21 +132665,21 @@ - + - + - + - + - + - + @@ -132887,7 +132904,7 @@ - + @@ -133127,7 +133144,7 @@ - + @@ -133902,7 +133919,7 @@ - + @@ -140861,120 +140878,120 @@ - - - - - - - - - + + + + + + + + + - - - + + + - - - - - + + + + + - - + + - - - - + + + + - - - - - - + + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - + + + + + - - - - - - - + + + + + + + - - - - - + + + + + - - - - - - + + + + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - - + + + + - - - - + + + + @@ -141759,201 +141776,201 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -141964,18 +141981,18 @@ - + - + - + - + - + @@ -142276,195 +142293,195 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -142813,7 +142830,7 @@ - + @@ -147632,29 +147649,29 @@ - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + diff --git a/arch/arm64/configs/vendor/lahaina_QGKI.config b/arch/arm64/configs/vendor/lahaina_QGKI.config index 2eb59768edd1..5358cae0d6d2 100755 --- a/arch/arm64/configs/vendor/lahaina_QGKI.config +++ b/arch/arm64/configs/vendor/lahaina_QGKI.config @@ -271,3 +271,4 @@ CONFIG_PCIEASPM_POWER_SUPERSAVE=y CONFIG_TLB_CONF_HANDLER=y CONFIG_PRINTK_CALLER=y CONFIG_QCOM_SUBSYSTEM_SLEEP_STATS=y +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y diff --git a/drivers/crypto/msm/qcedev.c b/drivers/crypto/msm/qcedev.c index 6221510f7997..d81ce43e3fd6 100644 --- a/drivers/crypto/msm/qcedev.c +++ b/drivers/crypto/msm/qcedev.c @@ -1916,7 +1916,9 @@ long qcedev_ioctl(struct file *file, goto exit_free_qcedev_areq; } - if (map_buf.num_fds > QCEDEV_MAX_BUFFERS) { + if (map_buf.num_fds > ARRAY_SIZE(map_buf.fd)) { + pr_err("%s: err: num_fds = %d exceeds max value\n", + __func__, map_buf.num_fds); err = -EINVAL; goto exit_free_qcedev_areq; } @@ -1956,6 +1958,12 @@ long qcedev_ioctl(struct file *file, err = -EFAULT; goto exit_free_qcedev_areq; } + if (unmap_buf.num_fds > ARRAY_SIZE(unmap_buf.fd)) { + pr_err("%s: err: num_fds = %d exceeds max value\n", + __func__, unmap_buf.num_fds); + err = -EINVAL; + goto exit_free_qcedev_areq; + } for (i = 0; i < unmap_buf.num_fds; i++) { err = qcedev_check_and_unmap_buffer(handle, diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 8ab1514ebe6a..3a898033c178 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -1585,6 +1585,7 @@ err: if (of_find_matching_node(dev->of_node, adreno_gmu_match)) component_unbind_all(dev, NULL); + idr_destroy(&device->context_idr); kgsl_bus_close(device); return status; diff --git a/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c b/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c index cc7ad875a598..5b19a616ee3e 100644 --- a/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c +++ b/drivers/gpu/msm/adreno_a6xx_gmu_snapshot.c @@ -43,7 +43,7 @@ static const unsigned int a6xx_gmu_registers[] = { 0x24000, 0x24012, 0x24040, 0x24052, 0x24400, 0x24404, 0x24407, 0x2440B, 0x24415, 0x2441C, 0x2441E, 0x2442D, 0x2443C, 0x2443D, 0x2443F, 0x24440, 0x24442, 0x24449, 0x24458, 0x2445A, 0x24540, 0x2455E, 0x24800, 0x24802, - 0x24C00, 0x24C02, 0x25400, 0x25402, 0x25800, 0x25802, 0x25C00, 0x25C02, + 0x24C00, 0x24C02, 0x25400, 0x25402, 0x25800, 0x25802, 0x26000, 0x26002, /* GPU CC ACD */ 0x26400, 0x26416, 0x26420, 0x26427, diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 196b6ed7fd92..de5c52d3a54b 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -4293,6 +4293,9 @@ static void _unregister_device(struct kgsl_device *device) { int minor; + if (device->gpu_sysfs_kobj.state_initialized) + kobject_del(&device->gpu_sysfs_kobj); + mutex_lock(&kgsl_driver.devlock); for (minor = 0; minor < ARRAY_SIZE(kgsl_driver.devp); minor++) { if (device == kgsl_driver.devp[minor]) { @@ -4484,12 +4487,6 @@ int kgsl_device_platform_probe(struct kgsl_device *device) device->pwrctrl.interrupt_num = status; disable_irq(device->pwrctrl.interrupt_num); - rwlock_init(&device->context_lock); - spin_lock_init(&device->submit_lock); - - idr_init(&device->timelines); - spin_lock_init(&device->timelines_lock); - device->events_wq = alloc_workqueue("kgsl-events", WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS | WQ_HIGHPRI, 0); @@ -4504,6 +4501,12 @@ int kgsl_device_platform_probe(struct kgsl_device *device) if (status != 0) goto error_pwrctrl_close; + rwlock_init(&device->context_lock); + spin_lock_init(&device->submit_lock); + + idr_init(&device->timelines); + spin_lock_init(&device->timelines_lock); + kgsl_device_debugfs_init(device); dma_set_coherent_mask(&pdev->dev, KGSL_DMA_BIT_MASK); @@ -4537,9 +4540,6 @@ void kgsl_device_platform_remove(struct kgsl_device *device) kgsl_device_snapshot_close(device); - if (device->gpu_sysfs_kobj.state_initialized) - kobject_del(&device->gpu_sysfs_kobj); - idr_destroy(&device->context_idr); idr_destroy(&device->timelines); diff --git a/drivers/gpu/msm/kgsl_bus.c b/drivers/gpu/msm/kgsl_bus.c index 8cae22d18b54..0839c474f1de 100644 --- a/drivers/gpu/msm/kgsl_bus.c +++ b/drivers/gpu/msm/kgsl_bus.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -224,6 +225,7 @@ void kgsl_bus_close(struct kgsl_device *device) kfree(device->pwrctrl.ddr_table); device->pwrctrl.ddr_table = NULL; icc_put(device->pwrctrl.icc_path); + device->pwrctrl.icc_path = NULL; if (device->pwrctrl.ddr_qos_devfreq) put_device(&device->pwrctrl.ddr_qos_devfreq->dev); } diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c index 0e71e38dcb37..9731d528c4af 100644 --- a/drivers/net/usb/ax88179_178a.c +++ b/drivers/net/usb/ax88179_178a.c @@ -1698,7 +1698,7 @@ static const struct driver_info ax88179_info = { .link_reset = ax88179_link_reset, .reset = ax88179_reset, .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_THROTTLE_RX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; @@ -1711,7 +1711,7 @@ static const struct driver_info ax88178a_info = { .link_reset = ax88179_link_reset, .reset = ax88179_reset, .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_THROTTLE_RX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; @@ -1724,7 +1724,7 @@ static const struct driver_info cypress_GX3_info = { .link_reset = ax88179_link_reset, .reset = ax88179_reset, .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_THROTTLE_RX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; @@ -1737,7 +1737,7 @@ static const struct driver_info dlink_dub1312_info = { .link_reset = ax88179_link_reset, .reset = ax88179_reset, .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_THROTTLE_RX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; @@ -1750,7 +1750,7 @@ static const struct driver_info sitecom_info = { .link_reset = ax88179_link_reset, .reset = ax88179_reset, .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_THROTTLE_RX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; @@ -1763,7 +1763,7 @@ static const struct driver_info samsung_info = { .link_reset = ax88179_link_reset, .reset = ax88179_reset, .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_THROTTLE_RX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; @@ -1776,7 +1776,7 @@ static const struct driver_info lenovo_info = { .link_reset = ax88179_link_reset, .reset = ax88179_reset, .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_THROTTLE_RX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; @@ -1789,7 +1789,7 @@ static const struct driver_info belkin_info = { .link_reset = ax88179_link_reset, .reset = ax88179_reset, .stop = ax88179_stop, - .flags = FLAG_ETHER | FLAG_FRAMING_AX, + .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_THROTTLE_RX, .rx_fixup = ax88179_rx_fixup, .tx_fixup = ax88179_tx_fixup, }; diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 5d6b46e7ee51..1be11bea294e 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -75,6 +75,10 @@ static int msg_level = -1; module_param (msg_level, int, 0); MODULE_PARM_DESC (msg_level, "Override default message level"); +static int usb0_rx_skb_threshold = 500; +module_param(usb0_rx_skb_threshold, int, 0644); +MODULE_PARM_DESC(usb0_rx_skb_threshold, "Throttle rx traffic in USB3"); + /*-------------------------------------------------------------------------*/ /* handles CDC Ethernet and many other network "bulk data" interfaces */ @@ -654,9 +658,13 @@ block: if (netif_running (dev->net) && !test_bit (EVENT_RX_HALT, &dev->flags) && state != unlink_start) { - rx_submit (dev, urb, GFP_ATOMIC); - usb_mark_last_busy(dev->udev); - return; + if ((!(dev->driver_info->flags & FLAG_THROTTLE_RX)) || + ((dev->driver_info->flags & FLAG_THROTTLE_RX) && + (dev->done.qlen < usb0_rx_skb_threshold))) { + rx_submit(dev, urb, GFP_ATOMIC); + usb_mark_last_busy(dev->udev); + return; + } } usb_free_urb (urb); } diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 4b8f78da518d..1428c2493d56 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -89,6 +89,13 @@ static DEFINE_SPINLOCK(time_sync_lock); #define MHI_SUSPEND_RETRY_CNT 3 +#define AFC_SLOT_SIZE 0x1000 +#define AFC_MAX_SLOT 2 +#define AFC_MEM_SIZE (AFC_SLOT_SIZE * AFC_MAX_SLOT) +#define AFC_AUTH_STATUS_OFFSET 1 +#define AFC_AUTH_SUCCESS 1 +#define AFC_AUTH_ERROR 0 + static struct cnss_pci_reg ce_src[] = { { "SRC_RING_BASE_LSB", QCA6390_CE_SRC_RING_BASE_LSB_OFFSET }, { "SRC_RING_BASE_MSB", QCA6390_CE_SRC_RING_BASE_MSB_OFFSET }, @@ -3977,6 +3984,94 @@ int cnss_pci_qmi_send_put(struct cnss_pci_data *pci_priv) return ret; } +int cnss_send_buffer_to_afcmem(struct device *dev, char *afcdb, uint32_t len, + uint8_t slotid) +{ + struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); + struct cnss_fw_mem *fw_mem; + void *mem = NULL; + int i, ret; + u32 *status; + + if (!plat_priv) + return -EINVAL; + + fw_mem = plat_priv->fw_mem; + if (slotid >= AFC_MAX_SLOT) { + cnss_pr_err("Invalid slot id %d\n", slotid); + ret = -EINVAL; + goto err; + } + if (len > AFC_SLOT_SIZE) { + cnss_pr_err("len %d greater than slot size", len); + ret = -EINVAL; + goto err; + } + + for (i = 0; i < plat_priv->fw_mem_seg_len; i++) { + if (fw_mem[i].type == QMI_WLFW_AFC_MEM_V01) { + mem = fw_mem[i].va; + status = mem + (slotid * AFC_SLOT_SIZE); + break; + } + } + + if (!mem) { + cnss_pr_err("AFC mem is not available\n"); + ret = -ENOMEM; + goto err; + } + + memcpy(mem + (slotid * AFC_SLOT_SIZE), afcdb, len); + if (len < AFC_SLOT_SIZE) + memset(mem + (slotid * AFC_SLOT_SIZE) + len, + 0, AFC_SLOT_SIZE - len); + status[AFC_AUTH_STATUS_OFFSET] = cpu_to_le32(AFC_AUTH_SUCCESS); + + return 0; +err: + return ret; +} +EXPORT_SYMBOL(cnss_send_buffer_to_afcmem); + +int cnss_reset_afcmem(struct device *dev, uint8_t slotid) +{ + struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev); + struct cnss_fw_mem *fw_mem; + void *mem = NULL; + int i, ret; + + if (!plat_priv) + return -EINVAL; + + fw_mem = plat_priv->fw_mem; + if (slotid >= AFC_MAX_SLOT) { + cnss_pr_err("Invalid slot id %d\n", slotid); + ret = -EINVAL; + goto err; + } + + for (i = 0; i < plat_priv->fw_mem_seg_len; i++) { + if (fw_mem[i].type == QMI_WLFW_AFC_MEM_V01) { + mem = fw_mem[i].va; + break; + } + } + + if (!mem) { + cnss_pr_err("AFC mem is not available\n"); + ret = -ENOMEM; + goto err; + } + + memset(mem + (slotid * AFC_SLOT_SIZE), 0, AFC_SLOT_SIZE); + return 0; + +err: + return ret; +} +EXPORT_SYMBOL(cnss_reset_afcmem); + int cnss_pci_alloc_fw_mem(struct cnss_pci_data *pci_priv) { struct cnss_plat_data *plat_priv = pci_priv->plat_priv; diff --git a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h index eb89ad4176ad..4145358c86bd 100644 --- a/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h +++ b/drivers/net/wireless/cnss_utils/wlan_firmware_service_v01.h @@ -168,6 +168,7 @@ enum wlfw_mem_type_enum_v01 { QMI_WLFW_MEM_HANG_DATA_V01 = 7, QMI_WLFW_MLO_GLOBAL_MEM_V01 = 8, QMI_WLFW_PAGEABLE_MEM_V01 = 9, + QMI_WLFW_AFC_MEM_V01 = 10, WLFW_MEM_TYPE_ENUM_MAX_VAL_V01 = INT_MAX, }; diff --git a/drivers/pci/controller/pci-msm.c b/drivers/pci/controller/pci-msm.c index f27e6e68ed24..bf1718dfe5a1 100644 --- a/drivers/pci/controller/pci-msm.c +++ b/drivers/pci/controller/pci-msm.c @@ -74,6 +74,7 @@ #define PCIE20_PARF_MHI_CLOCK_RESET_CTRL (0x174) #define PCIE20_PARF_AXI_MSTR_RD_ADDR_HALT (0x1a4) #define PCIE20_PARF_AXI_MSTR_WR_ADDR_HALT (0x1a8) +#define PCIE20_PCIE_PARF_AXI_MSTR_WR_NS_BDF_HALT (0x4a0) #define PCIE20_PARF_LTSSM (0x1b0) #define PCIE20_PARF_INT_ALL_STATUS (0x224) #define PCIE20_PARF_INT_ALL_CLEAR (0x228) @@ -847,6 +848,7 @@ struct msm_pcie_dev_t { bool linkdown_panic; uint32_t boot_option; bool pcie_halt_feature_dis; + bool pcie_bdf_halt_dis; uint32_t rc_idx; uint32_t phy_ver; @@ -1684,6 +1686,8 @@ static void msm_pcie_show_status(struct msm_pcie_dev_t *dev) dev->slv_addr_space_size); PCIE_DBG_FS(dev, "PCIe: halt_feature_dis is %d\n", dev->pcie_halt_feature_dis); + PCIE_DBG_FS(dev, "PCIe: bdf_halt_dis is %d\n", + dev->pcie_bdf_halt_dis); PCIE_DBG_FS(dev, "phy_status_offset: 0x%x\n", dev->phy_status_offset); PCIE_DBG_FS(dev, "phy_status_bit: %u\n", @@ -4761,6 +4765,12 @@ static int msm_pcie_enable(struct msm_pcie_dev_t *dev) BIT(31) | val); } + if (dev->pcie_bdf_halt_dis) { + val = readl_relaxed(dev->parf + PCIE20_PCIE_PARF_AXI_MSTR_WR_NS_BDF_HALT); + msm_pcie_write_reg(dev->parf, PCIE20_PCIE_PARF_AXI_MSTR_WR_NS_BDF_HALT, + (~BIT(0)) & val); + } + /* init tcsr */ if (dev->tcsr_config) pcie_tcsr_init(dev); @@ -6312,6 +6322,11 @@ static int msm_pcie_probe(struct platform_device *pdev) PCIE_DBG(pcie_dev, "PCIe halt feature is %s enabled.\n", pcie_dev->pcie_halt_feature_dis ? "not" : ""); + pcie_dev->pcie_bdf_halt_dis = of_property_read_bool(of_node, + "qcom,bdf-halt-dis"); + PCIE_DBG(pcie_dev, "PCIe BDF halt feature is %s enabled.\n", + pcie_dev->pcie_bdf_halt_dis ? "not" : ""); + of_property_read_u32(of_node, "qcom,phy-status-offset", &pcie_dev->phy_status_offset); PCIE_DBG(pcie_dev, "RC%d: phy-status-offset: 0x%x.\n", pcie_dev->rc_idx, diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c index d8c8f8655f25..222c71854d3b 100644 --- a/drivers/platform/msm/mhi_dev/mhi_uci.c +++ b/drivers/platform/msm/mhi_dev/mhi_uci.c @@ -1748,8 +1748,12 @@ static int mhi_uci_ctrl_set_tiocm(struct uci_client *client, reinit_completion(ctrl_client->write_done); ret_val = mhi_uci_send_packet(ctrl_client, ctrl_msg, sizeof(*ctrl_msg)); - if (ret_val != sizeof(*ctrl_msg)) + if (ret_val != sizeof(*ctrl_msg)) { + uci_log(UCI_DBG_ERROR, "Failed to send ctrl msg\n"); + kfree(ctrl_msg); + ctrl_msg = NULL; goto tiocm_error; + } compl_ret = wait_for_completion_interruptible_timeout( ctrl_client->write_done, MHI_UCI_ASYNC_WRITE_TIMEOUT); @@ -1768,7 +1772,6 @@ static int mhi_uci_ctrl_set_tiocm(struct uci_client *client, return 0; tiocm_error: - kfree(ctrl_msg); return ret_val; } diff --git a/drivers/soc/qcom/icnss2/debug.c b/drivers/soc/qcom/icnss2/debug.c index e12cee7dfc04..88dda1cb3065 100644 --- a/drivers/soc/qcom/icnss2/debug.c +++ b/drivers/soc/qcom/icnss2/debug.c @@ -521,7 +521,8 @@ static int icnss_fw_debug_show(struct seq_file *s, void *data) seq_puts(s, " VAL: 2 (CCPM test)\n"); seq_puts(s, " VAL: 3 (Trigger Recovery)\n"); seq_puts(s, " VAL: 4 (allow recursive recovery)\n"); - seq_puts(s, " VAL: 3 (Disallow recursive recovery)\n"); + seq_puts(s, " VAL: 5 (Disallow recursive recovery)\n"); + seq_puts(s, " VAL: 6 (Trigger power supply callback)\n"); seq_puts(s, "\nCMD: dynamic_feature_mask\n"); seq_puts(s, " VAL: (64 bit feature mask)\n"); @@ -682,6 +683,9 @@ static ssize_t icnss_fw_debug_write(struct file *fp, case 5: icnss_disallow_recursive_recovery(&priv->pdev->dev); break; + case 6: + power_supply_changed(priv->batt_psy); + break; default: return -EINVAL; } diff --git a/drivers/soc/qcom/icnss2/main.c b/drivers/soc/qcom/icnss2/main.c index 7d7021a33e14..51aff64aaa5c 100644 --- a/drivers/soc/qcom/icnss2/main.c +++ b/drivers/soc/qcom/icnss2/main.c @@ -722,6 +722,9 @@ static int icnss_driver_event_server_arrive(struct icnss_priv *priv, if (priv->vbatt_supported) icnss_init_vph_monitor(priv); + if (priv->psf_supported) + queue_work(priv->soc_update_wq, &priv->soc_update_work); + return ret; device_info_failure: @@ -745,6 +748,9 @@ static int icnss_driver_event_server_exit(struct icnss_priv *priv) adc_tm_disable_chan_meas(priv->adc_tm_dev, &priv->vph_monitor_params); + if (priv->psf_supported) + priv->last_updated_voltage = 0; + return 0; } @@ -3610,6 +3616,13 @@ static int icnss_resource_parse(struct icnss_priv *priv) goto put_vreg; } + if (of_property_read_bool(pdev->dev.of_node, "qcom,psf-supported")) { + ret = icnss_get_psf_info(priv); + if (ret < 0) + goto out; + priv->psf_supported = true; + } + if (priv->device_id == ADRASTEA_DEVICE_ID) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "membase"); @@ -4145,6 +4158,18 @@ out_reset_drvdata: return ret; } +static void icnss_unregister_power_supply_notifier(struct icnss_priv *priv) +{ + if (priv->batt_psy) + power_supply_put(penv->batt_psy); + + if (priv->psf_supported) { + flush_workqueue(priv->soc_update_wq); + destroy_workqueue(priv->soc_update_wq); + power_supply_unreg_notifier(&priv->psf_nb); + } +} + static int icnss_remove(struct platform_device *pdev) { struct icnss_priv *priv = dev_get_drvdata(&pdev->dev); @@ -4164,6 +4189,8 @@ static int icnss_remove(struct platform_device *pdev) icnss_debugfs_destroy(priv); + icnss_unregister_power_supply_notifier(penv); + icnss_sysfs_destroy(priv); complete_all(&priv->unblock_shutdown); diff --git a/drivers/soc/qcom/icnss2/main.h b/drivers/soc/qcom/icnss2/main.h index 2c13b3b442a4..b62029408be9 100644 --- a/drivers/soc/qcom/icnss2/main.h +++ b/drivers/soc/qcom/icnss2/main.h @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -167,6 +168,11 @@ struct icnss_clk_cfg { u32 required; }; +struct icnss_battery_level { + int lower_battery_threshold; + int ldo_voltage; +}; + struct icnss_clk_info { struct list_head list; struct clk *clk; @@ -466,6 +472,12 @@ struct icnss_priv { struct icnss_dms_data dms; u8 use_nv_mac; u32 wlan_en_delay_ms; + bool psf_supported; + struct notifier_block psf_nb; + struct power_supply *batt_psy; + int last_updated_voltage; + struct work_struct soc_update_work; + struct workqueue_struct *soc_update_wq; unsigned long device_config; struct timer_list recovery_timer; }; diff --git a/drivers/soc/qcom/icnss2/power.c b/drivers/soc/qcom/icnss2/power.c index 86b33c5a5ad9..0f85f010e2b1 100644 --- a/drivers/soc/qcom/icnss2/power.c +++ b/drivers/soc/qcom/icnss2/power.c @@ -29,6 +29,14 @@ static struct icnss_vreg_cfg icnss_adrestea_vreg_list[] = { {"vdd-smps", 984000, 984000, 0, 0, 0, false, true}, }; +static struct icnss_battery_level icnss_battery_level[] = { + {70, 3300000}, + {60, 3200000}, + {50, 3100000}, + {25, 3000000}, + {0, 2850000}, +}; + static struct icnss_clk_cfg icnss_clk_list[] = { {"rf_clk", 0, 0}, }; @@ -55,6 +63,9 @@ static struct icnss_clk_cfg icnss_adrestea_clk_list[] = { #define MAX_TCS_CMD_NUM 5 #define BT_CXMX_VOLTAGE_MV 950 +#define ICNSS_BATTERY_LEVEL_COUNT ARRAY_SIZE(icnss_battery_level) +#define ICNSS_MAX_BATTERY_LEVEL 100 + static int icnss_get_vreg_single(struct icnss_priv *priv, struct icnss_vreg_info *vreg) { @@ -821,6 +832,110 @@ out: return ret; } +static int icnss_get_battery_level(struct icnss_priv *priv) +{ + int err = 0, battery_percentage = 0; + union power_supply_propval psp = {0,}; + + if (!priv->batt_psy) + priv->batt_psy = power_supply_get_by_name("battery"); + + if (priv->batt_psy) { + err = power_supply_get_property(priv->batt_psy, + POWER_SUPPLY_PROP_CAPACITY, + &psp); + if (err) { + icnss_pr_err("battery percentage read error:%d\n", err); + goto out; + } + battery_percentage = psp.intval; + } + + icnss_pr_info("Battery Percentage: %d\n", battery_percentage); +out: + return battery_percentage; +} + +static void icnss_update_soc_level(struct work_struct *work) +{ + int battery_percentage = 0, current_updated_voltage = 0, err = 0; + int level_count; + struct icnss_priv *priv = container_of(work, struct icnss_priv, soc_update_work); + + battery_percentage = icnss_get_battery_level(priv); + if (!battery_percentage || + battery_percentage > ICNSS_MAX_BATTERY_LEVEL) { + icnss_pr_err("Battery percentage read failure\n"); + return; + } + + for (level_count = 0; level_count < ICNSS_BATTERY_LEVEL_COUNT; + level_count++) { + if (battery_percentage >= + icnss_battery_level[level_count].lower_battery_threshold) { + current_updated_voltage = + icnss_battery_level[level_count].ldo_voltage; + break; + } + } + + if (level_count != ICNSS_BATTERY_LEVEL_COUNT && + priv->last_updated_voltage != current_updated_voltage) { + err = icnss_send_vbatt_update(priv, current_updated_voltage); + if (err < 0) { + icnss_pr_err("Unable to update ldo voltage"); + return; + } + priv->last_updated_voltage = current_updated_voltage; + } +} + +static int icnss_battery_supply_callback(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct power_supply *psy = data; + struct icnss_priv *priv = container_of(nb, struct icnss_priv, + psf_nb); + if (strcmp(psy->desc->name, "battery")) + return NOTIFY_OK; + + if (test_bit(ICNSS_WLFW_CONNECTED, &priv->state) && + !test_bit(ICNSS_FW_DOWN, &priv->state)) + queue_work(priv->soc_update_wq, &priv->soc_update_work); + + return NOTIFY_OK; +} + +int icnss_get_psf_info(struct icnss_priv *priv) +{ + int ret = 0; + + priv->soc_update_wq = alloc_workqueue("icnss_soc_update", + WQ_UNBOUND, 1); + if (!priv->soc_update_wq) { + icnss_pr_err("Workqueue creation failed for soc update\n"); + ret = -EFAULT; + goto out; + } + + priv->psf_nb.notifier_call = icnss_battery_supply_callback; + ret = power_supply_reg_notifier(&priv->psf_nb); + if (ret < 0) { + icnss_pr_err("Power supply framework registration err: %d\n", + ret); + goto err_psf_registration; + } + + INIT_WORK(&priv->soc_update_work, icnss_update_soc_level); + + return 0; + +err_psf_registration: + destroy_workqueue(priv->soc_update_wq); +out: + return ret; +} + int icnss_get_cpr_info(struct icnss_priv *priv) { struct platform_device *plat_dev = priv->pdev; diff --git a/drivers/soc/qcom/icnss2/power.h b/drivers/soc/qcom/icnss2/power.h index 003694135435..490728f0e9a7 100644 --- a/drivers/soc/qcom/icnss2/power.h +++ b/drivers/soc/qcom/icnss2/power.h @@ -15,5 +15,5 @@ void icnss_put_resources(struct icnss_priv *priv); void icnss_put_vreg(struct icnss_priv *priv); void icnss_put_clk(struct icnss_priv *priv); int icnss_vreg_unvote(struct icnss_priv *priv); - +int icnss_get_psf_info(struct icnss_priv *priv); #endif diff --git a/drivers/usb/gadget/function/f_cdev.c b/drivers/usb/gadget/function/f_cdev.c index bef28623462d..9357949a1525 100644 --- a/drivers/usb/gadget/function/f_cdev.c +++ b/drivers/usb/gadget/function/f_cdev.c @@ -573,7 +573,9 @@ static void usb_cser_resume(struct usb_function *f) if (port->setup_pending) { pr_info("%s: start_rx called due to rx_out error.\n", __func__); port->setup_pending = false; + spin_unlock_irqrestore(&port->port_lock, flags); usb_cser_start_rx(port); + spin_lock_irqsave(&port->port_lock, flags); } in = port->port_usb.in; /* process any pending requests */ diff --git a/drivers/virt/haven/hh_rm_core.c b/drivers/virt/haven/hh_rm_core.c index 5bb93ea78643..02fcfcb8ef82 100644 --- a/drivers/virt/haven/hh_rm_core.c +++ b/drivers/virt/haven/hh_rm_core.c @@ -37,18 +37,32 @@ #define HH_RM_MAX_MSG_SIZE_BYTES \ (HH_MSGQ_MAX_MSG_SIZE_BYTES - sizeof(struct hh_rm_rpc_hdr)) +/** + * struct hh_rm_connection - Represents a complete message from resource manager + * @payload: Combined payload of all the fragments without any RPC headers + * @size: Size of the payload. + * @msg_id: Message ID from the header. + * @ret: Linux return code, set in case there was an error processing the connection. + * @type: HH_RM_RPC_TYPE_RPLY or HH_RM_RPC_TYPE_NOTIF. + * @num_fragments: total number of fragments expected to be received for this connection. + * @fragments_received: fragments received so far. + * @rm_error: For request/reply sequences with standard replies. + * @seq: Sequence ID for the main message. + */ struct hh_rm_connection { + void *payload; + size_t size; u32 msg_id; - u16 seq; - void *recv_buff; - u32 reply_err_code; - size_t recv_buff_size; - - struct completion seq_done; + int ret; + u8 type; u8 num_fragments; u8 fragments_received; - void *current_recv_buff; + + /* only for req/reply sequence */ + u32 rm_error; + u16 seq; + struct completion seq_done; }; static struct task_struct *hh_rm_drv_recv_task; @@ -92,6 +106,10 @@ hh_rm_init_connection_buff(struct hh_rm_connection *connection, struct hh_rm_rpc_hdr *hdr = recv_buff; size_t max_buf_size; + connection->num_fragments = hdr->fragments; + connection->fragments_received = 0; + connection->type = hdr->type; + /* Some of the 'reply' types doesn't contain any payload */ if (!payload_size) return 0; @@ -107,15 +125,12 @@ hh_rm_init_connection_buff(struct hh_rm_connection *connection, /* If the data is split into multiple fragments, allocate a large * enough buffer to hold the payloads for all the fragments. */ - connection->recv_buff = connection->current_recv_buff = - kzalloc(max_buf_size, GFP_KERNEL); - if (!connection->recv_buff) + connection->payload = kzalloc(max_buf_size, GFP_KERNEL); + if (!connection->payload) return -ENOMEM; - memcpy(connection->recv_buff, recv_buff + hdr_size, payload_size); - connection->current_recv_buff += payload_size; - connection->recv_buff_size = payload_size; - connection->num_fragments = hdr->fragments; + memcpy(connection->payload, recv_buff + hdr_size, payload_size); + connection->size = payload_size; return 0; } @@ -132,152 +147,121 @@ int hh_rm_unregister_notifier(struct notifier_block *nb) } EXPORT_SYMBOL(hh_rm_unregister_notifier); -static struct hh_rm_connection * -hh_rm_wait_for_notif_fragments(void *recv_buff, size_t recv_buff_size) +static int hh_rm_process_notif(void *msg, size_t msg_size) { - struct hh_rm_rpc_hdr *hdr = recv_buff; + struct hh_rm_rpc_hdr *hdr = msg; struct hh_rm_connection *connection; + u32 notification; size_t payload_size; + void *payload; int ret = 0; - connection = hh_rm_alloc_connection(hdr->msg_id); - if (IS_ERR_OR_NULL(connection)) - return connection; - - payload_size = recv_buff_size - sizeof(*hdr); - curr_connection = connection; - - ret = hh_rm_init_connection_buff(connection, recv_buff, - sizeof(*hdr), payload_size); - if (ret < 0) - goto out; - - if (wait_for_completion_interruptible(&connection->seq_done)) { - ret = -ERESTARTSYS; - goto out; - } - - return connection; - -out: - kfree(connection); - return ERR_PTR(ret); -} - -static int hh_rm_process_notif(void *recv_buff, size_t recv_buff_size) -{ - struct hh_rm_connection *connection = NULL; - struct hh_rm_rpc_hdr *hdr = recv_buff; - u32 notification = hdr->msg_id; - void *payload = NULL; - int ret = 0; - - pr_debug("Notification received from RM-VM: %x\n", notification); - if (curr_connection) { pr_err("Received new notification from RM-VM before completing last connection\n"); return -EINVAL; } - if (recv_buff_size > sizeof(*hdr)) - payload = recv_buff + sizeof(*hdr); + connection = hh_rm_alloc_connection(hdr->msg_id); + if (!connection) + return -EINVAL; - /* If the notification payload is split-up into - * fragments, wait until all them arrive. - */ - if (hdr->fragments) { - connection = hh_rm_wait_for_notif_fragments(recv_buff, - recv_buff_size); - if (IS_ERR_OR_NULL(connection)) - return PTR_ERR(connection); - - /* In the case of fragments, the complete payload - * is contained under connection->recv_buff - */ - payload = connection->recv_buff; - recv_buff_size = connection->recv_buff_size; + if (hh_rm_init_connection_buff(connection, msg, sizeof(*hdr), msg_size - sizeof(*hdr))) { + kfree(connection); + return -EINVAL; } + if (hdr->fragments) + return PTR_ERR(connection); + + payload = connection->payload; + payload_size = connection->size; + notification = connection->msg_id; + pr_debug("Notification received from RM-VM: %x\n", notification); + switch (notification) { case HH_RM_NOTIF_VM_STATUS: - if (recv_buff_size != sizeof(*hdr) + + if (payload_size != sizeof(struct hh_rm_notif_vm_status_payload)) { pr_err("%s: Invalid size for VM_STATUS notif: %u\n", - __func__, recv_buff_size - sizeof(*hdr)); + __func__, payload_size); ret = -EINVAL; goto err; } break; case HH_RM_NOTIF_VM_IRQ_LENT: - if (recv_buff_size != sizeof(*hdr) + + if (payload_size != sizeof(struct hh_rm_notif_vm_irq_lent_payload)) { pr_err("%s: Invalid size for VM_IRQ_LENT notif: %u\n", - __func__, recv_buff_size - sizeof(*hdr)); + __func__, payload_size); ret = -EINVAL; goto err; } break; case HH_RM_NOTIF_VM_IRQ_RELEASED: - if (recv_buff_size != sizeof(*hdr) + + if (payload_size != sizeof(struct hh_rm_notif_vm_irq_released_payload)) { pr_err("%s: Invalid size for VM_IRQ_REL notif: %u\n", - __func__, recv_buff_size - sizeof(*hdr)); + __func__, payload_size); ret = -EINVAL; goto err; } break; case HH_RM_NOTIF_VM_IRQ_ACCEPTED: - if (recv_buff_size != sizeof(*hdr) + + if (payload_size != sizeof(struct hh_rm_notif_vm_irq_accepted_payload)) { pr_err("%s: Invalid size for VM_IRQ_ACCEPTED notif: %u\n", - __func__, recv_buff_size - sizeof(*hdr)); + __func__, payload_size); ret = -EINVAL; goto err; } break; case HH_RM_NOTIF_MEM_SHARED: - if (recv_buff_size < sizeof(*hdr) + + if (payload_size < sizeof(struct hh_rm_notif_mem_shared_payload)) { pr_err("%s: Invalid size for MEM_SHARED notif: %u\n", - __func__, recv_buff_size - sizeof(*hdr)); + __func__, payload_size); ret = -EINVAL; goto err; } break; case HH_RM_NOTIF_MEM_RELEASED: - if (recv_buff_size != sizeof(*hdr) + + if (payload_size != sizeof(struct hh_rm_notif_mem_released_payload)) { pr_err("%s: Invalid size for MEM_RELEASED notif: %u\n", - __func__, recv_buff_size - sizeof(*hdr)); + __func__, payload_size); ret = -EINVAL; goto err; } break; case HH_RM_NOTIF_MEM_ACCEPTED: - if (recv_buff_size != sizeof(*hdr) + + if (payload_size != sizeof(struct hh_rm_notif_mem_accepted_payload)) { pr_err("%s: Invalid size for MEM_ACCEPTED notif: %u\n", - __func__, recv_buff_size - sizeof(*hdr)); + __func__, payload_size); ret = -EINVAL; goto err; } break; case HH_RM_NOTIF_VM_CONSOLE_CHARS: - if (recv_buff_size < sizeof(*hdr) + + if (payload_size >= sizeof(struct hh_rm_notif_vm_console_chars)) { struct hh_rm_notif_vm_console_chars *console_chars; u16 num_bytes; - console_chars = recv_buff + sizeof(*hdr); + console_chars = payload; num_bytes = console_chars->num_bytes; - if (sizeof(*hdr) + sizeof(*console_chars) + num_bytes != - recv_buff_size) { + if (sizeof(*console_chars) + num_bytes != + payload_size) { pr_err("%s: Invalid size for VM_CONSOLE_CHARS notify %u\n", - __func__, recv_buff_size - sizeof(*hdr)); + __func__, payload_size); ret = -EINVAL; goto err; } + } else { + pr_err("%s: Invalid size for VM_CONSOLE_CHARS notify %u\n", + __func__, payload_size); + goto err; } break; default: @@ -291,7 +275,7 @@ static int hh_rm_process_notif(void *recv_buff, size_t recv_buff_size) err: if (connection) { - kfree(connection->recv_buff); + kfree(payload); kfree(connection); } @@ -335,7 +319,7 @@ static int hh_rm_process_rply(void *recv_buff, size_t recv_buff_size) if (ret < 0) return ret; - connection->reply_err_code = reply_hdr->err_code; + connection->rm_error = reply_hdr->err_code; /* * If the data is composed of a single message, wakeup the @@ -383,10 +367,9 @@ static int hh_rm_process_cont(void *recv_buff, size_t recv_buff_size) payload_size = recv_buff_size - sizeof(*hdr); /* Keep appending the data to the previous fragment's end */ - memcpy(connection->current_recv_buff, + memcpy(connection->payload + connection->size, recv_buff + sizeof(*hdr), payload_size); - connection->current_recv_buff += payload_size; - connection->recv_buff_size += payload_size; + connection->size += payload_size; connection->fragments_received++; if (connection->fragments_received == connection->num_fragments) { @@ -403,6 +386,21 @@ struct hh_rm_msgq_data { struct work_struct recv_work; }; +static void hh_rm_abort_connection(struct hh_rm_connection *connection) +{ + switch (connection->type) { + case HH_RM_RPC_TYPE_RPLY: + connection->ret = -EIO; + complete(&connection->seq_done); + break; + case HH_RM_RPC_TYPE_NOTIF: + fallthrough; + default: + kfree(connection->payload); + kfree(connection); + } +} + static void hh_rm_process_recv_work(struct work_struct *work) { struct hh_rm_msgq_data *msgq_data; @@ -414,12 +412,27 @@ static void hh_rm_process_recv_work(struct work_struct *work) switch (hdr->type) { case HH_RM_RPC_TYPE_NOTIF: + if (curr_connection) { + /* Not possible per protocol. Do something better than BUG_ON */ + pr_warn("Received start of new notification without finishing existing message series.\n"); + hh_rm_abort_connection(curr_connection); + } hh_rm_process_notif(recv_buff, msgq_data->recv_buff_size); break; case HH_RM_RPC_TYPE_RPLY: + if (curr_connection) { + /* Not possible per protocol. Do something better than BUG_ON */ + pr_warn("Received start of new reply without finishing existing message series.\n"); + hh_rm_abort_connection(curr_connection); + } hh_rm_process_rply(recv_buff, msgq_data->recv_buff_size); break; case HH_RM_RPC_TYPE_CONT: + if (!curr_connection) { + /* Not possible per protocol. Do something better than BUG_ON */ + pr_warn("Received a continuation message without receiving initial message\n"); + break; + } hh_rm_process_cont(recv_buff, msgq_data->recv_buff_size); break; default: @@ -494,8 +507,8 @@ static int hh_rm_send_request(u32 message_id, unsigned long tx_flags; u32 num_fragments = 0; size_t payload_size; - void *send_buff; - int i, ret; + void *msg; + int i, ret = 0; num_fragments = (req_buff_size + HH_RM_MAX_MSG_SIZE_BYTES - 1) / HH_RM_MAX_MSG_SIZE_BYTES; @@ -512,11 +525,15 @@ static int hh_rm_send_request(u32 message_id, return -E2BIG; } + msg = kzalloc(HH_RM_MAX_MSG_SIZE_BYTES, GFP_KERNEL); + if (!msg) + return -ENOMEM; + if (mutex_lock_interruptible(&hh_rm_send_lock)) { - return -ERESTARTSYS; + ret = -ERESTARTSYS; + goto free_msg; } - /* Consider also the 'request' packet for the loop count */ for (i = 0; i <= num_fragments; i++) { if (buff_size_remaining > HH_RM_MAX_MSG_SIZE_BYTES) { payload_size = HH_RM_MAX_MSG_SIZE_BYTES; @@ -525,13 +542,10 @@ static int hh_rm_send_request(u32 message_id, payload_size = buff_size_remaining; } - send_buff = kzalloc(sizeof(*hdr) + payload_size, GFP_KERNEL); - if (!send_buff) { - mutex_unlock(&hh_rm_send_lock); - return -ENOMEM; - } + memset(msg, 0, HH_RM_MAX_MSG_SIZE_BYTES); + /* Fill header */ + hdr = msg; - hdr = send_buff; hdr->version = HH_RM_RPC_HDR_VERSION_ONE; hdr->hdr_words = HH_RM_RPC_HDR_WORDS; hdr->type = i == 0 ? HH_RM_RPC_TYPE_REQ : HH_RM_RPC_TYPE_CONT; @@ -539,11 +553,12 @@ static int hh_rm_send_request(u32 message_id, hdr->seq = connection->seq; hdr->msg_id = message_id; - memcpy(send_buff + sizeof(*hdr), req_buff_curr, payload_size); + /* Copy payload */ + memcpy(msg + sizeof(*hdr), req_buff_curr, payload_size); req_buff_curr += payload_size; - /* Force the last fragment (or the request type) - * to be sent immediately to the receiver + /* Force the last fragment to be sent immediately to + * the receiver */ tx_flags = (i == num_fragments) ? HH_MSGQ_TX_PUSH : 0; @@ -552,25 +567,17 @@ static int hh_rm_send_request(u32 message_id, message_id == HH_RM_RPC_MSG_ID_CALL_VM_CONSOLE_FLUSH) udelay(800); - ret = hh_msgq_send(hh_rm_msgq_desc, send_buff, + ret = hh_msgq_send(hh_rm_msgq_desc, msg, sizeof(*hdr) + payload_size, tx_flags); - /* - * In the case of a success, the hypervisor would have consumed - * the buffer. While in the case of a failure, we are going to - * quit anyways. Hence, free the buffer regardless of the - * return value. - */ - kfree(send_buff); - - if (ret) { - mutex_unlock(&hh_rm_send_lock); - return ret; - } + if (ret) + break; } mutex_unlock(&hh_rm_send_lock); - return 0; +free_msg: + kfree(msg); + return ret; } /** @@ -579,7 +586,7 @@ static int hh_rm_send_request(u32 message_id, * @req_buff: Request buffer that contains the payload * @req_buff_size: Total size of the payload * @resp_buff_size: Size of the response buffer - * @reply_err_code: Returns Haven standard error code for the response + * @rm_error: Returns Haven standard error code for the response * * Make a request to the RM-VM and expect a reply back. For a successful * response, the function returns the payload and its size for the response. @@ -591,13 +598,13 @@ static int hh_rm_send_request(u32 message_id, */ void *hh_rm_call(hh_rm_msgid_t message_id, void *req_buff, size_t req_buff_size, - size_t *resp_buff_size, int *reply_err_code) + size_t *resp_buff_size, int *rm_error) { struct hh_rm_connection *connection; int req_ret; void *ret; - if (!message_id || !req_buff || !resp_buff_size || !reply_err_code) + if (!message_id || !req_buff || !resp_buff_size || !rm_error) return ERR_PTR(-EINVAL); connection = hh_rm_alloc_connection(message_id); @@ -632,27 +639,33 @@ void *hh_rm_call(hh_rm_msgid_t message_id, goto out; } - *reply_err_code = connection->reply_err_code; - if (connection->reply_err_code) { - pr_err("%s: Reply for seq:%d failed with RM err: %d\n", - __func__, connection->seq, connection->reply_err_code); - ret = ERR_PTR(hh_remap_error(connection->reply_err_code)); - kfree(connection->recv_buff); - goto out; - } - - print_hex_dump_debug("hh_rm_call RX: ", DUMP_PREFIX_OFFSET, 4, 1, - connection->recv_buff, connection->recv_buff_size, - false); - - ret = connection->recv_buff; - *resp_buff_size = connection->recv_buff_size; - -out: mutex_lock(&hh_rm_call_idr_lock); idr_remove(&hh_rm_call_idr, connection->seq); mutex_unlock(&hh_rm_call_idr_lock); + *rm_error = connection->rm_error; + if (connection->rm_error) { + pr_err("%s: Reply for seq:%d failed with RM err: %d\n", + __func__, connection->seq, connection->rm_error); + ret = ERR_PTR(hh_remap_error(connection->rm_error)); + kfree(connection->payload); + goto out; + } + + if (connection->ret) { + ret = ERR_PTR(connection->ret); + kfree(connection->payload); + goto out; + } + + print_hex_dump_debug("hh_rm_call RX: ", DUMP_PREFIX_OFFSET, 4, 1, + connection->payload, connection->size, + false); + + ret = connection->payload; + *resp_buff_size = connection->size; + +out: kfree(connection); return ret; } diff --git a/include/linux/ipa_eth.h b/include/linux/ipa_eth.h index f746ce965777..e64fca58d1fe 100644 --- a/include/linux/ipa_eth.h +++ b/include/linux/ipa_eth.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _IPA_ETH_H_ @@ -73,10 +75,13 @@ enum ipa_eth_pipe_direction { * * @bar_addr: bar PA to access NTN register * @tail_ptr_offs: tail ptr offset + * @ioc_mod_threshold: Descriptors # per interrupt request from + * NTN3 HW via descriptor bit as part of the protocol. */ struct ipa_eth_ntn_setup_info { phys_addr_t bar_addr; phys_addr_t tail_ptr_offs; + uint16_t ioc_mod_threshold; }; /** @@ -112,6 +117,7 @@ struct ipa_eth_realtek_setup_info { phys_addr_t dest_tail_ptr_offs; }; + /** * struct ipa_eth_buff_smmu_map - IPA iova->pa SMMU mapping * @iova: virtual address of the data buffer diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h index a90e2a9dfdd3..73f5f58d6e72 100644 --- a/include/linux/usb/usbnet.h +++ b/include/linux/usb/usbnet.h @@ -129,6 +129,7 @@ struct driver_info { #define FLAG_MULTI_PACKET 0x2000 #define FLAG_RX_ASSEMBLE 0x4000 /* rx packets may span >1 frames */ #define FLAG_NOARP 0x8000 /* device can't do ARP */ +#define FLAG_THROTTLE_RX 0x10000 /* Throttle RX traffic in USB SS */ /* init device ... can sleep, or cause probe() failure */ int (*bind)(struct usbnet *, struct usb_interface *); diff --git a/include/net/cnss2.h b/include/net/cnss2.h index 2cbfd3136d82..dbb0ea5978fb 100644 --- a/include/net/cnss2.h +++ b/include/net/cnss2.h @@ -278,4 +278,7 @@ extern int cnss_get_mem_seg_count(enum cnss_remote_mem_type type, u32 *seg); extern int cnss_get_mem_segment_info(enum cnss_remote_mem_type type, struct cnss_mem_segment segment[], u32 segment_count); +extern int cnss_send_buffer_to_afcmem(struct device *dev, char *afcdb, + uint32_t len, uint8_t slotid); +extern int cnss_reset_afcmem(struct device *dev, uint8_t slotid); #endif /* _NET_CNSS2_H */ diff --git a/include/uapi/linux/ipa_qmi_service_v01.h b/include/uapi/linux/ipa_qmi_service_v01.h index 55148fd4f494..d79855aa3cc2 100644 --- a/include/uapi/linux/ipa_qmi_service_v01.h +++ b/include/uapi/linux/ipa_qmi_service_v01.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ /* @@ -52,6 +54,9 @@ #define QMI_IPA_IPFLTR_NUM_MEQ_32_EQNS_V01 2 #define QMI_IPA_MAX_PIPES_V01 20 #define QMI_IPA_MAX_PER_CLIENTS_V01 64 +#define QMI_IPA_MAX_RMNET_ETH_INFO_V01 19 +#define QMI_IPA_MAX_MAC_ADDR_LEN_V01 6 +#define QMI_IPA_MAX_IPV4_ADDR_LEN_V01 4 /* * Indicates presence of newly added member to support HW stats. @@ -113,6 +118,19 @@ enum ipa_platform_type_enum_v01 { /* To force a 32 bit signed enum. Do not change or use */ }; +enum ipa_eth_hw_config_enum_v01 { + IPA_QMI_ETH_HW_CONFIG_ENUM_MIN_ENUM_VAL_V01 = -2147483647, + /**< To force a 32 bit signed enum. Do not change or use*/ + IPA_QMI_ETH_HW_NONE_V01 = 0x00, + /**< Ethernet Setting HW Default \n */ + IPA_QMI_ETH_HW_VLAN_IP_V01 = 0x01, + /**< Ethernet HW VLAN+IP supported \n */ + IPA_QMI_ETH_HW_NON_VLAN_IP_V01 = 0x02, + /**< Ethernet HW NON_VLAN+IP supported */ + IPA_QMI_ETH_HW_CONFIG_ENUM_MAX_ENUM_VAL_V01 = 2147483647 + /**< To force a 32 bit signed enum. Do not change or use*/ +}; + #define QMI_IPA_PLATFORM_TYPE_LE_MHI_V01 \ QMI_IPA_PLATFORM_TYPE_LE_MHI_V01 @@ -538,6 +556,18 @@ struct ipa_indication_reg_req_msg_v01 { * message makes sense only when the QMI_IPA_INDICATION_REGISTER_REQ * is being originated from the master driver. */ + + /* Optional */ + /* Rmnet Ethernet MAC Information */ + __u8 rmnet_eth_mac_info_valid; + /* Must be set to true if rmnet_eth_mac_info is being passed */ + __u8 rmnet_eth_mac_info; + /* If set to TRUE, this field indicates that the client wants to + * receive indications about embeddd rmnet_eth mac info via + * QMI_IPA_RMNET_ETH_INFO_INDICATION. Setting this field in the request + * message makes sense only when the QMI_IPA_INDICATION_REGISTER_REQ is + * being originated from the master driver. + */ }; /* Message */ @@ -2559,6 +2589,7 @@ enum ipa_ic_type_enum_v01 { DATA_IC_TYPE_AP_V01 = 0x04, DATA_IC_TYPE_Q6_V01 = 0x05, DATA_IC_TYPE_UC_V01 = 0x06, + DATA_IC_TYPE_ETH_V01 = 0x07, IPA_IC_TYPE_ENUM_MAX_VAL_V01 = IPA_INT_MAX, }; @@ -2781,6 +2812,78 @@ struct ipa_move_nat_table_complt_ind_msg_v01 { }; /* Message */ #define QMI_IPA_NAT_TABLE_MOVE_COMPLETE_IND_MAX_MSG_LEN_V01 7 +/* + * Request Message; QMI request message to request for a dual-backhaul traffic + * offloading with ethernet and WWAN and notify the eth-header + */ +struct ipa_eth_backhaul_info_req_msg_v01 { + /* Mandatory */ + /* SRC MAC ADDR */ + __u8 src_mac_addr[QMI_IPA_MAX_MAC_ADDR_LEN_V01]; + /* src mac addr of eth hdr */ + /* Mandatory */ + /* DST MAC ADDR */ + __u8 dst_mac_addr[QMI_IPA_MAX_MAC_ADDR_LEN_V01]; + /* dst mac addr of eth hdr */ + /* Mandatory */ + /* IPv4 ADDR of ETH0 */ + __u32 ipv4_addr_eth0[QMI_IPA_MAX_IPV4_ADDR_LEN_V01]; + /* ipv4 addr of eth0 */ + /* Mandatory */ + /* ETH PIPE */ + __u8 eth_pipe; + /* Specifies eth pipe for Q6 to route UL pkts for ETH backhaul */ + /* Mandatory */ + /* ACTION */ + __u8 enable; + /* Specifies whether eth backhaul is enabled or disabled */ +}; /* Message */ +#define IPA_ETH_BACKHAUL_INFO_REQ_MSG_V01_MAX_MSG_LEN 45 + +/* Response Message; to notify the status of the dual-backhaul traffic + * offloading request using QMI_IPA_ETH_BACKHAUL_INFO_REQ + */ +struct ipa_eth_backhaul_info_resp_msg_v01 { + /* Mandatory */ + /* Result Code */ + struct ipa_qmi_response_type_v01 resp; + /* + * Standard response type. + * Standard response type. Contains the following data members: + * qmi_result_type -- QMI_RESULT_SUCCESS or QMI_RESULT_FAILURE + * qmi_error_type -- Error code. Possible error code values are + * described in the error codes section of each message definition. + */ +}; /* Message */ +#define IPA_ETH_BACKHAUL_INFO_RESP_MSG_V01_MAX_MSG_LEN 7 + +struct ipa_rmnet_eth_info_type_v01 { + __u8 mac_addr[QMI_IPA_MAX_MAC_ADDR_LEN_V01]; + /* mac addr of rmnet_eth */ + __u32 mux_id; + /* QMAP Mux ID. As a part of the QMAP protocol, + * several data calls may be multiplexed over the same physical transport + * channel. This identifier is used to identify one such data call. + * The maximum value for this identifier is 255. + */ +}; /* Type */ + +/* Indication Message; This is an indication to send rmnet ethernet information + * for embedded wireless ethernet PDU from the modem processor to + * the application processor + */ +struct ipa_rmnet_eth_info_indication_msg_v01 { + /* Optional */ + /* Rmnet Ethernet Information */ + __u8 rmnet_eth_info_valid; + /* Must be set to true if rmnet_eth_info is being passed */ + __u32 rmnet_eth_info_len; + /* Must be set to # of elements in rmnet_eth_info */ + struct ipa_rmnet_eth_info_type_v01 rmnet_eth_info[QMI_IPA_MAX_RMNET_ETH_INFO_V01]; + /* Rmnet Ethernet Info array */ +}; /* Message */ +#define IPA_RMNET_ETH_INFO_INDICATION_MSG_V01_MAX_MSG_LEN 194 + /*Service Message Definition*/ #define QMI_IPA_INDICATION_REGISTER_REQ_V01 0x0020 #define QMI_IPA_INDICATION_REGISTER_RESP_V01 0x0020 @@ -2839,6 +2942,9 @@ struct ipa_move_nat_table_complt_ind_msg_v01 { #define QMI_IPA_MOVE_NAT_REQ_V01 0x0046 #define QMI_IPA_MOVE_NAT_RESP_V01 0x0046 #define QMI_IPA_MOVE_NAT_COMPLETE_IND_V01 0x0046 +#define QMI_IPA_ETH_BACKHAUL_INFO_REQ_V01 0x0047 +#define QMI_IPA_ETH_BACKHAUL_INFO_RESP_V01 0x0047 +#define QMI_IPA_RMNET_ETH_INFO_INDICATION_V01 0x0048 /* add for max length*/ #define QMI_IPA_INIT_MODEM_DRIVER_REQ_MAX_MSG_LEN_V01 197 diff --git a/include/uapi/linux/msm_ipa.h b/include/uapi/linux/msm_ipa.h index b6ad02a7ea3c..594cc65c2d0c 100644 --- a/include/uapi/linux/msm_ipa.h +++ b/include/uapi/linux/msm_ipa.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _UAPI_MSM_IPA_H_ @@ -261,12 +263,13 @@ #define IPA_FLT_L2TP_UDP_INNER_MAC_DST_ADDR (1ul << 31) /* Extended attributes for the rule (routing or filtering) */ -#define IPA_FLT_EXT_L2TP_UDP_TCP_SYN (1ul << 0) -#define IPA_FLT_EXT_L2TP_UDP_INNER_ETHER_TYPE (1ul << 1) -#define IPA_FLT_EXT_MTU (1ul << 2) -#define IPA_FLT_EXT_L2TP_UDP_INNER_NEXT_HDR (1ul << 3) -#define IPA_FLT_EXT_NEXT_HDR (1ul << 4) - +#define IPA_FLT_EXT_L2TP_UDP_TCP_SYN (1ul << 0) +#define IPA_FLT_EXT_L2TP_UDP_INNER_ETHER_TYPE (1ul << 1) +#define IPA_FLT_EXT_MTU (1ul << 2) +#define IPA_FLT_EXT_L2TP_UDP_INNER_NEXT_HDR (1ul << 3) +#define IPA_FLT_EXT_NEXT_HDR (1ul << 4) +/* ip protocol/udp ports/eth-type */ +#define IPA_FLT_EXT_MPLS_GRE_GENERAL (1ul << 5) /** * maximal number of NAT PDNs in the PDN config table @@ -517,9 +520,15 @@ enum ipa_client_type { /* RESERVED PROD = 124, */ IPA_CLIENT_TPUT_CONS = 125, + + IPA_CLIENT_Q6_DL_NLO_ETH_DATA_PROD = 126, + /* RESERVED CONS = 127, */ + + IPA_CLIENT_APPS_WAN_ETH_PROD = 128, + /* RESERVED CONS = 129, */ }; -#define IPA_CLIENT_MAX (IPA_CLIENT_TPUT_CONS + 1) +#define IPA_CLIENT_MAX (IPA_CLIENT_APPS_WAN_ETH_PROD + 1) #define IPA_CLIENT_WLAN2_PROD IPA_CLIENT_A5_WLAN_AMPDU_PROD #define IPA_CLIENT_Q6_DL_NLO_DATA_PROD IPA_CLIENT_Q6_DL_NLO_DATA_PROD @@ -562,7 +571,8 @@ enum ipa_client_type { ((client) == IPA_CLIENT_APPS_LAN_PROD || \ (client) == IPA_CLIENT_APPS_WAN_PROD || \ (client) == IPA_CLIENT_APPS_WAN_LOW_LAT_PROD || \ - (client) == IPA_CLIENT_APPS_WAN_LOW_LAT_DATA_PROD) + (client) == IPA_CLIENT_APPS_WAN_LOW_LAT_DATA_PROD || \ + (client) == IPA_CLIENT_APPS_WAN_ETH_PROD) #define IPA_CLIENT_IS_USB_CONS(client) \ ((client) == IPA_CLIENT_USB_CONS || \ @@ -611,7 +621,8 @@ enum ipa_client_type { (client) == IPA_CLIENT_Q6_DL_NLO_LL_DATA_PROD || \ (client) == IPA_CLIENT_Q6_DL_NLO_DATA_PROD || \ (client) == IPA_CLIENT_Q6_CV2X_PROD || \ - (client) == IPA_CLIENT_Q6_AUDIO_DMA_MHI_PROD) + (client) == IPA_CLIENT_Q6_AUDIO_DMA_MHI_PROD || \ + (client) == IPA_CLIENT_Q6_DL_NLO_ETH_DATA_PROD) #define IPA_CLIENT_IS_Q6_NON_ZIP_CONS(client) \ ((client) == IPA_CLIENT_Q6_LAN_CONS || \ @@ -712,6 +723,17 @@ enum ipa_ip_type { #define VALID_IPA_IP_TYPE(t) \ ((t) >= IPA_IP_v4 && (t) < IPA_IP_MAX) +static inline const char *ipa_ip_type_as_str(enum ipa_ip_type t) +{ + return + (t == IPA_IP_v4) ? "v4" : + (t == IPA_IP_v6) ? "v6" : + (t == IPA_IP_MAX) ? "max|v4_vlan" : + (t == IPA_IP_v6_VLAN) ? "v6_vlan" : + (t == IPA_IP_MAX_WLAN) ? "max_wlan" : + "???"; +} + /** * enum ipa_rule_type - Type of routing or filtering rule * Hashable: Rule will be located at the hashable tables @@ -939,7 +961,14 @@ enum ipa_ext_route_evt { #define IPA_SET_EXT_ROUTER_MODE_EVENT_MAX IPA_SET_EXT_ROUTER_MODE_EVENT_MAX }; -#define IPA_EVENT_MAX_NUM (IPA_SET_EXT_ROUTER_MODE_EVENT_MAX) +enum ipa_eth_pdu_evt { + IPA_ENABLE_ETH_PDU_MODE_EVENT = IPA_SET_EXT_ROUTER_MODE_EVENT_MAX, + IPA_ENABLE_ETH_PDU_MODE_EVENT_MAX +#define IPA_ENABLE_ETH_PDU_MODE_EVENT_MAX IPA_ENABLE_ETH_PDU_MODE_EVENT_MAX +}; + + +#define IPA_EVENT_MAX_NUM (IPA_ENABLE_ETH_PDU_MODE_EVENT_MAX) #define IPA_EVENT_MAX ((int)IPA_EVENT_MAX_NUM) /** @@ -1056,6 +1085,100 @@ enum ipa_hw_feature_support { #define IPA_HW_ETH_BRIDGING_SUPPORT_BMSK 0x1 +/** + * enum ipa_exception_type + * + * This enum is for describing which field is to be looked at for + * exception path consideration. + * + * NOTE 1: The field implies an offset into the packet under + * consideration. This offset will be calculated on behalf of + * the user of this API. + * + * NOTE 2: When exceptions are generated/sent in an ipa_exception + * structure, they will considered to be from the upload + * perspective. And when appropriate, a corresponding, and + * perhaps inverted, downlink exception will be automatically + * created on the callers behalf. As an example: If a + * FIELD_UDP_SRC_PORT is sent, an uplink exception will be + * created for udp source port, and a corresponding + * FIELD_UDP_DST_PORT will be automatically created for the + * downlink. + */ +enum ipa_exception_type { + FIELD_IP_PROTOCOL = 0, + FIELD_TCP_SRC_PORT = 1, + FIELD_TCP_DST_PORT = 2, + FIELD_UDP_SRC_PORT = 3, + FIELD_UDP_DST_PORT = 4, + FIELD_ETHER_TYPE = 5, + FIELD_MAX +}; + +#define VALID_EXCEPTION_TYPE(x) \ + ((x) >= FIELD_IP_PROTOCOL && (x) < FIELD_MAX) + +static inline const char *exception_type_as_str(enum ipa_exception_type t) +{ + return + (t == FIELD_IP_PROTOCOL) ? "ip_protocol" : + (t == FIELD_TCP_SRC_PORT) ? "tcp_src_port" : + (t == FIELD_TCP_DST_PORT) ? "tcp_dst_port" : + (t == FIELD_UDP_SRC_PORT) ? "udp_src_port" : + (t == FIELD_UDP_DST_PORT) ? "udp_dst_port" : + (t == FIELD_ETHER_TYPE) ? "ether_type" : + (t == FIELD_MAX) ? "max" : + "???"; +} + +#define IP_TYPE_EXCEPTION(x) \ + ((x) == FIELD_IP_PROTOCOL || \ + (x) == FIELD_TCP_SRC_PORT || \ + (x) == FIELD_TCP_DST_PORT || \ + (x) == FIELD_UDP_SRC_PORT || \ + (x) == FIELD_UDP_DST_PORT) + +/** + * enum ipa_data_flow_type + * + * This enum is for describing whether a data flow is uplink or down. + */ +enum ipa_data_flow_type { + FLOW_UPLINK = 0, + FLOW_DOWNLINK = 1, + FLOW_MAX +}; + +#define VALID_FLOW_TYPE(x) \ + ((x) >= FLOW_UPLINK && (x) < FLOW_MAX) + +static inline const char *flow_type_as_str(enum ipa_data_flow_type t) +{ + return + (t == FLOW_UPLINK) ? "uplink" : + (t == FLOW_DOWNLINK) ? "downlink" : + (t == FLOW_MAX) ? "max" : + "???"; +} + +/** + * struct ipa_field_val_equation_gen + * + * Needed for generating an equation for peering into and finding + * data in a packet or frame. + * + * @flow: Are we generating an equation for uplink or downlink + * @inner_iptype: What's the ip type of the inner packet + * @field: Field we're generating equation for + * @value: The value at that field we're looking for + */ +struct ipa_field_val_equation_gen { + enum ipa_data_flow_type flow; + enum ipa_ip_type inner_iptype; + enum ipa_exception_type field; + uint32_t value; +}; + /** * struct ipa_rule_attrib - attributes of a routing/filtering * rule, all in LE @@ -1088,6 +1211,7 @@ enum ipa_hw_feature_support { * @payload_length: Payload length. * @ext_attrib_mask: Extended attributes. * @l2tp_udp_next_hdr: next header in L2TP tunneling + * @field_val_equ: for finding a value at a particular offset */ struct ipa_rule_attrib { uint32_t attrib_mask; @@ -1133,7 +1257,7 @@ struct ipa_rule_attrib { __u32 ext_attrib_mask; __u8 l2tp_udp_next_hdr; __u8 padding1; - __u32 padding2; + struct ipa_field_val_equation_gen fld_val_eq; }; @@ -1396,8 +1520,8 @@ enum ipa_hdr_l2_type { * IPA_HDR_PROC_L2TP_UDP_HEADER_REMOVE: Process Ethernet To WLAN packets to * remove L2TP UDP header. * IPA_HDR_PROC_SET_DSCP: - * IPA_HDR_PROC_EoGRE_HEADER_ADD: Add IPV[46] GRE header - * IPA_HDR_PROC_EoGRE_HEADER_REMOVE: Remove IPV[46] GRE header + * IPA_HDR_PROC_EoGRE_HEADER_ADD: Add IPV[46] and GRE header + * IPA_HDR_PROC_EoGRE_HEADER_REMOVE: Remove IPV[46] and GRE header */ enum ipa_hdr_proc_type { IPA_HDR_PROC_NONE, @@ -1576,7 +1700,8 @@ struct ipa_l2tp_hdr_proc_ctx_params { }; #define IPA_EoGRE_MAX_PCP_IDX 8 /* From 802.1Q tag format (reflects IEEE P802.1p) */ -#define IPA_EoGRE_MAX_VLAN 8 /* Our supported number of VLAN id's */ +#define IPA_EoGRE_MAX_VLAN 8 /* Supported number of VLAN id's (C-Tag when MPLSoGRE) */ +#define IPA_GRE_MAX_S_VLAN 4 /* We'll support up to 4 vlans from the S-Tag */ /* vlan 12 bits + pcp 3 bites <-> dscp 6 bits */ struct IpaDscpVlanPcpMap_t { @@ -1587,23 +1712,98 @@ struct IpaDscpVlanPcpMap_t { /* * dscp[vlan][pcp], valid only lower 6 bits, using pcp as index */ - uint8_t dscp[IPA_EoGRE_MAX_VLAN][IPA_EoGRE_MAX_PCP_IDX]; - uint8_t num_vlan; /* indicate how many vlans valid */ - uint8_t reserved0; + uint8_t dscp[IPA_EoGRE_MAX_VLAN][IPA_EoGRE_MAX_PCP_IDX]; + uint8_t num_vlan; /* indicate how many vlans valid vlan above */ + uint8_t num_s_vlan; /* indicate how many vlans valid in s_vlan below */ + uint8_t dscp_opt; /* indicates if dscp is required or optional */ + uint8_t pad1; /* for alignment */ + /* + * The same lookup scheme, using vlan[] above, is used for + * generating the first index of mpls below; and in addition, + * we've added a similar array, s_vlan[], for generating the + * second index below. + */ + uint16_t s_vlan[IPA_GRE_MAX_S_VLAN]; + /* + * mpls[C-Tag vlan][S-Tag vlan] -> Only the lower 20 bits of the + * 32-bit mpls value will be used, since that's the size of the + * MPLS label component. + */ + uint32_t mpls[IPA_EoGRE_MAX_VLAN][IPA_GRE_MAX_S_VLAN]; + /* + * following three arrays are used for DL vlan tag lookup + * mpls_val_sorted is in ascending order, by mpls label values in mpls array + * vlan_c and vlan_s are vlan id values that are corresponding to the mpls label + */ + uint16_t pad2; /* for alignment */ + uint8_t pad3; /* for alignment */ + uint8_t num_mpls_val_sorted; /* num of elements in mpls_val_sorted */ + uint32_t mpls_val_sorted[IPA_EoGRE_MAX_VLAN * IPA_GRE_MAX_S_VLAN]; + uint8_t vlan_c[IPA_EoGRE_MAX_VLAN * IPA_GRE_MAX_S_VLAN]; + uint8_t vlan_s[IPA_EoGRE_MAX_VLAN * IPA_GRE_MAX_S_VLAN]; } __packed; +/** + * struct ipa_exception + * + * This structure is used to generate an exception filter rule (see + * exception_list in struct ipa_ipgre_info). + * + * NOTE: + * + * When generating the exception list, generate them from the + * perepctive of the UL data flow. The inner workings of the system + * will generate the complimentary DL rule, if necessary. For + * example, UL TCP or UDP source/destination ports will have the + * complimentary DL rule generated with the addresses and ports + * reversed. + * + * For finding/matching @value at @field. + * + * Please always set @inner_iptype even when looking for an element in + * an Ethernet header. In that case, inner_iptype would be set to the + * ip header type following the Ethernet header. + */ +struct ipa_exception { + enum ipa_exception_type field; + uint32_t value; + enum ipa_ip_type inner_iptype; +} __packed; + +#define IPA_MAX_EXCEPTIONS 10 /* Max exception rule tuples */ + struct ipa_ipgre_info { - /* ip address type */ + /* + * GRE tunnel's ip address type. + */ enum ipa_ip_type iptype; - /* ipv4 */ + /* + * If GRE tunnel is ipv4, then address goes here. + */ uint32_t ipv4_src; uint32_t ipv4_dst; - /* ipv6 */ + /* + * Else if GRE tunnel is ipv6, then address goes here. + */ uint32_t ipv6_src[4]; uint32_t ipv6_dst[4]; - /* gre header info */ + /* + * If running MPLS over GRE, please provide mpls header value + * here. + */ + uint32_t mpls_protocol; + /* + * GRE header value. + */ uint16_t gre_protocol; -}; + uint8_t unused; /* for alignment */ + /* + * The number of valid elements in, and the accompanying + * exception_list, below + */ + uint8_t num_exceptions; + struct ipa_exception exception_list[IPA_MAX_EXCEPTIONS]; +} __packed; struct ipa_ioc_eogre_info { /* ip and gre info */ @@ -1618,23 +1818,33 @@ struct ipa_ioc_eogre_info { * @input_ip_version: Specifies if Input header is IPV4(0) or IPV6(1) * @output_ip_version: Specifies if template header's outer IP is IPV4(0) or IPV6(1) * @second_pass: Specifies if the data should be processed again. + * @is_mpls: Specifies if ucp cmd is for legacy EoGRE(0) or MPLSoGRE(1) + * @tag_remove_len: Specifies amount to be removed for the tags */ struct ipa_eogre_header_add_procparams { uint32_t eth_hdr_retained :1; uint32_t input_ip_version :1; uint32_t output_ip_version :1; uint32_t second_pass :1; - uint32_t reserved :28; + uint32_t is_mpls :1; + uint32_t tag_remove_len :4; + uint32_t reserved :23; }; /** * struct ipa_eogre_header_remove_procparams - - * @hdr_len_remove: Specifies how much (in bytes) of the header needs - * to be removed + * @hdr_len_remove: Specifies how much (in bytes) of the header needs + * to be removed + * @outer_ip_version: Specifies if template header's outer IP is IPV4(0) or IPV6(1) + * @is_mpls: Specifies if ucp cmd is for legacy EoGRE(0) or MPLSoGRE(1) + * @tag_add_len: Specifies amount to be added for the tags */ struct ipa_eogre_header_remove_procparams { - uint32_t hdr_len_remove:8; /* 44 bytes for IPV6, 24 for IPV4 */ - uint32_t reserved:24; + uint32_t hdr_len_remove :8; /* 44 bytes for IPV6, 24 for IPV4 */ + uint32_t outer_ip_version :1; + uint32_t is_mpls :1; + uint32_t tag_add_len :4; + uint32_t reserved :18; }; /** diff --git a/include/uapi/linux/msm_rmnet.h b/include/uapi/linux/msm_rmnet.h index 25267c3c9b09..fb00ec04b48a 100644 --- a/include/uapi/linux/msm_rmnet.h +++ b/include/uapi/linux/msm_rmnet.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ /* * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef _UAPI_MSM_RMNET_H_ @@ -72,6 +74,10 @@ #define RMNET_IOCTL_SET_MTU 0x0020 /* Set v4/v6 MTU */ #define RMNET_IOCTL_GET_EPID_LL 0x0021 /* Get LL ep ID */ #define RMNET_IOCTL_GET_EP_PAIR_LL 0x0022 /* LL ep pair */ +#define RMNET_IOCTL_SET_ETH_VLAN 0x0023 /* Set ETH Vlan */ +#define RMNET_IOCTL_ADD_MUX_CHANNEL_v2 0x0024 /* Add MUX ID + mac*/ +#define RMNET_IOCTL_GET_EPID_ETH 0x0025 /* Get ETH ep ID */ +#define RMNET_IOCTL_GET_EP_PAIR_ETH 0x0026 /* ETH data ep pair*/ /** * RMNET_IOCTL_EXTENDED_V2 ioctl types. @@ -100,19 +106,21 @@ #define RMNET_IOCTL_FEAT_FLOW_CONTROL (1<<7) #define RMNET_IOCTL_FEAT_GET_DFLT_CONTROL_CHANNEL (1<<8) #define RMNET_IOCTL_FEAT_GET_HWSW_MAP (1<<9) +#define RMNET_IOCTL_FEAT_ETH_PDU (1<<10) /* Input values for the RMNET_IOCTL_SET_EGRESS_DATA_FORMAT IOCTL */ #define RMNET_IOCTL_EGRESS_FORMAT_MAP (1<<1) #define RMNET_IOCTL_EGRESS_FORMAT_AGGREGATION (1<<2) #define RMNET_IOCTL_EGRESS_FORMAT_MUXING (1<<3) #define RMNET_IOCTL_EGRESS_FORMAT_CHECKSUM (1<<4) - +#define RMNET_IOCTL_EGRESS_FORMAT_IP_ROUTE (1<<5) /* Input values for the RMNET_IOCTL_SET_INGRESS_DATA_FORMAT IOCTL */ #define RMNET_IOCTL_INGRESS_FORMAT_MAP (1<<1) #define RMNET_IOCTL_INGRESS_FORMAT_DEAGGREGATION (1<<2) #define RMNET_IOCTL_INGRESS_FORMAT_DEMUXING (1<<3) #define RMNET_IOCTL_INGRESS_FORMAT_CHECKSUM (1<<4) #define RMNET_IOCTL_INGRESS_FORMAT_AGG_DATA (1<<5) +#define RMNET_IOCTL_INGRESS_FORMAT_IP_ROUTE (1<<6) /* Input values for the RMNET_IOCTL_SET_OFFLOAD */ #define RMNET_IOCTL_OFFLOAD_FORMAT_NONE (0) @@ -124,6 +132,9 @@ #define IFNAMSIZ 16 #endif +/* size of the mac address */ +#define MAC_ADDR_SIZE 6 + /** * enum rmnet_egress_ep_type - To specify pipe type for egress * @RMNET_EGRESS_DEFAULT: WAN Producer pipe @@ -132,10 +143,11 @@ * Add any number of pipes before max */ enum rmnet_egress_ep_type { - RMNET_EGRESS_DEFAULT = 0x0000, + RMNET_EGRESS_DEFAULT = 0x0000, RMNET_EGRESS_LOW_LAT_CTRL = 0x0001, RMNET_EGRESS_LOW_LAT_DATA = 0x0002, - RMNET_EGRESS_MAX = 0x0003, + RMNET_EGRESS_ETH_DATA = 0x0003, + RMNET_EGRESS_MAX = 0x0004, }; @@ -300,7 +312,7 @@ struct rmnet_ioctl_extended_s { /* Input values for the RMNET_IOCTL_ADD_MUX_CHANNEL IOCTL */ struct { __u32 mux_id; - __s8 vchannel_name[IFNAMSIZ]; + __s8 vchannel_name[IFNAMSIZ]; } rmnet_mux_val; /* Input values for the RMNET_IOCTL_FLOW_CONTROL IOCTL */ @@ -309,7 +321,7 @@ struct rmnet_ioctl_extended_s { __u8 mux_id; } flow_control_prop; - /* Return values for RMNET_IOCTL_GET_EP_PAIR */ + /* Return values for RMNET_IOCTL_GET_EP_PAIR/LL/ETH */ struct { __u32 consumer_pipe_num; __u32 producer_pipe_num; @@ -334,6 +346,13 @@ struct rmnet_ioctl_extended_s { __u16 mtu_v4; __u16 mtu_v6; } mtu_params; + + /* Input values for the RMNET_IOCTL_ADD_MUX_CHANNEL_v2 IOCTL */ + struct { + __u32 mux_id; + __s8 vchannel_name[IFNAMSIZ]; + __u8 mac[MAC_ADDR_SIZE]; + } rmnet_mux_val_v2; } u; }; diff --git a/kernel/sched/walt/core_ctl.c b/kernel/sched/walt/core_ctl.c index 44b0fef98e4c..b3e4e5548ace 100644 --- a/kernel/sched/walt/core_ctl.c +++ b/kernel/sched/walt/core_ctl.c @@ -340,7 +340,7 @@ static ssize_t store_not_preferred(struct cluster_data *state, const char *buf, size_t count) { struct cpu_data *c; - unsigned int i; + unsigned int i, mask; unsigned int val[MAX_CPUS_PER_CLUSTER]; unsigned long flags; int ret; @@ -353,10 +353,16 @@ static ssize_t store_not_preferred(struct cluster_data *state, return -EINVAL; spin_lock_irqsave(&state_lock, flags); - for (i = 0; i < state->num_cpus; i++) { - c = &per_cpu(cpu_state, i + state->first_cpu); + for (i = 0, mask = 0; i < state->num_cpus;) { + if (!cpumask_test_cpu(i + mask + state->first_cpu, cpu_possible_mask)) { + mask++; + continue; + } + + c = &per_cpu(cpu_state, i + mask + state->first_cpu); c->not_preferred = val[i]; not_preferred_count += !!val[i]; + i++; } state->nr_not_preferred_cpus = not_preferred_count; spin_unlock_irqrestore(&state_lock, flags); @@ -369,20 +375,26 @@ static ssize_t show_not_preferred(const struct cluster_data *state, char *buf) struct cpu_data *c; ssize_t count = 0; unsigned long flags; - int i; + int i, mask; spin_lock_irqsave(&state_lock, flags); - for (i = 0; i < state->num_cpus; i++) { - c = &per_cpu(cpu_state, i + state->first_cpu); + for (i = 0, mask = 0; i < state->num_cpus;) { + if (!cpumask_test_cpu(i + mask + state->first_cpu, cpu_possible_mask)) { + mask++; + continue; + } + + c = &per_cpu(cpu_state, i + mask + state->first_cpu); count += scnprintf(buf + count, PAGE_SIZE - count, - "CPU#%d: %u\n", c->cpu, c->not_preferred); + "CPU#%d: %u\n", c->cpu, c->not_preferred); + i++; } + spin_unlock_irqrestore(&state_lock, flags); return count; } - struct core_ctl_attr { struct attribute attr; ssize_t (*show)(const struct cluster_data *, char *);