Skip to content

Commit 4ea41f8

Browse files
committed
Merge tag 'linux-can-fixes-for-4.16-20180314' of ssh://gitolite.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can
Marc Kleine-Budde says: ==================== pull-request: can 2018-03-14 this is a pull request of two patches for net/master. Both patches are by Andri Yngvason and fix problems in the cc770 driver, that show up quite fast on RT systems, but also on non RT setups. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents ea91df6 + 7462012 commit 4ea41f8

File tree

2 files changed

+65
-40
lines changed

2 files changed

+65
-40
lines changed

drivers/net/can/cc770/cc770.c

Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -390,37 +390,23 @@ static int cc770_get_berr_counter(const struct net_device *dev,
390390
return 0;
391391
}
392392

393-
static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
393+
static void cc770_tx(struct net_device *dev, int mo)
394394
{
395395
struct cc770_priv *priv = netdev_priv(dev);
396-
struct net_device_stats *stats = &dev->stats;
397-
struct can_frame *cf = (struct can_frame *)skb->data;
398-
unsigned int mo = obj2msgobj(CC770_OBJ_TX);
396+
struct can_frame *cf = (struct can_frame *)priv->tx_skb->data;
399397
u8 dlc, rtr;
400398
u32 id;
401399
int i;
402400

403-
if (can_dropped_invalid_skb(dev, skb))
404-
return NETDEV_TX_OK;
405-
406-
if ((cc770_read_reg(priv,
407-
msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) {
408-
netdev_err(dev, "TX register is still occupied!\n");
409-
return NETDEV_TX_BUSY;
410-
}
411-
412-
netif_stop_queue(dev);
413-
414401
dlc = cf->can_dlc;
415402
id = cf->can_id;
416-
if (cf->can_id & CAN_RTR_FLAG)
417-
rtr = 0;
418-
else
419-
rtr = MSGCFG_DIR;
403+
rtr = cf->can_id & CAN_RTR_FLAG ? 0 : MSGCFG_DIR;
404+
405+
cc770_write_reg(priv, msgobj[mo].ctrl0,
406+
MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
420407
cc770_write_reg(priv, msgobj[mo].ctrl1,
421408
RMTPND_RES | TXRQST_RES | CPUUPD_SET | NEWDAT_RES);
422-
cc770_write_reg(priv, msgobj[mo].ctrl0,
423-
MSGVAL_SET | TXIE_SET | RXIE_RES | INTPND_RES);
409+
424410
if (id & CAN_EFF_FLAG) {
425411
id &= CAN_EFF_MASK;
426412
cc770_write_reg(priv, msgobj[mo].config,
@@ -439,22 +425,30 @@ static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
439425
for (i = 0; i < dlc; i++)
440426
cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]);
441427

442-
/* Store echo skb before starting the transfer */
443-
can_put_echo_skb(skb, dev, 0);
444-
445428
cc770_write_reg(priv, msgobj[mo].ctrl1,
446-
RMTPND_RES | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);
429+
RMTPND_UNC | TXRQST_SET | CPUUPD_RES | NEWDAT_UNC);
430+
cc770_write_reg(priv, msgobj[mo].ctrl0,
431+
MSGVAL_SET | TXIE_SET | RXIE_SET | INTPND_UNC);
432+
}
447433

448-
stats->tx_bytes += dlc;
434+
static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev)
435+
{
436+
struct cc770_priv *priv = netdev_priv(dev);
437+
unsigned int mo = obj2msgobj(CC770_OBJ_TX);
449438

439+
if (can_dropped_invalid_skb(dev, skb))
440+
return NETDEV_TX_OK;
450441

451-
/*
452-
* HM: We had some cases of repeated IRQs so make sure the
453-
* INT is acknowledged I know it's already further up, but
454-
* doing again fixed the issue
455-
*/
456-
cc770_write_reg(priv, msgobj[mo].ctrl0,
457-
MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES);
442+
netif_stop_queue(dev);
443+
444+
if ((cc770_read_reg(priv,
445+
msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) {
446+
netdev_err(dev, "TX register is still occupied!\n");
447+
return NETDEV_TX_BUSY;
448+
}
449+
450+
priv->tx_skb = skb;
451+
cc770_tx(dev, mo);
458452

459453
return NETDEV_TX_OK;
460454
}
@@ -680,19 +674,47 @@ static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
680674
struct cc770_priv *priv = netdev_priv(dev);
681675
struct net_device_stats *stats = &dev->stats;
682676
unsigned int mo = obj2msgobj(o);
677+
struct can_frame *cf;
678+
u8 ctrl1;
679+
680+
ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
683681

684-
/* Nothing more to send, switch off interrupts */
685682
cc770_write_reg(priv, msgobj[mo].ctrl0,
686683
MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
687-
/*
688-
* We had some cases of repeated IRQ so make sure the
689-
* INT is acknowledged
684+
cc770_write_reg(priv, msgobj[mo].ctrl1,
685+
RMTPND_RES | TXRQST_RES | MSGLST_RES | NEWDAT_RES);
686+
687+
if (unlikely(!priv->tx_skb)) {
688+
netdev_err(dev, "missing tx skb in tx interrupt\n");
689+
return;
690+
}
691+
692+
if (unlikely(ctrl1 & MSGLST_SET)) {
693+
stats->rx_over_errors++;
694+
stats->rx_errors++;
695+
}
696+
697+
/* When the CC770 is sending an RTR message and it receives a regular
698+
* message that matches the id of the RTR message, it will overwrite the
699+
* outgoing message in the TX register. When this happens we must
700+
* process the received message and try to transmit the outgoing skb
701+
* again.
690702
*/
691-
cc770_write_reg(priv, msgobj[mo].ctrl0,
692-
MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES);
703+
if (unlikely(ctrl1 & NEWDAT_SET)) {
704+
cc770_rx(dev, mo, ctrl1);
705+
cc770_tx(dev, mo);
706+
return;
707+
}
693708

694-
stats->tx_packets++;
709+
can_put_echo_skb(priv->tx_skb, dev, 0);
695710
can_get_echo_skb(dev, 0);
711+
712+
cf = (struct can_frame *)priv->tx_skb->data;
713+
stats->tx_bytes += cf->can_dlc;
714+
stats->tx_packets++;
715+
716+
priv->tx_skb = NULL;
717+
696718
netif_wake_queue(dev);
697719
}
698720

@@ -804,6 +826,7 @@ struct net_device *alloc_cc770dev(int sizeof_priv)
804826
priv->can.do_set_bittiming = cc770_set_bittiming;
805827
priv->can.do_set_mode = cc770_set_mode;
806828
priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
829+
priv->tx_skb = NULL;
807830

808831
memcpy(priv->obj_flags, cc770_obj_flags, sizeof(cc770_obj_flags));
809832

drivers/net/can/cc770/cc770.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ struct cc770_priv {
193193
u8 cpu_interface; /* CPU interface register */
194194
u8 clkout; /* Clock out register */
195195
u8 bus_config; /* Bus conffiguration register */
196+
197+
struct sk_buff *tx_skb;
196198
};
197199

198200
struct net_device *alloc_cc770dev(int sizeof_priv);

0 commit comments

Comments
 (0)