Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 48 additions & 5 deletions intrepid.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ MODULE_VERSION(KO_VERSION);
#define SIOCGCLIENTVEROK 0x3009
#define SIOCSBAUDRATE 0x300A

/* Flag bit encoded into intrepid_pending_tx_info.count when reporting a
* settings change to the usermode daemon (tx_box_index < 0). The low bits
* carry the arbitration bitrate, which bitrate_const caps at 1 Mbit/s, so
* the flag cannot collide with a real bitrate value. Only sent to daemons
* that announce v3.2+ via SIOCGCLIENTVEROK.
*/
#define INTREPID_BITRATE_FLAG_LISTENONLY BIT(30)

/* This is true until we have Ethernet support
* It is used to stop the netif queues before we have to return NETDEV_TX_BUSY
*/
Expand Down Expand Up @@ -128,6 +136,8 @@ struct intrepid_netdevice {
unsigned char *from_user;
uint8_t tx_idx;
int bitrate_changed;
u32 last_reported_bitrate;
int last_reported_listenonly;
struct sk_buff *tx_skbs[MAX_TX];
};

Expand Down Expand Up @@ -369,6 +379,26 @@ static int intrepid_netdevice_stop(struct net_device *dev)

static int intrepid_netdevice_open(struct net_device *dev)
{
/* can_changelink() stores ctrlmode changes (e.g. listen-only) without
* calling into the driver, and requires the interface to be down, so
* ndo_open is the point where the accumulated CAN configuration is
* final. Report it to the usermode daemon, but only when it differs
* from what the daemon was already told, so repeated ifup/ifdown
* cycles do not re-apply unchanged settings to the hardware.
*/
if (dev->type == ARPHRD_CAN && VER_MIN_FROM_INT(client_version) > 1) {
struct intrepid_netdevice *ics = netdev_priv(dev);
u32 bitrate = ics->can.bittiming.bitrate;
int listenonly = (ics->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) ? 1 : 0;

if (bitrate != 0 &&
(bitrate != ics->last_reported_bitrate ||
listenonly != ics->last_reported_listenonly)) {
WRITE_ONCE(ics->bitrate_changed, 1);
wake_up_interruptible(&tx_wait);
}
}

netif_start_queue(dev);
netif_carrier_on(dev);
return 0;
Expand Down Expand Up @@ -433,7 +463,7 @@ static int intrepid_set_bittiming(struct net_device *netdev)
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;
WRITE_ONCE(dev->bitrate_changed, 1);
wake_up_interruptible(&tx_wait);
return 0;
}
Expand All @@ -450,7 +480,7 @@ static int intrepid_set_data_bittiming(struct net_device *netdev)
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;
WRITE_ONCE(dev->bitrate_changed, 1);
wake_up_interruptible(&tx_wait);
return 0;
}
Expand Down Expand Up @@ -562,6 +592,8 @@ static int intrepid_add_can_if(struct intrepid_netdevice **result, const char *r
}
ics->can.state = CAN_STATE_ERROR_ACTIVE;
ics->can.ctrlmode_supported = CAN_CTRLMODE_FD;
if (VER_MIN_FROM_INT(client_version) > 1)
ics->can.ctrlmode_supported |= CAN_CTRLMODE_LISTENONLY;

spin_lock_init(&ics->lock);

Expand Down Expand Up @@ -1060,6 +1092,12 @@ static long intrepid_dev_ioctl(struct file *fp, unsigned int cmd, unsigned long
#else
ics->can.data_bittiming.bitrate = info.baudrates[1];
#endif
/* Values seeded by the daemon are already applied to the
* hardware; record them so the next ifup does not
* re-report an unchanged configuration.
*/
ics->last_reported_bitrate = info.baudrates[0];
ics->last_reported_listenonly = 0;
break;
}
case SIOCSADDETHIF: {
Expand Down Expand Up @@ -1186,15 +1224,20 @@ static int check_bitrate_change(struct intrepid_pending_tx_info *info)
continue;
ics = netdev_priv(net_devices[i]);

if (ics->bitrate_changed) {
if (xchg(&ics->bitrate_changed, 0)) {
info->tx_box_index = -(i + 1);
info->count = ics->can.bittiming.bitrate;
ics->last_reported_bitrate = ics->can.bittiming.bitrate;
ics->last_reported_listenonly = 0;
if (ics->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
info->count |= INTREPID_BITRATE_FLAG_LISTENONLY;
ics->last_reported_listenonly = 1;
}
#if KERNEL_CAN_PRIV_FD
info->bytes = ics->can.fd.data_bittiming.bitrate;
#else
info->bytes = ics->can.data_bittiming.bitrate;
#endif
ics->bitrate_changed = 0;
return 1;
}
}
Expand Down Expand Up @@ -1263,7 +1306,7 @@ static unsigned int intrepid_dev_poll(struct file *fp, poll_table *wait)
continue;
struct intrepid_netdevice *ics = netdev_priv(net_devices[i]);

if (ics->bitrate_changed)
if (READ_ONCE(ics->bitrate_changed))
return POLLIN | POLLRDNORM;
}
}
Expand Down