aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/can
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/can')
-rw-r--r--drivers/net/can/Kconfig2
-rw-r--r--drivers/net/can/at91_can.c4
-rw-r--r--drivers/net/can/bfin_can.c258
-rw-r--r--drivers/net/can/cc770/cc770_platform.c2
-rw-r--r--drivers/net/can/flexcan.c18
-rw-r--r--drivers/net/can/grcan.c2
-rw-r--r--drivers/net/can/led.c22
-rw-r--r--drivers/net/can/m_can/m_can.c4
-rw-r--r--drivers/net/can/mscan/mpc5xxx_can.c2
-rw-r--r--drivers/net/can/sja1000/sja1000_platform.c2
-rw-r--r--drivers/net/can/usb/ems_usb.c11
-rw-r--r--drivers/net/can/usb/esd_usb2.c4
-rw-r--r--drivers/net/can/usb/gs_usb.c2
-rw-r--r--drivers/net/can/usb/kvaser_usb.c136
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_ucan.h15
-rw-r--r--drivers/net/can/usb/peak_usb/pcan_usb_fd.c75
-rw-r--r--drivers/net/can/xilinx_can.c2
17 files changed, 369 insertions, 192 deletions
diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 98d73aab52fe..58808f651452 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -131,7 +131,7 @@ config CAN_RCAR
config CAN_XILINXCAN
tristate "Xilinx CAN"
- depends on ARCH_ZYNQ || MICROBLAZE || COMPILE_TEST
+ depends on ARCH_ZYNQ || ARM64 || MICROBLAZE || COMPILE_TEST
depends on COMMON_CLK && HAS_IOMEM
---help---
Xilinx CAN driver. This driver supports both soft AXI CAN IP and
diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c
index eeb4b8b6b335..f4e40aa4d2a2 100644
--- a/drivers/net/can/at91_can.c
+++ b/drivers/net/can/at91_can.c
@@ -291,13 +291,13 @@ static inline unsigned int get_tx_echo_mb(const struct at91_priv *priv)
static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
{
- return __raw_readl(priv->reg_base + reg);
+ return readl_relaxed(priv->reg_base + reg);
}
static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg,
u32 value)
{
- __raw_writel(value, priv->reg_base + reg);
+ writel_relaxed(value, priv->reg_base + reg);
}
static inline void set_mb_mode_prio(const struct at91_priv *priv,
diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c
index e7a6363e736b..27ad312e7abf 100644
--- a/drivers/net/can/bfin_can.c
+++ b/drivers/net/can/bfin_can.c
@@ -20,13 +20,121 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#include <asm/bfin_can.h>
#include <asm/portmux.h>
#define DRV_NAME "bfin_can"
#define BFIN_CAN_TIMEOUT 100
#define TX_ECHO_SKB_MAX 1
+/* transmit and receive channels */
+#define TRANSMIT_CHL 24
+#define RECEIVE_STD_CHL 0
+#define RECEIVE_EXT_CHL 4
+#define RECEIVE_RTR_CHL 8
+#define RECEIVE_EXT_RTR_CHL 12
+#define MAX_CHL_NUMBER 32
+
+/* All Blackfin system MMRs are padded to 32bits even if the register
+ * itself is only 16bits. So use a helper macro to streamline this
+ */
+#define __BFP(m) u16 m; u16 __pad_##m
+
+/* bfin can registers layout */
+struct bfin_can_mask_regs {
+ __BFP(aml);
+ __BFP(amh);
+};
+
+struct bfin_can_channel_regs {
+ /* data[0,2,4,6] -> data{0,1,2,3} while data[1,3,5,7] is padding */
+ u16 data[8];
+ __BFP(dlc);
+ __BFP(tsv);
+ __BFP(id0);
+ __BFP(id1);
+};
+
+struct bfin_can_regs {
+ /* global control and status registers */
+ __BFP(mc1); /* offset 0x00 */
+ __BFP(md1); /* offset 0x04 */
+ __BFP(trs1); /* offset 0x08 */
+ __BFP(trr1); /* offset 0x0c */
+ __BFP(ta1); /* offset 0x10 */
+ __BFP(aa1); /* offset 0x14 */
+ __BFP(rmp1); /* offset 0x18 */
+ __BFP(rml1); /* offset 0x1c */
+ __BFP(mbtif1); /* offset 0x20 */
+ __BFP(mbrif1); /* offset 0x24 */
+ __BFP(mbim1); /* offset 0x28 */
+ __BFP(rfh1); /* offset 0x2c */
+ __BFP(opss1); /* offset 0x30 */
+ u32 __pad1[3];
+ __BFP(mc2); /* offset 0x40 */
+ __BFP(md2); /* offset 0x44 */
+ __BFP(trs2); /* offset 0x48 */
+ __BFP(trr2); /* offset 0x4c */
+ __BFP(ta2); /* offset 0x50 */
+ __BFP(aa2); /* offset 0x54 */
+ __BFP(rmp2); /* offset 0x58 */
+ __BFP(rml2); /* offset 0x5c */
+ __BFP(mbtif2); /* offset 0x60 */
+ __BFP(mbrif2); /* offset 0x64 */
+ __BFP(mbim2); /* offset 0x68 */
+ __BFP(rfh2); /* offset 0x6c */
+ __BFP(opss2); /* offset 0x70 */
+ u32 __pad2[3];
+ __BFP(clock); /* offset 0x80 */
+ __BFP(timing); /* offset 0x84 */
+ __BFP(debug); /* offset 0x88 */
+ __BFP(status); /* offset 0x8c */
+ __BFP(cec); /* offset 0x90 */
+ __BFP(gis); /* offset 0x94 */
+ __BFP(gim); /* offset 0x98 */
+ __BFP(gif); /* offset 0x9c */
+ __BFP(control); /* offset 0xa0 */
+ __BFP(intr); /* offset 0xa4 */
+ __BFP(version); /* offset 0xa8 */
+ __BFP(mbtd); /* offset 0xac */
+ __BFP(ewr); /* offset 0xb0 */
+ __BFP(esr); /* offset 0xb4 */
+ u32 __pad3[2];
+ __BFP(ucreg); /* offset 0xc0 */
+ __BFP(uccnt); /* offset 0xc4 */
+ __BFP(ucrc); /* offset 0xc8 */
+ __BFP(uccnf); /* offset 0xcc */
+ u32 __pad4[1];
+ __BFP(version2); /* offset 0xd4 */
+ u32 __pad5[10];
+
+ /* channel(mailbox) mask and message registers */
+ struct bfin_can_mask_regs msk[MAX_CHL_NUMBER]; /* offset 0x100 */
+ struct bfin_can_channel_regs chl[MAX_CHL_NUMBER]; /* offset 0x200 */
+};
+
+#undef __BFP
+
+#define SRS 0x0001 /* Software Reset */
+#define SER 0x0008 /* Stuff Error */
+#define BOIM 0x0008 /* Enable Bus Off Interrupt */
+#define CCR 0x0080 /* CAN Configuration Mode Request */
+#define CCA 0x0080 /* Configuration Mode Acknowledge */
+#define SAM 0x0080 /* Sampling */
+#define AME 0x8000 /* Acceptance Mask Enable */
+#define RMLIM 0x0080 /* Enable RX Message Lost Interrupt */
+#define RMLIS 0x0080 /* RX Message Lost IRQ Status */
+#define RTR 0x4000 /* Remote Frame Transmission Request */
+#define BOIS 0x0008 /* Bus Off IRQ Status */
+#define IDE 0x2000 /* Identifier Extension */
+#define EPIS 0x0004 /* Error-Passive Mode IRQ Status */
+#define EPIM 0x0004 /* Enable Error-Passive Mode Interrupt */
+#define EWTIS 0x0001 /* TX Error Count IRQ Status */
+#define EWRIS 0x0002 /* RX Error Count IRQ Status */
+#define BEF 0x0040 /* Bit Error Flag */
+#define FER 0x0080 /* Form Error Flag */
+#define SMR 0x0020 /* Sleep Mode Request */
+#define SMACK 0x0008 /* Sleep Mode Acknowledge */
+
/*
* bfin can private data
*/
@@ -78,8 +186,8 @@ static int bfin_can_set_bittiming(struct net_device *dev)
if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
timing |= SAM;
- bfin_write(&reg->clock, clk);
- bfin_write(&reg->timing, timing);
+ writew(clk, &reg->clock);
+ writew(timing, &reg->timing);
netdev_info(dev, "setting CLOCK=0x%04x TIMING=0x%04x\n", clk, timing);
@@ -94,16 +202,14 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
int i;
/* disable interrupts */
- bfin_write(&reg->mbim1, 0);
- bfin_write(&reg->mbim2, 0);
- bfin_write(&reg->gim, 0);
+ writew(0, &reg->mbim1);
+ writew(0, &reg->mbim2);
+ writew(0, &reg->gim);
/* reset can and enter configuration mode */
- bfin_write(&reg->control, SRS | CCR);
- SSYNC();
- bfin_write(&reg->control, CCR);
- SSYNC();
- while (!(bfin_read(&reg->control) & CCA)) {
+ writew(SRS | CCR, &reg->control);
+ writew(CCR, &reg->control);
+ while (!(readw(&reg->control) & CCA)) {
udelay(10);
if (--timeout == 0) {
netdev_err(dev, "fail to enter configuration mode\n");
@@ -116,34 +222,33 @@ static void bfin_can_set_reset_mode(struct net_device *dev)
* by writing to CAN Mailbox Configuration Registers 1 and 2
* For all bits: 0 - Mailbox disabled, 1 - Mailbox enabled
*/
- bfin_write(&reg->mc1, 0);
- bfin_write(&reg->mc2, 0);
+ writew(0, &reg->mc1);
+ writew(0, &reg->mc2);
/* Set Mailbox Direction */
- bfin_write(&reg->md1, 0xFFFF); /* mailbox 1-16 are RX */
- bfin_write(&reg->md2, 0); /* mailbox 17-32 are TX */
+ writew(0xFFFF, &reg->md1); /* mailbox 1-16 are RX */
+ writew(0, &reg->md2); /* mailbox 17-32 are TX */
/* RECEIVE_STD_CHL */
for (i = 0; i < 2; i++) {
- bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id0, 0);
- bfin_write(&reg->chl[RECEIVE_STD_CHL + i].id1, AME);
- bfin_write(&reg->chl[RECEIVE_STD_CHL + i].dlc, 0);
- bfin_write(&reg->msk[RECEIVE_STD_CHL + i].amh, 0x1FFF);
- bfin_write(&reg->msk[RECEIVE_STD_CHL + i].aml, 0xFFFF);
+ writew(0, &reg->chl[RECEIVE_STD_CHL + i].id0);
+ writew(AME, &reg->chl[RECEIVE_STD_CHL + i].id1);
+ writew(0, &reg->chl[RECEIVE_STD_CHL + i].dlc);
+ writew(0x1FFF, &reg->msk[RECEIVE_STD_CHL + i].amh);
+ writew(0xFFFF, &reg->msk[RECEIVE_STD_CHL + i].aml);
}
/* RECEIVE_EXT_CHL */
for (i = 0; i < 2; i++) {
- bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id0, 0);
- bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].id1, AME | IDE);
- bfin_write(&reg->chl[RECEIVE_EXT_CHL + i].dlc, 0);
- bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].amh, 0x1FFF);
- bfin_write(&reg->msk[RECEIVE_EXT_CHL + i].aml, 0xFFFF);
+ writew(0, &reg->chl[RECEIVE_EXT_CHL + i].id0);
+ writew(AME | IDE, &reg->chl[RECEIVE_EXT_CHL + i].id1);
+ writew(0, &reg->chl[RECEIVE_EXT_CHL + i].dlc);
+ writew(0x1FFF, &reg->msk[RECEIVE_EXT_CHL + i].amh);
+ writew(0xFFFF, &reg->msk[RECEIVE_EXT_CHL + i].aml);
}
- bfin_write(&reg->mc2, BIT(TRANSMIT_CHL - 16));
- bfin_write(&reg->mc1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
- SSYNC();
+ writew(BIT(TRANSMIT_CHL - 16), &reg->mc2);
+ writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), &reg->mc1);
priv->can.state = CAN_STATE_STOPPED;
}
@@ -157,9 +262,9 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
/*
* leave configuration mode
*/
- bfin_write(&reg->control, bfin_read(&reg->control) & ~CCR);
+ writew(readw(&reg->control) & ~CCR, &reg->control);
- while (bfin_read(&reg->status) & CCA) {
+ while (readw(&reg->status) & CCA) {
udelay(10);
if (--timeout == 0) {
netdev_err(dev, "fail to leave configuration mode\n");
@@ -170,26 +275,25 @@ static void bfin_can_set_normal_mode(struct net_device *dev)
/*
* clear _All_ tx and rx interrupts
*/
- bfin_write(&reg->mbtif1, 0xFFFF);
- bfin_write(&reg->mbtif2, 0xFFFF);
- bfin_write(&reg->mbrif1, 0xFFFF);
- bfin_write(&reg->mbrif2, 0xFFFF);
+ writew(0xFFFF, &reg->mbtif1);
+ writew(0xFFFF, &reg->mbtif2);
+ writew(0xFFFF, &reg->mbrif1);
+ writew(0xFFFF, &reg->mbrif2);
/*
* clear global interrupt status register
*/
- bfin_write(&reg->gis, 0x7FF); /* overwrites with '1' */
+ writew(0x7FF, &reg->gis); /* overwrites with '1' */
/*
* Initialize Interrupts
* - set bits in the mailbox interrupt mask register
* - global interrupt mask
*/
- bfin_write(&reg->mbim1, BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL));
- bfin_write(&reg->mbim2, BIT(TRANSMIT_CHL - 16));
+ writew(BIT(RECEIVE_STD_CHL) + BIT(RECEIVE_EXT_CHL), &reg->mbim1);
+ writew(BIT(TRANSMIT_CHL - 16), &reg->mbim2);
- bfin_write(&reg->gim, EPIM | BOIM | RMLIM);
- SSYNC();
+ writew(EPIM | BOIM | RMLIM, &reg->gim);
}
static void bfin_can_start(struct net_device *dev)
@@ -226,7 +330,7 @@ static int bfin_can_get_berr_counter(const struct net_device *dev,
struct bfin_can_priv *priv = netdev_priv(dev);
struct bfin_can_regs __iomem *reg = priv->membase;
- u16 cec = bfin_read(&reg->cec);
+ u16 cec = readw(&reg->cec);
bec->txerr = cec >> 8;
bec->rxerr = cec;
@@ -252,28 +356,28 @@ static int bfin_can_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* fill id */
if (id & CAN_EFF_FLAG) {
- bfin_write(&reg->chl[TRANSMIT_CHL].id0, id);
+ writew(id, &reg->chl[TRANSMIT_CHL].id0);
val = ((id & 0x1FFF0000) >> 16) | IDE;
} else
val = (id << 2);
if (id & CAN_RTR_FLAG)
val |= RTR;
- bfin_write(&reg->chl[TRANSMIT_CHL].id1, val | AME);
+ writew(val | AME, &reg->chl[TRANSMIT_CHL].id1);
/* fill payload */
for (i = 0; i < 8; i += 2) {
val = ((7 - i) < dlc ? (data[7 - i]) : 0) +
((6 - i) < dlc ? (data[6 - i] << 8) : 0);
- bfin_write(&reg->chl[TRANSMIT_CHL].data[i], val);
+ writew(val, &reg->chl[TRANSMIT_CHL].data[i]);
}
/* fill data length code */
- bfin_write(&reg->chl[TRANSMIT_CHL].dlc, dlc);
+ writew(dlc, &reg->chl[TRANSMIT_CHL].dlc);
can_put_echo_skb(skb, dev, 0);
/* set transmit request */
- bfin_write(&reg->trs2, BIT(TRANSMIT_CHL - 16));
+ writew(BIT(TRANSMIT_CHL - 16), &reg->trs2);
return 0;
}
@@ -296,26 +400,26 @@ static void bfin_can_rx(struct net_device *dev, u16 isrc)
/* get id */
if (isrc & BIT(RECEIVE_EXT_CHL)) {
/* extended frame format (EFF) */
- cf->can_id = ((bfin_read(&reg->chl[RECEIVE_EXT_CHL].id1)
+ cf->can_id = ((readw(&reg->chl[RECEIVE_EXT_CHL].id1)
& 0x1FFF) << 16)
- + bfin_read(&reg->chl[RECEIVE_EXT_CHL].id0);
+ + readw(&reg->chl[RECEIVE_EXT_CHL].id0);
cf->can_id |= CAN_EFF_FLAG;
obj = RECEIVE_EXT_CHL;
} else {
/* standard frame format (SFF) */
- cf->can_id = (bfin_read(&reg->chl[RECEIVE_STD_CHL].id1)
+ cf->can_id = (readw(&reg->chl[RECEIVE_STD_CHL].id1)
& 0x1ffc) >> 2;
obj = RECEIVE_STD_CHL;
}
- if (bfin_read(&reg->chl[obj].id1) & RTR)
+ if (readw(&reg->chl[obj].id1) & RTR)
cf->can_id |= CAN_RTR_FLAG;
/* get data length code */
- cf->can_dlc = get_can_dlc(bfin_read(&reg->chl[obj].dlc) & 0xF);
+ cf->can_dlc = get_can_dlc(readw(&reg->chl[obj].dlc) & 0xF);
/* get payload */
for (i = 0; i < 8; i += 2) {
- val = bfin_read(&reg->chl[obj].data[i]);
+ val = readw(&reg->chl[obj].data[i]);
cf->data[7 - i] = (7 - i) < cf->can_dlc ? val : 0;
cf->data[6 - i] = (6 - i) < cf->can_dlc ? (val >> 8) : 0;
}
@@ -369,7 +473,7 @@ static int bfin_can_err(struct net_device *dev, u16 isrc, u16 status)
if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
state == CAN_STATE_ERROR_PASSIVE)) {
- u16 cec = bfin_read(&reg->cec);
+ u16 cec = readw(&reg->cec);
u8 rxerr = cec;
u8 txerr = cec >> 8;
@@ -420,23 +524,23 @@ static irqreturn_t bfin_can_interrupt(int irq, void *dev_id)
struct net_device_stats *stats = &dev->stats;
u16 status, isrc;
- if ((irq == priv->tx_irq) && bfin_read(&reg->mbtif2)) {
+ if ((irq == priv->tx_irq) && readw(&reg->mbtif2)) {
/* transmission complete interrupt */
- bfin_write(&reg->mbtif2, 0xFFFF);
+ writew(0xFFFF, &reg->mbtif2);
stats->tx_packets++;
- stats->tx_bytes += bfin_read(&reg->chl[TRANSMIT_CHL].dlc);
+ stats->tx_bytes += readw(&reg->chl[TRANSMIT_CHL].dlc);
can_get_echo_skb(dev, 0);
netif_wake_queue(dev);
- } else if ((irq == priv->rx_irq) && bfin_read(&reg->mbrif1)) {
+ } else if ((irq == priv->rx_irq) && readw(&reg->mbrif1)) {
/* receive interrupt */
- isrc = bfin_read(&reg->mbrif1);
- bfin_write(&reg->mbrif1, 0xFFFF);
+ isrc = readw(&reg->mbrif1);
+ writew(0xFFFF, &reg->mbrif1);
bfin_can_rx(dev, isrc);
- } else if ((irq == priv->err_irq) && bfin_read(&reg->gis)) {
+ } else if ((irq == priv->err_irq) && readw(&reg->gis)) {
/* error interrupt */
- isrc = bfin_read(&reg->gis);
- status = bfin_read(&reg->esr);
- bfin_write(&reg->gis, 0x7FF);
+ isrc = readw(&reg->gis);
+ status = readw(&reg->esr);
+ writew(0x7FF, &reg->gis);
bfin_can_err(dev, isrc, status);
} else {
return IRQ_NONE;
@@ -556,16 +660,10 @@ static int bfin_can_probe(struct platform_device *pdev)
goto exit;
}
- if (!request_mem_region(res_mem->start, resource_size(res_mem),
- dev_name(&pdev->dev))) {
- err = -EBUSY;
- goto exit;
- }
-
/* request peripheral pins */
err = peripheral_request_list(pdata, dev_name(&pdev->dev));
if (err)
- goto exit_mem_release;
+ goto exit;
dev = alloc_bfin_candev();
if (!dev) {
@@ -574,7 +672,13 @@ static int bfin_can_probe(struct platform_device *pdev)
}
priv = netdev_priv(dev);
- priv->membase = (void __iomem *)res_mem->start;
+
+ priv->membase = devm_ioremap_resource(&pdev->dev, res_mem);
+ if (IS_ERR(priv->membase)) {
+ err = PTR_ERR(priv->membase);
+ goto exit_peri_pin_free;
+ }
+
priv->rx_irq = rx_irq->start;
priv->tx_irq = tx_irq->start;
priv->err_irq = err_irq->start;
@@ -606,8 +710,6 @@ exit_candev_free:
free_candev(dev);
exit_peri_pin_free:
peripheral_free_list(pdata);
-exit_mem_release:
- release_mem_region(res_mem->start, resource_size(res_mem));
exit:
return err;
}
@@ -616,15 +718,11 @@ static int bfin_can_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct bfin_can_priv *priv = netdev_priv(dev);
- struct resource *res;
bfin_can_set_reset_mode(dev);
unregister_candev(dev);
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
peripheral_free_list(priv->pin_list);
free_candev(dev);
@@ -641,9 +739,8 @@ static int bfin_can_suspend(struct platform_device *pdev, pm_message_t mesg)
if (netif_running(dev)) {
/* enter sleep mode */
- bfin_write(&reg->control, bfin_read(&reg->control) | SMR);
- SSYNC();
- while (!(bfin_read(&reg->intr) & SMACK)) {
+ writew(readw(&reg->control) | SMR, &reg->control);
+ while (!(readw(&reg->intr) & SMACK)) {
udelay(10);
if (--timeout == 0) {
netdev_err(dev, "fail to enter sleep mode\n");
@@ -663,8 +760,7 @@ static int bfin_can_resume(struct platform_device *pdev)
if (netif_running(dev)) {
/* leave sleep mode */
- bfin_write(&reg->intr, 0);
- SSYNC();
+ writew(0, &reg->intr);
}
return 0;
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
index b1e8851d3cc4..866e5e12fdd2 100644
--- a/drivers/net/can/cc770/cc770_platform.c
+++ b/drivers/net/can/cc770/cc770_platform.c
@@ -254,7 +254,7 @@ static int cc770_platform_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id cc770_platform_table[] = {
+static const struct of_device_id cc770_platform_table[] = {
{.compatible = "bosch,cc770"}, /* CC770 from Bosch */
{.compatible = "intc,82527"}, /* AN82527 from Intel CP */
{},
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 80c46ad4cee4..ad0a7e8c2c2b 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -592,13 +592,12 @@ static int flexcan_poll_state(struct net_device *dev, u32 reg_esr)
rx_state = unlikely(reg_esr & FLEXCAN_ESR_RX_WRN) ?
CAN_STATE_ERROR_WARNING : CAN_STATE_ERROR_ACTIVE;
new_state = max(tx_state, rx_state);
- } else if (unlikely(flt == FLEXCAN_ESR_FLT_CONF_PASSIVE)) {
+ } else {
__flexcan_get_berr_counter(dev, &bec);
- new_state = CAN_STATE_ERROR_PASSIVE;
+ new_state = flt == FLEXCAN_ESR_FLT_CONF_PASSIVE ?
+ CAN_STATE_ERROR_PASSIVE : CAN_STATE_BUS_OFF;
rx_state = bec.rxerr >= bec.txerr ? new_state : 0;
tx_state = bec.rxerr <= bec.txerr ? new_state : 0;
- } else {
- new_state = CAN_STATE_BUS_OFF;
}
/* state hasn't changed */
@@ -1158,12 +1157,19 @@ static int flexcan_probe(struct platform_device *pdev)
const struct flexcan_devtype_data *devtype_data;
struct net_device *dev;
struct flexcan_priv *priv;
+ struct regulator *reg_xceiver;
struct resource *mem;
struct clk *clk_ipg = NULL, *clk_per = NULL;
void __iomem *base;
int err, irq;
u32 clock_freq = 0;
+ reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
+ if (PTR_ERR(reg_xceiver) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ else if (IS_ERR(reg_xceiver))
+ reg_xceiver = NULL;
+
if (pdev->dev.of_node)
of_property_read_u32(pdev->dev.of_node,
"clock-frequency", &clock_freq);
@@ -1224,9 +1230,7 @@ static int flexcan_probe(struct platform_device *pdev)
priv->pdata = dev_get_platdata(&pdev->dev);
priv->devtype_data = devtype_data;
- priv->reg_xceiver = devm_regulator_get(&pdev->dev, "xceiver");
- if (IS_ERR(priv->reg_xceiver))
- priv->reg_xceiver = NULL;
+ priv->reg_xceiver = reg_xceiver;
netif_napi_add(dev, &priv->napi, flexcan_poll, FLEXCAN_NAPI_WEIGHT);
diff --git a/drivers/net/can/grcan.c b/drivers/net/can/grcan.c
index fed1bbd0b0d2..e3d7e22a4fa0 100644
--- a/drivers/net/can/grcan.c
+++ b/drivers/net/can/grcan.c
@@ -1725,7 +1725,7 @@ static int grcan_remove(struct platform_device *ofdev)
return 0;
}
-static struct of_device_id grcan_match[] = {
+static const struct of_device_id grcan_match[] = {
{.name = "GAISLER_GRCAN"},
{.name = "01_03d"},
{.name = "GAISLER_GRHCAN"},
diff --git a/drivers/net/can/led.c b/drivers/net/can/led.c
index ab7f1b01be49..c1b667675fa1 100644
--- a/drivers/net/can/led.c
+++ b/drivers/net/can/led.c
@@ -30,20 +30,28 @@ void can_led_event(struct net_device *netdev, enum can_led_event event)
case CAN_LED_EVENT_OPEN:
led_trigger_event(priv->tx_led_trig, LED_FULL);
led_trigger_event(priv->rx_led_trig, LED_FULL);
+ led_trigger_event(priv->rxtx_led_trig, LED_FULL);
break;
case CAN_LED_EVENT_STOP:
led_trigger_event(priv->tx_led_trig, LED_OFF);
led_trigger_event(priv->rx_led_trig, LED_OFF);
+ led_trigger_event(priv->rxtx_led_trig, LED_OFF);
break;
case CAN_LED_EVENT_TX:
- if (led_delay)
+ if (led_delay) {
led_trigger_blink_oneshot(priv->tx_led_trig,
&led_delay, &led_delay, 1);
+ led_trigger_blink_oneshot(priv->rxtx_led_trig,
+ &led_delay, &led_delay, 1);
+ }
break;
case CAN_LED_EVENT_RX:
- if (led_delay)
+ if (led_delay) {
led_trigger_blink_oneshot(priv->rx_led_trig,
&led_delay, &led_delay, 1);
+ led_trigger_blink_oneshot(priv->rxtx_led_trig,
+ &led_delay, &led_delay, 1);
+ }
break;
}
}
@@ -55,6 +63,7 @@ static void can_led_release(struct device *gendev, void *res)
led_trigger_unregister_simple(priv->tx_led_trig);
led_trigger_unregister_simple(priv->rx_led_trig);
+ led_trigger_unregister_simple(priv->rxtx_led_trig);
}
/* Register CAN LED triggers for a CAN device
@@ -76,11 +85,15 @@ void devm_can_led_init(struct net_device *netdev)
"%s-tx", netdev->name);
snprintf(priv->rx_led_trig_name, sizeof(priv->rx_led_trig_name),
"%s-rx", netdev->name);
+ snprintf(priv->rxtx_led_trig_name, sizeof(priv->rxtx_led_trig_name),
+ "%s-rxtx", netdev->name);
led_trigger_register_simple(priv->tx_led_trig_name,
&priv->tx_led_trig);
led_trigger_register_simple(priv->rx_led_trig_name,
&priv->rx_led_trig);
+ led_trigger_register_simple(priv->rxtx_led_trig_name,
+ &priv->rxtx_led_trig);
devres_add(&netdev->dev, res);
}
@@ -97,7 +110,7 @@ static int can_led_notifier(struct notifier_block *nb, unsigned long msg,
if (!priv)
return NOTIFY_DONE;
- if (!priv->tx_led_trig || !priv->rx_led_trig)
+ if (!priv->tx_led_trig || !priv->rx_led_trig || !priv->rxtx_led_trig)
return NOTIFY_DONE;
if (msg == NETDEV_CHANGENAME) {
@@ -106,6 +119,9 @@ static int can_led_notifier(struct notifier_block *nb, unsigned long msg,
snprintf(name, sizeof(name), "%s-rx", netdev->name);
led_trigger_rename_static(name, priv->rx_led_trig);
+
+ snprintf(name, sizeof(name), "%s-rxtx", netdev->name);
+ led_trigger_rename_static(name, priv->rxtx_led_trig);
}
return NOTIFY_DONE;
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 2e04b3aeeb37..ef655177bb5e 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -312,8 +312,8 @@ static inline u32 m_can_fifo_read(const struct m_can_priv *priv,
static inline void m_can_fifo_write(const struct m_can_priv *priv,
u32 fpi, unsigned int offset, u32 val)
{
- return writel(val, priv->mram_base + priv->mcfg[MRAM_TXB].off +
- fpi * TXB_ELEMENT_SIZE + offset);
+ writel(val, priv->mram_base + priv->mcfg[MRAM_TXB].off +
+ fpi * TXB_ELEMENT_SIZE + offset);
}
static inline void m_can_config_endisable(const struct m_can_priv *priv,
diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c
index ad024e60ba8c..c7427bdd3a4b 100644
--- a/drivers/net/can/mscan/mpc5xxx_can.c
+++ b/drivers/net/can/mscan/mpc5xxx_can.c
@@ -43,7 +43,7 @@ struct mpc5xxx_can_data {
};
#ifdef CONFIG_PPC_MPC52xx
-static struct of_device_id mpc52xx_cdm_ids[] = {
+static const struct of_device_id mpc52xx_cdm_ids[] = {
{ .compatible = "fsl,mpc5200-cdm", },
{}
};
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
index 93115250eaf5..0552ed46a206 100644
--- a/drivers/net/can/sja1000/sja1000_platform.c
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -242,7 +242,7 @@ static int sp_remove(struct platform_device *pdev)
return 0;
}
-static struct of_device_id sp_of_table[] = {
+static const struct of_device_id sp_of_table[] = {
{.compatible = "nxp,sja1000"},
{},
};
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 9376f5e5b94e..866bac0ae7e9 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -123,7 +123,7 @@ MODULE_LICENSE("GPL v2");
* CPC_MSG_TYPE_EXT_CAN_FRAME or CPC_MSG_TYPE_EXT_RTR_FRAME.
*/
struct cpc_can_msg {
- u32 id;
+ __le32 id;
u8 length;
u8 msg[8];
};
@@ -200,8 +200,8 @@ struct __packed ems_cpc_msg {
u8 type; /* type of message */
u8 length; /* length of data within union 'msg' */
u8 msgid; /* confirmation handle */
- u32 ts_sec; /* timestamp in seconds */
- u32 ts_nsec; /* timestamp in nano seconds */
+ __le32 ts_sec; /* timestamp in seconds */
+ __le32 ts_nsec; /* timestamp in nano seconds */
union {
u8 generic[64];
@@ -765,7 +765,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
msg = (struct ems_cpc_msg *)&buf[CPC_HEADER_SIZE];
- msg->msg.can_msg.id = cf->can_id & CAN_ERR_MASK;
+ msg->msg.can_msg.id = cpu_to_le32(cf->can_id & CAN_ERR_MASK);
msg->msg.can_msg.length = cf->can_dlc;
if (cf->can_id & CAN_RTR_FLAG) {
@@ -783,9 +783,6 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne
msg->length = CPC_CAN_MSG_MIN_SIZE + cf->can_dlc;
}
- /* Respect byte order */
- msg->msg.can_msg.id = cpu_to_le32(msg->msg.can_msg.id);
-
for (i = 0; i < MAX_TX_URBS; i++) {
if (dev->tx_contexts[i].echo_index == MAX_TX_URBS) {
context = &dev->tx_contexts[i];
diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c
index bacca0bd89c1..411c1af92c62 100644
--- a/drivers/net/can/usb/esd_usb2.c
+++ b/drivers/net/can/usb/esd_usb2.c
@@ -139,7 +139,7 @@ struct tx_msg {
u8 cmd;
u8 net;
u8 dlc;
- __le32 hnd;
+ u32 hnd; /* opaque handle, not used by device */
__le32 id; /* upper 3 bits contain flags */
u8 data[8];
};
@@ -149,7 +149,7 @@ struct tx_done_msg {
u8 cmd;
u8 net;
u8 status;
- __le32 hnd;
+ u32 hnd; /* opaque handle, not used by device */
__le32 ts;
};
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index 009acc8641fc..8b4d3e6875eb 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -901,6 +901,8 @@ static int gs_usb_probe(struct usb_interface *intf, const struct usb_device_id *
}
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
init_usb_anchor(&dev->rx_submitted);
atomic_set(&dev->active_channels, 0);
diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c
index a316fa4b91ab..4643914859b2 100644
--- a/drivers/net/can/usb/kvaser_usb.c
+++ b/drivers/net/can/usb/kvaser_usb.c
@@ -14,6 +14,7 @@
* Copyright (C) 2015 Valeo S.A.
*/
+#include <linux/spinlock.h>
#include <linux/kernel.h>
#include <linux/completion.h>
#include <linux/module.h>
@@ -24,7 +25,6 @@
#include <linux/can/dev.h>
#include <linux/can/error.h>
-#define MAX_TX_URBS 16
#define MAX_RX_URBS 4
#define START_TIMEOUT 1000 /* msecs */
#define STOP_TIMEOUT 1000 /* msecs */
@@ -442,6 +442,7 @@ struct kvaser_usb_error_summary {
};
};
+/* Context for an outstanding, not yet ACKed, transmission */
struct kvaser_usb_tx_urb_context {
struct kvaser_usb_net_priv *priv;
u32 echo_index;
@@ -455,8 +456,13 @@ struct kvaser_usb {
struct usb_endpoint_descriptor *bulk_in, *bulk_out;
struct usb_anchor rx_submitted;
+ /* @max_tx_urbs: Firmware-reported maximum number of oustanding,
+ * not yet ACKed, transmissions on this device. This value is
+ * also used as a sentinel for marking free tx contexts.
+ */
u32 fw_version;
unsigned int nchannels;
+ unsigned int max_tx_urbs;
enum kvaser_usb_family family;
bool rxinitdone;
@@ -466,18 +472,18 @@ struct kvaser_usb {
struct kvaser_usb_net_priv {
struct can_priv can;
-
- atomic_t active_tx_urbs;
- struct usb_anchor tx_submitted;
- struct kvaser_usb_tx_urb_context tx_contexts[MAX_TX_URBS];
-
- struct completion start_comp, stop_comp;
+ struct can_berr_counter bec;
struct kvaser_usb *dev;
struct net_device *netdev;
int channel;
- struct can_berr_counter bec;
+ struct completion start_comp, stop_comp;
+ struct usb_anchor tx_submitted;
+
+ spinlock_t tx_contexts_lock;
+ int active_tx_contexts;
+ struct kvaser_usb_tx_urb_context tx_contexts[];
};
static const struct usb_device_id kvaser_usb_table[] = {
@@ -590,8 +596,8 @@ static int kvaser_usb_wait_msg(const struct kvaser_usb *dev, u8 id,
* for further details.
*/
if (tmp->len == 0) {
- pos = round_up(pos,
- dev->bulk_in->wMaxPacketSize);
+ pos = round_up(pos, le16_to_cpu(dev->bulk_in->
+ wMaxPacketSize));
continue;
}
@@ -655,9 +661,13 @@ static int kvaser_usb_get_software_info(struct kvaser_usb *dev)
switch (dev->family) {
case KVASER_LEAF:
dev->fw_version = le32_to_cpu(msg.u.leaf.softinfo.fw_version);
+ dev->max_tx_urbs =
+ le16_to_cpu(msg.u.leaf.softinfo.max_outstanding_tx);
break;
case KVASER_USBCAN:
dev->fw_version = le32_to_cpu(msg.u.usbcan.softinfo.fw_version);
+ dev->max_tx_urbs =
+ le16_to_cpu(msg.u.usbcan.softinfo.max_outstanding_tx);
break;
}
@@ -694,6 +704,7 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
struct kvaser_usb_net_priv *priv;
struct sk_buff *skb;
struct can_frame *cf;
+ unsigned long flags;
u8 channel, tid;
channel = msg->u.tx_acknowledge_header.channel;
@@ -712,7 +723,7 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
stats = &priv->netdev->stats;
- context = &priv->tx_contexts[tid % MAX_TX_URBS];
+ context = &priv->tx_contexts[tid % dev->max_tx_urbs];
/* Sometimes the state change doesn't come after a bus-off event */
if (priv->can.restart_ms &&
@@ -737,12 +748,15 @@ static void kvaser_usb_tx_acknowledge(const struct kvaser_usb *dev,
stats->tx_packets++;
stats->tx_bytes += context->dlc;
- can_get_echo_skb(priv->netdev, context->echo_index);
- context->echo_index = MAX_TX_URBS;
- atomic_dec(&priv->active_tx_urbs);
+ spin_lock_irqsave(&priv->tx_contexts_lock, flags);
+ can_get_echo_skb(priv->netdev, context->echo_index);
+ context->echo_index = dev->max_tx_urbs;
+ --priv->active_tx_contexts;
netif_wake_queue(priv->netdev);
+
+ spin_unlock_irqrestore(&priv->tx_contexts_lock, flags);
}
static void kvaser_usb_simple_msg_callback(struct urb *urb)
@@ -803,17 +817,6 @@ static int kvaser_usb_simple_msg_async(struct kvaser_usb_net_priv *priv,
return 0;
}
-static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
-{
- int i;
-
- usb_kill_anchored_urbs(&priv->tx_submitted);
- atomic_set(&priv->active_tx_urbs, 0);
-
- for (i = 0; i < MAX_TX_URBS; i++)
- priv->tx_contexts[i].echo_index = MAX_TX_URBS;
-}
-
static void kvaser_usb_rx_error_update_can_state(struct kvaser_usb_net_priv *priv,
const struct kvaser_usb_error_summary *es,
struct can_frame *cf)
@@ -1334,7 +1337,8 @@ static void kvaser_usb_read_bulk_callback(struct urb *urb)
* number of events in case of a heavy rx load on the bus.
*/
if (msg->len == 0) {
- pos = round_up(pos, dev->bulk_in->wMaxPacketSize);
+ pos = round_up(pos, le16_to_cpu(dev->bulk_in->
+ wMaxPacketSize));
continue;
}
@@ -1515,6 +1519,26 @@ error:
return err;
}
+static void kvaser_usb_reset_tx_urb_contexts(struct kvaser_usb_net_priv *priv)
+{
+ int i, max_tx_urbs;
+
+ max_tx_urbs = priv->dev->max_tx_urbs;
+
+ priv->active_tx_contexts = 0;
+ for (i = 0; i < max_tx_urbs; i++)
+ priv->tx_contexts[i].echo_index = max_tx_urbs;
+}
+
+/* This method might sleep. Do not call it in the atomic context
+ * of URB completions.
+ */
+static void kvaser_usb_unlink_tx_urbs(struct kvaser_usb_net_priv *priv)
+{
+ usb_kill_anchored_urbs(&priv->tx_submitted);
+ kvaser_usb_reset_tx_urb_contexts(priv);
+}
+
static void kvaser_usb_unlink_all_urbs(struct kvaser_usb *dev)
{
int i;
@@ -1634,6 +1658,7 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
struct kvaser_msg *msg;
int i, err, ret = NETDEV_TX_OK;
u8 *msg_tx_can_flags = NULL; /* GCC */
+ unsigned long flags;
if (can_dropped_invalid_skb(netdev, skb))
return NETDEV_TX_OK;
@@ -1687,12 +1712,21 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
if (cf->can_id & CAN_RTR_FLAG)
*msg_tx_can_flags |= MSG_FLAG_REMOTE_FRAME;
- for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++) {
- if (priv->tx_contexts[i].echo_index == MAX_TX_URBS) {
+ spin_lock_irqsave(&priv->tx_contexts_lock, flags);
+ for (i = 0; i < dev->max_tx_urbs; i++) {
+ if (priv->tx_contexts[i].echo_index == dev->max_tx_urbs) {
context = &priv->tx_contexts[i];
+
+ context->echo_index = i;
+ can_put_echo_skb(skb, netdev, context->echo_index);
+ ++priv->active_tx_contexts;
+ if (priv->active_tx_contexts >= dev->max_tx_urbs)
+ netif_stop_queue(netdev);
+
break;
}
}
+ spin_unlock_irqrestore(&priv->tx_contexts_lock, flags);
/* This should never happen; it implies a flow control bug */
if (!context) {
@@ -1704,7 +1738,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
}
context->priv = priv;
- context->echo_index = i;
context->dlc = cf->can_dlc;
msg->u.tx_can.tid = context->echo_index;
@@ -1716,18 +1749,17 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,
kvaser_usb_write_bulk_callback, context);
usb_anchor_urb(urb, &priv->tx_submitted);
- can_put_echo_skb(skb, netdev, context->echo_index);
-
- atomic_inc(&priv->active_tx_urbs);
-
- if (atomic_read(&priv->active_tx_urbs) >= MAX_TX_URBS)
- netif_stop_queue(netdev);
-
err = usb_submit_urb(urb, GFP_ATOMIC);
if (unlikely(err)) {
+ spin_lock_irqsave(&priv->tx_contexts_lock, flags);
+
can_free_echo_skb(netdev, context->echo_index);
+ context->echo_index = dev->max_tx_urbs;
+ --priv->active_tx_contexts;
+ netif_wake_queue(netdev);
+
+ spin_unlock_irqrestore(&priv->tx_contexts_lock, flags);
- atomic_dec(&priv->active_tx_urbs);
usb_unanchor_urb(urb);
stats->tx_dropped++;
@@ -1835,7 +1867,7 @@ static void kvaser_usb_remove_interfaces(struct kvaser_usb *dev)
if (!dev->nets[i])
continue;
- unregister_netdev(dev->nets[i]->netdev);
+ unregister_candev(dev->nets[i]->netdev);
}
kvaser_usb_unlink_all_urbs(dev);
@@ -1854,13 +1886,15 @@ static int kvaser_usb_init_one(struct usb_interface *intf,
struct kvaser_usb *dev = usb_get_intfdata(intf);
struct net_device *netdev;
struct kvaser_usb_net_priv *priv;
- int i, err;
+ int err;
err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, channel);
if (err)
return err;
- netdev = alloc_candev(sizeof(*priv), MAX_TX_URBS);
+ netdev = alloc_candev(sizeof(*priv) +
+ dev->max_tx_urbs * sizeof(*priv->tx_contexts),
+ dev->max_tx_urbs);
if (!netdev) {
dev_err(&intf->dev, "Cannot alloc candev\n");
return -ENOMEM;
@@ -1868,19 +1902,17 @@ static int kvaser_usb_init_one(struct usb_interface *intf,
priv = netdev_priv(netdev);
+ init_usb_anchor(&priv->tx_submitted);
init_completion(&priv->start_comp);
init_completion(&priv->stop_comp);
- init_usb_anchor(&priv->tx_submitted);
- atomic_set(&priv->active_tx_urbs, 0);
-
- for (i = 0; i < ARRAY_SIZE(priv->tx_contexts); i++)
- priv->tx_contexts[i].echo_index = MAX_TX_URBS;
-
priv->dev = dev;
priv->netdev = netdev;
priv->channel = channel;
+ spin_lock_init(&priv->tx_contexts_lock);
+ kvaser_usb_reset_tx_urb_contexts(priv);
+
priv->can.state = CAN_STATE_STOPPED;
priv->can.clock.freq = CAN_USB_CLOCK;
priv->can.bittiming_const = &kvaser_usb_bittiming_const;
@@ -1990,6 +2022,13 @@ static int kvaser_usb_probe(struct usb_interface *intf,
return err;
}
+ dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n",
+ ((dev->fw_version >> 24) & 0xff),
+ ((dev->fw_version >> 16) & 0xff),
+ (dev->fw_version & 0xffff));
+
+ dev_dbg(&intf->dev, "Max oustanding tx = %d URBs\n", dev->max_tx_urbs);
+
err = kvaser_usb_get_card_info(dev);
if (err) {
dev_err(&intf->dev,
@@ -1997,11 +2036,6 @@ static int kvaser_usb_probe(struct usb_interface *intf,
return err;
}
- dev_dbg(&intf->dev, "Firmware version: %d.%d.%d\n",
- ((dev->fw_version >> 24) & 0xff),
- ((dev->fw_version >> 16) & 0xff),
- (dev->fw_version & 0xffff));
-
for (i = 0; i < dev->nchannels; i++) {
err = kvaser_usb_init_one(intf, id, i);
if (err) {
diff --git a/drivers/net/can/usb/peak_usb/pcan_ucan.h b/drivers/net/can/usb/peak_usb/pcan_ucan.h
index 1ba7c25002e1..e8fc4952c6b0 100644
--- a/drivers/net/can/usb/peak_usb/pcan_ucan.h
+++ b/drivers/net/can/usb/peak_usb/pcan_ucan.h
@@ -26,8 +26,8 @@
#define PUCAN_CMD_FILTER_STD 0x008
#define PUCAN_CMD_TX_ABORT 0x009
#define PUCAN_CMD_WR_ERR_CNT 0x00a
-#define PUCAN_CMD_RX_FRAME_ENABLE 0x00b
-#define PUCAN_CMD_RX_FRAME_DISABLE 0x00c
+#define PUCAN_CMD_SET_EN_OPTION 0x00b
+#define PUCAN_CMD_CLR_DIS_OPTION 0x00c
#define PUCAN_CMD_END_OF_COLLECTION 0x3ff
/* uCAN received messages list */
@@ -101,14 +101,15 @@ struct __packed pucan_wr_err_cnt {
u16 unused;
};
-/* uCAN RX_FRAME_ENABLE command fields */
-#define PUCAN_FLTEXT_ERROR 0x0001
-#define PUCAN_FLTEXT_BUSLOAD 0x0002
+/* uCAN SET_EN/CLR_DIS _OPTION command fields */
+#define PUCAN_OPTION_ERROR 0x0001
+#define PUCAN_OPTION_BUSLOAD 0x0002
+#define PUCAN_OPTION_CANDFDISO 0x0004
-struct __packed pucan_filter_ext {
+struct __packed pucan_options {
__le16 opcode_channel;
- __le16 ext_mask;
+ __le16 options;
u32 unused;
};
diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
index 0bac0f14edc3..09d14e70abd7 100644
--- a/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
+++ b/drivers/net/can/usb/peak_usb/pcan_usb_fd.c
@@ -110,13 +110,13 @@ struct __packed pcan_ufd_led {
u8 unused[5];
};
-/* Extended usage of uCAN commands CMD_RX_FRAME_xxxABLE for PCAN-USB Pro FD */
+/* Extended usage of uCAN commands CMD_xxx_xx_OPTION for PCAN-USB Pro FD */
#define PCAN_UFD_FLTEXT_CALIBRATION 0x8000
-struct __packed pcan_ufd_filter_ext {
+struct __packed pcan_ufd_options {
__le16 opcode_channel;
- __le16 ext_mask;
+ __le16 ucan_mask;
u16 unused;
__le16 usb_mask;
};
@@ -182,7 +182,7 @@ static inline void *pcan_usb_fd_cmd_buffer(struct peak_usb_device *dev)
static int pcan_usb_fd_send_cmd(struct peak_usb_device *dev, void *cmd_tail)
{
void *cmd_head = pcan_usb_fd_cmd_buffer(dev);
- int err;
+ int err = 0;
u8 *packet_ptr;
int i, n = 1, packet_len;
ptrdiff_t cmd_len;
@@ -251,6 +251,27 @@ static int pcan_usb_fd_build_restart_cmd(struct peak_usb_device *dev, u8 *buf)
/* moves the pointer forward */
pc += sizeof(struct pucan_wr_err_cnt);
+ /* add command to switch from ISO to non-ISO mode, if fw allows it */
+ if (dev->can.ctrlmode_supported & CAN_CTRLMODE_FD_NON_ISO) {
+ struct pucan_options *puo = (struct pucan_options *)pc;
+
+ puo->opcode_channel =
+ (dev->can.ctrlmode & CAN_CTRLMODE_FD_NON_ISO) ?
+ pucan_cmd_opcode_channel(dev,
+ PUCAN_CMD_CLR_DIS_OPTION) :
+ pucan_cmd_opcode_channel(dev, PUCAN_CMD_SET_EN_OPTION);
+
+ puo->options = cpu_to_le16(PUCAN_OPTION_CANDFDISO);
+
+ /* to be sure that no other extended bits will be taken into
+ * account
+ */
+ puo->unused = 0;
+
+ /* moves the pointer forward */
+ pc += sizeof(struct pucan_options);
+ }
+
/* next, go back to operational mode */
cmd = (struct pucan_command *)pc;
cmd->opcode_channel = pucan_cmd_opcode_channel(dev,
@@ -321,21 +342,21 @@ static int pcan_usb_fd_set_filter_std(struct peak_usb_device *dev, int idx,
return pcan_usb_fd_send_cmd(dev, cmd);
}
-/* set/unset notifications filter:
+/* set/unset options
*
- * onoff sets(1)/unset(0) notifications
- * mask each bit defines a kind of notification to set/unset
+ * onoff set(1)/unset(0) options
+ * mask each bit defines a kind of options to set/unset
*/
-static int pcan_usb_fd_set_filter_ext(struct peak_usb_device *dev,
- bool onoff, u16 ext_mask, u16 usb_mask)
+static int pcan_usb_fd_set_options(struct peak_usb_device *dev,
+ bool onoff, u16 ucan_mask, u16 usb_mask)
{
- struct pcan_ufd_filter_ext *cmd = pcan_usb_fd_cmd_buffer(dev);
+ struct pcan_ufd_options *cmd = pcan_usb_fd_cmd_buffer(dev);
cmd->opcode_channel = pucan_cmd_opcode_channel(dev,
- (onoff) ? PUCAN_CMD_RX_FRAME_ENABLE :
- PUCAN_CMD_RX_FRAME_DISABLE);
+ (onoff) ? PUCAN_CMD_SET_EN_OPTION :
+ PUCAN_CMD_CLR_DIS_OPTION);
- cmd->ext_mask = cpu_to_le16(ext_mask);
+ cmd->ucan_mask = cpu_to_le16(ucan_mask);
cmd->usb_mask = cpu_to_le16(usb_mask);
/* send the command */
@@ -770,9 +791,9 @@ static int pcan_usb_fd_start(struct peak_usb_device *dev)
&pcan_usb_pro_fd);
/* enable USB calibration messages */
- err = pcan_usb_fd_set_filter_ext(dev, 1,
- PUCAN_FLTEXT_ERROR,
- PCAN_UFD_FLTEXT_CALIBRATION);
+ err = pcan_usb_fd_set_options(dev, 1,
+ PUCAN_OPTION_ERROR,
+ PCAN_UFD_FLTEXT_CALIBRATION);
}
pdev->usb_if->dev_opened_count++;
@@ -806,9 +827,9 @@ static int pcan_usb_fd_stop(struct peak_usb_device *dev)
/* turn off special msgs for that interface if no other dev opened */
if (pdev->usb_if->dev_opened_count == 1)
- pcan_usb_fd_set_filter_ext(dev, 0,
- PUCAN_FLTEXT_ERROR,
- PCAN_UFD_FLTEXT_CALIBRATION);
+ pcan_usb_fd_set_options(dev, 0,
+ PUCAN_OPTION_ERROR,
+ PCAN_UFD_FLTEXT_CALIBRATION);
pdev->usb_if->dev_opened_count--;
return 0;
@@ -860,8 +881,14 @@ static int pcan_usb_fd_init(struct peak_usb_device *dev)
pdev->usb_if->fw_info.fw_version[2],
dev->adapter->ctrl_count);
- /* the currently supported hw is non-ISO */
- dev->can.ctrlmode = CAN_CTRLMODE_FD_NON_ISO;
+ /* check for ability to switch between ISO/non-ISO modes */
+ if (pdev->usb_if->fw_info.fw_version[0] >= 2) {
+ /* firmware >= 2.x supports ISO/non-ISO switching */
+ dev->can.ctrlmode_supported |= CAN_CTRLMODE_FD_NON_ISO;
+ } else {
+ /* firmware < 2.x only supports fixed(!) non-ISO */
+ dev->can.ctrlmode |= CAN_CTRLMODE_FD_NON_ISO;
+ }
/* tell the hardware the can driver is running */
err = pcan_usb_fd_drv_loaded(dev, 1);
@@ -937,9 +964,9 @@ static void pcan_usb_fd_exit(struct peak_usb_device *dev)
if (dev->ctrl_idx == 0) {
/* turn off calibration message if any device were opened */
if (pdev->usb_if->dev_opened_count > 0)
- pcan_usb_fd_set_filter_ext(dev, 0,
- PUCAN_FLTEXT_ERROR,
- PCAN_UFD_FLTEXT_CALIBRATION);
+ pcan_usb_fd_set_options(dev, 0,
+ PUCAN_OPTION_ERROR,
+ PCAN_UFD_FLTEXT_CALIBRATION);
/* tell USB adapter that the driver is being unloaded */
pcan_usb_fd_drv_loaded(dev, 0);
diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c
index 6c6764312285..6bddfe062b51 100644
--- a/drivers/net/can/xilinx_can.c
+++ b/drivers/net/can/xilinx_can.c
@@ -1185,7 +1185,7 @@ static int xcan_remove(struct platform_device *pdev)
}
/* Match table for OF platform binding */
-static struct of_device_id xcan_of_match[] = {
+static const struct of_device_id xcan_of_match[] = {
{ .compatible = "xlnx,zynq-can-1.0", },
{ .compatible = "xlnx,axi-can-1.00.a", },
{ /* end of list */ },