aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-03-14 13:50:47 -0400
committerDavid S. Miller <davem@davemloft.net>2018-03-14 13:50:47 -0400
commit4ea41f829a69828565b75515a091b394d5dc5116 (patch)
tree0e408fb22ba5389b2e655d1200023d4031222478
parentea91df6d8a55836c7401eb6d5d4d828b659d8d67 (diff)
parent746201235b3f876792099079f4c6fea941d76183 (diff)
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 <davem@davemloft.net>
-rw-r--r--drivers/net/can/cc770/cc770.c103
-rw-r--r--drivers/net/can/cc770/cc770.h2
2 files changed, 65 insertions, 40 deletions
diff --git a/drivers/net/can/cc770/cc770.c b/drivers/net/can/cc770/cc770.c
index 1e37313054f3..2743d82d4424 100644
--- a/drivers/net/can/cc770/cc770.c
+++ b/drivers/net/can/cc770/cc770.c
@@ -390,37 +390,23 @@ static int cc770_get_berr_counter(const struct net_device *dev,
390 return 0; 390 return 0;
391} 391}
392 392
393static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev) 393static void cc770_tx(struct net_device *dev, int mo)
394{ 394{
395 struct cc770_priv *priv = netdev_priv(dev); 395 struct cc770_priv *priv = netdev_priv(dev);
396 struct net_device_stats *stats = &dev->stats; 396 struct can_frame *cf = (struct can_frame *)priv->tx_skb->data;
397 struct can_frame *cf = (struct can_frame *)skb->data;
398 unsigned int mo = obj2msgobj(CC770_OBJ_TX);
399 u8 dlc, rtr; 397 u8 dlc, rtr;
400 u32 id; 398 u32 id;
401 int i; 399 int i;
402 400
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
414 dlc = cf->can_dlc; 401 dlc = cf->can_dlc;
415 id = cf->can_id; 402 id = cf->can_id;
416 if (cf->can_id & CAN_RTR_FLAG) 403 rtr = cf->can_id & CAN_RTR_FLAG ? 0 : MSGCFG_DIR;
417 rtr = 0; 404
418 else 405 cc770_write_reg(priv, msgobj[mo].ctrl0,
419 rtr = MSGCFG_DIR; 406 MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
420 cc770_write_reg(priv, msgobj[mo].ctrl1, 407 cc770_write_reg(priv, msgobj[mo].ctrl1,
421 RMTPND_RES | TXRQST_RES | CPUUPD_SET | NEWDAT_RES); 408 RMTPND_RES | TXRQST_RES | CPUUPD_SET | NEWDAT_RES);
422 cc770_write_reg(priv, msgobj[mo].ctrl0, 409
423 MSGVAL_SET | TXIE_SET | RXIE_RES | INTPND_RES);
424 if (id & CAN_EFF_FLAG) { 410 if (id & CAN_EFF_FLAG) {
425 id &= CAN_EFF_MASK; 411 id &= CAN_EFF_MASK;
426 cc770_write_reg(priv, msgobj[mo].config, 412 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)
439 for (i = 0; i < dlc; i++) 425 for (i = 0; i < dlc; i++)
440 cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]); 426 cc770_write_reg(priv, msgobj[mo].data[i], cf->data[i]);
441 427
442 /* Store echo skb before starting the transfer */
443 can_put_echo_skb(skb, dev, 0);
444
445 cc770_write_reg(priv, msgobj[mo].ctrl1, 428 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}
447 433
448 stats->tx_bytes += dlc; 434static 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);
449 438
439 if (can_dropped_invalid_skb(dev, skb))
440 return NETDEV_TX_OK;
450 441
451 /* 442 netif_stop_queue(dev);
452 * HM: We had some cases of repeated IRQs so make sure the 443
453 * INT is acknowledged I know it's already further up, but 444 if ((cc770_read_reg(priv,
454 * doing again fixed the issue 445 msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) {
455 */ 446 netdev_err(dev, "TX register is still occupied!\n");
456 cc770_write_reg(priv, msgobj[mo].ctrl0, 447 return NETDEV_TX_BUSY;
457 MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES); 448 }
449
450 priv->tx_skb = skb;
451 cc770_tx(dev, mo);
458 452
459 return NETDEV_TX_OK; 453 return NETDEV_TX_OK;
460} 454}
@@ -680,19 +674,47 @@ static void cc770_tx_interrupt(struct net_device *dev, unsigned int o)
680 struct cc770_priv *priv = netdev_priv(dev); 674 struct cc770_priv *priv = netdev_priv(dev);
681 struct net_device_stats *stats = &dev->stats; 675 struct net_device_stats *stats = &dev->stats;
682 unsigned int mo = obj2msgobj(o); 676 unsigned int mo = obj2msgobj(o);
677 struct can_frame *cf;
678 u8 ctrl1;
679
680 ctrl1 = cc770_read_reg(priv, msgobj[mo].ctrl1);
683 681
684 /* Nothing more to send, switch off interrupts */
685 cc770_write_reg(priv, msgobj[mo].ctrl0, 682 cc770_write_reg(priv, msgobj[mo].ctrl0,
686 MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES); 683 MSGVAL_RES | TXIE_RES | RXIE_RES | INTPND_RES);
687 /* 684 cc770_write_reg(priv, msgobj[mo].ctrl1,
688 * We had some cases of repeated IRQ so make sure the 685 RMTPND_RES | TXRQST_RES | MSGLST_RES | NEWDAT_RES);
689 * INT is acknowledged 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.
690 */ 702 */
691 cc770_write_reg(priv, msgobj[mo].ctrl0, 703 if (unlikely(ctrl1 & NEWDAT_SET)) {
692 MSGVAL_UNC | TXIE_UNC | RXIE_UNC | INTPND_RES); 704 cc770_rx(dev, mo, ctrl1);
705 cc770_tx(dev, mo);
706 return;
707 }
693 708
694 stats->tx_packets++; 709 can_put_echo_skb(priv->tx_skb, dev, 0);
695 can_get_echo_skb(dev, 0); 710 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
696 netif_wake_queue(dev); 718 netif_wake_queue(dev);
697} 719}
698 720
@@ -804,6 +826,7 @@ struct net_device *alloc_cc770dev(int sizeof_priv)
804 priv->can.do_set_bittiming = cc770_set_bittiming; 826 priv->can.do_set_bittiming = cc770_set_bittiming;
805 priv->can.do_set_mode = cc770_set_mode; 827 priv->can.do_set_mode = cc770_set_mode;
806 priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES; 828 priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES;
829 priv->tx_skb = NULL;
807 830
808 memcpy(priv->obj_flags, cc770_obj_flags, sizeof(cc770_obj_flags)); 831 memcpy(priv->obj_flags, cc770_obj_flags, sizeof(cc770_obj_flags));
809 832
diff --git a/drivers/net/can/cc770/cc770.h b/drivers/net/can/cc770/cc770.h
index a1739db98d91..95752e1d1283 100644
--- a/drivers/net/can/cc770/cc770.h
+++ b/drivers/net/can/cc770/cc770.h
@@ -193,6 +193,8 @@ struct cc770_priv {
193 u8 cpu_interface; /* CPU interface register */ 193 u8 cpu_interface; /* CPU interface register */
194 u8 clkout; /* Clock out register */ 194 u8 clkout; /* Clock out register */
195 u8 bus_config; /* Bus conffiguration register */ 195 u8 bus_config; /* Bus conffiguration register */
196
197 struct sk_buff *tx_skb;
196}; 198};
197 199
198struct net_device *alloc_cc770dev(int sizeof_priv); 200struct net_device *alloc_cc770dev(int sizeof_priv);