From 1910cd88539c07abf34a558a0976b506483c377c Mon Sep 17 00:00:00 2001 From: Christer Beskow Date: Tue, 6 Aug 2019 09:29:38 +0200 Subject: [PATCH 01/41] can: kvaser_pciefd: kvaser_pciefd_pwm_stop(): remove unnecessary code when setting pwm duty cycle to zero To set the duty cycle to zero (i.e. pwm_stop), the trigger value shall be equal to the top value. This is achieved by reading the value of the top bit field from the pwm register and then writing back this value to the trigger and top bit fields. Addresses-Coverity: ("Logically dead code") Reported-by: Colin Ian King Signed-off-by: Christer Beskow Signed-off-by: Marc Kleine-Budde --- drivers/net/can/kvaser_pciefd.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index 3af747cbbde4..ccba42c544a3 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -643,7 +643,7 @@ static int kvaser_pciefd_bus_on(struct kvaser_pciefd_can *can) static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can) { - int top, trigger; + u8 top; u32 pwm_ctrl; unsigned long irq; @@ -651,12 +651,8 @@ static void kvaser_pciefd_pwm_stop(struct kvaser_pciefd_can *can) pwm_ctrl = ioread32(can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); top = (pwm_ctrl >> KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT) & 0xff; - trigger = (100 * top + 50) / 100; - if (trigger < 0) - trigger = 0; - - pwm_ctrl = trigger & 0xff; - pwm_ctrl |= (top & 0xff) << KVASER_PCIEFD_KCAN_PWM_TOP_SHIFT; + /* Set duty cycle to zero */ + pwm_ctrl |= top; iowrite32(pwm_ctrl, can->reg_base + KVASER_PCIEFD_KCAN_PWM_REG); spin_unlock_irqrestore(&can->lock, irq); } From 5549369cfde0f86799bff110ce46c3721c19e2ca Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 25 Jul 2019 07:02:17 +0000 Subject: [PATCH 02/41] can: kvaser_pciefd: Remove unused including Remove including that don't need it. Reported-by: Hulk Robot Signed-off-by: YueHaibing Signed-off-by: Marc Kleine-Budde --- drivers/net/can/kvaser_pciefd.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/can/kvaser_pciefd.c b/drivers/net/can/kvaser_pciefd.c index ccba42c544a3..f9815fda8840 100644 --- a/drivers/net/can/kvaser_pciefd.c +++ b/drivers/net/can/kvaser_pciefd.c @@ -7,7 +7,6 @@ */ #include -#include #include #include #include From 175a60b73b1789dc624d16b8e24f5c3c9114d448 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 25 Jul 2019 06:59:40 +0000 Subject: [PATCH 03/41] can: sja1000: f81601: remove unused including Remove including that don't need it. Signed-off-by: YueHaibing Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sja1000/f81601.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/can/sja1000/f81601.c b/drivers/net/can/sja1000/f81601.c index 362a9d4f44d5..8f25e95814ef 100644 --- a/drivers/net/can/sja1000/f81601.c +++ b/drivers/net/can/sja1000/f81601.c @@ -14,7 +14,6 @@ #include #include #include -#include #include "sja1000.h" From 99a3d7c122431c625d368fb959aa0de5fa94a85b Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:16:29 +0200 Subject: [PATCH 04/41] can: ti_hecc: convert block comments to network style comments This patch converts all block comments to network subsystem style block comments. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index b62f75fa03f0..0448b9a78ed2 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -46,8 +46,7 @@ MODULE_VERSION(HECC_MODULE_VERSION); #define HECC_MAX_MAILBOXES 32 /* hardware mailboxes - do not change */ #define MAX_TX_PRIO 0x3F /* hardware value - do not change */ -/* - * Important Note: TX mailbox configuration +/* Important Note: TX mailbox configuration * TX mailboxes should be restricted to the number of SKB buffers to avoid * maintaining SKB buffers separately. TX mailboxes should be a power of 2 * for the mailbox logic to work. Top mailbox numbers are reserved for RX @@ -309,8 +308,7 @@ static void ti_hecc_reset(struct net_device *ndev) /* Set change control request and wait till enabled */ hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_CCR); - /* - * INFO: It has been observed that at times CCE bit may not be + /* INFO: It has been observed that at times CCE bit may not be * set and hw seems to be ok even if this bit is not set so * timing out with a timing of 1ms to respect the specs */ @@ -320,8 +318,7 @@ static void ti_hecc_reset(struct net_device *ndev) udelay(10); } - /* - * Note: On HECC, BTC can be programmed only in initialization mode, so + /* Note: On HECC, BTC can be programmed only in initialization mode, so * it is expected that the can bittiming parameters are set via ip * utility before the device is opened */ @@ -330,13 +327,11 @@ static void ti_hecc_reset(struct net_device *ndev) /* Clear CCR (and CANMC register) and wait for CCE = 0 enable */ hecc_write(priv, HECC_CANMC, 0); - /* - * INFO: CAN net stack handles bus off and hence disabling auto-bus-on + /* INFO: CAN net stack handles bus off and hence disabling auto-bus-on * hecc_set_bit(priv, HECC_CANMC, HECC_CANMC_ABO); */ - /* - * INFO: It has been observed that at times CCE bit may not be + /* INFO: It has been observed that at times CCE bit may not be * set and hw seems to be ok even if this bit is not set so */ cnt = HECC_CCE_WAIT_COUNT; @@ -439,8 +434,7 @@ static int ti_hecc_get_berr_counter(const struct net_device *ndev, return 0; } -/* - * ti_hecc_xmit: HECC Transmit +/* ti_hecc_xmit: HECC Transmit * * The transmit mailboxes start from 0 to HECC_MAX_TX_MBOX. In HECC the * priority of the mailbox for tranmission is dependent upon priority setting @@ -601,8 +595,7 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR); } - /* - * Need to check busoff condition in error status register too to + /* Need to check busoff condition in error status register too to * ensure warning interrupts don't hog the system */ if ((int_status & HECC_CANGIF_BOIF) || (err_status & HECC_CANES_BO)) { From d5f1a984edd8aebcc3de96905047137931b0f8a5 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 25 Jul 2019 15:07:19 +0200 Subject: [PATCH 05/41] can: ti_hecc: fix indention This patch fixes the indention in the driver. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 41 ++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 0448b9a78ed2..c5d80a126e21 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -222,7 +222,7 @@ static inline u32 hecc_read_stamp(struct ti_hecc_priv *priv, u32 mbxno) } static inline void hecc_write_mbx(struct ti_hecc_priv *priv, u32 mbxno, - u32 reg, u32 val) + u32 reg, u32 val) { __raw_writel(val, priv->mbx + mbxno * 0x10 + reg); } @@ -243,13 +243,13 @@ static inline u32 hecc_read(struct ti_hecc_priv *priv, int reg) } static inline void hecc_set_bit(struct ti_hecc_priv *priv, int reg, - u32 bit_mask) + u32 bit_mask) { hecc_write(priv, reg, hecc_read(priv, reg) | bit_mask); } static inline void hecc_clear_bit(struct ti_hecc_priv *priv, int reg, - u32 bit_mask) + u32 bit_mask) { hecc_write(priv, reg, hecc_read(priv, reg) & ~bit_mask); } @@ -390,7 +390,7 @@ static void ti_hecc_start(struct net_device *ndev) } else { hecc_write(priv, HECC_CANMIL, 0); hecc_write(priv, HECC_CANGIM, - HECC_CANGIM_DEF_MASK | HECC_CANGIM_I0EN); + HECC_CANGIM_DEF_MASK | HECC_CANGIM_I0EN); } priv->can.state = CAN_STATE_ERROR_ACTIVE; } @@ -424,7 +424,7 @@ static int ti_hecc_do_set_mode(struct net_device *ndev, enum can_mode mode) } static int ti_hecc_get_berr_counter(const struct net_device *ndev, - struct can_berr_counter *bec) + struct can_berr_counter *bec) { struct ti_hecc_priv *priv = netdev_priv(ndev); @@ -472,8 +472,8 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) spin_unlock_irqrestore(&priv->mbx_lock, flags); netif_stop_queue(ndev); netdev_err(priv->ndev, - "BUG: TX mbx not ready tx_head=%08X, tx_tail=%08X\n", - priv->tx_head, priv->tx_tail); + "BUG: TX mbx not ready tx_head=%08X, tx_tail=%08X\n", + priv->tx_head, priv->tx_tail); return NETDEV_TX_BUSY; } spin_unlock_irqrestore(&priv->mbx_lock, flags); @@ -490,10 +490,10 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) data = (cf->can_id & CAN_SFF_MASK) << 18; hecc_write_mbx(priv, mbxno, HECC_CANMID, data); hecc_write_mbx(priv, mbxno, HECC_CANMDL, - be32_to_cpu(*(__be32 *)(cf->data))); + be32_to_cpu(*(__be32 *)(cf->data))); if (cf->can_dlc > 4) hecc_write_mbx(priv, mbxno, HECC_CANMDH, - be32_to_cpu(*(__be32 *)(cf->data + 4))); + be32_to_cpu(*(__be32 *)(cf->data + 4))); else *(u32 *)(cf->data + 4) = 0; can_put_echo_skb(skb, ndev, mbxno); @@ -501,7 +501,7 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) spin_lock_irqsave(&priv->mbx_lock, flags); --priv->tx_head; if ((hecc_read(priv, HECC_CANME) & BIT(get_tx_head_mb(priv))) || - (priv->tx_head & HECC_TX_MASK) == HECC_TX_MASK) { + (priv->tx_head & HECC_TX_MASK) == HECC_TX_MASK) { netif_stop_queue(ndev); } hecc_set_bit(priv, HECC_CANME, mbx_mask); @@ -549,7 +549,7 @@ static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload, } static int ti_hecc_error(struct net_device *ndev, int int_status, - int err_status) + int err_status) { struct ti_hecc_priv *priv = netdev_priv(ndev); struct can_frame *cf; @@ -649,15 +649,16 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) unsigned long flags, rx_pending; int_status = hecc_read(priv, - (priv->use_hecc1int) ? HECC_CANGIF1 : HECC_CANGIF0); + priv->use_hecc1int ? + HECC_CANGIF1 : HECC_CANGIF0); if (!int_status) return IRQ_NONE; err_status = hecc_read(priv, HECC_CANES); if (err_status & (HECC_BUS_ERROR | HECC_CANES_BO | - HECC_CANES_EP | HECC_CANES_EW)) - ti_hecc_error(ndev, int_status, err_status); + HECC_CANES_EP | HECC_CANES_EW)) + ti_hecc_error(ndev, int_status, err_status); if (int_status & HECC_CANGIF_GMIF) { while (priv->tx_tail - priv->tx_head > 0) { @@ -679,10 +680,10 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) } /* restart queue if wrap-up or if queue stalled on last pkt */ - if (((priv->tx_head == priv->tx_tail) && - ((priv->tx_head & HECC_TX_MASK) != HECC_TX_MASK)) || - (((priv->tx_tail & HECC_TX_MASK) == HECC_TX_MASK) && - ((priv->tx_head & HECC_TX_MASK) == HECC_TX_MASK))) + if ((priv->tx_head == priv->tx_tail && + ((priv->tx_head & HECC_TX_MASK) != HECC_TX_MASK)) || + (((priv->tx_tail & HECC_TX_MASK) == HECC_TX_MASK) && + ((priv->tx_head & HECC_TX_MASK) == HECC_TX_MASK))) netif_wake_queue(ndev); /* offload RX mailboxes and let NAPI deliver them */ @@ -711,7 +712,7 @@ static int ti_hecc_open(struct net_device *ndev) int err; err = request_irq(ndev->irq, ti_hecc_interrupt, IRQF_SHARED, - ndev->name, ndev); + ndev->name, ndev); if (err) { netdev_err(ndev, "error requesting interrupt\n"); return err; @@ -887,7 +888,7 @@ static int ti_hecc_probe(struct platform_device *pdev) devm_can_led_init(ndev); dev_info(&pdev->dev, "device registered (reg_base=%p, irq=%u)\n", - priv->base, (u32) ndev->irq); + priv->base, (u32)ndev->irq); return 0; From ab3a78f65983adf1bba53c8506968c25df206ae4 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 25 Jul 2019 15:10:07 +0200 Subject: [PATCH 06/41] can: ti_hecc: avoid long lines This patch fixes long lines in the driver. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index c5d80a126e21..2c2b2b791d90 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -514,7 +514,8 @@ static netdev_tx_t ti_hecc_xmit(struct sk_buff *skb, struct net_device *ndev) return NETDEV_TX_OK; } -static inline struct ti_hecc_priv *rx_offload_to_priv(struct can_rx_offload *offload) +static inline +struct ti_hecc_priv *rx_offload_to_priv(struct can_rx_offload *offload) { return container_of(offload, struct ti_hecc_priv, offload); } @@ -672,8 +673,9 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id) hecc_clear_bit(priv, HECC_CANME, mbx_mask); spin_unlock_irqrestore(&priv->mbx_lock, flags); stamp = hecc_read_stamp(priv, mbxno); - stats->tx_bytes += can_rx_offload_get_echo_skb(&priv->offload, - mbxno, stamp); + stats->tx_bytes += + can_rx_offload_get_echo_skb(&priv->offload, + mbxno, stamp); stats->tx_packets++; can_led_event(ndev, CAN_LED_EVENT_TX); --priv->tx_tail; From dfa9352dbe4e0da468cba0412b83ddbba35cd788 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Thu, 25 Jul 2019 15:11:32 +0200 Subject: [PATCH 07/41] can: ti_hecc: fix print formating strings This patch fixes the print format strings in the driver. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 2c2b2b791d90..652970b1a660 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -271,8 +271,8 @@ static int ti_hecc_set_btc(struct ti_hecc_priv *priv) if (bit_timing->brp > 4) can_btc |= HECC_CANBTC_SAM; else - netdev_warn(priv->ndev, "WARN: Triple" - "sampling not set due to h/w limitations"); + netdev_warn(priv->ndev, + "WARN: Triple sampling not set due to h/w limitations"); } can_btc |= ((bit_timing->sjw - 1) & 0x3) << 8; can_btc |= ((bit_timing->brp - 1) & 0xFF) << 16; @@ -562,7 +562,8 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, if (!skb) { if (printk_ratelimit()) netdev_err(priv->ndev, - "ti_hecc_error: alloc_can_err_skb() failed\n"); + "%s: alloc_can_err_skb() failed\n", + __func__); return -ENOMEM; } From c71400cec4389461153798de845a2be0f3827c99 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 26 Jul 2019 09:09:33 +0200 Subject: [PATCH 08/41] can: ti_hecc: ti_hecc_start(): avoid multiple assignments This patch changes the multiple assignments of HECC_TX_MASK in ti_hecc_start() into two single ones. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 652970b1a660..cae1e603ae51 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -364,7 +364,8 @@ static void ti_hecc_start(struct net_device *ndev) /* put HECC in initialization mode and set btc */ ti_hecc_reset(ndev); - priv->tx_head = priv->tx_tail = HECC_TX_MASK; + priv->tx_head = HECC_TX_MASK; + priv->tx_tail = HECC_TX_MASK; /* Enable local and global acceptance mask registers */ hecc_write(priv, HECC_CANGAM, HECC_SET_REG); From babfcda6ef436a529edb5d48e8180c323f1ca391 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 26 Jul 2019 09:29:14 +0200 Subject: [PATCH 09/41] can: ti_hecc: ti_hecc_mailbox_read(): add blank lines to improve readability This patch adds two blank lines in ti_hecc_mailbox_read() to improve the readability of the function. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index cae1e603ae51..2bfffa8c7dab 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -534,10 +534,12 @@ static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload, cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG; else cf->can_id = (data >> 18) & CAN_SFF_MASK; + data = hecc_read_mbx(priv, mbxno, HECC_CANMCF); if (data & HECC_CANMCF_RTR) cf->can_id |= CAN_RTR_FLAG; cf->can_dlc = get_can_dlc(data & 0xF); + data = hecc_read_mbx(priv, mbxno, HECC_CANMDL); *(__be32 *)(cf->data) = cpu_to_be32(data); if (cf->can_dlc > 4) { From 7123e1c7ea29f841819900bcf99763aa51ecda58 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 25 Jul 2019 07:00:44 +0000 Subject: [PATCH 10/41] can: ti_hecc: ti_hecc_mailbox_read(): remove set but not used variable 'mbx_mask' Fixes gcc '-Wunused-but-set-variable' warning: drivers/net/can/ti_hecc.c: In function 'ti_hecc_mailbox_read': drivers/net/can/ti_hecc.c:533:12: warning: variable 'mbx_mask' set but not used [-Wunused-but-set-variable] It is never used so can be removed. Reported-by: Hulk Robot Signed-off-by: YueHaibing Reviewed-by: Jeroen Hofstee Signed-off-by: Marc Kleine-Budde --- drivers/net/can/ti_hecc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index 2bfffa8c7dab..f8b19eef5d26 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c @@ -526,9 +526,8 @@ static unsigned int ti_hecc_mailbox_read(struct can_rx_offload *offload, u32 *timestamp, unsigned int mbxno) { struct ti_hecc_priv *priv = rx_offload_to_priv(offload); - u32 data, mbx_mask; + u32 data; - mbx_mask = BIT(mbxno); data = hecc_read_mbx(priv, mbxno, HECC_CANMID); if (data & HECC_CANMID_IDE) cf->can_id = (data & CAN_EFF_MASK) | CAN_EFF_FLAG; From 3486cc40ccbfe4cbf55feecce88a792e3043c178 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Wed, 3 Apr 2019 15:18:53 +0300 Subject: [PATCH 11/41] can: xilinx_can: xcan_chip_start(): fix failure with invalid bus Currently the xilinx_can xcan_chip_start() function, called from .ndo_open() and via CAN_MODE_START (bus-off restart), waits for the SR register to show the wanted operating state, with a 1 sec timeout. However, that register bit will only be set once the HW has observed 11 consecutive recessive bits (BusIdle) on the bus. If the bus will not see the 11 bits (e.g. it is stuck dominant), the function will timeout and return an error. If this was done as part of a scheduled restart from bus-off, the interface will stay in bus-off state forever even if the bus recovers later. According to M_CAN and FLEXCAN documentation they also wait for 11 consecutive recessive bits, but their drivers do not seem to wait for that. To make the behavior consistent, modify xilinx_can to also not wait for the synchronization to complete. The only way for users to know for sure that the bus has been joined successfully is to see successfully received or transmitted frames. That does not seem optimal, but it is consistent with other drivers and we should have a properly working restart-ms with xilinx_can. Tested on ZynqMP with Xilinx CAN-FD 1.0. Fixes: b1201e44f50b ("can: xilinx CAN controller support") Signed-off-by: Anssi Hannula Tested-by: Appana Durga Kedareswara Rao Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index bd95cfaff857..c7d043a40837 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -456,9 +456,8 @@ static int xcan_set_bittiming(struct net_device *ndev) static int xcan_chip_start(struct net_device *ndev) { struct xcan_priv *priv = netdev_priv(ndev); - u32 reg_msr, reg_sr_mask; + u32 reg_msr; int err; - unsigned long timeout; u32 ier; /* Check if it is in reset mode */ @@ -484,10 +483,8 @@ static int xcan_chip_start(struct net_device *ndev) /* Check whether it is loopback mode or normal mode */ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) { reg_msr = XCAN_MSR_LBACK_MASK; - reg_sr_mask = XCAN_SR_LBACK_MASK; } else { reg_msr = 0x0; - reg_sr_mask = XCAN_SR_NORMAL_MASK; } /* enable the first extended filter, if any, as cores with extended @@ -499,14 +496,6 @@ static int xcan_chip_start(struct net_device *ndev) priv->write_reg(priv, XCAN_MSR_OFFSET, reg_msr); priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_CEN_MASK); - timeout = jiffies + XCAN_TIMEOUT; - while (!(priv->read_reg(priv, XCAN_SR_OFFSET) & reg_sr_mask)) { - if (time_after(jiffies, timeout)) { - netdev_warn(ndev, - "timed out for correct mode\n"); - return -ETIMEDOUT; - } - } netdev_dbg(ndev, "status:#x%08x\n", priv->read_reg(priv, XCAN_SR_OFFSET)); From 6b0d35891c835319291f2c3b459e666fc809f831 Mon Sep 17 00:00:00 2001 From: Venkatesh Yadav Abbarapu Date: Mon, 12 Aug 2019 15:36:42 +0530 Subject: [PATCH 12/41] can: xilinx_can: xcan_probe(): skip error message on deferred probe When can clock is provided from the clock wizard, clock wizard driver may not be available when can driver probes resulting to the error message "Device clock not found error". As this error message is not very userful to the end user, skip printing it in the case of deferred probe. Fixes: b1201e44 ("can: xilinx CAN controller support") Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Venkatesh Yadav Abbarapu Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index c7d043a40837..161bb5e1f378 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -1780,7 +1780,8 @@ static int xcan_probe(struct platform_device *pdev) /* Getting the CAN can_clk info */ priv->can_clk = devm_clk_get(&pdev->dev, "can_clk"); if (IS_ERR(priv->can_clk)) { - dev_err(&pdev->dev, "Device clock not found.\n"); + if (PTR_ERR(priv->can_clk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Device clock not found.\n"); ret = PTR_ERR(priv->can_clk); goto err_free; } From 93bbd6c5eeb1dbc1f826b4924c21dc71d14b25c8 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 12 Aug 2019 15:36:43 +0530 Subject: [PATCH 13/41] can: xilinx_can: xcanfd_rx(): fix FSR register handling in the RX path After commit c223da689324 ("can: xilinx_can: Add support for CANFD FD frames") the driver is updating the FSR IRI index multiple times (i.e in xcanfd_rx() and xcan_rx_fifo_get_next_frame()), It should be updated once per RX packet. This patch fixes this issue, also this patch removes the unnecessary fsr register checks in xcanfd_rx() API. Fixes: c223da6 ("can: xilinx_can: Add support for CANFD FD frames") Reviewed-by: Radhey Shyam Pandey Reviewed-by: Shubhrajyoti Datta Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 137 ++++++++++++++++------------------- 1 file changed, 62 insertions(+), 75 deletions(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 161bb5e1f378..2e5cbffc2f4e 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -808,91 +808,78 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base) u32 id_xcan, dlc, data[2] = {0, 0}, dwindex = 0, i, fsr, readindex; fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); - if (fsr & XCAN_FSR_FL_MASK) { - readindex = fsr & XCAN_FSR_RI_MASK; - id_xcan = priv->read_reg(priv, - XCAN_FRAME_ID_OFFSET(frame_base)); - dlc = priv->read_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_base)); - if (dlc & XCAN_DLCR_EDL_MASK) - skb = alloc_canfd_skb(ndev, &cf); - else - skb = alloc_can_skb(ndev, (struct can_frame **)&cf); + readindex = fsr & XCAN_FSR_RI_MASK; + id_xcan = priv->read_reg(priv, XCAN_FRAME_ID_OFFSET(frame_base)); + dlc = priv->read_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_base)); + if (dlc & XCAN_DLCR_EDL_MASK) + skb = alloc_canfd_skb(ndev, &cf); + else + skb = alloc_can_skb(ndev, (struct can_frame **)&cf); - if (unlikely(!skb)) { - stats->rx_dropped++; - return 0; - } + if (unlikely(!skb)) { + stats->rx_dropped++; + return 0; + } - /* Change Xilinx CANFD data length format to socketCAN data - * format - */ - if (dlc & XCAN_DLCR_EDL_MASK) - cf->len = can_dlc2len((dlc & XCAN_DLCR_DLC_MASK) >> + /* Change Xilinx CANFD data length format to socketCAN data + * format + */ + if (dlc & XCAN_DLCR_EDL_MASK) + cf->len = can_dlc2len((dlc & XCAN_DLCR_DLC_MASK) >> + XCAN_DLCR_DLC_SHIFT); + else + cf->len = get_can_dlc((dlc & XCAN_DLCR_DLC_MASK) >> XCAN_DLCR_DLC_SHIFT); - else - cf->len = get_can_dlc((dlc & XCAN_DLCR_DLC_MASK) >> - XCAN_DLCR_DLC_SHIFT); - /* Change Xilinx CAN ID format to socketCAN ID format */ - if (id_xcan & XCAN_IDR_IDE_MASK) { - /* The received frame is an Extended format frame */ - cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3; - cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >> - XCAN_IDR_ID2_SHIFT; - cf->can_id |= CAN_EFF_FLAG; - if (id_xcan & XCAN_IDR_RTR_MASK) - cf->can_id |= CAN_RTR_FLAG; - } else { - /* The received frame is a standard format frame */ - cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> - XCAN_IDR_ID1_SHIFT; - if (!(dlc & XCAN_DLCR_EDL_MASK) && (id_xcan & - XCAN_IDR_SRR_MASK)) - cf->can_id |= CAN_RTR_FLAG; - } + /* Change Xilinx CAN ID format to socketCAN ID format */ + if (id_xcan & XCAN_IDR_IDE_MASK) { + /* The received frame is an Extended format frame */ + cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> 3; + cf->can_id |= (id_xcan & XCAN_IDR_ID2_MASK) >> + XCAN_IDR_ID2_SHIFT; + cf->can_id |= CAN_EFF_FLAG; + if (id_xcan & XCAN_IDR_RTR_MASK) + cf->can_id |= CAN_RTR_FLAG; + } else { + /* The received frame is a standard format frame */ + cf->can_id = (id_xcan & XCAN_IDR_ID1_MASK) >> + XCAN_IDR_ID1_SHIFT; + if (!(dlc & XCAN_DLCR_EDL_MASK) && (id_xcan & + XCAN_IDR_SRR_MASK)) + cf->can_id |= CAN_RTR_FLAG; + } - /* Check the frame received is FD or not*/ - if (dlc & XCAN_DLCR_EDL_MASK) { - for (i = 0; i < cf->len; i += 4) { - if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - data[0] = priv->read_reg(priv, + /* Check the frame received is FD or not*/ + if (dlc & XCAN_DLCR_EDL_MASK) { + for (i = 0; i < cf->len; i += 4) { + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + data[0] = priv->read_reg(priv, (XCAN_RXMSG_2_FRAME_OFFSET(readindex) + (dwindex * XCANFD_DW_BYTES))); - else - data[0] = priv->read_reg(priv, + else + data[0] = priv->read_reg(priv, (XCAN_RXMSG_FRAME_OFFSET(readindex) + - (dwindex * XCANFD_DW_BYTES))); - *(__be32 *)(cf->data + i) = - cpu_to_be32(data[0]); - dwindex++; - } - } else { - for (i = 0; i < cf->len; i += 4) { - if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - data[0] = priv->read_reg(priv, - XCAN_RXMSG_2_FRAME_OFFSET(readindex) + i); - else - data[0] = priv->read_reg(priv, - XCAN_RXMSG_FRAME_OFFSET(readindex) + i); - *(__be32 *)(cf->data + i) = - cpu_to_be32(data[0]); - } + (dwindex * XCANFD_DW_BYTES))); + *(__be32 *)(cf->data + i) = cpu_to_be32(data[0]); + dwindex++; + } + } else { + for (i = 0; i < cf->len; i += 4) { + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + data[0] = priv->read_reg(priv, + XCAN_RXMSG_2_FRAME_OFFSET(readindex) + + i); + else + data[0] = priv->read_reg(priv, + XCAN_RXMSG_FRAME_OFFSET(readindex) + i); + *(__be32 *)(cf->data + i) = cpu_to_be32(data[0]); } - /* Update FSR Register so that next packet will save to - * buffer - */ - fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); - fsr |= XCAN_FSR_IRI_MASK; - priv->write_reg(priv, XCAN_FSR_OFFSET, fsr); - fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); - stats->rx_bytes += cf->len; - stats->rx_packets++; - netif_receive_skb(skb); - - return 1; } - /* If FSR Register is not updated with fill level */ - return 0; + stats->rx_bytes += cf->len; + stats->rx_packets++; + netif_receive_skb(skb); + + return 1; } /** From e6997dd2688403bf8f760bd9fd7ddb5c654bc8bd Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 12 Aug 2019 15:36:44 +0530 Subject: [PATCH 14/41] can: xilinx_can: fix the data update logic for CANFD FD frames commit c223da689324 ("can: xilinx_can: Add support for CANFD FD frames") is writing data to a wrong offset for FD frames. This patch fixes this issue. Fixes: c223da6 ("can: xilinx_can: Add support for CANFD FD frames") Reviewed-by: Radhey Shyam Pandey Reviewed-by: Shubhrajyoti Datta Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 2e5cbffc2f4e..a312fe32cf12 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -66,8 +66,7 @@ enum xcan_reg { #define XCAN_FRAME_DLC_OFFSET(frame_base) ((frame_base) + 0x04) #define XCAN_FRAME_DW1_OFFSET(frame_base) ((frame_base) + 0x08) #define XCAN_FRAME_DW2_OFFSET(frame_base) ((frame_base) + 0x0C) -#define XCANFD_FRAME_DW_OFFSET(frame_base, n) (((frame_base) + 0x08) + \ - ((n) * XCAN_CANFD_FRAME_SIZE)) +#define XCANFD_FRAME_DW_OFFSET(frame_base) ((frame_base) + 0x08) #define XCAN_CANFD_FRAME_SIZE 0x48 #define XCAN_TXMSG_FRAME_OFFSET(n) (XCAN_TXMSG_BASE_OFFSET + \ @@ -589,7 +588,7 @@ static void xcan_write_frame(struct xcan_priv *priv, struct sk_buff *skb, if (priv->devtype.cantype == XAXI_CANFD || priv->devtype.cantype == XAXI_CANFD_2_0) { for (i = 0; i < cf->len; i += 4) { - ramoff = XCANFD_FRAME_DW_OFFSET(frame_offset, dwindex) + + ramoff = XCANFD_FRAME_DW_OFFSET(frame_offset) + (dwindex * XCANFD_DW_BYTES); priv->write_reg(priv, ramoff, be32_to_cpup((__be32 *)(cf->data + i))); @@ -805,10 +804,8 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base) struct net_device_stats *stats = &ndev->stats; struct canfd_frame *cf; struct sk_buff *skb; - u32 id_xcan, dlc, data[2] = {0, 0}, dwindex = 0, i, fsr, readindex; + u32 id_xcan, dlc, data[2] = {0, 0}, dwindex = 0, i, dw_offset; - fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); - readindex = fsr & XCAN_FSR_RI_MASK; id_xcan = priv->read_reg(priv, XCAN_FRAME_ID_OFFSET(frame_base)); dlc = priv->read_reg(priv, XCAN_FRAME_DLC_OFFSET(frame_base)); if (dlc & XCAN_DLCR_EDL_MASK) @@ -852,26 +849,16 @@ static int xcanfd_rx(struct net_device *ndev, int frame_base) /* Check the frame received is FD or not*/ if (dlc & XCAN_DLCR_EDL_MASK) { for (i = 0; i < cf->len; i += 4) { - if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - data[0] = priv->read_reg(priv, - (XCAN_RXMSG_2_FRAME_OFFSET(readindex) + - (dwindex * XCANFD_DW_BYTES))); - else - data[0] = priv->read_reg(priv, - (XCAN_RXMSG_FRAME_OFFSET(readindex) + - (dwindex * XCANFD_DW_BYTES))); + dw_offset = XCANFD_FRAME_DW_OFFSET(frame_base) + + (dwindex * XCANFD_DW_BYTES); + data[0] = priv->read_reg(priv, dw_offset); *(__be32 *)(cf->data + i) = cpu_to_be32(data[0]); dwindex++; } } else { for (i = 0; i < cf->len; i += 4) { - if (priv->devtype.flags & XCAN_FLAG_CANFD_2) - data[0] = priv->read_reg(priv, - XCAN_RXMSG_2_FRAME_OFFSET(readindex) + - i); - else - data[0] = priv->read_reg(priv, - XCAN_RXMSG_FRAME_OFFSET(readindex) + i); + dw_offset = XCANFD_FRAME_DW_OFFSET(frame_base); + data[0] = priv->read_reg(priv, dw_offset + i); *(__be32 *)(cf->data + i) = cpu_to_be32(data[0]); } } From 9d06bcb9aa48dc4fc474dc8441a036bc4a090270 Mon Sep 17 00:00:00 2001 From: Appana Durga Kedareswara rao Date: Mon, 12 Aug 2019 15:36:45 +0530 Subject: [PATCH 15/41] can: xilinx_can: xcan_rx_fifo_get_next_frame(): fix FSR register FL and RI mask values for canfd 2.0 For CANFD 2.0 IP configuration existing driver is using incorrect mask values for FSR register FL and RI fields. Fixes: c223da6 ("can: xilinx_can: Add support for CANFD FD frames") Signed-off-by: Appana Durga Kedareswara rao Acked-by: Shubhrajyoti Datta Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index a312fe32cf12..f939f7ac5b64 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -123,8 +123,10 @@ enum xcan_reg { #define XCAN_IDR_RTR_MASK 0x00000001 /* Remote TX request */ #define XCAN_DLCR_DLC_MASK 0xF0000000 /* Data length code */ #define XCAN_FSR_FL_MASK 0x00003F00 /* RX Fill Level */ +#define XCAN_2_FSR_FL_MASK 0x00007F00 /* RX Fill Level */ #define XCAN_FSR_IRI_MASK 0x00000080 /* RX Increment Read Index */ #define XCAN_FSR_RI_MASK 0x0000001F /* RX Read Index */ +#define XCAN_2_FSR_RI_MASK 0x0000003F /* RX Read Index */ #define XCAN_DLCR_EDL_MASK 0x08000000 /* EDL Mask in DLC */ #define XCAN_DLCR_BRS_MASK 0x04000000 /* BRS Mask in DLC */ @@ -1127,7 +1129,7 @@ static int xcan_rx_fifo_get_next_frame(struct xcan_priv *priv) int offset; if (priv->devtype.flags & XCAN_FLAG_RX_FIFO_MULTI) { - u32 fsr; + u32 fsr, mask; /* clear RXOK before the is-empty check so that any newly * received frame will reassert it without a race @@ -1137,12 +1139,17 @@ static int xcan_rx_fifo_get_next_frame(struct xcan_priv *priv) fsr = priv->read_reg(priv, XCAN_FSR_OFFSET); /* check if RX FIFO is empty */ - if (!(fsr & XCAN_FSR_FL_MASK)) + if (priv->devtype.flags & XCAN_FLAG_CANFD_2) + mask = XCAN_2_FSR_FL_MASK; + else + mask = XCAN_FSR_FL_MASK; + + if (!(fsr & mask)) return -ENOENT; if (priv->devtype.flags & XCAN_FLAG_CANFD_2) offset = - XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); + XCAN_RXMSG_2_FRAME_OFFSET(fsr & XCAN_2_FSR_RI_MASK); else offset = XCAN_RXMSG_FRAME_OFFSET(fsr & XCAN_FSR_RI_MASK); From 3e994ff28f867a20ae0dd055a5e4a4a34aad9c3c Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Mon, 12 Aug 2019 15:36:46 +0530 Subject: [PATCH 16/41] can: xilinx_can: xcan_set_bittiming(): fix the data phase btr1 calculation While calculating bitrate for the data phase, the driver is using phase segment 1 of the arbitration phase instead of the data phase. Fixes: c223da6 ("can: xilinx_can: Add support for CANFD FD frames") Signed-off-by: Appana Durga Kedareswara rao Signed-off-by: Srinivas Neeli Acked-by: Shubhrajyoti Datta Signed-off-by: Michal Simek Signed-off-by: Marc Kleine-Budde --- drivers/net/can/xilinx_can.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index f939f7ac5b64..911b34316c9d 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -425,7 +425,7 @@ static int xcan_set_bittiming(struct net_device *ndev) btr0 = dbt->brp - 1; /* Setting Time Segment 1 in BTR Register */ - btr1 = dbt->prop_seg + bt->phase_seg1 - 1; + btr1 = dbt->prop_seg + dbt->phase_seg1 - 1; /* Setting Time Segment 2 in BTR Register */ btr1 |= (dbt->phase_seg2 - 1) << priv->devtype.btr_ts2_shift; From 147d9e9a67e118270bc83ea89cc989f7f1e4edea Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:16:29 +0200 Subject: [PATCH 17/41] can: af_can: convert block comments to network style comments This patch converts all block comments to network subsystem style block comments. Signed-off-by: Marc Kleine-Budde --- net/can/af_can.c | 49 ++++++++++++++---------------------------------- net/can/af_can.h | 3 +-- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index 76cf83b2bd40..dc8f9720d5cd 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) -/* - * af_can.c - Protocol family CAN core module +/* af_can.c - Protocol family CAN core module * (used by different CAN protocol modules) * * Copyright (c) 2002-2017 Volkswagen Group Electronic Research @@ -84,9 +83,7 @@ static DEFINE_MUTEX(proto_tab_lock); static atomic_t skbcounter = ATOMIC_INIT(0); -/* - * af_can socket functions - */ +/* af_can socket functions */ static void can_sock_destruct(struct sock *sk) { @@ -132,8 +129,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol, err = request_module("can-proto-%d", protocol); - /* - * In case of error we only print a message but don't + /* In case of error we only print a message but don't * return the error code immediately. Below we will * return -EPROTONOSUPPORT */ @@ -180,9 +176,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol, return err; } -/* - * af_can tx path - */ +/* af_can tx path */ /** * can_send - transmit a CAN frame (optional with local loopback) @@ -218,8 +212,7 @@ int can_send(struct sk_buff *skb, int loop) } else goto inval_skb; - /* - * Make sure the CAN frame can pass the selected CAN netdevice. + /* Make sure the CAN frame can pass the selected CAN netdevice. * As structs can_frame and canfd_frame are similar, we can provide * CAN FD frames to legacy CAN drivers as long as the length is <= 8 */ @@ -250,8 +243,7 @@ int can_send(struct sk_buff *skb, int loop) /* indication for the CAN driver: do loopback */ skb->pkt_type = PACKET_LOOPBACK; - /* - * The reference to the originating sock may be required + /* The reference to the originating sock may be required * by the receiving socket to check whether the frame is * its own. Example: can_raw sockopt CAN_RAW_RECV_OWN_MSGS * Therefore we have to ensure that skb->sk remains the @@ -260,8 +252,7 @@ int can_send(struct sk_buff *skb, int loop) */ if (!(skb->dev->flags & IFF_ECHO)) { - /* - * If the interface is not capable to do loopback + /* If the interface is not capable to do loopback * itself, we do it here. */ newskb = skb_clone(skb, GFP_ATOMIC); @@ -304,9 +295,7 @@ inval_skb: } EXPORT_SYMBOL(can_send); -/* - * af_can rx path - */ +/* af_can rx path */ static struct can_dev_rcv_lists *find_dev_rcv_lists(struct net *net, struct net_device *dev) @@ -498,9 +487,7 @@ int can_rx_register(struct net *net, struct net_device *dev, canid_t can_id, } EXPORT_SYMBOL(can_rx_register); -/* - * can_rx_delete_receiver - rcu callback for single receiver entry removal - */ +/* can_rx_delete_receiver - rcu callback for single receiver entry removal */ static void can_rx_delete_receiver(struct rcu_head *rp) { struct receiver *r = container_of(rp, struct receiver, rcu); @@ -549,8 +536,7 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id, rl = find_rcv_list(&can_id, &mask, d); - /* - * Search the receiver list for the item to delete. This should + /* Search the receiver list for the item to delete. This should * exist, since no receiver may be unregistered that hasn't * been registered before. */ @@ -561,8 +547,7 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id, break; } - /* - * Check for bugs in CAN protocol implementations using af_can.c: + /* Check for bugs in CAN protocol implementations using af_can.c: * 'r' will be NULL if no matching list item was found for removal. */ @@ -737,9 +722,7 @@ static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, return NET_RX_SUCCESS; } -/* - * af_can protocol functions - */ +/* af_can protocol functions */ /** * can_proto_register - register CAN transport protocol @@ -801,9 +784,7 @@ void can_proto_unregister(const struct can_proto *cp) } EXPORT_SYMBOL(can_proto_unregister); -/* - * af_can notifier to create/remove CAN netdevice specific structs - */ +/* af_can notifier to create/remove CAN netdevice specific structs */ static int can_notifier(struct notifier_block *nb, unsigned long msg, void *ptr) { @@ -913,9 +894,7 @@ static void can_pernet_exit(struct net *net) kfree(net->can.can_pstats); } -/* - * af_can module init/exit functions - */ +/* af_can module init/exit functions */ static struct packet_type can_packet __read_mostly = { .type = cpu_to_be16(ETH_P_CAN), diff --git a/net/can/af_can.h b/net/can/af_can.h index ef21f7c6bc80..41a45e3bc4a4 100644 --- a/net/can/af_can.h +++ b/net/can/af_can.h @@ -1,6 +1,5 @@ /* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */ -/* - * Copyright (c) 2002-2007 Volkswagen Group Electronic Research +/* Copyright (c) 2002-2007 Volkswagen Group Electronic Research * All rights reserved. * * Redistribution and use in source and binary forms, with or without From 8325ce9bca5522852e6fe9e9bee7ea8a9c30caac Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 13 Aug 2019 09:03:55 +0200 Subject: [PATCH 18/41] can: af_can: balance braces around else statements This patch balances the braces around else statements, so that checkpatch doesn't complain anymore. Signed-off-by: Marc Kleine-Budde --- net/can/af_can.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index dc8f9720d5cd..e3b37676cf53 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -209,8 +209,9 @@ int can_send(struct sk_buff *skb, int loop) skb->protocol = htons(ETH_P_CANFD); if (unlikely(cfd->len > CANFD_MAX_DLEN)) goto inval_skb; - } else + } else { goto inval_skb; + } /* Make sure the CAN frame can pass the selected CAN netdevice. * As structs can_frame and canfd_frame are similar, we can provide @@ -753,8 +754,9 @@ int can_proto_register(const struct can_proto *cp) if (rcu_access_pointer(proto_tab[proto])) { pr_err("can: protocol %d already registered\n", proto); err = -EBUSY; - } else + } else { RCU_INIT_POINTER(proto_tab[proto], cp); + } mutex_unlock(&proto_tab_lock); @@ -812,15 +814,16 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg, d = dev->ml_priv; if (d) { - if (d->entries) + if (d->entries) { d->remove_on_zero_entries = 1; - else { + } else { kfree(d); dev->ml_priv = NULL; } - } else + } else { pr_err("can: notifier: receive list not found for dev " "%s\n", dev->name); + } spin_unlock(&dev_net(dev)->can.can_rcvlists_lock); From b11844b6068cf091640e6e43a27906b2c5bf86fa Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 13 Aug 2019 09:06:17 +0200 Subject: [PATCH 19/41] can: af_can: fix alignment This patch fixes the alignment of find_dev_rcv_lists() and canfd_rcv() so that checkpatch doesn't complain anymore. Signed-off-by: Marc Kleine-Budde --- net/can/af_can.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index e3b37676cf53..1fa6abf15302 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -299,7 +299,7 @@ EXPORT_SYMBOL(can_send); /* af_can rx path */ static struct can_dev_rcv_lists *find_dev_rcv_lists(struct net *net, - struct net_device *dev) + struct net_device *dev) { if (!dev) return net->can.can_rx_alldev_list; @@ -707,7 +707,7 @@ static int can_rcv(struct sk_buff *skb, struct net_device *dev, } static int canfd_rcv(struct sk_buff *skb, struct net_device *dev, - struct packet_type *pt, struct net_device *orig_dev) + struct packet_type *pt, struct net_device *orig_dev) { struct canfd_frame *cfd = (struct canfd_frame *)skb->data; From 1cf571eb81d3f435e6a4ea359a08b35cb7c5f81a Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 13 Aug 2019 09:29:10 +0200 Subject: [PATCH 20/41] can: af_can: avoid splitting quoted string across lines This patch joins all error message strings in af_can to be in single lines, to ease searching for them. Signed-off-by: Marc Kleine-Budde --- net/can/af_can.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index 1fa6abf15302..020e019cf4e3 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -134,8 +134,8 @@ static int can_create(struct net *net, struct socket *sock, int protocol, * return -EPROTONOSUPPORT */ if (err) - printk_ratelimited(KERN_ERR "can: request_module " - "(can-proto-%d) failed.\n", protocol); + pr_err_ratelimited("can: request_module (can-proto-%d) failed.\n", + protocol); cp = can_get_proto(protocol); } @@ -391,7 +391,6 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, /* extra filterlists for the subscription of a single non-RTR can_id */ if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS) && !(*can_id & CAN_RTR_FLAG)) { - if (*can_id & CAN_EFF_FLAG) { if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) return &d->rx_eff[effhash(*can_id)]; @@ -529,8 +528,7 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id, d = find_dev_rcv_lists(net, dev); if (!d) { - pr_err("BUG: receive list not found for " - "dev %s, id %03X, mask %03X\n", + pr_err("BUG: receive list not found for dev %s, id %03X, mask %03X\n", DNAME(dev), can_id, mask); goto out; } @@ -553,8 +551,8 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id, */ if (!r) { - WARN(1, "BUG: receive list entry not found for dev %s, " - "id %03X, mask %03X\n", DNAME(dev), can_id, mask); + WARN(1, "BUG: receive list entry not found for dev %s, id %03X, mask %03X\n", + DNAME(dev), can_id, mask); goto out; } @@ -797,7 +795,6 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg, return NOTIFY_DONE; switch (msg) { - case NETDEV_REGISTER: /* create new dev_rcv_lists for this device */ @@ -821,8 +818,8 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg, dev->ml_priv = NULL; } } else { - pr_err("can: notifier: receive list not found for dev " - "%s\n", dev->name); + pr_err("can: notifier: receive list not found for dev %s\n", + dev->name); } spin_unlock(&dev_net(dev)->can.can_rcvlists_lock); From fbd4665a67f74b6af44f6a9cf335ddc3fc124f75 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 13 Aug 2019 09:41:40 +0200 Subject: [PATCH 21/41] can: af_can: can_pernet_init(): Use preferred style kzalloc(sizeof()) usage This patch switches can_pernet_init() to the preferred style of using the sizeof() operator in kzalloc(). Signed-off-by: Marc Kleine-Budde --- net/can/af_can.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/can/af_can.c b/net/can/af_can.c index 020e019cf4e3..9a9a51847c7c 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c @@ -834,13 +834,13 @@ static int can_pernet_init(struct net *net) { spin_lock_init(&net->can.can_rcvlists_lock); net->can.can_rx_alldev_list = - kzalloc(sizeof(struct can_dev_rcv_lists), GFP_KERNEL); + kzalloc(sizeof(*net->can.can_rx_alldev_list), GFP_KERNEL); if (!net->can.can_rx_alldev_list) goto out; - net->can.can_stats = kzalloc(sizeof(struct s_stats), GFP_KERNEL); + net->can.can_stats = kzalloc(sizeof(*net->can.can_stats), GFP_KERNEL); if (!net->can.can_stats) goto out_free_alldev_list; - net->can.can_pstats = kzalloc(sizeof(struct s_pstats), GFP_KERNEL); + net->can.can_pstats = kzalloc(sizeof(*net->can.can_pstats), GFP_KERNEL); if (!net->can.can_pstats) goto out_free_can_stats; From 97c334935100e762feb4f083291bb2fc006de7df Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 13 Aug 2019 11:25:33 +0200 Subject: [PATCH 22/41] can: af_can: add missing identifiers to struct receiver::func This patch adds the missing identifiers to the struct receiver::func declaration. Signed-off-by: Marc Kleine-Budde --- net/can/af_can.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/can/af_can.h b/net/can/af_can.h index 41a45e3bc4a4..9cdb79083623 100644 --- a/net/can/af_can.h +++ b/net/can/af_can.h @@ -53,7 +53,7 @@ struct receiver { canid_t can_id; canid_t mask; unsigned long matches; - void (*func)(struct sk_buff *, void *); + void (*func)(struct sk_buff *skb, void *data); void *data; char *ident; struct sock *sk; From d6ada83bba9905c436b1ffcbd5fd995f5e38f291 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:16:29 +0200 Subject: [PATCH 23/41] can: raw: convert block comments to network style comments This patch converts all block comments to network subsystem style block comments. Signed-off-by: Marc Kleine-Budde --- net/can/raw.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/net/can/raw.c b/net/can/raw.c index da386f1fa815..cb68e155075c 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) -/* - * raw.c - Raw sockets for protocol family CAN +/* raw.c - Raw sockets for protocol family CAN * * Copyright (c) 2002-2007 Volkswagen Group Electronic Research * All rights reserved. @@ -65,8 +64,7 @@ MODULE_ALIAS("can-proto-1"); #define MASK_ALL 0 -/* - * A raw socket has a list of can_filters attached to it, each receiving +/* A raw socket has a list of can_filters attached to it, each receiving * the CAN frames matching that filter. If the filter list is empty, * no CAN frames will be received by the socket. The default after * opening the socket, is to have one filter which receives all frames. @@ -97,8 +95,7 @@ struct raw_sock { struct uniqframe __percpu *uniq; }; -/* - * Return pointer to store the extra msg flags for raw_recvmsg(). +/* Return pointer to store the extra msg flags for raw_recvmsg(). * We use the space of one unsigned int beyond the 'struct sockaddr_can' * in skb->cb. */ @@ -157,8 +154,7 @@ static void raw_rcv(struct sk_buff *oskb, void *data) if (!skb) return; - /* - * Put the datagram to the queue so that raw_recvmsg() can + /* Put the datagram to the queue so that raw_recvmsg() can * get it from there. We need to pass the interface index to * raw_recvmsg(). We pass a whole struct sockaddr_can in skb->cb * containing the interface index. From d5e4ecac87fc620b642c331d374a5fc4569493ed Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:28:21 +0200 Subject: [PATCH 24/41] can: raw: remove unnecessary blank lines, add suggested blank lines This patch removes unnecessary blank lines, and adds suggested ones, so that checkpatch doesn't complain anymore. Signed-off-by: Marc Kleine-Budde --- net/can/raw.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/net/can/raw.c b/net/can/raw.c index cb68e155075c..96fe0b5e3e1e 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -280,7 +280,6 @@ static int raw_notifier(struct notifier_block *nb, return NOTIFY_DONE; switch (msg) { - case NETDEV_UNREGISTER: lock_sock(sk); /* remove current filters & unregister */ @@ -499,7 +498,6 @@ static int raw_setsockopt(struct socket *sock, int level, int optname, return -EINVAL; switch (optname) { - case CAN_RAW_FILTER: if (optlen % sizeof(struct can_filter) != 0) return -EINVAL; @@ -662,11 +660,11 @@ static int raw_getsockopt(struct socket *sock, int level, int optname, return -EINVAL; switch (optname) { - case CAN_RAW_FILTER: lock_sock(sk); if (ro->count > 0) { int fsize = ro->count * sizeof(struct can_filter); + if (len > fsize) len = fsize; if (copy_to_user(optval, ro->filter, len)) From bff10040672d41bd027c267d78e967c374d4e04b Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 13 Aug 2019 09:03:55 +0200 Subject: [PATCH 25/41] can: raw: balance braces around else statements This patch balances the braces around else statements, so that checkpatch doesn't complain anymore. Signed-off-by: Marc Kleine-Budde --- net/can/raw.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/can/raw.c b/net/can/raw.c index 96fe0b5e3e1e..54517f9b1662 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -365,8 +365,9 @@ static int raw_release(struct socket *sock) raw_disable_allfilters(dev_net(dev), dev, sk); dev_put(dev); } - } else + } else { raw_disable_allfilters(sock_net(sk), NULL, sk); + } } if (ro->count > 1) @@ -446,8 +447,9 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len) dev, sk); dev_put(dev); } - } else + } else { raw_disable_allfilters(sock_net(sk), NULL, sk); + } } ro->ifindex = ifindex; ro->bound = 1; @@ -669,8 +671,9 @@ static int raw_getsockopt(struct socket *sock, int level, int optname, len = fsize; if (copy_to_user(optval, ro->filter, len)) err = -EFAULT; - } else + } else { len = 0; + } release_sock(sk); if (!err) @@ -737,8 +740,9 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) return -EINVAL; ifindex = addr->can_ifindex; - } else + } else { ifindex = ro->ifindex; + } dev = dev_get_by_index(sock_net(sk), ifindex); if (!dev) From d956b1a87f9bc84aed7bd4f5f5ae52f9ead0381d Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 13 Aug 2019 09:07:14 +0200 Subject: [PATCH 26/41] can: raw: raw_module_init(): use pr_err() instead of printk(KERN_ERR, ...) This patch converts a printk(KERN_ERR, ...) to a pr_err(). Signed-off-by: Marc Kleine-Budde --- net/can/raw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/can/raw.c b/net/can/raw.c index 54517f9b1662..a28b285545e5 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -885,7 +885,7 @@ static __init int raw_module_init(void) err = can_proto_register(&raw_can_proto); if (err < 0) - printk(KERN_ERR "can: registration of raw protocol failed\n"); + pr_err("can: registration of raw protocol failed\n"); return err; } From af0b1470bda9751c4d757a0efd50edda8da49c99 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 12 Aug 2019 15:49:04 +0200 Subject: [PATCH 27/41] can: raw: raw_sock_no_ioctlcmd(): mark function as static This patch marks the raw_sock_no_ioctlcmd() function as static as it's only used in this source file. Fixes: 473d924d7d46 ("can: fix ioctl function removal") Signed-off-by: Marc Kleine-Budde --- net/can/raw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/can/raw.c b/net/can/raw.c index a28b285545e5..fdbc36140e9b 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -835,8 +835,8 @@ static int raw_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, return size; } -int raw_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd, - unsigned long arg) +static int raw_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd, + unsigned long arg) { /* no ioctls for socket layer -> hand it down to NIC layer */ return -ENOIOCTLCMD; From 9989f6333c58e5068abf65384b05de3847b07ce1 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 12 Aug 2019 15:49:04 +0200 Subject: [PATCH 28/41] can: bcm: bcm_sock_no_ioctlcmd(): mark function as static This patch marks the bcm_sock_no_ioctlcmd() function as static as it's only used in this source file. Fixes: 473d924d7d46 ("can: fix ioctl function removal") Signed-off-by: Marc Kleine-Budde --- net/can/bcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/can/bcm.c b/net/can/bcm.c index bf1d0bbecec8..eb1d28b8c46a 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -1680,8 +1680,8 @@ static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, return size; } -int bcm_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd, - unsigned long arg) +static int bcm_sock_no_ioctlcmd(struct socket *sock, unsigned int cmd, + unsigned long arg) { /* no ioctls for socket layer -> hand it down to NIC layer */ return -ENOIOCTLCMD; From bf74aa86e111aa3b2fbb25db37e3a3fab71b5b68 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 12 Aug 2019 14:57:14 +0200 Subject: [PATCH 29/41] can: bcm: switch timer to HRTIMER_MODE_SOFT and remove hrtimer_tasklet This patch switches the timer to HRTIMER_MODE_SOFT, which executed the timer callback in softirq context and removes the hrtimer_tasklet. Signed-off-by: Thomas Gleixner Signed-off-by: Anna-Maria Gleixner Acked-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- net/can/bcm.c | 156 +++++++++++++++++--------------------------------- 1 file changed, 52 insertions(+), 104 deletions(-) diff --git a/net/can/bcm.c b/net/can/bcm.c index eb1d28b8c46a..28fd1a1c8487 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -106,7 +106,6 @@ struct bcm_op { unsigned long frames_abs, frames_filtered; struct bcm_timeval ival1, ival2; struct hrtimer timer, thrtimer; - struct tasklet_struct tsklet, thrtsklet; ktime_t rx_stamp, kt_ival1, kt_ival2, kt_lastmsg; int rx_ifindex; int cfsiz; @@ -371,25 +370,34 @@ static void bcm_send_to_user(struct bcm_op *op, struct bcm_msg_head *head, } } -static void bcm_tx_start_timer(struct bcm_op *op) +static bool bcm_tx_set_expiry(struct bcm_op *op, struct hrtimer *hrt) { + ktime_t ival; + if (op->kt_ival1 && op->count) - hrtimer_start(&op->timer, - ktime_add(ktime_get(), op->kt_ival1), - HRTIMER_MODE_ABS); + ival = op->kt_ival1; else if (op->kt_ival2) - hrtimer_start(&op->timer, - ktime_add(ktime_get(), op->kt_ival2), - HRTIMER_MODE_ABS); + ival = op->kt_ival2; + else + return false; + + hrtimer_set_expires(hrt, ktime_add(ktime_get(), ival)); + return true; } -static void bcm_tx_timeout_tsklet(unsigned long data) +static void bcm_tx_start_timer(struct bcm_op *op) { - struct bcm_op *op = (struct bcm_op *)data; + if (bcm_tx_set_expiry(op, &op->timer)) + hrtimer_start_expires(&op->timer, HRTIMER_MODE_ABS_SOFT); +} + +/* bcm_tx_timeout_handler - performs cyclic CAN frame transmissions */ +static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer) +{ + struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer); struct bcm_msg_head msg_head; if (op->kt_ival1 && (op->count > 0)) { - op->count--; if (!op->count && (op->flags & TX_COUNTEVT)) { @@ -406,22 +414,12 @@ static void bcm_tx_timeout_tsklet(unsigned long data) } bcm_can_tx(op); - } else if (op->kt_ival2) + } else if (op->kt_ival2) { bcm_can_tx(op); + } - bcm_tx_start_timer(op); -} - -/* - * bcm_tx_timeout_handler - performs cyclic CAN frame transmissions - */ -static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer) -{ - struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer); - - tasklet_schedule(&op->tsklet); - - return HRTIMER_NORESTART; + return bcm_tx_set_expiry(op, &op->timer) ? + HRTIMER_RESTART : HRTIMER_NORESTART; } /* @@ -487,7 +485,7 @@ static void bcm_rx_update_and_send(struct bcm_op *op, /* do not send the saved data - only start throttle timer */ hrtimer_start(&op->thrtimer, ktime_add(op->kt_lastmsg, op->kt_ival2), - HRTIMER_MODE_ABS); + HRTIMER_MODE_ABS_SOFT); return; } @@ -546,14 +544,21 @@ static void bcm_rx_starttimer(struct bcm_op *op) return; if (op->kt_ival1) - hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL); + hrtimer_start(&op->timer, op->kt_ival1, HRTIMER_MODE_REL_SOFT); } -static void bcm_rx_timeout_tsklet(unsigned long data) +/* bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out */ +static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer) { - struct bcm_op *op = (struct bcm_op *)data; + struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer); struct bcm_msg_head msg_head; + /* if user wants to be informed, when cyclic CAN-Messages come back */ + if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) { + /* clear received CAN frames to indicate 'nothing received' */ + memset(op->last_frames, 0, op->nframes * op->cfsiz); + } + /* create notification to user */ msg_head.opcode = RX_TIMEOUT; msg_head.flags = op->flags; @@ -564,25 +569,6 @@ static void bcm_rx_timeout_tsklet(unsigned long data) msg_head.nframes = 0; bcm_send_to_user(op, &msg_head, NULL, 0); -} - -/* - * bcm_rx_timeout_handler - when the (cyclic) CAN frame reception timed out - */ -static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer) -{ - struct bcm_op *op = container_of(hrtimer, struct bcm_op, timer); - - /* schedule before NET_RX_SOFTIRQ */ - tasklet_hi_schedule(&op->tsklet); - - /* no restart of the timer is done here! */ - - /* if user wants to be informed, when cyclic CAN-Messages come back */ - if ((op->flags & RX_ANNOUNCE_RESUME) && op->last_frames) { - /* clear received CAN frames to indicate 'nothing received' */ - memset(op->last_frames, 0, op->nframes * op->cfsiz); - } return HRTIMER_NORESTART; } @@ -590,14 +576,12 @@ static enum hrtimer_restart bcm_rx_timeout_handler(struct hrtimer *hrtimer) /* * bcm_rx_do_flush - helper for bcm_rx_thr_flush */ -static inline int bcm_rx_do_flush(struct bcm_op *op, int update, - unsigned int index) +static inline int bcm_rx_do_flush(struct bcm_op *op, unsigned int index) { struct canfd_frame *lcf = op->last_frames + op->cfsiz * index; if ((op->last_frames) && (lcf->flags & RX_THR)) { - if (update) - bcm_rx_changed(op, lcf); + bcm_rx_changed(op, lcf); return 1; } return 0; @@ -605,11 +589,8 @@ static inline int bcm_rx_do_flush(struct bcm_op *op, int update, /* * bcm_rx_thr_flush - Check for throttled data and send it to the userspace - * - * update == 0 : just check if throttled data is available (any irq context) - * update == 1 : check and send throttled data to userspace (soft_irq context) */ -static int bcm_rx_thr_flush(struct bcm_op *op, int update) +static int bcm_rx_thr_flush(struct bcm_op *op) { int updated = 0; @@ -618,24 +599,16 @@ static int bcm_rx_thr_flush(struct bcm_op *op, int update) /* for MUX filter we start at index 1 */ for (i = 1; i < op->nframes; i++) - updated += bcm_rx_do_flush(op, update, i); + updated += bcm_rx_do_flush(op, i); } else { /* for RX_FILTER_ID and simple filter */ - updated += bcm_rx_do_flush(op, update, 0); + updated += bcm_rx_do_flush(op, 0); } return updated; } -static void bcm_rx_thr_tsklet(unsigned long data) -{ - struct bcm_op *op = (struct bcm_op *)data; - - /* push the changed data to the userspace */ - bcm_rx_thr_flush(op, 1); -} - /* * bcm_rx_thr_handler - the time for blocked content updates is over now: * Check for throttled data and send it to the userspace @@ -644,9 +617,7 @@ static enum hrtimer_restart bcm_rx_thr_handler(struct hrtimer *hrtimer) { struct bcm_op *op = container_of(hrtimer, struct bcm_op, thrtimer); - tasklet_schedule(&op->thrtsklet); - - if (bcm_rx_thr_flush(op, 0)) { + if (bcm_rx_thr_flush(op)) { hrtimer_forward(hrtimer, ktime_get(), op->kt_ival2); return HRTIMER_RESTART; } else { @@ -742,23 +713,8 @@ static struct bcm_op *bcm_find_op(struct list_head *ops, static void bcm_remove_op(struct bcm_op *op) { - if (op->tsklet.func) { - while (test_bit(TASKLET_STATE_SCHED, &op->tsklet.state) || - test_bit(TASKLET_STATE_RUN, &op->tsklet.state) || - hrtimer_active(&op->timer)) { - hrtimer_cancel(&op->timer); - tasklet_kill(&op->tsklet); - } - } - - if (op->thrtsklet.func) { - while (test_bit(TASKLET_STATE_SCHED, &op->thrtsklet.state) || - test_bit(TASKLET_STATE_RUN, &op->thrtsklet.state) || - hrtimer_active(&op->thrtimer)) { - hrtimer_cancel(&op->thrtimer); - tasklet_kill(&op->thrtsklet); - } - } + hrtimer_cancel(&op->timer); + hrtimer_cancel(&op->thrtimer); if ((op->frames) && (op->frames != &op->sframe)) kfree(op->frames); @@ -991,15 +947,13 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, op->ifindex = ifindex; /* initialize uninitialized (kzalloc) structure */ - hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&op->timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_SOFT); op->timer.function = bcm_tx_timeout_handler; - /* initialize tasklet for tx countevent notification */ - tasklet_init(&op->tsklet, bcm_tx_timeout_tsklet, - (unsigned long) op); - /* currently unused in tx_ops */ - hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_SOFT); /* add this bcm_op to the list of the tx_ops */ list_add(&op->list, &bo->tx_ops); @@ -1168,20 +1122,14 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, op->rx_ifindex = ifindex; /* initialize uninitialized (kzalloc) structure */ - hrtimer_init(&op->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&op->timer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_SOFT); op->timer.function = bcm_rx_timeout_handler; - /* initialize tasklet for rx timeout notification */ - tasklet_init(&op->tsklet, bcm_rx_timeout_tsklet, - (unsigned long) op); - - hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + hrtimer_init(&op->thrtimer, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_SOFT); op->thrtimer.function = bcm_rx_thr_handler; - /* initialize tasklet for rx throttle handling */ - tasklet_init(&op->thrtsklet, bcm_rx_thr_tsklet, - (unsigned long) op); - /* add this bcm_op to the list of the rx_ops */ list_add(&op->list, &bo->rx_ops); @@ -1227,12 +1175,12 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg, */ op->kt_lastmsg = 0; hrtimer_cancel(&op->thrtimer); - bcm_rx_thr_flush(op, 1); + bcm_rx_thr_flush(op); } if ((op->flags & STARTTIMER) && op->kt_ival1) hrtimer_start(&op->timer, op->kt_ival1, - HRTIMER_MODE_REL); + HRTIMER_MODE_REL_SOFT); } /* now we can register for can_ids, if we added a new bcm_op */ From 465c0deb10577e384937970dc99b61cc69212651 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:16:29 +0200 Subject: [PATCH 30/41] can: gw: convert block comments to network style comments This patch converts all block comments to network subsystem style block comments. Signed-off-by: Marc Kleine-Budde --- net/can/gw.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/net/can/gw.c b/net/can/gw.c index ce17f836262b..0f13649c0b36 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) -/* - * gw.c - CAN frame Gateway/Router/Bridge with netlink interface +/* gw.c - CAN frame Gateway/Router/Bridge with netlink interface * * Copyright (c) 2017 Volkswagen Group Electronic Research * All rights reserved. @@ -113,8 +112,7 @@ struct cf_mod { }; -/* - * So far we just support CAN -> CAN routing and frame modifications. +/* So far we just support CAN -> CAN routing and frame modifications. * * The internal can_can_gw structure contains data and attributes for * a CAN -> CAN gateway job. @@ -170,8 +168,7 @@ MODFUNC(mod_set_data, *(u64 *)cf->data = *(u64 *)mod->modframe.set.data) static inline void canframecpy(struct can_frame *dst, struct can_frame *src) { - /* - * Copy the struct members separately to ensure that no uninitialized + /* Copy the struct members separately to ensure that no uninitialized * data are copied in the 3 bytes hole of the struct. This is needed * to make easy compares of the data in the struct cf_mod. */ @@ -183,8 +180,7 @@ static inline void canframecpy(struct can_frame *dst, struct can_frame *src) static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re) { - /* - * absolute dlc values 0 .. 7 => 0 .. 7, e.g. data [0] + /* absolute dlc values 0 .. 7 => 0 .. 7, e.g. data [0] * relative to received dlc -1 .. -8 : * e.g. for received dlc = 8 * -1 => index = 7 (data[7]) @@ -353,8 +349,7 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) struct sk_buff *nskb; int modidx = 0; - /* - * Do not handle CAN frames routed more than 'max_hops' times. + /* Do not handle CAN frames routed more than 'max_hops' times. * In general we should never catch this delimiter which is intended * to cover a misconfiguration protection (e.g. circular CAN routes). * @@ -385,8 +380,7 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) can_skb_prv(skb)->ifindex == gwj->dst.dev->ifindex) return; - /* - * clone the given skb, which has not been done in can_rcv() + /* clone the given skb, which has not been done in can_rcv() * * When there is at least one modification function activated, * we need to copy the skb as we want to modify skb->data. @@ -755,8 +749,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, nla_memcpy(&mod->csum.crc8, tb[CGW_CS_CRC8], CGW_CS_CRC8_LEN); - /* - * select dedicated processing function to reduce + /* select dedicated processing function to reduce * runtime operations in receive hot path. */ if (c->from_idx < 0 || c->to_idx < 0 || @@ -779,8 +772,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, nla_memcpy(&mod->csum.xor, tb[CGW_CS_XOR], CGW_CS_XOR_LEN); - /* - * select dedicated processing function to reduce + /* select dedicated processing function to reduce * runtime operations in receive hot path. */ if (c->from_idx < 0 || c->to_idx < 0 || From f62564f5e3f2463d3b252f7e73b86700c89795e0 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:28:21 +0200 Subject: [PATCH 31/41] can: gw: remove unnecessary blank lines, add suggested blank lines This patch removes unnecessary blank lines, and adds suggested ones, so that checkpatch doesn't complain anymore. Signed-off-by: Marc Kleine-Budde --- net/can/gw.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/net/can/gw.c b/net/can/gw.c index 0f13649c0b36..faecd1047611 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -111,7 +111,6 @@ struct cf_mod { u32 uid; }; - /* So far we just support CAN -> CAN routing and frame modifications. * * The internal can_can_gw structure contains data and attributes for @@ -268,7 +267,6 @@ static void cgw_csum_crc8_rel(struct can_frame *cf, struct cgw_csum_crc8 *crc8) } switch (crc8->profile) { - case CGW_CRC8PRF_1U8: crc = crc8->crctab[crc^crc8->profile_data[0]]; break; @@ -281,7 +279,6 @@ static void cgw_csum_crc8_rel(struct can_frame *cf, struct cgw_csum_crc8 *crc8) crc = crc8->crctab[crc^(cf->can_id & 0xFF)^ (cf->can_id >> 8 & 0xFF)]; break; - } cf->data[crc8->result_idx] = crc^crc8->final_xor_val; @@ -296,7 +293,6 @@ static void cgw_csum_crc8_pos(struct can_frame *cf, struct cgw_csum_crc8 *crc8) crc = crc8->crctab[crc^cf->data[i]]; switch (crc8->profile) { - case CGW_CRC8PRF_1U8: crc = crc8->crctab[crc^crc8->profile_data[0]]; break; @@ -323,7 +319,6 @@ static void cgw_csum_crc8_neg(struct can_frame *cf, struct cgw_csum_crc8 *crc8) crc = crc8->crctab[crc^cf->data[i]]; switch (crc8->profile) { - case CGW_CRC8PRF_1U8: crc = crc8->crctab[crc^crc8->profile_data[0]]; break; @@ -478,14 +473,12 @@ static int cgw_notifier(struct notifier_block *nb, return NOTIFY_DONE; if (msg == NETDEV_UNREGISTER) { - struct cgw_job *gwj = NULL; struct hlist_node *nx; ASSERT_RTNL(); hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) { - if (gwj->src.dev == dev || gwj->dst.dev == dev) { hlist_del(&gwj->list); cgw_unregister_filter(net, gwj); @@ -583,7 +576,6 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, } if (gwj->gwtype == CGW_TYPE_CAN_CAN) { - if (gwj->ccgw.filter.can_id || gwj->ccgw.filter.can_mask) { if (nla_put(skb, CGW_FILTER, sizeof(struct can_filter), &gwj->ccgw.filter) < 0) @@ -737,7 +729,6 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, /* check for checksum operations after CAN frame modifications */ if (modidx) { - if (tb[CGW_CS_CRC8]) { struct cgw_csum_crc8 *c = nla_data(tb[CGW_CS_CRC8]); @@ -790,10 +781,9 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, } if (gwtype == CGW_TYPE_CAN_CAN) { - /* check CGW_TYPE_CAN_CAN specific attributes */ - struct can_can_gw *ccgw = (struct can_can_gw *)gwtypeattr; + memset(ccgw, 0, sizeof(*ccgw)); /* check for can_filter in attributes */ @@ -854,12 +844,10 @@ static int cgw_create_job(struct sk_buff *skb, struct nlmsghdr *nlh, return err; if (mod.uid) { - ASSERT_RTNL(); /* check for updating an existing job with identical uid */ hlist_for_each_entry(gwj, &net->can.cgw_list, list) { - if (gwj->mod.uid != mod.uid) continue; @@ -980,7 +968,6 @@ static int cgw_remove_job(struct sk_buff *skb, struct nlmsghdr *nlh, /* remove only the first matching entry */ hlist_for_each_entry_safe(gwj, nx, &net->can.cgw_list, list) { - if (gwj->flags != r->flags) continue; From 5dfc8c94a887d3e0553316430c4fb33df85ccc89 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:31:48 +0200 Subject: [PATCH 32/41] can: gw: add missing spaces around operators This patch add missing spaces around the '^' and '+' operators. Signed-off-by: Marc Kleine-Budde --- net/can/gw.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/net/can/gw.c b/net/can/gw.c index faecd1047611..ff7366ecd5cd 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -260,28 +260,28 @@ static void cgw_csum_crc8_rel(struct can_frame *cf, struct cgw_csum_crc8 *crc8) if (from <= to) { for (i = crc8->from_idx; i <= crc8->to_idx; i++) - crc = crc8->crctab[crc^cf->data[i]]; + crc = crc8->crctab[crc ^ cf->data[i]]; } else { for (i = crc8->from_idx; i >= crc8->to_idx; i--) - crc = crc8->crctab[crc^cf->data[i]]; + crc = crc8->crctab[crc ^ cf->data[i]]; } switch (crc8->profile) { case CGW_CRC8PRF_1U8: - crc = crc8->crctab[crc^crc8->profile_data[0]]; + crc = crc8->crctab[crc ^ crc8->profile_data[0]]; break; case CGW_CRC8PRF_16U8: - crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]]; + crc = crc8->crctab[crc ^ crc8->profile_data[cf->data[1] & 0xF]]; break; case CGW_CRC8PRF_SFFID_XOR: - crc = crc8->crctab[crc^(cf->can_id & 0xFF)^ + crc = crc8->crctab[crc ^ (cf->can_id & 0xFF) ^ (cf->can_id >> 8 & 0xFF)]; break; } - cf->data[crc8->result_idx] = crc^crc8->final_xor_val; + cf->data[crc8->result_idx] = crc ^ crc8->final_xor_val; } static void cgw_csum_crc8_pos(struct can_frame *cf, struct cgw_csum_crc8 *crc8) @@ -290,24 +290,24 @@ static void cgw_csum_crc8_pos(struct can_frame *cf, struct cgw_csum_crc8 *crc8) int i; for (i = crc8->from_idx; i <= crc8->to_idx; i++) - crc = crc8->crctab[crc^cf->data[i]]; + crc = crc8->crctab[crc ^ cf->data[i]]; switch (crc8->profile) { case CGW_CRC8PRF_1U8: - crc = crc8->crctab[crc^crc8->profile_data[0]]; + crc = crc8->crctab[crc ^ crc8->profile_data[0]]; break; case CGW_CRC8PRF_16U8: - crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]]; + crc = crc8->crctab[crc ^ crc8->profile_data[cf->data[1] & 0xF]]; break; case CGW_CRC8PRF_SFFID_XOR: - crc = crc8->crctab[crc^(cf->can_id & 0xFF)^ + crc = crc8->crctab[crc ^ (cf->can_id & 0xFF) ^ (cf->can_id >> 8 & 0xFF)]; break; } - cf->data[crc8->result_idx] = crc^crc8->final_xor_val; + cf->data[crc8->result_idx] = crc ^ crc8->final_xor_val; } static void cgw_csum_crc8_neg(struct can_frame *cf, struct cgw_csum_crc8 *crc8) @@ -316,24 +316,24 @@ static void cgw_csum_crc8_neg(struct can_frame *cf, struct cgw_csum_crc8 *crc8) int i; for (i = crc8->from_idx; i >= crc8->to_idx; i--) - crc = crc8->crctab[crc^cf->data[i]]; + crc = crc8->crctab[crc ^ cf->data[i]]; switch (crc8->profile) { case CGW_CRC8PRF_1U8: - crc = crc8->crctab[crc^crc8->profile_data[0]]; + crc = crc8->crctab[crc ^ crc8->profile_data[0]]; break; case CGW_CRC8PRF_16U8: - crc = crc8->crctab[crc^crc8->profile_data[cf->data[1] & 0xF]]; + crc = crc8->crctab[crc ^ crc8->profile_data[cf->data[1] & 0xF]]; break; case CGW_CRC8PRF_SFFID_XOR: - crc = crc8->crctab[crc^(cf->can_id & 0xFF)^ + crc = crc8->crctab[crc ^ (cf->can_id & 0xFF) ^ (cf->can_id >> 8 & 0xFF)]; break; } - cf->data[crc8->result_idx] = crc^crc8->final_xor_val; + cf->data[crc8->result_idx] = crc ^ crc8->final_xor_val; } /* the receive & process & send function */ @@ -623,7 +623,7 @@ cont: return skb->len; } -static const struct nla_policy cgw_policy[CGW_MAX+1] = { +static const struct nla_policy cgw_policy[CGW_MAX + 1] = { [CGW_MOD_AND] = { .len = sizeof(struct cgw_frame_mod) }, [CGW_MOD_OR] = { .len = sizeof(struct cgw_frame_mod) }, [CGW_MOD_XOR] = { .len = sizeof(struct cgw_frame_mod) }, @@ -641,7 +641,7 @@ static const struct nla_policy cgw_policy[CGW_MAX+1] = { static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, u8 gwtype, void *gwtypeattr, u8 *limhops) { - struct nlattr *tb[CGW_MAX+1]; + struct nlattr *tb[CGW_MAX + 1]; struct cgw_frame_mod mb; int modidx = 0; int err = 0; From 0815c891e52208dc798916650b3496a2a53ee81f Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:33:13 +0200 Subject: [PATCH 33/41] can: gw: can_can_gw_rcv(): remove return at end of void function This patch remove the return at the end of the void function can_can_gw_rcv(). Signed-off-by: Marc Kleine-Budde --- net/can/gw.c | 1 - 1 file changed, 1 deletion(-) diff --git a/net/can/gw.c b/net/can/gw.c index ff7366ecd5cd..9b2efbad1b7e 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -447,7 +447,6 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) /* delete frame due to misconfiguration */ gwj->deleted_frames++; kfree_skb(nskb); - return; } static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj) From 78f8a326f924b090d5a495049c91aa599796f2aa Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:34:42 +0200 Subject: [PATCH 34/41] can: gw: cgw_dump_jobs(): avoid long lines This patch rewraps the arguments of cgw_put_job() to avoid long lines, which also fixes the indention. Signed-off-by: Marc Kleine-Budde --- net/can/gw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/can/gw.c b/net/can/gw.c index 9b2efbad1b7e..2d2be4afd560 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -609,8 +609,9 @@ static int cgw_dump_jobs(struct sk_buff *skb, struct netlink_callback *cb) if (idx < s_idx) goto cont; - if (cgw_put_job(skb, gwj, RTM_NEWROUTE, NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, NLM_F_MULTI) < 0) + if (cgw_put_job(skb, gwj, RTM_NEWROUTE, + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI) < 0) break; cont: idx++; From 21468e6de80e2e3584024f796e3c0ce8b12474bd Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:48:14 +0200 Subject: [PATCH 35/41] can: gw: cgw_parse_attr(): remove unnecessary braces for single statement block This patch removes some unnecessary braces for a single statement block. Signed-off-by: Marc Kleine-Budde --- net/can/gw.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/net/can/gw.c b/net/can/gw.c index 2d2be4afd560..4c6ad0054a4c 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -775,9 +775,8 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, mod->csumfunc.xor = cgw_csum_xor_neg; } - if (tb[CGW_MOD_UID]) { + if (tb[CGW_MOD_UID]) nla_memcpy(&mod->uid, tb[CGW_MOD_UID], sizeof(u32)); - } } if (gwtype == CGW_TYPE_CAN_CAN) { From e9dc7c60507c822992e793bd3845f0556ae0ff98 Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Sat, 10 Aug 2019 21:18:09 +0200 Subject: [PATCH 36/41] can: gw: use struct canfd_frame as internal data structure To prepare the CAN FD support this patch implements the first adaptions in data structures for CAN FD without changing the current functionality. Additionally some code at the end of this patch is moved or indented to simplify the review of the next implementation step. Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- include/uapi/linux/can/gw.h | 5 +- net/can/gw.c | 222 +++++++++++++++++++----------------- 2 files changed, 120 insertions(+), 107 deletions(-) diff --git a/include/uapi/linux/can/gw.h b/include/uapi/linux/can/gw.h index 7bee7a0b9800..ed811bc463b5 100644 --- a/include/uapi/linux/can/gw.h +++ b/include/uapi/linux/can/gw.h @@ -93,10 +93,11 @@ enum { /* CAN frame elements that are affected by curr. 3 CAN frame modifications */ #define CGW_MOD_ID 0x01 -#define CGW_MOD_DLC 0x02 +#define CGW_MOD_DLC 0x02 /* contains the data length in bytes */ +#define CGW_MOD_LEN CGW_MOD_DLC /* CAN FD length representation */ #define CGW_MOD_DATA 0x04 -#define CGW_FRAME_MODS 3 /* ID DLC DATA */ +#define CGW_FRAME_MODS 3 /* ID DLC/LEN DATA */ #define MAX_MODFUNCTIONS (CGW_MOD_FUNCS * CGW_FRAME_MODS) diff --git a/net/can/gw.c b/net/can/gw.c index 4c6ad0054a4c..3a1ad206fbef 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -85,10 +85,10 @@ static struct kmem_cache *cgw_cache __read_mostly; /* structure that contains the (on-the-fly) CAN frame modifications */ struct cf_mod { struct { - struct can_frame and; - struct can_frame or; - struct can_frame xor; - struct can_frame set; + struct canfd_frame and; + struct canfd_frame or; + struct canfd_frame xor; + struct canfd_frame set; } modframe; struct { u8 and; @@ -96,7 +96,7 @@ struct cf_mod { u8 xor; u8 set; } modtype; - void (*modfunc[MAX_MODFUNCTIONS])(struct can_frame *cf, + void (*modfunc[MAX_MODFUNCTIONS])(struct canfd_frame *cf, struct cf_mod *mod); /* CAN frame checksum calculation after CAN frame modifications */ @@ -105,8 +105,10 @@ struct cf_mod { struct cgw_csum_crc8 crc8; } csum; struct { - void (*xor)(struct can_frame *cf, struct cgw_csum_xor *xor); - void (*crc8)(struct can_frame *cf, struct cgw_csum_crc8 *crc8); + void (*xor)(struct canfd_frame *cf, + struct cgw_csum_xor *xor); + void (*crc8)(struct canfd_frame *cf, + struct cgw_csum_crc8 *crc8); } csumfunc; u32 uid; }; @@ -149,23 +151,23 @@ struct cgw_job { /* modification functions that are invoked in the hot path in can_can_gw_rcv */ -#define MODFUNC(func, op) static void func(struct can_frame *cf, \ +#define MODFUNC(func, op) static void func(struct canfd_frame *cf, \ struct cf_mod *mod) { op ; } MODFUNC(mod_and_id, cf->can_id &= mod->modframe.and.can_id) -MODFUNC(mod_and_dlc, cf->can_dlc &= mod->modframe.and.can_dlc) +MODFUNC(mod_and_len, cf->len &= mod->modframe.and.len) MODFUNC(mod_and_data, *(u64 *)cf->data &= *(u64 *)mod->modframe.and.data) MODFUNC(mod_or_id, cf->can_id |= mod->modframe.or.can_id) -MODFUNC(mod_or_dlc, cf->can_dlc |= mod->modframe.or.can_dlc) +MODFUNC(mod_or_len, cf->len |= mod->modframe.or.len) MODFUNC(mod_or_data, *(u64 *)cf->data |= *(u64 *)mod->modframe.or.data) MODFUNC(mod_xor_id, cf->can_id ^= mod->modframe.xor.can_id) -MODFUNC(mod_xor_dlc, cf->can_dlc ^= mod->modframe.xor.can_dlc) +MODFUNC(mod_xor_len, cf->len ^= mod->modframe.xor.len) MODFUNC(mod_xor_data, *(u64 *)cf->data ^= *(u64 *)mod->modframe.xor.data) MODFUNC(mod_set_id, cf->can_id = mod->modframe.set.can_id) -MODFUNC(mod_set_dlc, cf->can_dlc = mod->modframe.set.can_dlc) +MODFUNC(mod_set_len, cf->len = mod->modframe.set.len) MODFUNC(mod_set_data, *(u64 *)cf->data = *(u64 *)mod->modframe.set.data) -static inline void canframecpy(struct can_frame *dst, struct can_frame *src) +static void canframecpy(struct canfd_frame *dst, struct can_frame *src) { /* Copy the struct members separately to ensure that no uninitialized * data are copied in the 3 bytes hole of the struct. This is needed @@ -173,12 +175,14 @@ static inline void canframecpy(struct can_frame *dst, struct can_frame *src) */ dst->can_id = src->can_id; - dst->can_dlc = src->can_dlc; + dst->len = src->can_dlc; *(u64 *)dst->data = *(u64 *)src->data; } static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re) { + s8 dlen = CAN_MAX_DLEN; + /* absolute dlc values 0 .. 7 => 0 .. 7, e.g. data [0] * relative to received dlc -1 .. -8 : * e.g. for received dlc = 8 @@ -187,27 +191,27 @@ static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re) * -8 => index = 0 (data[0]) */ - if (fr > -9 && fr < 8 && - to > -9 && to < 8 && - re > -9 && re < 8) + if (fr >= -dlen && fr < dlen && + to >= -dlen && to < dlen && + re >= -dlen && re < dlen) return 0; else return -EINVAL; } -static inline int calc_idx(int idx, int rx_dlc) +static inline int calc_idx(int idx, int rx_len) { if (idx < 0) - return rx_dlc + idx; + return rx_len + idx; else return idx; } -static void cgw_csum_xor_rel(struct can_frame *cf, struct cgw_csum_xor *xor) +static void cgw_csum_xor_rel(struct canfd_frame *cf, struct cgw_csum_xor *xor) { - int from = calc_idx(xor->from_idx, cf->can_dlc); - int to = calc_idx(xor->to_idx, cf->can_dlc); - int res = calc_idx(xor->result_idx, cf->can_dlc); + int from = calc_idx(xor->from_idx, cf->len); + int to = calc_idx(xor->to_idx, cf->len); + int res = calc_idx(xor->result_idx, cf->len); u8 val = xor->init_xor_val; int i; @@ -225,7 +229,7 @@ static void cgw_csum_xor_rel(struct can_frame *cf, struct cgw_csum_xor *xor) cf->data[res] = val; } -static void cgw_csum_xor_pos(struct can_frame *cf, struct cgw_csum_xor *xor) +static void cgw_csum_xor_pos(struct canfd_frame *cf, struct cgw_csum_xor *xor) { u8 val = xor->init_xor_val; int i; @@ -236,7 +240,7 @@ static void cgw_csum_xor_pos(struct can_frame *cf, struct cgw_csum_xor *xor) cf->data[xor->result_idx] = val; } -static void cgw_csum_xor_neg(struct can_frame *cf, struct cgw_csum_xor *xor) +static void cgw_csum_xor_neg(struct canfd_frame *cf, struct cgw_csum_xor *xor) { u8 val = xor->init_xor_val; int i; @@ -247,11 +251,12 @@ static void cgw_csum_xor_neg(struct can_frame *cf, struct cgw_csum_xor *xor) cf->data[xor->result_idx] = val; } -static void cgw_csum_crc8_rel(struct can_frame *cf, struct cgw_csum_crc8 *crc8) +static void cgw_csum_crc8_rel(struct canfd_frame *cf, + struct cgw_csum_crc8 *crc8) { - int from = calc_idx(crc8->from_idx, cf->can_dlc); - int to = calc_idx(crc8->to_idx, cf->can_dlc); - int res = calc_idx(crc8->result_idx, cf->can_dlc); + int from = calc_idx(crc8->from_idx, cf->len); + int to = calc_idx(crc8->to_idx, cf->len); + int res = calc_idx(crc8->result_idx, cf->len); u8 crc = crc8->init_crc_val; int i; @@ -284,7 +289,8 @@ static void cgw_csum_crc8_rel(struct can_frame *cf, struct cgw_csum_crc8 *crc8) cf->data[crc8->result_idx] = crc ^ crc8->final_xor_val; } -static void cgw_csum_crc8_pos(struct can_frame *cf, struct cgw_csum_crc8 *crc8) +static void cgw_csum_crc8_pos(struct canfd_frame *cf, + struct cgw_csum_crc8 *crc8) { u8 crc = crc8->init_crc_val; int i; @@ -310,7 +316,8 @@ static void cgw_csum_crc8_pos(struct can_frame *cf, struct cgw_csum_crc8 *crc8) cf->data[crc8->result_idx] = crc ^ crc8->final_xor_val; } -static void cgw_csum_crc8_neg(struct can_frame *cf, struct cgw_csum_crc8 *crc8) +static void cgw_csum_crc8_neg(struct canfd_frame *cf, + struct cgw_csum_crc8 *crc8) { u8 crc = crc8->init_crc_val; int i; @@ -340,7 +347,7 @@ static void cgw_csum_crc8_neg(struct can_frame *cf, struct cgw_csum_crc8 *crc8) static void can_can_gw_rcv(struct sk_buff *skb, void *data) { struct cgw_job *gwj = (struct cgw_job *)data; - struct can_frame *cf; + struct canfd_frame *cf; struct sk_buff *nskb; int modidx = 0; @@ -400,7 +407,7 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) nskb->dev = gwj->dst.dev; /* pointer to modifiable CAN frame */ - cf = (struct can_frame *)nskb->data; + cf = (struct canfd_frame *)nskb->data; /* perform preprocessed modification functions if there are any */ while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx]) @@ -409,22 +416,22 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) /* Has the CAN frame been modified? */ if (modidx) { /* get available space for the processed CAN frame type */ - int max_len = nskb->len - offsetof(struct can_frame, data); + int max_len = nskb->len - offsetof(struct canfd_frame, data); /* dlc may have changed, make sure it fits to the CAN frame */ - if (cf->can_dlc > max_len) + if (cf->len > max_len) goto out_delete; /* check for checksum updates in classic CAN length only */ if (gwj->mod.csumfunc.crc8) { - if (cf->can_dlc > 8) + if (cf->len > 8) goto out_delete; (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8); } if (gwj->mod.csumfunc.xor) { - if (cf->can_dlc > 8) + if (cf->len > 8) goto out_delete; (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor); @@ -492,7 +499,6 @@ static int cgw_notifier(struct notifier_block *nb, static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, u32 pid, u32 seq, int flags) { - struct cgw_frame_mod mb; struct rtcanmsg *rtcan; struct nlmsghdr *nlh; @@ -529,32 +535,36 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, goto cancel; } - if (gwj->mod.modtype.and) { - memcpy(&mb.cf, &gwj->mod.modframe.and, sizeof(mb.cf)); - mb.modtype = gwj->mod.modtype.and; - if (nla_put(skb, CGW_MOD_AND, sizeof(mb), &mb) < 0) - goto cancel; - } + if (1) { + struct cgw_frame_mod mb; - if (gwj->mod.modtype.or) { - memcpy(&mb.cf, &gwj->mod.modframe.or, sizeof(mb.cf)); - mb.modtype = gwj->mod.modtype.or; - if (nla_put(skb, CGW_MOD_OR, sizeof(mb), &mb) < 0) - goto cancel; - } + if (gwj->mod.modtype.and) { + memcpy(&mb.cf, &gwj->mod.modframe.and, sizeof(mb.cf)); + mb.modtype = gwj->mod.modtype.and; + if (nla_put(skb, CGW_MOD_AND, sizeof(mb), &mb) < 0) + goto cancel; + } - if (gwj->mod.modtype.xor) { - memcpy(&mb.cf, &gwj->mod.modframe.xor, sizeof(mb.cf)); - mb.modtype = gwj->mod.modtype.xor; - if (nla_put(skb, CGW_MOD_XOR, sizeof(mb), &mb) < 0) - goto cancel; - } + if (gwj->mod.modtype.or) { + memcpy(&mb.cf, &gwj->mod.modframe.or, sizeof(mb.cf)); + mb.modtype = gwj->mod.modtype.or; + if (nla_put(skb, CGW_MOD_OR, sizeof(mb), &mb) < 0) + goto cancel; + } - if (gwj->mod.modtype.set) { - memcpy(&mb.cf, &gwj->mod.modframe.set, sizeof(mb.cf)); - mb.modtype = gwj->mod.modtype.set; - if (nla_put(skb, CGW_MOD_SET, sizeof(mb), &mb) < 0) - goto cancel; + if (gwj->mod.modtype.xor) { + memcpy(&mb.cf, &gwj->mod.modframe.xor, sizeof(mb.cf)); + mb.modtype = gwj->mod.modtype.xor; + if (nla_put(skb, CGW_MOD_XOR, sizeof(mb), &mb) < 0) + goto cancel; + } + + if (gwj->mod.modtype.set) { + memcpy(&mb.cf, &gwj->mod.modframe.set, sizeof(mb.cf)); + mb.modtype = gwj->mod.modtype.set; + if (nla_put(skb, CGW_MOD_SET, sizeof(mb), &mb) < 0) + goto cancel; + } } if (gwj->mod.uid) { @@ -642,7 +652,6 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, u8 gwtype, void *gwtypeattr, u8 *limhops) { struct nlattr *tb[CGW_MAX + 1]; - struct cgw_frame_mod mb; int modidx = 0; int err = 0; @@ -662,69 +671,72 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, } /* check for AND/OR/XOR/SET modifications */ + if (1) { + struct cgw_frame_mod mb; - if (tb[CGW_MOD_AND]) { - nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN); + if (tb[CGW_MOD_AND]) { + nla_memcpy(&mb, tb[CGW_MOD_AND], CGW_MODATTR_LEN); - canframecpy(&mod->modframe.and, &mb.cf); - mod->modtype.and = mb.modtype; + canframecpy(&mod->modframe.and, &mb.cf); + mod->modtype.and = mb.modtype; - if (mb.modtype & CGW_MOD_ID) - mod->modfunc[modidx++] = mod_and_id; + if (mb.modtype & CGW_MOD_ID) + mod->modfunc[modidx++] = mod_and_id; - if (mb.modtype & CGW_MOD_DLC) - mod->modfunc[modidx++] = mod_and_dlc; + if (mb.modtype & CGW_MOD_LEN) + mod->modfunc[modidx++] = mod_and_len; - if (mb.modtype & CGW_MOD_DATA) - mod->modfunc[modidx++] = mod_and_data; - } + if (mb.modtype & CGW_MOD_DATA) + mod->modfunc[modidx++] = mod_and_data; + } - if (tb[CGW_MOD_OR]) { - nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN); + if (tb[CGW_MOD_OR]) { + nla_memcpy(&mb, tb[CGW_MOD_OR], CGW_MODATTR_LEN); - canframecpy(&mod->modframe.or, &mb.cf); - mod->modtype.or = mb.modtype; + canframecpy(&mod->modframe.or, &mb.cf); + mod->modtype.or = mb.modtype; - if (mb.modtype & CGW_MOD_ID) - mod->modfunc[modidx++] = mod_or_id; + if (mb.modtype & CGW_MOD_ID) + mod->modfunc[modidx++] = mod_or_id; - if (mb.modtype & CGW_MOD_DLC) - mod->modfunc[modidx++] = mod_or_dlc; + if (mb.modtype & CGW_MOD_LEN) + mod->modfunc[modidx++] = mod_or_len; - if (mb.modtype & CGW_MOD_DATA) - mod->modfunc[modidx++] = mod_or_data; - } + if (mb.modtype & CGW_MOD_DATA) + mod->modfunc[modidx++] = mod_or_data; + } - if (tb[CGW_MOD_XOR]) { - nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN); + if (tb[CGW_MOD_XOR]) { + nla_memcpy(&mb, tb[CGW_MOD_XOR], CGW_MODATTR_LEN); - canframecpy(&mod->modframe.xor, &mb.cf); - mod->modtype.xor = mb.modtype; + canframecpy(&mod->modframe.xor, &mb.cf); + mod->modtype.xor = mb.modtype; - if (mb.modtype & CGW_MOD_ID) - mod->modfunc[modidx++] = mod_xor_id; + if (mb.modtype & CGW_MOD_ID) + mod->modfunc[modidx++] = mod_xor_id; - if (mb.modtype & CGW_MOD_DLC) - mod->modfunc[modidx++] = mod_xor_dlc; + if (mb.modtype & CGW_MOD_LEN) + mod->modfunc[modidx++] = mod_xor_len; - if (mb.modtype & CGW_MOD_DATA) - mod->modfunc[modidx++] = mod_xor_data; - } + if (mb.modtype & CGW_MOD_DATA) + mod->modfunc[modidx++] = mod_xor_data; + } - if (tb[CGW_MOD_SET]) { - nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN); + if (tb[CGW_MOD_SET]) { + nla_memcpy(&mb, tb[CGW_MOD_SET], CGW_MODATTR_LEN); - canframecpy(&mod->modframe.set, &mb.cf); - mod->modtype.set = mb.modtype; + canframecpy(&mod->modframe.set, &mb.cf); + mod->modtype.set = mb.modtype; - if (mb.modtype & CGW_MOD_ID) - mod->modfunc[modidx++] = mod_set_id; + if (mb.modtype & CGW_MOD_ID) + mod->modfunc[modidx++] = mod_set_id; - if (mb.modtype & CGW_MOD_DLC) - mod->modfunc[modidx++] = mod_set_dlc; + if (mb.modtype & CGW_MOD_LEN) + mod->modfunc[modidx++] = mod_set_len; - if (mb.modtype & CGW_MOD_DATA) - mod->modfunc[modidx++] = mod_set_data; + if (mb.modtype & CGW_MOD_DATA) + mod->modfunc[modidx++] = mod_set_data; + } } /* check for checksum operations after CAN frame modifications */ From 456a8a646b2563438c16a9b27decf9aa717f1ebb Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Sat, 10 Aug 2019 21:18:10 +0200 Subject: [PATCH 37/41] can: gw: add support for CAN FD frames Introduce CAN FD support which needs an extension of the netlink API to pass CAN FD type content to the kernel which has a different size to Classic CAN. Additionally the struct canfd_frame has a new 'flags' element that can now be modified with can-gw. The new CGW_FLAGS_CAN_FD option flag defines whether the routing job handles Classic CAN or CAN FD frames. This setting is very strict at reception time and enables the new possibilities, e.g. CGW_FDMOD_* and modifying the flags element of struct canfd_frame, only when CGW_FLAGS_CAN_FD is set. Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- include/uapi/linux/can/gw.h | 14 ++- net/can/gw.c | 214 +++++++++++++++++++++++++++++++----- 2 files changed, 200 insertions(+), 28 deletions(-) diff --git a/include/uapi/linux/can/gw.h b/include/uapi/linux/can/gw.h index ed811bc463b5..3aea5388c8e4 100644 --- a/include/uapi/linux/can/gw.h +++ b/include/uapi/linux/can/gw.h @@ -80,6 +80,10 @@ enum { CGW_DELETED, /* number of deleted CAN frames (see max_hops param) */ CGW_LIM_HOPS, /* limit the number of hops of this specific rule */ CGW_MOD_UID, /* user defined identifier for modification updates */ + CGW_FDMOD_AND, /* CAN FD frame modification binary AND */ + CGW_FDMOD_OR, /* CAN FD frame modification binary OR */ + CGW_FDMOD_XOR, /* CAN FD frame modification binary XOR */ + CGW_FDMOD_SET, /* CAN FD frame modification set alternate values */ __CGW_MAX }; @@ -88,6 +92,7 @@ enum { #define CGW_FLAGS_CAN_ECHO 0x01 #define CGW_FLAGS_CAN_SRC_TSTAMP 0x02 #define CGW_FLAGS_CAN_IIF_TX_OK 0x04 +#define CGW_FLAGS_CAN_FD 0x08 #define CGW_MOD_FUNCS 4 /* AND OR XOR SET */ @@ -96,8 +101,9 @@ enum { #define CGW_MOD_DLC 0x02 /* contains the data length in bytes */ #define CGW_MOD_LEN CGW_MOD_DLC /* CAN FD length representation */ #define CGW_MOD_DATA 0x04 +#define CGW_MOD_FLAGS 0x08 /* CAN FD flags */ -#define CGW_FRAME_MODS 3 /* ID DLC/LEN DATA */ +#define CGW_FRAME_MODS 4 /* ID DLC/LEN DATA FLAGS */ #define MAX_MODFUNCTIONS (CGW_MOD_FUNCS * CGW_FRAME_MODS) @@ -106,7 +112,13 @@ struct cgw_frame_mod { __u8 modtype; } __attribute__((packed)); +struct cgw_fdframe_mod { + struct canfd_frame cf; + __u8 modtype; +} __attribute__((packed)); + #define CGW_MODATTR_LEN sizeof(struct cgw_frame_mod) +#define CGW_FDMODATTR_LEN sizeof(struct cgw_fdframe_mod) struct cgw_csum_xor { __s8 from_idx; diff --git a/net/can/gw.c b/net/can/gw.c index 3a1ad206fbef..65d60c93af29 100644 --- a/net/can/gw.c +++ b/net/can/gw.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) /* gw.c - CAN frame Gateway/Router/Bridge with netlink interface * - * Copyright (c) 2017 Volkswagen Group Electronic Research + * Copyright (c) 2019 Volkswagen Group Electronic Research * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -59,7 +59,7 @@ #include #include -#define CAN_GW_VERSION "20170425" +#define CAN_GW_VERSION "20190810" #define CAN_GW_NAME "can-gw" MODULE_DESCRIPTION("PF_CAN netlink gateway"); @@ -156,17 +156,50 @@ struct cgw_job { MODFUNC(mod_and_id, cf->can_id &= mod->modframe.and.can_id) MODFUNC(mod_and_len, cf->len &= mod->modframe.and.len) +MODFUNC(mod_and_flags, cf->flags &= mod->modframe.and.flags) MODFUNC(mod_and_data, *(u64 *)cf->data &= *(u64 *)mod->modframe.and.data) MODFUNC(mod_or_id, cf->can_id |= mod->modframe.or.can_id) MODFUNC(mod_or_len, cf->len |= mod->modframe.or.len) +MODFUNC(mod_or_flags, cf->flags |= mod->modframe.or.flags) MODFUNC(mod_or_data, *(u64 *)cf->data |= *(u64 *)mod->modframe.or.data) MODFUNC(mod_xor_id, cf->can_id ^= mod->modframe.xor.can_id) MODFUNC(mod_xor_len, cf->len ^= mod->modframe.xor.len) +MODFUNC(mod_xor_flags, cf->flags ^= mod->modframe.xor.flags) MODFUNC(mod_xor_data, *(u64 *)cf->data ^= *(u64 *)mod->modframe.xor.data) MODFUNC(mod_set_id, cf->can_id = mod->modframe.set.can_id) MODFUNC(mod_set_len, cf->len = mod->modframe.set.len) +MODFUNC(mod_set_flags, cf->flags = mod->modframe.set.flags) MODFUNC(mod_set_data, *(u64 *)cf->data = *(u64 *)mod->modframe.set.data) +static void mod_and_fddata(struct canfd_frame *cf, struct cf_mod *mod) +{ + int i; + + for (i = 0; i < CANFD_MAX_DLEN; i += 8) + *(u64 *)(cf->data + i) &= *(u64 *)(mod->modframe.and.data + i); +} + +static void mod_or_fddata(struct canfd_frame *cf, struct cf_mod *mod) +{ + int i; + + for (i = 0; i < CANFD_MAX_DLEN; i += 8) + *(u64 *)(cf->data + i) |= *(u64 *)(mod->modframe.or.data + i); +} + +static void mod_xor_fddata(struct canfd_frame *cf, struct cf_mod *mod) +{ + int i; + + for (i = 0; i < CANFD_MAX_DLEN; i += 8) + *(u64 *)(cf->data + i) ^= *(u64 *)(mod->modframe.xor.data + i); +} + +static void mod_set_fddata(struct canfd_frame *cf, struct cf_mod *mod) +{ + memcpy(cf->data, mod->modframe.set.data, CANFD_MAX_DLEN); +} + static void canframecpy(struct canfd_frame *dst, struct can_frame *src) { /* Copy the struct members separately to ensure that no uninitialized @@ -179,10 +212,26 @@ static void canframecpy(struct canfd_frame *dst, struct can_frame *src) *(u64 *)dst->data = *(u64 *)src->data; } -static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re) +static void canfdframecpy(struct canfd_frame *dst, struct canfd_frame *src) +{ + /* Copy the struct members separately to ensure that no uninitialized + * data are copied in the 2 bytes hole of the struct. This is needed + * to make easy compares of the data in the struct cf_mod. + */ + + dst->can_id = src->can_id; + dst->flags = src->flags; + dst->len = src->len; + memcpy(dst->data, src->data, CANFD_MAX_DLEN); +} + +static int cgw_chk_csum_parms(s8 fr, s8 to, s8 re, struct rtcanmsg *r) { s8 dlen = CAN_MAX_DLEN; + if (r->flags & CGW_FLAGS_CAN_FD) + dlen = CANFD_MAX_DLEN; + /* absolute dlc values 0 .. 7 => 0 .. 7, e.g. data [0] * relative to received dlc -1 .. -8 : * e.g. for received dlc = 8 @@ -351,6 +400,15 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) struct sk_buff *nskb; int modidx = 0; + /* process strictly Classic CAN or CAN FD frames */ + if (gwj->flags & CGW_FLAGS_CAN_FD) { + if (skb->len != CANFD_MTU) + return; + } else { + if (skb->len != CAN_MTU) + return; + } + /* Do not handle CAN frames routed more than 'max_hops' times. * In general we should never catch this delimiter which is intended * to cover a misconfiguration protection (e.g. circular CAN routes). @@ -419,23 +477,19 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) int max_len = nskb->len - offsetof(struct canfd_frame, data); /* dlc may have changed, make sure it fits to the CAN frame */ - if (cf->len > max_len) - goto out_delete; - - /* check for checksum updates in classic CAN length only */ - if (gwj->mod.csumfunc.crc8) { - if (cf->len > 8) - goto out_delete; + if (cf->len > max_len) { + /* delete frame due to misconfiguration */ + gwj->deleted_frames++; + kfree_skb(nskb); + return; + } + /* check for checksum updates */ + if (gwj->mod.csumfunc.crc8) (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8); - } - - if (gwj->mod.csumfunc.xor) { - if (cf->len > 8) - goto out_delete; + if (gwj->mod.csumfunc.xor) (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor); - } } /* clear the skb timestamp if not configured the other way */ @@ -447,13 +501,6 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data) gwj->dropped_frames++; else gwj->handled_frames++; - - return; - - out_delete: - /* delete frame due to misconfiguration */ - gwj->deleted_frames++; - kfree_skb(nskb); } static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj) @@ -535,7 +582,37 @@ static int cgw_put_job(struct sk_buff *skb, struct cgw_job *gwj, int type, goto cancel; } - if (1) { + if (gwj->flags & CGW_FLAGS_CAN_FD) { + struct cgw_fdframe_mod mb; + + if (gwj->mod.modtype.and) { + memcpy(&mb.cf, &gwj->mod.modframe.and, sizeof(mb.cf)); + mb.modtype = gwj->mod.modtype.and; + if (nla_put(skb, CGW_FDMOD_AND, sizeof(mb), &mb) < 0) + goto cancel; + } + + if (gwj->mod.modtype.or) { + memcpy(&mb.cf, &gwj->mod.modframe.or, sizeof(mb.cf)); + mb.modtype = gwj->mod.modtype.or; + if (nla_put(skb, CGW_FDMOD_OR, sizeof(mb), &mb) < 0) + goto cancel; + } + + if (gwj->mod.modtype.xor) { + memcpy(&mb.cf, &gwj->mod.modframe.xor, sizeof(mb.cf)); + mb.modtype = gwj->mod.modtype.xor; + if (nla_put(skb, CGW_FDMOD_XOR, sizeof(mb), &mb) < 0) + goto cancel; + } + + if (gwj->mod.modtype.set) { + memcpy(&mb.cf, &gwj->mod.modframe.set, sizeof(mb.cf)); + mb.modtype = gwj->mod.modtype.set; + if (nla_put(skb, CGW_FDMOD_SET, sizeof(mb), &mb) < 0) + goto cancel; + } + } else { struct cgw_frame_mod mb; if (gwj->mod.modtype.and) { @@ -645,6 +722,10 @@ static const struct nla_policy cgw_policy[CGW_MAX + 1] = { [CGW_FILTER] = { .len = sizeof(struct can_filter) }, [CGW_LIM_HOPS] = { .type = NLA_U8 }, [CGW_MOD_UID] = { .type = NLA_U32 }, + [CGW_FDMOD_AND] = { .len = sizeof(struct cgw_fdframe_mod) }, + [CGW_FDMOD_OR] = { .len = sizeof(struct cgw_fdframe_mod) }, + [CGW_FDMOD_XOR] = { .len = sizeof(struct cgw_fdframe_mod) }, + [CGW_FDMOD_SET] = { .len = sizeof(struct cgw_fdframe_mod) }, }; /* check for common and gwtype specific attributes */ @@ -652,6 +733,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, u8 gwtype, void *gwtypeattr, u8 *limhops) { struct nlattr *tb[CGW_MAX + 1]; + struct rtcanmsg *r = nlmsg_data(nlh); int modidx = 0; int err = 0; @@ -671,7 +753,85 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, } /* check for AND/OR/XOR/SET modifications */ - if (1) { + if (r->flags & CGW_FLAGS_CAN_FD) { + struct cgw_fdframe_mod mb; + + if (tb[CGW_FDMOD_AND]) { + nla_memcpy(&mb, tb[CGW_FDMOD_AND], CGW_FDMODATTR_LEN); + + canfdframecpy(&mod->modframe.and, &mb.cf); + mod->modtype.and = mb.modtype; + + if (mb.modtype & CGW_MOD_ID) + mod->modfunc[modidx++] = mod_and_id; + + if (mb.modtype & CGW_MOD_LEN) + mod->modfunc[modidx++] = mod_and_len; + + if (mb.modtype & CGW_MOD_FLAGS) + mod->modfunc[modidx++] = mod_and_flags; + + if (mb.modtype & CGW_MOD_DATA) + mod->modfunc[modidx++] = mod_and_fddata; + } + + if (tb[CGW_FDMOD_OR]) { + nla_memcpy(&mb, tb[CGW_FDMOD_OR], CGW_FDMODATTR_LEN); + + canfdframecpy(&mod->modframe.or, &mb.cf); + mod->modtype.or = mb.modtype; + + if (mb.modtype & CGW_MOD_ID) + mod->modfunc[modidx++] = mod_or_id; + + if (mb.modtype & CGW_MOD_LEN) + mod->modfunc[modidx++] = mod_or_len; + + if (mb.modtype & CGW_MOD_FLAGS) + mod->modfunc[modidx++] = mod_or_flags; + + if (mb.modtype & CGW_MOD_DATA) + mod->modfunc[modidx++] = mod_or_fddata; + } + + if (tb[CGW_FDMOD_XOR]) { + nla_memcpy(&mb, tb[CGW_FDMOD_XOR], CGW_FDMODATTR_LEN); + + canfdframecpy(&mod->modframe.xor, &mb.cf); + mod->modtype.xor = mb.modtype; + + if (mb.modtype & CGW_MOD_ID) + mod->modfunc[modidx++] = mod_xor_id; + + if (mb.modtype & CGW_MOD_LEN) + mod->modfunc[modidx++] = mod_xor_len; + + if (mb.modtype & CGW_MOD_FLAGS) + mod->modfunc[modidx++] = mod_xor_flags; + + if (mb.modtype & CGW_MOD_DATA) + mod->modfunc[modidx++] = mod_xor_fddata; + } + + if (tb[CGW_FDMOD_SET]) { + nla_memcpy(&mb, tb[CGW_FDMOD_SET], CGW_FDMODATTR_LEN); + + canfdframecpy(&mod->modframe.set, &mb.cf); + mod->modtype.set = mb.modtype; + + if (mb.modtype & CGW_MOD_ID) + mod->modfunc[modidx++] = mod_set_id; + + if (mb.modtype & CGW_MOD_LEN) + mod->modfunc[modidx++] = mod_set_len; + + if (mb.modtype & CGW_MOD_FLAGS) + mod->modfunc[modidx++] = mod_set_flags; + + if (mb.modtype & CGW_MOD_DATA) + mod->modfunc[modidx++] = mod_set_fddata; + } + } else { struct cgw_frame_mod mb; if (tb[CGW_MOD_AND]) { @@ -745,7 +905,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, struct cgw_csum_crc8 *c = nla_data(tb[CGW_CS_CRC8]); err = cgw_chk_csum_parms(c->from_idx, c->to_idx, - c->result_idx); + c->result_idx, r); if (err) return err; @@ -768,7 +928,7 @@ static int cgw_parse_attr(struct nlmsghdr *nlh, struct cf_mod *mod, struct cgw_csum_xor *c = nla_data(tb[CGW_CS_XOR]); err = cgw_chk_csum_parms(c->from_idx, c->to_idx, - c->result_idx); + c->result_idx, r); if (err) return err; From d569de814967362bdd69f073b88f1f1321097dee Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:16:29 +0200 Subject: [PATCH 38/41] can: vcan: convert block comments to network style comments This patch converts all block comments to network subsystem style block comments. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/vcan.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index d200a5b0651c..8922dbd93ee2 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -1,5 +1,4 @@ -/* - * vcan.c - Virtual CAN interface +/* vcan.c - Virtual CAN interface * * Copyright (c) 2002-2017 Volkswagen Group Electronic Research * All rights reserved. @@ -57,9 +56,7 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Urs Thuermann "); MODULE_ALIAS_RTNL_LINK(DRV_NAME); - -/* - * CAN test feature: +/* CAN test feature: * Enable the echo on driver level for testing the CAN core echo modes. * See Documentation/networking/can.rst for details. */ @@ -101,10 +98,8 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) if (!echo) { /* no echo handling available inside this driver */ - if (loop) { - /* - * only count the packets here, because the + /* only count the packets here, because the * CAN core already did the echo for us */ stats->rx_packets++; From 4248f5e02f2e23f75f15db15253137923209ad79 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 24 Jul 2019 14:28:21 +0200 Subject: [PATCH 39/41] can: vcan: remove unnecessary blank lines This patch removes unnecessary blank lines, so that checkpatch doesn't complain anymore. Signed-off-by: Marc Kleine-Budde --- drivers/net/can/vcan.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 8922dbd93ee2..351e562ecc90 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -65,7 +65,6 @@ static bool echo; /* echo testing. Default: 0 (Off) */ module_param(echo, bool, 0444); MODULE_PARM_DESC(echo, "Echo sent frames (for testing). Default: 0 (Off)"); - static void vcan_rx(struct sk_buff *skb, struct net_device *dev) { struct canfd_frame *cfd = (struct canfd_frame *)skb->data; @@ -112,7 +111,6 @@ static netdev_tx_t vcan_tx(struct sk_buff *skb, struct net_device *dev) /* perform standard echo handling for CAN network interfaces */ if (loop) { - skb = can_create_echo_skb(skb); if (!skb) return NETDEV_TX_OK; From e83e416cdf4ff7f4815fe039a70688cf7e2d9d58 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Fri, 26 Jul 2019 09:35:43 +0200 Subject: [PATCH 40/41] can: vcan: introduce pr_fmt and make use of it This patch introduces pr_fmt and makes use of it, also it converts a printk() to pr_info(). Signed-off-by: Marc Kleine-Budde --- drivers/net/can/vcan.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/vcan.c b/drivers/net/can/vcan.c index 351e562ecc90..daf27133887b 100644 --- a/drivers/net/can/vcan.c +++ b/drivers/net/can/vcan.c @@ -38,6 +38,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -166,10 +168,10 @@ static struct rtnl_link_ops vcan_link_ops __read_mostly = { static __init int vcan_init_module(void) { - pr_info("vcan: Virtual CAN interface driver\n"); + pr_info("Virtual CAN interface driver\n"); if (echo) - printk(KERN_INFO "vcan: enabled echo on driver level.\n"); + pr_info("enabled echo on driver level.\n"); return rtnl_link_register(&vcan_link_ops); } From 3ca3c4aad2efa2931b663acc4ece7a38b31071d1 Mon Sep 17 00:00:00 2001 From: Andre Hartmann Date: Sat, 23 Mar 2019 16:04:19 +0100 Subject: [PATCH 41/41] can: netlink: fix documentation typos This patch fixes some documentation typos in struct can_bittiming_const. Signed-off-by: Andre Hartmann Signed-off-by: Marc Kleine-Budde --- include/uapi/linux/can/netlink.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/uapi/linux/can/netlink.h b/include/uapi/linux/can/netlink.h index 9f56fad4785b..1bc70d3a4d39 100644 --- a/include/uapi/linux/can/netlink.h +++ b/include/uapi/linux/can/netlink.h @@ -40,15 +40,15 @@ struct can_bittiming { }; /* - * CAN harware-dependent bit-timing constant + * CAN hardware-dependent bit-timing constant * * Used for calculating and checking bit-timing parameters */ struct can_bittiming_const { char name[16]; /* Name of the CAN controller hardware */ - __u32 tseg1_min; /* Time segement 1 = prop_seg + phase_seg1 */ + __u32 tseg1_min; /* Time segment 1 = prop_seg + phase_seg1 */ __u32 tseg1_max; - __u32 tseg2_min; /* Time segement 2 = phase_seg2 */ + __u32 tseg2_min; /* Time segment 2 = phase_seg2 */ __u32 tseg2_max; __u32 sjw_max; /* Synchronisation jump width */ __u32 brp_min; /* Bit-rate prescaler */