0

I'm using wpanusb kernel module with kernel 4.14.112 on a Raspberry Pi to send IEEE802.15.4 frames over USB to a nrf52840 MCU running wpanusb from samples of Zephyr OS. The kernel module I use comes from this repo : https://github.com/jadonk/wpanusb/blob/master/wpanusb.c. This module is almost a copy from atusb mainline kernel module. As wpanusb is outdated compared to atusb, I've integrated 2 fixes which were missing:

Sadly, kmemleak keeps reporting the following after each ifup/ifdown of the wpan0 interface:

unreferenced object 0x9a422f00 (size 128):
  comm "kworker/0:1", pid 29, jiffies 4294939089 (age 2003.690s)
  hex dump (first 32 bytes):
    01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
    00 00 00 00 14 2f 42 9a 14 2f 42 9a 00 01 00 00  ...../B../B.....
  backtrace:
    [<7f1fbd28>] wpanusb_probe+0x144/0x504 [wpanusb]
    [<804a7f08>] usb_probe_interface+0xd0/0x290
    [<8046b1e0>] driver_probe_device+0x2a8/0x424
    [<804694d0>] bus_for_each_drv+0x70/0x94
    [<8046ae04>] __device_attach+0xb0/0x134
    [<8046a26c>] bus_probe_device+0x84/0x8c
    [<80468498>] device_add+0x368/0x5c0
    [<804a5df0>] usb_set_configuration+0x488/0x9e0
    [<804b0998>] generic_probe+0x4c/0x74
    [<8046b1e0>] driver_probe_device+0x2a8/0x424
    [<804694d0>] bus_for_each_drv+0x70/0x94
    [<8046ae04>] __device_attach+0xb0/0x134
    [<8046a26c>] bus_probe_device+0x84/0x8c
    [<80468498>] device_add+0x368/0x5c0
    [<8049be28>] usb_new_device+0x260/0x464
    [<8049dcb8>] hub_event+0xf50/0x13a4

Before getting the network interface up, I perform a hard reset of the MCU on its RESET pin. This is to ensure to be able to communicate again with the MCU in case it gets stuck. If I don't perform this hard reset, the memory leak doesn't show up because disconnect() function is not called.

I provide here an extract of the functions called at probe and disconnect :

static int wpanusb_probe(struct usb_interface *interface,
             const struct usb_device_id *id)
{
    struct usb_device *udev = interface_to_usbdev(interface);
    struct ieee802154_hw *hw;
    struct wpanusb *wpanusb;
    int ret;

    hw = ieee802154_alloc_hw(sizeof(struct wpanusb), &wpanusb_ops);
    if (!hw)
        return -ENOMEM;

    wpanusb = hw->priv;
    wpanusb->hw = hw;
    wpanusb->udev = usb_get_dev(udev);
    usb_set_intfdata(interface, wpanusb);

    wpanusb->shutdown = 0;
    INIT_DELAYED_WORK(&wpanusb->work, wpanusb_work_urbs);
    init_usb_anchor(&wpanusb->idle_urbs);
    init_usb_anchor(&wpanusb->rx_urbs);

    ret = wpanusb_alloc_urbs(wpanusb, WPANUSB_NUM_RX_URBS);
    if (ret)
        goto fail;

    wpanusb->tx_dr.bRequestType = VENDOR_OUT;
    wpanusb->tx_dr.bRequest = TX;
    wpanusb->tx_dr.wValue = cpu_to_le16(0);

    wpanusb->tx_urb = usb_alloc_urb(0, GFP_KERNEL);
    if (!wpanusb->tx_urb)
        goto fail;

    hw->parent = &udev->dev;

    ret = wpanusb_control_send(wpanusb, usb_sndctrlpipe(udev, 0), RESET,
                   NULL, 0);
    if (ret < 0) {
        dev_err(&udev->dev, "Failed to RESET ieee802154");
        goto fail;
    }

    ret = wpanusb_get_device_capabilities(hw);

    if (ret < 0) {
        dev_err(&udev->dev, "Failed to get device capabilities");
        goto fail;
    }

    ret = wpanusb_set_extended_addr(hw);

    if (ret < 0) {
        dev_err(&udev->dev, "Failed to set permanent address");
        goto fail;
    }

    ret = ieee802154_register_hw(hw);
    if (ret) {
        dev_err(&udev->dev, "Failed to register ieee802154");
        goto fail;
    }

    dev_dbg(&udev->dev, "ieee802154 ready to go");

    return 0;

fail:
    dev_err(&udev->dev, "Failed ieee802154 probe");
    wpanusb_free_urbs(wpanusb);
    usb_kill_urb(wpanusb->tx_urb);
    usb_free_urb(wpanusb->tx_urb);
    usb_put_dev(udev);
    ieee802154_free_hw(hw);

    return ret;
}

static void wpanusb_disconnect(struct usb_interface *interface)
{
    struct wpanusb *wpanusb = usb_get_intfdata(interface);

    wpanusb->shutdown = 1;
    cancel_delayed_work_sync(&wpanusb->work);

    usb_kill_anchored_urbs(&wpanusb->rx_urbs);
    wpanusb_free_urbs(wpanusb);
    usb_kill_urb(wpanusb->tx_urb);
    usb_free_urb(wpanusb->tx_urb);

    ieee802154_unregister_hw(wpanusb->hw);

    usb_put_dev(wpanusb->udev);

    ieee802154_free_hw(wpanusb->hw);

    usb_set_intfdata(interface, NULL);
}

New information 22.09.22: I've tried to put at line 709 a goto fail; in wpanusb_probe() to check what's happening. No memory leak seen.

Carton_
  • 23
  • 3

0 Answers0