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
......
...@@ -114,6 +114,14 @@ ...@@ -114,6 +114,14 @@
IF_COMM_CONTROL | IF_COMM_TXRQST | \ IF_COMM_CONTROL | IF_COMM_TXRQST | \
IF_COMM_DATAA | IF_COMM_DATAB) IF_COMM_DATAA | IF_COMM_DATAB)
/* For the low buffers we clear the interrupt bit, but keep newdat */
#define IF_COMM_RCV_LOW (IF_COMM_MASK | IF_COMM_ARB | \
IF_COMM_CONTROL | IF_COMM_CLR_INT_PND | \
IF_COMM_DATAA | IF_COMM_DATAB)
/* For the high buffers we clear the interrupt bit and newdat */
#define IF_COMM_RCV_HIGH (IF_COMM_RCV_LOW | IF_COMM_TXRQST)
/* IFx arbitration */ /* IFx arbitration */
#define IF_ARB_MSGVAL BIT(15) #define IF_ARB_MSGVAL BIT(15)
#define IF_ARB_MSGXTD BIT(14) #define IF_ARB_MSGXTD BIT(14)
...@@ -122,7 +130,6 @@ ...@@ -122,7 +130,6 @@
/* IFx message control */ /* IFx message control */
#define IF_MCONT_NEWDAT BIT(15) #define IF_MCONT_NEWDAT BIT(15)
#define IF_MCONT_MSGLST BIT(14) #define IF_MCONT_MSGLST BIT(14)
#define IF_MCONT_CLR_MSGLST (0 << 14)
#define IF_MCONT_INTPND BIT(13) #define IF_MCONT_INTPND BIT(13)
#define IF_MCONT_UMASK BIT(12) #define IF_MCONT_UMASK BIT(12)
#define IF_MCONT_TXIE BIT(11) #define IF_MCONT_TXIE BIT(11)
...@@ -133,31 +140,10 @@ ...@@ -133,31 +140,10 @@
#define IF_MCONT_DLC_MASK 0xf #define IF_MCONT_DLC_MASK 0xf
/* /*
* IFx register masks: * Use IF1 for RX and IF2 for TX
* allow easy operation on 16-bit registers when the
* argument is 32-bit instead
*/ */
#define IFX_WRITE_LOW_16BIT(x) ((x) & 0xFFFF) #define IF_RX 0
#define IFX_WRITE_HIGH_16BIT(x) (((x) & 0xFFFF0000) >> 16) #define IF_TX 1
/* 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
/* status interrupt */ /* status interrupt */
#define STATUS_INTERRUPT 0x8000 #define STATUS_INTERRUPT 0x8000
...@@ -246,10 +232,9 @@ static inline int get_tx_next_msg_obj(const struct c_can_priv *priv) ...@@ -246,10 +232,9 @@ static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
C_CAN_MSG_OBJ_TX_FIRST; C_CAN_MSG_OBJ_TX_FIRST;
} }
static inline int get_tx_echo_msg_obj(const struct c_can_priv *priv) static inline int get_tx_echo_msg_obj(int txecho)
{ {
return (priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) + return (txecho & C_CAN_NEXT_MSG_OBJ_MASK) + C_CAN_MSG_OBJ_TX_FIRST;
C_CAN_MSG_OBJ_TX_FIRST;
} }
static u32 c_can_read_reg32(struct c_can_priv *priv, enum reg index) static u32 c_can_read_reg32(struct c_can_priv *priv, enum reg index)
...@@ -366,18 +351,6 @@ static void c_can_write_msg_object(struct net_device *dev, ...@@ -366,18 +351,6 @@ static void c_can_write_msg_object(struct net_device *dev,
c_can_object_put(dev, iface, objno, IF_COMM_ALL); c_can_object_put(dev, iface, objno, IF_COMM_ALL);
} }
static inline void c_can_mark_rx_msg_obj(struct net_device *dev,
int iface, int ctrl_mask,
int obj)
{
struct c_can_priv *priv = netdev_priv(dev);
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
ctrl_mask & ~(IF_MCONT_MSGLST | IF_MCONT_INTPND));
c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
}
static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev, static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
int iface, int iface,
int ctrl_mask) int ctrl_mask)
...@@ -387,45 +360,27 @@ static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev, ...@@ -387,45 +360,27 @@ static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) { for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) {
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
ctrl_mask & ~(IF_MCONT_MSGLST | ctrl_mask & ~IF_MCONT_NEWDAT);
IF_MCONT_INTPND | IF_MCONT_NEWDAT));
c_can_object_put(dev, iface, i, IF_COMM_CONTROL); c_can_object_put(dev, iface, i, IF_COMM_CONTROL);
} }
} }
static inline void c_can_activate_rx_msg_obj(struct net_device *dev, static int c_can_handle_lost_msg_obj(struct net_device *dev,
int iface, int ctrl_mask, int iface, int objno, u32 ctrl)
int obj)
{
struct c_can_priv *priv = netdev_priv(dev);
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
ctrl_mask & ~(IF_MCONT_MSGLST |
IF_MCONT_INTPND | IF_MCONT_NEWDAT));
c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
}
static void c_can_handle_lost_msg_obj(struct net_device *dev,
int iface, int objno)
{ {
struct c_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats; struct net_device_stats *stats = &dev->stats;
struct sk_buff *skb; struct c_can_priv *priv = netdev_priv(dev);
struct can_frame *frame; struct can_frame *frame;
struct sk_buff *skb;
netdev_err(dev, "msg lost in buffer %d\n", objno); ctrl &= ~(IF_MCONT_MSGLST | IF_MCONT_INTPND | IF_MCONT_NEWDAT);
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface), ctrl);
c_can_object_get(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST); c_can_object_put(dev, iface, objno, IF_COMM_CONTROL);
priv->write_reg(priv, C_CAN_IFACE(MSGCTRL_REG, iface),
IF_MCONT_CLR_MSGLST);
c_can_object_put(dev, 0, objno, IF_COMM_CONTROL);
/* create an error msg */ /* create an error msg */
skb = alloc_can_err_skb(dev, &frame); skb = alloc_can_err_skb(dev, &frame);
if (unlikely(!skb)) if (unlikely(!skb))
return; return 0;
frame->can_id |= CAN_ERR_CRTL; frame->can_id |= CAN_ERR_CRTL;
frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
...@@ -433,6 +388,7 @@ static void c_can_handle_lost_msg_obj(struct net_device *dev, ...@@ -433,6 +388,7 @@ static void c_can_handle_lost_msg_obj(struct net_device *dev,
stats->rx_over_errors++; stats->rx_over_errors++;
netif_receive_skb(skb); netif_receive_skb(skb);
return 1;
} }
static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
...@@ -477,9 +433,6 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl) ...@@ -477,9 +433,6 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
stats->rx_packets++; stats->rx_packets++;
stats->rx_bytes += frame->can_dlc; stats->rx_bytes += frame->can_dlc;
can_led_event(dev, CAN_LED_EVENT_RX);
return 0; return 0;
} }
...@@ -548,10 +501,12 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, ...@@ -548,10 +501,12 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
if (can_dropped_invalid_skb(dev, skb)) if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK; return NETDEV_TX_OK;
spin_lock_bh(&priv->xmit_lock);
msg_obj_no = get_tx_next_msg_obj(priv); msg_obj_no = get_tx_next_msg_obj(priv);
/* prepare message object for transmission */ /* prepare message object for transmission */
c_can_write_msg_object(dev, 0, frame, msg_obj_no); c_can_write_msg_object(dev, IF_TX, frame, msg_obj_no);
priv->dlc[msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST] = frame->can_dlc;
can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST); can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
/* /*
...@@ -562,10 +517,26 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb, ...@@ -562,10 +517,26 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) || if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) ||
(priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0) (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0)
netif_stop_queue(dev); netif_stop_queue(dev);
spin_unlock_bh(&priv->xmit_lock);
return NETDEV_TX_OK; return NETDEV_TX_OK;
} }
static int c_can_wait_for_ctrl_init(struct net_device *dev,
struct c_can_priv *priv, u32 init)
{
int retry = 0;
while (init != (priv->read_reg(priv, C_CAN_CTRL_REG) & CONTROL_INIT)) {
udelay(10);
if (retry++ > 1000) {
netdev_err(dev, "CCTRL: set CONTROL_INIT failed\n");
return -EIO;
}
}
return 0;
}
static int c_can_set_bittiming(struct net_device *dev) static int c_can_set_bittiming(struct net_device *dev)
{ {
unsigned int reg_btr, reg_brpe, ctrl_save; unsigned int reg_btr, reg_brpe, ctrl_save;
...@@ -573,6 +544,7 @@ static int c_can_set_bittiming(struct net_device *dev) ...@@ -573,6 +544,7 @@ static int c_can_set_bittiming(struct net_device *dev)
u32 ten_bit_brp; u32 ten_bit_brp;
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
const struct can_bittiming *bt = &priv->can.bittiming; const struct can_bittiming *bt = &priv->can.bittiming;
int res;
/* c_can provides a 6-bit brp and 4-bit brpe fields */ /* c_can provides a 6-bit brp and 4-bit brpe fields */
ten_bit_brp = bt->brp - 1; ten_bit_brp = bt->brp - 1;
...@@ -590,13 +562,17 @@ static int c_can_set_bittiming(struct net_device *dev) ...@@ -590,13 +562,17 @@ static int c_can_set_bittiming(struct net_device *dev)
"setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe); "setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe);
ctrl_save = priv->read_reg(priv, C_CAN_CTRL_REG); ctrl_save = priv->read_reg(priv, C_CAN_CTRL_REG);
priv->write_reg(priv, C_CAN_CTRL_REG, ctrl_save &= ~CONTROL_INIT;
ctrl_save | CONTROL_CCE | CONTROL_INIT); priv->write_reg(priv, C_CAN_CTRL_REG, CONTROL_CCE | CONTROL_INIT);
res = c_can_wait_for_ctrl_init(dev, priv, CONTROL_INIT);
if (res)
return res;
priv->write_reg(priv, C_CAN_BTR_REG, reg_btr); priv->write_reg(priv, C_CAN_BTR_REG, reg_btr);
priv->write_reg(priv, C_CAN_BRPEXT_REG, reg_brpe); priv->write_reg(priv, C_CAN_BRPEXT_REG, reg_brpe);
priv->write_reg(priv, C_CAN_CTRL_REG, ctrl_save); priv->write_reg(priv, C_CAN_CTRL_REG, ctrl_save);
return 0; return c_can_wait_for_ctrl_init(dev, priv, 0);
} }
/* /*
...@@ -614,14 +590,14 @@ static void c_can_configure_msg_objects(struct net_device *dev) ...@@ -614,14 +590,14 @@ static void c_can_configure_msg_objects(struct net_device *dev)
/* first invalidate all message objects */ /* first invalidate all message objects */
for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++) for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++)
c_can_inval_msg_object(dev, 0, i); c_can_inval_msg_object(dev, IF_RX, i);
/* setup receive message objects */ /* setup receive message objects */
for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++) for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++)
c_can_setup_receive_object(dev, 0, i, 0, 0, c_can_setup_receive_object(dev, IF_RX, i, 0, 0,
(IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB); (IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB);
c_can_setup_receive_object(dev, 0, C_CAN_MSG_OBJ_RX_LAST, 0, 0, c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK); IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK);
} }
...@@ -631,7 +607,7 @@ static void c_can_configure_msg_objects(struct net_device *dev) ...@@ -631,7 +607,7 @@ static void c_can_configure_msg_objects(struct net_device *dev)
* - set operating mode * - set operating mode
* - configure message objects * - configure message objects
*/ */
static void c_can_chip_config(struct net_device *dev) static int c_can_chip_config(struct net_device *dev)
{ {
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
...@@ -668,15 +644,18 @@ static void c_can_chip_config(struct net_device *dev) ...@@ -668,15 +644,18 @@ static void c_can_chip_config(struct net_device *dev)
priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED); priv->write_reg(priv, C_CAN_STS_REG, LEC_UNUSED);
/* set bittiming params */ /* set bittiming params */
c_can_set_bittiming(dev); return c_can_set_bittiming(dev);
} }
static void c_can_start(struct net_device *dev) static int c_can_start(struct net_device *dev)
{ {
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
int err;
/* basic c_can configuration */ /* basic c_can configuration */
c_can_chip_config(dev); err = c_can_chip_config(dev);
if (err)
return err;
priv->can.state = CAN_STATE_ERROR_ACTIVE; priv->can.state = CAN_STATE_ERROR_ACTIVE;
...@@ -685,6 +664,8 @@ static void c_can_start(struct net_device *dev) ...@@ -685,6 +664,8 @@ static void c_can_start(struct net_device *dev)
/* enable status change, error and module interrupts */ /* enable status change, error and module interrupts */
c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS); c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
return 0;
} }
static void c_can_stop(struct net_device *dev) static void c_can_stop(struct net_device *dev)
...@@ -700,9 +681,13 @@ static void c_can_stop(struct net_device *dev) ...@@ -700,9 +681,13 @@ static void c_can_stop(struct net_device *dev)
static int c_can_set_mode(struct net_device *dev, enum can_mode mode) static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
{ {
int err;
switch (mode) { switch (mode) {
case CAN_MODE_START: case CAN_MODE_START:
c_can_start(dev); err = c_can_start(dev);
if (err)
return err;
netif_wake_queue(dev); netif_wake_queue(dev);
break; break;
default: default:
...@@ -740,8 +725,6 @@ static int c_can_get_berr_counter(const struct net_device *dev, ...@@ -740,8 +725,6 @@ static int c_can_get_berr_counter(const struct net_device *dev,
} }
/* /*
* theory of operation:
*
* priv->tx_echo holds the number of the oldest can_frame put for * priv->tx_echo holds the number of the oldest can_frame put for
* transmission into the hardware, but not yet ACKed by the CAN tx * transmission into the hardware, but not yet ACKed by the CAN tx
* complete IRQ. * complete IRQ.
...@@ -752,33 +735,113 @@ static int c_can_get_berr_counter(const struct net_device *dev, ...@@ -752,33 +735,113 @@ static int c_can_get_berr_counter(const struct net_device *dev,
*/ */
static void c_can_do_tx(struct net_device *dev) static void c_can_do_tx(struct net_device *dev)
{ {
u32 val;
u32 msg_obj_no;
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats; struct net_device_stats *stats = &dev->stats;
u32 val, obj, pkts = 0, bytes = 0;
for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) { spin_lock_bh(&priv->xmit_lock);
msg_obj_no = get_tx_echo_msg_obj(priv);
for (; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
obj = get_tx_echo_msg_obj(priv->tx_echo);
val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG); val = c_can_read_reg32(priv, C_CAN_TXRQST1_REG);
if (!(val & (1 << (msg_obj_no - 1)))) {
can_get_echo_skb(dev, if (val & (1 << (obj - 1)))
msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
c_can_object_get(dev, 0, msg_obj_no, IF_COMM_ALL);
stats->tx_bytes += priv->read_reg(priv,
C_CAN_IFACE(MSGCTRL_REG, 0))
& IF_MCONT_DLC_MASK;
stats->tx_packets++;
can_led_event(dev, CAN_LED_EVENT_TX);
c_can_inval_msg_object(dev, 0, msg_obj_no);
} else {
break; break;
}
can_get_echo_skb(dev, obj - C_CAN_MSG_OBJ_TX_FIRST);
bytes += priv->dlc[obj - C_CAN_MSG_OBJ_TX_FIRST];
pkts++;
c_can_inval_msg_object(dev, IF_TX, obj);
} }
/* restart queue if wrap-up or if queue stalled on last pkt */ /* restart queue if wrap-up or if queue stalled on last pkt */
if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) || if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) ||
((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0)) ((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0))
netif_wake_queue(dev); netif_wake_queue(dev);
spin_unlock_bh(&priv->xmit_lock);
if (pkts) {
stats->tx_bytes += bytes;
stats->tx_packets += pkts;
can_led_event(dev, CAN_LED_EVENT_TX);
}
}
/*
* If we have a gap in the pending bits, that means we either
* raced with the hardware or failed to readout all upper
* objects in the last run due to quota limit.
*/
static u32 c_can_adjust_pending(u32 pend)
{
u32 weight, lasts;
if (pend == RECEIVE_OBJECT_BITS)
return pend;
/*
* If the last set bit is larger than the number of pending
* bits we have a gap.
*/
weight = hweight32(pend);
lasts = fls(pend);
/* If the bits are linear, nothing to do */
if (lasts == weight)
return pend;
/*
* Find the first set bit after the gap. We walk backwards
* from the last set bit.
*/
for (lasts--; pend & (1 << (lasts - 1)); lasts--);
return pend & ~((1 << lasts) - 1);
}
static int c_can_read_objects(struct net_device *dev, struct c_can_priv *priv,
u32 pend, int quota)
{
u32 pkts = 0, ctrl, obj, mcmd;
while ((obj = ffs(pend)) && quota > 0) {
pend &= ~BIT(obj - 1);
mcmd = obj < C_CAN_MSG_RX_LOW_LAST ?
IF_COMM_RCV_LOW : IF_COMM_RCV_HIGH;
c_can_object_get(dev, IF_RX, obj, mcmd);
ctrl = priv->read_reg(priv, C_CAN_IFACE(MSGCTRL_REG, IF_RX));
if (ctrl & IF_MCONT_MSGLST) {
int n = c_can_handle_lost_msg_obj(dev, IF_RX, obj, ctrl);
pkts += n;
quota -= n;
continue;
}
/*
* This really should not happen, but this covers some
* odd HW behaviour. Do not remove that unless you
* want to brick your machine.
*/
if (!(ctrl & IF_MCONT_NEWDAT))
continue;
/* read the data from the message object */
c_can_read_msg_object(dev, IF_RX, ctrl);
if (obj == C_CAN_MSG_RX_LOW_LAST)
/* activate all lower message objects */
c_can_activate_all_lower_rx_msg_obj(dev, IF_RX, ctrl);
pkts++;
quota--;
}
return pkts;
} }
/* /*
...@@ -805,10 +868,8 @@ static void c_can_do_tx(struct net_device *dev) ...@@ -805,10 +868,8 @@ static void c_can_do_tx(struct net_device *dev)
*/ */
static int c_can_do_rx_poll(struct net_device *dev, int quota) static int c_can_do_rx_poll(struct net_device *dev, int quota)
{ {
u32 num_rx_pkts = 0;
unsigned int msg_obj, msg_ctrl_save;
struct c_can_priv *priv = netdev_priv(dev); struct c_can_priv *priv = netdev_priv(dev);
u16 val; u32 pkts = 0, pend = 0, toread, n;
/* /*
* It is faster to read only one 16bit register. This is only possible * It is faster to read only one 16bit register. This is only possible
...@@ -817,49 +878,31 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota) ...@@ -817,49 +878,31 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16, BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16,
"Implementation does not support more message objects than 16"); "Implementation does not support more message objects than 16");
while (quota > 0 && (val = priv->read_reg(priv, C_CAN_INTPND1_REG))) { while (quota > 0) {
while ((msg_obj = ffs(val)) && quota > 0) { if (!pend) {
val &= ~BIT(msg_obj - 1); pend = priv->read_reg(priv, C_CAN_INTPND1_REG);
if (!pend)
c_can_object_get(dev, 0, msg_obj, IF_COMM_ALL & break;
~IF_COMM_TXRQST); /*
msg_ctrl_save = priv->read_reg(priv, * If the pending field has a gap, handle the
C_CAN_IFACE(MSGCTRL_REG, 0)); * bits above the gap first.
*/
if (msg_ctrl_save & IF_MCONT_MSGLST) { toread = c_can_adjust_pending(pend);
c_can_handle_lost_msg_obj(dev, 0, msg_obj); } else {
num_rx_pkts++; toread = pend;
quota--;
continue;
}
if (msg_ctrl_save & IF_MCONT_EOB)
return num_rx_pkts;
if (!(msg_ctrl_save & IF_MCONT_NEWDAT))
continue;
/* read the data from the message object */
c_can_read_msg_object(dev, 0, msg_ctrl_save);
if (msg_obj < C_CAN_MSG_RX_LOW_LAST)
c_can_mark_rx_msg_obj(dev, 0,
msg_ctrl_save, msg_obj);
else if (msg_obj > C_CAN_MSG_RX_LOW_LAST)
/* activate this msg obj */
c_can_activate_rx_msg_obj(dev, 0,
msg_ctrl_save, msg_obj);
else if (msg_obj == C_CAN_MSG_RX_LOW_LAST)
/* activate all lower message objects */
c_can_activate_all_lower_rx_msg_obj(dev,
0, msg_ctrl_save);
num_rx_pkts++;
quota--;
} }
/* Remove the bits from pend */
pend &= ~toread;
/* Read the objects */
n = c_can_read_objects(dev, priv, toread, quota);
pkts += n;
quota -= n;
} }
return num_rx_pkts; if (pkts)
can_led_event(dev, CAN_LED_EVENT_RX);
return pkts;
} }
static inline int c_can_has_and_handle_berr(struct c_can_priv *priv) static inline int c_can_has_and_handle_berr(struct c_can_priv *priv)
...@@ -1133,17 +1176,20 @@ static int c_can_open(struct net_device *dev) ...@@ -1133,17 +1176,20 @@ static int c_can_open(struct net_device *dev)
goto exit_irq_fail; goto exit_irq_fail;
} }
napi_enable(&priv->napi); /* start the c_can controller */
err = c_can_start(dev);
if (err)
goto exit_start_fail;
can_led_event(dev, CAN_LED_EVENT_OPEN); can_led_event(dev, CAN_LED_EVENT_OPEN);
/* start the c_can controller */ napi_enable(&priv->napi);
c_can_start(dev);
netif_start_queue(dev); netif_start_queue(dev);
return 0; return 0;
exit_start_fail:
free_irq(dev->irq, dev);
exit_irq_fail: exit_irq_fail:
close_candev(dev); close_candev(dev);
exit_open_fail: exit_open_fail:
...@@ -1180,6 +1226,7 @@ struct net_device *alloc_c_can_dev(void) ...@@ -1180,6 +1226,7 @@ struct net_device *alloc_c_can_dev(void)
return NULL; return NULL;
priv = netdev_priv(dev); priv = netdev_priv(dev);
spin_lock_init(&priv->xmit_lock);
netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT); netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT);
priv->dev = dev; priv->dev = dev;
...@@ -1260,15 +1307,16 @@ int c_can_power_up(struct net_device *dev) ...@@ -1260,15 +1307,16 @@ int c_can_power_up(struct net_device *dev)
if (time_after(jiffies, time_out)) if (time_after(jiffies, time_out))
return -ETIMEDOUT; return -ETIMEDOUT;
c_can_start(dev); return c_can_start(dev);
return 0;
} }
EXPORT_SYMBOL_GPL(c_can_power_up); EXPORT_SYMBOL_GPL(c_can_power_up);
#endif #endif
void free_c_can_dev(struct net_device *dev) void free_c_can_dev(struct net_device *dev)
{ {
struct c_can_priv *priv = netdev_priv(dev);
netif_napi_del(&priv->napi);
free_candev(dev); free_candev(dev);
} }
EXPORT_SYMBOL_GPL(free_c_can_dev); EXPORT_SYMBOL_GPL(free_c_can_dev);
......
...@@ -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