linux-can-fixes-for-4.16-20180312
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEENrCndlB/VnAEWuH5k9IU1zQoZfEFAlqmTtoTHG1rbEBwZW5n dXRyb25peC5kZQAKCRCT0hTXNChl8TpIB/0XE7uXTbSgoKbpN8mfagjfeh7FZdnF r5yI/MGhtS5+JRJScp73yexfVXIBYTlMZ2Q9vYAgAmDJUg5vDywKUxfK2gzqFju8 P8ao0wp/QCu0uaLYc7ajW6udAQGLnHUT3PmJGZvSRgtlKj6c/KmfQBxq8S7bFvqc ye07Lp3EYeSEKQ3RexCTbPPH0YZoX1dQw9phKV9jNFU9OYI0uOACjuI+KBQt91AW 60X4uWMR9bl02aL6Pm2wQWuxxNfGI6HlAJSqToK9/F1gbIDNE9Jy/URaSXU/5cvq hWNbjdoXKFIimgFVITiWbnXRdAAV4w4Lr/Fhu0pnKpyrFfeJlXME961e =88JD -----END PGP SIGNATURE----- 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: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
4665c6b046
4 changed files with 67 additions and 48 deletions
|
|
@ -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;
|
||||
u32 rxstcmd = readl(priv->base + IFI_CANFD_RXSTCMD);
|
||||
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);
|
||||
|
||||
/* 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 */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue