Commit 4665c6b0 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-fixes-for-4.16-20180312' of...

Merge tag 'linux-can-fixes-for-4.16-20180312' of ssh://gitolite.kernel.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: default avatarDavid S. Miller <davem@davemloft.net>
parents bf2ae2e4 c9b3bce1
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#define IFI_CANFD_STCMD_ERROR_ACTIVE BIT(2) #define IFI_CANFD_STCMD_ERROR_ACTIVE BIT(2)
#define IFI_CANFD_STCMD_ERROR_PASSIVE BIT(3) #define IFI_CANFD_STCMD_ERROR_PASSIVE BIT(3)
#define IFI_CANFD_STCMD_BUSOFF BIT(4) #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_BUSMONITOR BIT(16)
#define IFI_CANFD_STCMD_LOOPBACK BIT(18) #define IFI_CANFD_STCMD_LOOPBACK BIT(18)
#define IFI_CANFD_STCMD_DISABLE_CANFD BIT(24) #define IFI_CANFD_STCMD_DISABLE_CANFD BIT(24)
...@@ -52,7 +53,10 @@ ...@@ -52,7 +53,10 @@
#define IFI_CANFD_TXSTCMD_OVERFLOW BIT(13) #define IFI_CANFD_TXSTCMD_OVERFLOW BIT(13)
#define IFI_CANFD_INTERRUPT 0xc #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_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_ERROR_COUNTER BIT(10)
#define IFI_CANFD_INTERRUPT_TXFIFO_EMPTY BIT(16) #define IFI_CANFD_INTERRUPT_TXFIFO_EMPTY BIT(16)
#define IFI_CANFD_INTERRUPT_TXFIFO_REMOVE BIT(22) #define IFI_CANFD_INTERRUPT_TXFIFO_REMOVE BIT(22)
...@@ -61,6 +65,10 @@ ...@@ -61,6 +65,10 @@
#define IFI_CANFD_INTERRUPT_SET_IRQ ((u32)BIT(31)) #define IFI_CANFD_INTERRUPT_SET_IRQ ((u32)BIT(31))
#define IFI_CANFD_IRQMASK 0x10 #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_ERR BIT(7)
#define IFI_CANFD_IRQMASK_SET_TS BIT(15) #define IFI_CANFD_IRQMASK_SET_TS BIT(15)
#define IFI_CANFD_IRQMASK_TXFIFO_EMPTY BIT(16) #define IFI_CANFD_IRQMASK_TXFIFO_EMPTY BIT(16)
...@@ -136,6 +144,8 @@ ...@@ -136,6 +144,8 @@
#define IFI_CANFD_SYSCLOCK 0x50 #define IFI_CANFD_SYSCLOCK 0x50
#define IFI_CANFD_VER 0x54 #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 0x58
#define IFI_CANFD_IP_ID_VALUE 0xD073CAFD #define IFI_CANFD_IP_ID_VALUE 0xD073CAFD
...@@ -220,7 +230,10 @@ static void ifi_canfd_irq_enable(struct net_device *ndev, bool enable) ...@@ -220,7 +230,10 @@ static void ifi_canfd_irq_enable(struct net_device *ndev, bool enable)
if (enable) { if (enable) {
enirq = IFI_CANFD_IRQMASK_TXFIFO_EMPTY | 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) if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
enirq |= IFI_CANFD_INTERRUPT_ERROR_COUNTER; enirq |= IFI_CANFD_INTERRUPT_ERROR_COUNTER;
} }
...@@ -361,12 +374,13 @@ static int ifi_canfd_handle_lost_msg(struct net_device *ndev) ...@@ -361,12 +374,13 @@ static int ifi_canfd_handle_lost_msg(struct net_device *ndev)
return 1; 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 ifi_canfd_priv *priv = netdev_priv(ndev);
struct net_device_stats *stats = &ndev->stats; struct net_device_stats *stats = &ndev->stats;
struct can_frame *cf; struct can_frame *cf;
struct sk_buff *skb; struct sk_buff *skb;
u32 errctr = readl(priv->base + IFI_CANFD_ERROR_CTR);
const u32 errmask = IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST | const u32 errmask = IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST |
IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST | IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST |
IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST | IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST |
...@@ -449,6 +463,11 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev, ...@@ -449,6 +463,11 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev,
switch (new_state) { switch (new_state) {
case CAN_STATE_ERROR_ACTIVE: 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 */ /* error warning state */
priv->can.can_stats.error_warning++; priv->can.can_stats.error_warning++;
priv->can.state = CAN_STATE_ERROR_WARNING; priv->can.state = CAN_STATE_ERROR_WARNING;
...@@ -477,7 +496,7 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev, ...@@ -477,7 +496,7 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev,
ifi_canfd_get_berr_counter(ndev, &bec); ifi_canfd_get_berr_counter(ndev, &bec);
switch (new_state) { switch (new_state) {
case CAN_STATE_ERROR_ACTIVE: case CAN_STATE_ERROR_WARNING:
/* error warning state */ /* error warning state */
cf->can_id |= CAN_ERR_CRTL; cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (bec.txerr > bec.rxerr) ? cf->data[1] = (bec.txerr > bec.rxerr) ?
...@@ -510,22 +529,21 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev, ...@@ -510,22 +529,21 @@ static int ifi_canfd_handle_state_change(struct net_device *ndev,
return 1; 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); struct ifi_canfd_priv *priv = netdev_priv(ndev);
u32 stcmd = readl(priv->base + IFI_CANFD_STCMD);
int work_done = 0; int work_done = 0;
u32 isr;
/* if ((stcmd & IFI_CANFD_STCMD_ERROR_ACTIVE) &&
* The ErrWarn condition is a little special, since the bit is (priv->can.state != CAN_STATE_ERROR_ACTIVE)) {
* located in the INTERRUPT register instead of STCMD register. netdev_dbg(ndev, "Error, entered active state\n");
*/ work_done += ifi_canfd_handle_state_change(ndev,
isr = readl(priv->base + IFI_CANFD_INTERRUPT); CAN_STATE_ERROR_ACTIVE);
if ((isr & IFI_CANFD_INTERRUPT_ERROR_WARNING) && }
if ((stcmd & IFI_CANFD_STCMD_ERROR_WARNING) &&
(priv->can.state != CAN_STATE_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"); netdev_dbg(ndev, "Error, entered warning state\n");
work_done += ifi_canfd_handle_state_change(ndev, work_done += ifi_canfd_handle_state_change(ndev,
CAN_STATE_ERROR_WARNING); CAN_STATE_ERROR_WARNING);
...@@ -552,18 +570,11 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota) ...@@ -552,18 +570,11 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota)
{ {
struct net_device *ndev = napi->dev; struct net_device *ndev = napi->dev;
struct ifi_canfd_priv *priv = netdev_priv(ndev); 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 rxstcmd = readl(priv->base + IFI_CANFD_RXSTCMD);
u32 errctr = readl(priv->base + IFI_CANFD_ERROR_CTR); int work_done = 0;
/* Handle bus state changes */ /* Handle bus state changes */
if ((stcmd & stcmd_state_mask) || work_done += ifi_canfd_handle_state_errors(ndev);
((stcmd & IFI_CANFD_STCMD_ERROR_ACTIVE) == 0))
work_done += ifi_canfd_handle_state_errors(ndev, stcmd);
/* Handle lost messages on RX */ /* Handle lost messages on RX */
if (rxstcmd & IFI_CANFD_RXSTCMD_OVERFLOW) if (rxstcmd & IFI_CANFD_RXSTCMD_OVERFLOW)
...@@ -571,7 +582,7 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota) ...@@ -571,7 +582,7 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota)
/* Handle lec errors on the bus */ /* Handle lec errors on the bus */
if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) 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 */ /* Handle normal messages on RX */
if (!(rxstcmd & IFI_CANFD_RXSTCMD_EMPTY)) if (!(rxstcmd & IFI_CANFD_RXSTCMD_EMPTY))
...@@ -592,12 +603,13 @@ static irqreturn_t ifi_canfd_isr(int irq, void *dev_id) ...@@ -592,12 +603,13 @@ static irqreturn_t ifi_canfd_isr(int irq, void *dev_id)
struct net_device_stats *stats = &ndev->stats; struct net_device_stats *stats = &ndev->stats;
const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY | const u32 rx_irq_mask = IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY |
IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER | IFI_CANFD_INTERRUPT_RXFIFO_NEMPTY_PER |
IFI_CANFD_INTERRUPT_ERROR_COUNTER |
IFI_CANFD_INTERRUPT_ERROR_STATE_CHG |
IFI_CANFD_INTERRUPT_ERROR_WARNING | 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 | const u32 tx_irq_mask = IFI_CANFD_INTERRUPT_TXFIFO_EMPTY |
IFI_CANFD_INTERRUPT_TXFIFO_REMOVE; IFI_CANFD_INTERRUPT_TXFIFO_REMOVE;
const u32 clr_irq_mask = ~((u32)(IFI_CANFD_INTERRUPT_SET_IRQ | const u32 clr_irq_mask = ~((u32)IFI_CANFD_INTERRUPT_SET_IRQ);
IFI_CANFD_INTERRUPT_ERROR_WARNING));
u32 isr; u32 isr;
isr = readl(priv->base + IFI_CANFD_INTERRUPT); isr = readl(priv->base + IFI_CANFD_INTERRUPT);
...@@ -933,7 +945,7 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev) ...@@ -933,7 +945,7 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev)
struct resource *res; struct resource *res;
void __iomem *addr; void __iomem *addr;
int irq, ret; int irq, ret;
u32 id; u32 id, rev;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
addr = devm_ioremap_resource(dev, res); addr = devm_ioremap_resource(dev, res);
...@@ -947,6 +959,13 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev) ...@@ -947,6 +959,13 @@ static int ifi_canfd_plat_probe(struct platform_device *pdev)
return -EINVAL; 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); ndev = alloc_candev(sizeof(*priv), 1);
if (!ndev) if (!ndev)
return -ENOMEM; return -ENOMEM;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/iopoll.h> #include <linux/iopoll.h>
#include <linux/can/dev.h> #include <linux/can/dev.h>
#include <linux/pinctrl/consumer.h>
/* napi related */ /* napi related */
#define M_CAN_NAPI_WEIGHT 64 #define M_CAN_NAPI_WEIGHT 64
...@@ -253,7 +254,7 @@ enum m_can_mram_cfg { ...@@ -253,7 +254,7 @@ enum m_can_mram_cfg {
/* Rx FIFO 0/1 Configuration (RXF0C/RXF1C) */ /* Rx FIFO 0/1 Configuration (RXF0C/RXF1C) */
#define RXFC_FWM_SHIFT 24 #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_SHIFT 16
#define RXFC_FS_MASK (0x7f << RXFC_FS_SHIFT) #define RXFC_FS_MASK (0x7f << RXFC_FS_SHIFT)
...@@ -1700,6 +1701,8 @@ static __maybe_unused int m_can_suspend(struct device *dev) ...@@ -1700,6 +1701,8 @@ static __maybe_unused int m_can_suspend(struct device *dev)
m_can_clk_stop(priv); m_can_clk_stop(priv);
} }
pinctrl_pm_select_sleep_state(dev);
priv->can.state = CAN_STATE_SLEEPING; priv->can.state = CAN_STATE_SLEEPING;
return 0; return 0;
...@@ -1710,6 +1713,8 @@ static __maybe_unused int m_can_resume(struct device *dev) ...@@ -1710,6 +1713,8 @@ static __maybe_unused int m_can_resume(struct device *dev)
struct net_device *ndev = dev_get_drvdata(dev); struct net_device *ndev = dev_get_drvdata(dev);
struct m_can_priv *priv = netdev_priv(ndev); struct m_can_priv *priv = netdev_priv(ndev);
pinctrl_pm_select_default_state(dev);
m_can_init_ram(priv); m_can_init_ram(priv);
priv->can.state = CAN_STATE_ERROR_ACTIVE; priv->can.state = CAN_STATE_ERROR_ACTIVE;
......
...@@ -262,7 +262,6 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv, ...@@ -262,7 +262,6 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv,
spin_lock_irqsave(&priv->echo_lock, flags); spin_lock_irqsave(&priv->echo_lock, flags);
can_get_echo_skb(priv->ndev, msg->client); can_get_echo_skb(priv->ndev, msg->client);
spin_unlock_irqrestore(&priv->echo_lock, flags);
/* count bytes of the echo instead of skb */ /* count bytes of the echo instead of skb */
stats->tx_bytes += cf_len; stats->tx_bytes += cf_len;
...@@ -271,6 +270,7 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv, ...@@ -271,6 +270,7 @@ static int pucan_handle_can_rx(struct peak_canfd_priv *priv,
/* restart tx queue (a slot is free) */ /* restart tx queue (a slot is free) */
netif_wake_queue(priv->ndev); netif_wake_queue(priv->ndev);
spin_unlock_irqrestore(&priv->echo_lock, flags);
return 0; return 0;
} }
...@@ -333,7 +333,6 @@ static int pucan_handle_status(struct peak_canfd_priv *priv, ...@@ -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 */ /* this STATUS is the CNF of the RX_BARRIER: Tx path can be setup */
if (pucan_status_is_rx_barrier(msg)) { if (pucan_status_is_rx_barrier(msg)) {
unsigned long flags;
if (priv->enable_tx_path) { if (priv->enable_tx_path) {
int err = priv->enable_tx_path(priv); int err = priv->enable_tx_path(priv);
...@@ -342,16 +341,8 @@ static int pucan_handle_status(struct peak_canfd_priv *priv, ...@@ -342,16 +341,8 @@ static int pucan_handle_status(struct peak_canfd_priv *priv,
return err; return err;
} }
/* restart network queue only if echo skb array is free */ /* start network queue (echo_skb array is empty) */
spin_lock_irqsave(&priv->echo_lock, flags); netif_start_queue(ndev);
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);
}
return 0; return 0;
} }
...@@ -726,11 +717,6 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb, ...@@ -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]); 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 */ /* stop network tx queue if not enough room to save one more msg too */
if (priv->can.ctrlmode & CAN_CTRLMODE_FD) if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
should_stop_tx_queue |= (room_left < should_stop_tx_queue |= (room_left <
...@@ -742,6 +728,11 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb, ...@@ -742,6 +728,11 @@ static netdev_tx_t peak_canfd_start_xmit(struct sk_buff *skb,
if (should_stop_tx_queue) if (should_stop_tx_queue)
netif_stop_queue(ndev); 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; return NETDEV_TX_OK;
} }
......
...@@ -349,8 +349,12 @@ static irqreturn_t pciefd_irq_handler(int irq, void *arg) ...@@ -349,8 +349,12 @@ static irqreturn_t pciefd_irq_handler(int irq, void *arg)
priv->tx_pages_free++; priv->tx_pages_free++;
spin_unlock_irqrestore(&priv->tx_lock, flags); spin_unlock_irqrestore(&priv->tx_lock, flags);
/* wake producer up */ /* wake producer up (only if enough room in echo_skb array) */
netif_wake_queue(priv->ucan.ndev); 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 */ /* re-enable Rx DMA transfer for this CAN */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment