diff options
author | David S. Miller <davem@davemloft.net> | 2016-05-10 20:19:06 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-05-10 20:19:06 +0200 |
commit | 7a27de7810aee8d839e4a70d86ab450af60f72e5 (patch) | |
tree | 6c2598332d625a2db928caec9ef55ab6d83a47fc /drivers | |
parent | gtp: add initial driver for datapath of GPRS Tunneling Protocol (GTP-U) (diff) | |
parent | can: ifi: Add more detailed error reporting (diff) | |
download | linux-7a27de7810aee8d839e4a70d86ab450af60f72e5.tar.xz linux-7a27de7810aee8d839e4a70d86ab450af60f72e5.zip |
Merge tag 'linux-can-next-for-4.7-20160509' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next
Marc Kleine-Budde says:
====================
pull-request: can-next 2016-05-09
this is a pull request of 12 patches for net-next/master.
Alexander Gerasiov and Nikita Edward Baruzdin each contribute a patch
improving the sja1000 driver. Amitoj Kaur Chawla's patch converts the
mcp251x driver to alloc_workqueue(). A patch by Oliver Hartkopp fixes
the handling of CAN config options. Andreas Gröger improves the error
handling in the janz-ican3 driver. The patch by Maximilian Schneider
for the gs_usb improves probing of the USB driver. Finally there are 6
improvement patches by Marek Vasut for the ifi CAN driver.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/can/dev.c | 56 | ||||
-rw-r--r-- | drivers/net/can/ifi_canfd/ifi_canfd.c | 187 | ||||
-rw-r--r-- | drivers/net/can/janz-ican3.c | 104 | ||||
-rw-r--r-- | drivers/net/can/m_can/m_can.c | 2 | ||||
-rw-r--r-- | drivers/net/can/sja1000/plx_pci.c | 64 | ||||
-rw-r--r-- | drivers/net/can/sja1000/sja1000.c | 6 | ||||
-rw-r--r-- | drivers/net/can/spi/mcp251x.c | 3 | ||||
-rw-r--r-- | drivers/net/can/usb/gs_usb.c | 3 |
8 files changed, 347 insertions, 78 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 141c2a42d7ed..910c12e2638e 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -696,11 +696,17 @@ int can_change_mtu(struct net_device *dev, int new_mtu) /* allow change of MTU according to the CANFD ability of the device */ switch (new_mtu) { case CAN_MTU: + /* 'CANFD-only' controllers can not switch to CAN_MTU */ + if (priv->ctrlmode_static & CAN_CTRLMODE_FD) + return -EINVAL; + priv->ctrlmode &= ~CAN_CTRLMODE_FD; break; case CANFD_MTU: - if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD)) + /* check for potential CANFD ability */ + if (!(priv->ctrlmode_supported & CAN_CTRLMODE_FD) && + !(priv->ctrlmode_static & CAN_CTRLMODE_FD)) return -EINVAL; priv->ctrlmode |= CAN_CTRLMODE_FD; @@ -782,6 +788,35 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { = { .len = sizeof(struct can_bittiming_const) }, }; +static int can_validate(struct nlattr *tb[], struct nlattr *data[]) +{ + bool is_can_fd = false; + + /* Make sure that valid CAN FD configurations always consist of + * - nominal/arbitration bittiming + * - data bittiming + * - control mode with CAN_CTRLMODE_FD set + */ + + if (data[IFLA_CAN_CTRLMODE]) { + struct can_ctrlmode *cm = nla_data(data[IFLA_CAN_CTRLMODE]); + + is_can_fd = cm->flags & cm->mask & CAN_CTRLMODE_FD; + } + + if (is_can_fd) { + if (!data[IFLA_CAN_BITTIMING] || !data[IFLA_CAN_DATA_BITTIMING]) + return -EOPNOTSUPP; + } + + if (data[IFLA_CAN_DATA_BITTIMING]) { + if (!is_can_fd || !data[IFLA_CAN_BITTIMING]) + return -EOPNOTSUPP; + } + + return 0; +} + static int can_changelink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[]) { @@ -813,19 +848,31 @@ static int can_changelink(struct net_device *dev, if (data[IFLA_CAN_CTRLMODE]) { struct can_ctrlmode *cm; + u32 ctrlstatic; + u32 maskedflags; /* Do not allow changing controller mode while running */ if (dev->flags & IFF_UP) return -EBUSY; cm = nla_data(data[IFLA_CAN_CTRLMODE]); + ctrlstatic = priv->ctrlmode_static; + maskedflags = cm->flags & cm->mask; + + /* check whether provided bits are allowed to be passed */ + if (cm->mask & ~(priv->ctrlmode_supported | ctrlstatic)) + return -EOPNOTSUPP; + + /* do not check for static fd-non-iso if 'fd' is disabled */ + if (!(maskedflags & CAN_CTRLMODE_FD)) + ctrlstatic &= ~CAN_CTRLMODE_FD_NON_ISO; - /* check whether changed bits are allowed to be modified */ - if (cm->mask & ~priv->ctrlmode_supported) + /* make sure static options are provided by configuration */ + if ((maskedflags & ctrlstatic) != ctrlstatic) return -EOPNOTSUPP; /* clear bits to be modified and copy the flag values */ priv->ctrlmode &= ~cm->mask; - priv->ctrlmode |= (cm->flags & cm->mask); + priv->ctrlmode |= maskedflags; /* CAN_CTRLMODE_FD can only be set when driver supports FD */ if (priv->ctrlmode & CAN_CTRLMODE_FD) @@ -966,6 +1013,7 @@ static struct rtnl_link_ops can_link_ops __read_mostly = { .maxtype = IFLA_CAN_MAX, .policy = can_policy, .setup = can_setup, + .validate = can_validate, .newlink = can_newlink, .changelink = can_changelink, .get_size = can_get_size, diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c index a1bd54ffd31e..2d1d22eec750 100644 --- a/drivers/net/can/ifi_canfd/ifi_canfd.c +++ b/drivers/net/can/ifi_canfd/ifi_canfd.c @@ -34,6 +34,7 @@ #define IFI_CANFD_STCMD_LOOPBACK BIT(18) #define IFI_CANFD_STCMD_DISABLE_CANFD BIT(24) #define IFI_CANFD_STCMD_ENABLE_ISO BIT(25) +#define IFI_CANFD_STCMD_ENABLE_7_9_8_8_TIMING BIT(26) #define IFI_CANFD_STCMD_NORMAL_MODE ((u32)BIT(31)) #define IFI_CANFD_RXSTCMD 0x4 @@ -51,7 +52,8 @@ #define IFI_CANFD_TXSTCMD_OVERFLOW BIT(13) #define IFI_CANFD_INTERRUPT 0xc -#define IFI_CANFD_INTERRUPT_ERROR_WARNING ((u32)BIT(1)) +#define IFI_CANFD_INTERRUPT_ERROR_WARNING BIT(1) +#define IFI_CANFD_INTERRUPT_ERROR_COUNTER BIT(10) #define IFI_CANFD_INTERRUPT_TXFIFO_EMPTY BIT(16) #define IFI_CANFD_INTERRUPT_TXFIFO_REMOVE BIT(22) #define IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY BIT(24) @@ -71,12 +73,12 @@ #define IFI_CANFD_TIME_TIMEB_OFF 0 #define IFI_CANFD_TIME_TIMEA_OFF 8 #define IFI_CANFD_TIME_PRESCALE_OFF 16 -#define IFI_CANFD_TIME_SJW_OFF_ISO 25 -#define IFI_CANFD_TIME_SJW_OFF_BOSCH 28 -#define IFI_CANFD_TIME_SET_SJW_BOSCH BIT(6) -#define IFI_CANFD_TIME_SET_TIMEB_BOSCH BIT(7) -#define IFI_CANFD_TIME_SET_PRESC_BOSCH BIT(14) -#define IFI_CANFD_TIME_SET_TIMEA_BOSCH BIT(15) +#define IFI_CANFD_TIME_SJW_OFF_7_9_8_8 25 +#define IFI_CANFD_TIME_SJW_OFF_4_12_6_6 28 +#define IFI_CANFD_TIME_SET_SJW_4_12_6_6 BIT(6) +#define IFI_CANFD_TIME_SET_TIMEB_4_12_6_6 BIT(7) +#define IFI_CANFD_TIME_SET_PRESC_4_12_6_6 BIT(14) +#define IFI_CANFD_TIME_SET_TIMEA_4_12_6_6 BIT(15) #define IFI_CANFD_TDELAY 0x1c @@ -102,7 +104,26 @@ #define IFI_CANFD_RES1 0x40 -#define IFI_CANFD_RES2 0x44 +#define IFI_CANFD_ERROR_CTR 0x44 +#define IFI_CANFD_ERROR_CTR_UNLOCK_MAGIC 0x21302899 +#define IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST BIT(0) +#define IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST BIT(1) +#define IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST BIT(2) +#define IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST BIT(3) +#define IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST BIT(4) +#define IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST BIT(5) +#define IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST BIT(6) +#define IFI_CANFD_ERROR_CTR_OVERLOAD_ALL BIT(8) +#define IFI_CANFD_ERROR_CTR_ACK_ERROR_ALL BIT(9) +#define IFI_CANFD_ERROR_CTR_BIT0_ERROR_ALL BIT(10) +#define IFI_CANFD_ERROR_CTR_BIT1_ERROR_ALL BIT(11) +#define IFI_CANFD_ERROR_CTR_STUFF_ERROR_ALL BIT(12) +#define IFI_CANFD_ERROR_CTR_CRC_ERROR_ALL BIT(13) +#define IFI_CANFD_ERROR_CTR_FORM_ERROR_ALL BIT(14) +#define IFI_CANFD_ERROR_CTR_BITPOSITION_OFFSET 16 +#define IFI_CANFD_ERROR_CTR_BITPOSITION_MASK 0xff +#define IFI_CANFD_ERROR_CTR_ER_RESET BIT(30) +#define IFI_CANFD_ERROR_CTR_ER_ENABLE ((u32)BIT(31)) #define IFI_CANFD_PAR 0x48 @@ -196,6 +217,8 @@ static void ifi_canfd_irq_enable(struct net_device *ndev, bool enable) if (enable) { enirq = IFI_CANFD_IRQMASK_TXFIFO_EMPTY | IFI_CANFD_IRQMASK_RXFIFO_NEMPTY; + if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + enirq |= IFI_CANFD_INTERRUPT_ERROR_COUNTER; } writel(IFI_CANFD_IRQMASK_SET_ERR | @@ -334,6 +357,68 @@ static int ifi_canfd_handle_lost_msg(struct net_device *ndev) return 1; } +static int ifi_canfd_handle_lec_err(struct net_device *ndev, const u32 errctr) +{ + struct ifi_canfd_priv *priv = netdev_priv(ndev); + struct net_device_stats *stats = &ndev->stats; + struct can_frame *cf; + struct sk_buff *skb; + const u32 errmask = IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST | + IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST | + IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST | + IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST | + IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST | + IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST | + IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST; + + if (!(errctr & errmask)) /* No error happened. */ + return 0; + + priv->can.can_stats.bus_error++; + stats->rx_errors++; + + /* Propagate the error condition to the CAN stack. */ + skb = alloc_can_err_skb(ndev, &cf); + if (unlikely(!skb)) + return 0; + + /* Read the error counter register and check for new errors. */ + cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + + if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST) + cf->data[2] |= CAN_ERR_PROT_OVERLOAD; + + if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST) + cf->data[3] = CAN_ERR_PROT_LOC_ACK; + + if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST) + cf->data[2] |= CAN_ERR_PROT_BIT0; + + if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST) + cf->data[2] |= CAN_ERR_PROT_BIT1; + + if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST) + cf->data[2] |= CAN_ERR_PROT_STUFF; + + if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST) + cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ; + + if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST) + cf->data[2] |= CAN_ERR_PROT_FORM; + + /* Reset the error counter, ack the IRQ and re-enable the counter. */ + writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR); + writel(IFI_CANFD_INTERRUPT_ERROR_COUNTER, + priv->base + IFI_CANFD_INTERRUPT); + writel(IFI_CANFD_ERROR_CTR_ER_ENABLE, priv->base + IFI_CANFD_ERROR_CTR); + + stats->rx_packets++; + stats->rx_bytes += cf->can_dlc; + netif_receive_skb(skb); + + return 1; +} + static int ifi_canfd_get_berr_counter(const struct net_device *ndev, struct can_berr_counter *bec) { @@ -469,6 +554,7 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota) u32 stcmd = readl(priv->base + IFI_CANFD_STCMD); u32 rxstcmd = readl(priv->base + IFI_CANFD_STCMD); + u32 errctr = readl(priv->base + IFI_CANFD_ERROR_CTR); /* Handle bus state changes */ if ((stcmd & stcmd_state_mask) || @@ -479,6 +565,10 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota) if (rxstcmd & IFI_CANFD_RXSTCMD_OVERFLOW) work_done += ifi_canfd_handle_lost_msg(ndev); + /* Handle lec errors on the bus */ + if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) + work_done += ifi_canfd_handle_lec_err(ndev, errctr); + /* Handle normal messages on RX */ if (!(rxstcmd & IFI_CANFD_RXSTCMD_EMPTY)) work_done += ifi_canfd_do_rx_poll(ndev, quota - work_done); @@ -497,11 +587,13 @@ static irqreturn_t ifi_canfd_isr(int irq, void *dev_id) struct ifi_canfd_priv *priv = netdev_priv(ndev); struct net_device_stats *stats = &ndev->stats; const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY | - IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER; + IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER | + IFI_CANFD_INTERRUPT_ERROR_WARNING | + IFI_CANFD_INTERRUPT_ERROR_COUNTER; const u32 tx_irq_mask = IFI_CANFD_INTERRUPT_TXFIFO_EMPTY | IFI_CANFD_INTERRUPT_TXFIFO_REMOVE; - const u32 clr_irq_mask = ~(IFI_CANFD_INTERRUPT_SET_IRQ | - IFI_CANFD_INTERRUPT_ERROR_WARNING); + const u32 clr_irq_mask = ~((u32)(IFI_CANFD_INTERRUPT_SET_IRQ | + IFI_CANFD_INTERRUPT_ERROR_WARNING)); u32 isr; isr = readl(priv->base + IFI_CANFD_INTERRUPT); @@ -513,44 +605,34 @@ static irqreturn_t ifi_canfd_isr(int irq, void *dev_id) /* Clear all pending interrupts but ErrWarn */ writel(clr_irq_mask, priv->base + IFI_CANFD_INTERRUPT); - /* RX IRQ, start NAPI */ + /* RX IRQ or bus warning, start NAPI */ if (isr & rx_irq_mask) { ifi_canfd_irq_enable(ndev, 0); napi_schedule(&priv->napi); } /* TX IRQ */ - if (isr & tx_irq_mask) { + if (isr & IFI_CANFD_INTERRUPT_TXFIFO_REMOVE) { stats->tx_bytes += can_get_echo_skb(ndev, 0); stats->tx_packets++; can_led_event(ndev, CAN_LED_EVENT_TX); - netif_wake_queue(ndev); } + if (isr & tx_irq_mask) + netif_wake_queue(ndev); + return IRQ_HANDLED; } static const struct can_bittiming_const ifi_canfd_bittiming_const = { .name = KBUILD_MODNAME, .tseg1_min = 1, /* Time segment 1 = prop_seg + phase_seg1 */ - .tseg1_max = 64, - .tseg2_min = 2, /* Time segment 2 = phase_seg2 */ - .tseg2_max = 64, - .sjw_max = 16, - .brp_min = 2, - .brp_max = 256, - .brp_inc = 1, -}; - -static const struct can_bittiming_const ifi_canfd_data_bittiming_const = { - .name = KBUILD_MODNAME, - .tseg1_min = 1, /* Time segment 1 = prop_seg + phase_seg1 */ - .tseg1_max = 64, + .tseg1_max = 256, .tseg2_min = 2, /* Time segment 2 = phase_seg2 */ - .tseg2_max = 64, - .sjw_max = 16, + .tseg2_max = 256, + .sjw_max = 128, .brp_min = 2, - .brp_max = 256, + .brp_max = 512, .brp_inc = 1, }; @@ -560,19 +642,6 @@ static void ifi_canfd_set_bittiming(struct net_device *ndev) const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *dbt = &priv->can.data_bittiming; u16 brp, sjw, tseg1, tseg2; - u32 noniso_arg = 0; - u32 time_off; - - if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) && - !(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)) { - time_off = IFI_CANFD_TIME_SJW_OFF_ISO; - } else { - noniso_arg = IFI_CANFD_TIME_SET_TIMEB_BOSCH | - IFI_CANFD_TIME_SET_TIMEA_BOSCH | - IFI_CANFD_TIME_SET_PRESC_BOSCH | - IFI_CANFD_TIME_SET_SJW_BOSCH; - time_off = IFI_CANFD_TIME_SJW_OFF_BOSCH; - } /* Configure bit timing */ brp = bt->brp - 2; @@ -582,8 +651,7 @@ static void ifi_canfd_set_bittiming(struct net_device *ndev) writel((tseg2 << IFI_CANFD_TIME_TIMEB_OFF) | (tseg1 << IFI_CANFD_TIME_TIMEA_OFF) | (brp << IFI_CANFD_TIME_PRESCALE_OFF) | - (sjw << time_off) | - noniso_arg, + (sjw << IFI_CANFD_TIME_SJW_OFF_7_9_8_8), priv->base + IFI_CANFD_TIME); /* Configure data bit timing */ @@ -594,8 +662,7 @@ static void ifi_canfd_set_bittiming(struct net_device *ndev) writel((tseg2 << IFI_CANFD_TIME_TIMEB_OFF) | (tseg1 << IFI_CANFD_TIME_TIMEA_OFF) | (brp << IFI_CANFD_TIME_PRESCALE_OFF) | - (sjw << time_off) | - noniso_arg, + (sjw << IFI_CANFD_TIME_SJW_OFF_7_9_8_8), priv->base + IFI_CANFD_FTIME); } @@ -640,7 +707,8 @@ static void ifi_canfd_start(struct net_device *ndev) /* Reset the IP */ writel(IFI_CANFD_STCMD_HARDRESET, priv->base + IFI_CANFD_STCMD); - writel(0, priv->base + IFI_CANFD_STCMD); + writel(IFI_CANFD_STCMD_ENABLE_7_9_8_8_TIMING, + priv->base + IFI_CANFD_STCMD); ifi_canfd_set_bittiming(ndev); ifi_canfd_set_filters(ndev); @@ -659,7 +727,8 @@ static void ifi_canfd_start(struct net_device *ndev) writel((u32)(~IFI_CANFD_INTERRUPT_SET_IRQ), priv->base + IFI_CANFD_INTERRUPT); - stcmd = IFI_CANFD_STCMD_ENABLE | IFI_CANFD_STCMD_NORMAL_MODE; + stcmd = IFI_CANFD_STCMD_ENABLE | IFI_CANFD_STCMD_NORMAL_MODE | + IFI_CANFD_STCMD_ENABLE_7_9_8_8_TIMING; if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) stcmd |= IFI_CANFD_STCMD_BUSMONITOR; @@ -667,16 +736,23 @@ static void ifi_canfd_start(struct net_device *ndev) if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) stcmd |= IFI_CANFD_STCMD_LOOPBACK; - if (priv->can.ctrlmode & CAN_CTRLMODE_FD) + if ((priv->can.ctrlmode & CAN_CTRLMODE_FD) && + !(priv->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO)) stcmd |= IFI_CANFD_STCMD_ENABLE_ISO; - if (!(priv->can.ctrlmode & (CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO))) + if (!(priv->can.ctrlmode & CAN_CTRLMODE_FD)) stcmd |= IFI_CANFD_STCMD_DISABLE_CANFD; priv->can.state = CAN_STATE_ERROR_ACTIVE; ifi_canfd_irq_enable(ndev, 1); + /* Unlock, reset and enable the error counter. */ + writel(IFI_CANFD_ERROR_CTR_UNLOCK_MAGIC, + priv->base + IFI_CANFD_ERROR_CTR); + writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR); + writel(IFI_CANFD_ERROR_CTR_ER_ENABLE, priv->base + IFI_CANFD_ERROR_CTR); + /* Enable controller */ writel(stcmd, priv->base + IFI_CANFD_STCMD); } @@ -685,6 +761,10 @@ static void ifi_canfd_stop(struct net_device *ndev) { struct ifi_canfd_priv *priv = netdev_priv(ndev); + /* Reset and disable the error counter. */ + writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR); + writel(0, priv->base + IFI_CANFD_ERROR_CTR); + /* Reset the IP */ writel(IFI_CANFD_STCMD_HARDRESET, priv->base + IFI_CANFD_STCMD); @@ -877,7 +957,7 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev) priv->can.clock.freq = readl(addr + IFI_CANFD_CANCLOCK); priv->can.bittiming_const = &ifi_canfd_bittiming_const; - priv->can.data_bittiming_const = &ifi_canfd_data_bittiming_const; + priv->can.data_bittiming_const = &ifi_canfd_bittiming_const; priv->can.do_set_mode = ifi_canfd_set_mode; priv->can.do_get_berr_counter = ifi_canfd_get_berr_counter; @@ -888,7 +968,8 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev) priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_FD | - CAN_CTRLMODE_FD_NON_ISO; + CAN_CTRLMODE_FD_NON_ISO | + CAN_CTRLMODE_BERR_REPORTING; platform_set_drvdata(pdev, ndev); SET_NETDEV_DEV(ndev, dev); diff --git a/drivers/net/can/janz-ican3.c b/drivers/net/can/janz-ican3.c index 5d04f5464faf..f13bb8d9bb84 100644 --- a/drivers/net/can/janz-ican3.c +++ b/drivers/net/can/janz-ican3.c @@ -84,6 +84,7 @@ #define MSG_COFFREQ 0x42 #define MSG_CONREQ 0x43 #define MSG_CCONFREQ 0x47 +#define MSG_NMTS 0xb0 #define MSG_LMTS 0xb4 /* @@ -130,6 +131,22 @@ #define ICAN3_CAN_DLC_MASK 0x0f +/* Janz ICAN3 NMTS subtypes */ +#define NMTS_CREATE_NODE_REQ 0x0 +#define NMTS_SLAVE_STATE_IND 0x8 +#define NMTS_SLAVE_EVENT_IND 0x9 + +/* Janz ICAN3 LMTS subtypes */ +#define LMTS_BUSON_REQ 0x0 +#define LMTS_BUSOFF_REQ 0x1 +#define LMTS_CAN_CONF_REQ 0x2 + +/* Janz ICAN3 NMTS Event indications */ +#define NE_LOCAL_OCCURRED 0x3 +#define NE_LOCAL_RESOLVED 0x2 +#define NE_REMOTE_OCCURRED 0xc +#define NE_REMOTE_RESOLVED 0x8 + /* * SJA1000 Status and Error Register Definitions * @@ -800,21 +817,41 @@ static int ican3_set_bus_state(struct ican3_dev *mod, bool on) return ican3_send_msg(mod, &msg); } else if (mod->fwtype == ICAN3_FWTYPE_CAL_CANOPEN) { + /* bittiming + can-on/off request */ memset(&msg, 0, sizeof(msg)); msg.spec = MSG_LMTS; if (on) { msg.len = cpu_to_le16(4); - msg.data[0] = 0; + msg.data[0] = LMTS_BUSON_REQ; msg.data[1] = 0; msg.data[2] = btr0; msg.data[3] = btr1; } else { msg.len = cpu_to_le16(2); - msg.data[0] = 1; + msg.data[0] = LMTS_BUSOFF_REQ; msg.data[1] = 0; } + res = ican3_send_msg(mod, &msg); + if (res) + return res; - return ican3_send_msg(mod, &msg); + if (on) { + /* create NMT Slave Node for error processing + * class 2 (with error capability, see CiA/DS203-1) + * id 1 + * name locnod1 (must be exactly 7 bytes) + */ + memset(&msg, 0, sizeof(msg)); + msg.spec = MSG_NMTS; + msg.len = cpu_to_le16(11); + msg.data[0] = NMTS_CREATE_NODE_REQ; + msg.data[1] = 0; + msg.data[2] = 2; /* node class */ + msg.data[3] = 1; /* node id */ + strcpy(msg.data + 4, "locnod1"); /* node name */ + return ican3_send_msg(mod, &msg); + } + return 0; } return -ENOTSUPP; } @@ -849,12 +886,23 @@ static int ican3_set_buserror(struct ican3_dev *mod, u8 quota) { struct ican3_msg msg; - memset(&msg, 0, sizeof(msg)); - msg.spec = MSG_CCONFREQ; - msg.len = cpu_to_le16(2); - msg.data[0] = 0x00; - msg.data[1] = quota; - + if (mod->fwtype == ICAN3_FWTYPE_ICANOS) { + memset(&msg, 0, sizeof(msg)); + msg.spec = MSG_CCONFREQ; + msg.len = cpu_to_le16(2); + msg.data[0] = 0x00; + msg.data[1] = quota; + } else if (mod->fwtype == ICAN3_FWTYPE_CAL_CANOPEN) { + memset(&msg, 0, sizeof(msg)); + msg.spec = MSG_LMTS; + msg.len = cpu_to_le16(4); + msg.data[0] = LMTS_CAN_CONF_REQ; + msg.data[1] = 0x00; + msg.data[2] = 0x00; + msg.data[3] = quota; + } else { + return -ENOTSUPP; + } return ican3_send_msg(mod, &msg); } @@ -1150,6 +1198,41 @@ static void ican3_handle_inquiry(struct ican3_dev *mod, struct ican3_msg *msg) } } +/* Handle NMTS Slave Event Indication Messages from the firmware */ +static void ican3_handle_nmtsind(struct ican3_dev *mod, struct ican3_msg *msg) +{ + u16 subspec; + + subspec = msg->data[0] + msg->data[1] * 0x100; + if (subspec == NMTS_SLAVE_EVENT_IND) { + switch (msg->data[2]) { + case NE_LOCAL_OCCURRED: + case NE_LOCAL_RESOLVED: + /* now follows the same message as Raw ICANOS CEVTIND + * shift the data at the same place and call this method + */ + le16_add_cpu(&msg->len, -3); + memmove(msg->data, msg->data + 3, le16_to_cpu(msg->len)); + ican3_handle_cevtind(mod, msg); + break; + case NE_REMOTE_OCCURRED: + case NE_REMOTE_RESOLVED: + /* should not occurre, ignore */ + break; + default: + netdev_warn(mod->ndev, "unknown NMTS event indication %x\n", + msg->data[2]); + break; + } + } else if (subspec == NMTS_SLAVE_STATE_IND) { + /* ignore state indications */ + } else { + netdev_warn(mod->ndev, "unhandled NMTS indication %x\n", + subspec); + return; + } +} + static void ican3_handle_unknown_message(struct ican3_dev *mod, struct ican3_msg *msg) { @@ -1179,6 +1262,9 @@ static void ican3_handle_message(struct ican3_dev *mod, struct ican3_msg *msg) case MSG_INQUIRY: ican3_handle_inquiry(mod, msg); break; + case MSG_NMTS: + ican3_handle_nmtsind(mod, msg); + break; default: ican3_handle_unknown_message(mod, msg); break; diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c index 39cf911f7a1e..195f15edb32e 100644 --- a/drivers/net/can/m_can/m_can.c +++ b/drivers/net/can/m_can/m_can.c @@ -955,7 +955,7 @@ static struct net_device *alloc_m_can_dev(void) priv->can.do_get_berr_counter = m_can_get_berr_counter; /* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.1 */ - priv->can.ctrlmode = CAN_CTRLMODE_FD_NON_ISO; + can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO); /* CAN_CTRLMODE_FD_NON_ISO can not be changed with M_CAN IP v3.0.1 */ priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | diff --git a/drivers/net/can/sja1000/plx_pci.c b/drivers/net/can/sja1000/plx_pci.c index 8836a7485c81..3eb7430dffbf 100644 --- a/drivers/net/can/sja1000/plx_pci.c +++ b/drivers/net/can/sja1000/plx_pci.c @@ -39,6 +39,7 @@ MODULE_DESCRIPTION("Socket-CAN driver for PLX90xx PCI-bridge cards with " MODULE_SUPPORTED_DEVICE("Adlink PCI-7841/cPCI-7841, " "Adlink PCI-7841/cPCI-7841 SE, " "Marathon CAN-bus-PCI, " + "Marathon CAN-bus-PCIe, " "TEWS TECHNOLOGIES TPMC810, " "esd CAN-PCI/CPCI/PCI104/200, " "esd CAN-PCI/PMC/266, " @@ -133,6 +134,7 @@ struct plx_pci_card { #define IXXAT_PCI_SUB_SYS_ID 0x2540 #define MARATHON_PCI_DEVICE_ID 0x2715 +#define MARATHON_PCIE_DEVICE_ID 0x3432 #define TEWS_PCI_VENDOR_ID 0x1498 #define TEWS_PCI_DEVICE_ID_TMPC810 0x032A @@ -141,8 +143,9 @@ struct plx_pci_card { #define CTI_PCI_DEVICE_ID_CRG001 0x0900 static void plx_pci_reset_common(struct pci_dev *pdev); -static void plx_pci_reset_marathon(struct pci_dev *pdev); static void plx9056_pci_reset_common(struct pci_dev *pdev); +static void plx_pci_reset_marathon_pci(struct pci_dev *pdev); +static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev); struct plx_pci_channel_map { u32 bar; @@ -215,14 +218,22 @@ static struct plx_pci_card_info plx_pci_card_info_ixxat = { /* based on PLX9050 */ }; -static struct plx_pci_card_info plx_pci_card_info_marathon = { +static struct plx_pci_card_info plx_pci_card_info_marathon_pci = { "Marathon CAN-bus-PCI", 2, PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {4, 0x00, 0x00} }, - &plx_pci_reset_marathon + &plx_pci_reset_marathon_pci /* based on PLX9052 */ }; +static struct plx_pci_card_info plx_pci_card_info_marathon_pcie = { + "Marathon CAN-bus-PCIe", 2, + PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, + {0, 0x00, 0x00}, { {2, 0x00, 0x00}, {3, 0x80, 0x00} }, + &plx_pci_reset_marathon_pcie + /* based on PEX8311 */ +}; + static struct plx_pci_card_info plx_pci_card_info_tews = { "TEWS TECHNOLOGIES TPMC810", 2, PLX_PCI_CAN_CLOCK, PLX_PCI_OCR, PLX_PCI_CDR, @@ -316,7 +327,14 @@ static const struct pci_device_id plx_pci_tbl[] = { PCI_VENDOR_ID_PLX, MARATHON_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, - (kernel_ulong_t)&plx_pci_card_info_marathon + (kernel_ulong_t)&plx_pci_card_info_marathon_pci + }, + { + /* Marathon CAN-bus-PCIe card */ + PCI_VENDOR_ID_PLX, MARATHON_PCIE_DEVICE_ID, + PCI_ANY_ID, PCI_ANY_ID, + 0, 0, + (kernel_ulong_t)&plx_pci_card_info_marathon_pcie }, { /* TEWS TECHNOLOGIES TPMC810 card */ @@ -437,8 +455,8 @@ static void plx9056_pci_reset_common(struct pci_dev *pdev) iowrite32(cntrl, card->conf_addr + PLX9056_CNTRL); }; -/* Special reset function for Marathon card */ -static void plx_pci_reset_marathon(struct pci_dev *pdev) +/* Special reset function for Marathon CAN-bus-PCI card */ +static void plx_pci_reset_marathon_pci(struct pci_dev *pdev) { void __iomem *reset_addr; int i; @@ -460,6 +478,34 @@ static void plx_pci_reset_marathon(struct pci_dev *pdev) } } +/* Special reset function for Marathon CAN-bus-PCIe card */ +static void plx_pci_reset_marathon_pcie(struct pci_dev *pdev) +{ + void __iomem *addr; + void __iomem *reset_addr; + int i; + + plx9056_pci_reset_common(pdev); + + for (i = 0; i < 2; i++) { + struct plx_pci_channel_map *chan_map = + &plx_pci_card_info_marathon_pcie.chan_map_tbl[i]; + addr = pci_iomap(pdev, chan_map->bar, chan_map->size); + if (!addr) { + dev_err(&pdev->dev, "Failed to remap reset " + "space %d (BAR%d)\n", i, chan_map->bar); + } else { + /* reset the SJA1000 chip */ + #define MARATHON_PCIE_RESET_OFFSET 32 + reset_addr = addr + chan_map->offset + + MARATHON_PCIE_RESET_OFFSET; + iowrite8(0x1, reset_addr); + udelay(100); + pci_iounmap(pdev, addr); + } + } +} + static void plx_pci_del_card(struct pci_dev *pdev) { struct plx_pci_card *card = pci_get_drvdata(pdev); @@ -486,7 +532,8 @@ static void plx_pci_del_card(struct pci_dev *pdev) * Disable interrupts from PCI-card and disable local * interrupts */ - if (pdev->device != PCI_DEVICE_ID_PLX_9056) + if (pdev->device != PCI_DEVICE_ID_PLX_9056 && + pdev->device != MARATHON_PCIE_DEVICE_ID) iowrite32(0x0, card->conf_addr + PLX_INTCSR); else iowrite32(0x0, card->conf_addr + PLX9056_INTCSR); @@ -619,7 +666,8 @@ static int plx_pci_add_card(struct pci_dev *pdev, * Enable interrupts from PCI-card (PLX90xx) and enable Local_1, * Local_2 interrupts from the SJA1000 chips */ - if (pdev->device != PCI_DEVICE_ID_PLX_9056) { + if (pdev->device != PCI_DEVICE_ID_PLX_9056 && + pdev->device != MARATHON_PCIE_DEVICE_ID) { val = ioread32(card->conf_addr + PLX_INTCSR); if (pdev->subsystem_vendor == PCI_VENDOR_ID_ESDGMBH) val |= PLX_LINT1_EN | PLX_PCI_INT_EN; diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c index 8dda3b703d39..9f107798f904 100644 --- a/drivers/net/can/sja1000/sja1000.c +++ b/drivers/net/can/sja1000/sja1000.c @@ -438,6 +438,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; + /* set error type */ switch (ecc & ECC_MASK) { case ECC_BIT: cf->data[2] |= CAN_ERR_PROT_BIT; @@ -449,9 +450,12 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status) cf->data[2] |= CAN_ERR_PROT_STUFF; break; default: - cf->data[3] = ecc & ECC_SEG; break; } + + /* set error location */ + cf->data[3] = ecc & ECC_SEG; + /* Error occurred during transmission? */ if ((ecc & ECC_DIR) == 0) cf->data[2] |= CAN_ERR_PROT_TX; diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index 74a7dfecee27..cf36d26ef002 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -961,7 +961,8 @@ static int mcp251x_open(struct net_device *net) goto open_unlock; } - priv->wq = create_freezable_workqueue("mcp251x_wq"); + priv->wq = alloc_workqueue("mcp251x_wq", WQ_FREEZABLE | WQ_MEM_RECLAIM, + 0); INIT_WORK(&priv->tx_work, mcp251x_tx_work_handler); INIT_WORK(&priv->restart_work, mcp251x_restart_work_handler); diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index cbc99d5649af..1556d4286235 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -950,7 +950,8 @@ static void gs_usb_disconnect(struct usb_interface *intf) } static const struct usb_device_id gs_usb_table[] = { - {USB_DEVICE(USB_GSUSB_1_VENDOR_ID, USB_GSUSB_1_PRODUCT_ID)}, + { USB_DEVICE_INTERFACE_NUMBER(USB_GSUSB_1_VENDOR_ID, + USB_GSUSB_1_PRODUCT_ID, 0) }, {} /* Terminating entry */ }; |