linux-can-next-for-5.15-20210725

-----BEGIN PGP SIGNATURE-----
 
 iQFHBAABCgAxFiEEK3kIWJt9yTYMP3ehqclaivrt76kFAmD9M0sTHG1rbEBwZW5n
 dXRyb25peC5kZQAKCRCpyVqK+u3vqT6SB/9S0h403FVv8IMCX2Vs3lD1ydQag8Uu
 B7Pnb2eI5lQ7sRyaCTBxQvZIwcClx1DKdRDqeyvHQ3GqMA9mhysyovhFfXt6OmaD
 VyPIOBxquothlelZwMz743dXAta8WVyMHxIQkn4PJuEHoaFRLXI1TcXtlN/rPfSr
 VRt/QTN8Z4xYVx34YNQcK0jxkgVkkWY0Bv0hjHO0+XIW27zeX6JeAsJZZxQAQpmx
 bT4pZq9oKYSq9WTIdh8uq2HeBIbcA8wlVHV7ixdVfe0hWrBW5INfB5hsQ+THjJ51
 7XhO3cVaOuQZnZEta69RSFBvZiugevZXN1AJudgle16+317LTVUZ/bTX
 =/GFB
 -----END PGP SIGNATURE-----

Merge tag 'linux-can-next-for-5.15-20210725' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

linux-can-next-for-5.15-20210725

Marc Kleine-Budde says:

====================
pull-request: can-next 2021-07-25

this is a pull request of 46 patches for net-next/master.

The first 6 patches target the CAN J1939 protocol. One is from
gushengxian, fixing a grammatical error, 5 are by me fixing a checkpatch
warning, make use of the fallthrough pseudo-keyword, and use
consistent variable naming.

The next 3 patches target the rx-offload helper, are by me and improve
the performance and fix the local softirq work pending error, when
napi_schedule() is called from threaded IRQ context.

The next 3 patches are by Vincent Mailhol and me update the CAN
bittiming and transmitter delay compensation, the documentation for
the struct can_tdc is fixed, clear data_bittiming if FD mode is turned
off and a redundant check is removed.

Followed by 4 patches targeting the m_can driver. Faiz Abbas's patches
add support for CAN PHY via the generic phy subsystem. Yang Yingliang
converts the driver to use devm_platform_ioremap_resource_byname().
And a patch by me which removes the unused support for custom bit
timing.

Andy Shevchenko contributes 2 patches for the mcp251xfd driver to
prepare the driver for ACPI support. A patch by me adds support for
shared IRQ handlers.

Zhen Lei contributes 3 patches to convert the esd_usb2, janz-ican3 and
the at91_can driver to make use of the DEVICE_ATTR_RO/RW() macros.

The next 8 patches are by Peng Li and provide general cleanups for the
at91_can driver.

The next 7 patches target the peak driver. Frist 2 cleanup patches by
me for the peak_pci driver, followed by Stephane Grosjean' patch to
print the name and firmware version of the detected hardware. The
peak_usb driver gets a cleanup patch, loopback and one-shot mode and
an upgrading of the bus state change handling in Stephane Grosjean's
patches.

Vincent Mailhol provides 6 cleanup patches for the etas_es58x driver.

In the last 3 patches Angelo Dureghello add support for the mcf5441x
SoC to the flexcan driver.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2021-07-26 22:07:29 +01:00
commit d20e5880fe
24 changed files with 586 additions and 445 deletions

View File

@ -107,6 +107,9 @@ properties:
can-transceiver:
$ref: can-transceiver.yaml#
phys:
maxItems: 1
required:
- compatible
- reg

View File

@ -97,7 +97,8 @@ config CAN_AT91
config CAN_FLEXCAN
tristate "Support for Freescale FLEXCAN based chips"
depends on OF && HAS_IOMEM
depends on OF || COLDFIRE || COMPILE_TEST
depends on HAS_IOMEM
help
Say Y here if you want to support for Freescale FlexCAN.

View File

