2 Commits
Author SHA1 Message Date
chgabriel79andGitHub 0b0fa206c7 Merge b00c957824 into c4828c486d 2025-09-30 12:21:27 +02:00
Christian Gabriel b00c957824 Setting of individual bit timing and berr reporting
Signed-off-by: Christian Gabriel <ch_gabriel@web.de>
2024-09-25 10:40:29 +02:00
+257 -105
View File
@@ -66,15 +66,6 @@
#define VER_MIN_FROM_INT(VERINT) ((VERINT >> 8) & 0xFF) #define VER_MIN_FROM_INT(VERINT) ((VERINT >> 8) & 0xFF)
#define VER_PATCH_FROM_INT(VERINT) (VERINT & 0xFF) #define VER_PATCH_FROM_INT(VERINT) (VERINT & 0xFF)
#define RX_BOX_SIZE (SHARED_MEM_SIZE / (MAX_NET_DEVICES * 2))
#define TX_BOX_SIZE (SHARED_MEM_SIZE / 4)
#define GET_RX_BOX(DEVICE_INDEX) \
(shared_mem + (RX_BOX_SIZE * DEVICE_INDEX))
#define GET_TX_BOX(BOX_INDEX) \
(shared_mem + (SHARED_MEM_SIZE / 2) + (BOX_INDEX * TX_BOX_SIZE))
#define MAX_TX (0x100)
#define DESC_OFFSET (2)
MODULE_DESCRIPTION(KO_DESC); MODULE_DESCRIPTION(KO_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_AUTHOR("Paul Hollinsky <phollinsky@intrepidcs.com>"); MODULE_AUTHOR("Paul Hollinsky <phollinsky@intrepidcs.com>");
@@ -98,6 +89,8 @@ MODULE_VERSION(KO_VERSION);
#define SIOCGVERSION 0x3008 #define SIOCGVERSION 0x3008
#define SIOCGCLIENTVEROK 0x3009 #define SIOCGCLIENTVEROK 0x3009
#define SIOCSBAUDRATE 0x300A #define SIOCSBAUDRATE 0x300A
#define SIOCSERRCOUNT 0x300B
#define SIOCSIFSETTINGS 0x300C
/* This is true until we have Ethernet support /* This is true until we have Ethernet support
* It is used to stop the netif queues before we have to return NETDEV_TX_BUSY * It is used to stop the netif queues before we have to return NETDEV_TX_BUSY
@@ -108,7 +101,6 @@ MODULE_VERSION(KO_VERSION);
#define KERNEL_SUPPORTS_ALIASES (LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0)) #define KERNEL_SUPPORTS_ALIASES (LINUX_VERSION_CODE >= KERNEL_VERSION(4,15,0))
#define KERNEL_DEFINES_VM_FAULT_T (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0)) #define KERNEL_DEFINES_VM_FAULT_T (LINUX_VERSION_CODE >= KERNEL_VERSION(4,17,0))
#define KERNEL_CAN_ECHO_TRACKS_LEN (LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0)) #define KERNEL_CAN_ECHO_TRACKS_LEN (LINUX_VERSION_CODE >= KERNEL_VERSION(5,12,0))
#define KERNEL_CAN_PRIV_FD (LINUX_VERSION_CODE >= KERNEL_VERSION(6,16,0))
#if KERNEL_DEFINES_VM_FAULT_T == 0 #if KERNEL_DEFINES_VM_FAULT_T == 0
typedef int vm_fault_t; typedef int vm_fault_t;
@@ -127,8 +119,36 @@ struct intrepid_netdevice {
int is_stopped; int is_stopped;
unsigned char *from_user; unsigned char *from_user;
uint8_t tx_idx; uint8_t tx_idx;
int bitrate_changed; /* for CAN only */
struct sk_buff *tx_skbs[MAX_TX]; int bitrate_changed;
struct can_bittiming_const bittiming_const;
struct can_bittiming_const data_bittiming_const;
struct can_berr_counter berr_counter;
};
#define ICS_MAGIC 0x49435343 // ICSC
struct add_can_if_info {
char alias[IFALIASZ];
u32 magic;
u32 ctrl_mode;
struct can_clock clock;
struct can_bittiming_const bittiming_const;
struct can_bittiming_const data_bittiming_const;
};
struct can_err_report {
int device;
enum can_state state;
struct can_berr_counter err_count;
};
struct can_dev_settings {
int device;
struct can_bittiming bittiming;
struct can_bittiming data_bittiming;
u32 ctrl_mode;
bool termination;
}; };
static int is_open; static int is_open;
@@ -147,6 +167,15 @@ static int tx_box_count[2];
static size_t tx_box_bytes[2]; static size_t tx_box_bytes[2];
static spinlock_t tx_box_lock; static spinlock_t tx_box_lock;
#define RX_BOX_SIZE (SHARED_MEM_SIZE / (MAX_NET_DEVICES * 2))
#define TX_BOX_SIZE (SHARED_MEM_SIZE / 4)
#define GET_RX_BOX(DEVICE_INDEX) \
(shared_mem + (RX_BOX_SIZE * DEVICE_INDEX))
#define GET_TX_BOX(BOX_INDEX) \
(shared_mem + (SHARED_MEM_SIZE / 2) + (BOX_INDEX * TX_BOX_SIZE))
#define MAX_TX (0x100)
#define DESC_OFFSET (2)
static uint16_t intrepid_next_tx_description( static uint16_t intrepid_next_tx_description(
struct intrepid_netdevice* ics, struct intrepid_netdevice* ics,
int* idx_out) int* idx_out)
@@ -217,6 +246,7 @@ static netdev_tx_t intrepid_CAN_netdevice_xmit(struct sk_buff *skb, struct net_d
struct canfd_frame *cf = (struct canfd_frame*)skb->data; struct canfd_frame *cf = (struct canfd_frame*)skb->data;
bool fd = can_is_canfd_skb(skb); bool fd = can_is_canfd_skb(skb);
bool needs_unlock = false; bool needs_unlock = false;
bool consumed = false;
int tx_idx; int tx_idx;
neomessage_can_t msg = {0}; neomessage_can_t msg = {0};
@@ -257,7 +287,6 @@ static netdev_tx_t intrepid_CAN_netdevice_xmit(struct sk_buff *skb, struct net_d
if (cf->can_id & CAN_RTR_FLAG) { if (cf->can_id & CAN_RTR_FLAG) {
if (unlikely(fd)) { if (unlikely(fd)) {
pr_info("intrepid: tried to send RTR frame on CANFD %s\n", dev->name); pr_info("intrepid: tried to send RTR frame on CANFD %s\n", dev->name);
kfree_skb(skb);
goto exit; goto exit;
} }
msg.status.remoteFrame = true; msg.status.remoteFrame = true;
@@ -281,6 +310,7 @@ static netdev_tx_t intrepid_CAN_netdevice_xmit(struct sk_buff *skb, struct net_d
, msg.length , msg.length
#endif #endif
); );
consumed = true;
/* Copy the message into the usermode box */ /* Copy the message into the usermode box */
memcpy(tx_boxes[current_tx_box] + tx_box_bytes[current_tx_box], &msg, sizeof(neomessage_can_t)); memcpy(tx_boxes[current_tx_box] + tx_box_bytes[current_tx_box], &msg, sizeof(neomessage_can_t));
@@ -293,6 +323,8 @@ static netdev_tx_t intrepid_CAN_netdevice_xmit(struct sk_buff *skb, struct net_d
if (intrepid_tx_box_no_space_for(sizeof(neomessage_can_t) + CANFD_MTU)) if (intrepid_tx_box_no_space_for(sizeof(neomessage_can_t) + CANFD_MTU))
intrepid_pause_all_queues(); intrepid_pause_all_queues();
exit: exit:
if (ret == NETDEV_TX_OK && !consumed)
consume_skb(skb);
wake_up_interruptible(&tx_wait); wake_up_interruptible(&tx_wait);
if (needs_unlock) if (needs_unlock)
spin_unlock_bh(&tx_box_lock); spin_unlock_bh(&tx_box_lock);
@@ -303,6 +335,7 @@ static netdev_tx_t intrepid_ETH_netdevice_xmit(struct sk_buff *skb, struct net_d
int ret = NETDEV_TX_OK; int ret = NETDEV_TX_OK;
struct intrepid_netdevice *ics = netdev_priv(dev); struct intrepid_netdevice *ics = netdev_priv(dev);
bool needs_unlock = false; bool needs_unlock = false;
bool consumed = false;
int tx_idx; int tx_idx;
neomessage_eth_t msg = {0}; neomessage_eth_t msg = {0};
@@ -332,11 +365,7 @@ static netdev_tx_t intrepid_ETH_netdevice_xmit(struct sk_buff *skb, struct net_d
goto exit; goto exit;
} }
msg.description = intrepid_next_tx_description(ics, &tx_idx); msg.description = intrepid_next_tx_description(ics, &tx_idx);
if (ics->tx_skbs[tx_idx]) { consumed = true;
kfree_skb(ics->tx_skbs[tx_idx]);
++dev->stats.tx_dropped;
}
ics->tx_skbs[tx_idx] = skb;
/* Copy the message into the usermode box */ /* Copy the message into the usermode box */
memcpy(tx_boxes[current_tx_box] + tx_box_bytes[current_tx_box], &msg, sizeof(neomessage_eth_t)); memcpy(tx_boxes[current_tx_box] + tx_box_bytes[current_tx_box], &msg, sizeof(neomessage_eth_t));
@@ -349,6 +378,8 @@ static netdev_tx_t intrepid_ETH_netdevice_xmit(struct sk_buff *skb, struct net_d
if (intrepid_tx_box_no_space_for(sizeof(neomessage_eth_t) + ETH_DATA_LEN)) if (intrepid_tx_box_no_space_for(sizeof(neomessage_eth_t) + ETH_DATA_LEN))
intrepid_pause_all_queues(); intrepid_pause_all_queues();
exit: exit:
if (ret == NETDEV_TX_OK && !consumed)
consume_skb(skb);
wake_up_interruptible(&tx_wait); wake_up_interruptible(&tx_wait);
if (needs_unlock) if (needs_unlock)
spin_unlock_bh(&tx_box_lock); spin_unlock_bh(&tx_box_lock);
@@ -364,13 +395,18 @@ static int intrepid_netdevice_stop(struct net_device *dev)
netif_carrier_off(dev); netif_carrier_off(dev);
spin_unlock_bh(&ics->lock); spin_unlock_bh(&ics->lock);
ics->can.state = CAN_STATE_STOPPED;
return 0; return 0;
} }
static int intrepid_netdevice_open(struct net_device *dev) static int intrepid_netdevice_open(struct net_device *dev)
{ {
struct intrepid_netdevice *ics = netdev_priv(dev);
netif_start_queue(dev); netif_start_queue(dev);
netif_carrier_on(dev); netif_carrier_on(dev);
ics->can.state = CAN_STATE_ERROR_ACTIVE;
return 0; return 0;
} }
@@ -416,8 +452,6 @@ static int intrepid_remove_can_if(int index)
unregister_candev(device); unregister_candev(device);
free_candev(device);
net_devices[index] = NULL; net_devices[index] = NULL;
pr_info("intrepid: Removed device %d\n", index); pr_info("intrepid: Removed device %d\n", index);
@@ -425,36 +459,6 @@ static int intrepid_remove_can_if(int index)
return 0; return 0;
} }
static int intrepid_set_bittiming(struct net_device *netdev)
{
struct intrepid_netdevice *dev = netdev_priv(netdev);
struct can_bittiming *bt = &dev->can.bittiming;
dev_dbg(&netdev->dev, "bitrate %d sample_point %d tq %d sjw %d phase1 %d phase2 %d prop %d brp %d",
bt->bitrate, bt->sample_point, bt->tq, bt->sjw, bt->phase_seg1, bt->phase_seg2, bt->prop_seg, bt->brp);
dev->bitrate_changed = 1;
wake_up_interruptible(&tx_wait);
return 0;
}
static int intrepid_set_data_bittiming(struct net_device *netdev)
{
struct intrepid_netdevice *dev = netdev_priv(netdev);
#if KERNEL_CAN_PRIV_FD
struct can_bittiming *bt = &dev->can.fd.data_bittiming;
#else
struct can_bittiming *bt = &dev->can.data_bittiming;
#endif
dev_dbg(&netdev->dev, "bitrate %d sample_point %d tq %d sjw %d phase1 %d phase2 %d prop %d brp %d",
bt->bitrate, bt->sample_point, bt->tq, bt->sjw, bt->phase_seg1, bt->phase_seg2, bt->prop_seg, bt->brp);
dev->bitrate_changed = 1;
wake_up_interruptible(&tx_wait);
return 0;
}
static int intrepid_bitrates[] = { static int intrepid_bitrates[] = {
20000, 20000,
33000, 33000,
@@ -491,12 +495,136 @@ static int intrepid_data_bitrates[] = {
10000000 10000000
}; };
static int intrepid_add_can_if(struct intrepid_netdevice **result, const char *requestedName) static const u16 intrepid_terminations[] = {
0,
50
};
static int intrepid_set_bittiming(struct net_device *netdev)
{
struct intrepid_netdevice *dev = netdev_priv(netdev);
struct can_bittiming *bt = &dev->can.bittiming;
dev_dbg(&netdev->dev, "bitrate %d sample_point %d tq %d sjw %d phase1 %d phase2 %d prop %d brp %d",
bt->bitrate, bt->sample_point, bt->tq, bt->sjw, bt->phase_seg1, bt->phase_seg2, bt->prop_seg, bt->brp);
dev->bitrate_changed = 1;
wake_up_interruptible(&tx_wait);
return 0;
}
static int intrepid_set_data_bittiming(struct net_device *netdev)
{
struct intrepid_netdevice *dev = netdev_priv(netdev);
struct can_bittiming *bt = &dev->can.data_bittiming;
dev_dbg(&netdev->dev, "bitrate %d sample_point %d tq %d sjw %d phase1 %d phase2 %d prop %d brp %d",
bt->bitrate, bt->sample_point, bt->tq, bt->sjw, bt->phase_seg1, bt->phase_seg2, bt->prop_seg, bt->brp);
dev->bitrate_changed = 1;
wake_up_interruptible(&tx_wait);
return 0;
}
static int intrepid_set_bittiming_v2(struct net_device *netdev)
{
/* nothing to do, kernel will inform userspace via netlink and the
* daemon will pick up the data from there */
return 0;
}
static int intrepid_set_termination(struct net_device *netdev, u16 termination)
{
/* nothing to do, kernel will inform userspace via netlink and the
* daemon will pick up the data from there */
return 0;
}
static int intrepid_get_berr_counter(const struct net_device *netdev, struct can_berr_counter *bec)
{
struct intrepid_netdevice *dev = netdev_priv(netdev);
*bec = dev->berr_counter;
return 0;
}
static int intrepid_handle_err_counts(struct can_err_report *err)
{
struct net_device *netdev = intrepid_get_dev_by_index(err->device);
struct intrepid_netdevice *dev = netdev_priv(netdev);
struct can_frame *cf;
struct sk_buff *skb;
netdev_info(netdev, "%s: tx_err: %d rx_err: %d, state: %d", __func__,
err->err_count.txerr, err->err_count.rxerr, err->state);
dev->berr_counter = err->err_count;
if (dev->can.state == err->state) {
return 0;
}
skb = alloc_can_err_skb(netdev, &cf);
switch (err->state) {
case CAN_STATE_ERROR_WARNING:
/* error warning state */
dev->can.can_stats.error_warning++;
dev->can.state = CAN_STATE_ERROR_WARNING;
if (skb) {
cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
cf->data[1] = (err->err_count.txerr > err->err_count.rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
cf->data[6] = err->err_count.txerr;
cf->data[7] = err->err_count.rxerr;
}
break;
case CAN_STATE_ERROR_PASSIVE:
/* error passive state */
dev->can.can_stats.error_passive++;
dev->can.state = CAN_STATE_ERROR_PASSIVE;
if (skb) {
cf->can_id |= CAN_ERR_CRTL | CAN_ERR_CNT;
cf->data[1] = (err->err_count.txerr > err->err_count.rxerr) ?
CAN_ERR_CRTL_TX_PASSIVE :
CAN_ERR_CRTL_RX_PASSIVE;
cf->data[6] = err->err_count.txerr;
cf->data[7] = err->err_count.rxerr;
}
break;
case CAN_STATE_BUS_OFF:
/* bus-off state */
dev->can.state = CAN_STATE_BUS_OFF;
dev->can.can_stats.bus_off++;
can_bus_off(netdev);
if (skb)
cf->can_id |= CAN_ERR_BUSOFF;
break;
default:
break;
}
if (skb)
netif_rx(skb);
return 0;
}
static int intrepid_handle_dev_settings(struct can_dev_settings *settings)
{
struct net_device *netdev = intrepid_get_dev_by_index(settings->device);
struct intrepid_netdevice *dev = netdev_priv(netdev);
dev->can.bittiming = settings->bittiming;
if (settings->data_bittiming.bitrate != 0)
dev->can.data_bittiming = settings->data_bittiming;
dev->can.ctrlmode = settings->ctrl_mode;
dev->can.termination = intrepid_terminations[settings->termination?1:0];
return 0;
}
static int intrepid_add_can_if(struct intrepid_netdevice **result, struct add_can_if_info *info)
{ {
// The `requestedName` parameter is always NULL if KERNEL_SUPPORTS_ALIASES is false
#if KERNEL_SUPPORTS_ALIASES
size_t aliasLen = 0; size_t aliasLen = 0;
#endif
int i; int i;
int ret = -EPERM; int ret = -EPERM;
struct net_device *dev = NULL; struct net_device *dev = NULL;
@@ -530,13 +658,13 @@ static int intrepid_add_can_if(struct intrepid_netdevice **result, const char *r
dev->mtu = CANFD_MTU; /* TODO: Check CAN-FD support from usermode daemon */ dev->mtu = CANFD_MTU; /* TODO: Check CAN-FD support from usermode daemon */
dev->netdev_ops = &intrepid_CAN_netdevice_ops; dev->netdev_ops = &intrepid_CAN_netdevice_ops;
#if KERNEL_SUPPORTS_ALIASES #if KERNEL_SUPPORTS_ALIASES
if (requestedName && ((aliasLen = strlen(requestedName)) > 0) && aliasLen < IFALIASZ) { if (((aliasLen = strlen(info->alias)) > 0) && aliasLen < IFALIASZ) {
dev->ifalias = kzalloc(sizeof(struct dev_ifalias) + aliasLen + 1, GFP_KERNEL); dev->ifalias = kzalloc(sizeof(struct dev_ifalias) + aliasLen + 1, GFP_KERNEL);
if (dev->ifalias == NULL) { if (dev->ifalias == NULL) {
pr_alert("intrepid: Could not allocate space for ifalias %zu\n", sizeof(struct dev_ifalias)); pr_alert("intrepid: Could not allocate space for ifalias %zu\n", sizeof(struct dev_ifalias));
} else { } else {
strncpy(dev->ifalias->ifalias, requestedName, aliasLen + 1); strncpy(dev->ifalias->ifalias, info->alias, aliasLen + 1);
pr_info("intrepid: %s alias set to %s\n", dev->name, requestedName); pr_info("intrepid: %s alias set to %s\n", dev->name, info->alias);
} }
} }
#endif #endif
@@ -546,22 +674,33 @@ static int intrepid_add_can_if(struct intrepid_netdevice **result, const char *r
ics->from_user = GET_RX_BOX(i); /* incoming rx messages */ ics->from_user = GET_RX_BOX(i); /* incoming rx messages */
ics->tx_idx = 0; ics->tx_idx = 0;
if (VER_MIN_FROM_INT(client_version) > 1) { if (VER_MIN_FROM_INT(client_version) > 2 && info->clock.freq) {
// client sent bittiming information
ics->bittiming_const = info->bittiming_const;
ics->data_bittiming_const = info->data_bittiming_const;
ics->can.clock.freq = info->clock.freq;
ics->can.bittiming_const = &ics->bittiming_const;
ics->can.data_bittiming_const = &ics->data_bittiming_const;
ics->can.termination_const = intrepid_terminations;
ics->can.termination_const_cnt = ARRAY_SIZE(intrepid_terminations);
ics->can.ctrlmode_supported = info->ctrl_mode;;
ics->can.do_set_termination = intrepid_set_termination;
ics->can.do_set_bittiming = intrepid_set_bittiming_v2;
ics->can.do_set_data_bittiming = intrepid_set_bittiming_v2;
ics->can.do_get_berr_counter = intrepid_get_berr_counter;
} else if (VER_MIN_FROM_INT(client_version) > 1) {
// no bittiming information, set static bitrates
ics->can.bitrate_const = intrepid_bitrates; ics->can.bitrate_const = intrepid_bitrates;
ics->can.bitrate_const_cnt = ARRAY_SIZE(intrepid_bitrates); ics->can.bitrate_const_cnt = ARRAY_SIZE(intrepid_bitrates);
ics->can.do_set_bittiming = intrepid_set_bittiming;
#if KERNEL_CAN_PRIV_FD
ics->can.fd.data_bitrate_const = intrepid_data_bitrates;
ics->can.fd.data_bitrate_const_cnt = ARRAY_SIZE(intrepid_data_bitrates);
ics->can.fd.do_set_data_bittiming = intrepid_set_data_bittiming;
#else
ics->can.data_bitrate_const = intrepid_data_bitrates; ics->can.data_bitrate_const = intrepid_data_bitrates;
ics->can.data_bitrate_const_cnt = ARRAY_SIZE(intrepid_data_bitrates); ics->can.data_bitrate_const_cnt = ARRAY_SIZE(intrepid_data_bitrates);
ics->can.do_set_bittiming = intrepid_set_bittiming;
ics->can.do_set_data_bittiming = intrepid_set_data_bittiming; ics->can.do_set_data_bittiming = intrepid_set_data_bittiming;
#endif ics->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
} else {
ics->can.ctrlmode_supported |= CAN_CTRLMODE_FD;
} }
ics->can.state = CAN_STATE_ERROR_ACTIVE;
ics->can.ctrlmode_supported = CAN_CTRLMODE_FD;
spin_lock_init(&ics->lock); spin_lock_init(&ics->lock);
@@ -710,12 +849,10 @@ static bool handle_CAN_transmit_receipt(
} }
static bool handle_ETH_transmit_receipt( static bool handle_ETH_transmit_receipt(
struct net_device *device,
const neomessage_eth_t *msg, const neomessage_eth_t *msg,
const uint8_t *data, const uint8_t *data,
struct net_device_stats *stats) struct net_device_stats *stats)
{ {
struct intrepid_netdevice *ics = netdev_priv(device);
int tx_idx; int tx_idx;
if (!msg->status.transmitMessage) { if (!msg->status.transmitMessage) {
@@ -731,14 +868,11 @@ static bool handle_ETH_transmit_receipt(
/* unsuccessful transmits */ /* unsuccessful transmits */
if (msg->status.globalError) { if (msg->status.globalError) {
kfree_skb(ics->tx_skbs[tx_idx]); struct sk_buff *skb;
ics->tx_skbs[tx_idx] = NULL; kfree_skb(&skb[tx_idx]);
return false; return false;
} }
dev_kfree_skb(ics->tx_skbs[tx_idx]);
ics->tx_skbs[tx_idx] = NULL;
stats->tx_packets++; stats->tx_packets++;
stats->tx_bytes += msg->length; stats->tx_bytes += msg->length;
@@ -756,18 +890,8 @@ static int intrepid_remove_eth_if(int index)
pr_info("intrepid: Removing device %d %s 0x%p\n", index, device->name, device); pr_info("intrepid: Removing device %d %s 0x%p\n", index, device->name, device);
struct intrepid_netdevice *ics = netdev_priv(device);
for (size_t i = 0; i < MAX_TX; ++i) {
if (ics->tx_skbs[i]) {
kfree_skb(ics->tx_skbs[i]);
}
}
unregister_netdev(device); unregister_netdev(device);
free_netdev(device);
net_devices[index] = NULL; net_devices[index] = NULL;
pr_info("intrepid: Removed device %d\n", index); pr_info("intrepid: Removed device %d\n", index);
@@ -943,7 +1067,7 @@ static struct sk_buff *intrepid_skb_from_neomessage(
case ICSNEO_NETWORK_TYPE_ETHERNET: case ICSNEO_NETWORK_TYPE_ETHERNET:
{ {
const neomessage_eth_t *msg = (const neomessage_eth_t*)msg_generic; const neomessage_eth_t *msg = (const neomessage_eth_t*)msg_generic;
if (handle_ETH_transmit_receipt(device, msg, data, stats)) if (handle_ETH_transmit_receipt(msg, data, stats))
goto out; goto out;
skb = netdev_alloc_skb_ip_align(device, msg->length); skb = netdev_alloc_skb_ip_align(device, msg->length);
if (unlikely(skb == NULL)) { if (unlikely(skb == NULL)) {
@@ -1023,20 +1147,31 @@ static long intrepid_dev_ioctl(struct file *fp, unsigned int cmd, unsigned long
switch(cmd) { switch(cmd) {
case SIOCSADDCANIF: { case SIOCSADDCANIF: {
struct intrepid_netdevice *result = NULL; struct intrepid_netdevice *result = NULL;
struct add_can_if_info info = {};
if (VER_MIN_FROM_INT(client_version) < 3) {
#if KERNEL_SUPPORTS_ALIASES #if KERNEL_SUPPORTS_ALIASES
char requestedNameBuffer[IFALIASZ] = {0}; if ((void __user*)arg != NULL) {
char* requestedName = NULL; if (copy_from_user(info.alias, (void __user*)arg, IFALIASZ) != 0)
int bytesNotCopied = 0; pr_warn("intrepid: Unabe to copy alias");
if ((void __user*)arg != NULL) { }
bytesNotCopied = copy_from_user(requestedNameBuffer, (void __user*)arg, IFALIASZ);
if (bytesNotCopied != 0)
pr_warn("intrepid: %d bytes not copied for alias", bytesNotCopied);
requestedName = requestedNameBuffer;
}
ret = intrepid_add_can_if(&result, requestedName);
#else
ret = intrepid_add_can_if(&result, NULL);
#endif #endif
} else {
if ((void __user*)arg == NULL) {
ret = -EINVAL;
break;
}
if (copy_from_user(&info, (void __user*)arg, sizeof(info)) != 0) {
pr_warn("intrepid: Unable to copy data");
ret = -EINVAL;
break;
}
if (info.magic != ICS_MAGIC) {
pr_warn("intrepid: Invalid data");
ret = -EINVAL;
break;
}
}
ret = intrepid_add_can_if(&result, &info);
break; break;
} }
case SIOCSREMOVECANIF: case SIOCSREMOVECANIF:
@@ -1055,11 +1190,32 @@ static long intrepid_dev_ioctl(struct file *fp, unsigned int cmd, unsigned long
break; break;
struct intrepid_netdevice *ics = netdev_priv(device); struct intrepid_netdevice *ics = netdev_priv(device);
ics->can.bittiming.bitrate = info.baudrates[0]; ics->can.bittiming.bitrate = info.baudrates[0];
#if KERNEL_CAN_PRIV_FD
ics->can.fd.data_bittiming.bitrate = info.baudrates[1];
#else
ics->can.data_bittiming.bitrate = info.baudrates[1]; ics->can.data_bittiming.bitrate = info.baudrates[1];
#endif break;
}
case SIOCGIFINDEX: {
struct net_device *device = intrepid_get_dev_by_index(arg);
if (! device) {
ret = -ENODEV;
break;
}
ret = device->ifindex;
break;
}
case SIOCSERRCOUNT: {
struct can_err_report err;
ret = copy_from_user(&err, (void __user*)arg, sizeof(err));
if (ret)
break;
ret = intrepid_handle_err_counts(&err);
break;
}
case SIOCSIFSETTINGS: {
struct can_dev_settings settings;
ret = copy_from_user(&settings, (void __user*)arg, sizeof(settings));
if (ret)
break;
ret = intrepid_handle_dev_settings(&settings);
break; break;
} }
case SIOCSADDETHIF: { case SIOCSADDETHIF: {
@@ -1189,11 +1345,7 @@ static int check_bitrate_change(struct intrepid_pending_tx_info *info)
if (ics->bitrate_changed) { if (ics->bitrate_changed) {
info->tx_box_index = -(i + 1); info->tx_box_index = -(i + 1);
info->count = ics->can.bittiming.bitrate; info->count = ics->can.bittiming.bitrate;
#if KERNEL_CAN_PRIV_FD
info->bytes = ics->can.fd.data_bittiming.bitrate;
#else
info->bytes = ics->can.data_bittiming.bitrate; info->bytes = ics->can.data_bittiming.bitrate;
#endif
ics->bitrate_changed = 0; ics->bitrate_changed = 0;
return 1; return 1;
} }