提交 4665c6b0 编写于 作者: D 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: NDavid S. Miller <davem@davemloft.net>
......@@ -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)
......@@ -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)
......@@ -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)
......@@ -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
......@@ -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;
}
......@@ -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 |
......@@ -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;
......@@ -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) ?
......@@ -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);
......@@ -552,18 +570,11 @@ 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)
......@@ -571,7 +582,7 @@ static int ifi_canfd_poll(struct napi_struct *napi, int quota)
/* 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))
......@@ -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);
......@@ -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);
......@@ -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;
......
......@@ -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
......@@ -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)
......@@ -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;
......@@ -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;
......
......@@ -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;
......@@ -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;
}
......@@ -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);
......@@ -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;
}
......@@ -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 <
......@@ -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;
}
......
......@@ -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 */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册