diff options
Diffstat (limited to 'drivers/net/can/spi/mcp251x.c')
-rw-r--r-- | drivers/net/can/spi/mcp251x.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index 025e07cb7439..79c4bab5f724 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -22,11 +22,11 @@ #include <linux/bitfield.h> #include <linux/can/core.h> #include <linux/can/dev.h> -#include <linux/can/led.h> #include <linux/clk.h> #include <linux/completion.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/ethtool.h> #include <linux/freezer.h> #include <linux/gpio.h> #include <linux/gpio/driver.h> @@ -738,9 +738,7 @@ static void mcp251x_hw_rx(struct spi_device *spi, int buf_idx) } priv->net->stats.rx_packets++; - can_led_event(priv->net, CAN_LED_EVENT_RX); - - netif_rx_ni(skb); + netif_rx(skb); } static void mcp251x_hw_sleep(struct spi_device *spi) @@ -791,7 +789,7 @@ static netdev_tx_t mcp251x_hard_start_xmit(struct sk_buff *skb, return NETDEV_TX_BUSY; } - if (can_dropped_invalid_skb(net, skb)) + if (can_dev_dropped_skb(net, skb)) return NETDEV_TX_OK; netif_stop_queue(net); @@ -973,8 +971,6 @@ static int mcp251x_stop(struct net_device *net) mutex_unlock(&priv->mcp_lock); - can_led_event(net, CAN_LED_EVENT_STOP); - return 0; } @@ -987,7 +983,7 @@ static void mcp251x_error_skb(struct net_device *net, int can_id, int data1) if (skb) { frame->can_id |= can_id; frame->data[1] = data1; - netif_rx_ni(skb); + netif_rx(skb); } else { netdev_err(net, "cannot allocate error skb\n"); } @@ -1074,9 +1070,6 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) mcp251x_read_2regs(spi, CANINTF, &intf, &eflag); - /* mask out flags we don't care about */ - intf &= CANINTF_RX | CANINTF_TX | CANINTF_ERR; - /* receive buffer 0 */ if (intf & CANINTF_RX0IF) { mcp251x_hw_rx(spi, 0); @@ -1086,6 +1079,18 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) if (mcp251x_is_2510(spi)) mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00); + + /* check if buffer 1 is already known to be full, no need to re-read */ + if (!(intf & CANINTF_RX1IF)) { + u8 intf1, eflag1; + + /* intf needs to be read again to avoid a race condition */ + mcp251x_read_2regs(spi, CANINTF, &intf1, &eflag1); + + /* combine flags from both operations for error handling */ + intf |= intf1; + eflag |= eflag1; + } } /* receive buffer 1 */ @@ -1096,6 +1101,9 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) clear_intf |= CANINTF_RX1IF; } + /* mask out flags we don't care about */ + intf &= CANINTF_RX | CANINTF_TX | CANINTF_ERR; + /* any error or tx interrupt we need to clear? */ if (intf & (CANINTF_ERR | CANINTF_TX)) clear_intf |= intf & (CANINTF_ERR | CANINTF_TX); @@ -1177,7 +1185,6 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) break; if (intf & CANINTF_TX) { - can_led_event(net, CAN_LED_EVENT_TX); if (priv->tx_busy) { net->stats.tx_packets++; net->stats.tx_bytes += can_get_echo_skb(net, 0, @@ -1232,8 +1239,6 @@ static int mcp251x_open(struct net_device *net) if (ret) goto out_free_irq; - can_led_event(net, CAN_LED_EVENT_OPEN); - netif_wake_queue(net); mutex_unlock(&priv->mcp_lock); @@ -1256,6 +1261,10 @@ static const struct net_device_ops mcp251x_netdev_ops = { .ndo_change_mtu = can_change_mtu, }; +static const struct ethtool_ops mcp251x_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, +}; + static const struct of_device_id mcp251x_of_match[] = { { .compatible = "microchip,mcp2510", @@ -1321,6 +1330,7 @@ static int mcp251x_can_probe(struct spi_device *spi) goto out_free; net->netdev_ops = &mcp251x_netdev_ops; + net->ethtool_ops = &mcp251x_ethtool_ops; net->flags |= IFF_ECHO; priv = netdev_priv(net); @@ -1403,15 +1413,16 @@ static int mcp251x_can_probe(struct spi_device *spi) if (ret) goto error_probe; - devm_can_led_init(net); - ret = mcp251x_gpio_setup(priv); if (ret) - goto error_probe; + goto out_unregister_candev; netdev_info(net, "MCP%x successfully initialized.\n", priv->model); return 0; +out_unregister_candev: + unregister_candev(net); + error_probe: destroy_workqueue(priv->wq); priv->wq = NULL; @@ -1427,7 +1438,7 @@ out_free: return ret; } -static int mcp251x_can_remove(struct spi_device *spi) +static void mcp251x_can_remove(struct spi_device *spi) { struct mcp251x_priv *priv = spi_get_drvdata(spi); struct net_device *net = priv->net; @@ -1442,8 +1453,6 @@ static int mcp251x_can_remove(struct spi_device *spi) clk_disable_unprepare(priv->clk); free_candev(net); - - return 0; } static int __maybe_unused mcp251x_can_suspend(struct device *dev) |