diff options
author | David S. Miller <davem@davemloft.net> | 2021-07-26 22:07:29 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-07-26 22:07:29 +0100 |
commit | d20e5880fe9df149a9159673d9fec57aab43ac61 (patch) | |
tree | 8019c9bfa5e59b89db1324623282d50681e4b0b8 | |
parent | af996031e1545c47423dfdd024840702ceb5a26c (diff) | |
parent | 8dad5561c13ade87238d9de6dd410b43f7562447 (diff) |
Merge tag 'linux-can-next-for-5.15-20210725' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
linux-can-next-for-5.15-20210725
Marc Kleine-Budde says:
====================
pull-request: can-next 2021-07-25
this is a pull request of 46 patches for net-next/master.
The first 6 patches target the CAN J1939 protocol. One is from
gushengxian, fixing a grammatical error, 5 are by me fixing a checkpatch
warning, make use of the fallthrough pseudo-keyword, and use
consistent variable naming.
The next 3 patches target the rx-offload helper, are by me and improve
the performance and fix the local softirq work pending error, when
napi_schedule() is called from threaded IRQ context.
The next 3 patches are by Vincent Mailhol and me update the CAN
bittiming and transmitter delay compensation, the documentation for
the struct can_tdc is fixed, clear data_bittiming if FD mode is turned
off and a redundant check is removed.
Followed by 4 patches targeting the m_can driver. Faiz Abbas's patches
add support for CAN PHY via the generic phy subsystem. Yang Yingliang
converts the driver to use devm_platform_ioremap_resource_byname().
And a patch by me which removes the unused support for custom bit
timing.
Andy Shevchenko contributes 2 patches for the mcp251xfd driver to
prepare the driver for ACPI support. A patch by me adds support for
shared IRQ handlers.
Zhen Lei contributes 3 patches to convert the esd_usb2, janz-ican3 and
the at91_can driver to make use of the DEVICE_ATTR_RO/RW() macros.
The next 8 patches are by Peng Li and provide general cleanups for the
at91_can driver.
The next 7 patches target the peak driver. Frist 2 cleanup patches by
me for the peak_pci driver, followed by Stephane Grosjean' patch to
print the name and firmware version of the detected hardware. The
peak_usb driver gets a cleanup patch, loopback and one-shot mode and
an upgrading of the bus state change handling in Stephane Grosjean's
patches.
Vincent Mailhol provides 6 cleanup patches for the etas_es58x driver.
In the last 3 patches Angelo Dureghello add support for the mcf5441x
SoC to the flexcan driver.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
24 files changed, 584 insertions, 443 deletions
diff --git a/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml b/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml index f84e31348d80..a7b5807c5543 100644 --- a/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml +++ b/Documentation/devicetree/bindings/net/can/bosch,m_can.yaml @@ -107,6 +107,9 @@ properties: can-transceiver: $ref: can-transceiver.yaml# + phys: + maxItems: 1 + required: - compatible - reg diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig index e355d3974977..fff259247d52 100644 --- a/drivers/net/can/Kconfig +++ b/drivers/net/can/Kconfig @@ -97,7 +97,8 @@ config CAN_AT91 config CAN_FLEXCAN tristate "Support for Freescale FLEXCAN based chips" - depends on OF && HAS_IOMEM + depends on OF || COLDFIRE || COMPILE_TEST + depends on HAS_IOMEM help Say Y here if you want to support for Freescale FlexCAN. diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index 04d0bb3ffe89..b06af90a9964 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -43,14 +43,14 @@ enum at91_reg { }; /* Mailbox registers (0 <= i <= 15) */ -#define AT91_MMR(i) (enum at91_reg)(0x200 + ((i) * 0x20)) -#define AT91_MAM(i) (enum at91_reg)(0x204 + ((i) * 0x20)) -#define AT91_MID(i) (enum at91_reg)(0x208 + ((i) * 0x20)) -#define AT91_MFID(i) (enum at91_reg)(0x20C + ((i) * 0x20)) -#define AT91_MSR(i) (enum at91_reg)(0x210 + ((i) * 0x20)) -#define AT91_MDL(i) (enum at91_reg)(0x214 + ((i) * 0x20)) -#define AT91_MDH(i) (enum at91_reg)(0x218 + ((i) * 0x20)) -#define AT91_MCR(i) (enum at91_reg)(0x21C + ((i) * 0x20)) +#define AT91_MMR(i) ((enum at91_reg)(0x200 + ((i) * 0x20))) +#define AT91_MAM(i) ((enum at91_reg)(0x204 + ((i) * 0x20))) +#define AT91_MID(i) ((enum at91_reg)(0x208 + ((i) * 0x20))) +#define AT91_MFID(i) ((enum at91_reg)(0x20C + ((i) * 0x20))) +#define AT91_MSR(i) ((enum at91_reg)(0x210 + ((i) * 0x20))) +#define AT91_MDL(i) ((enum at91_reg)(0x214 + ((i) * 0x20))) +#define AT91_MDH(i) ((enum at91_reg)(0x218 + ((i) * 0x20))) +#define AT91_MCR(i) ((enum at91_reg)(0x21C + ((i) * 0x20))) /* Register bits */ #define AT91_MR_CANEN BIT(0) @@ -87,19 +87,19 @@ enum at91_mb_mode { }; /* Interrupt mask bits */ -#define AT91_IRQ_ERRA (1 << 16) -#define AT91_IRQ_WARN (1 << 17) -#define AT91_IRQ_ERRP (1 << 18) -#define AT91_IRQ_BOFF (1 << 19) -#define AT91_IRQ_SLEEP (1 << 20) -#define AT91_IRQ_WAKEUP (1 << 21) -#define AT91_IRQ_TOVF (1 << 22) -#define AT91_IRQ_TSTP (1 << 23) -#define AT91_IRQ_CERR (1 << 24) -#define AT91_IRQ_SERR (1 << 25) -#define AT91_IRQ_AERR (1 << 26) -#define AT91_IRQ_FERR (1 << 27) -#define AT91_IRQ_BERR (1 << 28) +#define AT91_IRQ_ERRA BIT(16) +#define AT91_IRQ_WARN BIT(17) +#define AT91_IRQ_ERRP BIT(18) +#define AT91_IRQ_BOFF BIT(19) +#define AT91_IRQ_SLEEP BIT(20) +#define AT91_IRQ_WAKEUP BIT(21) +#define AT91_IRQ_TOVF BIT(22) +#define AT91_IRQ_TSTP BIT(23) +#define AT91_IRQ_CERR BIT(24) +#define AT91_IRQ_SERR BIT(25) +#define AT91_IRQ_AERR BIT(26) +#define AT91_IRQ_FERR BIT(27) +#define AT91_IRQ_BERR BIT(28) #define AT91_IRQ_ERR_ALL (0x1fff0000) #define AT91_IRQ_ERR_FRAME (AT91_IRQ_CERR | AT91_IRQ_SERR | \ @@ -163,7 +163,7 @@ static const struct can_bittiming_const at91_bittiming_const = { .tseg2_min = 2, .tseg2_max = 8, .sjw_max = 4, - .brp_min = 2, + .brp_min = 2, .brp_max = 128, .brp_inc = 1, }; @@ -281,19 +281,20 @@ static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg) } static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg, - u32 value) + u32 value) { writel_relaxed(value, priv->reg_base + reg); } static inline void set_mb_mode_prio(const struct at91_priv *priv, - unsigned int mb, enum at91_mb_mode mode, int prio) + unsigned int mb, enum at91_mb_mode mode, + int prio) { at91_write(priv, AT91_MMR(mb), (mode << 24) | (prio << 16)); } static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb, - enum at91_mb_mode mode) + enum at91_mb_mode mode) { set_mb_mode_prio(priv, mb, mode, 0); } @@ -316,8 +317,7 @@ static void at91_setup_mailboxes(struct net_device *dev) unsigned int i; u32 reg_mid; - /* - * Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first + /* Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first * mailbox is disabled. The next 11 mailboxes are used as a * reception FIFO. The last mailbox is configured with * overwrite option. The overwrite flag indicates a FIFO @@ -368,7 +368,7 @@ static int at91_set_bittiming(struct net_device *dev) } static int at91_get_berr_counter(const struct net_device *dev, - struct can_berr_counter *bec) + struct can_berr_counter *bec) { const struct at91_priv *priv = netdev_priv(dev); u32 reg_ecr = at91_read(priv, AT91_ECR); @@ -423,8 +423,7 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state) priv->can.state = state; } -/* - * theory of operation: +/* theory of operation: * * According to the datasheet priority 0 is the highest priority, 15 * is the lowest. If two mailboxes have the same priority level the @@ -486,8 +485,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) /* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */ can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv), 0); - /* - * we have to stop the queue and deliver all messages in case + /* we have to stop the queue and deliver all messages in case * of a prio+mb counter wrap around. This is the case if * tx_next buffer prio and mailbox equals 0. * @@ -515,6 +513,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev) static inline void at91_activate_rx_low(const struct at91_priv *priv) { u32 mask = get_mb_rx_low_mask(priv); + at91_write(priv, AT91_TCR, mask); } @@ -526,9 +525,10 @@ static inline void at91_activate_rx_low(const struct at91_priv *priv) * Reenables given mailbox for reception of new CAN messages */ static inline void at91_activate_rx_mb(const struct at91_priv *priv, - unsigned int mb) + unsigned int mb) { u32 mask = 1 << mb; + at91_write(priv, AT91_TCR, mask); } @@ -568,7 +568,7 @@ static void at91_rx_overflow_err(struct net_device *dev) * given can frame. "mb" and "cf" must be valid. */ static void at91_read_mb(struct net_device *dev, unsigned int mb, - struct can_frame *cf) + struct can_frame *cf) { const struct at91_priv *priv = netdev_priv(dev); u32 reg_msr, reg_mid; @@ -582,9 +582,9 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb, reg_msr = at91_read(priv, AT91_MSR(mb)); cf->len = can_cc_dlc2len((reg_msr >> 16) & 0xf); - if (reg_msr & AT91_MSR_MRTR) + if (reg_msr & AT91_MSR_MRTR) { cf->can_id |= CAN_RTR_FLAG; - else { + } else { *(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb)); *(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb)); } @@ -685,7 +685,7 @@ static int at91_poll_rx(struct net_device *dev, int quota) if (priv->rx_next > get_mb_rx_low_last(priv) && reg_sr & get_mb_rx_low_mask(priv)) netdev_info(dev, - "order of incoming frames cannot be guaranteed\n"); + "order of incoming frames cannot be guaranteed\n"); again: for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next); @@ -718,7 +718,7 @@ static int at91_poll_rx(struct net_device *dev, int quota) } static void at91_poll_err_frame(struct net_device *dev, - struct can_frame *cf, u32 reg_sr) + struct can_frame *cf, u32 reg_sr) { struct at91_priv *priv = netdev_priv(dev); @@ -796,8 +796,7 @@ static int at91_poll(struct napi_struct *napi, int quota) if (reg_sr & get_irq_mb_rx(priv)) work_done += at91_poll_rx(dev, quota - work_done); - /* - * The error bits are clear on read, + /* The error bits are clear on read, * so use saved value from irq handler. */ reg_sr |= priv->reg_sr; @@ -807,6 +806,7 @@ static int at91_poll(struct napi_struct *napi, int quota) if (work_done < quota) { /* enable IRQs for frame errors and all mailboxes >= rx_next */ u32 reg_ier = AT91_IRQ_ERR_FRAME; + reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next); napi_complete_done(napi, work_done); @@ -816,8 +816,7 @@ static int at91_poll(struct napi_struct *napi, int quota) return work_done; } -/* - * theory of operation: +/* theory of operation: * * priv->tx_echo holds the number of the oldest can_frame put for * transmission into the hardware, but not yet ACKed by the CAN tx @@ -846,8 +845,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr) /* Disable irq for this TX mailbox */ at91_write(priv, AT91_IDR, 1 << mb); - /* - * only echo if mailbox signals us a transfer + /* only echo if mailbox signals us a transfer * complete (MSR_MRDY). Otherwise it's a tansfer * abort. "can_bus_off()" takes care about the skbs * parked in the echo queue. @@ -862,8 +860,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr) } } - /* - * restart queue if we don't have a wrap around but restart if + /* restart queue if we don't have a wrap around but restart if * we get a TX int for the last can frame directly before a * wrap around. */ @@ -873,7 +870,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr) } static void at91_irq_err_state(struct net_device *dev, - struct can_frame *cf, enum can_state new_state) + struct can_frame *cf, enum can_state new_state) { struct at91_priv *priv = netdev_priv(dev); u32 reg_idr = 0, reg_ier = 0; @@ -883,8 +880,7 @@ static void at91_irq_err_state(struct net_device *dev, switch (priv->can.state) { case CAN_STATE_ERROR_ACTIVE: - /* - * from: ERROR_ACTIVE + /* from: ERROR_ACTIVE * to : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF * => : there was a warning int */ @@ -900,8 +896,7 @@ static void at91_irq_err_state(struct net_device *dev, } fallthrough; case CAN_STATE_ERROR_WARNING: - /* - * from: ERROR_ACTIVE, ERROR_WARNING + /* from: ERROR_ACTIVE, ERROR_WARNING * to : ERROR_PASSIVE, BUS_OFF * => : error passive int */ @@ -917,8 +912,7 @@ static void at91_irq_err_state(struct net_device *dev, } break; case CAN_STATE_BUS_OFF: - /* - * from: BUS_OFF + /* from: BUS_OFF * to : ERROR_ACTIVE, ERROR_WARNING, ERROR_PASSIVE */ if (new_state <= CAN_STATE_ERROR_PASSIVE) { @@ -935,12 +929,10 @@ static void at91_irq_err_state(struct net_device *dev, break; } - /* process state changes depending on the new state */ switch (new_state) { case CAN_STATE_ERROR_ACTIVE: - /* - * actually we want to enable AT91_IRQ_WARN here, but + /* actually we want to enable AT91_IRQ_WARN here, but * it screws up the system under certain * circumstances. so just enable AT91_IRQ_ERRP, thus * the "fallthrough" @@ -983,7 +975,7 @@ static void at91_irq_err_state(struct net_device *dev, } static int at91_get_state_by_bec(const struct net_device *dev, - enum can_state *state) + enum can_state *state) { struct can_berr_counter bec; int err; @@ -1004,7 +996,6 @@ static int at91_get_state_by_bec(const struct net_device *dev, return 0; } - static void at91_irq_err(struct net_device *dev) { struct at91_priv *priv = netdev_priv(dev); @@ -1018,15 +1009,15 @@ static void at91_irq_err(struct net_device *dev) reg_sr = at91_read(priv, AT91_SR); /* we need to look at the unmasked reg_sr */ - if (unlikely(reg_sr & AT91_IRQ_BOFF)) + if (unlikely(reg_sr & AT91_IRQ_BOFF)) { new_state = CAN_STATE_BUS_OFF; - else if (unlikely(reg_sr & AT91_IRQ_ERRP)) + } else if (unlikely(reg_sr & AT91_IRQ_ERRP)) { new_state = CAN_STATE_ERROR_PASSIVE; - else if (unlikely(reg_sr & AT91_IRQ_WARN)) + } else if (unlikely(reg_sr & AT91_IRQ_WARN)) { new_state = CAN_STATE_ERROR_WARNING; - else if (likely(reg_sr & AT91_IRQ_ERRA)) + } else if (likely(reg_sr & AT91_IRQ_ERRA)) { new_state = CAN_STATE_ERROR_ACTIVE; - else { + } else { netdev_err(dev, "BUG! hardware in undefined state\n"); return; } @@ -1053,8 +1044,7 @@ static void at91_irq_err(struct net_device *dev) priv->can.state = new_state; } -/* - * interrupt handler +/* interrupt handler */ static irqreturn_t at91_irq(int irq, void *dev_id) { @@ -1075,8 +1065,7 @@ static irqreturn_t at91_irq(int irq, void *dev_id) /* Receive or error interrupt? -> napi */ if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) { - /* - * The error bits are clear on read, + /* The error bits are clear on read, * save for later use. */ priv->reg_sr = reg_sr; @@ -1133,8 +1122,7 @@ static int at91_open(struct net_device *dev) return err; } -/* - * stop CAN bus activity +/* stop CAN bus activity */ static int at91_close(struct net_device *dev) { @@ -1176,8 +1164,8 @@ static const struct net_device_ops at91_netdev_ops = { .ndo_change_mtu = can_change_mtu, }; -static ssize_t at91_sysfs_show_mb0_id(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t mb0_id_show(struct device *dev, + struct device_attribute *attr, char *buf) { struct at91_priv *priv = netdev_priv(to_net_dev(dev)); @@ -1187,8 +1175,9 @@ static ssize_t at91_sysfs_show_mb0_id(struct device *dev, return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id); } -static ssize_t at91_sysfs_set_mb0_id(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) +static ssize_t mb0_id_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct net_device *ndev = to_net_dev(dev); struct at91_priv *priv = netdev_priv(ndev); @@ -1222,7 +1211,7 @@ static ssize_t at91_sysfs_set_mb0_id(struct device *dev, return ret; } -static DEVICE_ATTR(mb0_id, 0644, at91_sysfs_show_mb0_id, at91_sysfs_set_mb0_id); +static DEVICE_ATTR_RW(mb0_id); static struct attribute *at91_sysfs_attrs[] = { &dev_attr_mb0_id.attr, diff --git a/drivers/net/can/dev/netlink.c b/drivers/net/can/dev/netlink.c index e38c2566aff4..147c23d7dab7 100644 --- a/drivers/net/can/dev/netlink.c +++ b/drivers/net/can/dev/netlink.c @@ -47,7 +47,7 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[], } if (data[IFLA_CAN_DATA_BITTIMING]) { - if (!is_can_fd || !data[IFLA_CAN_BITTIMING]) + if (!is_can_fd) return -EOPNOTSUPP; } @@ -132,10 +132,13 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[], priv->ctrlmode |= maskedflags; /* CAN_CTRLMODE_FD can only be set when driver supports FD */ - if (priv->ctrlmode & CAN_CTRLMODE_FD) + if (priv->ctrlmode & CAN_CTRLMODE_FD) { dev->mtu = CANFD_MTU; - else + } else { dev->mtu = CAN_MTU; + memset(&priv->data_bittiming, 0, + sizeof(priv->data_bittiming)); + } } if (data[IFLA_CAN_RESTART_MS]) { diff --git a/drivers/net/can/dev/rx-offload.c b/drivers/net/can/dev/rx-offload.c index ab2c1543786c..37b0cc65237b 100644 --- a/drivers/net/can/dev/rx-offload.c +++ b/drivers/net/can/dev/rx-offload.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* Copyright (c) 2014 Protonic Holland, * David Jander - * Copyright (C) 2014-2017 Pengutronix, + * Copyright (C) 2014-2021 Pengutronix, * Marc Kleine-Budde <kernel@pengutronix.de> */ @@ -174,10 +174,8 @@ can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n) int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, u64 pending) { - struct sk_buff_head skb_queue; unsigned int i; - - __skb_queue_head_init(&skb_queue); + int received = 0; for (i = offload->mb_first; can_rx_offload_le(offload, i, offload->mb_last); @@ -191,26 +189,12 @@ int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload, if (IS_ERR_OR_NULL(skb)) continue; - __skb_queue_add_sort(&skb_queue, skb, can_rx_offload_compare); - } - - if (!skb_queue_empty(&skb_queue)) { - unsigned long flags; - u32 queue_len; - - spin_lock_irqsave(&offload->skb_queue.lock, flags); - skb_queue_splice_tail(&skb_queue, &offload->skb_queue); - spin_unlock_irqrestore(&offload->skb_queue.lock, flags); - - queue_len = skb_queue_len(&offload->skb_queue); - if (queue_len > offload->skb_queue_len_max / 8) - netdev_dbg(offload->dev, "%s: queue_len=%d\n", - __func__, queue_len); - - can_rx_offload_schedule(offload); + __skb_queue_add_sort(&offload->skb_irq_queue, skb, + can_rx_offload_compare); + received++; } - return skb_queue_len(&skb_queue); + return received; } EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_timestamp); @@ -226,13 +210,10 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload) if (!skb) break; - skb_queue_tail(&offload->skb_queue, skb); + __skb_queue_tail(&offload->skb_irq_queue, skb); received++; } - if (received) - can_rx_offload_schedule(offload); - return received; } EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo); @@ -241,7 +222,6 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload, struct sk_buff *skb, u32 timestamp) { struct can_rx_offload_cb *cb; - unsigned long flags; if (skb_queue_len(&offload->skb_queue) > offload->skb_queue_len_max) { @@ -252,11 +232,8 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload, cb = can_rx_offload_get_cb(skb); cb->timestamp = timestamp; - spin_lock_irqsave(&offload->skb_queue.lock, flags); - __skb_queue_add_sort(&offload->skb_queue, skb, can_rx_offload_compare); - spin_unlock_irqrestore(&offload->skb_queue.lock, flags); - - can_rx_offload_schedule(offload); + __skb_queue_add_sort(&offload->skb_irq_queue, skb, + can_rx_offload_compare); return 0; } @@ -295,13 +272,56 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload, return -ENOBUFS; } - skb_queue_tail(&offload->skb_queue, skb); - can_rx_offload_schedule(offload); + __skb_queue_tail(&offload->skb_irq_queue, skb); return 0; } EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail); +void can_rx_offload_irq_finish(struct can_rx_offload *offload) +{ + unsigned long flags; + int queue_len; + + if (skb_queue_empty_lockless(&offload->skb_irq_queue)) + return; + + spin_lock_irqsave(&offload->skb_queue.lock, flags); + skb_queue_splice_tail_init(&offload->skb_irq_queue, &offload->skb_queue); + spin_unlock_irqrestore(&offload->skb_queue.lock, flags); + + queue_len = skb_queue_len(&offload->skb_queue); + if (queue_len > offload->skb_queue_len_max / 8) + netdev_dbg(offload->dev, "%s: queue_len=%d\n", + __func__, queue_len); + + napi_schedule(&offload->napi); +} +EXPORT_SYMBOL_GPL(can_rx_offload_irq_finish); + +void can_rx_offload_threaded_irq_finish(struct can_rx_offload *offload) +{ + unsigned long flags; + int queue_len; + + if (skb_queue_empty_lockless(&offload->skb_irq_queue)) + return; + + spin_lock_irqsave(&offload->skb_queue.lock, flags); + skb_queue_splice_tail_init(&offload->skb_irq_queue, &offload->skb_queue); + spin_unlock_irqrestore(&offload->skb_queue.lock, flags); + + queue_len = skb_queue_len(&offload->skb_queue); + if (queue_len > offload->skb_queue_len_max / 8) + netdev_dbg(offload->dev, "%s: queue_len=%d\n", + __func__, queue_len); + + local_bh_disable(); + napi_schedule(&offload->napi); + local_bh_enable(); +} +EXPORT_SYMBOL_GPL(can_rx_offload_threaded_irq_finish); + static int can_rx_offload_init_queue(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight) @@ -312,6 +332,7 @@ static int can_rx_offload_init_queue(struct net_device *dev, offload->skb_queue_len_max = 2 << fls(weight); offload->skb_queue_len_max *= 4; skb_queue_head_init(&offload->skb_queue); + __skb_queue_head_init(&offload->skb_irq_queue); netif_napi_add(dev, &offload->napi, can_rx_offload_napi_poll, weight); @@ -373,5 +394,6 @@ void can_rx_offload_del(struct can_rx_offload *offload) { netif_napi_del(&offload->napi); skb_queue_purge(&offload->skb_queue); + __skb_queue_purge(&offload->skb_irq_queue); } EXPORT_SYMBOL_GPL(can_rx_offload_del); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 57f3635ad8d7..54ffb796a320 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -28,6 +28,7 @@ #include <linux/of_device.h> #include <linux/pinctrl/consumer.h> #include <linux/platform_device.h> +#include <linux/can/platform/flexcan.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> @@ -208,18 +209,19 @@ /* FLEXCAN hardware feature flags * * Below is some version info we got: - * SOC Version IP-Version Glitch- [TR]WRN_INT IRQ Err Memory err RTR rece- FD Mode + * SOC Version IP-Version Glitch- [TR]WRN_INT IRQ Err Memory err RTR rece- FD Mode MB * Filter? connected? Passive detection ption in MB Supported? - * MX25 FlexCAN2 03.00.00.00 no no no no no no - * MX28 FlexCAN2 03.00.04.00 yes yes no no no no - * MX35 FlexCAN2 03.00.00.00 no no no no no no - * MX53 FlexCAN2 03.00.00.00 yes no no no no no - * MX6s FlexCAN3 10.00.12.00 yes yes no no yes no - * MX8QM FlexCAN3 03.00.23.00 yes yes no no yes yes - * MX8MP FlexCAN3 03.00.17.01 yes yes no yes yes yes - * VF610 FlexCAN3 ? no yes no yes yes? no - * LS1021A FlexCAN2 03.00.04.00 no yes no no yes no - * LX2160A FlexCAN3 03.00.23.00 no yes no yes yes yes + * MCF5441X FlexCAN2 ? no yes no no yes no 16 + * MX25 FlexCAN2 03.00.00.00 no no no no no no 64 + * MX28 FlexCAN2 03.00.04.00 yes yes no no no no 64 + * MX35 FlexCAN2 03.00.00.00 no no no no no no 64 + * MX53 FlexCAN2 03.00.00.00 yes no no no no no 64 + * MX6s FlexCAN3 10.00.12.00 yes yes no no yes no 64 + * MX8QM FlexCAN3 03.00.23.00 yes yes no no yes yes 64 + * MX8MP FlexCAN3 03.00.17.01 yes yes no yes yes yes 64 + * VF610 FlexCAN3 ? no yes no yes yes? no 64 + * LS1021A FlexCAN2 03.00.04.00 no yes no no yes no 64 + * LX2160A FlexCAN3 03.00.23.00 no yes no yes yes yes 64 * * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. */ @@ -246,6 +248,10 @@ #define FLEXCAN_QUIRK_SUPPORT_ECC BIT(10) /* Setup stop mode with SCU firmware to support wakeup */ #define FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW BIT(11) +/* Setup 3 separate interrupts, main, boff and err */ +#define FLEXCAN_QUIRK_NR_IRQ_3 BIT(12) +/* Setup 16 mailboxes */ +#define FLEXCAN_QUIRK_NR_MB_16 BIT(13) /* Structure of the message buffer */ struct flexcan_mb { @@ -363,6 +369,9 @@ struct flexcan_priv { struct regulator *reg_xceiver; struct flexcan_stop_mode stm; + int irq_boff; + int irq_err; + /* IPC handle when setup stop mode by System Controller firmware(scfw) */ struct imx_sc_ipc *sc_ipc_handle; @@ -371,6 +380,11 @@ struct flexcan_priv { void (*write)(u32 val, void __iomem *addr); }; +static const struct flexcan_devtype_data fsl_mcf5441x_devtype_data = { + .quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE | + FLEXCAN_QUIRK_NR_IRQ_3 | FLEXCAN_QUIRK_NR_MB_16, +}; + static const struct flexcan_devtype_data fsl_p1010_devtype_data = { .quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE | FLEXCAN_QUIRK_BROKEN_PERR_STATE | @@ -637,13 +651,17 @@ static int flexcan_clks_enable(const struct flexcan_priv *priv) { int err; - err = clk_prepare_enable(priv->clk_ipg); - if (err) - return err; + if (priv->clk_ipg) { + err = clk_prepare_enable(priv->clk_ipg); + if (err) + return err; + } - err = clk_prepare_enable(priv->clk_per); - if (err) - clk_disable_unprepare(priv->clk_ipg); + if (priv->clk_per) { + err = clk_prepare_enable(priv->clk_per); + if (err) + clk_disable_unprepare(priv->clk_ipg); + } return err; } @@ -1198,6 +1216,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) } } + if (handled) + can_rx_offload_irq_finish(&priv->offload); + return handled; } @@ -1401,8 +1422,12 @@ static int flexcan_rx_offload_setup(struct net_device *dev) priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN; else priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN; - priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) + - (sizeof(priv->regs->mb[1]) / priv->mb_size); + + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_MB_16) + priv->mb_count = 16; + else + priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) + + (sizeof(priv->regs->mb[1]) / priv->mb_size); if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) priv->tx_mb_reserved = @@ -1774,6 +1799,18 @@ static int flexcan_open(struct net_device *dev) if (err) goto out_can_rx_offload_disable; + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) { + err = request_irq(priv->irq_boff, + flexcan_irq, IRQF_SHARED, dev->name, dev); + if (err) + goto out_free_irq; + + err = request_irq(priv->irq_err, + flexcan_irq, IRQF_SHARED, dev->name, dev); + if (err) + goto out_free_irq_boff; + } + flexcan_chip_interrupts_enable(dev); can_led_event(dev, CAN_LED_EVENT_OPEN); @@ -1782,6 +1819,10 @@ static int flexcan_open(struct net_device *dev) return 0; + out_free_irq_boff: + free_irq(priv->irq_boff, dev); + out_free_irq: + free_irq(dev->irq, dev); out_can_rx_offload_disable: can_rx_offload_disable(&priv->offload); flexcan_chip_stop(dev); @@ -1803,6 +1844,12 @@ static int flexcan_close(struct net_device *dev) netif_stop_queue(dev); flexcan_chip_interrupts_disable(dev); + + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) { + free_irq(priv->irq_err, dev); + free_irq(priv->irq_boff, dev); + } + free_irq(dev->irq, dev); can_rx_offload_disable(&priv->offload); flexcan_chip_stop_disable_on_error(dev); @@ -2039,14 +2086,26 @@ static const struct of_device_id flexcan_of_match[] = { }; MODULE_DEVICE_TABLE(of, flexcan_of_match); +static const struct platform_device_id flexcan_id_table[] = { + { + .name = "flexcan-mcf5441x", + .driver_data = (kernel_ulong_t)&fsl_mcf5441x_devtype_data, + }, { + /* sentinel */ + }, +}; +MODULE_DEVICE_TABLE(platform, flexcan_id_table); + static int flexcan_probe(struct platform_device *pdev) { + const struct of_device_id *of_id; const struct flexcan_devtype_data *devtype_data; struct net_device *dev; struct flexcan_priv *priv; struct regulator *reg_xceiver; struct clk *clk_ipg = NULL, *clk_per = NULL; struct flexcan_regs __iomem *regs; + struct flexcan_platform_data *pdata; int err, irq; u8 clk_src = 1; u32 clock_freq = 0; @@ -2064,6 +2123,12 @@ static int flexcan_probe(struct platform_device *pdev) "clock-frequency", &clock_freq); of_property_read_u8(pdev->dev.of_node, "fsl,clk-source", &clk_src); + } else { + pdata = dev_get_platdata(&pdev->dev); + if (pdata) { + clock_freq = pdata->clock_frequency; + clk_src = pdata->clk_src; + } } if (!clock_freq) { @@ -2089,7 +2154,14 @@ static int flexcan_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - devtype_data = of_device_get_match_data(&pdev->dev); + of_id = of_match_device(flexcan_of_match, &pdev->dev); + if (of_id) + devtype_data = of_id->data; + else if (platform_get_device_id(pdev)->driver_data) + devtype_data = (struct flexcan_devtype_data *) + platform_get_device_id(pdev)->driver_data; + else + return -ENODEV; if ((devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) && !(devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)) { @@ -2133,6 +2205,19 @@ static int flexcan_probe(struct platform_device *pdev) priv->devtype_data = devtype_data; priv->reg_xceiver = reg_xceiver; + if (devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) { + priv->irq_boff = platform_get_irq(pdev, 1); + if (priv->irq_boff <= 0) { + err = -ENODEV; + goto failed_platform_get_irq; + } + priv->irq_err = platform_get_irq(pdev, 2); + if (priv->irq_err <= 0) { + err = -ENODEV; + goto failed_platform_get_irq; + } + } + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) { priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO; @@ -2170,6 +2255,7 @@ static int flexcan_probe(struct platform_device *pdev) failed_register: pm_runtime_put_noidle(&pdev->dev); pm_runtime_disable(&pdev->dev); + failed_platform_get_irq: free_candev(dev); return err; } @@ -2322,6 +2408,7 @@ static struct platform_driver flexcan_driver = { }, .probe = flexcan_probe, .remove = flexcan_remove, + .id_table = flexcan_id_table, }; module_platform_driver(flexcan_driver); diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 2a6c918186c0..c68ad56628bd 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -1815,9 +1815,9 @@ static int ican3_get_berr_counter(const struct net_device *ndev, * Sysfs Attributes */ -static ssize_t ican3_sysfs_show_term(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t termination_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); int ret; @@ -1834,9 +1834,9 @@ static ssize_t ican3_sysfs_show_term(struct device *dev, return snprintf(buf, PAGE_SIZE, "%u\n", mod->termination_enabled); } -static ssize_t ican3_sysfs_set_term(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t termination_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); unsigned long enable; @@ -1852,18 +1852,17 @@ static ssize_t ican3_sysfs_set_term(struct device *dev, return count; } -static ssize_t ican3_sysfs_show_fwinfo(struct device *dev, - struct device_attribute *attr, - char *buf) +static ssize_t fwinfo_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct ican3_dev *mod = netdev_priv(to_net_dev(dev)); return scnprintf(buf, PAGE_SIZE, "%s\n", mod->fwinfo); } -static DEVICE_ATTR(termination, 0644, ican3_sysfs_show_term, - ican3_sysfs_set_term); -static DEVICE_ATTR(fwinfo, 0444, ican3_sysfs_show_fwinfo, NULL); +static DEVICE_ATTR_RW(termination); +static DEVICE_ATTR_RO(fwinfo); static struct attribute *ican3_sysfs_attrs[] = { &dev_attr_termination.attr, diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index bba2a449ac70..0cffaad905c2 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -21,6 +21,7 @@ #include <linux/iopoll.h> #include <linux/can/dev.h> #include <linux/pinctrl/consumer.h> +#include <linux/phy/phy.h> #include "m_can.h" @@ -1058,6 +1059,9 @@ static irqreturn_t m_can_isr(int irq, void *dev_id) } } + if (cdev->is_peripheral) + can_rx_offload_threaded_irq_finish(&cdev->offload); + return IRQ_HANDLED; } @@ -1436,32 +1440,20 @@ static int m_can_dev_setup(struct m_can_classdev *cdev) case 30: /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */ can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); - cdev->can.bittiming_const = cdev->bit_timing ? - cdev->bit_timing : &m_can_bittiming_const_30X; - - cdev->can.data_bittiming_const = cdev->data_timing ? - cdev->data_timing : - &m_can_data_bittiming_const_30X; + cdev->can.bittiming_const = &m_can_bittiming_const_30X; + cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X; break; case 31: /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */ can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); - cdev->can.bittiming_const = cdev->bit_timing ? - cdev->bit_timing : &m_can_bittiming_const_31X; - - cdev->can.data_bittiming_const = cdev->data_timing ? - cdev->data_timing : - &m_can_data_bittiming_const_31X; + cdev->can.bittiming_const = &m_can_bittiming_const_31X; + cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; break; case 32: case 33: /* Support both MCAN version v3.2.x and v3.3.0 */ - cdev->can.bittiming_const = cdev->bit_timing ? - cdev->bit_timing : &m_can_bittiming_const_31X; - - cdev->can.data_bittiming_const = cdev->data_timing ? - cdev->data_timing : - &m_can_data_bittiming_const_31X; + cdev->can.bittiming_const = &m_can_bittiming_const_31X; + cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X; cdev->can.ctrlmode_supported |= (m_can_niso_supported(cdev) ? @@ -1518,6 +1510,8 @@ static int m_can_close(struct net_device *dev) close_candev(dev); can_led_event(dev, CAN_LED_EVENT_STOP); + phy_power_off(cdev->transceiver); + return 0; } @@ -1703,10 +1697,14 @@ static int m_can_open(struct net_device *dev) struct m_can_classdev *cdev = netdev_priv(dev); int err; - err = m_can_clk_start(cdev); + err = phy_power_on(cdev->transceiver); if (err) return err; + err = m_can_clk_start(cdev); + if (err) + goto out_phy_power_off; + /* open the can device */ err = open_candev(dev); if (err) { @@ -1763,6 +1761,8 @@ out_wq_fail: close_candev(dev); exit_disable_clks: m_can_clk_stop(cdev); +out_phy_power_off: + phy_power_off(cdev->transceiver); return err; } diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h index ace071c3e58c..56e994376a7b 100644 --- a/drivers/net/can/m_can/m_can.h +++ b/drivers/net/can/m_can/m_can.h @@ -28,6 +28,7 @@ #include <linux/iopoll.h> #include <linux/can/dev.h> #include <linux/pinctrl/consumer.h> +#include <linux/phy/phy.h> /* m_can lec values */ enum m_can_lec_type { @@ -82,9 +83,7 @@ struct m_can_classdev { struct workqueue_struct *tx_wq; struct work_struct tx_work; struct sk_buff *tx_skb; - - struct can_bittiming_const *bit_timing; - struct can_bittiming_const *data_timing; + struct phy *transceiver; struct m_can_ops *ops; diff --git a/drivers/net/can/m_can/m_can_platform.c b/drivers/net/can/m_can/m_can_platform.c index 599de0e08cd7..a28c84aa8fa8 100644 --- a/drivers/net/can/m_can/m_can_platform.c +++ b/drivers/net/can/m_can/m_can_platform.c @@ -6,6 +6,7 @@ // Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/ #include <linux/platform_device.h> +#include <linux/phy/phy.h> #include "m_can.h" @@ -67,6 +68,7 @@ static int m_can_plat_probe(struct platform_device *pdev) struct resource *res; void __iomem *addr; void __iomem *mram_addr; + struct phy *transceiver; int irq, ret = 0; mcan_class = m_can_class_allocate_dev(&pdev->dev, @@ -80,8 +82,7 @@ static int m_can_plat_probe(struct platform_device *pdev) if (ret) goto probe_fail; - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can"); - addr = devm_ioremap_resource(&pdev->dev, res); + addr = devm_platform_ioremap_resource_byname(pdev, "m_can"); irq = platform_get_irq_byname(pdev, "int0"); if (IS_ERR(addr) || irq < 0) { ret = -EINVAL; @@ -101,6 +102,16 @@ static int m_can_plat_probe(struct platform_device *pdev) goto probe_fail; } + transceiver = devm_phy_optional_get(&pdev->dev, NULL); + if (IS_ERR(transceiver)) { + ret = PTR_ERR(transceiver); + dev_err_probe(&pdev->dev, ret, "failed to get phy\n"); + goto probe_fail; + } + + if (transceiver) + mcan_class->can.bitrate_max = transceiver->attrs.max_link_rate; + priv->base = addr; priv->mram_base = mram_addr; @@ -108,6 +119,7 @@ static int m_can_plat_probe(struct platform_device *pdev) mcan_class->pm_clock_support = 1; mcan_class->can.clock.freq = clk_get_rate(mcan_class->cclk); mcan_class->dev = &pdev->dev; + mcan_class->transceiver = transceiver; mcan_class->ops = &m_can_plat_ops; diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index 84eac8cb8686..6db90dc4bc9d 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -28,6 +28,10 @@ MODULE_LICENSE("GPL v2"); #define DRV_NAME "peak_pci" +/* FPGA cards FW version registers */ +#define PEAK_VER_REG1 0x40 +#define PEAK_VER_REG2 0x44 + struct peak_pciec_card; struct peak_pci_chan { void __iomem *cfg_base; /* Common for all channels */ @@ -41,9 +45,7 @@ struct peak_pci_chan { #define PEAK_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK) #define PEAK_PCI_OCR OCR_TX0_PUSHPULL -/* - * Important PITA registers - */ +/* Important PITA registers */ #define PITA_ICR 0x00 /* Interrupt control register */ #define PITA_GPIOICR 0x18 /* GPIO interface control register */ #define PITA_MISC 0x1C /* Miscellaneous register */ @@ -70,27 +72,47 @@ static const u16 peak_pci_icr_masks[PEAK_PCI_CHAN_MAX] = { }; static const struct pci_device_id peak_pci_tbl[] = { - {PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,}, + { + PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-PCI", + }, { + PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-PCI Express", + }, { + PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-miniPCI", + }, { + PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-miniPCIe", + }, { + PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-PC/104-Plus Quad", + }, { + PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-PCI/104-Express", + }, { + PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-cPCI", + }, { + PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-Chip PCIe", + }, #ifdef CONFIG_CAN_PEAK_PCIEC - {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, - {PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + { + PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-ExpressCard", + }, { + PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, + .driver_data = (kernel_ulong_t)"PCAN-ExpressCard 34", + }, #endif - {0,} + { /* sentinel */ } }; MODULE_DEVICE_TABLE(pci, peak_pci_tbl); #ifdef CONFIG_CAN_PEAK_PCIEC -/* - * PCAN-ExpressCard needs I2C bit-banging configuration option. - */ +/* PCAN-ExpressCard needs I2C bit-banging configuration option. */ /* GPIOICR byte access offsets */ #define PITA_GPOUT 0x18 /* GPx output value */ @@ -156,12 +178,14 @@ static void peak_pci_write_reg(const struct sja1000_priv *priv, static inline void pita_set_scl_highz(struct peak_pciec_card *card) { u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SCL; + writeb(gp_outen, card->cfg_base + PITA_GPOEN); } static inline void pita_set_sda_highz(struct peak_pciec_card *card) { u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SDA; + writeb(gp_outen, card->cfg_base + PITA_GPOEN); } @@ -230,9 +254,7 @@ static int pita_getscl(void *data) return (readb(card->cfg_base + PITA_GPIN) & PITA_GPIN_SCL) ? 1 : 0; } -/* - * write commands to the LED chip though the I2C-bus of the PCAN-PCIeC - */ +/* write commands to the LED chip though the I2C-bus of the PCAN-PCIeC */ static int peak_pciec_write_pca9553(struct peak_pciec_card *card, u8 offset, u8 data) { @@ -248,7 +270,7 @@ static int peak_pciec_write_pca9553(struct peak_pciec_card *card, int ret; /* cache led mask */ - if ((offset == 5) && (data == card->led_cache)) + if (offset == 5 && data == card->led_cache) return 0; ret = i2c_transfer(&card->led_chip, &msg, 1); @@ -261,9 +283,7 @@ static int peak_pciec_write_pca9553(struct peak_pciec_card *card, return 0; } -/* - * delayed work callback used to control the LEDs - */ +/* delayed work callback used to control the LEDs */ static void peak_pciec_led_work(struct work_struct *work) { struct peak_pciec_card *card = @@ -309,9 +329,7 @@ static void peak_pciec_led_work(struct work_struct *work) schedule_delayed_work(&card->led_work, HZ); } -/* - * set LEDs blinking state - */ +/* set LEDs blinking state */ static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s) { u8 new_led = card->led_cache; @@ -328,25 +346,19 @@ static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s) peak_pciec_write_pca9553(card, 5, new_led); } -/* - * start one second delayed work to control LEDs - */ +/* start one second delayed work to control LEDs */ static void peak_pciec_start_led_work(struct peak_pciec_card *card) { schedule_delayed_work(&card->led_work, HZ); } -/* - * stop LEDs delayed work - */ +/* stop LEDs delayed work */ static void peak_pciec_stop_led_work(struct peak_pciec_card *card) { cancel_delayed_work_sync(&card->led_work); } -/* - * initialize the PCA9553 4-bit I2C-bus LED chip - */ +/* initialize the PCA9553 4-bit I2C-bus LED chip */ static int peak_pciec_init_leds(struct peak_pciec_card *card) { int err; @@ -375,17 +387,14 @@ static int peak_pciec_init_leds(struct peak_pciec_card *card) return peak_pciec_write_pca9553(card, 5, PCA9553_LS0_INIT); } -/* - * restore LEDs state to off peak_pciec_leds_exit - */ +/* restore LEDs state to off peak_pciec_leds_exit */ static void peak_pciec_leds_exit(struct peak_pciec_card *card) { /* switch LEDs to off */ peak_pciec_write_pca9553(card, 5, PCA9553_LED_OFF_ALL); } -/* - * normal write sja1000 register method overloaded to catch when controller +/* normal write sja1000 register method overloaded to catch when controller * is started or stopped, to control leds */ static void peak_pciec_write_reg(const struct sja1000_priv *priv, @@ -443,7 +452,7 @@ static int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev) /* channel is the first one: do the init part */ } else { /* create the bit banging I2C adapter structure */ - card = kzalloc(sizeof(struct peak_pciec_card), GFP_KERNEL); + card = kzalloc(sizeof(*card), GFP_KERNEL); if (!card) return -ENOMEM; @@ -506,9 +515,7 @@ static void peak_pciec_remove(struct peak_pciec_card *card) #else /* CONFIG_CAN_PEAK_PCIEC */ -/* - * Placebo functions when PCAN-ExpressCard support is not selected - */ +/* Placebo functions when PCAN-ExpressCard support is not selected */ static inline int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev) { return -ENODEV; @@ -549,6 +556,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) void __iomem *cfg_base, *reg_base; u16 sub_sys_id, icr; int i, err, channels; + char fw_str[14] = ""; err = pci_enable_device(pdev); if (err) @@ -602,6 +610,21 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* Leave parport mux mode */ writeb(0x04, cfg_base + PITA_MISC + 3); + /* FPGA equipped card if not 0 */ + if (readl(cfg_base + PEAK_VER_REG1)) { + /* FPGA card: display version of the running firmware */ + u32 fw_ver = readl(cfg_base + PEAK_VER_REG2); + + snprintf(fw_str, sizeof(fw_str), " FW v%u.%u.%u", + (fw_ver >> 12) & 0xf, + (fw_ver >> 8) & 0xf, + (fw_ver >> 4) & 0xf); + } + + /* Display commercial name (and, eventually, FW version) of the card */ + dev_info(&pdev->dev, "%ux CAN %s%s\n", + channels, (const char *)ent->driver_data, fw_str); + icr = readw(cfg_base + PITA_ICR + 2); for (i = 0; i < channels; i++) { @@ -642,8 +665,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) chan->prev_dev = pci_get_drvdata(pdev); pci_set_drvdata(pdev, dev); - /* - * PCAN-ExpressCard needs some additional i2c init. + /* PCAN-ExpressCard needs some additional i2c init. * This must be done *before* register_sja1000dev() but * *after* devices linkage */ @@ -709,7 +731,8 @@ failure_disable_pci: /* pci_xxx_config_word() return positive PCIBIOS_xxx error codes while * the probe() function must return a negative errno in case of failure - * (err is unchanged if negative) */ + * (err is unchanged if negative) + */ return pcibios_err_to_errno(err); } diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c index 47c3f408a799..2b1e57552e1c 100644 --- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c +++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c @@ -15,10 +15,10 @@ #include <linux/bitfield.h> #include <linux/clk.h> #include <linux/device.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> -#include <linux/of.h> -#include <linux/of_device.h> #include <linux/pm_runtime.h> +#include <linux/property.h> #include <asm/unaligned.h> @@ -2195,8 +2195,10 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) FIELD_GET(MCP251XFD_REG_INT_IE_MASK, priv->regs_status.intf); - if (!(intf_pending)) + if (!(intf_pending)) { + can_rx_offload_threaded_irq_finish(&priv->offload); return handled; + } /* Some interrupts must be ACKed in the * MCP251XFD_REG_INT register. @@ -2296,6 +2298,8 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id) } while (1); out_fail: + can_rx_offload_threaded_irq_finish(&priv->offload); + netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n", err, priv->regs_status.intf); mcp251xfd_dump(priv); @@ -2523,8 +2527,8 @@ static int mcp251xfd_open(struct net_device *ndev) can_rx_offload_enable(&priv->offload); err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq, - IRQF_ONESHOT, dev_name(&spi->dev), - priv); + IRQF_SHARED | IRQF_ONESHOT, + dev_name(&spi->dev), priv); if (err) goto out_can_rx_offload_disable; @@ -2856,7 +2860,7 @@ static int mcp251xfd_probe(struct spi_device *spi) struct gpio_desc *rx_int; struct regulator *reg_vdd, *reg_xceiver; struct clk *clk; - u32 freq; + u32 freq = 0; int err; if (!spi->irq) @@ -2883,11 +2887,19 @@ static int mcp251xfd_probe(struct spi_device *spi) return dev_err_probe(&spi->dev, PTR_ERR(reg_xceiver), "Failed to get Transceiver regulator!\n"); - clk = devm_clk_get(&spi->dev, NULL); + clk = devm_clk_get_optional(&spi->dev, NULL); if (IS_ERR(clk)) return dev_err_probe(&spi->dev, PTR_ERR(clk), "Failed to get Oscillator (clock)!\n"); - freq = clk_get_rate(clk); + if (clk) { + freq = clk_get_rate(clk); + } else { + err = device_property_read_u32(&spi->dev, "clock-frequency", + &freq); + if (err) + return dev_err_probe(&spi->dev, err, + "Failed to get clock-frequency!\n"); + } /* Sanity check */ if (freq < MCP251XFD_SYSCLOCK_HZ_MIN || diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 73245d8836a9..353062ead98f 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -786,6 +786,8 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) int_status = hecc_read(priv, HECC_CANGIF0); } + can_rx_offload_irq_finish(&priv->offload); + return IRQ_HANDLED; } diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index 65b58f8fc328..60f3e0ca080a 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -474,7 +474,7 @@ static void esd_usb2_write_bulk_callback(struct urb *urb) netif_trans_update(netdev); } -static ssize_t show_firmware(struct device *d, +static ssize_t firmware_show(struct device *d, struct device_attribute *attr, char *buf) { struct usb_interface *intf = to_usb_interface(d); @@ -485,9 +485,9 @@ static ssize_t show_firmware(struct device *d, (dev->version >> 8) & 0xf, dev->version & 0xff); } -static DEVICE_ATTR(firmware, 0444, show_firmware, NULL); +static DEVICE_ATTR_RO(firmware); -static ssize_t show_hardware(struct device *d, +static ssize_t hardware_show(struct device *d, struct device_attribute *attr, char *buf) { struct usb_interface *intf = to_usb_interface(d); @@ -498,9 +498,9 @@ static ssize_t show_hardware(struct device *d, (dev->version >> 24) & 0xf, (dev->version >> 16) & 0xff); } -static DEVICE_ATTR(hardware, 0444, show_hardware, NULL); +static DEVICE_ATTR_RO(hardware); -static ssize_t show_nets(struct device *d, +static ssize_t nets_show(struct device *d, struct device_attribute *attr, char *buf) { struct usb_interface *intf = to_usb_interface(d); @@ -508,7 +508,7 @@ static ssize_t show_nets(struct device *d, return sprintf(buf, "%d", dev->net_count); } -static DEVICE_ATTR(nets, 0444, show_nets, NULL); +static DEVICE_ATTR_RO(nets); static int esd_usb2_send_msg(struct esd_usb2 *dev, struct esd_usb2_msg *msg) { diff --git a/drivers/net/can/usb/etas_es58x/es581_4.c b/drivers/net/can/usb/etas_es58x/es581_4.c index 1985f772fc3c..14e360c9f2c9 100644 --- a/drivers/net/can/usb/etas_es58x/es581_4.c +++ b/drivers/net/can/usb/etas_es58x/es581_4.c @@ -355,7 +355,7 @@ static int es581_4_tx_can_msg(struct es58x_priv *priv, return -EMSGSIZE; if (priv->tx_can_msg_cnt == 0) { - msg_len = 1; /* struct es581_4_bulk_tx_can_msg:num_can_msg */ + msg_len = sizeof(es581_4_urb_cmd->bulk_tx_can_msg.num_can_msg); es581_4_fill_urb_header(urb_cmd, ES581_4_CAN_COMMAND_TYPE, ES581_4_CMD_ID_TX_MSG, priv->channel_idx, msg_len); @@ -371,8 +371,7 @@ static int es581_4_tx_can_msg(struct es58x_priv *priv, return ret; /* Fill message contents. */ - tx_can_msg = (struct es581_4_tx_can_msg *) - &es581_4_urb_cmd->bulk_tx_can_msg.tx_can_msg_buf[msg_len - 1]; + tx_can_msg = (typeof(tx_can_msg))&es581_4_urb_cmd->raw_msg[msg_len]; put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id); put_unaligned_le32(priv->tx_head, &tx_can_msg->packet_idx); put_unaligned_le16((u16)es58x_get_flags(skb), &tx_can_msg->flags); diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.c b/drivers/net/can/usb/etas_es58x/es58x_core.c index 8e9102482c52..96a13c770e4a 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_core.c +++ b/drivers/net/can/usb/etas_es58x/es58x_core.c @@ -19,7 +19,7 @@ #include "es58x_core.h" #define DRV_VERSION "1.00" -MODULE_AUTHOR("Mailhol Vincent <mailhol.vincent@wanadoo.fr>"); +MODULE_AUTHOR("Vincent Mailhol <mailhol.vincent@wanadoo.fr>"); MODULE_AUTHOR("Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>"); MODULE_DESCRIPTION("Socket CAN driver for ETAS ES58X USB adapters"); MODULE_VERSION(DRV_VERSION); @@ -70,7 +70,7 @@ MODULE_DEVICE_TABLE(usb, es58x_id_table); * bytes (the start of frame) are skipped and the CRC calculation * starts on the third byte. */ -#define ES58X_CRC_CALC_OFFSET 2 +#define ES58X_CRC_CALC_OFFSET sizeof_field(union es58x_urb_cmd, sof) /** * es58x_calculate_crc() - Compute the crc16 of a given URB. @@ -2108,6 +2108,25 @@ static int es58x_init_netdev(struct es58x_device *es58x_dev, int channel_idx) } /** + * es58x_free_netdevs() - Release all network resources of the device. + * @es58x_dev: ES58X device. + */ +static void es58x_free_netdevs(struct es58x_device *es58x_dev) +{ + int i; + + for (i = 0; i < es58x_dev->num_can_ch; i++) { + struct net_device *netdev = es58x_dev->netdev[i]; + + if (!netdev) + continue; + unregister_candev(netdev); + es58x_dev->netdev[i] = NULL; + free_candev(netdev); + } +} + +/** * es58x_get_product_info() - Get the product information and print them. * @es58x_dev: ES58X device. * @@ -2152,14 +2171,13 @@ static int es58x_get_product_info(struct es58x_device *es58x_dev) /** * es58x_init_es58x_dev() - Initialize the ES58X device. * @intf: USB interface. - * @p_es58x_dev: pointer to the address of the ES58X device. * @driver_info: Quirks of the device. * - * Return: zero on success, errno when any error occurs. + * Return: pointer to an ES58X device on success, error pointer when + * any error occurs. */ -static int es58x_init_es58x_dev(struct usb_interface *intf, - struct es58x_device **p_es58x_dev, - kernel_ulong_t driver_info) +static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf, + kernel_ulong_t driver_info) { struct device *dev = &intf->dev; struct es58x_device *es58x_dev; @@ -2176,7 +2194,7 @@ static int es58x_init_es58x_dev(struct usb_interface *intf, ret = usb_find_common_endpoints(intf->cur_altsetting, &ep_in, &ep_out, NULL, NULL); if (ret) - return ret; + return ERR_PTR(ret); if (driver_info & ES58X_FD_FAMILY) { param = &es58x_fd_param; @@ -2186,9 +2204,10 @@ static int es58x_init_es58x_dev(struct usb_interface *intf, ops = &es581_4_ops; } - es58x_dev = kzalloc(es58x_sizeof_es58x_device(param), GFP_KERNEL); + es58x_dev = devm_kzalloc(dev, es58x_sizeof_es58x_device(param), + GFP_KERNEL); if (!es58x_dev) - return -ENOMEM; + return ERR_PTR(-ENOMEM); es58x_dev->param = param; es58x_dev->ops = ops; @@ -2213,9 +2232,7 @@ static int es58x_init_es58x_dev(struct usb_interface *intf, ep_out->bEndpointAddress); es58x_dev->rx_max_packet_size = le16_to_cpu(ep_in->wMaxPacketSize); - *p_es58x_dev = es58x_dev; - - return 0; + return es58x_dev; } /** @@ -2232,30 +2249,21 @@ static int es58x_probe(struct usb_interface *intf, struct es58x_device *es58x_dev; int ch_idx, ret; - ret = es58x_init_es58x_dev(intf, &es58x_dev, id->driver_info); - if (ret) - return ret; + es58x_dev = es58x_init_es58x_dev(intf, id->driver_info); + if (IS_ERR(es58x_dev)) + return PTR_ERR(es58x_dev); ret = es58x_get_product_info(es58x_dev); if (ret) - goto cleanup_es58x_dev; + return ret; for (ch_idx = 0; ch_idx < es58x_dev->num_can_ch; ch_idx++) { ret = es58x_init_netdev(es58x_dev, ch_idx); - if (ret) - goto cleanup_candev; - } - - return ret; - - cleanup_candev: - for (ch_idx = 0; ch_idx < es58x_dev->num_can_ch; ch_idx++) - if (es58x_dev->netdev[ch_idx]) { - unregister_candev(es58x_dev->netdev[ch_idx]); - free_candev(es58x_dev->netdev[ch_idx]); + if (ret) { + es58x_free_netdevs(es58x_dev); + return ret; } - cleanup_es58x_dev: - kfree(es58x_dev); + } return ret; } @@ -2270,24 +2278,12 @@ static int es58x_probe(struct usb_interface *intf, static void es58x_disconnect(struct usb_interface *intf) { struct es58x_device *es58x_dev = usb_get_intfdata(intf); - struct net_device *netdev; - int i; dev_info(&intf->dev, "Disconnecting %s %s\n", es58x_dev->udev->manufacturer, es58x_dev->udev->product); - for (i = 0; i < es58x_dev->num_can_ch; i++) { - netdev = es58x_dev->netdev[i]; - if (!netdev) - continue; - unregister_candev(netdev); - es58x_dev->netdev[i] = NULL; - free_candev(netdev); - } - + es58x_free_netdevs(es58x_dev); es58x_free_urbs(es58x_dev); - - kfree(es58x_dev); usb_set_intfdata(intf, NULL); } diff --git a/drivers/net/can/usb/etas_es58x/es58x_core.h b/drivers/net/can/usb/etas_es58x/es58x_core.h index fcf219e727bf..826a15871573 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_core.h +++ b/drivers/net/can/usb/etas_es58x/es58x_core.h @@ -287,7 +287,7 @@ struct es58x_priv { * @rx_urb_cmd_max_len: Maximum length of a RX URB command. * @fifo_mask: Bit mask to quickly convert the tx_tail and tx_head * field of the struct es58x_priv into echo_skb - * indexes. Properties: @fifo_mask = echos_skb_max - 1 where + * indexes. Properties: @fifo_mask = echo_skb_max - 1 where * echo_skb_max must be a power of two. Also, echo_skb_max must * not exceed the maximum size of the device internal TX FIFO * length. This parameter is used to control the network queue diff --git a/drivers/net/can/usb/etas_es58x/es58x_fd.c b/drivers/net/can/usb/etas_es58x/es58x_fd.c index 1a2779d383a4..af042aa55f59 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_fd.c +++ b/drivers/net/can/usb/etas_es58x/es58x_fd.c @@ -357,8 +357,7 @@ static int es58x_fd_tx_can_msg(struct es58x_priv *priv, return ret; /* Fill message contents. */ - tx_can_msg = (struct es58x_fd_tx_can_msg *) - &es58x_fd_urb_cmd->tx_can_msg_buf[msg_len]; + tx_can_msg = (typeof(tx_can_msg))&es58x_fd_urb_cmd->raw_msg[msg_len]; tx_can_msg->packet_idx = (u8)priv->tx_head; put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id); tx_can_msg->flags = (u8)es58x_get_flags(skb); @@ -463,9 +462,9 @@ static int es58x_fd_get_timestamp(struct es58x_device *es58x_dev) } /* Nominal bittiming constants for ES582.1 and ES584.1 as specified in - * the microcontroller datasheet: "SAM E701/S70/V70/V71 Family" - * section 49.6.8 "MCAN Nominal Bit Timing and Prescaler Register" - * from Microchip. + * the microcontroller datasheet: "SAM E70/S70/V70/V71 Family" section + * 49.6.8 "MCAN Nominal Bit Timing and Prescaler Register" from + * Microchip. * * The values from the specification are the hardware register * values. To convert them to the functional values, all ranges were @@ -484,8 +483,8 @@ static const struct can_bittiming_const es58x_fd_nom_bittiming_const = { }; /* Data bittiming constants for ES582.1 and ES584.1 as specified in - * the microcontroller datasheet: "SAM E701/S70/V70/V71 Family" - * section 49.6.4 "MCAN Data Bit Timing and Prescaler Register" from + * the microcontroller datasheet: "SAM E70/S70/V70/V71 Family" section + * 49.6.4 "MCAN Data Bit Timing and Prescaler Register" from * Microchip. */ static const struct can_bittiming_const es58x_fd_data_bittiming_const = { @@ -501,9 +500,9 @@ static const struct can_bittiming_const es58x_fd_data_bittiming_const = { }; /* Transmission Delay Compensation constants for ES582.1 and ES584.1 - * as specified in the microcontroller datasheet: "SAM - * E701/S70/V70/V71 Family" section 49.6.15 "MCAN Transmitter Delay - * Compensation Register" from Microchip. + * as specified in the microcontroller datasheet: "SAM E70/S70/V70/V71 + * Family" section 49.6.15 "MCAN Transmitter Delay Compensation + * Register" from Microchip. */ static const struct can_tdc_const es58x_tdc_const = { .tdcv_max = 0, /* Manual mode not supported. */ diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c index 1d6f77252f01..e36e60c3703a 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c @@ -63,6 +63,8 @@ #define PCAN_USB_MSG_HEADER_LEN 2 +#define PCAN_USB_MSG_TX_CAN 2 /* Tx msg is a CAN frame */ + /* PCAN-USB adapter internal clock (MHz) */ #define PCAN_USB_CRYSTAL_HZ 16000000 @@ -73,6 +75,10 @@ #define PCAN_USB_STATUSLEN_RTR (1 << 4) #define PCAN_USB_STATUSLEN_DLC (0xf) +/* PCAN-USB 4.1 CAN Id tx extended flags */ +#define PCAN_USB_TX_SRR 0x01 /* SJA1000 SRR command */ +#define PCAN_USB_TX_AT 0x02 /* SJA1000 AT command */ + /* PCAN-USB error flags */ #define PCAN_USB_ERROR_TXFULL 0x01 #define PCAN_USB_ERROR_RXQOVR 0x02 @@ -384,7 +390,8 @@ static int pcan_usb_get_device_id(struct peak_usb_device *dev, u32 *device_id) if (err) netdev_err(dev->netdev, "getting device id failure: %d\n", err); - *device_id = args[0]; + else + *device_id = args[0]; return err; } @@ -445,145 +452,65 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n, { struct sk_buff *skb; struct can_frame *cf; - enum can_state new_state; + enum can_state new_state = CAN_STATE_ERROR_ACTIVE; /* ignore this error until 1st ts received */ if (n == PCAN_USB_ERROR_QOVR) if (!mc->pdev->time_ref.tick_count) return 0; - new_state = mc->pdev->dev.can.state; - - switch (mc->pdev->dev.can.state) { - case CAN_STATE_ERROR_ACTIVE: - if (n & PCAN_USB_ERROR_BUS_LIGHT) { - new_state = CAN_STATE_ERROR_WARNING; - break; - } - fallthrough; - - case CAN_STATE_ERROR_WARNING: - if (n & PCAN_USB_ERROR_BUS_HEAVY) { - new_state = CAN_STATE_ERROR_PASSIVE; - break; - } - if (n & PCAN_USB_ERROR_BUS_OFF) { - new_state = CAN_STATE_BUS_OFF; - break; - } - if (n & ~PCAN_USB_ERROR_BUS) { - /* - * trick to bypass next comparison and process other - * errors - */ - new_state = CAN_STATE_MAX; - break; - } - if ((n & PCAN_USB_ERROR_BUS_LIGHT) == 0) { - /* no error (back to active state) */ - new_state = CAN_STATE_ERROR_ACTIVE; - break; - } - break; - - case CAN_STATE_ERROR_PASSIVE: - if (n & PCAN_USB_ERROR_BUS_OFF) { - new_state = CAN_STATE_BUS_OFF; - break; - } - if (n & PCAN_USB_ERROR_BUS_LIGHT) { - new_state = CAN_STATE_ERROR_WARNING; - break; - } - if (n & ~PCAN_USB_ERROR_BUS) { - /* - * trick to bypass next comparison and process other - * errors - */ - new_state = CAN_STATE_MAX; - break; - } - - if ((n & PCAN_USB_ERROR_BUS_HEAVY) == 0) { - /* no error (back to warning state) */ - new_state = CAN_STATE_ERROR_WARNING; - break; - } - break; - - default: - /* do nothing waiting for restart */ - return 0; - } - - /* donot post any error if current state didn't change */ - if (mc->pdev->dev.can.state == new_state) - return 0; - /* allocate an skb to store the error frame */ skb = alloc_can_err_skb(mc->netdev, &cf); - if (!skb) - return -ENOMEM; - - switch (new_state) { - case CAN_STATE_BUS_OFF: - cf->can_id |= CAN_ERR_BUSOFF; - mc->pdev->dev.can.can_stats.bus_off++; - can_bus_off(mc->netdev); - break; - - case CAN_STATE_ERROR_PASSIVE: - cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = (mc->pdev->bec.txerr > mc->pdev->bec.rxerr) ? - CAN_ERR_CRTL_TX_PASSIVE : - CAN_ERR_CRTL_RX_PASSIVE; - cf->data[6] = mc->pdev->bec.txerr; - cf->data[7] = mc->pdev->bec.rxerr; - - mc->pdev->dev.can.can_stats.error_passive++; - break; - - case CAN_STATE_ERROR_WARNING: - cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = (mc->pdev->bec.txerr > mc->pdev->bec.rxerr) ? - CAN_ERR_CRTL_TX_WARNING : - CAN_ERR_CRTL_RX_WARNING; - cf->data[6] = mc->pdev->bec.txerr; - cf->data[7] = mc->pdev->bec.rxerr; - - mc->pdev->dev.can.can_stats.error_warning++; - break; - case CAN_STATE_ERROR_ACTIVE: - cf->can_id |= CAN_ERR_CRTL; - cf->data[1] = CAN_ERR_CRTL_ACTIVE; - - /* sync local copies of rxerr/txerr counters */ - mc->pdev->bec.txerr = 0; - mc->pdev->bec.rxerr = 0; - break; - - default: - /* CAN_STATE_MAX (trick to handle other errors) */ - if (n & PCAN_USB_ERROR_TXQFULL) - netdev_dbg(mc->netdev, "device Tx queue full)\n"); - - if (n & PCAN_USB_ERROR_RXQOVR) { - netdev_dbg(mc->netdev, "data overrun interrupt\n"); + if (n & PCAN_USB_ERROR_RXQOVR) { + /* data overrun interrupt */ + netdev_dbg(mc->netdev, "data overrun interrupt\n"); + mc->netdev->stats.rx_over_errors++; + mc->netdev->stats.rx_errors++; + if (cf) { cf->can_id |= CAN_ERR_CRTL; cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; - mc->netdev->stats.rx_over_errors++; - mc->netdev->stats.rx_errors++; } + } - cf->data[6] = mc->pdev->bec.txerr; - cf->data[7] = mc->pdev->bec.rxerr; + if (n & PCAN_USB_ERROR_TXQFULL) + netdev_dbg(mc->netdev, "device Tx queue full)\n"); - new_state = mc->pdev->dev.can.state; - break; + if (n & PCAN_USB_ERROR_BUS_OFF) { + new_state = CAN_STATE_BUS_OFF; + } else if (n & PCAN_USB_ERROR_BUS_HEAVY) { + new_state = ((mc->pdev->bec.txerr >= 128) || + (mc->pdev->bec.rxerr >= 128)) ? + CAN_STATE_ERROR_PASSIVE : + CAN_STATE_ERROR_WARNING; + } else { + new_state = CAN_STATE_ERROR_ACTIVE; } - mc->pdev->dev.can.state = new_state; + /* handle change of state */ + if (new_state != mc->pdev->dev.can.state) { + enum can_state tx_state = + (mc->pdev->bec.txerr >= mc->pdev->bec.rxerr) ? + new_state : 0; + enum can_state rx_state = + (mc->pdev->bec.txerr <= mc->pdev->bec.rxerr) ? + new_state : 0; + + can_change_state(mc->netdev, cf, tx_state, rx_state); + + if (new_state == CAN_STATE_BUS_OFF) { + can_bus_off(mc->netdev); + } else if (cf && (cf->can_id & CAN_ERR_CRTL)) { + /* Supply TX/RX error counters in case of + * controller error. + */ + cf->data[6] = mc->pdev->bec.txerr; + cf->data[7] = mc->pdev->bec.rxerr; + } + } + + if (!skb) + return -ENOMEM; if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) { struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb); @@ -704,6 +631,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) struct sk_buff *skb; struct can_frame *cf; struct skb_shared_hwtstamps *hwts; + u32 can_id_flags; skb = alloc_can_skb(mc->netdev, &cf); if (!skb) @@ -713,13 +641,15 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) if ((mc->ptr + 4) > mc->end) goto decode_failed; - cf->can_id = get_unaligned_le32(mc->ptr) >> 3 | CAN_EFF_FLAG; + can_id_flags = get_unaligned_le32(mc->ptr); + cf->can_id = can_id_flags >> 3 | CAN_EFF_FLAG; mc->ptr += 4; } else { if ((mc->ptr + 2) > mc->end) goto decode_failed; - cf->can_id = get_unaligned_le16(mc->ptr) >> 5; + can_id_flags = get_unaligned_le16(mc->ptr); + cf->can_id = can_id_flags >> 5; mc->ptr += 2; } @@ -742,6 +672,10 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len) memcpy(cf->data, mc->ptr, cf->len); mc->ptr += rec_len; + + /* Ignore next byte (client private id) if SRR bit is set */ + if (can_id_flags & PCAN_USB_TX_SRR) + mc->ptr++; } /* convert timestamp into kernel time */ @@ -819,10 +753,11 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb, struct net_device *netdev = dev->netdev; struct net_device_stats *stats = &netdev->stats; struct can_frame *cf = (struct can_frame *)skb->data; + u32 can_id_flags = cf->can_id & CAN_ERR_MASK; u8 *pc; - obuf[0] = 2; - obuf[1] = 1; + obuf[0] = PCAN_USB_MSG_TX_CAN; + obuf[1] = 1; /* only one CAN frame is stored in the packet */ pc = obuf + PCAN_USB_MSG_HEADER_LEN; @@ -837,12 +772,28 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb, *pc |= PCAN_USB_STATUSLEN_EXT_ID; pc++; - put_unaligned_le32((cf->can_id & CAN_ERR_MASK) << 3, pc); + can_id_flags <<= 3; + + if (dev->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) + can_id_flags |= PCAN_USB_TX_SRR; + + if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) + can_id_flags |= PCAN_USB_TX_AT; + + put_unaligned_le32(can_id_flags, pc); pc += 4; } else { pc++; - put_unaligned_le16((cf->can_id & CAN_ERR_MASK) << 5, pc); + can_id_flags <<= 5; + + if (dev->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) + can_id_flags |= PCAN_USB_TX_SRR; + + if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT) + can_id_flags |= PCAN_USB_TX_AT; + + put_unaligned_le16(can_id_flags, pc); pc += 2; } @@ -852,6 +803,10 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb, pc += cf->len; } + /* SRR bit needs a writer id (useless here) */ + if (can_id_flags & PCAN_USB_TX_SRR) + *pc++ = 0x80; + obuf[(*size)-1] = (u8)(stats->tx_packets & 0xff); return 0; @@ -926,6 +881,19 @@ static int pcan_usb_init(struct peak_usb_device *dev) return err; } + /* Since rev 4.1, PCAN-USB is able to make single-shot as well as + * looped back frames. + */ + if (dev->device_rev >= 41) { + struct can_priv *priv = netdev_priv(dev->netdev); + + priv->ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT | + CAN_CTRLMODE_LOOPBACK; + } else { + dev_info(dev->netdev->dev.parent, + "Firmware update available. Please contact support@peak-system.com\n"); + } + dev_info(dev->netdev->dev.parent, "PEAK-System %s adapter hwrev %u serial %08X (%u channel)\n", pcan_usb.name, dev->device_rev, serial_number, diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index ae7a3411167c..9de6e9053e34 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -37,7 +37,7 @@ * quanta, from when the bit is sent on the TX pin to when it is * received on the RX pin of the transmitter. Possible options: * - * O: automatic mode. The controller dynamically measure @tdcv + * 0: automatic mode. The controller dynamically measures @tdcv * for each transmitted CAN FD frame. * * Other values: manual mode. Use the fixed provided value. @@ -45,7 +45,7 @@ * @tdco: Transmitter Delay Compensation Offset. Offset value, in time * quanta, defining the distance between the start of the bit * reception on the RX pin of the transceiver and the SSP - * position such as SSP = @tdcv + @tdco. + * position such that SSP = @tdcv + @tdco. * * If @tdco is zero, then TDC is disabled and both @tdcv and * @tdcf should be ignored. diff --git a/include/linux/can/platform/flexcan.h b/include/linux/can/platform/flexcan.h new file mode 100644 index 000000000000..1b536fb999de --- /dev/null +++ b/include/linux/can/platform/flexcan.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2021 Angelo Dureghello <angelo@kernel-space.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * version 2 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. + */ + +#ifndef _CAN_PLATFORM_FLEXCAN_H +#define _CAN_PLATFORM_FLEXCAN_H + +struct flexcan_platform_data { + u32 clock_frequency; + u8 clk_src; +}; + +#endif /* _CAN_PLATFORM_FLEXCAN_H */ diff --git a/include/linux/can/rx-offload.h b/include/linux/can/rx-offload.h index 40882df7105e..c11477620403 100644 --- a/include/linux/can/rx-offload.h +++ b/include/linux/can/rx-offload.h @@ -20,6 +20,7 @@ struct can_rx_offload { bool drop); struct sk_buff_head skb_queue; + struct sk_buff_head skb_irq_queue; u32 skb_queue_len_max; unsigned int mb_first; @@ -48,14 +49,11 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload, unsigned int *frame_len_ptr); int can_rx_offload_queue_tail(struct can_rx_offload *offload, struct sk_buff *skb); +void can_rx_offload_irq_finish(struct can_rx_offload *offload); +void can_rx_offload_threaded_irq_finish(struct can_rx_offload *offload); void can_rx_offload_del(struct can_rx_offload *offload); void can_rx_offload_enable(struct can_rx_offload *offload); -static inline void can_rx_offload_schedule(struct can_rx_offload *offload) -{ - napi_schedule(&offload->napi); -} - static inline void can_rx_offload_disable(struct can_rx_offload *offload) { napi_disable(&offload->napi); diff --git a/net/can/j1939/socket.c b/net/can/j1939/socket.c index 54f6d521492f..b904c06ab0cf 100644 --- a/net/can/j1939/socket.c +++ b/net/can/j1939/socket.c @@ -352,7 +352,7 @@ static void j1939_sk_sock_destruct(struct sock *sk) { struct j1939_sock *jsk = j1939_sk(sk); - /* This function will be call by the generic networking code, when then + /* This function will be called by the generic networking code, when * the socket is ultimately closed (sk->sk_destruct). * * The race between diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c index c3946c355882..efdf79de3db6 100644 --- a/net/can/j1939/transport.c +++ b/net/can/j1939/transport.c @@ -776,7 +776,7 @@ static int j1939_session_tx_dpo(struct j1939_session *session) static int j1939_session_tx_dat(struct j1939_session *session) { struct j1939_priv *priv = session->priv; - struct j1939_sk_buff_cb *skcb; + struct j1939_sk_buff_cb *se_skcb; int offset, pkt_done, pkt_end; unsigned int len, pdelay; struct sk_buff *se_skb; @@ -788,7 +788,7 @@ static int j1939_session_tx_dat(struct j1939_session *session) if (!se_skb) return -ENOBUFS; - skcb = j1939_skb_to_cb(se_skb); + se_skcb = j1939_skb_to_cb(se_skb); tpdat = se_skb->data; ret = 0; pkt_done = 0; @@ -800,7 +800,7 @@ static int j1939_session_tx_dat(struct j1939_session *session) while (session->pkt.tx < pkt_end) { dat[0] = session->pkt.tx - session->pkt.dpo + 1; - offset = (session->pkt.tx * 7) - skcb->offset; + offset = (session->pkt.tx * 7) - se_skcb->offset; len = se_skb->len - offset; if (len > 7) len = 7; @@ -808,7 +808,8 @@ static int j1939_session_tx_dat(struct j1939_session *session) if (offset + len > se_skb->len) { netdev_err_once(priv->ndev, "%s: 0x%p: requested data outside of queued buffer: offset %i, len %i, pkt.tx: %i\n", - __func__, session, skcb->offset, se_skb->len , session->pkt.tx); + __func__, session, se_skcb->offset, + se_skb->len , session->pkt.tx); ret = -EOVERFLOW; goto out_free; } @@ -1092,7 +1093,7 @@ j1939_session_deactivate_activate_next(struct j1939_session *session) } static void __j1939_session_cancel(struct j1939_session *session, - enum j1939_xtp_abort err) + enum j1939_xtp_abort err) { struct j1939_priv *priv = session->priv; @@ -1190,13 +1191,13 @@ static enum hrtimer_restart j1939_tp_txtimer(struct hrtimer *hrtimer) static void j1939_session_completed(struct j1939_session *session) { - struct sk_buff *skb; + struct sk_buff *se_skb; if (!session->transmission) { - skb = j1939_session_skb_get(session); + se_skb = j1939_session_skb_get(session); /* distribute among j1939 receivers */ - j1939_sk_recv(session->priv, skb); - consume_skb(skb); + j1939_sk_recv(session->priv, se_skb); + consume_skb(se_skb); } j1939_session_deactivate_activate_next(session); @@ -1263,12 +1264,14 @@ static bool j1939_xtp_rx_cmd_bad_pgn(struct j1939_session *session, break; case J1939_ETP_CMD_RTS: - case J1939_TP_CMD_RTS: /* fall through */ + fallthrough; + case J1939_TP_CMD_RTS: abort = J1939_XTP_ABORT_BUSY; break; case J1939_ETP_CMD_CTS: - case J1939_TP_CMD_CTS: /* fall through */ + fallthrough; + case J1939_TP_CMD_CTS: abort = J1939_XTP_ABORT_ECTS_UNXPECTED_PGN; break; @@ -1277,7 +1280,8 @@ static bool j1939_xtp_rx_cmd_bad_pgn(struct j1939_session *session, break; case J1939_ETP_CMD_EOMA: - case J1939_TP_CMD_EOMA: /* fall through */ + fallthrough; + case J1939_TP_CMD_EOMA: abort = J1939_XTP_ABORT_OTHER; break; @@ -1767,7 +1771,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session, struct sk_buff *skb) { struct j1939_priv *priv = session->priv; - struct j1939_sk_buff_cb *skcb; + struct j1939_sk_buff_cb *skcb, *se_skcb; struct sk_buff *se_skb = NULL; const u8 *dat; u8 *tpdat; @@ -1792,7 +1796,8 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session, break; fallthrough; case J1939_TP_CMD_BAM: - case J1939_TP_CMD_CTS: /* fall through */ + fallthrough; + case J1939_TP_CMD_CTS: if (skcb->addr.type != J1939_ETP) break; fallthrough; @@ -1817,8 +1822,8 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session, goto out_session_cancel; } - skcb = j1939_skb_to_cb(se_skb); - offset = packet * 7 - skcb->offset; + se_skcb = j1939_skb_to_cb(se_skb); + offset = packet * 7 - se_skcb->offset; nbytes = se_skb->len - offset; if (nbytes > 7) nbytes = 7; @@ -1846,7 +1851,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session, if (packet == session->pkt.rx) session->pkt.rx++; - if (skcb->addr.type != J1939_ETP && + if (se_skcb->addr.type != J1939_ETP && j1939_cb_is_broadcast(&session->skcb)) { if (session->pkt.rx >= session->pkt.total) final = true; @@ -1995,7 +2000,8 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb) extd = J1939_ETP; fallthrough; case J1939_TP_CMD_BAM: - case J1939_TP_CMD_RTS: /* fall through */ + fallthrough; + case J1939_TP_CMD_RTS: if (skcb->addr.type != extd) return; |