@ -43,14 +43,14 @@ enum at91_reg {
};
/* Mailbox registers (0 <= i <= 15) */
#define AT91_MMR(i) (enum at91_reg)(0x200 + ((i) * 0x20))
#define AT91_MAM(i) (enum at91_reg)(0x204 + ((i) * 0x20))
#define AT91_MID(i) (enum at91_reg)(0x208 + ((i) * 0x20))
#define AT91_MFID(i) (enum at91_reg)(0x20C + ((i) * 0x20))
#define AT91_MSR(i) (enum at91_reg)(0x210 + ((i) * 0x20))
#define AT91_MDL(i) (enum at91_reg)(0x214 + ((i) * 0x20))
#define AT91_MDH(i) (enum at91_reg)(0x218 + ((i) * 0x20))
#define AT91_MCR(i) (enum at91_reg)(0x21C + ((i) * 0x20))
#define AT91_MMR(i) ((enum at91_reg)(0x200 + ((i) * 0x20)))
#define AT91_MAM(i) ((enum at91_reg)(0x204 + ((i) * 0x20)))
#define AT91_MID(i) ((enum at91_reg)(0x208 + ((i) * 0x20)))
#define AT91_MFID(i) ((enum at91_reg)(0x20C + ((i) * 0x20)))
#define AT91_MSR(i) ((enum at91_reg)(0x210 + ((i) * 0x20)))
#define AT91_MDL(i) ((enum at91_reg)(0x214 + ((i) * 0x20)))
#define AT91_MDH(i) ((enum at91_reg)(0x218 + ((i) * 0x20)))
#define AT91_MCR(i) ((enum at91_reg)(0x21C + ((i) * 0x20)))
/* Register bits */
#define AT91_MR_CANEN BIT(0)
@ -87,19 +87,19 @@ enum at91_mb_mode {
};
/* Interrupt mask bits */
#define AT91_IRQ_ERRA (1 << 16)
#define AT91_IRQ_WARN (1 << 17)
#define AT91_IRQ_ERRP (1 << 18)
#define AT91_IRQ_BOFF (1 << 19)
#define AT91_IRQ_SLEEP (1 << 20)
#define AT91_IRQ_WAKEUP (1 << 21)
#define AT91_IRQ_TOVF (1 << 22)
#define AT91_IRQ_TSTP (1 << 23)
#define AT91_IRQ_CERR (1 << 24)
#define AT91_IRQ_SERR (1 << 25)
#define AT91_IRQ_AERR (1 << 26)
#define AT91_IRQ_FERR (1 << 27)
#define AT91_IRQ_BERR (1 << 28)
#define AT91_IRQ_ERRA BIT(16)
#define AT91_IRQ_WARN BIT(17)
#define AT91_IRQ_ERRP BIT(18)
#define AT91_IRQ_BOFF BIT(19)
#define AT91_IRQ_SLEEP BIT(20)
#define AT91_IRQ_WAKEUP BIT(21)
#define AT91_IRQ_TOVF BIT(22)
#define AT91_IRQ_TSTP BIT(23)
#define AT91_IRQ_CERR BIT(24)
#define AT91_IRQ_SERR BIT(25)
#define AT91_IRQ_AERR BIT(26)
#define AT91_IRQ_FERR BIT(27)
#define AT91_IRQ_BERR BIT(28)
#define AT91_IRQ_ERR_ALL (0x1fff0000)
#define AT91_IRQ_ERR_FRAME (AT91_IRQ_CERR | AT91_IRQ_SERR | \
@ -163,7 +163,7 @@ static const struct can_bittiming_const at91_bittiming_const = {
.tseg2_min = 2,
.tseg2_max = 8,
.sjw_max = 4,
.brp_min = 2,
.brp_min = 2,
.brp_max = 128,
.brp_inc = 1,
};
@ -281,19 +281,20 @@ static inline u32 at91_read(const struct at91_priv *priv, enum at91_reg reg)
}
static inline void at91_write(const struct at91_priv *priv, enum at91_reg reg,
u32 value)
u32 value)
{
writel_relaxed(value, priv->reg_base + reg);
}
static inline void set_mb_mode_prio(const struct at91_priv *priv,
unsigned int mb, enum at91_mb_mode mode, int prio)
unsigned int mb, enum at91_mb_mode mode,
int prio)
{
at91_write(priv, AT91_MMR(mb), (mode << 24) | (prio << 16));
}
static inline void set_mb_mode(const struct at91_priv *priv, unsigned int mb,
enum at91_mb_mode mode)
enum at91_mb_mode mode)
{
set_mb_mode_prio(priv, mb, mode, 0);
}
@ -316,8 +317,7 @@ static void at91_setup_mailboxes(struct net_device *dev)
unsigned int i;
u32 reg_mid;
/*
* Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first
/* Due to a chip bug (errata 50.2.6.3 & 50.3.5.3) the first
* mailbox is disabled. The next 11 mailboxes are used as a
* reception FIFO. The last mailbox is configured with
* overwrite option. The overwrite flag indicates a FIFO
@ -368,7 +368,7 @@ static int at91_set_bittiming(struct net_device *dev)
}
static int at91_get_berr_counter(const struct net_device *dev,
struct can_berr_counter *bec)
struct can_berr_counter *bec)
{
const struct at91_priv *priv = netdev_priv(dev);
u32 reg_ecr = at91_read(priv, AT91_ECR);
@ -423,8 +423,7 @@ static void at91_chip_stop(struct net_device *dev, enum can_state state)
priv->can.state = state;
}
/*
* theory of operation:
/* theory of operation:
*
* According to the datasheet priority 0 is the highest priority, 15
* is the lowest. If two mailboxes have the same priority level the
@ -486,8 +485,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
can_put_echo_skb(skb, dev, mb - get_mb_tx_first(priv), 0);
/*
* we have to stop the queue and deliver all messages in case
/* we have to stop the queue and deliver all messages in case
* of a prio+mb counter wrap around. This is the case if
* tx_next buffer prio and mailbox equals 0.
*
@ -515,6 +513,7 @@ static netdev_tx_t at91_start_xmit(struct sk_buff *skb, struct net_device *dev)
static inline void at91_activate_rx_low(const struct at91_priv *priv)
{
u32 mask = get_mb_rx_low_mask(priv);
at91_write(priv, AT91_TCR, mask);
}
@ -526,9 +525,10 @@ static inline void at91_activate_rx_low(const struct at91_priv *priv)
* Reenables given mailbox for reception of new CAN messages
*/
static inline void at91_activate_rx_mb(const struct at91_priv *priv,
unsigned int mb)
unsigned int mb)
{
u32 mask = 1 << mb;
at91_write(priv, AT91_TCR, mask);
}
@ -568,7 +568,7 @@ static void at91_rx_overflow_err(struct net_device *dev)
* given can frame. "mb" and "cf" must be valid.
*/
static void at91_read_mb(struct net_device *dev, unsigned int mb,
struct can_frame *cf)
struct can_frame *cf)
{
const struct at91_priv *priv = netdev_priv(dev);
u32 reg_msr, reg_mid;
@ -582,9 +582,9 @@ static void at91_read_mb(struct net_device *dev, unsigned int mb,
reg_msr = at91_read(priv, AT91_MSR(mb));
cf->len = can_cc_dlc2len((reg_msr >> 16) & 0xf);
if (reg_msr & AT91_MSR_MRTR)
if (reg_msr & AT91_MSR_MRTR) {
cf->can_id |= CAN_RTR_FLAG;
else {
} else {
*(u32 *)(cf->data + 0) = at91_read(priv, AT91_MDL(mb));
*(u32 *)(cf->data + 4) = at91_read(priv, AT91_MDH(mb));
}
@ -685,7 +685,7 @@ static int at91_poll_rx(struct net_device *dev, int quota)
if (priv->rx_next > get_mb_rx_low_last(priv) &&
reg_sr & get_mb_rx_low_mask(priv))
netdev_info(dev,
"order of incoming frames cannot be guaranteed\n");
"order of incoming frames cannot be guaranteed\n");
again:
for (mb = find_next_bit(addr, get_mb_tx_first(priv), priv->rx_next);
@ -718,7 +718,7 @@ static int at91_poll_rx(struct net_device *dev, int quota)
}
static void at91_poll_err_frame(struct net_device *dev,
struct can_frame *cf, u32 reg_sr)
struct can_frame *cf, u32 reg_sr)
{
struct at91_priv *priv = netdev_priv(dev);
@ -796,8 +796,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
if (reg_sr & get_irq_mb_rx(priv))
work_done += at91_poll_rx(dev, quota - work_done);
/*
* The error bits are clear on read,
/* The error bits are clear on read,
* so use saved value from irq handler.
*/
reg_sr |= priv->reg_sr;
@ -807,6 +806,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
if (work_done < quota) {
/* enable IRQs for frame errors and all mailboxes >= rx_next */
u32 reg_ier = AT91_IRQ_ERR_FRAME;
reg_ier |= get_irq_mb_rx(priv) & ~AT91_MB_MASK(priv->rx_next);
napi_complete_done(napi, work_done);
@ -816,8 +816,7 @@ static int at91_poll(struct napi_struct *napi, int quota)
return work_done;
}
/*
* theory of operation:
/* theory of operation:
*
* priv->tx_echo holds the number of the oldest can_frame put for
* transmission into the hardware, but not yet ACKed by the CAN tx
@ -846,8 +845,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
/* Disable irq for this TX mailbox */
at91_write(priv, AT91_IDR, 1 << mb);
/*
* only echo if mailbox signals us a transfer
/* only echo if mailbox signals us a transfer
* complete (MSR_MRDY). Otherwise it's a tansfer
* abort. "can_bus_off()" takes care about the skbs
* parked in the echo queue.
@ -862,8 +860,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
}
}
/*
* restart queue if we don't have a wrap around but restart if
/* restart queue if we don't have a wrap around but restart if
* we get a TX int for the last can frame directly before a
* wrap around.
*/
@ -873,7 +870,7 @@ static void at91_irq_tx(struct net_device *dev, u32 reg_sr)
}
static void at91_irq_err_state(struct net_device *dev,
struct can_frame *cf, enum can_state new_state)
struct can_frame *cf, enum can_state new_state)
{
struct at91_priv *priv = netdev_priv(dev);
u32 reg_idr = 0, reg_ier = 0;
@ -883,8 +880,7 @@ static void at91_irq_err_state(struct net_device *dev,
switch (priv->can.state) {
case CAN_STATE_ERROR_ACTIVE:
/*
* from: ERROR_ACTIVE
/* from: ERROR_ACTIVE
* to : ERROR_WARNING, ERROR_PASSIVE, BUS_OFF
* => : there was a warning int
*/
@ -900,8 +896,7 @@ static void at91_irq_err_state(struct net_device *dev,
}
fallthrough;
case CAN_STATE_ERROR_WARNING:
/*
* from: ERROR_ACTIVE, ERROR_WARNING
/* from: ERROR_ACTIVE, ERROR_WARNING
* to : ERROR_PASSIVE, BUS_OFF
* => : error passive int
*/
@ -917,8 +912,7 @@ static void at91_irq_err_state(struct net_device *dev,
}
break;
case CAN_STATE_BUS_OFF:
/*
* from: BUS_OFF
/* from: BUS_OFF
* to : ERROR_ACTIVE, ERROR_WARNING, ERROR_PASSIVE
*/
if (new_state <= CAN_STATE_ERROR_PASSIVE) {
@ -935,12 +929,10 @@ static void at91_irq_err_state(struct net_device *dev,
break;
}
/* process state changes depending on the new state */
switch (new_state) {
case CAN_STATE_ERROR_ACTIVE:
/*
* actually we want to enable AT91_IRQ_WARN here, but
/* actually we want to enable AT91_IRQ_WARN here, but
* it screws up the system under certain
* circumstances. so just enable AT91_IRQ_ERRP, thus
* the "fallthrough"
@ -983,7 +975,7 @@ static void at91_irq_err_state(struct net_device *dev,
}
static int at91_get_state_by_bec(const struct net_device *dev,
enum can_state *state)
enum can_state *state)
{
struct can_berr_counter bec;
int err;
@ -1004,7 +996,6 @@ static int at91_get_state_by_bec(const struct net_device *dev,
return 0;
}
static void at91_irq_err(struct net_device *dev)
{
struct at91_priv *priv = netdev_priv(dev);
@ -1018,15 +1009,15 @@ static void at91_irq_err(struct net_device *dev)
reg_sr = at91_read(priv, AT91_SR);
/* we need to look at the unmasked reg_sr */
if (unlikely(reg_sr & AT91_IRQ_BOFF))
if (unlikely(reg_sr & AT91_IRQ_BOFF)) {
new_state = CAN_STATE_BUS_OFF;
else if (unlikely(reg_sr & AT91_IRQ_ERRP))
} else if (unlikely(reg_sr & AT91_IRQ_ERRP)) {
new_state = CAN_STATE_ERROR_PASSIVE;
else if (unlikely(reg_sr & AT91_IRQ_WARN))
} else if (unlikely(reg_sr & AT91_IRQ_WARN)) {
new_state = CAN_STATE_ERROR_WARNING;
else if (likely(reg_sr & AT91_IRQ_ERRA))
} else if (likely(reg_sr & AT91_IRQ_ERRA)) {
new_state = CAN_STATE_ERROR_ACTIVE;
else {
} else {
netdev_err(dev, "BUG! hardware in undefined state\n");
return;
}
@ -1053,8 +1044,7 @@ static void at91_irq_err(struct net_device *dev)
priv->can.state = new_state;
}
/*
* interrupt handler
/* interrupt handler
*/
static irqreturn_t at91_irq(int irq, void *dev_id)
{
@ -1075,8 +1065,7 @@ static irqreturn_t at91_irq(int irq, void *dev_id)
/* Receive or error interrupt? -> napi */
if (reg_sr & (get_irq_mb_rx(priv) | AT91_IRQ_ERR_FRAME)) {
/*
* The error bits are clear on read,
/* The error bits are clear on read,
* save for later use.
*/
priv->reg_sr = reg_sr;
@ -1133,8 +1122,7 @@ static int at91_open(struct net_device *dev)
return err;
}
/*
* stop CAN bus activity
/* stop CAN bus activity
*/
static int at91_close(struct net_device *dev)
{
@ -1176,8 +1164,8 @@ static const struct net_device_ops at91_netdev_ops = {
.ndo_change_mtu = can_change_mtu,
};
static ssize_t at91_sysfs_show_mb0_id(struct device *dev,
struct device_attribute *attr, char *buf)
static ssize_t mb0_id_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct at91_priv *priv = netdev_priv(to_net_dev(dev));
@ -1187,8 +1175,9 @@ static ssize_t at91_sysfs_show_mb0_id(struct device *dev,
return snprintf(buf, PAGE_SIZE, "0x%03x\n", priv->mb0_id);
}
static ssize_t at91_sysfs_set_mb0_id(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
static ssize_t mb0_id_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct net_device *ndev = to_net_dev(dev);
struct at91_priv *priv = netdev_priv(ndev);
@ -1222,7 +1211,7 @@ static ssize_t at91_sysfs_set_mb0_id(struct device *dev,
return ret;
}
static DEVICE_ATTR(mb0_id, 0644, at91_sysfs_show_mb0_id, at91_sysfs_set_mb0_id);
static DEVICE_ATTR_RW(mb0_id);
static struct attribute *at91_sysfs_attrs[] = {
&dev_attr_mb0_id.attr,

View File

@ -47,7 +47,7 @@ static int can_validate(struct nlattr *tb[], struct nlattr *data[],
}
if (data[IFLA_CAN_DATA_BITTIMING]) {
if (!is_can_fd || !data[IFLA_CAN_BITTIMING])
if (!is_can_fd)
return -EOPNOTSUPP;
}
@ -132,10 +132,13 @@ static int can_changelink(struct net_device *dev, struct nlattr *tb[],
priv->ctrlmode |= maskedflags;
/* CAN_CTRLMODE_FD can only be set when driver supports FD */
if (priv->ctrlmode & CAN_CTRLMODE_FD)
if (priv->ctrlmode & CAN_CTRLMODE_FD) {
dev->mtu = CANFD_MTU;
else
} else {
dev->mtu = CAN_MTU;
memset(&priv->data_bittiming, 0,
sizeof(priv->data_bittiming));
}
}
if (data[IFLA_CAN_RESTART_MS]) {

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2014 Protonic Holland,
* David Jander
* Copyright (C) 2014-2017 Pengutronix,
* Copyright (C) 2014-2021 Pengutronix,
* Marc Kleine-Budde <kernel@pengutronix.de>
*/
@ -174,10 +174,8 @@ can_rx_offload_offload_one(struct can_rx_offload *offload, unsigned int n)
int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload,
u64 pending)
{
struct sk_buff_head skb_queue;
unsigned int i;
__skb_queue_head_init(&skb_queue);
int received = 0;
for (i = offload->mb_first;
can_rx_offload_le(offload, i, offload->mb_last);
@ -191,26 +189,12 @@ int can_rx_offload_irq_offload_timestamp(struct can_rx_offload *offload,
if (IS_ERR_OR_NULL(skb))
continue;
__skb_queue_add_sort(&skb_queue, skb, can_rx_offload_compare);
__skb_queue_add_sort(&offload->skb_irq_queue, skb,
can_rx_offload_compare);
received++;
}
if (!skb_queue_empty(&skb_queue)) {
unsigned long flags;
u32 queue_len;
spin_lock_irqsave(&offload->skb_queue.lock, flags);
skb_queue_splice_tail(&skb_queue, &offload->skb_queue);
spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
queue_len = skb_queue_len(&offload->skb_queue);
if (queue_len > offload->skb_queue_len_max / 8)
netdev_dbg(offload->dev, "%s: queue_len=%d\n",
__func__, queue_len);
can_rx_offload_schedule(offload);
}
return skb_queue_len(&skb_queue);
return received;
}
EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_timestamp);
@ -226,13 +210,10 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)
if (!skb)
break;
skb_queue_tail(&offload->skb_queue, skb);
__skb_queue_tail(&offload->skb_irq_queue, skb);
received++;
}
if (received)
can_rx_offload_schedule(offload);
return received;
}
EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo);
@ -241,7 +222,6 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
struct sk_buff *skb, u32 timestamp)
{
struct can_rx_offload_cb *cb;
unsigned long flags;
if (skb_queue_len(&offload->skb_queue) >
offload->skb_queue_len_max) {
@ -252,11 +232,8 @@ int can_rx_offload_queue_sorted(struct can_rx_offload *offload,
cb = can_rx_offload_get_cb(skb);
cb->timestamp = timestamp;
spin_lock_irqsave(&offload->skb_queue.lock, flags);
__skb_queue_add_sort(&offload->skb_queue, skb, can_rx_offload_compare);
spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
can_rx_offload_schedule(offload);
__skb_queue_add_sort(&offload->skb_irq_queue, skb,
can_rx_offload_compare);
return 0;
}
@ -295,13 +272,56 @@ int can_rx_offload_queue_tail(struct can_rx_offload *offload,
return -ENOBUFS;
}
skb_queue_tail(&offload->skb_queue, skb);
can_rx_offload_schedule(offload);
__skb_queue_tail(&offload->skb_irq_queue, skb);
return 0;
}
EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail);
void can_rx_offload_irq_finish(struct can_rx_offload *offload)
{
unsigned long flags;
int queue_len;
if (skb_queue_empty_lockless(&offload->skb_irq_queue))
return;
spin_lock_irqsave(&offload->skb_queue.lock, flags);
skb_queue_splice_tail_init(&offload->skb_irq_queue, &offload->skb_queue);
spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
queue_len = skb_queue_len(&offload->skb_queue);
if (queue_len > offload->skb_queue_len_max / 8)
netdev_dbg(offload->dev, "%s: queue_len=%d\n",
__func__, queue_len);
napi_schedule(&offload->napi);
}
EXPORT_SYMBOL_GPL(can_rx_offload_irq_finish);
void can_rx_offload_threaded_irq_finish(struct can_rx_offload *offload)
{
unsigned long flags;
int queue_len;
if (skb_queue_empty_lockless(&offload->skb_irq_queue))
return;
spin_lock_irqsave(&offload->skb_queue.lock, flags);
skb_queue_splice_tail_init(&offload->skb_irq_queue, &offload->skb_queue);
spin_unlock_irqrestore(&offload->skb_queue.lock, flags);
queue_len = skb_queue_len(&offload->skb_queue);
if (queue_len > offload->skb_queue_len_max / 8)
netdev_dbg(offload->dev, "%s: queue_len=%d\n",
__func__, queue_len);
local_bh_disable();
napi_schedule(&offload->napi);
local_bh_enable();
}
EXPORT_SYMBOL_GPL(can_rx_offload_threaded_irq_finish);
static int can_rx_offload_init_queue(struct net_device *dev,
struct can_rx_offload *offload,
unsigned int weight)
@ -312,6 +332,7 @@ static int can_rx_offload_init_queue(struct net_device *dev,
offload->skb_queue_len_max = 2 << fls(weight);
offload->skb_queue_len_max *= 4;
skb_queue_head_init(&offload->skb_queue);
__skb_queue_head_init(&offload->skb_irq_queue);
netif_napi_add(dev, &offload->napi, can_rx_offload_napi_poll, weight);
@ -373,5 +394,6 @@ void can_rx_offload_del(struct can_rx_offload *offload)
{
netif_napi_del(&offload->napi);
skb_queue_purge(&offload->skb_queue);
__skb_queue_purge(&offload->skb_irq_queue);
}
EXPORT_SYMBOL_GPL(can_rx_offload_del);

View File

@ -28,6 +28,7 @@
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
#include <linux/can/platform/flexcan.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
@ -208,18 +209,19 @@
/* FLEXCAN hardware feature flags
*
* Below is some version info we got:
* SOC Version IP-Version Glitch- [TR]WRN_INT IRQ Err Memory err RTR rece- FD Mode
* SOC Version IP-Version Glitch- [TR]WRN_INT IRQ Err Memory err RTR rece- FD Mode MB
* Filter? connected? Passive detection ption in MB Supported?
* MX25 FlexCAN2 03.00.00.00 no no no no no no
* MX28 FlexCAN2 03.00.04.00 yes yes no no no no
* MX35 FlexCAN2 03.00.00.00 no no no no no no
* MX53 FlexCAN2 03.00.00.00 yes no no no no no
* MX6s FlexCAN3 10.00.12.00 yes yes no no yes no
* MX8QM FlexCAN3 03.00.23.00 yes yes no no yes yes
* MX8MP FlexCAN3 03.00.17.01 yes yes no yes yes yes
* VF610 FlexCAN3 ? no yes no yes yes? no
* LS1021A FlexCAN2 03.00.04.00 no yes no no yes no
* LX2160A FlexCAN3 03.00.23.00 no yes no yes yes yes
* MCF5441X FlexCAN2 ? no yes no no yes no 16
* MX25 FlexCAN2 03.00.00.00 no no no no no no 64
* MX28 FlexCAN2 03.00.04.00 yes yes no no no no 64
* MX35 FlexCAN2 03.00.00.00 no no no no no no 64
* MX53 FlexCAN2 03.00.00.00 yes no no no no no 64
* MX6s FlexCAN3 10.00.12.00 yes yes no no yes no 64
* MX8QM FlexCAN3 03.00.23.00 yes yes no no yes yes 64
* MX8MP FlexCAN3 03.00.17.01 yes yes no yes yes yes 64
* VF610 FlexCAN3 ? no yes no yes yes? no 64
* LS1021A FlexCAN2 03.00.04.00 no yes no no yes no 64
* LX2160A FlexCAN3 03.00.23.00 no yes no yes yes yes 64
*
* Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected.
*/
@ -246,6 +248,10 @@
#define FLEXCAN_QUIRK_SUPPORT_ECC BIT(10)
/* Setup stop mode with SCU firmware to support wakeup */
#define FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW BIT(11)
/* Setup 3 separate interrupts, main, boff and err */
#define FLEXCAN_QUIRK_NR_IRQ_3 BIT(12)
/* Setup 16 mailboxes */
#define FLEXCAN_QUIRK_NR_MB_16 BIT(13)
/* Structure of the message buffer */
struct flexcan_mb {
@ -363,6 +369,9 @@ struct flexcan_priv {
struct regulator *reg_xceiver;
struct flexcan_stop_mode stm;
int irq_boff;
int irq_err;
/* IPC handle when setup stop mode by System Controller firmware(scfw) */
struct imx_sc_ipc *sc_ipc_handle;
@ -371,6 +380,11 @@ struct flexcan_priv {
void (*write)(u32 val, void __iomem *addr);
};
static const struct flexcan_devtype_data fsl_mcf5441x_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE |
FLEXCAN_QUIRK_NR_IRQ_3 | FLEXCAN_QUIRK_NR_MB_16,
};
static const struct flexcan_devtype_data fsl_p1010_devtype_data = {
.quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE |
@ -637,13 +651,17 @@ static int flexcan_clks_enable(const struct flexcan_priv *priv)
{
int err;
err = clk_prepare_enable(priv->clk_ipg);
if (err)
return err;
if (priv->clk_ipg) {
err = clk_prepare_enable(priv->clk_ipg);
if (err)
return err;
}
err = clk_prepare_enable(priv->clk_per);
if (err)
clk_disable_unprepare(priv->clk_ipg);
if (priv->clk_per) {
err = clk_prepare_enable(priv->clk_per);
if (err)
clk_disable_unprepare(priv->clk_ipg);
}
return err;
}
@ -1198,6 +1216,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
}
}
if (handled)
can_rx_offload_irq_finish(&priv->offload);
return handled;
}
@ -1401,8 +1422,12 @@ static int flexcan_rx_offload_setup(struct net_device *dev)
priv->mb_size = sizeof(struct flexcan_mb) + CANFD_MAX_DLEN;
else
priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
(sizeof(priv->regs->mb[1]) / priv->mb_size);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_MB_16)
priv->mb_count = 16;
else
priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
(sizeof(priv->regs->mb[1]) / priv->mb_size);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
priv->tx_mb_reserved =
@ -1774,6 +1799,18 @@ static int flexcan_open(struct net_device *dev)
if (err)
goto out_can_rx_offload_disable;
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
err = request_irq(priv->irq_boff,
flexcan_irq, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq;
err = request_irq(priv->irq_err,
flexcan_irq, IRQF_SHARED, dev->name, dev);
if (err)
goto out_free_irq_boff;
}
flexcan_chip_interrupts_enable(dev);
can_led_event(dev, CAN_LED_EVENT_OPEN);
@ -1782,6 +1819,10 @@ static int flexcan_open(struct net_device *dev)
return 0;
out_free_irq_boff:
free_irq(priv->irq_boff, dev);
out_free_irq:
free_irq(dev->irq, dev);
out_can_rx_offload_disable:
can_rx_offload_disable(&priv->offload);
flexcan_chip_stop(dev);
@ -1803,6 +1844,12 @@ static int flexcan_close(struct net_device *dev)
netif_stop_queue(dev);
flexcan_chip_interrupts_disable(dev);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
free_irq(priv->irq_err, dev);
free_irq(priv->irq_boff, dev);
}
free_irq(dev->irq, dev);
can_rx_offload_disable(&priv->offload);
flexcan_chip_stop_disable_on_error(dev);
@ -2039,14 +2086,26 @@ static const struct of_device_id flexcan_of_match[] = {
};
MODULE_DEVICE_TABLE(of, flexcan_of_match);
static const struct platform_device_id flexcan_id_table[] = {
{
.name = "flexcan-mcf5441x",
.driver_data = (kernel_ulong_t)&fsl_mcf5441x_devtype_data,
}, {
/* sentinel */
},
};
MODULE_DEVICE_TABLE(platform, flexcan_id_table);
static int flexcan_probe(struct platform_device *pdev)
{
const struct of_device_id *of_id;
const struct flexcan_devtype_data *devtype_data;
struct net_device *dev;
struct flexcan_priv *priv;
struct regulator *reg_xceiver;
struct clk *clk_ipg = NULL, *clk_per = NULL;
struct flexcan_regs __iomem *regs;
struct flexcan_platform_data *pdata;
int err, irq;
u8 clk_src = 1;
u32 clock_freq = 0;
@ -2064,6 +2123,12 @@ static int flexcan_probe(struct platform_device *pdev)
"clock-frequency", &clock_freq);
of_property_read_u8(pdev->dev.of_node,
"fsl,clk-source", &clk_src);
} else {
pdata = dev_get_platdata(&pdev->dev);
if (pdata) {
clock_freq = pdata->clock_frequency;
clk_src = pdata->clk_src;
}
}
if (!clock_freq) {
@ -2089,7 +2154,14 @@ static int flexcan_probe(struct platform_device *pdev)
if (IS_ERR(regs))
return PTR_ERR(regs);
devtype_data = of_device_get_match_data(&pdev->dev);
of_id = of_match_device(flexcan_of_match, &pdev->dev);
if (of_id)
devtype_data = of_id->data;
else if (platform_get_device_id(pdev)->driver_data)
devtype_data = (struct flexcan_devtype_data *)
platform_get_device_id(pdev)->driver_data;
else
return -ENODEV;
if ((devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) &&
!(devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)) {
@ -2133,6 +2205,19 @@ static int flexcan_probe(struct platform_device *pdev)
priv->devtype_data = devtype_data;
priv->reg_xceiver = reg_xceiver;
if (devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
priv->irq_boff = platform_get_irq(pdev, 1);
if (priv->irq_boff <= 0) {
err = -ENODEV;
goto failed_platform_get_irq;
}
priv->irq_err = platform_get_irq(pdev, 2);
if (priv->irq_err <= 0) {
err = -ENODEV;
goto failed_platform_get_irq;
}
}
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) {
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
CAN_CTRLMODE_FD_NON_ISO;
@ -2170,6 +2255,7 @@ static int flexcan_probe(struct platform_device *pdev)
failed_register:
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
failed_platform_get_irq:
free_candev(dev);
return err;
}
@ -2322,6 +2408,7 @@ static struct platform_driver flexcan_driver = {
},
.probe = flexcan_probe,
.remove = flexcan_remove,
.id_table = flexcan_id_table,
};
module_platform_driver(flexcan_driver);

View File

@ -1815,9 +1815,9 @@ static int ican3_get_berr_counter(const struct net_device *ndev,
* Sysfs Attributes
*/
static ssize_t ican3_sysfs_show_term(struct device *dev,
struct device_attribute *attr,
char *buf)
static ssize_t termination_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
int ret;
@ -1834,9 +1834,9 @@ static ssize_t ican3_sysfs_show_term(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%u\n", mod->termination_enabled);
}
static ssize_t ican3_sysfs_set_term(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
static ssize_t termination_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
unsigned long enable;
@ -1852,18 +1852,17 @@ static ssize_t ican3_sysfs_set_term(struct device *dev,
return count;
}
static ssize_t ican3_sysfs_show_fwinfo(struct device *dev,
struct device_attribute *attr,
char *buf)
static ssize_t fwinfo_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct ican3_dev *mod = netdev_priv(to_net_dev(dev));
return scnprintf(buf, PAGE_SIZE, "%s\n", mod->fwinfo);
}
static DEVICE_ATTR(termination, 0644, ican3_sysfs_show_term,
ican3_sysfs_set_term);
static DEVICE_ATTR(fwinfo, 0444, ican3_sysfs_show_fwinfo, NULL);
static DEVICE_ATTR_RW(termination);
static DEVICE_ATTR_RO(fwinfo);
static struct attribute *ican3_sysfs_attrs[] = {
&dev_attr_termination.attr,

View File

@ -21,6 +21,7 @@
#include <linux/iopoll.h>
#include <linux/can/dev.h>
#include <linux/pinctrl/consumer.h>
#include <linux/phy/phy.h>
#include "m_can.h"
@ -1058,6 +1059,9 @@ static irqreturn_t m_can_isr(int irq, void *dev_id)
}
}
if (cdev->is_peripheral)
can_rx_offload_threaded_irq_finish(&cdev->offload);
return IRQ_HANDLED;
}
@ -1436,32 +1440,20 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
case 30:
/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.0.x */
can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
cdev->can.bittiming_const = cdev->bit_timing ?
cdev->bit_timing : &m_can_bittiming_const_30X;
cdev->can.data_bittiming_const = cdev->data_timing ?
cdev->data_timing :
&m_can_data_bittiming_const_30X;
cdev->can.bittiming_const = &m_can_bittiming_const_30X;
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_30X;
break;
case 31:
/* CAN_CTRLMODE_FD_NON_ISO is fixed with M_CAN IP v3.1.x */
can_set_static_ctrlmode(dev, CAN_CTRLMODE_FD_NON_ISO);
cdev->can.bittiming_const = cdev->bit_timing ?
cdev->bit_timing : &m_can_bittiming_const_31X;
cdev->can.data_bittiming_const = cdev->data_timing ?
cdev->data_timing :
&m_can_data_bittiming_const_31X;
cdev->can.bittiming_const = &m_can_bittiming_const_31X;
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
break;
case 32:
case 33:
/* Support both MCAN version v3.2.x and v3.3.0 */
cdev->can.bittiming_const = cdev->bit_timing ?
cdev->bit_timing : &m_can_bittiming_const_31X;
cdev->can.data_bittiming_const = cdev->data_timing ?
cdev->data_timing :
&m_can_data_bittiming_const_31X;
cdev->can.bittiming_const = &m_can_bittiming_const_31X;
cdev->can.data_bittiming_const = &m_can_data_bittiming_const_31X;
cdev->can.ctrlmode_supported |=
(m_can_niso_supported(cdev) ?
@ -1518,6 +1510,8 @@ static int m_can_close(struct net_device *dev)
close_candev(dev);
can_led_event(dev, CAN_LED_EVENT_STOP);
phy_power_off(cdev->transceiver);
return 0;
}
@ -1703,10 +1697,14 @@ static int m_can_open(struct net_device *dev)
struct m_can_classdev *cdev = netdev_priv(dev);
int err;
err = m_can_clk_start(cdev);
err = phy_power_on(cdev->transceiver);
if (err)
return err;
err = m_can_clk_start(cdev);
if (err)
goto out_phy_power_off;
/* open the can device */
err = open_candev(dev);
if (err) {
@ -1763,6 +1761,8 @@ out_wq_fail:
close_candev(dev);
exit_disable_clks:
m_can_clk_stop(cdev);
out_phy_power_off:
phy_power_off(cdev->transceiver);
return err;
}

View File

@ -28,6 +28,7 @@
#include <linux/iopoll.h>
#include <linux/can/dev.h>
#include <linux/pinctrl/consumer.h>
#include <linux/phy/phy.h>
/* m_can lec values */
enum m_can_lec_type {
@ -82,9 +83,7 @@ struct m_can_classdev {
struct workqueue_struct *tx_wq;
struct work_struct tx_work;
struct sk_buff *tx_skb;
struct can_bittiming_const *bit_timing;
struct can_bittiming_const *data_timing;
struct phy *transceiver;
struct m_can_ops *ops;

View File

@ -6,6 +6,7 @@
// Copyright (C) 2018-19 Texas Instruments Incorporated - http://www.ti.com/
#include <linux/platform_device.h>
#include <linux/phy/phy.h>
#include "m_can.h"
@ -67,6 +68,7 @@ static int m_can_plat_probe(struct platform_device *pdev)
struct resource *res;
void __iomem *addr;
void __iomem *mram_addr;
struct phy *transceiver;
int irq, ret = 0;
mcan_class = m_can_class_allocate_dev(&pdev->dev,
@ -80,8 +82,7 @@ static int m_can_plat_probe(struct platform_device *pdev)
if (ret)
goto probe_fail;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "m_can");
addr = devm_ioremap_resource(&pdev->dev, res);
addr = devm_platform_ioremap_resource_byname(pdev, "m_can");
irq = platform_get_irq_byname(pdev, "int0");
if (IS_ERR(addr) || irq < 0) {
ret = -EINVAL;
@ -101,6 +102,16 @@ static int m_can_plat_probe(struct platform_device *pdev)
goto probe_fail;
}
transceiver = devm_phy_optional_get(&pdev->dev, NULL);
if (IS_ERR(transceiver)) {
ret = PTR_ERR(transceiver);
dev_err_probe(&pdev->dev, ret, "failed to get phy\n");
goto probe_fail;
}
if (transceiver)
mcan_class->can.bitrate_max = transceiver->attrs.max_link_rate;
priv->base = addr;
priv->mram_base = mram_addr;
@ -108,6 +119,7 @@ static int m_can_plat_probe(struct platform_device *pdev)
mcan_class->pm_clock_support = 1;
mcan_class->can.clock.freq = clk_get_rate(mcan_class->cclk);
mcan_class->dev = &pdev->dev;
mcan_class->transceiver = transceiver;
mcan_class->ops = &m_can_plat_ops;

View File

@ -28,6 +28,10 @@ MODULE_LICENSE("GPL v2");
#define DRV_NAME "peak_pci"
/* FPGA cards FW version registers */
#define PEAK_VER_REG1 0x40
#define PEAK_VER_REG2 0x44
struct peak_pciec_card;
struct peak_pci_chan {
void __iomem *cfg_base; /* Common for all channels */
@ -41,9 +45,7 @@ struct peak_pci_chan {
#define PEAK_PCI_CDR (CDR_CBP | CDR_CLKOUT_MASK)
#define PEAK_PCI_OCR OCR_TX0_PUSHPULL
/*
* Important PITA registers
*/
/* Important PITA registers */
#define PITA_ICR 0x00 /* Interrupt control register */
#define PITA_GPIOICR 0x18 /* GPIO interface control register */
#define PITA_MISC 0x1C /* Miscellaneous register */
@ -70,27 +72,47 @@ static const u16 peak_pci_icr_masks[PEAK_PCI_CHAN_MAX] = {
};
static const struct pci_device_id peak_pci_tbl[] = {
{PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,},
{
PEAK_PCI_VENDOR_ID, PEAK_PCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-PCI",
}, {
PEAK_PCI_VENDOR_ID, PEAK_PCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-PCI Express",
}, {
PEAK_PCI_VENDOR_ID, PEAK_MPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-miniPCI",
}, {
PEAK_PCI_VENDOR_ID, PEAK_MPCIE_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-miniPCIe",
}, {
PEAK_PCI_VENDOR_ID, PEAK_PC_104P_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-PC/104-Plus Quad",
}, {
PEAK_PCI_VENDOR_ID, PEAK_PCI_104E_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-PCI/104-Express",
}, {
PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-cPCI",
}, {
PEAK_PCI_VENDOR_ID, PEAK_PCIE_OEM_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-Chip PCIe",
},
#ifdef CONFIG_CAN_PEAK_PCIEC
{PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
{
PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-ExpressCard",
}, {
PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
.driver_data = (kernel_ulong_t)"PCAN-ExpressCard 34",
},
#endif
{0,}
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(pci, peak_pci_tbl);
#ifdef CONFIG_CAN_PEAK_PCIEC
/*
* PCAN-ExpressCard needs I2C bit-banging configuration option.
*/
/* PCAN-ExpressCard needs I2C bit-banging configuration option. */
/* GPIOICR byte access offsets */
#define PITA_GPOUT 0x18 /* GPx output value */
@ -156,12 +178,14 @@ static void peak_pci_write_reg(const struct sja1000_priv *priv,
static inline void pita_set_scl_highz(struct peak_pciec_card *card)
{
u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SCL;
writeb(gp_outen, card->cfg_base + PITA_GPOEN);
}
static inline void pita_set_sda_highz(struct peak_pciec_card *card)
{
u8 gp_outen = readb(card->cfg_base + PITA_GPOEN) & ~PITA_GPIN_SDA;
writeb(gp_outen, card->cfg_base + PITA_GPOEN);
}
@ -230,9 +254,7 @@ static int pita_getscl(void *data)
return (readb(card->cfg_base + PITA_GPIN) & PITA_GPIN_SCL) ? 1 : 0;
}
/*
* write commands to the LED chip though the I2C-bus of the PCAN-PCIeC
*/
/* write commands to the LED chip though the I2C-bus of the PCAN-PCIeC */
static int peak_pciec_write_pca9553(struct peak_pciec_card *card,
u8 offset, u8 data)
{
@ -248,7 +270,7 @@ static int peak_pciec_write_pca9553(struct peak_pciec_card *card,
int ret;
/* cache led mask */
if ((offset == 5) && (data == card->led_cache))
if (offset == 5 && data == card->led_cache)
return 0;
ret = i2c_transfer(&card->led_chip, &msg, 1);
@ -261,9 +283,7 @@ static int peak_pciec_write_pca9553(struct peak_pciec_card *card,
return 0;
}
/*
* delayed work callback used to control the LEDs
*/
/* delayed work callback used to control the LEDs */
static void peak_pciec_led_work(struct work_struct *work)
{
struct peak_pciec_card *card =
@ -309,9 +329,7 @@ static void peak_pciec_led_work(struct work_struct *work)
schedule_delayed_work(&card->led_work, HZ);
}
/*
* set LEDs blinking state
*/
/* set LEDs blinking state */
static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s)
{
u8 new_led = card->led_cache;
@ -328,25 +346,19 @@ static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s)
peak_pciec_write_pca9553(card, 5, new_led);
}
/*
* start one second delayed work to control LEDs
*/
/* start one second delayed work to control LEDs */
static void peak_pciec_start_led_work(struct peak_pciec_card *card)
{
schedule_delayed_work(&card->led_work, HZ);
}
/*
* stop LEDs delayed work
*/
/* stop LEDs delayed work */
static void peak_pciec_stop_led_work(struct peak_pciec_card *card)
{
cancel_delayed_work_sync(&card->led_work);
}
/*
* initialize the PCA9553 4-bit I2C-bus LED chip
*/
/* initialize the PCA9553 4-bit I2C-bus LED chip */
static int peak_pciec_init_leds(struct peak_pciec_card *card)
{
int err;
@ -375,17 +387,14 @@ static int peak_pciec_init_leds(struct peak_pciec_card *card)
return peak_pciec_write_pca9553(card, 5, PCA9553_LS0_INIT);
}
/*
* restore LEDs state to off peak_pciec_leds_exit
*/
/* restore LEDs state to off peak_pciec_leds_exit */
static void peak_pciec_leds_exit(struct peak_pciec_card *card)
{
/* switch LEDs to off */
peak_pciec_write_pca9553(card, 5, PCA9553_LED_OFF_ALL);
}
/*
* normal write sja1000 register method overloaded to catch when controller
/* normal write sja1000 register method overloaded to catch when controller
* is started or stopped, to control leds
*/
static void peak_pciec_write_reg(const struct sja1000_priv *priv,
@ -443,7 +452,7 @@ static int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev)
/* channel is the first one: do the init part */
} else {
/* create the bit banging I2C adapter structure */
card = kzalloc(sizeof(struct peak_pciec_card), GFP_KERNEL);
card = kzalloc(sizeof(*card), GFP_KERNEL);
if (!card)
return -ENOMEM;
@ -506,9 +515,7 @@ static void peak_pciec_remove(struct peak_pciec_card *card)
#else /* CONFIG_CAN_PEAK_PCIEC */
/*
* Placebo functions when PCAN-ExpressCard support is not selected
*/
/* Placebo functions when PCAN-ExpressCard support is not selected */
static inline int peak_pciec_probe(struct pci_dev *pdev, struct net_device *dev)
{
return -ENODEV;
@ -549,6 +556,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
void __iomem *cfg_base, *reg_base;
u16 sub_sys_id, icr;
int i, err, channels;
char fw_str[14] = "";
err = pci_enable_device(pdev);
if (err)
@ -602,6 +610,21 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Leave parport mux mode */
writeb(0x04, cfg_base + PITA_MISC + 3);
/* FPGA equipped card if not 0 */
if (readl(cfg_base + PEAK_VER_REG1)) {
/* FPGA card: display version of the running firmware */
u32 fw_ver = readl(cfg_base + PEAK_VER_REG2);
snprintf(fw_str, sizeof(fw_str), " FW v%u.%u.%u",
(fw_ver >> 12) & 0xf,
(fw_ver >> 8) & 0xf,
(fw_ver >> 4) & 0xf);
}
/* Display commercial name (and, eventually, FW version) of the card */
dev_info(&pdev->dev, "%ux CAN %s%s\n",
channels, (const char *)ent->driver_data, fw_str);
icr = readw(cfg_base + PITA_ICR + 2);
for (i = 0; i < channels; i++) {
@ -642,8 +665,7 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
chan->prev_dev = pci_get_drvdata(pdev);
pci_set_drvdata(pdev, dev);
/*
* PCAN-ExpressCard needs some additional i2c init.
/* PCAN-ExpressCard needs some additional i2c init.
* This must be done *before* register_sja1000dev() but
* *after* devices linkage
*/
@ -709,7 +731,8 @@ failure_disable_pci:
/* pci_xxx_config_word() return positive PCIBIOS_xxx error codes while
* the probe() function must return a negative errno in case of failure
* (err is unchanged if negative) */
* (err is unchanged if negative)
*/
return pcibios_err_to_errno(err);
}

View File

@ -15,10 +15,10 @@
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
#include <asm/unaligned.h>
@ -2195,8 +2195,10 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
FIELD_GET(MCP251XFD_REG_INT_IE_MASK,
priv->regs_status.intf);
if (!(intf_pending))
if (!(intf_pending)) {
can_rx_offload_threaded_irq_finish(&priv->offload);
return handled;
}
/* Some interrupts must be ACKed in the
* MCP251XFD_REG_INT register.
@ -2296,6 +2298,8 @@ static irqreturn_t mcp251xfd_irq(int irq, void *dev_id)
} while (1);
out_fail:
can_rx_offload_threaded_irq_finish(&priv->offload);
netdev_err(priv->ndev, "IRQ handler returned %d (intf=0x%08x).\n",
err, priv->regs_status.intf);
mcp251xfd_dump(priv);
@ -2523,8 +2527,8 @@ static int mcp251xfd_open(struct net_device *ndev)
can_rx_offload_enable(&priv->offload);
err = request_threaded_irq(spi->irq, NULL, mcp251xfd_irq,
IRQF_ONESHOT, dev_name(&spi->dev),
priv);
IRQF_SHARED | IRQF_ONESHOT,
dev_name(&spi->dev), priv);
if (err)
goto out_can_rx_offload_disable;
@ -2856,7 +2860,7 @@ static int mcp251xfd_probe(struct spi_device *spi)
struct gpio_desc *rx_int;
struct regulator *reg_vdd, *reg_xceiver;
struct clk *clk;
u32 freq;
u32 freq = 0;
int err;
if (!spi->irq)
@ -2883,11 +2887,19 @@ static int mcp251xfd_probe(struct spi_device *spi)
return dev_err_probe(&spi->dev, PTR_ERR(reg_xceiver),
"Failed to get Transceiver regulator!\n");
clk = devm_clk_get(&spi->dev, NULL);
clk = devm_clk_get_optional(&spi->dev, NULL);
if (IS_ERR(clk))
return dev_err_probe(&spi->dev, PTR_ERR(clk),
"Failed to get Oscillator (clock)!\n");
freq = clk_get_rate(clk);
if (clk) {
freq = clk_get_rate(clk);
} else {
err = device_property_read_u32(&spi->dev, "clock-frequency",
&freq);
if (err)
return dev_err_probe(&spi->dev, err,
"Failed to get clock-frequency!\n");
}
/* Sanity check */
if (freq < MCP251XFD_SYSCLOCK_HZ_MIN ||

View File

@ -786,6 +786,8 @@ static irqreturn_t ti_hecc_interrupt(int irq, void *dev_id)
int_status = hecc_read(priv, HECC_CANGIF0);
}
can_rx_offload_irq_finish(&priv->offload);
return IRQ_HANDLED;
}

View File

@ -474,7 +474,7 @@ static void esd_usb2_write_bulk_callback(struct urb *urb)
netif_trans_update(netdev);
}
static ssize_t show_firmware(struct device *d,
static ssize_t firmware_show(struct device *d,
struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(d);
@ -485,9 +485,9 @@ static ssize_t show_firmware(struct device *d,
(dev->version >> 8) & 0xf,
dev->version & 0xff);
}
static DEVICE_ATTR(firmware, 0444, show_firmware, NULL);
static DEVICE_ATTR_RO(firmware);
static ssize_t show_hardware(struct device *d,
static ssize_t hardware_show(struct device *d,
struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(d);
@ -498,9 +498,9 @@ static ssize_t show_hardware(struct device *d,
(dev->version >> 24) & 0xf,
(dev->version >> 16) & 0xff);
}
static DEVICE_ATTR(hardware, 0444, show_hardware, NULL);
static DEVICE_ATTR_RO(hardware);
static ssize_t show_nets(struct device *d,
static ssize_t nets_show(struct device *d,
struct device_attribute *attr, char *buf)
{
struct usb_interface *intf = to_usb_interface(d);
@ -508,7 +508,7 @@ static ssize_t show_nets(struct device *d,
return sprintf(buf, "%d", dev->net_count);
}
static DEVICE_ATTR(nets, 0444, show_nets, NULL);
static DEVICE_ATTR_RO(nets);
static int esd_usb2_send_msg(struct esd_usb2 *dev, struct esd_usb2_msg *msg)
{

View File

@ -355,7 +355,7 @@ static int es581_4_tx_can_msg(struct es58x_priv *priv,
return -EMSGSIZE;
if (priv->tx_can_msg_cnt == 0) {
msg_len = 1; /* struct es581_4_bulk_tx_can_msg:num_can_msg */
msg_len = sizeof(es581_4_urb_cmd->bulk_tx_can_msg.num_can_msg);
es581_4_fill_urb_header(urb_cmd, ES581_4_CAN_COMMAND_TYPE,
ES581_4_CMD_ID_TX_MSG,
priv->channel_idx, msg_len);
@ -371,8 +371,7 @@ static int es581_4_tx_can_msg(struct es58x_priv *priv,
return ret;
/* Fill message contents. */
tx_can_msg = (struct es581_4_tx_can_msg *)
&es581_4_urb_cmd->bulk_tx_can_msg.tx_can_msg_buf[msg_len - 1];
tx_can_msg = (typeof(tx_can_msg))&es581_4_urb_cmd->raw_msg[msg_len];
put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id);
put_unaligned_le32(priv->tx_head, &tx_can_msg->packet_idx);
put_unaligned_le16((u16)es58x_get_flags(skb), &tx_can_msg->flags);

View File

@ -19,7 +19,7 @@
#include "es58x_core.h"
#define DRV_VERSION "1.00"
MODULE_AUTHOR("Mailhol Vincent <mailhol.vincent@wanadoo.fr>");
MODULE_AUTHOR("Vincent Mailhol <mailhol.vincent@wanadoo.fr>");
MODULE_AUTHOR("Arunachalam Santhanam <arunachalam.santhanam@in.bosch.com>");
MODULE_DESCRIPTION("Socket CAN driver for ETAS ES58X USB adapters");
MODULE_VERSION(DRV_VERSION);
@ -70,7 +70,7 @@ MODULE_DEVICE_TABLE(usb, es58x_id_table);
* bytes (the start of frame) are skipped and the CRC calculation
* starts on the third byte.
*/
#define ES58X_CRC_CALC_OFFSET 2
#define ES58X_CRC_CALC_OFFSET sizeof_field(union es58x_urb_cmd, sof)
/**
* es58x_calculate_crc() - Compute the crc16 of a given URB.
@ -2107,6 +2107,25 @@ static int es58x_init_netdev(struct es58x_device *es58x_dev, int channel_idx)
return ret;
}
/**
* es58x_free_netdevs() - Release all network resources of the device.
* @es58x_dev: ES58X device.
*/
static void es58x_free_netdevs(struct es58x_device *es58x_dev)
{
int i;
for (i = 0; i < es58x_dev->num_can_ch; i++) {
struct net_device *netdev = es58x_dev->netdev[i];
if (!netdev)
continue;
unregister_candev(netdev);
es58x_dev->netdev[i] = NULL;
free_candev(netdev);
}
}
/**
* es58x_get_product_info() - Get the product information and print them.
* @es58x_dev: ES58X device.
@ -2152,14 +2171,13 @@ static int es58x_get_product_info(struct es58x_device *es58x_dev)
/**
* es58x_init_es58x_dev() - Initialize the ES58X device.
* @intf: USB interface.
* @p_es58x_dev: pointer to the address of the ES58X device.
* @driver_info: Quirks of the device.
*
* Return: zero on success, errno when any error occurs.
* Return: pointer to an ES58X device on success, error pointer when
* any error occurs.
*/
static int es58x_init_es58x_dev(struct usb_interface *intf,
struct es58x_device **p_es58x_dev,
kernel_ulong_t driver_info)
static struct es58x_device *es58x_init_es58x_dev(struct usb_interface *intf,
kernel_ulong_t driver_info)
{
struct device *dev = &intf->dev;
struct es58x_device *es58x_dev;
@ -2176,7 +2194,7 @@ static int es58x_init_es58x_dev(struct usb_interface *intf,
ret = usb_find_common_endpoints(intf->cur_altsetting, &ep_in, &ep_out,
NULL, NULL);
if (ret)
return ret;
return ERR_PTR(ret);
if (driver_info & ES58X_FD_FAMILY) {
param = &es58x_fd_param;
@ -2186,9 +2204,10 @@ static int es58x_init_es58x_dev(struct usb_interface *intf,
ops = &es581_4_ops;
}
es58x_dev = kzalloc(es58x_sizeof_es58x_device(param), GFP_KERNEL);
es58x_dev = devm_kzalloc(dev, es58x_sizeof_es58x_device(param),
GFP_KERNEL);
if (!es58x_dev)
return -ENOMEM;
return ERR_PTR(-ENOMEM);
es58x_dev->param = param;
es58x_dev->ops = ops;
@ -2213,9 +2232,7 @@ static int es58x_init_es58x_dev(struct usb_interface *intf,
ep_out->bEndpointAddress);
es58x_dev->rx_max_packet_size = le16_to_cpu(ep_in->wMaxPacketSize);
*p_es58x_dev = es58x_dev;
return 0;
return es58x_dev;
}
/**
@ -2232,30 +2249,21 @@ static int es58x_probe(struct usb_interface *intf,
struct es58x_device *es58x_dev;
int ch_idx, ret;
ret = es58x_init_es58x_dev(intf, &es58x_dev, id->driver_info);
if (ret)
return ret;
es58x_dev = es58x_init_es58x_dev(intf, id->driver_info);
if (IS_ERR(es58x_dev))
return PTR_ERR(es58x_dev);
ret = es58x_get_product_info(es58x_dev);
if (ret)
goto cleanup_es58x_dev;
return ret;
for (ch_idx = 0; ch_idx < es58x_dev->num_can_ch; ch_idx++) {
ret = es58x_init_netdev(es58x_dev, ch_idx);
if (ret)
goto cleanup_candev;
}
return ret;
cleanup_candev:
for (ch_idx = 0; ch_idx < es58x_dev->num_can_ch; ch_idx++)
if (es58x_dev->netdev[ch_idx]) {
unregister_candev(es58x_dev->netdev[ch_idx]);
free_candev(es58x_dev->netdev[ch_idx]);
if (ret) {
es58x_free_netdevs(es58x_dev);
return ret;
}
cleanup_es58x_dev:
kfree(es58x_dev);
}
return ret;
}
@ -2270,24 +2278,12 @@ static int es58x_probe(struct usb_interface *intf,
static void es58x_disconnect(struct usb_interface *intf)
{
struct es58x_device *es58x_dev = usb_get_intfdata(intf);
struct net_device *netdev;
int i;
dev_info(&intf->dev, "Disconnecting %s %s\n",
es58x_dev->udev->manufacturer, es58x_dev->udev->product);
for (i = 0; i < es58x_dev->num_can_ch; i++) {
netdev = es58x_dev->netdev[i];
if (!netdev)
continue;
unregister_candev(netdev);
es58x_dev->netdev[i] = NULL;
free_candev(netdev);
}
es58x_free_netdevs(es58x_dev);
es58x_free_urbs(es58x_dev);
kfree(es58x_dev);
usb_set_intfdata(intf, NULL);
}

View File

@ -287,7 +287,7 @@ struct es58x_priv {
* @rx_urb_cmd_max_len: Maximum length of a RX URB command.
* @fifo_mask: Bit mask to quickly convert the tx_tail and tx_head
* field of the struct es58x_priv into echo_skb
* indexes. Properties: @fifo_mask = echos_skb_max - 1 where
* indexes. Properties: @fifo_mask = echo_skb_max - 1 where
* echo_skb_max must be a power of two. Also, echo_skb_max must
* not exceed the maximum size of the device internal TX FIFO
* length. This parameter is used to control the network queue

View File

@ -357,8 +357,7 @@ static int es58x_fd_tx_can_msg(struct es58x_priv *priv,
return ret;
/* Fill message contents. */
tx_can_msg = (struct es58x_fd_tx_can_msg *)
&es58x_fd_urb_cmd->tx_can_msg_buf[msg_len];
tx_can_msg = (typeof(tx_can_msg))&es58x_fd_urb_cmd->raw_msg[msg_len];
tx_can_msg->packet_idx = (u8)priv->tx_head;
put_unaligned_le32(es58x_get_raw_can_id(cf), &tx_can_msg->can_id);
tx_can_msg->flags = (u8)es58x_get_flags(skb);
@ -463,9 +462,9 @@ static int es58x_fd_get_timestamp(struct es58x_device *es58x_dev)
}
/* Nominal bittiming constants for ES582.1 and ES584.1 as specified in
* the microcontroller datasheet: "SAM E701/S70/V70/V71 Family"
* section 49.6.8 "MCAN Nominal Bit Timing and Prescaler Register"
* from Microchip.
* the microcontroller datasheet: "SAM E70/S70/V70/V71 Family" section
* 49.6.8 "MCAN Nominal Bit Timing and Prescaler Register" from
* Microchip.
*
* The values from the specification are the hardware register
* values. To convert them to the functional values, all ranges were
@ -484,8 +483,8 @@ static const struct can_bittiming_const es58x_fd_nom_bittiming_const = {
};
/* Data bittiming constants for ES582.1 and ES584.1 as specified in
* the microcontroller datasheet: "SAM E701/S70/V70/V71 Family"
* section 49.6.4 "MCAN Data Bit Timing and Prescaler Register" from
* the microcontroller datasheet: "SAM E70/S70/V70/V71 Family" section
* 49.6.4 "MCAN Data Bit Timing and Prescaler Register" from
* Microchip.
*/
static const struct can_bittiming_const es58x_fd_data_bittiming_const = {
@ -501,9 +500,9 @@ static const struct can_bittiming_const es58x_fd_data_bittiming_const = {
};
/* Transmission Delay Compensation constants for ES582.1 and ES584.1
* as specified in the microcontroller datasheet: "SAM
* E701/S70/V70/V71 Family" section 49.6.15 "MCAN Transmitter Delay
* Compensation Register" from Microchip.
* as specified in the microcontroller datasheet: "SAM E70/S70/V70/V71
* Family" section 49.6.15 "MCAN Transmitter Delay Compensation
* Register" from Microchip.
*/
static const struct can_tdc_const es58x_tdc_const = {
.tdcv_max = 0, /* Manual mode not supported. */

View File

@ -63,6 +63,8 @@
#define PCAN_USB_MSG_HEADER_LEN 2
#define PCAN_USB_MSG_TX_CAN 2 /* Tx msg is a CAN frame */
/* PCAN-USB adapter internal clock (MHz) */
#define PCAN_USB_CRYSTAL_HZ 16000000
@ -73,6 +75,10 @@
#define PCAN_USB_STATUSLEN_RTR (1 << 4)
#define PCAN_USB_STATUSLEN_DLC (0xf)
/* PCAN-USB 4.1 CAN Id tx extended flags */
#define PCAN_USB_TX_SRR 0x01 /* SJA1000 SRR command */
#define PCAN_USB_TX_AT 0x02 /* SJA1000 AT command */
/* PCAN-USB error flags */
#define PCAN_USB_ERROR_TXFULL 0x01
#define PCAN_USB_ERROR_RXQOVR 0x02
@ -384,7 +390,8 @@ static int pcan_usb_get_device_id(struct peak_usb_device *dev, u32 *device_id)
if (err)
netdev_err(dev->netdev, "getting device id failure: %d\n", err);
*device_id = args[0];
else
*device_id = args[0];
return err;
}
@ -445,145 +452,65 @@ static int pcan_usb_decode_error(struct pcan_usb_msg_context *mc, u8 n,
{
struct sk_buff *skb;
struct can_frame *cf;
enum can_state new_state;
enum can_state new_state = CAN_STATE_ERROR_ACTIVE;
/* ignore this error until 1st ts received */
if (n == PCAN_USB_ERROR_QOVR)
if (!mc->pdev->time_ref.tick_count)
return 0;
new_state = mc->pdev->dev.can.state;
switch (mc->pdev->dev.can.state) {
case CAN_STATE_ERROR_ACTIVE:
if (n & PCAN_USB_ERROR_BUS_LIGHT) {
new_state = CAN_STATE_ERROR_WARNING;
break;
}
fallthrough;
case CAN_STATE_ERROR_WARNING:
if (n & PCAN_USB_ERROR_BUS_HEAVY) {
new_state = CAN_STATE_ERROR_PASSIVE;
break;
}
if (n & PCAN_USB_ERROR_BUS_OFF) {
new_state = CAN_STATE_BUS_OFF;
break;
}
if (n & ~PCAN_USB_ERROR_BUS) {
/*
* trick to bypass next comparison and process other
* errors
*/
new_state = CAN_STATE_MAX;
break;
}
if ((n & PCAN_USB_ERROR_BUS_LIGHT) == 0) {
/* no error (back to active state) */
new_state = CAN_STATE_ERROR_ACTIVE;
break;
}
break;
case CAN_STATE_ERROR_PASSIVE:
if (n & PCAN_USB_ERROR_BUS_OFF) {
new_state = CAN_STATE_BUS_OFF;
break;
}
if (n & PCAN_USB_ERROR_BUS_LIGHT) {
new_state = CAN_STATE_ERROR_WARNING;
break;
}
if (n & ~PCAN_USB_ERROR_BUS) {
/*
* trick to bypass next comparison and process other
* errors
*/
new_state = CAN_STATE_MAX;
break;
}
if ((n & PCAN_USB_ERROR_BUS_HEAVY) == 0) {
/* no error (back to warning state) */
new_state = CAN_STATE_ERROR_WARNING;
break;
}
break;
default:
/* do nothing waiting for restart */
return 0;
}
/* donot post any error if current state didn't change */
if (mc->pdev->dev.can.state == new_state)
return 0;
/* allocate an skb to store the error frame */
skb = alloc_can_err_skb(mc->netdev, &cf);
if (!skb)
return -ENOMEM;
switch (new_state) {
case CAN_STATE_BUS_OFF:
cf->can_id |= CAN_ERR_BUSOFF;
mc->pdev->dev.can.can_stats.bus_off++;
can_bus_off(mc->netdev);
break;
case CAN_STATE_ERROR_PASSIVE:
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (mc->pdev->bec.txerr > mc->pdev->bec.rxerr) ?
CAN_ERR_CRTL_TX_PASSIVE :
CAN_ERR_CRTL_RX_PASSIVE;
cf->data[6] = mc->pdev->bec.txerr;
cf->data[7] = mc->pdev->bec.rxerr;
mc->pdev->dev.can.can_stats.error_passive++;
break;
case CAN_STATE_ERROR_WARNING:
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (mc->pdev->bec.txerr > mc->pdev->bec.rxerr) ?
CAN_ERR_CRTL_TX_WARNING :
CAN_ERR_CRTL_RX_WARNING;
cf->data[6] = mc->pdev->bec.txerr;
cf->data[7] = mc->pdev->bec.rxerr;
mc->pdev->dev.can.can_stats.error_warning++;
break;
case CAN_STATE_ERROR_ACTIVE:
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = CAN_ERR_CRTL_ACTIVE;
/* sync local copies of rxerr/txerr counters */
mc->pdev->bec.txerr = 0;
mc->pdev->bec.rxerr = 0;
break;
default:
/* CAN_STATE_MAX (trick to handle other errors) */
if (n & PCAN_USB_ERROR_TXQFULL)
netdev_dbg(mc->netdev, "device Tx queue full)\n");
if (n & PCAN_USB_ERROR_RXQOVR) {
netdev_dbg(mc->netdev, "data overrun interrupt\n");
if (n & PCAN_USB_ERROR_RXQOVR) {
/* data overrun interrupt */
netdev_dbg(mc->netdev, "data overrun interrupt\n");
mc->netdev->stats.rx_over_errors++;
mc->netdev->stats.rx_errors++;
if (cf) {
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
mc->netdev->stats.rx_over_errors++;
mc->netdev->stats.rx_errors++;
}
cf->data[6] = mc->pdev->bec.txerr;
cf->data[7] = mc->pdev->bec.rxerr;
new_state = mc->pdev->dev.can.state;
break;
}
mc->pdev->dev.can.state = new_state;
if (n & PCAN_USB_ERROR_TXQFULL)
netdev_dbg(mc->netdev, "device Tx queue full)\n");
if (n & PCAN_USB_ERROR_BUS_OFF) {
new_state = CAN_STATE_BUS_OFF;
} else if (n & PCAN_USB_ERROR_BUS_HEAVY) {
new_state = ((mc->pdev->bec.txerr >= 128) ||
(mc->pdev->bec.rxerr >= 128)) ?
CAN_STATE_ERROR_PASSIVE :
CAN_STATE_ERROR_WARNING;
} else {
new_state = CAN_STATE_ERROR_ACTIVE;
}
/* handle change of state */
if (new_state != mc->pdev->dev.can.state) {
enum can_state tx_state =
(mc->pdev->bec.txerr >= mc->pdev->bec.rxerr) ?
new_state : 0;
enum can_state rx_state =
(mc->pdev->bec.txerr <= mc->pdev->bec.rxerr) ?
new_state : 0;
can_change_state(mc->netdev, cf, tx_state, rx_state);
if (new_state == CAN_STATE_BUS_OFF) {
can_bus_off(mc->netdev);
} else if (cf && (cf->can_id & CAN_ERR_CRTL)) {
/* Supply TX/RX error counters in case of
* controller error.
*/
cf->data[6] = mc->pdev->bec.txerr;
cf->data[7] = mc->pdev->bec.rxerr;
}
}
if (!skb)
return -ENOMEM;
if (status_len & PCAN_USB_STATUSLEN_TIMESTAMP) {
struct skb_shared_hwtstamps *hwts = skb_hwtstamps(skb);
@ -704,6 +631,7 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
struct sk_buff *skb;
struct can_frame *cf;
struct skb_shared_hwtstamps *hwts;
u32 can_id_flags;
skb = alloc_can_skb(mc->netdev, &cf);
if (!skb)
@ -713,13 +641,15 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
if ((mc->ptr + 4) > mc->end)
goto decode_failed;
cf->can_id = get_unaligned_le32(mc->ptr) >> 3 | CAN_EFF_FLAG;
can_id_flags = get_unaligned_le32(mc->ptr);
cf->can_id = can_id_flags >> 3 | CAN_EFF_FLAG;
mc->ptr += 4;
} else {
if ((mc->ptr + 2) > mc->end)
goto decode_failed;
cf->can_id = get_unaligned_le16(mc->ptr) >> 5;
can_id_flags = get_unaligned_le16(mc->ptr);
cf->can_id = can_id_flags >> 5;
mc->ptr += 2;
}
@ -742,6 +672,10 @@ static int pcan_usb_decode_data(struct pcan_usb_msg_context *mc, u8 status_len)
memcpy(cf->data, mc->ptr, cf->len);
mc->ptr += rec_len;
/* Ignore next byte (client private id) if SRR bit is set */
if (can_id_flags & PCAN_USB_TX_SRR)
mc->ptr++;
}
/* convert timestamp into kernel time */
@ -819,10 +753,11 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb,
struct net_device *netdev = dev->netdev;
struct net_device_stats *stats = &netdev->stats;
struct can_frame *cf = (struct can_frame *)skb->data;
u32 can_id_flags = cf->can_id & CAN_ERR_MASK;
u8 *pc;
obuf[0] = 2;
obuf[1] = 1;
obuf[0] = PCAN_USB_MSG_TX_CAN;
obuf[1] = 1; /* only one CAN frame is stored in the packet */
pc = obuf + PCAN_USB_MSG_HEADER_LEN;
@ -837,12 +772,28 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb,
*pc |= PCAN_USB_STATUSLEN_EXT_ID;
pc++;
put_unaligned_le32((cf->can_id & CAN_ERR_MASK) << 3, pc);
can_id_flags <<= 3;
if (dev->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
can_id_flags |= PCAN_USB_TX_SRR;
if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
can_id_flags |= PCAN_USB_TX_AT;
put_unaligned_le32(can_id_flags, pc);
pc += 4;
} else {
pc++;
put_unaligned_le16((cf->can_id & CAN_ERR_MASK) << 5, pc);
can_id_flags <<= 5;
if (dev->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
can_id_flags |= PCAN_USB_TX_SRR;
if (dev->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
can_id_flags |= PCAN_USB_TX_AT;
put_unaligned_le16(can_id_flags, pc);
pc += 2;
}
@ -852,6 +803,10 @@ static int pcan_usb_encode_msg(struct peak_usb_device *dev, struct sk_buff *skb,
pc += cf->len;
}
/* SRR bit needs a writer id (useless here) */
if (can_id_flags & PCAN_USB_TX_SRR)
*pc++ = 0x80;
obuf[(*size)-1] = (u8)(stats->tx_packets & 0xff);
return 0;
@ -926,6 +881,19 @@ static int pcan_usb_init(struct peak_usb_device *dev)
return err;
}
/* Since rev 4.1, PCAN-USB is able to make single-shot as well as
* looped back frames.
*/
if (dev->device_rev >= 41) {
struct can_priv *priv = netdev_priv(dev->netdev);
priv->ctrlmode_supported |= CAN_CTRLMODE_ONE_SHOT |
CAN_CTRLMODE_LOOPBACK;
} else {
dev_info(dev->netdev->dev.parent,
"Firmware update available. Please contact support@peak-system.com\n");
}
dev_info(dev->netdev->dev.parent,
"PEAK-System %s adapter hwrev %u serial %08X (%u channel)\n",
pcan_usb.name, dev->device_rev, serial_number,

View File

@ -37,7 +37,7 @@
* quanta, from when the bit is sent on the TX pin to when it is
* received on the RX pin of the transmitter. Possible options:
*
* O: automatic mode. The controller dynamically measure @tdcv
* 0: automatic mode. The controller dynamically measures @tdcv
* for each transmitted CAN FD frame.
*
* Other values: manual mode. Use the fixed provided value.
@ -45,7 +45,7 @@
* @tdco: Transmitter Delay Compensation Offset. Offset value, in time
* quanta, defining the distance between the start of the bit
* reception on the RX pin of the transceiver and the SSP
* position such as SSP = @tdcv + @tdco.
* position such that SSP = @tdcv + @tdco.
*
* If @tdco is zero, then TDC is disabled and both @tdcv and
* @tdcf should be ignored.

View File

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2021 Angelo Dureghello <angelo@kernel-space.org>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _CAN_PLATFORM_FLEXCAN_H
#define _CAN_PLATFORM_FLEXCAN_H
struct flexcan_platform_data {
u32 clock_frequency;
u8 clk_src;
};
#endif /* _CAN_PLATFORM_FLEXCAN_H */

View File

@ -20,6 +20,7 @@ struct can_rx_offload {
bool drop);
struct sk_buff_head skb_queue;
struct sk_buff_head skb_irq_queue;
u32 skb_queue_len_max;
unsigned int mb_first;
@ -48,14 +49,11 @@ unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload,
unsigned int *frame_len_ptr);
int can_rx_offload_queue_tail(struct can_rx_offload *offload,
struct sk_buff *skb);
void can_rx_offload_irq_finish(struct can_rx_offload *offload);
void can_rx_offload_threaded_irq_finish(struct can_rx_offload *offload);
void can_rx_offload_del(struct can_rx_offload *offload);
void can_rx_offload_enable(struct can_rx_offload *offload);
static inline void can_rx_offload_schedule(struct can_rx_offload *offload)
{
napi_schedule(&offload->napi);
}
static inline void can_rx_offload_disable(struct can_rx_offload *offload)
{
napi_disable(&offload->napi);

View File

@ -352,7 +352,7 @@ static void j1939_sk_sock_destruct(struct sock *sk)
{
struct j1939_sock *jsk = j1939_sk(sk);
/* This function will be call by the generic networking code, when then
/* This function will be called by the generic networking code, when
* the socket is ultimately closed (sk->sk_destruct).
*
* The race between

View File

@ -776,7 +776,7 @@ static int j1939_session_tx_dpo(struct j1939_session *session)
static int j1939_session_tx_dat(struct j1939_session *session)
{
struct j1939_priv *priv = session->priv;
struct j1939_sk_buff_cb *skcb;
struct j1939_sk_buff_cb *se_skcb;
int offset, pkt_done, pkt_end;
unsigned int len, pdelay;
struct sk_buff *se_skb;
@ -788,7 +788,7 @@ static int j1939_session_tx_dat(struct j1939_session *session)
if (!se_skb)
return -ENOBUFS;
skcb = j1939_skb_to_cb(se_skb);
se_skcb = j1939_skb_to_cb(se_skb);
tpdat = se_skb->data;
ret = 0;
pkt_done = 0;
@ -800,7 +800,7 @@ static int j1939_session_tx_dat(struct j1939_session *session)
while (session->pkt.tx < pkt_end) {
dat[0] = session->pkt.tx - session->pkt.dpo + 1;
offset = (session->pkt.tx * 7) - skcb->offset;
offset = (session->pkt.tx * 7) - se_skcb->offset;
len = se_skb->len - offset;
if (len > 7)
len = 7;
@ -808,7 +808,8 @@ static int j1939_session_tx_dat(struct j1939_session *session)
if (offset + len > se_skb->len) {
netdev_err_once(priv->ndev,
"%s: 0x%p: requested data outside of queued buffer: offset %i, len %i, pkt.tx: %i\n",
__func__, session, skcb->offset, se_skb->len , session->pkt.tx);
__func__, session, se_skcb->offset,
se_skb->len , session->pkt.tx);
ret = -EOVERFLOW;
goto out_free;
}
@ -1092,7 +1093,7 @@ j1939_session_deactivate_activate_next(struct j1939_session *session)
}
static void __j1939_session_cancel(struct j1939_session *session,
enum j1939_xtp_abort err)
enum j1939_xtp_abort err)
{
struct j1939_priv *priv = session->priv;
@ -1190,13 +1191,13 @@ static enum hrtimer_restart j1939_tp_txtimer(struct hrtimer *hrtimer)
static void j1939_session_completed(struct j1939_session *session)
{
struct sk_buff *skb;
struct sk_buff *se_skb;
if (!session->transmission) {
skb = j1939_session_skb_get(session);
se_skb = j1939_session_skb_get(session);
/* distribute among j1939 receivers */
j1939_sk_recv(session->priv, skb);
consume_skb(skb);
j1939_sk_recv(session->priv, se_skb);
consume_skb(se_skb);
}
j1939_session_deactivate_activate_next(session);
@ -1263,12 +1264,14 @@ static bool j1939_xtp_rx_cmd_bad_pgn(struct j1939_session *session,
break;
case J1939_ETP_CMD_RTS:
case J1939_TP_CMD_RTS: /* fall through */
fallthrough;
case J1939_TP_CMD_RTS:
abort = J1939_XTP_ABORT_BUSY;
break;
case J1939_ETP_CMD_CTS:
case J1939_TP_CMD_CTS: /* fall through */
fallthrough;
case J1939_TP_CMD_CTS:
abort = J1939_XTP_ABORT_ECTS_UNXPECTED_PGN;
break;
@ -1277,7 +1280,8 @@ static bool j1939_xtp_rx_cmd_bad_pgn(struct j1939_session *session,
break;
case J1939_ETP_CMD_EOMA:
case J1939_TP_CMD_EOMA: /* fall through */
fallthrough;
case J1939_TP_CMD_EOMA:
abort = J1939_XTP_ABORT_OTHER;
break;
@ -1767,7 +1771,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
struct sk_buff *skb)
{
struct j1939_priv *priv = session->priv;
struct j1939_sk_buff_cb *skcb;
struct j1939_sk_buff_cb *skcb, *se_skcb;
struct sk_buff *se_skb = NULL;
const u8 *dat;
u8 *tpdat;
@ -1792,7 +1796,8 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
break;
fallthrough;
case J1939_TP_CMD_BAM:
case J1939_TP_CMD_CTS: /* fall through */
fallthrough;
case J1939_TP_CMD_CTS:
if (skcb->addr.type != J1939_ETP)
break;
fallthrough;
@ -1817,8 +1822,8 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
goto out_session_cancel;
}
skcb = j1939_skb_to_cb(se_skb);
offset = packet * 7 - skcb->offset;
se_skcb = j1939_skb_to_cb(se_skb);
offset = packet * 7 - se_skcb->offset;
nbytes = se_skb->len - offset;
if (nbytes > 7)
nbytes = 7;
@ -1846,7 +1851,7 @@ static void j1939_xtp_rx_dat_one(struct j1939_session *session,
if (packet == session->pkt.rx)
session->pkt.rx++;
if (skcb->addr.type != J1939_ETP &&
if (se_skcb->addr.type != J1939_ETP &&
j1939_cb_is_broadcast(&session->skcb)) {
if (session->pkt.rx >= session->pkt.total)
final = true;
@ -1995,7 +2000,8 @@ static void j1939_tp_cmd_recv(struct j1939_priv *priv, struct sk_buff *skb)
extd = J1939_ETP;
fallthrough;
case J1939_TP_CMD_BAM:
case J1939_TP_CMD_RTS: /* fall through */
fallthrough;
case J1939_TP_CMD_RTS:
if (skcb->addr.type != extd)
return;