diff options
Diffstat (limited to 'drivers/net/can/mscan/mscan.c')
| -rw-r--r-- | drivers/net/can/mscan/mscan.c | 113 |
1 files changed, 47 insertions, 66 deletions
diff --git a/drivers/net/can/mscan/mscan.c b/drivers/net/can/mscan/mscan.c index acb708fc1463..39c7aa2a0b2f 100644 --- a/drivers/net/can/mscan/mscan.c +++ b/drivers/net/can/mscan/mscan.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * CAN bus driver for the alone generic (as possible as) MSCAN controller. * @@ -5,18 +6,6 @@ * Varma Electronics Oy * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com> * Copyright (C) 2008-2009 Pengutronix <kernel@pengutronix.de> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the version 2 of the GNU General Public License - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include <linux/kernel.h> @@ -45,12 +34,6 @@ static const struct can_bittiming_const mscan_bittiming_const = { .brp_inc = 1, }; -struct mscan_state { - u8 mode; - u8 canrier; - u8 cantier; -}; - static enum can_state state_map[] = { CAN_STATE_ERROR_ACTIVE, CAN_STATE_ERROR_WARNING, @@ -202,7 +185,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) int i, rtr, buf_id; u32 can_id; - if (can_dropped_invalid_skb(dev, skb)) + if (can_dev_dropped_skb(dev, skb)) return NETDEV_TX_OK; out_8(®s->cantier, 0); @@ -220,6 +203,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) * since buffer with lower id have higher priority (hell..) */ netif_stop_queue(dev); + fallthrough; case 2: if (buf_id < priv->prev_buf_id) { priv->cur_pri++; @@ -260,16 +244,16 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) void __iomem *data = ®s->tx.dsr1_0; u16 *payload = (u16 *)frame->data; - for (i = 0; i < frame->can_dlc / 2; i++) { + for (i = 0; i < frame->len / 2; i++) { out_be16(data, *payload++); data += 2 + _MSCAN_RESERVED_DSR_SIZE; } /* write remaining byte if necessary */ - if (frame->can_dlc & 1) - out_8(data, frame->data[frame->can_dlc - 1]); + if (frame->len & 1) + out_8(data, frame->data[frame->len - 1]); } - out_8(®s->tx.dlr, frame->can_dlc); + out_8(®s->tx.dlr, frame->len); out_8(®s->tx.tbpr, priv->cur_pri); /* Start transmission. */ @@ -280,7 +264,7 @@ static netdev_tx_t mscan_start_xmit(struct sk_buff *skb, struct net_device *dev) list_add_tail(&priv->tx_queue[buf_id].list, &priv->tx_head); - can_put_echo_skb(skb, dev, buf_id); + can_put_echo_skb(skb, dev, buf_id, 0); /* Enable interrupt. */ priv->tx_active |= 1 << buf_id; @@ -322,19 +306,19 @@ static void mscan_get_rx_frame(struct net_device *dev, struct can_frame *frame) if (can_id & 1) frame->can_id |= CAN_RTR_FLAG; - frame->can_dlc = get_can_dlc(in_8(®s->rx.dlr) & 0xf); + frame->len = can_cc_dlc2len(in_8(®s->rx.dlr) & 0xf); if (!(frame->can_id & CAN_RTR_FLAG)) { void __iomem *data = ®s->rx.dsr1_0; u16 *payload = (u16 *)frame->data; - for (i = 0; i < frame->can_dlc / 2; i++) { + for (i = 0; i < frame->len / 2; i++) { *payload++ = in_be16(data); data += 2 + _MSCAN_RESERVED_DSR_SIZE; } /* read remaining byte if necessary */ - if (frame->can_dlc & 1) - frame->data[frame->can_dlc - 1] = in_8(data); + if (frame->len & 1) + frame->data[frame->len - 1] = in_8(data); } out_8(®s->canrflg, MSCAN_RXF); @@ -382,7 +366,7 @@ static void mscan_get_err_frame(struct net_device *dev, struct can_frame *frame, } } priv->shadow_statflg = canrflg & MSCAN_STAT_MSK; - frame->can_dlc = CAN_ERR_DLC; + frame->len = CAN_ERR_DLC; out_8(®s->canrflg, MSCAN_ERR_IF); } @@ -392,13 +376,12 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota) struct net_device *dev = napi->dev; struct mscan_regs __iomem *regs = priv->reg_base; struct net_device_stats *stats = &dev->stats; - int npackets = 0; - int ret = 1; + int work_done = 0; struct sk_buff *skb; struct can_frame *frame; u8 canrflg; - while (npackets < quota) { + while (work_done < quota) { canrflg = in_8(®s->canrflg); if (!(canrflg & (MSCAN_RXF | MSCAN_ERR_IF))) break; @@ -412,25 +395,27 @@ static int mscan_rx_poll(struct napi_struct *napi, int quota) continue; } - if (canrflg & MSCAN_RXF) + if (canrflg & MSCAN_RXF) { mscan_get_rx_frame(dev, frame); - else if (canrflg & MSCAN_ERR_IF) + stats->rx_packets++; + if (!(frame->can_id & CAN_RTR_FLAG)) + stats->rx_bytes += frame->len; + } else if (canrflg & MSCAN_ERR_IF) { mscan_get_err_frame(dev, frame, canrflg); + } - stats->rx_packets++; - stats->rx_bytes += frame->can_dlc; - npackets++; + work_done++; netif_receive_skb(skb); } - if (!(in_8(®s->canrflg) & (MSCAN_RXF | MSCAN_ERR_IF))) { - napi_complete(&priv->napi); - clear_bit(F_RX_PROGRESS, &priv->flags); - if (priv->can.state < CAN_STATE_BUS_OFF) - out_8(®s->canrier, priv->shadow_canrier); - ret = 0; + if (work_done < quota) { + if (likely(napi_complete_done(&priv->napi, work_done))) { + clear_bit(F_RX_PROGRESS, &priv->flags); + if (priv->can.state < CAN_STATE_BUS_OFF) + out_8(®s->canrier, priv->shadow_canrier); + } } - return ret; + return work_done; } static irqreturn_t mscan_isr(int irq, void *dev_id) @@ -457,9 +442,9 @@ static irqreturn_t mscan_isr(int irq, void *dev_id) continue; out_8(®s->cantbsel, mask); - stats->tx_bytes += in_8(®s->tx.dlr); + stats->tx_bytes += can_get_echo_skb(dev, entry->id, + NULL); stats->tx_packets++; - can_get_echo_skb(dev, entry->id); priv->tx_active &= ~mask; list_del(pos); } @@ -552,16 +537,12 @@ static int mscan_open(struct net_device *dev) struct mscan_priv *priv = netdev_priv(dev); struct mscan_regs __iomem *regs = priv->reg_base; - if (priv->clk_ipg) { - ret = clk_prepare_enable(priv->clk_ipg); - if (ret) - goto exit_retcode; - } - if (priv->clk_can) { - ret = clk_prepare_enable(priv->clk_can); - if (ret) - goto exit_dis_ipg_clock; - } + ret = clk_prepare_enable(priv->clk_ipg); + if (ret) + goto exit_retcode; + ret = clk_prepare_enable(priv->clk_can); + if (ret) + goto exit_dis_ipg_clock; /* common open */ ret = open_candev(dev); @@ -595,11 +576,9 @@ exit_napi_disable: napi_disable(&priv->napi); close_candev(dev); exit_dis_can_clock: - if (priv->clk_can) - clk_disable_unprepare(priv->clk_can); + clk_disable_unprepare(priv->clk_can); exit_dis_ipg_clock: - if (priv->clk_ipg) - clk_disable_unprepare(priv->clk_ipg); + clk_disable_unprepare(priv->clk_ipg); exit_retcode: return ret; } @@ -618,10 +597,8 @@ static int mscan_close(struct net_device *dev) close_candev(dev); free_irq(dev->irq, dev); - if (priv->clk_can) - clk_disable_unprepare(priv->clk_can); - if (priv->clk_ipg) - clk_disable_unprepare(priv->clk_ipg); + clk_disable_unprepare(priv->clk_can); + clk_disable_unprepare(priv->clk_ipg); return 0; } @@ -630,7 +607,10 @@ static const struct net_device_ops mscan_netdev_ops = { .ndo_open = mscan_open, .ndo_stop = mscan_close, .ndo_start_xmit = mscan_start_xmit, - .ndo_change_mtu = can_change_mtu, +}; + +static const struct ethtool_ops mscan_ethtool_ops = { + .get_ts_info = ethtool_op_get_ts_info, }; int register_mscandev(struct net_device *dev, int mscan_clksrc) @@ -693,10 +673,11 @@ struct net_device *alloc_mscandev(void) priv = netdev_priv(dev); dev->netdev_ops = &mscan_netdev_ops; + dev->ethtool_ops = &mscan_ethtool_ops; dev->flags |= IFF_ECHO; /* we support local echo */ - netif_napi_add(dev, &priv->napi, mscan_rx_poll, 8); + netif_napi_add_weight(dev, &priv->napi, mscan_rx_poll, 8); priv->can.bittiming_const = &mscan_bittiming_const; priv->can.do_set_bittiming = mscan_do_set_bittiming; |
