thePhisitian
thePhisitian

Reputation: 21

ndo_start_xmit() not called when using cansend command

A little background, I want to receive CAN frames to Linux SOM, which does not have CAN peripheral, so I use stm32 which acts just like a bridge that sends CAN frames over UART to SoM. That part is already sorted out with custom kernel driver. Now when trying to include spawning CAN device I come to problem.

Custom kernel driver where I am registering CAN device with following simple program:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/can.h> 
#include <linux/can/dev.h> 
#include <linux/netdevice.h>
#include <linux/uaccess.h>

#include "main.h"
#include "can_dev.h"

static struct net_device *can_dev;

void uart_receive_handler(can_frame_stm *frame_stm, uint32_t Len)
{
    struct sk_buff *skb;
    struct can_frame *cf;
    
    // Allocate a new skb and can_frame
    
    skb = alloc_can_skb(can_dev, &cf);
    if (!skb) {
        printk(KERN_ERR "DEBUG %s can_dev: Failed to allocating can skb\n", MODULE_NAME);
        return;
    }

    cf->can_id = frame_stm->can_id;
    cf->can_dlc = frame_stm->can_dlc;
    memcpy(cf->data, frame_stm->data, frame_stm->can_dlc);

    // Process the received CAN frame
    netif_rx(skb);
}

// Transmit CAN frames
static netdev_tx_t can_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
    struct can_frame *cf = (struct can_frame *)skb->data;
    
    // Transmit the CAN frame via UART to STM32 here
    printk(KERN_INFO "DEBUG %s can_dev: transmit data\n", MODULE_NAME);
    // uart_send(cf, sizeof(struct can_frame));
    netif_trans_update(dev);
    dev_kfree_skb(skb);
    return NETDEV_TX_OK;
}

static int simple_can_open(struct net_device *dev)
{
    netif_start_queue(dev);
    printk(KERN_INFO "DEBUG %s can_dev: device opened\n", MODULE_NAME);
    return 0;
}

static int simple_can_close(struct net_device *dev)
{
    netif_stop_queue(dev);
    printk(KERN_INFO "DEBUG %s can_dev: device closed\n", MODULE_NAME);
    return 0;
}

// Net device operations
static const struct net_device_ops can_netdev_ops = {
    .ndo_open = simple_can_open,
    .ndo_stop = simple_can_close,
    .ndo_start_xmit = can_start_xmit,
};

static void simple_can_setup(struct net_device *dev)
{
    dev->netdev_ops = &can_netdev_ops;
    dev->flags |= IFF_NOARP;
    dev->mtu = CAN_MTU;
}

void init_can(void)
{
    printk(KERN_INFO "DEBUG %s can_dev: Start init\n", MODULE_NAME);
    can_dev = alloc_candev(0,10);
    if (!can_dev) {
        printk(KERN_ALERT "DEBUG %s can_dev: Failed to create can dev\n", MODULE_NAME);
        return;
    }
    simple_can_setup(can_dev);

    if (register_candev(can_dev)) {
      printk(KERN_ERR "DEBUG %s can_dev: Failed to register CAN device\n", MODULE_NAME);
      free_candev(can_dev);
      return;
    }
    printk(KERN_INFO "DEBUG %s can_dev: Finish\n", MODULE_NAME);
}

void exit_can(void)
{
    unregister_candev(can_dev);
    free_candev(can_dev);
}

So to load module first I have to load can-dev module modprobe can-dev then I load my module insmod can_module.ko and also need to bring link up ip link set can0 up.

When I try to watch receiving data with candump can0 I get the CAN frames printed on console. But when I try to use cansend it does print nothing not even error. However if I have candump can0 and I cansend command, it shows the CAN frame. Here is the dmesg output:

[   79.623157] CAN device driver interface
[   79.633722] DEBUG CAN_MODULE can_dev: Start init
[   79.634380] DEBUG CAN_MODULE can_dev: Finish
[   79.643978] DEBUG CAN_MODULE can_dev: device opened
////////// here I called `candump can0` ////////////////
[   98.963006] can: controller area network core
[   98.963140] NET: Registered PF_CAN protocol family
[   98.972396] can: raw protocol
////////// here I called `cansend can0 123#DEADBEEF` a bunch of times ////////////////

Upvotes: 1

Views: 40

Answers (1)

thePhisitian
thePhisitian

Reputation: 21

I have resolved this, I have forgot to open can device in simple_can_open(). so this is how simple_can_open() looks now:

static int simple_can_open(struct net_device *dev)
{
    int err = open_candev(dev);
    if (err) {
        printk(KERN_WARNING "LXNAV %s can_dev: Failed opening\n", MODULE_NAME);
        return err;
    }
    netif_start_queue(dev);
    printk(KERN_INFO "DEBUG %s can_dev: device opened\n", MODULE_NAME);
    return 0;
}

Upvotes: 0

Related Questions