Commit f91ca783 authored by David S. Miller's avatar David S. Miller

Merge tag 'linux-can-fixes-for-3.15-20140401' of git://gitorious.org/linux-can/linux-can

linux-can-fixes-for-3.15-20140401

Marc Kleine-Budde says:

====================
this is a pull request of 16 patches for the 3.15 release cycle.

Bjorn Van Tilt contributes a patch which fixes a memory leak in usb_8dev's
usb_8dev_start_xmit()s error path. A patch by Robert Schwebel fixes a typo in
the can documentation. The remaining patches all target the c_can driver. Two
of them are by me; they add a missing netif_napi_del() and return value
checking. Thomas Gleixner contributes 12 patches, which address several
shortcomings in the driver like hardware initialisation, concurrency, message
ordering and poor performance.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 7f1f6056 b1d8e431
...@@ -1017,7 +1017,7 @@ solution for a couple of reasons: ...@@ -1017,7 +1017,7 @@ solution for a couple of reasons:
in case of a bus-off condition after the specified delay time in case of a bus-off condition after the specified delay time
in milliseconds. By default it's off. in milliseconds. By default it's off.
"bitrate 125000 sample_point 0.875" "bitrate 125000 sample-point 0.875"
Shows the real bit-rate in bits/sec and the sample-point in the Shows the real bit-rate in bits/sec and the sample-point in the
range 0.000..0.999. If the calculation of bit-timing parameters range 0.000..0.999. If the calculation of bit-timing parameters
is enabled in the kernel (CONFIG_CAN_CALC_BITTIMING=y), the is enabled in the kernel (CONFIG_CAN_CALC_BITTIMING=y), the
......
This diff is collapsed.
...@@ -22,6 +22,33 @@ ...@@ -22,6 +22,33 @@
#ifndef C_CAN_H #ifndef C_CAN_H
#define C_CAN_H #define C_CAN_H
/*
* IFx register masks:
* allow easy operation on 16-bit registers when the
* argument is 32-bit instead
*/
#define IFX_WRITE_LOW_16BIT(x) ((x) & 0xFFFF)
#define IFX_WRITE_HIGH_16BIT(x) (((x) & 0xFFFF0000) >> 16)
/* message object split */
#define C_CAN_NO_OF_OBJECTS 32
#define C_CAN_MSG_OBJ_RX_NUM 16
#define C_CAN_MSG_OBJ_TX_NUM 16
#define C_CAN_MSG_OBJ_RX_FIRST 1
#define C_CAN_MSG_OBJ_RX_LAST (C_CAN_MSG_OBJ_RX_FIRST + \
C_CAN_MSG_OBJ_RX_NUM - 1)
#define C_CAN_MSG_OBJ_TX_FIRST (C_CAN_MSG_OBJ_RX_LAST + 1)
#define C_CAN_MSG_OBJ_TX_LAST (C_CAN_MSG_OBJ_TX_FIRST + \
C_CAN_MSG_OBJ_TX_NUM - 1)
#define C_CAN_MSG_OBJ_RX_SPLIT 9
#define C_CAN_MSG_RX_LOW_LAST (C_CAN_MSG_OBJ_RX_SPLIT - 1)
#define C_CAN_NEXT_MSG_OBJ_MASK (C_CAN_MSG_OBJ_TX_NUM - 1)
#define RECEIVE_OBJECT_BITS 0x0000ffff
enum reg { enum reg {
C_CAN_CTRL_REG = 0, C_CAN_CTRL_REG = 0,
C_CAN_CTRL_EX_REG, C_CAN_CTRL_EX_REG,
...@@ -156,6 +183,7 @@ struct c_can_priv { ...@@ -156,6 +183,7 @@ struct c_can_priv {
struct napi_struct napi; struct napi_struct napi;
struct net_device *dev; struct net_device *dev;
struct device *device; struct device *device;
spinlock_t xmit_lock;
int tx_object; int tx_object;
int current_status; int current_status;
int last_status; int last_status;
...@@ -172,6 +200,7 @@ struct c_can_priv { ...@@ -172,6 +200,7 @@ struct c_can_priv {
u32 __iomem *raminit_ctrlreg; u32 __iomem *raminit_ctrlreg;
unsigned int instance; unsigned int instance;
void (*raminit) (const struct c_can_priv *priv, bool enable); void (*raminit) (const struct c_can_priv *priv, bool enable);
u32 dlc[C_CAN_MSG_OBJ_TX_NUM];
}; };
struct net_device *alloc_c_can_dev(void); struct net_device *alloc_c_can_dev(void);
......
...@@ -37,8 +37,10 @@ ...@@ -37,8 +37,10 @@
#include "c_can.h" #include "c_can.h"
#define CAN_RAMINIT_START_MASK(i) (1 << (i)) #define CAN_RAMINIT_START_MASK(i) (0x001 << (i))
#define CAN_RAMINIT_DONE_MASK(i) (0x100 << (i))
#define CAN_RAMINIT_ALL_MASK(i) (0x101 << (i))
static DEFINE_SPINLOCK(raminit_lock);
/* /*
* 16-bit c_can registers can be arranged differently in the memory * 16-bit c_can registers can be arranged differently in the memory
* architecture of different implementations. For example: 16-bit * architecture of different implementations. For example: 16-bit
...@@ -69,16 +71,41 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv, ...@@ -69,16 +71,41 @@ static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv,
writew(val, priv->base + 2 * priv->regs[index]); writew(val, priv->base + 2 * priv->regs[index]);
} }
static void c_can_hw_raminit_wait(const struct c_can_priv *priv, u32 mask,
u32 val)
{
/* We look only at the bits of our instance. */
val &= mask;
while ((readl(priv->raminit_ctrlreg) & mask) != val)
udelay(1);
}
static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable) static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
{ {
u32 val; u32 mask = CAN_RAMINIT_ALL_MASK(priv->instance);
u32 ctrl;
val = readl(priv->raminit_ctrlreg);
if (enable) spin_lock(&raminit_lock);
val |= CAN_RAMINIT_START_MASK(priv->instance);
else ctrl = readl(priv->raminit_ctrlreg);
val &= ~CAN_RAMINIT_START_MASK(priv->instance); /* We clear the done and start bit first. The start bit is
writel(val, priv->raminit_ctrlreg); * looking at the 0 -> transition, but is not self clearing;
* And we clear the init done bit as well.
*/
ctrl &= ~CAN_RAMINIT_START_MASK(priv->instance);
ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
writel(ctrl, priv->raminit_ctrlreg);
ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance);
c_can_hw_raminit_wait(priv, ctrl, mask);
if (enable) {
/* Set start bit and wait for the done bit. */
ctrl |= CAN_RAMINIT_START_MASK(priv->instance);
writel(ctrl, priv->raminit_ctrlreg);
ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance);
c_can_hw_raminit_wait(priv, ctrl, mask);
}
spin_unlock(&raminit_lock);
} }
static struct platform_device_id c_can_id_table[] = { static struct platform_device_id c_can_id_table[] = {
......
...@@ -697,8 +697,8 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb, ...@@ -697,8 +697,8 @@ static netdev_tx_t usb_8dev_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK; return NETDEV_TX_OK;
nofreecontext: nofreecontext:
usb_unanchor_urb(urb);
usb_free_coherent(priv->udev, size, buf, urb->transfer_dma); usb_free_coherent(priv->udev, size, buf, urb->transfer_dma);
usb_free_urb(urb);
netdev_warn(netdev, "couldn't find free context"); netdev_warn(netdev, "couldn't find free context");
......
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