Skip to content

Commit

Permalink
Merge tag 'linux-can-fixes-for-4.16-20180312' of ssh://gitolite.kerne…
Browse files Browse the repository at this point in the history
…l.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2018-03-12

this is a pull reqeust of 6 patches for net/master.

The first patch is by Wolfram Sang and fixes a bitshift vs. comparison mistake
in the m_can driver. Two patches of Marek Vasut repair the error handling in
the ifi driver. The two patches by Stephane Grosjean fix a "echo_skb is
occupied!" bug in the peak/pcie_fd driver. Bich HEMON's patch adds pinctrl
select state calls to the m_can's driver to further improve power saving during
suspend.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Mar 12, 2018
2 parents bf2ae2e + c9b3bce commit 4665c6b
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 48 deletions.
75 changes: 47 additions & 28 deletions drivers/net/can/ifi_canfd/ifi_canfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#define IFI_CANFD_STCMD_ERROR_ACTIVE BIT(2)
#define IFI_CANFD_STCMD_ERROR_PASSIVE BIT(3)
#define IFI_CANFD_STCMD_BUSOFF BIT(4)
#define IFI_CANFD_STCMD_ERROR_WARNING BIT(5)
#define IFI_CANFD_STCMD_BUSMONITOR BIT(16)
#define IFI_CANFD_STCMD_LOOPBACK BIT(18)
#define IFI_CANFD_STCMD_DISABLE_CANFD BIT(24)
Expand All @@ -52,7 +53,10 @@
#define IFI_CANFD_TXSTCMD_OVERFLOW BIT(13)

#define IFI_CANFD_INTERRUPT 0xc
#define IFI_CANFD_INTERRUPT_ERROR_BUSOFF BIT(0)
#define IFI_CANFD_INTERRUPT_ERROR_WARNING BIT(1)
#define IFI_CANFD_INTERRUPT_ERROR_STATE_CHG BIT(2)
#define IFI_CANFD_INTERRUPT_ERROR_REC_TEC_INC BIT(3)
#define IFI_CANFD_INTERRUPT_ERROR_COUNTER BIT(10)
#define IFI_CANFD_INTERRUPT_TXFIFO_EMPTY BIT(16)
#define IFI_CANFD_INTERRUPT_TXFIFO_REMOVE BIT(22)
Expand All @@ -61,6 +65,10 @@
#define IFI_CANFD_INTERRUPT_SET_IRQ ((u32)BIT(31))

#define IFI_CANFD_IRQMASK 0x10
#define IFI_CANFD_IRQMASK_ERROR_BUSOFF BIT(0)
#define IFI_CANFD_IRQMASK_ERROR_WARNING BIT(1)
#define IFI_CANFD_IRQMASK_ERROR_STATE_CHG BIT(2)
#define IFI_CANFD_IRQMASK_ERROR_REC_TEC_INC BIT(3)
#define IFI_CANFD_IRQMASK_SET_ERR BIT(7)
#define IFI_CANFD_IRQMASK_SET_TS BIT(15)
#define IFI_CANFD_IRQMASK_TXFIFO_EMPTY BIT(16)
Expand Down Expand Up @@ -136,6 +144,8 @@
#define IFI_CANFD_SYSCLOCK 0x50

#define IFI_CANFD_VER 0x54
#define IFI_CANFD_VER_REV_MASK 0xff
#define IFI_CANFD_VER_REV_MIN_SUPPORTED 0x15

#define IFI_CANFD_IP_ID 0x58
#define IFI_CANFD_IP_ID_VALUE 0xD073CAFD
Expand Down Expand Up @@ -220,7 +230,10 @@ static void ifi_canfd_irq_enable(struct net_device *ndev, bool enable)

if (enable) {
enirq = IFI_CANFD_IRQMASK_TXFIFO_EMPTY |
IFI_CANFD_IRQMASK_RXFIFO_NEMPTY;
IFI_CANFD_IRQMASK_RXFIFO_NEMPTY |
IFI_CANFD_IRQMASK_ERROR_STATE_CHG |
IFI_CANFD_IRQMASK_ERROR_WARNING |
IFI_CANFD_IRQMASK_ERROR_BUSOFF;
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
enirq |= IFI_CANFD_INTERRUPT_ERROR_COUNTER;
}
Expand Down Expand Up @@ -361,12 +374,13 @@ static int ifi_canfd_handle_lost_msg(struct net_device *ndev)
return 1;
}

static int ifi_canfd_handle_lec_err(struct net_device *ndev, const u32 errctr)
static int ifi_canfd_handle_lec_err(struct net_device *ndev)
{
struct ifi_canfd_priv *priv = netdev_priv(ndev);
struct net_device_stats *stats = &ndev->stats;
struct can_frame *cf;
struct sk_buff *skb;
u32 errctr = readl(priv->base + IFI_CANFD_ERROR_CTR);
const u32 errmask = IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST |
IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST |
IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST |
Expand Down Expand Up @@ -449,6 +463,11 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev,

switch (new_state) {
case CAN_STATE_ERROR_ACTIVE:
/* error active state */
priv->can.can_stats.error_warning++;
priv->can.state = CAN_STATE_ERROR_ACTIVE;
break;
case CAN_STATE_ERROR_WARNING:
/* error warning state */
priv->can.can_stats.error_warning++;
priv->can.state = CAN_STATE_ERROR_WARNING;
Expand Down Expand Up @@ -477,7 +496,7 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev,
ifi_canfd_get_berr_counter(ndev, &bec);

switch (new_state) {
case CAN_STATE_ERROR_ACTIVE:
case CAN_STATE_ERROR_WARNING:
/* error warning state */
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (bec.txerr > bec.rxerr) ?
Expand Down Expand Up @@ -510,22 +529,21 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev,
return 1;
}

static int ifi_canfd_handle_state_errors(struct net_device *ndev, u32 stcmd)
static int ifi_canfd_handle_state_errors(struct net_device *ndev)
{
struct ifi_canfd_priv *priv = netdev_priv(ndev);
u32 stcmd = readl(priv->base + IFI_CANFD_STCMD);
int work_done = 0;
u32 isr;

/*
* The ErrWarn condition is a little special, since the bit is
* located in the INTERRUPT register instead of STCMD register.
*/
isr = readl(priv->base + IFI_CANFD_INTERRUPT);
if ((isr & IFI_CANFD_INTERRUPT_ERROR_WARNING) &&
if ((stcmd & IFI_CANFD_STCMD_ERROR_ACTIVE) &&
(priv->can.state != CAN_STATE_ERROR_ACTIVE)) {
netdev_dbg(ndev, "Error, entered active state\n");
work_done += ifi_canfd_handle_state_change(ndev,
CAN_STATE_ERROR_ACTIVE);
}

if ((stcmd & IFI_CANFD_STCMD_ERROR_WARNING) &&
(priv->can.state != CAN_STATE_ERROR_WARNING)) {
/* Clear the interrupt */
writel(IFI_CANFD_INTERRUPT_ERROR_WARNING,
priv->base + IFI_CANFD_INTERRUPT);
netdev_dbg(ndev, "Error, entered warning state\n");
work_done += ifi_canfd_handle_state_change(ndev,
CAN_STATE_ERROR_WARNING);
Expand All @@ -552,26 +570,19 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota)
{
struct net_device *ndev = napi->dev;
struct ifi_canfd_priv *priv = netdev_priv(ndev);
const u32 stcmd_state_mask = IFI_CANFD_STCMD_ERROR_PASSIVE |
IFI_CANFD_STCMD_BUSOFF;
int work_done = 0;

u32 stcmd = readl(priv->base + IFI_CANFD_STCMD);
u32 rxstcmd = readl(priv->base + IFI_CANFD_RXSTCMD);
u32 errctr = readl(priv->base + IFI_CANFD_ERROR_CTR);
int work_done = 0;

/* Handle bus state changes */
if ((stcmd & stcmd_state_mask) ||
((stcmd & IFI_CANFD_STCMD_ERROR_ACTIVE) == 0))
work_done += ifi_canfd_handle_state_errors(ndev, stcmd);
work_done += ifi_canfd_handle_state_errors(ndev);

/* Handle lost messages on RX */
if (rxstcmd & IFI_CANFD_RXSTCMD_OVERFLOW)
work_done += ifi_canfd_handle_lost_msg(ndev);

/* Handle lec errors on the bus */
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
work_done += ifi_canfd_handle_lec_err(ndev, errctr);
work_done += ifi_canfd_handle_lec_err(ndev);

/* Handle normal messages on RX */
if (!(rxstcmd & IFI_CANFD_RXSTCMD_EMPTY))
Expand All @@ -592,12 +603,13 @@ static irqreturn_t ifi_canfd_isr(int irq, void *dev_id)
struct net_device_stats *stats = &ndev->stats;
const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY |
IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER |
IFI_CANFD_INTERRUPT_ERROR_COUNTER |
IFI_CANFD_INTERRUPT_ERROR_STATE_CHG |
IFI_CANFD_INTERRUPT_ERROR_WARNING |
IFI_CANFD_INTERRUPT_ERROR_COUNTER;
IFI_CANFD_INTERRUPT_ERROR_BUSOFF;
const u32 tx_irq_mask = IFI_CANFD_INTERRUPT_TXFIFO_EMPTY |
IFI_CANFD_INTERRUPT_TXFIFO_REMOVE;
const u32 clr_irq_mask = ~((u32)(IFI_CANFD_INTERRUPT_SET_IRQ |
IFI_CANFD_INTERRUPT_ERROR_WARNING));
const u32 clr_irq_mask = ~((u32)IFI_CANFD_INTERRUPT_SET_IRQ);
u32 isr;

isr = readl(priv->base + IFI_CANFD_INTERRUPT);
Expand Down Expand Up @@ -933,7 +945,7 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev)
struct resource *res;
void __iomem *addr;
int irq, ret;
u32 id;
u32 id, rev;

res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
addr = devm_ioremap_resource(dev, res);
Expand All @@ -947,6 +959,13 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev)
return -EINVAL;
}

rev = readl(addr + IFI_CANFD_VER) & IFI_CANFD_VER_REV_MASK;
if (rev < IFI_CANFD_VER_REV_MIN_SUPPORTED) {
dev_err(dev, "This block is too old (rev %i), minimum supported is rev %i\n",
rev, IFI_CANFD_VER_REV_MIN_SUPPORTED);
return -EINVAL;
}

ndev = alloc_candev(sizeof(*priv), 1);
if (!ndev)
return -ENOMEM;
Expand Down
7 changes: 6 additions & 1 deletion drivers/net/can/m_can/m_can.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <linux/pm_runtime.h>
#include <linux/iopoll.h>
#include <linux/can/dev.h>
#include <linux/pinctrl/consumer.h>

/* napi related */
#define M_CAN_NAPI_WEIGHT 64
Expand Down Expand Up @@ -253,7 +254,7 @@ enum m_can_mram_cfg {

/* Rx FIFO 0/1 Configuration (RXF0C/RXF1C) */
#define RXFC_FWM_SHIFT 24
#define RXFC_FWM_MASK (0x7f < RXFC_FWM_SHIFT)
#define RXFC_FWM_MASK (0x7f << RXFC_FWM_SHIFT)
#define RXFC_FS_SHIFT 16
#define RXFC_FS_MASK (0x7f << RXFC_FS_SHIFT)

Expand Down Expand Up @@ -1700,6 +1701,8 @@ static __maybe_unused int m_can_suspend(struct device *dev)
m_can_clk_stop(priv);
}

pinctrl_pm_select_sleep_state(dev);

priv->can.state = CAN_STATE_SLEEPING;

return 0;
Expand All @@ -1710,6 +1713,8 @@ static __maybe_unused int m_can_resume(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev);
struct m_can_priv *priv = netdev_priv(ndev);

pinctrl_pm_select_default_state(dev);

m_can_init_ram(priv);

priv->can.state = CAN_STATE_ERROR_ACTIVE;
Expand Down
25 changes: 8 additions & 17 deletions drivers/net/can/peak_canfd/peak_canfd.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,6 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv,

spin_lock_irqsave(&priv->echo_lock, flags);
can_get_echo_skb(priv->ndev, msg->client);
spin_unlock_irqrestore(&priv->echo_lock, flags);

/* count bytes of the echo instead of skb */
stats->tx_bytes += cf_len;
Expand All @@ -271,6 +270,7 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv,
/* restart tx queue (a slot is free) */
netif_wake_queue(priv->ndev);

spin_unlock_irqrestore(&priv->echo_lock, flags);
return 0;
}

Expand Down Expand Up @@ -333,7 +333,6 @@ static int pucan_handle_status(struct peak_canfd_priv *priv,

/* this STATUS is the CNF of the RX_BARRIER: Tx path can be setup */
if (pucan_status_is_rx_barrier(msg)) {
unsigned long flags;

if (priv->enable_tx_path) {
int err = priv->enable_tx_path(priv);
Expand All @@ -342,16 +341,8 @@ static int pucan_handle_status(struct peak_canfd_priv *priv,
return err;
}

/* restart network queue only if echo skb array is free */
spin_lock_irqsave(&priv->echo_lock, flags);

if (!priv->can.echo_skb[priv->echo_idx]) {
spin_unlock_irqrestore(&priv->echo_lock, flags);

netif_wake_queue(ndev);
} else {
spin_unlock_irqrestore(&priv->echo_lock, flags);
}
/* start network queue (echo_skb array is empty) */
netif_start_queue(ndev);

return 0;
}
Expand Down Expand Up @@ -726,11 +717,6 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
*/
should_stop_tx_queue = !!(priv->can.echo_skb[priv->echo_idx]);

spin_unlock_irqrestore(&priv->echo_lock, flags);

/* write the skb on the interface */
priv->write_tx_msg(priv, msg);

/* stop network tx queue if not enough room to save one more msg too */
if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
should_stop_tx_queue |= (room_left <
Expand All @@ -742,6 +728,11 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
if (should_stop_tx_queue)
netif_stop_queue(ndev);

spin_unlock_irqrestore(&priv->echo_lock, flags);

/* write the skb on the interface */
priv->write_tx_msg(priv, msg);

return NETDEV_TX_OK;
}

Expand Down
8 changes: 6 additions & 2 deletions drivers/net/can/peak_canfd/peak_pciefd_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,8 +349,12 @@ static irqreturn_t pciefd_irq_handler(int irq, void *arg)
priv->tx_pages_free++;
spin_unlock_irqrestore(&priv->tx_lock, flags);

/* wake producer up */
netif_wake_queue(priv->ucan.ndev);
/* wake producer up (only if enough room in echo_skb array) */
spin_lock_irqsave(&priv->ucan.echo_lock, flags);
if (!priv->ucan.can.echo_skb[priv->ucan.echo_idx])
netif_wake_queue(priv->ucan.ndev);

spin_unlock_irqrestore(&priv->ucan.echo_lock, flags);
}

/* re-enable Rx DMA transfer for this CAN */
Expand Down

0 comments on commit 4665c6b

Please sign in to comment.