[PATCH 09/11] can: c_can: runtime message object divisions

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This commit prepares for per-device message object assignment.

Signed-off-by: Kurt Van Dijck <dev.kurt@xxxxxxxxxxxxxxxxxxxxxx>
---
 drivers/net/can/c_can/c_can.c          | 58 ++++++++++++++++++++++------------
 drivers/net/can/c_can/c_can.h          | 31 ++++++++----------
 drivers/net/can/c_can/c_can_pci.c      |  7 ++--
 drivers/net/can/c_can/c_can_platform.c |  4 +--
 4 files changed, 57 insertions(+), 43 deletions(-)

diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index cf2d47e..4ff9e49 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -173,10 +173,6 @@
 /* Wait for ~1 sec for INIT bit */
 #define INIT_WAIT_MS		1000
 
-/* Weight for rx-offload (napi) */
-#define C_CAN_OFFLOAD_WEIGHT	(C_CAN_MSG_OBJ_RX_NUM *2 \
-		+ C_CAN_MSG_OBJ_TX_NUM +16)
-
 /* c_can lec values */
 enum c_can_lec_type {
 	LEC_NO_ERROR = 0,
@@ -213,6 +209,11 @@ enum c_can_bus_error_types {
 	.brp_inc = 1,
 };
 
+static const int c_can_obj_counts[] = {
+	[BOSCH_C_CAN] = 32,
+	[BOSCH_D_CAN] = 32, /* the IP supports 128, we support only 32 */
+};
+
 static inline void c_can_pm_runtime_enable(const struct c_can_priv *priv)
 {
 	if (priv->device)
@@ -327,7 +328,7 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface,
 	 * first, i.e. clear the MSGVAL flag in the arbiter.
 	 */
 	if (rtr != (bool)test_bit(idx, &priv->tx_dir)) {
-		u32 obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+		u32 obj = idx + priv->obj.send_frst;
 
 		c_can_inval_msg_object(dev, iface, obj);
 		change_bit(idx, &priv->tx_dir);
@@ -360,9 +361,10 @@ static void c_can_setup_tx_object(struct net_device *dev, int iface,
 static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
 						       int iface)
 {
+	struct c_can_priv *priv = netdev_priv(dev);
 	int i;
 
-	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++)
+	for (i = priv->obj.recv_frst; i <= priv->obj.recv_last; i++)
 		c_can_object_get(dev, iface, i, IF_COMM_CLR_NEWDAT);
 }
 
@@ -474,10 +476,10 @@ static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
 	 * prioritized. The lowest buffer number wins.
 	 */
 	idx = fls(atomic_read(&priv->tx_active));
-	obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+	obj = idx + priv->obj.send_frst;
 
 	/* If this is the last buffer, stop the xmit queue */
-	if (idx == C_CAN_MSG_OBJ_TX_NUM - 1)
+	if (idx == priv->obj.send_count - 1)
 		netif_stop_queue(dev);
 	/*
 	 * Store the message in the interface so we can call
@@ -559,17 +561,18 @@ static int c_can_set_bittiming(struct net_device *dev)
  */
 static void c_can_configure_msg_objects(struct net_device *dev)
 {
+	struct c_can_priv *priv = netdev_priv(dev);
 	int i;
 
 	/* first invalidate all message objects */
-	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++)
+	for (i = priv->obj.recv_frst; i <= priv->obj.count; i++)
 		c_can_inval_msg_object(dev, IF_RX, i);
 
 	/* setup receive message objects */
-	for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++)
+	for (i = priv->obj.recv_frst; i < priv->obj.recv_last; i++)
 		c_can_setup_receive_object(dev, IF_RX, i, 0, 0, IF_MCONT_RCV);
 
-	c_can_setup_receive_object(dev, IF_RX, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
+	c_can_setup_receive_object(dev, IF_RX, priv->obj.recv_last, 0, 0,
 				   IF_MCONT_RCV_EOB);
 }
 
@@ -742,7 +745,7 @@ static void c_can_do_tx(struct net_device *dev)
 	while ((idx = ffs(pend))) {
 		idx--;
 		pend &= ~(1 << idx);
-		obj = idx + C_CAN_MSG_OBJ_TX_FIRST;
+		obj = idx + priv->obj.send_frst;
 		c_can_inval_tx_object(dev, IF_RX, obj);
 		skb = __can_get_echo_skb(dev, idx, &len);
 		can_rx_offload_irq_receive_skb(&priv->offload, skb);
@@ -753,7 +756,7 @@ static void c_can_do_tx(struct net_device *dev)
 	/* Clear the bits in the tx_active mask */
 	atomic_sub(clr, &priv->tx_active);
 
-	if (clr & (1 << (C_CAN_MSG_OBJ_TX_NUM - 1)))
+	if (clr & (1 << (priv->obj.send.count - 1)))
 		netif_wake_queue(dev);
 
 	if (pkts) {
@@ -768,11 +771,11 @@ static void c_can_do_tx(struct net_device *dev)
  * 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)
+static u32 c_can_adjust_pending(struct c_can_priv *priv, u32 pend)
 {
 	u32 weight, lasts;
 
-	if (pend == RECEIVE_OBJECT_BITS)
+	if (pend == priv->obj.recv_mask)
 		return pend;
 
 	/*
@@ -874,7 +877,7 @@ static int c_can_do_rx_poll(struct net_device *dev)
 	 * It is faster to read only one 16bit register. This is only possible
 	 * for a maximum number of 16 objects.
 	 */
-	BUILD_BUG_ON_MSG(C_CAN_MSG_OBJ_RX_LAST > 16,
+	WARN_ONCE(priv->obj.recv_last > 16,
 			"Implementation does not support more message objects than 16");
 
 	for (;;) {
@@ -886,7 +889,7 @@ static int c_can_do_rx_poll(struct net_device *dev)
 			 * If the pending field has a gap, handle the
 			 * bits above the gap first.
 			 */
-			toread = c_can_adjust_pending(pend);
+			toread = c_can_adjust_pending(priv, pend);
 		} else {
 			toread = pend;
 		}
@@ -1201,12 +1204,17 @@ static int c_can_close(struct net_device *dev)
 	return 0;
 }
 
-struct net_device *alloc_c_can_dev(void)
+struct net_device *alloc_c_can_dev(int type, int object_count)
 {
 	struct net_device *dev;
 	struct c_can_priv *priv;
+	int send_object_count;
+
+	if (!object_count || object_count > c_can_obj_counts[type])
+		object_count = c_can_obj_counts[type];
+	send_object_count = object_count/2;
 
-	dev = alloc_candev(sizeof(struct c_can_priv), C_CAN_MSG_OBJ_TX_NUM);
+	dev = alloc_candev(sizeof(struct c_can_priv), send_object_count);
 	if (!dev)
 		return NULL;
 
@@ -1220,6 +1228,16 @@ struct net_device *alloc_c_can_dev(void)
 					CAN_CTRLMODE_LISTENONLY |
 					CAN_CTRLMODE_BERR_REPORTING;
 
+	priv->type = type;
+	priv->obj.count = object_count;
+	priv->obj.send_count = send_object_count;
+	priv->obj.recv_count = object_count - send_object_count;
+	priv->obj.recv_frst = 1;
+	priv->obj.recv_last = priv->obj.recv_frst + priv->obj.recv_count - 1;
+	priv->obj.send_frst = priv->obj.recv_last + 1;
+	priv->obj.send_last = priv->obj.send_frst + priv->obj.send_count - 1;
+	priv->obj.recv_mask = (1ULL << priv->obj.recv_count) - 1;
+
 	return dev;
 }
 EXPORT_SYMBOL_GPL(alloc_c_can_dev);
@@ -1331,7 +1349,7 @@ int register_c_can_dev(struct net_device *dev)
 	dev->netdev_ops = &c_can_netdev_ops;
 
 	err = can_rx_offload_add_manual(dev, &priv->offload,
-					C_CAN_OFFLOAD_WEIGHT);
+			priv->obj.recv_count*2 + priv->obj.send.count + 16);
 	if (err)
 		goto register_exit_runtime_disable;
 
diff --git a/drivers/net/can/c_can/c_can.h b/drivers/net/can/c_can/c_can.h
index 8387b3f..70e3dc5 100644
--- a/drivers/net/can/c_can/c_can.h
+++ b/drivers/net/can/c_can/c_can.h
@@ -24,23 +24,6 @@
 
 #include <linux/can/rx-offload.h>
 
-/* 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 RECEIVE_OBJECT_BITS	0x0000ffff
-
 enum reg {
 	C_CAN_CTRL_REG = 0,
 	C_CAN_CTRL_EX_REG,
@@ -177,6 +160,7 @@ struct raminit_bits {
 
 struct c_can_driver_data {
 	enum c_can_dev_id id;
+	int object_count;
 
 	/* RAMINIT register description. Optional. */
 	const struct raminit_bits *raminit_bits; /* Array of START/DONE bit positions */
@@ -213,9 +197,20 @@ struct c_can_priv {
 	void (*raminit) (const struct c_can_priv *priv, bool enable);
 	u32 comm_rcv_high;
 	u32 rxmasked;
+	/* message object configuration */
+	struct c_can_obj_def {
+		int count;
+		int recv_count;
+		u32 recv_mask;
+		int recv_frst;
+		int recv_last;
+		int send_count;
+		int send_frst;
+		int send_last;
+	} obj;
 };
 
-struct net_device *alloc_c_can_dev(void);
+struct net_device *alloc_c_can_dev(int type, int object_count);
 void free_c_can_dev(struct net_device *dev);
 int register_c_can_dev(struct net_device *dev);
 void unregister_c_can_dev(struct net_device *dev);
diff --git a/drivers/net/can/c_can/c_can_pci.c b/drivers/net/can/c_can/c_can_pci.c
index 406b484..c960309 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 @@ enum c_can_pci_reg_align {
 struct c_can_pci_data {
 	/* Specify if is C_CAN or D_CAN */
 	enum c_can_dev_id type;
+	/* number of usable message objects */
+	int object_count;
 	/* Set the register alignment in the memory */
 	enum c_can_pci_reg_align reg_align;
 	/* Set the frequency */
@@ -149,7 +151,8 @@ static int c_can_pci_probe(struct pci_dev *pdev,
 	}
 
 	/* allocate the c_can device */
-	dev = alloc_c_can_dev();
+	dev = alloc_c_can_dev(c_can_pci_data->type,
+			c_can_pci_data->object_count);
 	if (!dev) {
 		ret = -ENOMEM;
 		goto out_iounmap;
@@ -184,8 +187,6 @@ static int c_can_pci_probe(struct pci_dev *pdev,
 		goto out_free_c_can;
 	}
 
-	priv->type = c_can_pci_data->type;
-
 	/* Configure access to registers */
 	switch (c_can_pci_data->reg_align) {
 	case C_CAN_REG_ALIGN_32:
diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c
index 05f425c..57fea84 100644
--- a/drivers/net/can/c_can/c_can_platform.c
+++ b/drivers/net/can/c_can/c_can_platform.c
@@ -217,6 +217,7 @@ static void c_can_hw_raminit(const struct c_can_priv *priv, bool enable)
 
 static const struct c_can_driver_data am3352_dcan_drvdata = {
 	.id = BOSCH_D_CAN,
+	.object_count = 64,
 	.raminit_num = ARRAY_SIZE(am3352_raminit_bits),
 	.raminit_bits = am3352_raminit_bits,
 };
@@ -293,7 +294,7 @@ static int c_can_plat_probe(struct platform_device *pdev)
 	}
 
 	/* allocate the c_can device */
-	dev = alloc_c_can_dev();
+	dev = alloc_c_can_dev(drvdata->id, drvdata->object_count);
 	if (!dev) {
 		ret = -ENOMEM;
 		goto exit;
@@ -381,7 +382,6 @@ static int c_can_plat_probe(struct platform_device *pdev)
 	priv->device = &pdev->dev;
 	priv->can.clock.freq = clk_get_rate(clk);
 	priv->priv = clk;
-	priv->type = drvdata->id;
 
 	platform_set_drvdata(pdev, dev);
 	SET_NETDEV_DEV(dev, &pdev->dev);
-- 
1.8.5.rc3




[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux