* [PATCH] wifi: mwifiex: validate HT/VHT element length before storing beacon IE pointers
From: Christopher Kleiner @ 2026-07-17 0:00 UTC (permalink / raw)
To: briannorris, linux-wireless; +Cc: francesco, netdev, linux-kernel
mwifiex_update_bss_desc_with_ie() stores raw pointers into the beacon
buffer for the HT Capability, HT Operation, VHT Capability and VHT
Operation elements without checking that the element is long enough to
hold the corresponding fixed-size structure. The generic IE loop only
guarantees that the declared element length fits inside the beacon
buffer (bytes_left >= total_ie_len); it does not guarantee that
element_len is large enough for the struct that later consumers copy.
beacon_buf is a tight kmemdup() of the over-the-air IEs. When the
association command is built, mwifiex_cmd_append_11n_tlv() /
mwifiex_cmd_append_11ac_tlv() copy a fixed number of bytes from the
stored pointers (sizeof(struct ieee80211_ht_cap) and friends). A
malicious AP that emits a beacon or probe response ending in a
truncated (e.g. zero-length) HT Capability element leaves bcn_ht_cap
pointing near the end of the slab, and the subsequent copy reads out of
bounds. The leaked bytes are placed into the association request
transmitted back to the AP, disclosing adjacent slab memory; on
CONFIG_KASAN / panic_on_oops kernels it is an out-of-bounds oops.
Commit 685c9b7750bf ("mwifiex: Abort at too short BSS descriptor
element") added such length checks for the FH/DS/CF/IBSS parameter sets
and a few other elements, but did not cover the HT/VHT capability and
operation elements. Validate element_len against the size of the
structure that will be consumed, mirroring those existing checks.
Fixes: 5e6e3a92b9a4 ("wireless: mwifiex: initial commit for Marvell mwifiex driver")
Cc: stable@vger.kernel.org
Signed-off-by: Christopher Kleiner <chris@kleiner.pro>
---
drivers/net/wireless/marvell/mwifiex/scan.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wireless/marvell/mwifiex/scan.c
index 97c0ec3b822e..0196c2adfeed 100644
--- a/drivers/net/wireless/marvell/mwifiex/scan.c
+++ b/drivers/net/wireless/marvell/mwifiex/scan.c
@@ -1384,6 +1384,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
bss_entry->beacon_buf);
break;
case WLAN_EID_HT_CAPABILITY:
+ if (element_len < sizeof(struct ieee80211_ht_cap))
+ return -EINVAL;
bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
(current_ptr +
sizeof(struct ieee_types_header));
@@ -1392,6 +1394,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
bss_entry->beacon_buf);
break;
case WLAN_EID_HT_OPERATION:
+ if (element_len < sizeof(struct ieee80211_ht_operation))
+ return -EINVAL;
bss_entry->bcn_ht_oper =
(struct ieee80211_ht_operation *)(current_ptr +
sizeof(struct ieee_types_header));
@@ -1400,6 +1404,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
bss_entry->beacon_buf);
break;
case WLAN_EID_VHT_CAPABILITY:
+ if (element_len < sizeof(struct ieee80211_vht_cap))
+ return -EINVAL;
bss_entry->disable_11ac = false;
bss_entry->bcn_vht_cap =
(void *)(current_ptr +
@@ -1409,6 +1415,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
bss_entry->beacon_buf);
break;
case WLAN_EID_VHT_OPERATION:
+ if (element_len < sizeof(struct ieee80211_vht_operation))
+ return -EINVAL;
bss_entry->bcn_vht_oper =
(void *)(current_ptr +
sizeof(struct ieee_types_header));
--
2.43.0
^ permalink raw reply related
* [PATCH v2 2/2] wifi: rtw89: pci: enable 36-bit DMA on spacemit K3
From: Anirudh Srinivasan @ 2026-07-16 23:05 UTC (permalink / raw)
To: Bjorn Helgaas, Yixun Lan, Ping-Ke Shih, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Inochi Amaoto, Aurelien Jarno
Cc: linux-pci, linux-kernel, linux-riscv, spacemit, linux-wireless,
Anirudh Srinivasan
In-Reply-To: <20260716-rtw89-spacemit-k3-v2-0-392b577ebf75@oss.tenstorrent.com>
The Spacemit K3 Pico ITX Board has a RTL8852BE pcie card behind a PCIe
root port, but the SoC doesn't have any 32 bit DMA addreseses which the
rtw89 seems to use by default. Enable 36 bit DMA ability that the driver
has when this particular root port is detected so that the driver can
probe on this SoC.
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Acked-by: Ping-Ke Shih <pkshih@realtek.com>
Signed-off-by: Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>
---
drivers/net/wireless/realtek/rtw89/pci.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 102bae4881805..c5b82fc46d063 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -3326,6 +3326,10 @@ static bool rtw89_pci_is_dac_compatible_bridge(struct rtw89_dev *rtwdev)
if (bridge->device == 0x2806)
return true;
break;
+ case PCI_VENDOR_ID_SPACEMIT:
+ if (bridge->device == PCI_DEVICE_ID_SPACEMIT_K3)
+ return true;
+ break;
}
return false;
--
2.43.0
^ permalink raw reply related
* [PATCH v2 1/2] PCI: Move Spacemit vendor and device IDs to linux/pci_ids.h
From: Anirudh Srinivasan @ 2026-07-16 23:05 UTC (permalink / raw)
To: Bjorn Helgaas, Yixun Lan, Ping-Ke Shih, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Inochi Amaoto, Aurelien Jarno
Cc: linux-pci, linux-kernel, linux-riscv, spacemit, linux-wireless,
Anirudh Srinivasan
In-Reply-To: <20260716-rtw89-spacemit-k3-v2-0-392b577ebf75@oss.tenstorrent.com>
Move the vendor and device ID for the existing Spacemit K1 PCIe Root
Complex to include/linux/pci_ids.h. Also add K3's Root Complex device ID
to this header. This is done so that these values can be referenced in
the rtw89 driver to enable 36-bit DMA ability in it for WiFi to function
on the K3 Pico ITX board.
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>
---
drivers/pci/controller/dwc/pcie-spacemit-k1.c | 3 ---
include/linux/pci_ids.h | 4 ++++
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
index be20a520255b6..f89c6d46c7684 100644
--- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
+++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
@@ -21,9 +21,6 @@
#include "pcie-designware.h"
-#define PCI_VENDOR_ID_SPACEMIT 0x201f
-#define PCI_DEVICE_ID_SPACEMIT_K1 0x0001
-
/* Offsets and field definitions for link management registers */
#define K1_PHY_AHB_IRQ_EN 0x0000
#define PCIE_INTERRUPT_EN BIT(0)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index 1c9d40e09107d..d6f26cacc8e35 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2640,6 +2640,10 @@
#define PCI_VENDOR_ID_SUNIX 0x1fd4
#define PCI_DEVICE_ID_SUNIX_1999 0x1999
+#define PCI_VENDOR_ID_SPACEMIT 0x201f
+#define PCI_DEVICE_ID_SPACEMIT_K1 0x0001
+#define PCI_DEVICE_ID_SPACEMIT_K3 0x0002
+
#define PCI_VENDOR_ID_HINT 0x3388
#define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013
--
2.43.0
^ permalink raw reply related
* [PATCH v2 0/2] Enable WiFi on Spacemit K3 Pico ITX
From: Anirudh Srinivasan @ 2026-07-16 23:05 UTC (permalink / raw)
To: Bjorn Helgaas, Yixun Lan, Ping-Ke Shih, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Inochi Amaoto, Aurelien Jarno
Cc: linux-pci, linux-kernel, linux-riscv, spacemit, linux-wireless,
Anirudh Srinivasan
The Spacemit K3 Pico ITX has a RTL8852BE Wifi card attached via PCIe.
The probe for the rtw89 driver currently fails because driver tries to
allocate a kernel page with GFP_DMA32, and this board has memory only
above the 32 bit range. The rtw89 driver has the ability to use 36 bit
DMA addresses, but this is only enabled for certain PCIe bridge/rootport
that have been validated to work on. Enable this ability for the PCIe
root port. A similar patch seems to exist in the vendor kernel tree.
To test this, you'll need the 3 patch series adding the K3 PCIe RC
Driver[1], K3 PCIe Phy[2] and K3 PCIe DTS[3].
I've dropped the dependency on [1] from v1 and added the PCI IDs to
pci_ids.h here directly. Inochi's PCIe RC series will now use the PCI
IDs added by this series.
One question I had was about whether the IOMMU on the K3 could be used
to do DMA mappings and allow the wifi card to work with a 32 bit virtual
address. The K3's IOMMU isn't supported currently in the kernel DT. It
seems to not be enabled in the vendor kernel too. Even if the IOMMU was
enabled, I'm not sure if it would help with this exact problem. The fix
proposed in this patch works to solve this problem, so I've sent it to
the list.
[1] https://lore.kernel.org/spacemit/20260709040027.958400-1-inochiama@gmail.com/
[2] https://lore.kernel.org/spacemit/20260703021024.495433-1-inochiama@gmail.com/
[3] https://lore.kernel.org/spacemit/20260709040415.977784-1-inochiama@gmail.com/
Signed-off-by: Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>
---
Changes in v2:
- Updated Patch 1's commit with reason for where the PCI IDs will be used
- Dropped the hard dependency on Inochi's PCIe RC series and add the PCI ids in this patch directly
- Added Acked by from Bjorn and Ping-Ke, Tested by from Aurelien
- Link to v1: https://patch.msgid.link/20260715-rtw89-spacemit-k3-v1-0-e577bc63706b@oss.tenstorrent.com
---
Anirudh Srinivasan (2):
PCI: Move Spacemit vendor and device IDs to linux/pci_ids.h
wifi: rtw89: pci: enable 36-bit DMA on spacemit K3
drivers/net/wireless/realtek/rtw89/pci.c | 4 ++++
drivers/pci/controller/dwc/pcie-spacemit-k1.c | 3 ---
include/linux/pci_ids.h | 4 ++++
3 files changed, 8 insertions(+), 3 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260715-rtw89-spacemit-k3-a37c9771b3c3
Best regards,
--
Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>
^ permalink raw reply
* ath12k: WCN785x firmware resets regulatory domain on resume causing ~7s reconnect delay
From: Stian Knudsen @ 2026-07-16 22:35 UTC (permalink / raw)
To: ath12k; +Cc: linux-wireless, linux-kernel
After resume from suspend, the WCN785x firmware resets its regulatory state to
WORLD and takes approximately 7 seconds to re-discover the country code from AP
beacons. This causes a consistent ~16 second total delay before wifi reconnects
after resume.
This is an improvement request rather than a crash bug: the driver currently
contains no WMI code for saving or restoring regulatory state across
suspend/resume, and I would like to ask whether this is feasible.
Hardware:
Lenovo ThinkPad T14 Gen 5 (BIOS: R2LET40W 1.21)
Wifi: Qualcomm WCN785x Wi-Fi 7 FastConnect 7800 [17cb:1107]
Subsystem: Lenovo [17aa:e0e6]
Kernel: 7.1.3-arch2-1 (Arch Linux, close to vanilla)
Firmware: WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3
Kernel taint: 0 (untainted)
Observed behavior:
On every resume from suspend, the following sequence is observed in dmesg and wpa_supplicant logs:
kernel: ath12k_wifi7_pci 0000:02:00.0: chip_id 0x2 chip_family 0x4 board_id 0xff soc_id 0x40170200
kernel: ath12k_wifi7_pci 0000:02:00.0: fw_version 0x1103006c fw_build_timestamp 2026-03-06 09:10 ...
wpa_supplicant: wlp2s0: CTRL-EVENT-REGDOM-CHANGE init=DRIVER type=WORLD
[ ~7 seconds pass ]
wpa_supplicant: wlp2s0: CTRL-EVENT-REGDOM-CHANGE init=DRIVER type=COUNTRY alpha2=DE
[ ~9 seconds pass ]
NetworkManager: policy: auto-activating connection 'SSID'
NetworkManager: device (wlp2s0): Activation: successful, device activated.
Total delay from resume to connected: ~16 seconds, 100% reproducible on every
resume.
The device advertises itself as self-managed (phy#0 (self-managed) in iw reg
get). All standard userspace methods of setting the regulatory domain are
ignored by the firmware -- iw reg set, wireless-regdb, cfg80211
ieee80211_regdom modprobe option -- and i found this blog which documents this:
https://www.julienturbide.com/blog/wifi-7-linux-ath12k-wcn785x-regulatory-domain
Grepping the ath12k driver source (7.1.3) reveals no WMI code for saving or
restoring regulatory state across suspend/resume:
$ grep -r "regdom|regulatory|country.*suspend|suspend.*country" drivers/net/wireless/ath/ath12k/
(no output)
The firmware resets to WORLD on every resume and must re-discover the country
code from AP beacons, taking ~7 seconds.
Is there a WMI command available in the WCN785x firmware to cache and restore
the last known country code on resume, avoiding the need to re-discover it from AP beacons? If so, would it be feasible to add this to the driver's suspend/resume path to reduce the post-resume reconnect delay?
Full dmesg output and wpa_supplicant logs are available on request.
^ permalink raw reply
* Re: [PATCH 2/2] wifi: rtw89: pci: enable 36-bit DMA on spacemit K3
From: Anirudh Srinivasan @ 2026-07-16 22:27 UTC (permalink / raw)
To: Inochi Amaoto
Cc: Ping-Ke Shih, Bjorn Helgaas, Yixun Lan, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-riscv@lists.infradead.org, spacemit@lists.linux.dev,
linux-wireless@vger.kernel.org
In-Reply-To: <allZOmTRIvot39Gj@inochi.infowork>
Hi Inochi,
On Thu, Jul 16, 2026 at 5:24 PM Inochi Amaoto <inochiama@gmail.com> wrote:
>
> On Thu, Jul 16, 2026 at 09:22:17AM +0000, Ping-Ke Shih wrote:
> > Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com> wrote:
> > > The Spacemit K3 Pico ITX Board has a RTL8852BE pcie card behind a PCIe
> > > root port, but the SoC doesn't have any 32 DMA addreseses which the
> > > rtw89 seems to use by default. Enable 36 bit DMA ability that the driver
> > > has when this particular root port is detected so that the driver can
> > > probe on this SoC.
> > >
> > > Signed-off-by: Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>
> >
> > This patch looks good to me:
> >
> > Acked-by: Ping-Ke Shih <pkshih@realtek.com>
> >
> > But I wonder how this patchset goes via which tree. I'm happy to merge
> > them into rtw tree and then wireless-next tree if people can ack
> > patch 1/2.
> >
> >
>
> These IDs are from my patchset.
> https://lore.kernel.org/spacemit/20260709040027.958400-1-inochiama@gmail.com/
>
> I think Anirudh can move this ID and add them to the pci_ids.h
> directly, And I can adjust my patch to depend on this. It still
> needs some improvement to be merged.
Sounds good, I'll drop the dependency on your series and just have my
series add these IDs to linux.pci_ids.h. I'll send out a V2 tonight.
>
> Regards,
> Inochi
>
>
^ permalink raw reply
* Re: [PATCH 2/2] wifi: rtw89: pci: enable 36-bit DMA on spacemit K3
From: Inochi Amaoto @ 2026-07-16 22:23 UTC (permalink / raw)
To: Ping-Ke Shih, Anirudh Srinivasan
Cc: Bjorn Helgaas, Yixun Lan, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Inochi Amaoto, linux-pci@vger.kernel.org,
linux-kernel@vger.kernel.org, linux-riscv@lists.infradead.org,
spacemit@lists.linux.dev, linux-wireless@vger.kernel.org
In-Reply-To: <e7a43955e41c4dbdb864e89edc3d9fe6@realtek.com>
On Thu, Jul 16, 2026 at 09:22:17AM +0000, Ping-Ke Shih wrote:
> Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com> wrote:
> > The Spacemit K3 Pico ITX Board has a RTL8852BE pcie card behind a PCIe
> > root port, but the SoC doesn't have any 32 DMA addreseses which the
> > rtw89 seems to use by default. Enable 36 bit DMA ability that the driver
> > has when this particular root port is detected so that the driver can
> > probe on this SoC.
> >
> > Signed-off-by: Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>
>
> This patch looks good to me:
>
> Acked-by: Ping-Ke Shih <pkshih@realtek.com>
>
> But I wonder how this patchset goes via which tree. I'm happy to merge
> them into rtw tree and then wireless-next tree if people can ack
> patch 1/2.
>
>
These IDs are from my patchset.
https://lore.kernel.org/spacemit/20260709040027.958400-1-inochiama@gmail.com/
I think Anirudh can move this ID and add them to the pci_ids.h
directly, And I can adjust my patch to depend on this. It still
needs some improvement to be merged.
Regards,
Inochi
^ permalink raw reply
* Re: [PATCH v2 0/3] MIPS: BCM47XX: convert buttons to software nodes
From: Waldemar Brodkorb @ 2026-07-16 22:16 UTC (permalink / raw)
To: Dmitry Torokhov
Cc: Arnd Bergmann, Rafał Miłecki, Michael Büsch,
Hauke Mehrtens, Thomas Bogendoerfer, Waldemar Brodkorb,
Bartosz Golaszewski, linux-wireless, linux-kernel, linux-mips,
Bartosz Golaszewski
In-Reply-To: <alci_45CzdVznaN2@google.com>
Hi Dmitry, all,
Dmitry Torokhov wrote,
> Hi Waldemar,
>
> On Wed, Jul 15, 2026 at 12:49:47AM +0200, Waldemar Brodkorb wrote:
> > Hi,
> > Arnd Bergmann wrote,
> >
> > > On Mon, Jul 13, 2026, at 23:58, Dmitry Torokhov wrote:
> > > > This series converts the legacy gpio-keys platform device on BCM47XX
> > > > boards to use software nodes and static properties.
> > > >
> > > > To do this properly without relying on legacy name-based matching
> > > > (which is being removed from gpiolib), we introduce and register
> > > > software nodes for the underlying GPIO controllers (BCMA and SSB)
> > > > and reference them in the button properties.
> > > >
> > > > The first two patches add the software nodes to bcma-gpio and
> > > > ssb-gpio respectively. The third patch performs the conversion
> > > > for the BCM47XX buttons.
> > > >
> > > > Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> > > > ---
> > > > As Johannes mentioned on v1 this best should go through MIPS tree.
> > >
> > > Adding Waldemar to Cc. He has recently done some work to
> > > get this platform working again in FreeWRT and should
> > > be able to test your patches on hardware.
> >
> > I normally use LTS kernel on the hardware (Linksys WRT54GS v1.0).
> > But for testing I updated to 7.1.3. Attached is the dmesg without
> > Dmitry's patches. Button works, I can go into failsafe mode after
> > pressing the reset button on bootup.
> >
> > With Dmitry's three patches applied I directly getting into failsafe
> > mode without pressing any button. Dmesg looks similar, but I get
> > following kernel message:
> > platform gpio-keys.0: deferred probe pending: gpio-keys: failed to get gpio
> >
> > Looking at /dev I see no /dev/input/event0 device node anymore.
> >
> > Attached is the small failsafe script I use on bootup.
> > Hope this helps.
> >
> > Do I need to change my failsafe script for the new stuff or is
> > something else broken now? Do I miss some new kernel config option?
> > Or is the patch only for latest Linus git repo.
>
> Thank you very much for testing. I think 7.1 should work. Could you
> please apply the test patch below and send me new dmesg? Hopefully I'll
> be able to figure out where I messed up.
We found the reason it was not working for me with 7.1.3.
The commit fe221742e388 is needed for 7.1.3. With that applied the
reset button works as usual.
So you can add:
Tested-by: Waldemar Brodkorb <wbx@openadk.org>
best regards
Waldemar
^ permalink raw reply
* Re: [PATCH] wifi: ar5523: fix integer underflow in ar5523_data_rx_cb()
From: Jeff Johnson @ 2026-07-16 22:15 UTC (permalink / raw)
To: pip-izony, Ingo Molnar, Thomas Gleixner, Johannes Berg,
Roopni Devanathan
Cc: Kyungtae Kim, Pontus Fuchs, John W . Linville, linux-wireless,
linux-kernel
In-Reply-To: <20251103195519.3152385-2-eeodqql09@gmail.com>
On 11/3/2025 11:55 AM, pip-izony wrote:
> From: Seungjin Bae <eeodqql09@gmail.com>
>
> In ar5523_data_rx_cb(), the `rxlen` variable is derived from desc->len,
> which is provided by the USB device.
>
> The function checks for an upper bound (rxlen > ar->rxbufsz) and for a
> zero value (!rxlen), but it fails to check for a proper lower bound
> against the size of the descriptor.
>
> If a malicious device provides an `rxlen` value that is positive
> but smaller than sizeof(struct ar5523_rx_desc), the subtraction in
> the call to skb_put() will result in an integer underflow.
>
> This passes a very large unsigned value to skb_put(), which then
> triggers a kernel panic upon detecting the potential buffer overflow.
>
> Fix this by adding a check to ensure `rxlen` is at least
> sizeof(struct ar5523_rx_desc) before performing the substraction.
>
> Fixes: b7d572e1871df ("ar5523: Add new driver")
> Signed-off-by: Seungjin Bae <eeodqql09@gmail.com>
> ---
> drivers/net/wireless/ath/ar5523/ar5523.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/drivers/net/wireless/ath/ar5523/ar5523.c b/drivers/net/wireless/ath/ar5523/ar5523.c
> index 1230e6278f23..dfaccf241560 100644
> --- a/drivers/net/wireless/ath/ar5523/ar5523.c
> +++ b/drivers/net/wireless/ath/ar5523/ar5523.c
> @@ -589,6 +589,12 @@ static void ar5523_data_rx_cb(struct urb *urb)
> goto skip;
> }
>
> + if (rxlen < sizeof(struct ar5523_rx_desc)) {
> + ar5523_dbg(ar, "RX: Bad descriptor (len=%d is too small)\n",
> + rxlen);
> + goto skip;
> + }
> +
> skb_reserve(data->skb, sizeof(*chunk));
> skb_put(data->skb, rxlen - sizeof(struct ar5523_rx_desc));
>
Since this is an orphaned driver, this patch has been sitting in my patchwork
queue for a very long time. Today I decided to take a look.
The patch does address the issue mentioned, but really doesn't completely
address the crux of the issue. I believe there should be a fixed correlation
between the rxlen and the usblen. I posed the following question to my review
agent:
given that the usblen should account for the ar5523_chunk header, the payload,
and the ar5523_rx_desc, shouldn't the rxlen always be the same as the usblen -
sizeof(ar5523_chunk)?
And my agent agreed:
Yes, that's exactly right. Looking at the struct comment "msg length including
header" for desc->len and the frame layout:
[ar5523_chunk (4B)] [802.11 payload] [ar5523_rx_desc]
←──────────────────── usblen ──────────────────────→
The invariant should be:
rxlen == usblen - sizeof(ar5523_chunk)
Because rxlen covers [802.11 payload] + [ar5523_rx_desc], and usblen covers
everything including the chunk header.
The code never cross-validates them. It independently bounds-checks usblen
(via AR5523_MIN_RXBUFSZ) and rxlen (upper bound vs rxbufsz, lower bound added
by the patch), but if a malicious device provides rxlen > usblen -
sizeof(ar5523_chunk), then:
skb_put(data->skb, rxlen - sizeof(struct ar5523_rx_desc));
...would expose bytes beyond the actual 802.11 payload — potentially biting
into the ar5523_rx_desc trailer bytes, or uninitialized skb tail space up to
rxbufsz, and pass that garbage to ieee80211_rx_irqsafe().
The existing upper bound check rxlen > ar->rxbufsz prevents a skb_put
overflow (since the skb is allocated with rxbufsz), but it's far too loose.
The right check would be:
if (rxlen != usblen - sizeof(struct ar5523_chunk))
goto skip;
Or at minimum a strict upper bound:
if (rxlen > usblen - sizeof(struct ar5523_chunk))
goto skip;
So the patch fixes the underflow but misses this inconsistency between rxlen
and usblen that could allow overreading valid-but-wrong data within the skb
buffer.
So please consider this analysis and propose a v2
/jeff
^ permalink raw reply
* Re: [PATCH 2/2] wifi: rtw89: pci: enable 36-bit DMA on spacemit K3
From: Aurelien Jarno @ 2026-07-16 21:34 UTC (permalink / raw)
To: Anirudh Srinivasan
Cc: Bjorn Helgaas, Yixun Lan, Ping-Ke Shih, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Inochi Amaoto, linux-pci, linux-kernel, linux-riscv, spacemit,
linux-wireless
In-Reply-To: <20260715-rtw89-spacemit-k3-v1-2-e577bc63706b@oss.tenstorrent.com>
On 2026-07-15 22:21, Anirudh Srinivasan wrote:
> The Spacemit K3 Pico ITX Board has a RTL8852BE pcie card behind a PCIe
> root port, but the SoC doesn't have any 32 DMA addreseses which the
> rtw89 seems to use by default. Enable 36 bit DMA ability that the driver
> has when this particular root port is detected so that the driver can
> probe on this SoC.
>
> Signed-off-by: Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>
> ---
> drivers/net/wireless/realtek/rtw89/pci.c | 4 ++++
> 1 file changed, 4 insertions(+)
Tested-by: Aurelien Jarno <aurelien@aurel32.net>
Note that you probably want the following patch to get the controller to
connect to a WiFi network:
https://lore.kernel.org/spacemit/20260716213314.3027969-5-aurelien@aurel32.net
--
Aurelien Jarno GPG: 4096R/1DDD8C9B
aurelien@aurel32.net http://aurel32.net
^ permalink raw reply
* [PATCH ath-next] wifi: ath11k: Avoid buffer overread in ath11k_wmi_tlv_op_rx()
From: Jeff Johnson @ 2026-07-16 20:01 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath11k, linux-kernel, Jeff Johnson
Currently, in ath11k_wmi_tlv_op_rx(), the firmware buffer is read
without first verifying that the buffer has enough data to hold a
header. This could result in a buffer overread.
Add an upfront length check before dereferencing skb->data as a
wmi_cmd_hdr. The check is placed before the trace_ath11k_wmi_event()
call to preserve the existing trace semantics (tracing the full raw
WMI event including the header), unlike the analogous ath12k fix which
could use skb_pull_data() directly.
Compile tested only.
Fixes: d5c65159f289 ("ath11k: driver for Qualcomm IEEE 802.11ax devices")
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath11k/wmi.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index dca6e011cc40..b10f0054c81e 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -8895,13 +8895,15 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb)
struct wmi_cmd_hdr *cmd_hdr;
enum wmi_tlv_event_id id;
+ if (skb->len < sizeof(*cmd_hdr))
+ goto out;
+
cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
id = FIELD_GET(WMI_CMD_HDR_CMD_ID, (cmd_hdr->cmd_id));
trace_ath11k_wmi_event(ab, id, skb->data, skb->len);
- if (skb_pull(skb, sizeof(struct wmi_cmd_hdr)) == NULL)
- goto out;
+ skb_pull(skb, sizeof(*cmd_hdr));
switch (id) {
/* Process all the WMI events here */
---
base-commit: 0ceb105245b5e57f803bdc0e79dc077fc06ff384
change-id: 20260715-ath11k_wmi_tlv_op_rx-overread-e104a0a56c10
^ permalink raw reply related
* [PATCH ath-next] wifi: ath12k: Avoid buffer overread in ath12k_wmi_op_rx()
From: Jeff Johnson @ 2026-07-16 20:01 UTC (permalink / raw)
To: Jeff Johnson; +Cc: linux-wireless, ath12k, linux-kernel, Jeff Johnson
Currently, in ath12k_wmi_op_rx(), the firmware buffer is read without
first verifying that the buffer has enough data to hold a header. This
could result in a buffer overread.
Update the logic to verify the buffer contains at least enough data to
hold a wmi_cmd_hdr before reading from the buffer.
Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c7-00108-QCAHMTSWPL_V1.0_V2.0_SILICONZ_UPSTREAM-3
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Assisted-by: Claude:claude-sonnet-4-6
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
---
drivers/net/wireless/ath/ath12k/wmi.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index ad739bffcf88..28b4dd397271 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -10280,12 +10280,12 @@ static void ath12k_wmi_op_rx(struct ath12k_base *ab, struct sk_buff *skb)
struct wmi_cmd_hdr *cmd_hdr;
enum wmi_tlv_event_id id;
- cmd_hdr = (struct wmi_cmd_hdr *)skb->data;
- id = le32_get_bits(cmd_hdr->cmd_id, WMI_CMD_HDR_CMD_ID);
-
- if (!skb_pull(skb, sizeof(struct wmi_cmd_hdr)))
+ cmd_hdr = skb_pull_data(skb, sizeof(*cmd_hdr));
+ if (!cmd_hdr)
goto out;
+ id = le32_get_bits(cmd_hdr->cmd_id, WMI_CMD_HDR_CMD_ID);
+
switch (id) {
/* Process all the WMI events here */
case WMI_SERVICE_READY_EVENTID:
---
base-commit: 0ceb105245b5e57f803bdc0e79dc077fc06ff384
change-id: 20260714-ath12k_wmi_op_rx-overread-c1347f1a7310
^ permalink raw reply related
* Re: [PATCH v8 1/9] dt-bindings: mmc: Document fixed-layout NVMEM provider support
From: Rob Herring (Arm) @ 2026-07-16 19:42 UTC (permalink / raw)
To: Loic Poulain
Cc: Andrew Lunn, Bjorn Andersson, linux-wireless, Johannes Berg,
daniel, linux-block, linux-mmc, Paolo Abeni, Eric Dumazet,
Conor Dooley, netdev, Balakrishna Godavarthi, Simon Horman,
Srinivas Kandagatla, Luiz Augusto von Dentz, Marcel Holtmann,
Bartosz Golaszewski, Russell King, Jens Axboe, Konrad Dybcio,
Jeff Johnson, David S. Miller, Saravana Kannan, linux-bluetooth,
Rocky Liao, Christian Marangi, Ulf Hansson, Krzysztof Kozlowski,
Heiner Kallweit, devicetree, linux-arm-msm, linux-kernel, ath10k,
Jakub Kicinski
In-Reply-To: <20260703-block-as-nvmem-v8-1-98ae32bfc49a@oss.qualcomm.com>
On Fri, 03 Jul 2026 15:45:14 +0200, Loic Poulain wrote:
> Allow an eMMC hardware partition node to describe an NVMEM layout so the
> partition can be exposed as an NVMEM provider. This lets a partition
> (e.g. an eMMC boot partition) store device-specific information such as a
> WiFi MAC address or a Bluetooth BD address and reference it through NVMEM
> cells.
>
> Accept "fixed-layout" as the partition node compatible, in addition to
> "fixed-partitions", so the layout can be described directly on the
> partition node.
>
> Signed-off-by: Loic Poulain <loic.poulain@oss.qualcomm.com>
> ---
> .../devicetree/bindings/mmc/mmc-card.yaml | 23 +++++++++++++++++++++-
> 1 file changed, 22 insertions(+), 1 deletion(-)
>
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply
* Re: [RFC PATCH net-next v0 2/6] net: fix GeoNetworking
From: Andrew Lunn @ 2026-07-16 19:28 UTC (permalink / raw)
To: Simon Dietz
Cc: simon.dietz, andrew+netdev, davem, edumazet, johannes, kuniyu,
linux-wireless, netdev
In-Reply-To: <20260716153917.3399255-1-dietz23838@hs-ansbach.de>
> drop:
> - pr_info("Packet was dropped.");
> + //pr_info("Packet was dropped.");
> kfree_skb(skb);
Don't comment it out, remove it.
And maybe think about incriminating a counter.
> @@ -1003,21 +1031,41 @@ static int gn_rcv(struct sk_buff *skb, struct net_device *dev,
>
> switch (gh->gc_h.ht) {
> case CH_HT_GUC:
> + if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_guc_header) + sizeof(struct btp_header)))
> + goto drop;
The netdev coding style asks for lines to be < 80 characters long.
We also have quite a lot of #defines for lengths of various
headers. So maybe add some _HLEN macros.
Andrew
^ permalink raw reply
* Re: [RFC PATCH net-next v0 1/6] net: add GeoNetworking protocol
From: Andrew Lunn @ 2026-07-16 19:17 UTC (permalink / raw)
To: Simon Dietz
Cc: netdev, edumazet, davem, kuniyu, andrew+netdev, dietz23838,
linux-wireless, johannes
In-Reply-To: <20260716135902.2895237-2-simon.dietz@plantwatch.de>
On Thu, Jul 16, 2026 at 03:58:41PM +0200, Simon Dietz wrote:
> Implement the GeoNetworking / ETSI ITS-G5 ('net/gn') protocol which
> is based on 802.11p wifi and used for vehicle2x applications. It is
> standardized by the ETSI and used by some car manufacturers
> (especially in europe). It enables ad-hoc, multi-hop geographical
> communication and routing among vehicles (and road- or railside
> infrastructure).
I'm probably doing a deep dive too early, but ...
> +#ifdef CONFIG_PROC_FS
> +extern int gn_proc_init(void);
> +extern void gn_proc_exit(void);
> +#else
> +static inline int gn_proc_init(void)
> +{
> + return 0;
> +}
> +static inline void gn_proc_exit(void)
> +{
> +}
> +#endif /* CONFIG_PROC_FS */
Nothing new has been added to /proc for a long time. Please consider a
different interface. I've not yet looked to see what is there, but
networking now pretty much only uses netlink.
> +/* protocol-specific ioctls */
> +#define SIOCGNSPOSITION (SIOCPROTOPRIVATE + 0)
New IOCTL code is also very likely to be rejected. The functionality
should go through netlink.
> +static inline void __gn_insert_socket(struct sock *sk)
> +{
> + sk_add_node(sk, &gn_sockets);
> +}
> +
> +static inline void gn_remove_socket(struct sock *sk)
> +{
> + write_lock_bh(&gn_sockets_lock);
> + sk_del_node_init(sk);
> + write_unlock_bh(&gn_sockets_lock);
> +}
Generally, inline functions in a .c file are rejected. It is better to
let the compiler decide. The exception would be if you have a
benchmark which shows inline actually helps.
> +static struct gn_iface *gn_if_add_device(struct net_device *dev,
> + struct sockaddr_gn *sa)
> +{
> + bool was_empty;
> + struct gn_iface *gnif,
> + *new_gnif = kzalloc(sizeof(struct gn_iface), GFP_KERNEL);
> +
> + if (!new_gnif)
> + return NULL;
> +
> + new_gnif->address = sa->sgn_addr;
> + new_gnif->dev = dev;
> +
> + pr_info("Add interface %s with address %llx", dev->name,
> + new_gnif->address);
This seems like debug. At minimum, it should be _dbg(), but maybe it
should be removed altogether.
> +u32 gn_tai_to_gn(ktime_t tai_time)
> +{
> + /* unix timestamp of 01/01/2004 00:00:00 UTC and 32 leap seconds between TAI and UNIX*/
> + const ktime_t tai_offset = ms_to_ktime(1072915200000LLU + 32000LLU);
> +
> + WARN_ONCE(ktime_before(tai_time, tai_offset),
> + "timestamp %lld out of bounds", tai_time);
> + /* truncate timestamp (GN timestamp has 32 bits) */
> + return (u32)ktime_sub(tai_time, tai_offset);
I'm too lazy to do the work. When does this wrap around? Maybe add it
as a comment.
> +static int gn_autobind(struct sock *sock)
> +{
> + //BUG();
Commented out code is not something we want in the kernel.
Maybe one of your later patches fixes this. We might want to consider
squashing them, so the review is done on the final clean code.
> +static void gn_location_service_req(struct gn_iface *gnif, gn_address_t saddr,
> + gn_address_t daddr)
> +{
> + int size = 0;
> + struct sk_buff *skb;
> + struct gn_basic_header *gb_h;
> + struct gn_common_header *gc_h;
> + struct gn_ls_request_header *gls_h;
netdev uses reverse christmas tree, longest lines first, shortest
last. It should apply to all functions.
> +// table is * 1000 | p1 * 100 entry
> +static int cos_table[] = {
> + 100000, 99995, 99980, 99955, 99920, 99875, 99820, 99755, 99680,
> + 99595, 99500, 99396, 99281, 99156, 99022, 98877, 98723, 98558,
> + 98384, 98200, 98007, 97803, 97590, 97367, 97134, 96891, 96639,
> + 96377, 96106, 95824, 95534, 95233, 94924, 94604, 94275, 93937,
> + 93590, 93233, 92866, 92491, 92106, 91712, 91309, 90897, 90475,
> + 90045, 89605, 89157, 88699, 88233, 87758, 87274, 86782, 86281,
> + 85771, 85252, 84726, 84190, 83646, 83094, 82534, 81965, 81388,
> + 80803, 80210, 79608, 78999, 78382, 77757, 77125, 76484, 75836,
> + 75181, 74517, 73847, 73169, 72484, 71791, 71091, 70385, 69671,
> + 68950, 68222, 67488, 66746, 65998, 65244, 64483, 63715, 62941,
> + 62161, 61375, 60582, 59783, 58979, 58168, 57352, 56530, 55702,
> + 54869, 54030, 53186, 52337, 51482, 50622, 49757, 48887, 48012,
> + 47133, 46249, 45360, 44466, 43568, 42666, 41759, 40849, 39934,
> + 39015, 38092, 37166, 36236, 35302, 34365, 33424, 32480, 31532,
> + 30582, 29628, 28672, 27712, 26750, 25785, 24818, 23848, 22875,
> + 21901, 20924, 19945, 18964, 17981, 16997, 16010, 15023, 14033,
> + 13042, 12050, 11057, 10063, 9067, 8071, 7074, 6076, 5077,
> + 4079, 3079, 2079, 1080, 0, -920, -1920, -2920, -3919,
> + -4918, -5917, -6915, -7912, -8909, -9904, -10899, -11892, -12884,
> + -13875, -14865, -15853, -16840, -17825, -18808, -19789, -20768, -21745,
> + -22720, -23693, -24663, -25631, -26596, -27559, -28519, -29476, -30430,
> + -31381, -32329, -33274, -34215, -35153, -36087, -37018, -37945, -38868,
> + -39788, -40703, -41615, -42522, -43425, -44323, -45218, -46107, -46992,
> + -47873, -48748, -49619, -50485, -51345, -52201, -53051, -53896, -54736,
> + -55570, -56399, -57221, -58039, -58850, -59656, -60455, -61249, -62036,
> + -62817, -63592, -64361, -65123, -65879, -66628, -67370, -68106, -68834,
> + -69556, -70271, -70979, -71680, -72374, -73060, -73739, -74411, -75075,
> + -75732, -76382, -77023, -77657, -78283, -78901, -79512, -80114, -80709,
> + -81295, -81873, -82444, -83005, -83559, -84104, -84641, -85169, -85689,
> + -86200, -86703, -87197, -87682, -88158, -88626, -89085, -89534, -89975,
> + -90407, -90830, -91244, -91648, -92044, -92430, -92807, -93175, -93533,
> + -93883, -94222, -94553, -94873, -95185, -95486, -95779, -96061, -96334,
> + -96598, -96852, -97096, -97330, -97555, -97770, -97975, -98170, -98356,
> + -98531, -98697, -98853, -98999, -99135, -99262, -99378, -99484, -99581,
> + -99667, -99744, -99810, -99867, -99914, -99950, -99977, -99993, -100000
> +};
> +
> +/* icos() - look up in cos_table for a rad value.
> + * @rad : the rad value.* 10^7
> + *
> + * Return : the cosine value * 100000
> + */
> +static int icos(__s64 rad)
> +{
> + if (rad > PI)
> + rad = PI - (rad - PI);
> + return cos_table[rad / 100000];
> +}
> +
> +/* degree_to_rad() - convert a degree value to a rad value.
> +* @a : the degree value as 1/10 micro degree (10^7).
> +*
> +* Return : the rad value * 10^7.
> +*/
> +static __s64 degree_to_rad(__s64 a)
> +{
> + return (((RAD_PER_DEGREE * a) / 10000000ULL)) % (PI * 2ULL);
> +}
Not the sort of thing you normally see in the kernel. I've not looked
at the code enough to see the big picture, but generally, the kernel
routing table is static, and fed from a user space daemon. Should all
this code be in user space?
> +static void debug_loc_te(void)
> +{
> + struct loc_te *entry;
> + int bucket;
> +
> + spin_lock_bh(&gn_loc_t_lock);
> + if (hash_empty(gn_loc_t)) {
> + spin_unlock_bh(&gn_loc_t_lock);
> + return;
> + }
> +
> + pr_info("Printing location table");
> + hash_for_each(gn_loc_t, bucket, entry, hnode) {
> + pr_info("LOC_TE(%p) tst=%x addr=%llx ll_addr=%llx is_neighbour=%x ls_pending=%x",
> + entry, entry->tst_addr, be64_to_cpu(entry->addr),
> + be64_to_cpu(entry->ll_address), entry->is_neighbour,
> + entry->ls_pending);
> + }
> + spin_unlock_bh(&gn_loc_t_lock);
debugfs? a netlink dump operation?
Andrew
^ permalink raw reply
* Re: [PATCH] wifi: mwifiex: fix freeze for 60 seconds caused by request_firmware
From: George Valkov @ 2026-07-16 18:01 UTC (permalink / raw)
To: Francesco Dolcini
Cc: johannes.berg, Dan Carpenter, briannorris, s.kerkmann, kees,
linux-wireless, linux-kernel, stable
In-Reply-To: <20260716085942.GA99146@francesco-nb>
Thank you! Note taken and I will try to do better when
I submit my last planned patch for this driver, soon.
I wanted to collect opinions from OpenWrt members first.
Georgi
On Thu, 16 Jul 2026 at 12:00, Francesco Dolcini <francesco@dolcini.it> wrote:
>
> On Thu, Jul 16, 2026 at 11:26:54AM +0300, George Valkov wrote:
> > Please backport to 6.18 and 6.12, which are used by OpenWrt.
> > Initially I did not know that I could insert
> > free text between the commit message and the patch.
> > I apologise for that. I am still learning how to use git send-mail.
>
> Please see Documentation/process/stable-kernel-rules.rst
> It should explain everything you need on this regard.
>
> Francesco
>
^ permalink raw reply
* Re: [PATCH v2] wifi: ath12k: Constify struct ath12k_dp_arch_ops
From: Rameshkumar Sundaram @ 2026-07-16 17:22 UTC (permalink / raw)
To: Christophe JAILLET, Jeff Johnson
Cc: linux-kernel, kernel-janitors, linux-wireless, ath12k
In-Reply-To: <969d732e2c6f169e1aa5e89c7e01743a1adb55df.1784010931.git.christophe.jaillet@wanadoo.fr>
On 7/14/2026 2:09 PM, Christophe JAILLET wrote:
> 'struct ath12k_dp_arch_ops' is not modified in this driver.
>
> Constifying this structure moves some data to a read-only section, so
> increases overall security, especially when the structure holds some
> function pointers.
>
> On a x86_64, with allmodconfig, as an example:
> Before:
> ======
> text data bss dec hex filename
> 6318 3384 0 9702 25e6 drivers/net/wireless/ath/ath12k/wifi7/dp.o
>
> After:
> =====
> text data bss dec hex filename
> 6478 3224 0 9702 25e6 drivers/net/wireless/ath/ath12k/wifi7/dp.o
>
> Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v2] wifi: ath12k: fix scan command endianness on big endian
From: Rameshkumar Sundaram @ 2026-07-16 17:12 UTC (permalink / raw)
To: Alexander Wilhelm, Jeff Johnson, Baochen Qiang
Cc: linux-wireless, ath12k, linux-kernel
In-Reply-To: <20260703-fix-channel-list-copy-v2-1-372c39306d79@westermo.com>
On 7/3/2026 1:05 PM, Alexander Wilhelm wrote:
> ath12k_wmi_scan_req_arg stores scan parameters in CPU-native byte order,
> while ath12k_wmi_send_scan_start_cmd() writes them into a WMI command
> buffer whose contents must be in little-endian format. The existing code
> copies the channel list and writes s_ssid and hint_bssid related values to
> the command buffer without endian conversion. As a result, scan requests
> contain invalid parameters on big-endian systems and fail.
>
> Convert the channel list as well as the s_ssid and hint_bssid related
> values to little-endian before writing them to the WMI command buffer. This
> preserves the existing behaviour on little-endian systems while fixing scan
> requests on big-endian architectures.
>
> Signed-off-by: Alexander Wilhelm <alexander.wilhelm@westermo.com>
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH 1/2] PCI: Move Spacemit vendor and device ID to linux/pci_Ids.h
From: Bjorn Helgaas @ 2026-07-16 16:43 UTC (permalink / raw)
To: Anirudh Srinivasan
Cc: Bjorn Helgaas, Yixun Lan, Ping-Ke Shih, Lorenzo Pieralisi,
Krzysztof Wilczyński, Manivannan Sadhasivam, Rob Herring,
Inochi Amaoto, linux-pci, linux-kernel, linux-riscv, spacemit,
linux-wireless
In-Reply-To: <20260715-rtw89-spacemit-k3-v1-1-e577bc63706b@oss.tenstorrent.com>
On Wed, Jul 15, 2026 at 10:21:54PM -0500, Anirudh Srinivasan wrote:
> Move the vendor and device IDs for Spacemit PCIe Root Complexes to
> include/linux/pci_ids.h so that they can be referenced elsewhere.
>
> Signed-off-by: Anirudh Srinivasan <asrinivasan@oss.tenstorrent.com>
Acked-by: Bjorn Helgaas <bhelgaas@google.com>
To help motivate this patch, it would be nice to say specifically
where PCI_VENDOR_ID_SPACEMIT will be used.
In subject line, s/pci_Ids.h/pci_ids.h/
> ---
> drivers/pci/controller/dwc/pcie-spacemit-k1.c | 4 ----
> include/linux/pci_ids.h | 4 ++++
> 2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/pci/controller/dwc/pcie-spacemit-k1.c b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> index 680acc93f5395..7b0bc1802954a 100644
> --- a/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> +++ b/drivers/pci/controller/dwc/pcie-spacemit-k1.c
> @@ -21,10 +21,6 @@
>
> #include "pcie-designware.h"
>
> -#define PCI_VENDOR_ID_SPACEMIT 0x201f
> -#define PCI_DEVICE_ID_SPACEMIT_K1 0x0001
> -#define PCI_DEVICE_ID_SPACEMIT_K3 0x0002
> -
> /* Offsets and field definitions for link management registers */
> #define K1_PHY_AHB_IRQ_EN 0x0000
> #define PCIE_INTERRUPT_EN BIT(0)
> diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
> index 1c9d40e09107d..d6f26cacc8e35 100644
> --- a/include/linux/pci_ids.h
> +++ b/include/linux/pci_ids.h
> @@ -2640,6 +2640,10 @@
> #define PCI_VENDOR_ID_SUNIX 0x1fd4
> #define PCI_DEVICE_ID_SUNIX_1999 0x1999
>
> +#define PCI_VENDOR_ID_SPACEMIT 0x201f
> +#define PCI_DEVICE_ID_SPACEMIT_K1 0x0001
> +#define PCI_DEVICE_ID_SPACEMIT_K3 0x0002
> +
> #define PCI_VENDOR_ID_HINT 0x3388
> #define PCI_DEVICE_ID_HINT_VXPROII_IDE 0x8013
>
>
> --
> 2.43.0
>
^ permalink raw reply
* Re: [RFC PATCH net-next v0 6/6] net: apply RCS to GeoNetworking
From: Simon Dietz @ 2026-07-16 16:39 UTC (permalink / raw)
To: simon.dietz
Cc: andrew+netdev, davem, dietz23838, edumazet, johannes, kuniyu,
linux-wireless, netdev
In-Reply-To: <20260716162152.3616762-1-dietz23838@hs-ansbach.de>
I am sorry for the now misformatted patch series tree and for the
partial transmission of this patch series. It turned out that because
I used git send-email --dry-run before actually sending the patch
series, which drained the email send limit per hour of my mail/hosting
provider. I now use(d) my university email address, which enforces a
(much higher) daily email send limit, instead and it worked. I hope
not to have caused too much inconvenience.
Simon
^ permalink raw reply
* [PATCH] wifi: mt76: mt7921: fix memory leak when skb_linearize fails in mcu rx event
From: Prashant Rahul @ 2026-07-16 16:25 UTC (permalink / raw)
To: Felix Fietkau, Lorenzo Bianconi, Ryder Lee, Shayne Chen,
Sean Wang, Matthias Brugger, AngeloGioacchino Del Regno
Cc: Shuah Khan, linux-wireless, linux-kernel, linux-arm-kernel,
linux-mediatek, Prashant Rahul
The ownership of sk_buff skb is passed to mt7921_queue_rx_skb, each
path inside it under the switch case handles cleaning of skb and it
is true for mt7921_mcu_rx_event as well.
mt7921_mcu_rx_event, on a success path, either queues skb via
mt76_mcu_rx_event or cleans it immediately inside
mt7921_mcu_uni_rx_unsolicited_event.
However inside mt7921_mcu_rx_event, if skb_linearize fails, the function
returns immediately and never bothers cleaning skb which leaks skb.
Since skb is fully owned at this point, it is safe to call
dev_kfree_skb which fixes the leak.
Granted, the skb_linearize failure is rare as it can only fail under
heavy memory usage, but at the same time, leaking memory under heavy
memory usage can worsen the OOM condition.
Signed-off-by: Prashant Rahul <prashantrahul23@gmail.com>
---
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index 25b9437250f7b..fb18d3b4e27ba 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -351,8 +351,10 @@ void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct mt76_connac2_mcu_rxd *rxd;
- if (skb_linearize(skb))
+ if (skb_linearize(skb)) {
+ dev_kfree_skb(skb);
return;
+ }
rxd = (struct mt76_connac2_mcu_rxd *)skb->data;
---
base-commit: b8809969e1d7a591e0f49dd464a5d04b3cf02ab1
change-id: 20260716-mt7921-mem-leak-a38cbc1d8132
Best regards,
--
Prashant Rahul <prashantrahul23@gmail.com>
^ permalink raw reply related
* [RFC PATCH net-next v0 6/6] net: apply RCS to GeoNetworking
From: Simon Dietz @ 2026-07-16 16:21 UTC (permalink / raw)
To: simon.dietz
Cc: andrew+netdev, davem, dietz23838, edumazet, johannes, kuniyu,
linux-wireless, netdev
In-Reply-To: <20260716161605.3587079-1-dietz23838@hs-ansbach.de>
From: Simon Dietz <simon.dietz@plantwatch.de>
Signed-off-by: Simon Dietz <simon.dietz@plantwatch.de>
---
net/gn/gn_proc.c | 2 +-
net/gn/gn_prot.c | 123 +++++++++++++++++++++++---------------------
net/gn/gn_routing.c | 24 ++++-----
3 files changed, 76 insertions(+), 73 deletions(-)
diff --git a/net/gn/gn_proc.c b/net/gn/gn_proc.c
index ecd2aea446e5..bc1280079695 100644
--- a/net/gn/gn_proc.c
+++ b/net/gn/gn_proc.c
@@ -38,8 +38,8 @@ static void gn_seq_socket_stop(struct seq_file *seq, void *v)
static int gn_seq_socket_show(struct seq_file *seq, void *v)
{
- struct sock *s;
struct gn_sock *gn;
+ struct sock *s;
if (v == SEQ_START_TOKEN) {
seq_puts(seq, "Type Local_addr Remote_addr Tx_queue Rx_queue St UID\n");
diff --git a/net/gn/gn_prot.c b/net/gn/gn_prot.c
index 1599dc0aa185..c8a6d4a78771 100644
--- a/net/gn/gn_prot.c
+++ b/net/gn/gn_prot.c
@@ -99,8 +99,9 @@ static void gn_activate_beacon(void);
static struct gn_iface *gn_if_add_device(struct net_device *dev,
struct sockaddr_gn *sa)
{
+ struct gn_iface *new_gnif = kzalloc_obj(*new_gnif, GFP_KERNEL);
+ struct gn_iface *gnif;
bool was_empty;
- struct gn_iface *gnif, *new_gnif = kzalloc_obj(*new_gnif, GFP_KERNEL);
if (!new_gnif)
return NULL;
@@ -138,8 +139,8 @@ static struct gn_iface *gn_if_add_device(struct net_device *dev,
static void gn_if_drop_device(struct net_device *dev)
{
- struct gn_iface *gnif;
struct hlist_node *tmp;
+ struct gn_iface *gnif;
spin_lock_bh(&gn_interfaces_lock);
hlist_for_each_entry_safe(gnif, tmp, &gn_interfaces, hnode) {
@@ -154,8 +155,8 @@ static void gn_if_drop_device(struct net_device *dev)
static void gn_interfaces_clear(void)
{
- struct gn_iface *gnif;
struct hlist_node *tmp;
+ struct gn_iface *gnif;
spin_lock_bh(&gn_interfaces_lock);
hlist_for_each_entry_safe(gnif, tmp, &gn_interfaces, hnode) {
@@ -341,8 +342,8 @@ try_next_port:;
static struct sock *gn_find_or_insert_socket(struct sock *sk,
struct sockaddr_gn *sgn)
{
- struct sock *s;
struct gn_sock *gn;
+ struct sock *s;
write_lock_bh(&gn_sockets_lock);
sk_for_each(s, &gn_sockets) {
@@ -373,9 +374,11 @@ static int gn_bind(struct socket *sock, struct sockaddr_unsized *uaddr,
{
DECLARE_SOCKADDR(struct sockaddr_gn *, addr, uaddr);
struct sock *sk = sock->sk;
- struct gn_sock *gn = gn_sk(sk);
+ struct gn_sock *gn;
int err;
+ gn = gn_sk(sk);
+
if (!sock_flag(sk, SOCK_ZAPPED) ||
addr_len != sizeof(struct sockaddr_gn))
return -EINVAL;
@@ -413,10 +416,12 @@ static int gn_connect(struct socket *sock, struct sockaddr_unsized *uaddr,
int addr_len, int flags)
{
struct sock *sk = sock->sk;
- struct gn_sock *gn = gn_sk(sk);
struct sockaddr_gn *addr;
+ struct gn_sock *gn;
int err;
+ gn = gn_sk(sk);
+
sk->sk_state = TCP_CLOSE;
sock->state = SS_UNCONNECTED;
@@ -450,8 +455,8 @@ static int gn_connect(struct socket *sock, struct sockaddr_unsized *uaddr,
static struct sock *gn_search_socket(struct sockaddr_gn *tosgn,
struct gn_iface *gnif)
{
- struct sock *s;
struct gn_sock *gn;
+ struct sock *s;
read_lock_bh(&gn_sockets_lock);
sk_for_each(s, &gn_sockets) {
@@ -537,11 +542,11 @@ static void gn_fill_bh_ch_nopayload(struct gn_iface *gnif,
static void gn_location_service_req(struct gn_iface *gnif, gn_address_t saddr,
gn_address_t daddr)
{
- int size = 0;
- struct sk_buff *skb;
- struct gn_basic_header *gb_h;
- struct gn_common_header *gc_h;
struct gn_ls_request_header *gls_h;
+ struct gn_common_header *gc_h;
+ struct gn_basic_header *gb_h;
+ struct sk_buff *skb;
+ int size = 0;
size += gn_dl->header_length;
size += gnif->dev->hard_header_len;
@@ -577,11 +582,11 @@ static void gn_location_service_reply(struct gn_spv *depv,
struct gn_iface *gnif, gn_address_t addr,
u64 llc)
{
- int size;
- struct sk_buff *skb;
- struct gn_basic_header *gb_h;
- struct gn_common_header *gc_h;
struct gn_ls_reply_header *gls_h;
+ struct gn_common_header *gc_h;
+ struct gn_basic_header *gb_h;
+ struct sk_buff *skb;
+ int size;
size = 0;
size += gn_dl->header_length;
@@ -616,8 +621,8 @@ static void gn_location_service_reply(struct gn_spv *depv,
static int gn_pass_payload_sock(struct sockaddr_gn *tosgn, struct sk_buff *skb)
{
- struct sock *sock;
int rc = NET_RX_DROP;
+ struct sock *sock;
sock = gn_search_socket(tosgn, NULL);
if (!sock)
@@ -631,9 +636,9 @@ static int gn_pass_payload_sock(struct sockaddr_gn *tosgn, struct sk_buff *skb)
static int gn_forward_guc_packet(struct sk_buff *skb, gn_address_t dest_addr)
{
struct sk_buff *forward_skb;
+ u8 next_hop_mac[ETH_ALEN];
struct gn_header *fwd_gh;
struct gn_iface *gnif;
- u8 next_hop_mac[ETH_ALEN];
fwd_gh = (struct gn_header *)skb_network_header(skb);
if (fwd_gh->gb_h.rhl <= 0)
@@ -684,10 +689,10 @@ static int gn_forward_tsb_packet(struct sk_buff *skb)
static int gn_process_guc_packet(struct sk_buff *skb)
{
- struct gn_header *gh;
struct btp_header *btp_h;
struct sockaddr_gn tosgn;
struct gn_iface *gnif;
+ struct gn_header *gh;
gh = (struct gn_header *)skb_network_header(skb);
GN_SET_BTP(skb, btp_h, struct gn_guc_header);
@@ -764,14 +769,14 @@ static struct gn_geo_scope gn_decode_geo_scope(struct gn_header *gh)
static int gn_process_gxc_packet(struct sk_buff *skb)
{
- struct gn_header *gh;
+ unsigned long long next_hop_addr;
+ struct gn_geo_scope scope;
struct btp_header *btp_h;
struct sockaddr_gn tosgn;
struct gn_iface *gnif;
- s64 f_value;
- struct gn_geo_scope scope;
+ struct gn_header *gh;
bool run_dpd;
- unsigned long long next_hop_addr;
+ s64 f_value;
next_hop_addr = GN_BROADCAST_ADDR;
@@ -821,8 +826,8 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
// Forwarding
if (gh->gb_h.rhl > 0 && ((gh->gc_h.ht == CH_HT_GAC && f_value >= 0) ||
gh->gc_h.ht == CH_HT_GBC)) {
- struct sk_buff *forward_skb;
struct gn_basic_header *fwd_gb_h;
+ struct sk_buff *forward_skb;
u8 dest_addr[ETH_ALEN];
int rc;
@@ -873,9 +878,9 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
static int gn_process_shb_packet(struct sk_buff *skb, const u8 *ll_address)
{
- struct gn_header *gh;
struct btp_header *btp_h;
struct sockaddr_gn tosgn;
+ struct gn_header *gh;
gh = (struct gn_header *)skb_network_header(skb);
GN_SET_BTP(skb, btp_h, struct gn_shb_header);
@@ -905,9 +910,9 @@ static int gn_process_shb_packet(struct sk_buff *skb, const u8 *ll_address)
static int gn_process_tsb_packet(struct sk_buff *skb)
{
- struct gn_header *gh;
struct btp_header *btp_h;
struct sockaddr_gn tosgn;
+ struct gn_header *gh;
gh = (struct gn_header *)skb_network_header(skb);
GN_SET_BTP(skb, btp_h, struct gn_tsb_header);
@@ -955,9 +960,9 @@ static int gn_process_beacon_packet(struct sk_buff *skb, const u8 *llc)
static int gn_process_ls_packet(struct sk_buff *skb)
{
- struct gn_header *gh;
gn_address_t dest_addr;
struct gn_iface *gnif;
+ struct gn_header *gh;
gh = (struct gn_header *)skb_network_header(skb);
@@ -1221,28 +1226,27 @@ static int gn_fill_tsb_header(struct gn_tsb_header *tsb_h,
*/
static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
{
- int packet_type, packet_subtype, btp_type;
- int err = -EINVAL;
- struct sock *sk = sock->sk;
- struct gn_sock *gn = gn_sk(sk);
-
- /*
- * usgn will contain address and port of the destination
- */
DECLARE_SOCKADDR(struct sockaddr_gn *, usgn, msg->msg_name);
- int flags = msg->msg_flags;
- struct sockaddr_gn local_sgn;
- struct sk_buff *skb;
- struct net_device *dev;
- struct btp_header *btp_h;
- void *gp_h;
+ int packet_type, packet_subtype, btp_type;
struct gn_common_header *gc_h;
struct gn_basic_header *gb_h;
+ struct sockaddr_gn local_sgn;
+ struct gn_spv depv = { 0 };
+ u8 rhl = DEFAULT_HOP_LIMIT;
+ int flags = msg->msg_flags;
+ struct btp_header *btp_h;
+ struct net_device *dev;
struct gn_iface *gnif;
- u32 size;
+ struct sk_buff *skb;
+ struct gn_sock *gn;
+ int err = -EINVAL;
+ struct sock *sk;
u32 eh_size;
- u8 rhl = DEFAULT_HOP_LIMIT;
- struct gn_spv depv = { 0 };
+ void *gp_h;
+ u32 size;
+
+ sk = sock->sk;
+ gn = gn_sk(sk);
if (flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) {
pr_warn("unsupported sendmsg flags");
@@ -1514,13 +1518,12 @@ static int gn_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
int flags)
{
struct sock *sk = sock->sk;
+ struct gn_header *gh;
struct sk_buff *skb;
- int err = 0;
u16 copied = 0;
+ int err = 0;
u32 offset;
- struct gn_header *gh;
-
/* It is necessary to find the actual length of the payload, which,
* in case of an unsecured package, resides in the commonheader and
* still has to be calculated without the length of the btp-header
@@ -1562,11 +1565,11 @@ static int gn_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
static int gn_send_beacon(struct gn_iface *gnif)
{
/* Note: Media dependent procedures (e.g. ITS-G5 DCC / DCC Access) evaluated here */
- unsigned int size;
- struct gn_basic_header *gb_h;
- struct gn_common_header *gc_h;
struct gn_beacon_header *gbe_h;
+ struct gn_common_header *gc_h;
+ struct gn_basic_header *gb_h;
struct sk_buff *skb;
+ unsigned int size;
size = gn_dl->header_length;
size += gnif->dev->hard_header_len;
@@ -1660,11 +1663,12 @@ static int validate_scope(struct gn_scope *scope)
static int gn_setsockopt(struct socket *sock, int level, int optname,
sockptr_t optval, unsigned int optlen)
{
- struct gn_scope opt;
struct sock *sk = sock->sk;
- struct gn_sock *gn = gn_sk(sk);
-
int rc = -ENOPROTOOPT;
+ struct gn_scope opt;
+ struct gn_sock *gn;
+
+ gn = gn_sk(sk);
if (level != SOL_GN || optname != GN_SCOPE)
goto out;
@@ -1693,9 +1697,11 @@ static int gn_setsockopt(struct socket *sock, int level, int optname,
static int gn_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
- struct sock *sk = sock->sk;
- struct gn_sock *gn = gn_sk(sk);
int len, rc = -ENOPROTOOPT;
+ struct sock *sk = sock->sk;
+ struct gn_sock *gn;
+
+ gn = gn_sk(sk);
if (level != SOL_GN || optname != GN_SCOPE)
goto out;
@@ -1737,12 +1743,11 @@ static int gn_validate_pos(struct gn_position *pos)
*/
static int gn_if_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
{
+ struct gn_iface *gnif = NULL;
struct sockaddr_gn *sa;
struct net_device *dev;
- struct ifreq gnreq;
struct gn_position pos;
-
- struct gn_iface *gnif = NULL;
+ struct ifreq gnreq;
if (copy_from_user(&gnreq, argp, sizeof(gnreq)))
return -EFAULT;
@@ -1824,9 +1829,9 @@ static int gn_if_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
static int gn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
{
- int rc = -ENOIOCTLCMD;
- struct sock *sk = sock->sk;
void __user *argp = (void __user *)arg;
+ struct sock *sk = sock->sk;
+ int rc = -ENOIOCTLCMD;
switch (cmd) {
/* Protocol layer */
diff --git a/net/gn/gn_routing.c b/net/gn/gn_routing.c
index 3672a345530f..c438c6ab6666 100644
--- a/net/gn/gn_routing.c
+++ b/net/gn/gn_routing.c
@@ -189,9 +189,9 @@ static inline u64 dist(struct gn_coord c)
*/
__s64 gn_F(struct gn_coord self, struct gn_geo_scope scope)
{
+ struct gn_coord coord_diff = gn_coord_diff(self, scope.coord);
s32 a2, b2, x2, y2;
s64 result = -1;
- struct gn_coord coord_diff = gn_coord_diff(self, scope.coord);
/* Note: Scope angle rotation for non-circular geographical areas */
a2 = scope.a * scope.a;
b2 = scope.b * scope.b;
@@ -223,12 +223,11 @@ __s64 gn_F(struct gn_coord self, struct gn_geo_scope scope)
static int greedy_forward(struct gn_iface *gnif, u8 *addr, struct gn_lpv *depv)
{
+ struct gn_coord dest_coord = pv_to_coord(depv);
+ u64 min_dist, curr_dist, ego_dist;
+ u8 *found_addr = NULL;
struct loc_te *curr;
int bkt, rc;
- u8 *found_addr = NULL;
-
- u64 min_dist, curr_dist, ego_dist;
- struct gn_coord dest_coord = pv_to_coord(depv);
ego_dist = dist(gn_coord_diff(dest_coord, gnif->pos.coord));
min_dist = ego_dist;
@@ -279,8 +278,8 @@ int gn_gxc_forward(struct gn_iface *gnif, s64 f, u8 *addr, struct gn_lpv *depv)
static void debug_loc_te(void)
{
- struct loc_te *entry;
struct hlist_node *tmp;
+ struct loc_te *entry;
int bucket;
spin_lock_bh(&gn_loc_t_lock);
@@ -301,11 +300,10 @@ static void debug_loc_te(void)
static void gn_prune(void)
{
+ struct hlist_node *tmp;
struct loc_te *entry;
int bucket;
- struct hlist_node *tmp;
-
spin_lock_bh(&gn_loc_t_lock);
hash_for_each_safe(gn_loc_t, bucket, tmp, entry, hnode) {
if (!GN_TST_VALID(entry->tst_addr)) {
@@ -406,8 +404,8 @@ int gn_update_location_table(struct gn_lpv *pv, bool make_neighbour,
static void __ls_queue(struct sk_buff_head *q, struct sk_buff *skb)
{
- struct sk_buff *curr;
u32 qlen = skb_queue_len(q);
+ struct sk_buff *curr;
while (qlen-- > GN_LSB_SIZE) {
curr = skb_dequeue(q);
@@ -479,9 +477,9 @@ int gn_ls_queue(gn_address_t dest_addr, struct sk_buff *skb)
void gn_ls_flush(gn_address_t dest_addr)
{
- struct loc_te *entry;
struct sk_buff *tmp_skb;
u8 ll_address[ETH_ALEN];
+ struct loc_te *entry;
bool has_mac = false;
spin_lock_bh(&gn_loc_t_lock);
@@ -557,9 +555,9 @@ int gn_query_ll_address(gn_address_t query_addr, u8 *ll_address)
*/
int gn_query_ll_nexthop(struct gn_iface *gnif, gn_address_t query_addr, u8 *ll_address)
{
- struct loc_te *entry;
- struct gn_lpv target_pv;
bool is_neighbor = false;
+ struct gn_lpv target_pv;
+ struct loc_te *entry;
bool found = false;
spin_lock_bh(&gn_loc_t_lock);
@@ -620,9 +618,9 @@ int gn_fill_depv(struct gn_spv *depv, gn_address_t dest_addr)
void gn_routing_exit(void)
{
+ struct hlist_node *tmp;
struct loc_te *entry;
int bucket;
- struct hlist_node *tmp;
spin_lock_bh(&gn_loc_t_lock);
hash_for_each_safe(gn_loc_t, bucket, tmp, entry, hnode) {
--
2.55.0
^ permalink raw reply related
* [RFC PATCH net-next v0 5/6] net: add ppc64 support for GeoNetworking
From: Simon Dietz @ 2026-07-16 16:16 UTC (permalink / raw)
To: simon.dietz
Cc: andrew+netdev, davem, dietz23838, edumazet, johannes, kuniyu,
linux-wireless, netdev
In-Reply-To: <20260716161213.3567275-1-dietz23838@hs-ansbach.de>
From: Simon Dietz <simon.dietz@plantwatch.de>
make GeoNetworking (cross-)compile under ppc64 (big endian)
Signed-off-by: Simon Dietz <simon.dietz@plantwatch.de>
---
include/linux/gn.h | 8 ++++----
net/gn/gn_prot.c | 11 +++++------
net/gn/gn_routing.c | 4 ++--
3 files changed, 11 insertions(+), 12 deletions(-)
diff --git a/include/linux/gn.h b/include/linux/gn.h
index 862f635d5d11..94239897ad40 100644
--- a/include/linux/gn.h
+++ b/include/linux/gn.h
@@ -188,10 +188,10 @@ struct gn_spv {
*The packet is dropped when rhl reaches 0
*/
struct gn_basic_header {
-#ifdef __LITTLE_ENDIAN_BITFIELD
+#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 nh : 4;
__u8 version : 4;
-#elif __BIG_ENDIAN_BITFIELD
+#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 version : 4;
__u8 nh : 4;
#else
@@ -203,12 +203,12 @@ struct gn_basic_header {
} __packed;
struct gn_common_header {
-#ifdef __LITTLE_ENDIAN_BITFIELD
+#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 reserved : 4;
__u8 nh : 4;
__u8 hst : 4;
__u8 ht : 4;
-#elif __BIG_ENDIAN_BITFIELD
+#elif defined(__BIG_ENDIAN_BITFIELD)
__u8 nh : 4;
__u8 reserved : 4;
__u8 ht : 4;
diff --git a/net/gn/gn_prot.c b/net/gn/gn_prot.c
index 90ecbd67b64d..1599dc0aa185 100644
--- a/net/gn/gn_prot.c
+++ b/net/gn/gn_prot.c
@@ -495,7 +495,7 @@ void gn_fill_sopv(struct gn_iface *gnif, struct gn_lpv *sopv, gn_address_t addr)
static void gn_fill_bh_ch(struct gn_iface *gnif, struct gn_header *gh,
u8 packet_type, u8 packet_subtype, u8 rhl,
- u8 next_header, u16 payload_size)
+ u8 next_header, __be16 payload_size)
{
const u8 mhl = DEFAULT_HOP_LIMIT;
/* rhl should never be greater than mhl */
@@ -1851,11 +1851,10 @@ static int gn_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
rc = put_user(amount, (int __user *)argp);
break;
}
- case SIOCGSTAMP:
- //rc = sock_get_timestamp(sk, argp);
- break;
- case SIOCGSTAMPNS:
- //rc = sock_get_timestampns(sk, argp);
+ case SIOCGSTAMP_OLD:
+ case SIOCGSTAMP_NEW:
+ case SIOCGSTAMPNS_OLD:
+ case SIOCGSTAMPNS_NEW:
break;
case SIOCGIFBRDADDR:
case SIOCDIFADDR:
diff --git a/net/gn/gn_routing.c b/net/gn/gn_routing.c
index 733ebd0d715a..3672a345530f 100644
--- a/net/gn/gn_routing.c
+++ b/net/gn/gn_routing.c
@@ -293,8 +293,8 @@ static void debug_loc_te(void)
hash_for_each_safe(gn_loc_t, bucket, tmp, entry, hnode) {
pr_debug("LOC_TE(%p) tst=%x addr=%llx ll_addr=%llx is_neighbour=%x ls_pending=%x\n",
entry, entry->tst_addr, be64_to_cpu(entry->addr),
- be64_to_cpu(entry->ll_address), entry->is_neighbour,
- entry->ls_pending);
+ ether_addr_to_u64(entry->ll_address),
+ entry->is_neighbour, entry->ls_pending);
}
spin_unlock_bh(&gn_loc_t_lock);
}
--
2.55.0
^ permalink raw reply related
* [RFC PATCH net-next v0 4/6] net: even further fix GeoNetworking
From: Simon Dietz @ 2026-07-16 16:12 UTC (permalink / raw)
To: simon.dietz
Cc: andrew+netdev, davem, dietz23838, edumazet, johannes, kuniyu,
linux-wireless, netdev
In-Reply-To: <20260716154909.3449985-1-dietz23838@hs-ansbach.de>
From: Simon Dietz <simon.dietz@plantwatch.de>
Include another set of fixes, including:
- gn_find_interface improvements
- move of timer setup to gn_init
- fix for missing packets
- kfree_skb fixes
- fixed return value in gn_sendmsg
- fixed error handling near register_snap_client
- uses hlist_for_each_entry_safe
- support for NETDEV_UNREGISTER
- timer improvements
Signed-off-by: Simon Dietz <simon.dietz@plantwatch.de>
---
include/linux/gn_routing.h | 1 +
net/gn/gn_prot.c | 67 +++++++++++++++++++++++++++-----------
net/gn/gn_routing.c | 4 +++
3 files changed, 53 insertions(+), 19 deletions(-)
diff --git a/include/linux/gn_routing.h b/include/linux/gn_routing.h
index 9384bbc4b288..64ccc80f5a90 100644
--- a/include/linux/gn_routing.h
+++ b/include/linux/gn_routing.h
@@ -55,6 +55,7 @@ struct loc_te {
s64 gn_F(struct gn_coord self, struct gn_geo_scope scope);
int gn_gxc_forward(struct gn_iface *gnif, s64 f, u8 *addr, struct gn_lpv *depv);
+struct gn_iface *gn_find_interface(gn_address_t addr);
struct gn_iface *gn_find_interface_by_dev(struct net_device *dev);
int gn_query_ll_address(gn_address_t addr, u8 *ll_address);
int gn_query_ll_nexthop(struct gn_iface *gnif, gn_address_t query_addr, u8 *ll_address);
diff --git a/net/gn/gn_prot.c b/net/gn/gn_prot.c
index 3c4e1157fbde..90ecbd67b64d 100644
--- a/net/gn/gn_prot.c
+++ b/net/gn/gn_prot.c
@@ -30,6 +30,7 @@
struct datalink_proto *gn_dl;
static const struct proto_ops gn_dgram_ops;
+static struct timer_list gn_beacon_timer;
/* Handlers for the socket list. */
@@ -114,6 +115,9 @@ static struct gn_iface *gn_if_add_device(struct net_device *dev,
hlist_for_each_entry_rcu(gnif, &gn_interfaces, hnode) {
if (gnif->dev == dev) {
// Replace existing interface address
+ atomic_set(&new_gnif->local_sn,
+ atomic_read(&gnif->local_sn));
+ memcpy(&new_gnif->pos, &gnif->pos, sizeof(gnif->pos));
hlist_replace_rcu(&gnif->hnode, &new_gnif->hnode);
spin_unlock_bh(&gn_interfaces_lock);
kfree_rcu(gnif, rcu);
@@ -135,12 +139,14 @@ static struct gn_iface *gn_if_add_device(struct net_device *dev,
static void gn_if_drop_device(struct net_device *dev)
{
struct gn_iface *gnif;
+ struct hlist_node *tmp;
spin_lock_bh(&gn_interfaces_lock);
- hlist_for_each_entry_rcu(gnif, &gn_interfaces, hnode) {
+ hlist_for_each_entry_safe(gnif, tmp, &gn_interfaces, hnode) {
if (gnif->dev == dev) {
hlist_del_rcu(&gnif->hnode);
kfree_rcu(gnif, rcu);
+ break;
}
}
spin_unlock_bh(&gn_interfaces_lock);
@@ -162,7 +168,7 @@ static void gn_interfaces_clear(void)
/*
* find the interface to which the socketaddress is bound
*/
-static struct gn_iface *gn_find_interface(gn_address_t addr)
+struct gn_iface *gn_find_interface(gn_address_t addr)
{
struct gn_iface *gnif;
bool found = false;
@@ -212,7 +218,7 @@ static int gn_device_event(struct notifier_block *this, unsigned long event,
if (dev->type != ARPHRD_ETHER)
return NOTIFY_DONE;
- if (event == NETDEV_DOWN)
+ if (event == NETDEV_DOWN || event == NETDEV_UNREGISTER)
gn_if_drop_device(dev);
return NOTIFY_DONE;
@@ -475,7 +481,7 @@ void gn_fill_sopv(struct gn_iface *gnif, struct gn_lpv *sopv, gn_address_t addr)
ktime_t tst = ktime_set(gnif->pos.tst.tv_sec, gnif->pos.tst.tv_nsec);
// fill empty timestamp with current timestamp
- if (tst == 0)
+ if (tst == 0 || ktime_before(tst, ms_to_ktime(1072915232000LLU)))
sopv->tst = cpu_to_be32(gn_timestamp_now());
else
sopv->tst = cpu_to_be32(gn_tai_to_gn(tst));
@@ -825,7 +831,7 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
pr_warn("dropping packet");
goto drop;
}
- fwd_gb_h = (struct gn_basic_header *)skb_transport_header(
+ fwd_gb_h = (struct gn_basic_header *)skb_network_header(
forward_skb);
fwd_gb_h->rhl--;
@@ -839,19 +845,24 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
break;
case GN_FORWARD_BUFFER:
pr_warn("forwarding buffers not implemented");
+ kfree_skb(forward_skb);
break;
case GN_FORWARD_DISCARD:
+ kfree_skb(forward_skb);
break;
default:
WARN_ONCE(1, "internal error: unexpected return value");
+ kfree_skb(forward_skb);
goto drop;
}
}
// Local delivery
- if (f_value >= 0 &&
- gn_pass_payload_sock(&tosgn, skb) != NET_RX_SUCCESS) {
- goto drop;
+ if (f_value >= 0) {
+ if (gn_pass_payload_sock(&tosgn, skb) != NET_RX_SUCCESS)
+ goto drop;
+ } else {
+ kfree_skb(skb);
}
return NET_RX_SUCCESS;
@@ -938,6 +949,7 @@ static int gn_process_beacon_packet(struct sk_buff *skb, const u8 *llc)
}
gn_ls_flush(gh->beacon_h.sopv.addr);
+ kfree_skb(skb);
return NET_RX_SUCCESS;
}
@@ -1029,6 +1041,11 @@ static int gn_rcv(struct sk_buff *skb, struct net_device *dev,
goto drop;
eth = (struct ethhdr *)skb_mac_header(skb);
+ // TODO: validate
+ if (skb->pkt_type == PACKET_LOOPBACK ||
+ ether_addr_equal(eth->h_source, dev->dev_addr))
+ goto drop;
+
skb_reset_network_header(skb);
if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE))
@@ -1274,7 +1291,8 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
dev = gnif->dev;
packet_subtype = CH_HST_UNSPECIFIED;
- if (0 /* is usgn unicast address? */) {
+ if (usgn->sgn_addr != 0 && usgn->sgn_addr != GNADDR_BROADCAST &&
+ gn->scope.scope_type == GN_SCOPE_UNSPECIFIED) {
packet_type = CH_HT_GUC;
} else {
switch (gn->scope.scope_type) {
@@ -1402,6 +1420,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
break;
default:
WARN_ONCE(1, "internal error");
+ kfree_skb(skb);
err = -EINVAL;
goto out;
}
@@ -1428,6 +1447,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
gn);
} else {
WARN_ONCE(1, "internal error");
+ kfree_skb(skb);
err = -EINVAL;
goto out;
}
@@ -1463,6 +1483,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
break;
case GN_QUEUE_ERROR:
default:
+ kfree_skb(skb);
err = -ENOMEM;
goto out;
}
@@ -1473,7 +1494,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
/* Destination position vector routing handled via location service queue */
- err = 0;
+ err = len;
out:
release_sock(sk);
return err;
@@ -1578,17 +1599,19 @@ static int gn_send_beacon(struct gn_iface *gnif)
static void gn_send_beacons(struct timer_list *tl)
{
struct gn_iface *gnif;
+ bool empty = true;
rcu_read_lock();
hlist_for_each_entry_rcu(gnif, &gn_interfaces, hnode) {
gn_send_beacon(gnif);
+ empty = false;
}
rcu_read_unlock();
- mod_timer(tl, jiffies + msecs_to_jiffies(GN_BEACON_RETRANSMIT_TIME));
+ if (!empty)
+ mod_timer(tl, jiffies + msecs_to_jiffies(GN_BEACON_RETRANSMIT_TIME));
}
-static DEFINE_TIMER(gn_beacon_timer, gn_send_beacons);
static void gn_activate_beacon(void)
{
@@ -1909,23 +1932,28 @@ static int __init gn_init(void)
{
int rc;
+ timer_setup(&gn_beacon_timer, gn_send_beacons, 0);
+
rc = proto_register(&gn_proto, 0);
if (rc)
- goto out;
+ return rc;
rc = sock_register(&gn_family_ops);
if (rc)
goto out_proto;
gn_dl = register_snap_client(gn_snap_id, gn_rcv);
- if (!gn_dl)
+ if (!gn_dl) {
pr_crit("Unable to register GeoNetworking with SNAP.\n");
+ rc = -ENOMEM;
+ goto out_snap;
+ }
dev_add_pack(&gn_packet_type);
rc = register_netdevice_notifier(&gn_notifier);
if (rc)
- goto out_sock;
+ goto out_dev;
rc = gn_proc_init();
if (rc)
@@ -1936,19 +1964,20 @@ static int __init gn_init(void)
goto out_proc;
#endif
-out:
- return rc;
+ return 0;
+
out_proc:
gn_proc_exit();
out_nd:
unregister_netdevice_notifier(&gn_notifier);
-out_sock:
+out_dev:
dev_remove_pack(&gn_packet_type);
unregister_snap_client(gn_dl);
+out_snap:
sock_unregister(PF_GN);
out_proto:
proto_unregister(&gn_proto);
- goto out;
+ return rc;
}
module_init(gn_init);
diff --git a/net/gn/gn_routing.c b/net/gn/gn_routing.c
index de1c77359e09..733ebd0d715a 100644
--- a/net/gn/gn_routing.c
+++ b/net/gn/gn_routing.c
@@ -333,6 +333,9 @@ int gn_update_location_table(struct gn_lpv *pv, bool make_neighbour,
struct loc_te *entry;
bool found = false;
+ if (gn_find_interface(pv->addr))
+ return -EINVAL;
+
spin_lock_bh(&gn_loc_t_lock);
hash_for_each_possible(gn_loc_t, entry, hnode, pv->addr) {
if (entry->addr != pv->addr)
@@ -443,6 +446,7 @@ int gn_ls_queue(gn_address_t dest_addr, struct sk_buff *skb)
} else if (entry->ls_pending == 1) {
// Entry is stale, but we already sent a LS request
rc = GN_QUEUE_LS_PENDING;
+ __ls_queue(&entry->lsb, skb);
} else {
// Entry is stale, perform LS request
rc = GN_QUEUE_LS_STALE;
--
2.55.0
^ permalink raw reply related
* [RFC PATCH net-next v0 3/6] net: further fix GeoNetworking
From: Simon Dietz @ 2026-07-16 15:49 UTC (permalink / raw)
To: simon.dietz
Cc: andrew+netdev, davem, dietz23838, edumazet, johannes, kuniyu,
linux-wireless, netdev
In-Reply-To: <20260716153917.3399255-1-dietz23838@hs-ansbach.de>
From: Simon Dietz <simon.dietz@plantwatch.de>
Improve the GeoNetworking code base, including:
- code comments
- kernel errno convention adherence
- removal of __attribute__((packed))
- several scripts/checkpatch.pl violation fixes
Additionally fixes one GeoNetworking logic related issue:
- default hop limit is now set according to ETSI standard
Signed-off-by: Simon Dietz <simon.dietz@plantwatch.de>
---
include/linux/gn.h | 46 ++++----
include/uapi/linux/gn.h | 2 +-
net/gn/gn_proc.c | 7 +-
net/gn/gn_prot.c | 226 +++++++++++++++++++++++++---------------
net/gn/gn_routing.c | 62 +++++------
5 files changed, 199 insertions(+), 144 deletions(-)
diff --git a/include/linux/gn.h b/include/linux/gn.h
index 393a8f440028..862f635d5d11 100644
--- a/include/linux/gn.h
+++ b/include/linux/gn.h
@@ -122,7 +122,7 @@ static inline struct gn_sock *gn_sk(struct sock *sk)
struct btp_header {
__be16 dst_port;
__be16 src_port;
-} __attribute__ ((packed));
+} __packed;
enum ITS_TYPE {
UNKNOWN,
@@ -157,14 +157,14 @@ struct gn_lpv {
__be32 lon;
gn_spai_t spai;
__be16 h; //signed
-} __attribute__ ((packed));
+} __packed;
struct gn_spv {
gn_address_t addr;
__be32 tst;
__be32 lat; //short
__be32 lon;
-} __attribute__ ((packed));
+} __packed;
/*version: Identifies the version of the GeoNetworking protocol
*
@@ -173,16 +173,24 @@ struct gn_spv {
*
*lt: Lifetime field.
*Indicates the maximum tolerable time a packet may be buffered until it reaches its destination Bit 0 to Bit 5:
- *LT sub-field Multiplier Bit 6 to Bit 7: LT sub-field Base Encoded as specified in clause 9.6.4
+ *lt_sub:
+ *0) 50 ms
+ *1) 1s
+ *2) 10 s
+ *3) 100 s
+ *4) 600 s
+ *5) 1000s
*
- *rhl: Decremented by 1 by each GeoAdhoc router that forwards the packet. The packet shall not be forwarded if RHL is decremented to zero
+ *Bit 6 to Bit 11:
+ *lt_mul: Multiplier for lt_sub, between 0 and 63
+ *
+ *rhl: Remaining hop limit. Set to the maximum hop limit (mhl) initially and decremented by 1 at each hop.
+ *The packet is dropped when rhl reaches 0
*/
-
struct gn_basic_header {
#ifdef __LITTLE_ENDIAN_BITFIELD
__u8 nh : 4;
__u8 version : 4;
-
#elif __BIG_ENDIAN_BITFIELD
__u8 version : 4;
__u8 nh : 4;
@@ -192,7 +200,7 @@ struct gn_basic_header {
__u8 reserved;
__u8 lt;
__u8 rhl;
-} __attribute__ ((packed));
+} __packed;
struct gn_common_header {
#ifdef __LITTLE_ENDIAN_BITFIELD
@@ -214,7 +222,7 @@ struct gn_common_header {
__be16 pl;
__u8 mhl;
__u8 reserved2;
-} __attribute__ ((packed));
+} __packed;
/*there are 6 types of headers:
* 1) GUC packet header (clause 9.8.2).
@@ -230,20 +238,20 @@ struct gn_guc_header {
__be16 reserved;
struct gn_lpv sopv;
struct gn_spv depv;
-} __attribute__ ((packed));
+} __packed;
struct gn_tsb_header {
__be16 sn;
__be16 reserved;
struct gn_lpv sopv;
-} __attribute__ ((packed));
+} __packed;
struct gn_shb_header {
struct gn_lpv sopv;
__be32 mdd;
-} __attribute__ ((packed));
+} __packed;
/* GAC and GBC share the same header structure */
@@ -257,21 +265,21 @@ struct gn_gxc_header {
__be16 db;
__be16 angle;
__be16 reserved2;
-} __attribute__ ((packed));
+} __packed;
-typedef struct gn_gxc_header gn_gac_header;
-typedef struct gn_gxc_header gn_gbc_header;
+#define gn_gac_header gn_gxc_header
+#define gn_gbc_header gn_gxc_header
struct gn_beacon_header {
struct gn_lpv sopv;
-} __attribute__ ((packed));
+} __packed;
struct gn_ls_request_header {
__be16 sn;
__be16 reserved;
struct gn_lpv sopv;
gn_address_t addr;
-} __attribute__ ((packed));
+} __packed;
//same structure as gn_guc_header, left in for abstraction
struct gn_ls_reply_header {
@@ -279,7 +287,7 @@ struct gn_ls_reply_header {
__be16 reserved;
struct gn_lpv sopv;
struct gn_spv depv;
-} __attribute__ ((packed));
+} __packed;
struct gn_header {
struct gn_basic_header gb_h;
@@ -297,7 +305,7 @@ struct gn_header {
struct gn_ls_reply_header ls_reply_h;
__be16 sn;
};
-} __attribute__ ((packed));
+} __packed;
/* Inter module exports */
diff --git a/include/uapi/linux/gn.h b/include/uapi/linux/gn.h
index c0df0d55f683..96cafbda54de 100644
--- a/include/uapi/linux/gn.h
+++ b/include/uapi/linux/gn.h
@@ -79,6 +79,6 @@ struct sockaddr_gn {
__kernel_sa_family_t sgn_family;
gn_address_t sgn_addr;
__u16 sgn_port;
-} __attribute__((packed));
+} __packed;
#endif /* _UAPI__LINUX_GN_H__ */
diff --git a/net/gn/gn_proc.c b/net/gn/gn_proc.c
index 75e126f9e494..ecd2aea446e5 100644
--- a/net/gn/gn_proc.c
+++ b/net/gn/gn_proc.c
@@ -42,17 +42,14 @@ static int gn_seq_socket_show(struct seq_file *seq, void *v)
struct gn_sock *gn;
if (v == SEQ_START_TOKEN) {
- seq_printf(seq, "Type Local_addr Remote_addr Tx_queue "
- "Rx_queue St UID\n");
+ seq_puts(seq, "Type Local_addr Remote_addr Tx_queue Rx_queue St UID\n");
goto out;
}
s = sk_entry(v);
gn = gn_sk(s);
- seq_printf(seq,
- "%02X %08llX:%04X %08llX:%04X %08X:%08X "
- "%02X\n",
+ seq_printf(seq, "%02X %08llX:%04X %08llX:%04X %08X:%08X %02X\n",
s->sk_type, be64_to_cpu(gn->src_addr), gn->src_port,
be64_to_cpu(gn->dst_addr), gn->dst_port,
sk_wmem_alloc_get(s), sk_rmem_alloc_get(s), s->sk_state);
diff --git a/net/gn/gn_prot.c b/net/gn/gn_prot.c
index a59aadf843b0..3c4e1157fbde 100644
--- a/net/gn/gn_prot.c
+++ b/net/gn/gn_prot.c
@@ -31,11 +31,7 @@
struct datalink_proto *gn_dl;
static const struct proto_ops gn_dgram_ops;
-/**************************************************************************\
-* *
-* Handlers for the socket list. *
-* *
-\**************************************************************************/
+/* Handlers for the socket list. */
HLIST_HEAD(gn_sockets);
DEFINE_RWLOCK(gn_sockets_lock);
@@ -53,7 +49,7 @@ static inline void gn_remove_socket(struct sock *sk)
}
#define from_timer(var, callback_timer, timer_fieldname) \
- container_of(callback_timer, typeof(*var), timer_fieldname)
+ container_of(callback_timer, typeof(*(var)), timer_fieldname)
static void gn_destroy_timer(struct timer_list *t)
{
@@ -81,12 +77,9 @@ static inline void gn_destroy_socket(struct sock *sk)
}
}
-/**************************************************************************\
-* *
-* Handling for system calls applied via the various interfaces to an *
-* GeoNetworking socket object. *
-* *
-\**************************************************************************/
+/* Handling for system calls applied via the various interfaces to a
+ * GeoNetworking socket object.
+ */
static struct proto gn_proto = {
.name = "GN",
@@ -97,7 +90,7 @@ static struct proto gn_proto = {
HLIST_HEAD(gn_interfaces);
DEFINE_SPINLOCK(gn_interfaces_lock);
-void gn_activate_beacon(void);
+static void gn_activate_beacon(void);
/**
* gn_iface - add device to the interface the socketaddress is bound to
@@ -106,8 +99,7 @@ static struct gn_iface *gn_if_add_device(struct net_device *dev,
struct sockaddr_gn *sa)
{
bool was_empty;
- struct gn_iface *gnif,
- *new_gnif = kzalloc(sizeof(struct gn_iface), GFP_KERNEL);
+ struct gn_iface *gnif, *new_gnif = kzalloc_obj(*new_gnif, GFP_KERNEL);
if (!new_gnif)
return NULL;
@@ -266,7 +258,7 @@ static int gn_create(struct net *net, struct socket *sock, int protocol,
if (protocol < GN_PROTO_ANY || protocol > GN_PROTO_MAX)
goto out;
- /* Note: Only BTP/GeoNetworking protocols are supported; IPv6 encapsulation is not enabled */
+ /* Note: Only BTP/GeoNetworking protocols supported; IPv6 encap not enabled */
if (protocol == GN_PROTO_INET6)
goto out;
@@ -357,8 +349,7 @@ static struct sock *gn_find_or_insert_socket(struct sock *sk,
gn = gn_sk(sk);
gn->src_addr = sgn->sgn_addr;
gn->src_port = sgn->sgn_port;
- pr_info("gn: Add socket addr=%llx port=%d", gn->src_addr,
- gn->src_port);
+ pr_info("gn: Add socket addr=%llx port=%d", gn->src_addr, gn->src_port);
__gn_insert_socket(sk); /* Wheee, it's free, assign and insert. */
found:
write_unlock_bh(&gn_sockets_lock);
@@ -462,7 +453,7 @@ static struct sock *gn_search_socket(struct sockaddr_gn *tosgn,
if (gn->src_port != tosgn->sgn_port)
continue;
- if (gnif == NULL || gn->src_addr == gnif->address) {
+ if (!gnif || gn->src_addr == gnif->address) {
sock_hold(s);
goto out;
}
@@ -473,14 +464,6 @@ static struct sock *gn_search_socket(struct sockaddr_gn *tosgn,
return s;
}
-/*
-static int gn_dupl_addr_detect(unsigned long long local_llc, gn_address_t local_addr,
- unsigned long long rcv_llc, gn_address_t rcv_addr)
-{
- return 0;
-}
-*/
-
static u16 gn_if_next_sn(struct gn_iface *gnif)
{
return atomic_inc_return(&gnif->local_sn) % USHRT_MAX;
@@ -488,7 +471,7 @@ static u16 gn_if_next_sn(struct gn_iface *gnif)
void gn_fill_sopv(struct gn_iface *gnif, struct gn_lpv *sopv, gn_address_t addr)
{
- /* Note: Speed and Heading fields are currently zeroed until velocity sensors are integrated */
+ /* Note: Speed and Heading zeroed until velocity sensors integrated */
ktime_t tst = ktime_set(gnif->pos.tst.tv_sec, gnif->pos.tst.tv_nsec);
// fill empty timestamp with current timestamp
@@ -639,6 +622,60 @@ static int gn_pass_payload_sock(struct sockaddr_gn *tosgn, struct sk_buff *skb)
return rc;
}
+static int gn_forward_guc_packet(struct sk_buff *skb, gn_address_t dest_addr)
+{
+ struct sk_buff *forward_skb;
+ struct gn_header *fwd_gh;
+ struct gn_iface *gnif;
+ u8 next_hop_mac[ETH_ALEN];
+
+ fwd_gh = (struct gn_header *)skb_network_header(skb);
+ if (fwd_gh->gb_h.rhl <= 0)
+ return -EINVAL;
+
+ gnif = gn_find_interface_by_dev(skb->dev);
+ if (!gnif)
+ return -ENODEV;
+
+ forward_skb = skb_copy(skb, GFP_ATOMIC);
+ if (!forward_skb) {
+ pr_warn("Dropping packet during GUC forwarding\n");
+ return -ENOMEM;
+ }
+
+ fwd_gh = (struct gn_header *)skb_network_header(forward_skb);
+ fwd_gh->gb_h.rhl--;
+
+ if (gn_query_ll_nexthop(gnif, dest_addr, next_hop_mac) == 0)
+ gn_dl->request(gn_dl, forward_skb, next_hop_mac);
+ else
+ gn_dl->request(gn_dl, forward_skb, skb->dev->broadcast);
+
+ return 0;
+}
+
+static int gn_forward_tsb_packet(struct sk_buff *skb)
+{
+ struct sk_buff *forward_skb;
+ struct gn_header *fwd_gh;
+
+ fwd_gh = (struct gn_header *)skb_network_header(skb);
+ if (fwd_gh->gb_h.rhl <= 0)
+ return -EINVAL;
+
+ forward_skb = skb_copy(skb, GFP_ATOMIC);
+ if (!forward_skb) {
+ pr_warn("Dropping packet during TSB forwarding\n");
+ return -ENOMEM;
+ }
+
+ fwd_gh = (struct gn_header *)skb_network_header(forward_skb);
+ fwd_gh->gb_h.rhl--;
+
+ gn_dl->request(gn_dl, forward_skb, skb->dev->broadcast);
+ return 0;
+}
+
static int gn_process_guc_packet(struct sk_buff *skb)
{
struct gn_header *gh;
@@ -660,8 +697,13 @@ static int gn_process_guc_packet(struct sk_buff *skb)
goto drop;
gnif = gn_find_interface(tosgn.sgn_addr);
- if (!gnif)
+ if (!gnif) {
+ if (gn_forward_guc_packet(skb, tosgn.sgn_addr) == 0) {
+ kfree_skb(skb);
+ return NET_RX_SUCCESS;
+ }
goto drop;
+ }
if (gn_pass_payload_sock(&tosgn, skb) != NET_RX_SUCCESS)
goto drop;
@@ -734,7 +776,7 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
tosgn.sgn_addr = gh->gbc_h.sopv.addr;
tosgn.sgn_port = be16_to_cpu(btp_h->dst_port);
- /* Resolve local GeoNetworking interface from skb->dev to check geographical area membership */
+ /* Resolve local GeoNetworking interface to check area membership */
gnif = gn_find_interface_by_dev(skb->dev);
if (!gnif)
goto drop;
@@ -783,7 +825,8 @@ static int gn_process_gxc_packet(struct sk_buff *skb)
pr_warn("dropping packet");
goto drop;
}
- fwd_gb_h = (struct gn_basic_header *)skb_transport_header(forward_skb);
+ fwd_gb_h = (struct gn_basic_header *)skb_transport_header(
+ forward_skb);
fwd_gb_h->rhl--;
rc = gn_gxc_forward(gnif, f_value, dest_addr, &gh->gbc_h.sopv);
@@ -864,22 +907,8 @@ static int gn_process_tsb_packet(struct sk_buff *skb)
&gh->tsb_h.sn))
goto drop;
- if (gh->gb_h.rhl > 0) {
- // Forward packet
- struct sk_buff *forward_skb;
- struct gn_header *fwd_gh;
-
- forward_skb = skb_copy(skb, GFP_ATOMIC);
- if (!forward_skb) {
- pr_warn("Dropping packet");
- goto drop;
- }
-
- fwd_gh = (struct gn_header *)skb_network_header(forward_skb);
- fwd_gh->gb_h.rhl--;
-
- gn_dl->request(gn_dl, forward_skb, skb->dev->broadcast);
- }
+ if (gh->gb_h.rhl > 0)
+ gn_forward_tsb_packet(skb);
// 7. pass payload of GN_PDU to the upper protocol unit
tosgn.sgn_family = PF_GN;
@@ -939,10 +968,10 @@ static int gn_process_ls_packet(struct sk_buff *skb)
dest_addr, 0);
} else {
// has to be forwarded like a tsb
- //5. try to flush own forward buffer
+ // 5. try to flush own forward buffer
gn_ls_flush(gls_req_h->sopv.addr);
- //6. forward like a tsb - (omitted atm, since forwarding of tsb
- // is processed on another branch)
+ // 6. forward like a tsb
+ gn_forward_tsb_packet(skb);
}
} else if (gh->gc_h.hst == CH_HST_LS_REPLY) {
struct gn_ls_reply_header *gls_rep_h = &gh->ls_reply_h;
@@ -953,14 +982,11 @@ static int gn_process_ls_packet(struct sk_buff *skb)
goto drop;
dest_addr = gls_rep_h->depv.addr;
- //4. flush forward buffer
+ // 4. flush forward buffer
gn_ls_flush(gls_rep_h->sopv.addr);
- //5. find out if the packet has to be forwarded
- if (!gn_find_interface(dest_addr)) {
- /* Note: Multi-hop forwarding of LS replies when destination router is non-local */
- ; //Packet is not for this router, it has to be forwarded like a guc
- //omitted atm, since F(x,y) needed
- }
+ // 5. find out if the packet has to be forwarded
+ if (!gn_find_interface(dest_addr))
+ gn_forward_guc_packet(skb, dest_addr);
} else {
//WARN_ONCE(1, "called gn_process_ls_packet on non-LS packet");
goto drop;
@@ -1031,37 +1057,54 @@ static int gn_rcv(struct sk_buff *skb, struct net_device *dev,
switch (gh->gc_h.ht) {
case CH_HT_GUC:
- if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_guc_header) + sizeof(struct btp_header)))
+ if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE +
+ sizeof(struct gn_guc_header) +
+ sizeof(struct btp_header)))
goto drop;
return gn_process_guc_packet(skb);
case CH_HT_GAC:
case CH_HT_GBC:
- if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_gxc_header) + sizeof(struct btp_header)))
+ if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE +
+ sizeof(struct gn_gxc_header) +
+ sizeof(struct btp_header)))
goto drop;
return gn_process_gxc_packet(skb);
case CH_HT_TSB:
if (gh->gc_h.hst == CH_HST_TSB_SINGLE_HOP) {
- if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_shb_header) + sizeof(struct btp_header)))
+ if (!pskb_may_pull(
+ skb, GN_BASE_HEADER_SIZE +
+ sizeof(struct gn_shb_header) +
+ sizeof(struct btp_header)))
goto drop;
return gn_process_shb_packet(skb, eth->h_source);
- } else if (gh->gc_h.hst == CH_HST_TSB_MULTI_HOP) {
- if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_tsb_header) + sizeof(struct btp_header)))
+ }
+ if (gh->gc_h.hst == CH_HST_TSB_MULTI_HOP) {
+ if (!pskb_may_pull(
+ skb, GN_BASE_HEADER_SIZE +
+ sizeof(struct gn_tsb_header) +
+ sizeof(struct btp_header)))
goto drop;
return gn_process_tsb_packet(skb);
- } else {
- goto drop;
}
- break;
+ goto drop;
case CH_HT_BEACON:
- if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_beacon_header)))
+ if (!pskb_may_pull(skb,
+ GN_BASE_HEADER_SIZE +
+ sizeof(struct gn_beacon_header)))
goto drop;
return gn_process_beacon_packet(skb, eth->h_source);
case CH_HT_LS:
if (gh->gc_h.hst == CH_HST_LS_REQUEST) {
- if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_ls_request_header)))
+ if (!pskb_may_pull(
+ skb,
+ GN_BASE_HEADER_SIZE +
+ sizeof(struct gn_ls_request_header)))
goto drop;
} else if (gh->gc_h.hst == CH_HST_LS_REPLY) {
- if (!pskb_may_pull(skb, GN_BASE_HEADER_SIZE + sizeof(struct gn_ls_reply_header)))
+ if (!pskb_may_pull(
+ skb,
+ GN_BASE_HEADER_SIZE +
+ sizeof(struct gn_ls_reply_header)))
goto drop;
} else {
goto drop;
@@ -1181,7 +1224,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
struct gn_iface *gnif;
u32 size;
u32 eh_size;
- u8 rhl;
+ u8 rhl = DEFAULT_HOP_LIMIT;
struct gn_spv depv = { 0 };
if (flags & ~(MSG_DONTWAIT | MSG_CMSG_COMPAT)) {
@@ -1376,11 +1419,13 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
case CH_HT_TSB:
if (packet_subtype == CH_HST_TSB_SINGLE_HOP) {
rhl = 1;
- gn_fill_shb_header((struct gn_shb_header *)gp_h, gnif, gn);
+ gn_fill_shb_header((struct gn_shb_header *)gp_h, gnif,
+ gn);
} else if (packet_subtype == CH_HST_TSB_MULTI_HOP) {
//at this point it is safe to assume that a topological scope is used
- rhl = gn->scope.topo_hops;
- gn_fill_tsb_header((struct gn_tsb_header *)gp_h, gnif, gn);
+ rhl = gn->scope.topo_hops ?: DEFAULT_HOP_LIMIT;
+ gn_fill_tsb_header((struct gn_tsb_header *)gp_h, gnif,
+ gn);
} else {
WARN_ONCE(1, "internal error");
err = -EINVAL;
@@ -1409,7 +1454,7 @@ static int gn_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
// LS request is pending, we're done
break;
case GN_QUEUE_DIRECT:
- /* Destination is in LocTE; resolve direct or greedy forwarding next-hop MAC */
+ /* Destination in LocTE; resolve MAC or greedy next-hop */
if (gn_query_ll_nexthop(gnif, usgn->sgn_addr,
ll_address))
gn_dl->request(gn_dl, skb, dev->broadcast);
@@ -1545,7 +1590,7 @@ static void gn_send_beacons(struct timer_list *tl)
static DEFINE_TIMER(gn_beacon_timer, gn_send_beacons);
-void gn_activate_beacon(void)
+static void gn_activate_beacon(void)
{
mod_timer(&gn_beacon_timer,
jiffies + msecs_to_jiffies(GN_BEACON_RETRANSMIT_TIME));
@@ -1554,22 +1599,20 @@ void gn_activate_beacon(void)
static int validate_geo_scope(struct gn_geo_scope *scope)
{
if (scope->angle > 360)
- return 1;
+ return -EINVAL;
if (scope->a == 0)
- return 1;
-
- int is_not_null = scope->b != 0 ? 1 : 0;
+ return -EINVAL;
switch (scope->shape) {
case GN_SHAPE_CIRCLE:
- return is_not_null;
+ return scope->b != 0 ? -EINVAL : 0;
case GN_SHAPE_RECTANGLE:
case GN_SHAPE_ELLIPSE:
return 0;
default:
case GN_SHAPE_UNSPECIFIED:
- return 1;
+ return -EINVAL;
}
return 0;
}
@@ -1578,7 +1621,7 @@ static int validate_scope(struct gn_scope *scope)
{
if (scope->scope_type < GN_SCOPE_TOPOLOGICAL ||
scope->scope_type > GN_SCOPE_MAX)
- return 1;
+ return -EINVAL;
switch (scope->scope_type) {
case GN_SCOPE_TOPOLOGICAL:
return 0;
@@ -1586,7 +1629,7 @@ static int validate_scope(struct gn_scope *scope)
case GN_SCOPE_GEOGRAPHICAL_ANYCAST:
return validate_geo_scope(&scope->geo_scope);
default:
- return 1;
+ return -EINVAL;
}
return 0;
}
@@ -1611,8 +1654,8 @@ static int gn_setsockopt(struct socket *sock, int level, int optname,
if (copy_from_sockptr(&opt, optval, sizeof(struct gn_scope)))
goto out;
- rc = -EINVAL;
- if (validate_scope(&opt))
+ rc = validate_scope(&opt);
+ if (rc < 0)
goto out;
lock_sock(sk);
@@ -1718,6 +1761,19 @@ static int gn_if_ioctl(struct socket *sock, unsigned int cmd, void __user *argp)
return -EINVAL;
if (dev->type != ARPHRD_ETHER)
return -EINVAL;
+ /*
+ * TODO: Remove the -EEXIST check below to allow SIOCSIFADDR to seamlessly
+ * update/replace an existing interface address (required for ETSI ITS
+ * pseudonym rotation per TS 102 636-4-1).
+ *
+ * Before removing -EEXIST, the following steps must be addressed:
+ * 1. Socket Synchronization: Active sockets bound to the old interface
+ * address must have their gn->src_addr updated when gnif->address changes.
+ * 2. Sequence Number Preservation: gn_if_add_device() currently allocates
+ * a new gn_iface with local_sn initialized to 0. When replacing an entry,
+ * preserve the existing local_sn value or perform in-place mutation under
+ * gn_interfaces_lock instead of allocating a replacement struct.
+ */
if (gn_find_interface_by_dev(dev))
return -EEXIST;
gnif = gn_if_add_device(dev, sa);
@@ -1844,7 +1900,7 @@ static struct packet_type gn_packet_type __read_mostly = {
/*
* SNAP-ID for Geonetworking 0x8947
- * Note: SNAP header format uses network byte order (big-endian 0x8947) as per ETSI EN 302 636-4-1 Annex E
+ * Note: SNAP header format uses big-endian 0x8947 per ETSI EN 302 636-4-1 Annex E
*/
static unsigned char gn_snap_id[] = { 0x00, 0x00, 0x00, 0x89, 0x47 };
diff --git a/net/gn/gn_routing.c b/net/gn/gn_routing.c
index 110a4d76d2bd..de1c77359e09 100644
--- a/net/gn/gn_routing.c
+++ b/net/gn/gn_routing.c
@@ -26,11 +26,7 @@ static DEFINE_SPINLOCK(gn_loc_t_lock);
#define GN_TST_VALID(tst) \
time_before(jiffies, (unsigned long)(tst) + GN_LT_JIFFIES)
-/***************************************************************************\
-* *
-* GeoNetworking routing *
-* *
-\***************************************************************************/
+/* GeoNetworking routing */
static u16 *gn_dpd_find(struct gn_dpd_buf *buf, u16 sn)
{
@@ -122,21 +118,21 @@ static int icos(__s64 rad)
}
/* degree_to_rad() - convert a degree value to a rad value.
-* @a : the degree value as 1/10 micro degree (10^7).
-*
-* Return : the rad value * 10^7.
-*/
+ * @a : the degree value as 1/10 micro degree (10^7).
+ *
+ * Return : the rad value * 10^7.
+ */
static __s64 degree_to_rad(__s64 a)
{
return (((RAD_PER_DEGREE * a) / 10000000ULL)) % (PI * 2ULL);
}
/* diff() - calculate the difference beween a and b.
-* @a : value a.
-* @b : value b.
-*
-* Return : the difference
-*/
+ * @a : value a.
+ * @b : value b.
+ *
+ * Return : the difference
+ */
static __s32 diff(__s32 a, __s32 b)
{
__s32 r = a - b;
@@ -150,7 +146,7 @@ static __s32 diff(__s32 a, __s32 b)
* @y : after execute includes the meter on Y-axes.
*
* the calculation based on pythagoras.
-*/
+ */
static struct gn_coord gn_coord_diff(struct gn_coord lhs, struct gn_coord rhs)
{
struct gn_coord c;
@@ -247,8 +243,7 @@ static int greedy_forward(struct gn_iface *gnif, u8 *addr, struct gn_lpv *depv)
}
}
}
-
- // FIXME traffic class check here
+ /* Note: Traffic class and store-carry-forward evaluation for next-hop selection */
if (found_addr) {
ether_addr_copy(addr, found_addr);
rc = GN_FORWARD_NEXT_HOP;
@@ -326,7 +321,7 @@ static void gn_prune(void)
/* update_location_table() - update location table
* @pv: the position vector which indicate an entry.
*
- * Return: 0 on success, 1 on error, 2 if packet is duplicate.
+ * Return: 0 on success, negative errno on error, -EALREADY if packet is duplicate.
*
* Update an entry, which indicated by @spv. If no entry found its will be add a new one.
* And all entries will be check with the update function.
@@ -334,8 +329,7 @@ static void gn_prune(void)
int gn_update_location_table(struct gn_lpv *pv, bool make_neighbour,
const u8 *ll_address, const __be16 *sn)
{
- // FIXME Use timestamp associated with incoming skb
- // TODO (Clause C.2): Only update PV if incoming PV is newer than stored PV
+ /* ETSI EN 302 636-4-1 Clause C.2: Update PV only when incoming PV timestamp is newer */
struct loc_te *entry;
bool found = false;
@@ -366,19 +360,18 @@ int gn_update_location_table(struct gn_lpv *pv, bool make_neighbour,
if (gn_dpd_find(&entry->dpl, be16_to_cpu(*sn))) {
pr_debug("received duplicate packet\n");
spin_unlock_bh(&gn_loc_t_lock);
- return 2;
- } else {
- gn_dpd_insert(&entry->dpl, be16_to_cpu(*sn));
+ return -EALREADY;
}
+ gn_dpd_insert(&entry->dpl, be16_to_cpu(*sn));
}
break;
}
if (!found) {
- entry = kzalloc(sizeof(struct loc_te), GFP_ATOMIC);
+ entry = kzalloc_obj(*entry, GFP_ATOMIC);
if (!entry) {
spin_unlock_bh(&gn_loc_t_lock);
- return 1;
+ return -ENOMEM;
}
pr_debug("adding entry addr=%llx\n", pv->addr);
entry->addr = pv->addr;
@@ -437,7 +430,7 @@ static void __ls_queue(struct sk_buff_head *q, struct sk_buff *skb)
int gn_ls_queue(gn_address_t dest_addr, struct sk_buff *skb)
{
struct loc_te *entry;
- int rc = -1;
+ int rc = -ENOENT;
spin_lock_bh(&gn_loc_t_lock);
hash_for_each_possible(gn_loc_t, entry, hnode, dest_addr) {
@@ -460,11 +453,11 @@ int gn_ls_queue(gn_address_t dest_addr, struct sk_buff *skb)
break;
}
- if (rc == -1) {
- entry = kzalloc(sizeof(struct loc_te), GFP_ATOMIC);
+ if (rc == -ENOENT) {
+ entry = kzalloc_obj(*entry, GFP_ATOMIC);
if (!entry) {
spin_unlock_bh(&gn_loc_t_lock);
- return GN_QUEUE_ERROR;
+ return -ENOMEM;
}
rc = GN_QUEUE_LS_STALE;
@@ -526,7 +519,7 @@ void gn_ls_flush(gn_address_t dest_addr)
int gn_query_ll_address(gn_address_t query_addr, u8 *ll_address)
{
struct loc_te *entry;
- int rc = 1;
+ int rc = -ENOENT;
spin_lock_bh(&gn_loc_t_lock);
hash_for_each_possible(gn_loc_t, entry, hnode, query_addr) {
@@ -556,7 +549,7 @@ int gn_query_ll_address(gn_address_t query_addr, u8 *ll_address)
* If query_addr is a multi-hop destination in LocTE, runs greedy forwarding to
* select the best next-hop neighbor toward the destination.
*
- * Return: 0 if link-layer address resolved (ll_address populated), 1 if broadcast needed.
+ * Return: 0 if link-layer address resolved, negative errno if broadcast needed.
*/
int gn_query_ll_nexthop(struct gn_iface *gnif, gn_address_t query_addr, u8 *ll_address)
{
@@ -583,11 +576,12 @@ int gn_query_ll_nexthop(struct gn_iface *gnif, gn_address_t query_addr, u8 *ll_a
spin_unlock_bh(&gn_loc_t_lock);
if (!found)
- return 1;
+ return -ENOENT;
if (is_neighbor)
return 0;
- return (greedy_forward(gnif, ll_address, &target_pv) == GN_FORWARD_NEXT_HOP) ? 0 : 1;
+ return (greedy_forward(gnif, ll_address, &target_pv) ==
+ GN_FORWARD_NEXT_HOP) ? 0 : -EHOSTUNREACH;
}
/**
@@ -600,7 +594,7 @@ int gn_query_ll_nexthop(struct gn_iface *gnif, gn_address_t query_addr, u8 *ll_a
int gn_fill_depv(struct gn_spv *depv, gn_address_t dest_addr)
{
struct loc_te *entry;
- int rc = -1;
+ int rc = -ENOENT;
spin_lock_bh(&gn_loc_t_lock);
hash_for_each_possible(gn_loc_t, entry, hnode, dest_addr) {
--
2.55.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox