* [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can
@ 2012-12-11 21:18 Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 1/7] pch_can: add spinlocks to protect tx objects Wolfgang Grandegger
` (7 more replies)
0 siblings, 8 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2012-12-11 21:18 UTC (permalink / raw)
To: linux-can
Cc: Alexander.Stein, Christian.Bendele, Michael Pellegrini,
bhupesh.sharma, Wolfgang Grandegger
Hello,
here is v3 of my patches for the C_CAN drivers.
Alexander reported strange results with write-readback of C_CAN register
showing up with concurrent I2C access. They might not be related to CAN
but to other problems on that board. At least Michael did not realize
them yet. Apart from that the c_can driver seems to work fine.
Anyway, we now know that the handling of reveive objects is not water-
proof. To fix out-of-order receipten we should implement an improved
algorithm as suggested by Marc here:
http://marc.info/?l=linux-can&m=135487418225533&w=2
I will not have time to look into that befoer Xmas. Volunteers are
welcome.
What's also missing is the suspend/resume handling. Then the pch_can
driver is obsolete and can be removed.
Wolfgang.
Changes since v2:
- re-use spin_[un]lock_[irqsave|irqrestore] to protect the tx objects
of the pch_can driver. spin_[un]lock_bh was not sufficient.
- adapted for the most recent version of the net-next tree
Changes since v1:
- use init callback after renaming it from initram
- use different sets of interface registers for rx and tx (like PCH_CAN)
- use spin_[un]lock_bh to protect the tx objects
Wolfgang Grandegger (7):
pch_can: add spinlocks to protect tx objects
c_can: rename callback "initram" to "init" to more general usage
c_can: use different sets of interface registers for rx and tx
c_can: add spinlock to protect tx objects
c_can_pci: introduce board specific PCI bar
c_can_pci: enable PCI bus master only for MSI
c_can_pci: add support for PCH CAN on Intel EG20T PCH
drivers/net/can/c_can/c_can.c | 102 ++++++++++++++++++++------------
drivers/net/can/c_can/c_can.h | 3 +-
drivers/net/can/c_can/c_can_pci.c | 57 +++++++++++++++++-
drivers/net/can/c_can/c_can_platform.c | 2 +-
drivers/net/can/pch_can.c | 11 ++++
5 files changed, 131 insertions(+), 44 deletions(-)
--
1.7.9.5
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC v3 1/7] pch_can: add spinlocks to protect tx objects
2012-12-11 21:18 [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
@ 2012-12-11 21:18 ` Wolfgang Grandegger
2013-06-20 14:29 ` Michael Pellegrini
[not found] ` <CAGY4fa-e6foJTzX9cKhNKgeJHfmyi_QsvO8k+94YVzHVM+BAtw@mail.gmail.com>
2012-12-11 21:18 ` [RFC v3 2/7] c_can: rename callback "initram" to "init" to more general usage Wolfgang Grandegger
` (6 subsequent siblings)
7 siblings, 2 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2012-12-11 21:18 UTC (permalink / raw)
To: linux-can
Cc: Alexander.Stein, Christian.Bendele, Michael Pellegrini,
bhupesh.sharma, Wolfgang Grandegger
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
drivers/net/can/pch_can.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 7d17485..af61961 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -182,6 +182,7 @@ struct pch_can_priv {
struct napi_struct napi;
int tx_obj; /* Point next Tx Obj index */
int use_msi;
+ spinlock_t lock; /* to protect tx objects */
};
static const struct can_bittiming_const pch_can_bittiming_const = {
@@ -722,8 +723,11 @@ static void pch_can_tx_complete(struct net_device *ndev, u32 int_stat)
{
struct pch_can_priv *priv = netdev_priv(ndev);
struct net_device_stats *stats = &(priv->ndev->stats);
+ unsigned long flags;
u32 dlc;
+ spin_lock_irqsave(&priv->lock, flags);
+
can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1);
iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND,
&priv->regs->ifregs[1].cmask);
@@ -734,6 +738,8 @@ static void pch_can_tx_complete(struct net_device *ndev, u32 int_stat)
stats->tx_packets++;
if (int_stat == PCH_TX_OBJ_END)
netif_wake_queue(ndev);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
}
static int pch_can_poll(struct napi_struct *napi, int quota)
@@ -894,6 +900,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
{
struct pch_can_priv *priv = netdev_priv(ndev);
struct can_frame *cf = (struct can_frame *)skb->data;
+ unsigned long flags;
int tx_obj_no;
int i;
u32 id2;
@@ -901,6 +908,8 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
if (can_dropped_invalid_skb(ndev, skb))
return NETDEV_TX_OK;
+ spin_lock_irqsave(&priv->lock, flags);
+
tx_obj_no = priv->tx_obj;
if (priv->tx_obj == PCH_TX_OBJ_END) {
if (ioread32(&priv->regs->treq2) & PCH_TREQ2_TX_MASK)
@@ -911,6 +920,8 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
priv->tx_obj++;
}
+ spin_unlock_irqrestore(&priv->lock, flags);
+
/* Setting the CMASK register. */
pch_can_bit_set(&priv->regs->ifregs[1].cmask, PCH_CMASK_ALL);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC v3 2/7] c_can: rename callback "initram" to "init" to more general usage
2012-12-11 21:18 [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 1/7] pch_can: add spinlocks to protect tx objects Wolfgang Grandegger
@ 2012-12-11 21:18 ` Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 3/7] c_can: use different sets of interface registers for rx and tx Wolfgang Grandegger
` (5 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2012-12-11 21:18 UTC (permalink / raw)
To: linux-can
Cc: Alexander.Stein, Christian.Bendele, Michael Pellegrini,
bhupesh.sharma, Wolfgang Grandegger
The callback "init" is called with the argument "true" when the
device is opened and with "false" when it is closed allowing for
device specific initialization and cleanup, e.g. raminit or reset.
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
drivers/net/can/c_can/c_can.c | 16 ++++++++--------
drivers/net/can/c_can/c_can.h | 2 +-
drivers/net/can/c_can/c_can_platform.c | 2 +-
3 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 5233b8f..3ae356f 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -233,10 +233,10 @@ static inline void c_can_pm_runtime_put_sync(const struct c_can_priv *priv)
pm_runtime_put_sync(priv->device);
}
-static inline void c_can_reset_ram(const struct c_can_priv *priv, bool enable)
+static inline void c_can_init(const struct c_can_priv *priv, bool enable)
{
- if (priv->raminit)
- priv->raminit(priv, enable);
+ if (priv->init)
+ priv->init(priv, enable);
}
static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
@@ -1096,7 +1096,7 @@ static int c_can_open(struct net_device *dev)
struct c_can_priv *priv = netdev_priv(dev);
c_can_pm_runtime_get_sync(priv);
- c_can_reset_ram(priv, true);
+ c_can_init(priv, true);
/* open the can device */
err = open_candev(dev);
@@ -1125,7 +1125,7 @@ static int c_can_open(struct net_device *dev)
exit_irq_fail:
close_candev(dev);
exit_open_fail:
- c_can_reset_ram(priv, false);
+ c_can_init(priv, false);
c_can_pm_runtime_put_sync(priv);
return err;
}
@@ -1140,7 +1140,7 @@ static int c_can_close(struct net_device *dev)
free_irq(dev->irq, dev);
close_candev(dev);
- c_can_reset_ram(priv, false);
+ c_can_init(priv, false);
c_can_pm_runtime_put_sync(priv);
return 0;
@@ -1198,7 +1198,7 @@ int c_can_power_down(struct net_device *dev)
c_can_stop(dev);
- c_can_reset_ram(priv, false);
+ c_can_init(priv, false);
c_can_pm_runtime_put_sync(priv);
return 0;
@@ -1217,7 +1217,7 @@ int c_can_power_up(struct net_device *dev)
WARN_ON(priv->type != BOSCH_D_CAN);
c_can_pm_runtime_get_sync(priv);
- c_can_reset_ram(priv, true);
+ c_can_init(priv, true);
/* Clear PDR and INIT bits */
val = priv->read_reg(priv, C_CAN_CTRL_EX_REG);
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index d2e1c21..4baf3f6 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -171,7 +171,7 @@ struct c_can_priv {
enum c_can_dev_id type;
u32 __iomem *raminit_ctrlreg;
unsigned int instance;
- void (*raminit) (const struct c_can_priv *priv, bool enable);
+ void (*init) (const struct c_can_priv *priv, bool enable);
};
struct net_device *alloc_c_can_dev(void);
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index d63b919..d9551d1 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -205,7 +205,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
if (!priv->raminit_ctrlreg || priv->instance < 0)
dev_info(&pdev->dev, "control memory is not used for raminit\n");
else
- priv->raminit = c_can_hw_raminit;
+ priv->init = c_can_hw_raminit;
break;
default:
ret = -EINVAL;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC v3 3/7] c_can: use different sets of interface registers for rx and tx
2012-12-11 21:18 [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 1/7] pch_can: add spinlocks to protect tx objects Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 2/7] c_can: rename callback "initram" to "init" to more general usage Wolfgang Grandegger
@ 2012-12-11 21:18 ` Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 4/7] c_can: add spinlock to protect tx objects Wolfgang Grandegger
` (4 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2012-12-11 21:18 UTC (permalink / raw)
To: linux-can
Cc: Alexander.Stein, Christian.Bendele, Michael Pellegrini,
bhupesh.sharma, Wolfgang Grandegger
To avoid conflicts between CPU access to the message RAM we now
use the first set of interface registers for RX and the second
for TX.
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
drivers/net/can/c_can/c_can.c | 73 ++++++++++++++++++++++++-----------------
1 file changed, 42 insertions(+), 31 deletions(-)
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 3ae356f..b0738c9 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -158,6 +158,12 @@
#define C_CAN_NEXT_MSG_OBJ_MASK (C_CAN_MSG_OBJ_TX_NUM - 1)
#define RECEIVE_OBJECT_BITS 0x0000ffff
+/* interface register sets used for rx and tx */
+enum c_can_iface {
+ C_CAN_IFACE_RX = 0,
+ C_CAN_IFACE_TX = 1,
+};
+
/* status interrupt */
#define STATUS_INTERRUPT 0x8000
@@ -272,7 +278,8 @@ static void c_can_enable_all_interrupts(struct c_can_priv *priv,
priv->write_reg(priv, C_CAN_CTRL_REG, cntrl_save);
}
-static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface)
+static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv,
+ enum c_can_iface iface)
{
int count = MIN_TIMEOUT_VALUE;
@@ -290,7 +297,7 @@ static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface)
}
static inline void c_can_object_get(struct net_device *dev,
- int iface, int objno, int mask)
+ enum c_can_iface iface, int objno, int mask)
{
struct c_can_priv *priv = netdev_priv(dev);
@@ -310,7 +317,7 @@ static inline void c_can_object_get(struct net_device *dev,
}
static inline void c_can_object_put(struct net_device *dev,
- int iface, int objno, int mask)
+ enum c_can_iface iface, int objno, int mask)
{
struct c_can_priv *priv = netdev_priv(dev);
@@ -330,7 +337,7 @@ static inline void c_can_object_put(struct net_device *dev,
}
static void c_can_write_msg_object(struct net_device *dev,
- int iface, struct can_frame *frame, int objno)
+ enum c_can_iface iface, struct can_frame *frame, int objno)
{
int i;
u16 flags = 0;
@@ -366,8 +373,7 @@ static void c_can_write_msg_object(struct net_device *dev,
}
static inline void c_can_mark_rx_msg_obj(struct net_device *dev,
- int iface, int ctrl_mask,
- int obj)
+ enum c_can_iface iface, int ctrl_mask, int obj)
{
struct c_can_priv *priv = netdev_priv(dev);
@@ -378,8 +384,7 @@ static inline void c_can_mark_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 ctrl_mask)
+ enum c_can_iface iface, int ctrl_mask)
{
int i;
struct c_can_priv *priv = netdev_priv(dev);
@@ -393,8 +398,7 @@ static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
}
static inline void c_can_activate_rx_msg_obj(struct net_device *dev,
- int iface, int ctrl_mask,
- int obj)
+ enum c_can_iface iface, int ctrl_mask, int obj)
{
struct c_can_priv *priv = netdev_priv(dev);
@@ -405,7 +409,7 @@ static inline void c_can_activate_rx_msg_obj(struct net_device *dev,
}
static void c_can_handle_lost_msg_obj(struct net_device *dev,
- int iface, int objno)
+ enum c_can_iface iface, int objno)
{
struct c_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
@@ -434,7 +438,8 @@ static void c_can_handle_lost_msg_obj(struct net_device *dev,
netif_receive_skb(skb);
}
-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,
+ enum c_can_iface iface, int ctrl)
{
u16 flags, data;
int i;
@@ -480,7 +485,8 @@ static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
return 0;
}
-static void c_can_setup_receive_object(struct net_device *dev, int iface,
+static void c_can_setup_receive_object(struct net_device *dev,
+ enum c_can_iface iface,
int objno, unsigned int mask,
unsigned int id, unsigned int mcont)
{
@@ -503,7 +509,8 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface,
c_can_read_reg32(priv, C_CAN_MSGVAL1_REG));
}
-static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
+static void c_can_inval_msg_object(struct net_device *dev,
+ enum c_can_iface iface, int objno)
{
struct c_can_priv *priv = netdev_priv(dev);
@@ -544,7 +551,7 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
msg_obj_no = get_tx_next_msg_obj(priv);
/* prepare message object for transmission */
- c_can_write_msg_object(dev, 0, frame, msg_obj_no);
+ c_can_write_msg_object(dev, C_CAN_IFACE_TX, frame, msg_obj_no);
can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
/*
@@ -606,16 +613,18 @@ static void c_can_configure_msg_objects(struct net_device *dev)
int i;
/* first invalidate all message objects */
- for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++)
- c_can_inval_msg_object(dev, 0, i);
+ for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_OBJ_RX_LAST; i++)
+ c_can_inval_msg_object(dev, C_CAN_IFACE_RX, i);
+ for (i = C_CAN_MSG_OBJ_TX_FIRST; i <= C_CAN_MSG_OBJ_TX_LAST; i++)
+ c_can_inval_msg_object(dev, C_CAN_IFACE_TX, i);
/* setup receive message objects */
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, C_CAN_IFACE_RX, i, 0, 0,
(IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB);
- c_can_setup_receive_object(dev, 0, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
- IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK);
+ c_can_setup_receive_object(dev, C_CAN_IFACE_RX, C_CAN_MSG_OBJ_RX_LAST,
+ 0, 0, IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK);
}
/*
@@ -748,10 +757,10 @@ static void c_can_do_tx(struct net_device *dev)
can_get_echo_skb(dev,
msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
stats->tx_bytes += priv->read_reg(priv,
- C_CAN_IFACE(MSGCTRL_REG, 0))
- & IF_MCONT_DLC_MASK;
+ C_CAN_IFACE(MSGCTRL_REG, C_CAN_IFACE_TX))
+ & IF_MCONT_DLC_MASK;
stats->tx_packets++;
- c_can_inval_msg_object(dev, 0, msg_obj_no);
+ c_can_inval_msg_object(dev, C_CAN_IFACE_TX, msg_obj_no);
} else {
break;
}
@@ -801,16 +810,17 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
* message object n, we need to handle the same properly.
*/
if (val & (1 << (msg_obj - 1))) {
- c_can_object_get(dev, 0, msg_obj, IF_COMM_ALL &
- ~IF_COMM_TXRQST);
+ c_can_object_get(dev, C_CAN_IFACE_RX, msg_obj,
+ IF_COMM_ALL & ~IF_COMM_TXRQST);
msg_ctrl_save = priv->read_reg(priv,
- C_CAN_IFACE(MSGCTRL_REG, 0));
+ C_CAN_IFACE(MSGCTRL_REG, C_CAN_IFACE_RX));
if (msg_ctrl_save & IF_MCONT_EOB)
return num_rx_pkts;
if (msg_ctrl_save & IF_MCONT_MSGLST) {
- c_can_handle_lost_msg_obj(dev, 0, msg_obj);
+ c_can_handle_lost_msg_obj(dev, C_CAN_IFACE_RX,
+ msg_obj);
num_rx_pkts++;
quota--;
continue;
@@ -820,19 +830,20 @@ static int c_can_do_rx_poll(struct net_device *dev, int quota)
continue;
/* read the data from the message object */
- c_can_read_msg_object(dev, 0, msg_ctrl_save);
+ c_can_read_msg_object(dev, C_CAN_IFACE_RX,
+ msg_ctrl_save);
if (msg_obj < C_CAN_MSG_RX_LOW_LAST)
- c_can_mark_rx_msg_obj(dev, 0,
+ c_can_mark_rx_msg_obj(dev, C_CAN_IFACE_RX,
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,
+ c_can_activate_rx_msg_obj(dev, C_CAN_IFACE_RX,
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);
+ C_CAN_IFACE_RX, msg_ctrl_save);
num_rx_pkts++;
quota--;
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC v3 4/7] c_can: add spinlock to protect tx objects
2012-12-11 21:18 [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
` (2 preceding siblings ...)
2012-12-11 21:18 ` [RFC v3 3/7] c_can: use different sets of interface registers for rx and tx Wolfgang Grandegger
@ 2012-12-11 21:18 ` Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 5/7] c_can_pci: introduce board specific PCI bar Wolfgang Grandegger
` (3 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2012-12-11 21:18 UTC (permalink / raw)
To: linux-can
Cc: Alexander.Stein, Christian.Bendele, Michael Pellegrini,
bhupesh.sharma, Wolfgang Grandegger
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
drivers/net/can/c_can/c_can.c | 13 +++++++++++++
drivers/net/can/c_can/c_can.h | 1 +
2 files changed, 14 insertions(+)
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index b0738c9..30646d6 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -34,6 +34,7 @@
#include <linux/if_ether.h>
#include <linux/list.h>
#include <linux/io.h>
+#include <linux/spinlock.h>
#include <linux/pm_runtime.h>
#include <linux/can.h>
@@ -544,10 +545,13 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
u32 msg_obj_no;
struct c_can_priv *priv = netdev_priv(dev);
struct can_frame *frame = (struct can_frame *)skb->data;
+ unsigned long flags;
if (can_dropped_invalid_skb(dev, skb))
return NETDEV_TX_OK;
+ spin_lock_irqsave(&priv->lock, flags);
+
msg_obj_no = get_tx_next_msg_obj(priv);
/* prepare message object for transmission */
@@ -563,6 +567,8 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
(priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0)
netif_stop_queue(dev);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
return NETDEV_TX_OK;
}
@@ -749,6 +755,9 @@ static void c_can_do_tx(struct net_device *dev)
u32 msg_obj_no;
struct c_can_priv *priv = netdev_priv(dev);
struct net_device_stats *stats = &dev->stats;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
msg_obj_no = get_tx_echo_msg_obj(priv);
@@ -770,6 +779,8 @@ static void c_can_do_tx(struct net_device *dev)
if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) ||
((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0))
netif_wake_queue(dev);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
}
/*
@@ -1177,6 +1188,8 @@ struct net_device *alloc_c_can_dev(void)
CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_BERR_REPORTING;
+ spin_lock_init(&priv->lock);
+
return dev;
}
EXPORT_SYMBOL_GPL(alloc_c_can_dev);
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 4baf3f6..3487d5e 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -172,6 +172,7 @@ struct c_can_priv {
u32 __iomem *raminit_ctrlreg;
unsigned int instance;
void (*init) (const struct c_can_priv *priv, bool enable);
+ spinlock_t lock; /* to protect tx and rx message objects */
};
struct net_device *alloc_c_can_dev(void);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC v3 5/7] c_can_pci: introduce board specific PCI bar
2012-12-11 21:18 [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
` (3 preceding siblings ...)
2012-12-11 21:18 ` [RFC v3 4/7] c_can: add spinlock to protect tx objects Wolfgang Grandegger
@ 2012-12-11 21:18 ` Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 6/7] c_can_pci: enable PCI bus master only for MSI Wolfgang Grandegger
` (2 subsequent siblings)
7 siblings, 0 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2012-12-11 21:18 UTC (permalink / raw)
To: linux-can
Cc: Alexander.Stein, Christian.Bendele, Michael Pellegrini,
bhupesh.sharma, Wolfgang Grandegger
Also fix minor issue with pci_iomap specifying size 0 for
mapping the full range.
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
drivers/net/can/c_can/c_can_pci.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index b374be7..3a2ac45 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -31,6 +31,8 @@ struct c_can_pci_data {
enum c_can_pci_reg_align reg_align;
/* Set the frequency */
unsigned int freq;
+ /* PCI bar number */
+ int bar;
};
/*
@@ -87,7 +89,7 @@ static int c_can_pci_probe(struct pci_dev *pdev,
pci_set_master(pdev);
pci_enable_msi(pdev);
- addr = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+ addr = pci_iomap(pdev, c_can_pci_data->bar, 0);
if (!addr) {
dev_err(&pdev->dev,
"device has no PCI memory resources, "
@@ -195,6 +197,7 @@ static struct c_can_pci_data c_can_sta2x11= {
.type = BOSCH_C_CAN,
.reg_align = C_CAN_REG_ALIGN_32,
.freq = 52000000, /* 52 Mhz */
+ .bar = 0,
};
#define C_CAN_ID(_vend, _dev, _driverdata) { \
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC v3 6/7] c_can_pci: enable PCI bus master only for MSI
2012-12-11 21:18 [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
` (4 preceding siblings ...)
2012-12-11 21:18 ` [RFC v3 5/7] c_can_pci: introduce board specific PCI bar Wolfgang Grandegger
@ 2012-12-11 21:18 ` Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 7/7] c_can_pci: add support for PCH CAN on Intel EG20T PCH Wolfgang Grandegger
2012-12-12 12:51 ` [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Christian Bendele
7 siblings, 0 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2012-12-11 21:18 UTC (permalink / raw)
To: linux-can
Cc: Alexander.Stein, Christian.Bendele, Michael Pellegrini,
bhupesh.sharma, Wolfgang Grandegger
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
drivers/net/can/c_can/c_can_pci.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index 3a2ac45..98562c2 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -86,8 +86,11 @@ static int c_can_pci_probe(struct pci_dev *pdev,
goto out_disable_device;
}
- pci_set_master(pdev);
- pci_enable_msi(pdev);
+ ret = pci_enable_msi(pdev);
+ if (!ret) {
+ dev_info(&pdev->dev, "MSI enabled\n");
+ pci_set_master(pdev);
+ }
addr = pci_iomap(pdev, c_can_pci_data->bar, 0);
if (!addr) {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC v3 7/7] c_can_pci: add support for PCH CAN on Intel EG20T PCH
2012-12-11 21:18 [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
` (5 preceding siblings ...)
2012-12-11 21:18 ` [RFC v3 6/7] c_can_pci: enable PCI bus master only for MSI Wolfgang Grandegger
@ 2012-12-11 21:18 ` Wolfgang Grandegger
2012-12-12 12:51 ` [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Christian Bendele
7 siblings, 0 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2012-12-11 21:18 UTC (permalink / raw)
To: linux-can
Cc: Alexander.Stein, Christian.Bendele, Michael Pellegrini,
bhupesh.sharma, Wolfgang Grandegger
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
drivers/net/can/c_can/c_can_pci.c | 45 +++++++++++++++++++++++++++++++++++++
1 file changed, 45 insertions(+)
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index 98562c2..c078a05 100644
--- a/drivers/net/can/c_can/c_can_pci.c
+++ b/drivers/net/can/c_can/c_can_pci.c
@@ -19,9 +19,13 @@
#include "c_can.h"
+#define PCI_DEVICE_ID_PCH_CAN 0x8818
+#define PCH_PCI_SOFT_RESET 0x01fc
+
enum c_can_pci_reg_align {
C_CAN_REG_ALIGN_16,
C_CAN_REG_ALIGN_32,
+ C_CAN_REG_32,
};
struct c_can_pci_data {
@@ -33,6 +37,8 @@ struct c_can_pci_data {
unsigned int freq;
/* PCI bar number */
int bar;
+ /* Callback for reset */
+ void (*init) (const struct c_can_priv *priv, bool enable);
};
/*
@@ -65,6 +71,29 @@ static void c_can_pci_write_reg_aligned_to_32bit(struct c_can_priv *priv,
writew(val, priv->base + 2 * priv->regs[index]);
}
+static u16 c_can_pci_read_reg_32bit(struct c_can_priv *priv,
+ enum reg index)
+{
+ return (u16)ioread32(priv->base + 2 * priv->regs[index]);
+}
+
+static void c_can_pci_write_reg_32bit(struct c_can_priv *priv,
+ enum reg index, u16 val)
+{
+ iowrite32((u32)val, priv->base + 2 * priv->regs[index]);
+}
+
+static void c_can_pci_reset_pch(const struct c_can_priv *priv, bool enable)
+{
+ if (enable) {
+ u32 __iomem *addr = priv->base + PCH_PCI_SOFT_RESET;
+
+ /* write to sw reset register */
+ iowrite32(1, addr);
+ iowrite32(0, addr);
+ }
+}
+
static int c_can_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
@@ -147,11 +176,17 @@ static int c_can_pci_probe(struct pci_dev *pdev,
priv->read_reg = c_can_pci_read_reg_aligned_to_16bit;
priv->write_reg = c_can_pci_write_reg_aligned_to_16bit;
break;
+ case C_CAN_REG_32:
+ priv->read_reg = c_can_pci_read_reg_32bit;
+ priv->write_reg = c_can_pci_write_reg_32bit;
+ break;
default:
ret = -EINVAL;
goto out_free_c_can;
}
+ priv->init = c_can_pci_data->init;
+
ret = register_c_can_dev(dev);
if (ret) {
dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
@@ -203,6 +238,14 @@ static struct c_can_pci_data c_can_sta2x11= {
.bar = 0,
};
+static struct c_can_pci_data c_can_pch = {
+ .type = BOSCH_C_CAN,
+ .reg_align = C_CAN_REG_32,
+ .freq = 50000000, /* 50 MHz */
+ .init = c_can_pci_reset_pch,
+ .bar = 1,
+};
+
#define C_CAN_ID(_vend, _dev, _driverdata) { \
PCI_DEVICE(_vend, _dev), \
.driver_data = (unsigned long)&_driverdata, \
@@ -210,6 +253,8 @@ static struct c_can_pci_data c_can_sta2x11= {
static DEFINE_PCI_DEVICE_TABLE(c_can_pci_tbl) = {
C_CAN_ID(PCI_VENDOR_ID_STMICRO, PCI_DEVICE_ID_STMICRO_CAN,
c_can_sta2x11),
+ C_CAN_ID(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_CAN,
+ c_can_pch),
{},
};
static struct pci_driver c_can_pci_driver = {
--
1.7.9.5
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can
2012-12-11 21:18 [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
` (6 preceding siblings ...)
2012-12-11 21:18 ` [RFC v3 7/7] c_can_pci: add support for PCH CAN on Intel EG20T PCH Wolfgang Grandegger
@ 2012-12-12 12:51 ` Christian Bendele
2012-12-12 13:42 ` Wolfgang Grandegger
7 siblings, 1 reply; 12+ messages in thread
From: Christian Bendele @ 2012-12-12 12:51 UTC (permalink / raw)
To: linux-can
Wolfgang Grandegger <wg <at> grandegger.com> writes:
>
> Hello,
>
> here is v3 of my patches for the C_CAN drivers.
What are those patches against? They don't apply against current mainstream
kernel (3.7)...
> Anyway, we now know that the handling of reveive objects is not water-
> proof. To fix out-of-order receipten we should implement an improved
> algorithm as suggested by Marc here:
>
> http://marc.info/?l=linux-can&m=135487418225533&w=2
I'd like to take a look at this, but unfortunately that link consistently times
out for me.
> I will not have time to look into that befoer Xmas. Volunteers are
> welcome.
Pfffffft.... Personally I wouldn't be opposed to investing some time in this,
but I don't think I could get this cleared through legal in any useful time
frame.
Definitely not before next year. If there's still a lot of work left in January
I'll give it a try.
Christian
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can
2012-12-12 12:51 ` [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Christian Bendele
@ 2012-12-12 13:42 ` Wolfgang Grandegger
0 siblings, 0 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2012-12-12 13:42 UTC (permalink / raw)
To: Christian Bendele; +Cc: linux-can
On 12/12/2012 01:51 PM, Christian Bendele wrote:
> Wolfgang Grandegger <wg <at> grandegger.com> writes:
>
>>
>> Hello,
>>
>> here is v3 of my patches for the C_CAN drivers.
>
> What are those patches against? They don't apply against current mainstream
> kernel (3.7)...
They are against David Miller's "net-next" tree, which you can get as
shown below:
git clone --reference=<another-recent-linux-tree> \
git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next
>> Anyway, we now know that the handling of reveive objects is not water-
>> proof. To fix out-of-order receipten we should implement an improved
>> algorithm as suggested by Marc here:
>>
>> http://marc.info/?l=linux-can&m=135487418225533&w=2
>
> I'd like to take a look at this, but unfortunately that link consistently times
> out for me.
Try http://news.gmane.org/gmane.linux.can instead. Search for:
7 Dec 10:55 Marc Kleine-Budde
*********** [RFC v2 0/7] pch_can/c_can: fix races and add PCH support to c_can
>> I will not have time to look into that befoer Xmas. Volunteers are
>> welcome.
>
> Pfffffft.... Personally I wouldn't be opposed to investing some time in this,
> but I don't think I could get this cleared through legal in any useful time
> frame.
> Definitely not before next year. If there's still a lot of work left in January
> I'll give it a try.
Hope I will find the time before beginning of next year. Anyway, would
be nice ifyou could give the c_can_pci driver a try to see if it works
better than the pch_can.
Thanks,
Wolfgang,
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC v3 1/7] pch_can: add spinlocks to protect tx objects
2012-12-11 21:18 ` [RFC v3 1/7] pch_can: add spinlocks to protect tx objects Wolfgang Grandegger
@ 2013-06-20 14:29 ` Michael Pellegrini
[not found] ` <CAGY4fa-e6foJTzX9cKhNKgeJHfmyi_QsvO8k+94YVzHVM+BAtw@mail.gmail.com>
1 sibling, 0 replies; 12+ messages in thread
From: Michael Pellegrini @ 2013-06-20 14:29 UTC (permalink / raw)
To: linux-can
Wolfgang Grandegger <wg <at> grandegger.com> writes:
>
> Signed-off-by: Wolfgang Grandegger <wg <at> grandegger.com>
> ---
> drivers/net/can/pch_can.c | 11 +++++++++++
> 1 file changed, 11 insertions(+)
>
> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
> index 7d17485..af61961 100644
> --- a/drivers/net/can/pch_can.c
> +++ b/drivers/net/can/pch_can.c
> <at> <at> -182,6 +182,7 <at> <at> struct pch_can_priv {
> struct napi_struct napi;
> int tx_obj; /* Point next Tx Obj index */
> int use_msi;
> + spinlock_t lock; /* to protect tx objects */
> };
>
> static const struct can_bittiming_const pch_can_bittiming_const = {
> <at> <at> -722,8 +723,11 <at> <at> static void
pch_can_tx_complete(struct net_device *ndev, u32 int_stat)
> {
> struct pch_can_priv *priv = netdev_priv(ndev);
> struct net_device_stats *stats = &(priv->ndev->stats);
> + unsigned long flags;
> u32 dlc;
>
> + spin_lock_irqsave(&priv->lock, flags);
> +
> can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1);
> iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND,
> &priv->regs->ifregs[1].cmask);
> <at> <at> -734,6 +738,8 <at> <at> static void
pch_can_tx_complete(struct net_device *ndev, u32 int_stat)
> stats->tx_packets++;
> if (int_stat == PCH_TX_OBJ_END)
> netif_wake_queue(ndev);
> +
> + spin_unlock_irqrestore(&priv->lock, flags);
> }
>
> static int pch_can_poll(struct napi_struct *napi, int quota)
> <at> <at> -894,6 +900,7 <at> <at> static netdev_tx_t pch_xmit(struct
sk_buff *skb, struct net_device *ndev)
> {
> struct pch_can_priv *priv = netdev_priv(ndev);
> struct can_frame *cf = (struct can_frame *)skb->data;
> + unsigned long flags;
> int tx_obj_no;
> int i;
> u32 id2;
> <at> <at> -901,6 +908,8 <at> <at> static netdev_tx_t pch_xmit(struct
sk_buff *skb, struct net_device *ndev)
> if (can_dropped_invalid_skb(ndev, skb))
> return NETDEV_TX_OK;
>
> + spin_lock_irqsave(&priv->lock, flags);
> +
> tx_obj_no = priv->tx_obj;
> if (priv->tx_obj == PCH_TX_OBJ_END) {
> if (ioread32(&priv->regs->treq2) & PCH_TREQ2_TX_MASK)
> <at> <at> -911,6 +920,8 <at> <at> static netdev_tx_t pch_xmit(struct
sk_buff *skb, struct net_device *ndev)
> priv->tx_obj++;
> }
>
> + spin_unlock_irqrestore(&priv->lock, flags);
> +
> /* Setting the CMASK register. */
> pch_can_bit_set(&priv->regs->ifregs[1].cmask, PCH_CMASK_ALL);
>
I believe I have found a bug in this changelist. When applying these
changes to the standard pch_can driver which ships with Ubuntu 12.04 (kernel
version 3.2.0-24.39), the race condition is still present and data
transmission ceases after a short period of time.
I applied the following modification and the data transmission problem went
away:
diff -c c-can-pci-v7/pch_can.c c-can-pci-v7-mrp/pch_can.c
*** c-can-pci-v7/pch_can.c 2012-11-25 05:09:13.000000000 -0500
--- c-can-pci-v7-mrp/pch_can.c 2012-11-26 11:29:11.350012074 -0500
***************
*** 921,928 ****
priv->tx_obj++;
}
- spin_unlock_irqrestore(&priv->lock, flags);
-
/* Setting the CMASK register. */
pch_can_bit_set(&priv->regs->ifregs[1].cmask, PCH_CMASK_ALL);
--- 921,926 ----
***************
*** 957,962 ****
--- 955,962 ----
pch_can_rw_msg_obj(&priv->regs->ifregs[1].creq, tx_obj_no);
+ spin_unlock_irqrestore(&priv->lock, flags);
+
return NETDEV_TX_OK;
}
This modification was suggested by Wolfgang during testing many months back
(I found it in my archive of test code); I think it got lost during the
shuffle between versions.
- Mike
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC v3 1/7] pch_can: add spinlocks to protect tx objects
[not found] ` <CAGY4fa-e6foJTzX9cKhNKgeJHfmyi_QsvO8k+94YVzHVM+BAtw@mail.gmail.com>
@ 2013-06-21 10:11 ` Wolfgang Grandegger
0 siblings, 0 replies; 12+ messages in thread
From: Wolfgang Grandegger @ 2013-06-21 10:11 UTC (permalink / raw)
To: Mike Pellegrini
Cc: linux-can, Alexander.Stein, Christian.Bendele, bhupesh.sharma
Hi Mike,
On 06/20/2013 04:23 PM, Mike Pellegrini wrote:
> I believe I have found a bug in this changelist. When applying these
> changes to the standard pch_can driver which ships with Ubuntu 12.04
> (kernel version 3.2.0-24.39), the race condition is still present and data
> transmission ceases after a short period of time.
>
> I applied the following modification and the data transmission problem went
> away:
>
> diff -c c-can-pci-v7/pch_can.c c-can-pci-v7-mrp/pch_can.c
> *** c-can-pci-v7/pch_can.c 2012-11-25 05:09:13.000000000 -0500
> --- c-can-pci-v7-mrp/pch_can.c 2012-11-26 11:29:11.350012074 -0500
> ***************
> *** 921,928 ****
> priv->tx_obj++;
> }
>
> - spin_unlock_irqrestore(&priv->lock, flags);
> -
> /* Setting the CMASK register. */
> pch_can_bit_set(&priv->regs->ifregs[1].cmask, PCH_CMASK_ALL);
>
> --- 921,926 ----
> ***************
> *** 957,962 ****
> --- 955,962 ----
>
> pch_can_rw_msg_obj(&priv->regs->ifregs[1].creq, tx_obj_no);
>
> + spin_unlock_irqrestore(&priv->lock, flags);
> +
> return NETDEV_TX_OK;
> }
>
> This modification was suggested by Wolfgang during testing many months back
> (I found it in my archive of test code); I think it got lost during the
> shuffle between versions.
Yes, I know. These patches did not go mainline yet because we know that
this driver does have other issues. Unfortunately the same is true for
the C_CAN based driver for the PCH I posted some time ago. That's a bad
situation but so far nobody with a hardware at hand made real progress
on the remaining issues. Maybe I should push my current patches
mainline, especially to introduce the C_CAN based driver.. and to make
the pch_can driver finally deprecated (or even remove it).
Wolfgang.
>
> - Mike
>
>
> On Tue, Dec 11, 2012 at 4:18 PM, Wolfgang Grandegger <wg@grandegger.com>wrote:
>
>> Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
>> ---
>> drivers/net/can/pch_can.c | 11 +++++++++++
>> 1 file changed, 11 insertions(+)
>>
>> diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
>> index 7d17485..af61961 100644
>> --- a/drivers/net/can/pch_can.c
>> +++ b/drivers/net/can/pch_can.c
>> @@ -182,6 +182,7 @@ struct pch_can_priv {
>> struct napi_struct napi;
>> int tx_obj; /* Point next Tx Obj index */
>> int use_msi;
>> + spinlock_t lock; /* to protect tx objects */
>> };
>>
>> static const struct can_bittiming_const pch_can_bittiming_const = {
>> @@ -722,8 +723,11 @@ static void pch_can_tx_complete(struct net_device
>> *ndev, u32 int_stat)
>> {
>> struct pch_can_priv *priv = netdev_priv(ndev);
>> struct net_device_stats *stats = &(priv->ndev->stats);
>> + unsigned long flags;
>> u32 dlc;
>>
>> + spin_lock_irqsave(&priv->lock, flags);
>> +
>> can_get_echo_skb(ndev, int_stat - PCH_RX_OBJ_END - 1);
>> iowrite32(PCH_CMASK_RX_TX_GET | PCH_CMASK_CLRINTPND,
>> &priv->regs->ifregs[1].cmask);
>> @@ -734,6 +738,8 @@ static void pch_can_tx_complete(struct net_device
>> *ndev, u32 int_stat)
>> stats->tx_packets++;
>> if (int_stat == PCH_TX_OBJ_END)
>> netif_wake_queue(ndev);
>> +
>> + spin_unlock_irqrestore(&priv->lock, flags);
>> }
>>
>> static int pch_can_poll(struct napi_struct *napi, int quota)
>> @@ -894,6 +900,7 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb,
>> struct net_device *ndev)
>> {
>> struct pch_can_priv *priv = netdev_priv(ndev);
>> struct can_frame *cf = (struct can_frame *)skb->data;
>> + unsigned long flags;
>> int tx_obj_no;
>> int i;
>> u32 id2;
>> @@ -901,6 +908,8 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb,
>> struct net_device *ndev)
>> if (can_dropped_invalid_skb(ndev, skb))
>> return NETDEV_TX_OK;
>>
>> + spin_lock_irqsave(&priv->lock, flags);
>> +
>> tx_obj_no = priv->tx_obj;
>> if (priv->tx_obj == PCH_TX_OBJ_END) {
>> if (ioread32(&priv->regs->treq2) & PCH_TREQ2_TX_MASK)
>> @@ -911,6 +920,8 @@ static netdev_tx_t pch_xmit(struct sk_buff *skb,
>> struct net_device *ndev)
>> priv->tx_obj++;
>> }
>>
>> + spin_unlock_irqrestore(&priv->lock, flags);
>> +
>> /* Setting the CMASK register. */
>> pch_can_bit_set(&priv->regs->ifregs[1].cmask, PCH_CMASK_ALL);
>>
>> --
>> 1.7.9.5
>>
>>
>
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2013-06-21 10:11 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-12-11 21:18 [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 1/7] pch_can: add spinlocks to protect tx objects Wolfgang Grandegger
2013-06-20 14:29 ` Michael Pellegrini
[not found] ` <CAGY4fa-e6foJTzX9cKhNKgeJHfmyi_QsvO8k+94YVzHVM+BAtw@mail.gmail.com>
2013-06-21 10:11 ` Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 2/7] c_can: rename callback "initram" to "init" to more general usage Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 3/7] c_can: use different sets of interface registers for rx and tx Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 4/7] c_can: add spinlock to protect tx objects Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 5/7] c_can_pci: introduce board specific PCI bar Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 6/7] c_can_pci: enable PCI bus master only for MSI Wolfgang Grandegger
2012-12-11 21:18 ` [RFC v3 7/7] c_can_pci: add support for PCH CAN on Intel EG20T PCH Wolfgang Grandegger
2012-12-12 12:51 ` [RFC v3 0/7] pch_can/c_can: fix races and add PCH support to c_can Christian Bendele
2012-12-12 13:42 ` Wolfgang Grandegger
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).