All of lore.kernel.org
 help / color / mirror / Atom feed
* [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
@ 2010-08-11  0:25 Masayuki Ohtak
       [not found] ` <4C61EDE5.4030505-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: Masayuki Ohtak @ 2010-08-11  0:25 UTC (permalink / raw)
  To: meego-dev-WXzIur8shnEAvxtiuMwx3w, Wolfgang Grandegger,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w


[-- Attachment #1.1: Type: text/plain, Size: 124239 bytes --]

CAN driver of Topcliff PCH

Topcliff PCH is the platform controller hub that is going to be used in
Intel's upcoming general embedded platform. All IO peripherals in
Topcliff PCH are actually devices sitting on AMBA bus. 
Topcliff PCH has CAN I/F. This driver enables CAN function.

Signed-off-by: Masayuki Ohtake <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>

---
 drivers/net/can/Kconfig   |    8 +
 drivers/net/can/Makefile  |    1 +
 drivers/net/can/pch_can.c | 4076 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/net/can/pch_can.h |  435 +++++
 4 files changed, 4520 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/can/pch_can.c
 create mode 100644 drivers/net/can/pch_can.h

diff --git a/drivers/net/can/Kconfig b/drivers/net/can/Kconfig
index 2c5227c..5c98a20 100644
--- a/drivers/net/can/Kconfig
+++ b/drivers/net/can/Kconfig
@@ -73,6 +73,14 @@ config CAN_JANZ_ICAN3
 	  This driver can also be built as a module. If so, the module will be
 	  called janz-ican3.ko.
 
+config PCH_CAN
+	tristate "PCH CAN"
+	depends on  CAN_DEV
+	---help---
+	  This driver is for PCH CAN of Topcliff which is an IOH for x86
+	  embedded processor.
+	  This driver can access CAN bus.
+
 source "drivers/net/can/mscan/Kconfig"
 
 source "drivers/net/can/sja1000/Kconfig"
diff --git a/drivers/net/can/Makefile b/drivers/net/can/Makefile
index 9047cd0..3ddc6a7 100644
--- a/drivers/net/can/Makefile
+++ b/drivers/net/can/Makefile
@@ -16,5 +16,6 @@ obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
 obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
 obj-$(CONFIG_CAN_BFIN)		+= bfin_can.o
 obj-$(CONFIG_CAN_JANZ_ICAN3)	+= janz-ican3.o
+obj-$(CONFIG_PCH_CAN)		+= pch_can.o
 
 ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
new file mode 100644
index 0000000..3f4fb5e
--- /dev/null
+++ b/drivers/net/can/pch_can.c
@@ -0,0 +1,4076 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#include "pch_can.h"
+
+static unsigned int pch_can_clock = 50000;
+static unsigned int pch_can_rx_buf_size = 16;	/* The number of message objects
+						that has to be configured as
+						receive objects.
+						*/
+
+static unsigned int pch_can_tx_buf_size = 16;	/* The number of message objects
+						that has to be configured as
+						transmit objects.
+						*/
+
+static struct pch_can_os can_os[MAX_CAN_DEVICES];
+
+static enum pch_can_auto_restart restat_mode = CAN_MANUAL; /* The variable used
+							      to store the
+							      restart mode. */
+
+static struct can_bittiming_const pch_can_bittiming_const = {
+	.name = MODULE_NAME,
+	.tseg1_min = 1,
+	.tseg1_max = 16,
+	.tseg2_min = 1,
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 1024, /* 6bit + extended 4bit */
+	.brp_inc = 1,
+};
+
+static const struct pci_device_id pch_can_pcidev_id[] __devinitdata = {
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PCH1_CAN)},
+	{}
+};
+
+/*
+This variable is used to store the configuration (receive /transmit) of the
+available message objects.
+This variable is used for storing the message object configuration related
+information. It includes the information about which message object is used as
+Receiver and Transmitter.
+*/
+static unsigned int pch_msg_obj_conf[MAX_MSG_OBJ] = {
+	3, 3, 3, 3,
+	3, 3, 3, 3,
+	3, 3, 3, 3,
+	3, 3, 3, 3,
+	3, 3, 3, 3,
+	3, 3, 3, 3,
+	3, 3, 3, 3,
+	3, 3, 3, 3
+};
+
+/* Array to store the timing settings. */
+static struct pch_can_timing can_rec_timing[] = {
+	/* <Baud rate>   <BRP>   <TS1>   <TS2>   <SJW> */
+	/* settings for 62.5MHz */
+	{0xa, 0x250, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 10 kbits/s */
+	{0x14, 0x8D, 0xB, 0x5, 0x0, 0x0, 0x0},	/* < 20 kbits/s */
+	{0x32, 0x5C, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 50 kbits/s */
+	{0x7d, 0x18, 0xC, 0x5, 0x0, 0x0, 0x0},	/* < 125 kbits/s */
+	{0xfa, 0x18, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 250 kbits/s */
+	{0x1f4, 0x8, 0x9, 0x2, 0x0, 0x0, 0x0},	/* < 500 kbits/s */
+	{0x320, 0x5, 0x8, 0x2, 0x0, 0x0, 0x0},	/* < 800 kbits/s  */
+	{0x3e8, 0x2, 0xC, 0x6, 0x0, 0x0, 0x0},	/* < 1000 kbits/s */
+
+	/* settings for 24MHz */
+	{0xa, 0xCF, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 10 kbits/s */
+	{0x14, 0x57, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 20 kbits/s */
+	{0x32, 0xF, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 50 kbits/s */
+	{0x7d, 0xF, 0x8, 0x1, 0x0, 0x0, 0x0},	/* < 125 kbits/s */
+	{0xfa, 0x7, 0x8, 0x1, 0x0, 0x0, 0x0},	/* < 250 kbits/s */
+	{0x1f4, 0x3, 0x8, 0x1, 0x0, 0x0, 0x0},	/* < 500 kbits/s */
+	{0x320, 0x2, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 800 kbits/s  */
+	{0x3e8, 0x1, 0x8, 0x1, 0x0, 0x0, 0x0},	/* < 1000 kbits/s */
+
+	/* settings for 50MHz */
+	{0xa, 0xFA, 0xC, 0x5, 0x1, 0x0, 0x0},	/* < 10 kbits/s */
+	{0x14, 0x7D, 0xC, 0x5, 0x1, 0x0, 0x0},	/* < 20 kbits/s */
+	{0x32, 0x32, 0xF, 0x2, 0x0, 0x0, 0x0},	/* < 50 kbits/s */
+	{0x7d, 0x19, 0xC, 0x1, 0x0, 0x0, 0x0},	/* < 125 kbits/s */
+	{0xfa, 0xA, 0xF, 0x2, 0x0, 0x0, 0x0},	/* < 250 kbits/s */
+	{0x1f4, 0x5, 0xF, 0x2, 0x0, 0x0, 0x0},	/* < 500 kbits/s */
+	{0x320, 0x5, 0x8, 0x2, 0x1, 0x0, 0x0},	/* < 800 kbits/s  */
+	{0x3e8, 0x2, 0xF, 0x7, 0x0, 0x0, 0x0}	/* < 1000 kbits/s */
+	/* Add the new clock settings here. */
+};
+
+static DEFINE_MUTEX(pch_can_mutex);
+
+#ifdef PCH_CAN_FIFO_MODE
+static int check_can_fifo_status(int handle)
+{
+	int ret_val;
+	struct can_fifo *f = (struct can_fifo *) handle;
+
+	if (f->head == f->tail)
+		ret_val = PCH_CAN_FIFO_EMPTY;
+	else if (f->head->next == f->tail)
+		ret_val = PCH_CAN_FIFO_FULL;
+	else
+		ret_val = PCH_CAN_FIFO_NOT_EMPTY;
+
+	return ret_val;
+}
+
+static int
+read_can_fifo(int handle, struct pch_can_msg *msg, struct net_device *ndev)
+{
+	int i;
+	int retval = 0;
+	struct can_fifo *f = (struct can_fifo *) handle;
+	struct pch_can_msg msg_tmp;
+
+	if ((handle == 0) || (msg == NULL)) {
+		dev_err(&ndev->dev, "%s -> Invalid parameter.\n", __func__);
+		retval = -EPERM;
+	} else if (f->head == f->tail) {	/* Buffer Empty */
+		dev_dbg(&ndev->dev, "%s -> FIFO empty.\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Accessing the msg object in the FIFO. */
+		msg_tmp = f->tail->msg;
+
+		/* Filling in the msg object. */
+		msg->ide = msg_tmp.ide;
+		msg->id = msg_tmp.id;
+		msg->dlc = msg_tmp.dlc;
+		msg->rtr = msg_tmp.rtr;
+
+		for (i = 0; i < PCH_CAN_MSG_DATA_LEN; i++)
+			msg->data[i] = msg_tmp.data[i];
+
+		/* Proceeding the FIFO read pointer. */
+		f->tail = f->tail->next;
+		dev_dbg(&ndev->dev, "%s successful.\n", __func__);
+	}
+
+	dev_dbg(&ndev->dev, "%s returns %d.\n", __func__, retval);
+	return retval;
+}
+
+static int
+write_can_fifo(int handle, struct pch_can_msg *msg, struct net_device *ndev)
+{
+	int i;
+	int retval = 0;
+	struct can_fifo *f = (struct can_fifo *) handle;
+	struct pch_can_msg *msg_tmp;
+
+	if ((handle == 0) || (msg == NULL)) {
+		dev_err(&ndev->dev, "%s -> Invalid parameters.\n", __func__);
+		retval = -EPERM;
+	} else if (f->head->next == f->tail) {
+		dev_dbg(&ndev->dev, "%s -> FIFO Full.\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Accessing the write node in the FIFO */
+		msg_tmp = &(f->head->msg);
+
+		/* Filling in the FIFO node. */
+		msg_tmp->ide = msg->ide;
+		msg_tmp->rtr = msg->rtr;
+		msg_tmp->id = msg->id;
+		msg_tmp->dlc = msg->dlc;
+
+		for (i = 0; i < PCH_CAN_MSG_DATA_LEN; i++)
+			msg_tmp->data[i] = msg->data[i];
+
+		/* Proceeding the write node. */
+		f->head = f->head->next;
+		dev_dbg(&ndev->dev, "%s successful.\n", __func__);
+	}
+
+	dev_dbg(&ndev->dev, "%s returns %d.\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_get_error_stats(int handle, struct pch_can_error *error)
+{
+	u32 reg_val;
+	int retval = 0;
+
+	if ((handle == 0) || (error == NULL)) {
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Reading the error count register. */
+		reg_val = ioread32(can->io_base + CAN_ERRC_OFFSET);
+
+		error->rxgte96 = 0;
+		error->txgte96 = 0;
+
+		error->rx_err_cnt =
+		    (reg_val & MSK_ES_RXERRCNT) >> BIT_ES_RXERRCNT;
+		error->tx_err_cnt =
+		    (reg_val & MSK_ES_TXERRCNT) >> BIT_ES_TXERRCNT;
+
+		/* receive error count > 96 */
+		if (error->rx_err_cnt >= ERROR_COUNT)
+			error->rxgte96 = 1;
+		/* transmit error count > 96. */
+		if (error->tx_err_cnt >= ERROR_COUNT)
+			error->txgte96 = 1;
+
+		/* Reading the Can status register. */
+		reg_val = ioread32(can->io_base + CAN_STAT_OFFSET);
+
+		/* EPass */
+		if ((reg_val & (1 << BIT_SHIFT_FIVE)) != 0)
+			error->error_stat = 1;
+		/* Buss Off */
+		else if ((reg_val & (1 << BIT_SHIFT_SEVEN)) != 0)
+			error->error_stat = 3;
+		else
+			error->error_stat = 0;
+	}
+
+	return retval;
+}
+#endif
+
+static void delete_can_fifo(int handle, struct net_device *ndev)
+{
+	unsigned int i;
+	struct can_fifo_item *curr = NULL;
+	struct can_fifo_item *next = NULL;
+	struct can_fifo *f = (struct can_fifo *) handle;
+
+	if (handle != 0) {
+		curr = f->head;
+		if (f->head != NULL) {
+			next = curr->next;
+
+			/* Freeing individual node. */
+			for (i = 0; i < f->size; i++) {
+				kfree(curr);
+				curr = next;
+				next = (struct can_fifo_item *) curr->next;
+			}
+		}
+
+		/* Free the START node. */
+		kfree(f);
+	} else {
+		dev_err(&ndev->dev, "%s -> Invalid handle.\n", __func__);
+	}
+
+	dev_dbg(&ndev->dev, "%s successful.\n", __func__);
+}
+
+static int create_can_fifo(unsigned int fifo_entries, struct net_device *ndev)
+{
+	unsigned int i;
+	struct can_fifo_item *curr;
+	struct can_fifo *f;
+	int retval;
+
+	/* Allocating the Main start node. */
+	f = kmalloc(sizeof(struct can_fifo), GFP_KERNEL);
+
+	if (f == NULL) {
+		dev_err(&ndev->dev,
+			"%s -> msg queue allocation failed.\n", __func__);
+		retval = (int) PCH_CAN_NULL;
+	} else {
+		/* Allocating the first node. */
+		f->head = kmalloc(sizeof(struct can_fifo_item), GFP_KERNEL);
+		if ((f->head == NULL)) {
+			kfree(f);
+			retval = (int) PCH_CAN_NULL;
+		} else {
+			/* Initially empty. */
+			f->tail = f->head;
+			curr = f->head;
+
+			/* Rest of the nod ecreation Node creation. */
+			for (i = 1; i <= fifo_entries; i++) {
+				curr->next =
+					kmalloc(sizeof(struct can_fifo_item),
+								GFP_KERNEL);
+				/* If allocation failed. */
+				if ((curr->next == NULL)) {
+					dev_err(&ndev->dev,
+						"%s -> Allocation failed.\n",
+						__func__);
+					i = (i - 1);
+					/* Freeing the already allocated
+					   nodes. */
+					while (i > 0) {
+						curr = f->head;
+						f->head = curr->next;
+						kfree(curr);
+
+						i--;
+					}
+
+					/* Freeing the main start node. */
+					kfree(f);
+					f = NULL;
+					retval =
+					    (int) PCH_CAN_NULL;
+					break;
+				}
+
+				curr = curr->next;
+			}
+
+			if (f != NULL) {
+				/* Making it circular. */
+				curr->next = f->head;
+				f->size = fifo_entries;
+
+				retval = (int) f;
+				dev_dbg(&ndev->dev,
+						"%s sucessful.\n", __func__);
+			}
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s returns %u.\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_create(u8 *io_base, struct net_device *ndev)
+{
+	struct can_hw *can = NULL;
+	int retval = (int) PCH_CAN_NULL;
+
+	if (io_base == NULL) {
+		dev_err(&ndev->dev, "%s -> Invalid IO Base\n", __func__);
+	}
+
+	else {
+		/* Allocates memory for the handle. */
+		can = kmalloc(sizeof(struct can_hw), GFP_KERNEL);
+		if (can == NULL) {	/* Allocation failed */
+			dev_err(&ndev->dev,
+			    "%s -> CAN Memory allocation failed\n", __func__);
+		} else {	/* Allocation successful */
+
+			can->io_base = io_base;
+			retval = (int) can;
+			dev_dbg(&ndev->dev,
+			    "%s -> Handle Creation successful.\n", __func__);
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %x\n", __func__, retval);
+	return retval;
+}
+
+static void pch_can_destroy(int handle, struct net_device *ndev)
+{
+	struct can_hw *can = (struct can_hw *) handle;
+
+	if (handle !=  0) {
+		/* Free the memory for the handle. */
+		kfree(can);
+		dev_dbg(&ndev->dev, "%s -> Free successful.\n", __func__);
+	} else {
+		dev_err(&ndev->dev, "%s-> Invalid handle.\n", __func__);
+	}
+}
+
+static int pch_can_set_run_mode(int handle, enum pch_can_run_mode mode,
+				struct net_device *ndev)
+{
+	int retval = 0;
+	struct can_hw *can;
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Retrieving base address for access. */
+		can = (struct can_hw *) handle;
+
+		switch (mode) {
+		case PCH_CAN_RUN:
+			PCH_CAN_BIT_CLEAR((can->io_base + CAN_CONT_OFFSET),
+					  CAN_CTRL_INIT);
+			dev_dbg(&ndev->dev,
+			    "%s -> Can set to RUN Mode.\n", __func__);
+			break;
+
+		case PCH_CAN_STOP:
+			PCH_CAN_BIT_SET((can->io_base + CAN_CONT_OFFSET),
+					CAN_CTRL_INIT);
+			dev_dbg(&ndev->dev,
+			    "%s -> Can set to STOP Mode.\n", __func__);
+			break;
+
+		default:
+			dev_err(&ndev->dev,
+				"%s -> Invalid run mode.\n", __func__);
+			retval = -EPERM;
+			break;
+		}
+	}
+
+	dev_dbg(&ndev->dev,
+			"%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_get_run_mode(int handle, enum pch_can_run_mode *mode,
+				struct net_device *ndev)
+{
+	u32 reg_val;
+	struct can_hw *can;
+	int retval = 0;
+
+	if ((handle ==  0) || (mode == NULL)) {
+		dev_err(&ndev->dev,
+			"%s -> Invalid parameter.\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		can = (struct can_hw *) handle;
+
+		reg_val = ioread32(can->io_base + CAN_CONT_OFFSET);
+
+		/* Checking the Init bit of Can Control Register.
+		   Init Bit 1 -> Stop
+		   Init Bit 0 -> Run
+		 */
+		if ((reg_val & CAN_CTRL_INIT) != 0) {
+			*mode = PCH_CAN_STOP;
+			dev_dbg(&ndev->dev,
+			    "%s -> Mode is PCH_CAN_STOP\n", __func__);
+		} else {
+			*mode = PCH_CAN_RUN;
+			dev_dbg(&ndev->dev,
+			    "%s -> Mode is PCH_CAN_RUN\n", __func__);
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_set_arbiter_mode(int handle, enum pch_can_arbiter mode,
+				    struct net_device *ndev)
+{
+	int retval = 0;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev,
+			"%s -> Invalid Handle\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* PCH CAN Controller supports only PCH_CAN_FIXED_PRIORITY
+		   arbiter mode.
+		 */
+		switch (mode) {
+		case PCH_CAN_FIXED_PRIORITY:
+			dev_dbg(&ndev->dev,
+			    "%s -> FIXED PRIORITY is set for Arbiter mode\n",
+			    __func__);
+			break;
+
+		case PCH_CAN_ROUND_ROBIN:
+		default:
+			dev_dbg(&ndev->dev,
+				"%s -> Invalid arbiter mode\n", __func__);
+			retval = -EPERM;
+			break;
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_get_arbiter_mode(int handle, enum pch_can_arbiter *mode,
+				    struct net_device *ndev)
+{
+	int retval = 0;
+
+	if ((handle == 0) || (mode == NULL)) {
+		dev_err(&ndev->dev,
+			"%s -> Invalid parameter\n", __func__);
+		retval = -EPERM;
+	}
+
+	else {
+		/* PCH CAN Controller supports only PCH_CAN_FIXED_PRIORITY
+		   arbiter mode.
+		 */
+		*mode = PCH_CAN_FIXED_PRIORITY;
+		dev_dbg(&ndev->dev,
+		    "%s -> Arbiter Mode is PCH_CAN_FIXED_PRIORITY\n", __func__);
+	}
+
+	dev_dbg(&ndev->dev, "%s returns %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_set_restart_mode(int handle,	enum pch_can_auto_restart mode,
+				    struct net_device *ndev)
+{
+	int retval = 0;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle\n", __func__);
+		retval = -EPERM;
+	} else {
+		switch (mode) {
+		case CAN_MANUAL:
+			restat_mode = CAN_MANUAL;
+			dev_dbg(&ndev->dev, "%s -> Value of variable "
+			     " restat_mode = 0. CAN_MANUAL mode set.\n",
+				__func__);
+			break;
+
+		case CAN_AUTO:
+			restat_mode = CAN_AUTO;
+			dev_dbg(&ndev->dev, "%s -> Value of variable "
+			     " restat_mode = 1. CAN_AUTO mode set.\n",
+			    __func__);
+			break;
+
+		default:
+			dev_dbg(&ndev->dev,
+				"%s -> Invalid restart mode\n", __func__);
+			retval = -EPERM;
+			break;
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s returns %d\n", __func__,
+								 retval);
+	return retval;
+}
+
+static int pch_can_get_restart_mode(int handle, enum pch_can_auto_restart *mode,
+				    struct net_device *ndev)
+{
+	int retval = 0;
+
+	if ((handle == 0) || (mode == NULL)) {
+		dev_err(&ndev->dev, "%s -> Invalid parameter.\n", __func__);
+		retval = -EPERM;
+	} else {
+		if (CAN_AUTO == restat_mode) {
+			*mode = CAN_AUTO;
+			dev_dbg(&ndev->dev,
+					"%s -> Mode CAN_AUTO.\n", __func__);
+		} else {
+			*mode = CAN_MANUAL;
+			dev_dbg(&ndev->dev,
+					"%s -> Mode CAN_MANUAL.\n", __func__);
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s returns: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_set_listen_mode(int handle, enum pch_can_listen_mode mode,
+				   struct net_device *ndev)
+{
+	int retval = 0;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Setting for Bit3 of Can Extended function register for
+		   appropriate mode.
+		   Silent bit = 0 (Active mode)
+		   Silent bit = 1 (Silent mode)
+		 */
+		switch (mode) {
+		case PCH_CAN_LISTEN:
+			PCH_CAN_BIT_SET((can->io_base + CAN_CONT_OFFSET),
+					CAN_CTRL_OPT);
+			PCH_CAN_BIT_SET((can->io_base + CAN_OPT_OFFSET),
+					CAN_OPT_SILENT);
+			dev_dbg(&ndev->dev,
+				"%s -> PCH_CAN_LISTEN mode set.\n", __func__);
+			break;
+
+		case PCH_CAN_ACTIVE:
+			PCH_CAN_BIT_SET((can->io_base + CAN_CONT_OFFSET),
+					CAN_CTRL_OPT);
+			PCH_CAN_BIT_CLEAR((can->io_base + CAN_OPT_OFFSET),
+					  CAN_OPT_SILENT);
+			dev_dbg(&ndev->dev,
+				"%s ->PCH_CAN_ACTIVE mode set.\n", __func__);
+			break;
+
+		default:
+			dev_dbg(&ndev->dev,
+					"%s ->Invalid listen mode\n", __func__);
+			retval = -EPERM;
+			break;
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_get_listen_mode(int handle, enum pch_can_listen_mode *mode,
+				   struct net_device *ndev)
+{
+	u32 reg_val;
+	int retval = 0;
+
+	if ((handle == 0) || (mode == NULL)) {
+		dev_err(&ndev->dev, "%s -> Invalid Parameter\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Attaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		reg_val = ioread32(can->io_base + CAN_OPT_OFFSET);
+
+		/*      Checking for Bit3 of Can Extended function register
+			 for silent mode
+		   Silent bit = 0 (Active mode)
+		   Silent bit = 1 (Silent mode)
+		 */
+
+		if ((reg_val & CAN_OPT_SILENT) != 0) {
+			*mode = PCH_CAN_LISTEN;
+			dev_dbg(&ndev->dev,
+					"%s -> Mode is listen\n", __func__);
+		} else {
+			*mode = PCH_CAN_ACTIVE;
+			dev_dbg(&ndev->dev, "%s -> Mode is active\n", __func__);
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_set_int_custom(int handle, u32 interrupts)
+{
+	int retval = 0;
+
+	if (handle == 0) {
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Clearing the IE, SIE and EIE bits of Can control register. */
+		PCH_CAN_BIT_CLEAR((can->io_base + CAN_CONT_OFFSET),
+				  CAN_CTRL_IE_SIE_EIE);
+
+		/* Appropriately setting them. */
+		PCH_CAN_BIT_SET((can->io_base + CAN_CONT_OFFSET),
+				((interrupts & MSK_CTRL_IE_SIE_EIE) <<
+				 BIT_SHIFT_ONE));
+	}
+
+	return retval;
+}
+
+/* This function retrieves interrupt enabled for the CAN device. */
+static int pch_can_get_int_enables(int handle, u32 *enables)
+{
+	u32 reg_ctrl_val;
+	int retval = 0;
+
+	if ((handle == 0) || (enables == NULL)) {
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Reading the Can control register. */
+		reg_ctrl_val = ioread32(can->io_base + CAN_CONT_OFFSET);
+
+		/* Obtaining the status of IE, SIE and EIE interrupt bits. */
+		*enables =
+		    (((reg_ctrl_val & CAN_CTRL_IE_SIE_EIE) >> BIT_SHIFT_ONE));
+	}
+
+	return retval;
+}
+
+static int pch_can_set_int_enables(int handle,
+				   enum pch_can_interrupt interrupt_no,
+				   struct net_device *ndev)
+{
+	int retval = 0;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle.\n", __func__);
+		retval = -EPERM;
+	} else {
+
+		/* Obatining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/*
+		   Appropriately setting the IE, SIE and EIE bits of Can control
+			 register.
+		 */
+		switch (interrupt_no) {
+		case CAN_ENABLE:
+			PCH_CAN_BIT_SET((can->io_base + CAN_CONT_OFFSET),
+					CAN_CTRL_IE);
+			dev_dbg(&ndev->dev,
+			    "%s -> CAN_ENABLE (IE) interrupt set.\n", __func__);
+			break;
+
+		case CAN_DISABLE:
+			PCH_CAN_BIT_CLEAR((can->io_base + CAN_CONT_OFFSET),
+					  CAN_CTRL_IE);
+			dev_dbg(&ndev->dev,
+			  "%s -> CAN_DIABLE (IE) interrupt reset.\n", __func__);
+			break;
+
+		case CAN_ALL:
+			PCH_CAN_BIT_SET((can->io_base + CAN_CONT_OFFSET),
+					CAN_CTRL_IE_SIE_EIE);
+			dev_dbg(&ndev->dev,
+				"%s -> CAN_ALL (IE,SIE,EIE) interrupt set.\n",
+				__func__);
+			break;
+
+		case CAN_NONE:
+			PCH_CAN_BIT_CLEAR((can->io_base + CAN_CONT_OFFSET),
+					  CAN_CTRL_IE_SIE_EIE);
+			dev_dbg(&ndev->dev,
+			    "%s -> CAN_NONE (IE,SIE,EIE) interrupt reset.\n",
+			    __func__);
+			break;
+
+		default:
+			dev_dbg(&ndev->dev,
+			    "%s -> Invalid parameter interrupt.\n", __func__);
+			retval = -EPERM;
+			break;
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_set_rx_enable(int handle, u32 buff_num, u32 set,
+				 struct net_device *ndev)
+{
+	u32 counter;
+	int retval = 0;
+	u32 if1_creq;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle.\n", __func__);
+		retval = -EPERM;
+	} else if ((pch_msg_obj_conf[buff_num - 1] != MSG_OBJ_RX) ||
+		 (buff_num > (pch_can_tx_buf_size + pch_can_rx_buf_size))) {
+		/* if invalid buffer number. */
+		dev_err(&ndev->dev,
+		    "%s -> Message object %u not configured for receive.\n",
+		    __func__, buff_num);
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/*Reading the receive buffer data from RAM to Interface1
+								 registers */
+		iowrite32(CAN_CMASK_RX_TX_GET,
+			       (can->io_base + CAN_IF1_CMASK_OFFSET));
+		iowrite32(buff_num,
+			       (can->io_base + CAN_IF1_CREQ_OFFSET));
+
+		counter = COUNTER_LIMIT;
+		while (counter) {
+			if1_creq = (ioread32(can->io_base +
+							CAN_IF1_CREQ_OFFSET)) &
+							CAN_IF_CREQ_BUSY;
+			if (if1_creq == 0)
+				break;
+
+			counter--;
+		}
+
+		if ((counter == 0)) {
+			dev_err(&ndev->dev,
+			    "%s -> Cannot read the message buffer object %u.\n",
+			    __func__, buff_num);
+			retval = -EPERM;
+		} else {		/* Reading successful */
+
+			/* Setting the IF1MASK1 register to access MsgVal and
+								 RxIE bits */
+			iowrite32((CAN_CMASK_RDWR | CAN_CMASK_ARB |
+						CAN_CMASK_CTRL),
+						(can->io_base +
+						CAN_IF1_CMASK_OFFSET));
+
+			if (set == ENABLE) {
+				/* Setting the MsgVal and RxIE bits */
+				PCH_CAN_BIT_SET((can->io_base +
+						 CAN_IF1_MCONT_OFFSET),
+						CAN_IF_MCONT_RXIE);
+				PCH_CAN_BIT_SET((can->io_base +
+						 CAN_IF1_ID2_OFFSET),
+						CAN_ID_MSGVAL);
+
+				dev_dbg(&ndev->dev,
+				   "%s -> Enabled receive message buffer %u.\n",
+				   __func__, buff_num);
+			} else if (set == DISABLE) {
+				/* Resetting the MsgVal and RxIE bits */
+				PCH_CAN_BIT_CLEAR((can->io_base +
+						   CAN_IF1_MCONT_OFFSET),
+						  CAN_IF_MCONT_RXIE);
+				PCH_CAN_BIT_CLEAR((can->io_base +
+						   CAN_IF1_ID2_OFFSET),
+						  CAN_ID_MSGVAL);
+
+				dev_dbg(&ndev->dev,
+				    "%s -> Disabled receive message buffer %u",
+				    __func__, buff_num);
+			}
+
+			/* Updating the changes to the message object. */
+			iowrite32(buff_num,
+				       (can->io_base + CAN_IF1_CREQ_OFFSET));
+
+			/* Confirming the write by checking the busy bit. */
+			counter = COUNTER_LIMIT;
+			while (counter) {
+				if1_creq = (ioread32(can->io_base +
+							CAN_IF1_CREQ_OFFSET)) &
+							CAN_IF_CREQ_BUSY;
+				if (if1_creq == 0)
+					break;
+
+				counter--;
+			}
+
+			if ((counter == 0)) {
+				dev_err(&ndev->dev,
+					"%s -> Write failed.\n", __func__);
+				retval = -EPERM;
+			}
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_rx_enable_all(int handle, struct net_device *ndev)
+{
+	u32 counter = 0;
+	int retval = 0;
+	u32 i;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle.\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Traversing to obtain the object configured as receivers. */
+		for (i = 0; i < (pch_can_tx_buf_size + pch_can_rx_buf_size);
+									i++) {
+			if (pch_msg_obj_conf[i] == MSG_OBJ_RX) {
+				/* Here i is the index, however (i+1) is object
+								 number. */
+				retval =
+				    pch_can_set_rx_enable(handle, (i + 1),
+							  ENABLE, ndev);
+
+				if (retval == -EPERM) {
+					dev_dbg(&ndev->dev,
+					    "%s -> Cannot Enable receive "
+					    "object%u\n", __func__, i + 1);
+					counter++;
+				} else {
+					dev_dbg(&ndev->dev,
+					   "%s -> Enabled receive object %u\n",
+					   __func__, i + 1);
+				}
+			}
+		}
+
+		/* If enabling of all the receive object failed. */
+		if (counter == pch_can_rx_buf_size) {
+			retval = -EPERM;
+			dev_err(&ndev->dev, "%s failed.\n", __func__);
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_rx_disable_all(int handle, struct net_device *ndev)
+{
+	u32 counter = 0;
+	int retval = 0;
+	u32 i;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle.\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Traversing to obtain the object configured as receivers. */
+		for (i = 0; i < (pch_can_rx_buf_size + pch_can_tx_buf_size);
+									i++) {
+			if (pch_msg_obj_conf[i] == MSG_OBJ_RX) {
+				/* Here i is the index, however (i+1) is the
+							 object number. */
+				retval =
+				    pch_can_set_rx_enable(handle, (i + 1),
+							  DISABLE, ndev);
+
+				if (retval == -EPERM) {
+					dev_dbg(&ndev->dev,
+					    "%s -> Disabling of Rx buffer %u "
+					    "failed.\n", __func__, (i + 1));
+					counter++;
+				} else {
+					dev_dbg(&ndev->dev,
+					  "%s -> Disabled receive object %u\n",
+					  __func__, i + 1);
+				}
+			}
+		}
+
+		/* If disabling of all the receive object failed. */
+		if (counter == pch_can_rx_buf_size) {
+			retval = -EPERM;
+			dev_err(&ndev->dev, "%s failed.\n", __func__);
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_set_tx_enable(int handle, u32 buff_num, u32 set,
+				 struct net_device *ndev)
+{
+	int retval = 0;
+	u32 counter;
+	u32 if1_creq;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle", __func__);
+		retval = -EPERM;
+	} else if ((pch_msg_obj_conf[buff_num - 1] != MSG_OBJ_TX) ||
+		 (buff_num > (pch_can_rx_buf_size + pch_can_tx_buf_size))) {
+		/* invalid buffer number. */
+		dev_err(&ndev->dev,
+		    "%s -> Message object %u not configured for transmit.\n",
+		    __func__, buff_num);
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/*Reading the Message buffer from Message RAM to Interface2
+								 registers. */
+		iowrite32(CAN_CMASK_RX_TX_GET,
+			       (can->io_base + CAN_IF1_CMASK_OFFSET));
+		iowrite32(buff_num,
+			       (can->io_base + CAN_IF1_CREQ_OFFSET));
+
+		counter = COUNTER_LIMIT;
+		while (counter) {
+			if1_creq = (ioread32(can->io_base +
+						CAN_IF1_CREQ_OFFSET)) &
+						CAN_IF_CREQ_BUSY;
+			if (if1_creq == 0)
+				break;
+
+			counter--;
+		}
+
+		if ((counter == 0)) {
+			dev_err(&ndev->dev,
+			   "%s -> Reading transmit buffer failed.\n", __func__);
+			retval = -EPERM;
+		} else {	/* Reading successful. */
+
+			/* Setting the IF2CMASK register for accessing the
+				MsgVal and TxIE bits */
+			iowrite32((CAN_CMASK_RDWR | CAN_CMASK_ARB |
+					CAN_CMASK_CTRL),
+				       (can->io_base +
+					CAN_IF1_CMASK_OFFSET));
+
+			if (set == ENABLE) {
+				/* Setting the MsgVal and TxIE bits */
+				PCH_CAN_BIT_SET((can->io_base +
+						 CAN_IF1_MCONT_OFFSET),
+						CAN_IF_MCONT_TXIE);
+				PCH_CAN_BIT_SET((can->io_base +
+						 CAN_IF1_ID2_OFFSET),
+						CAN_ID_MSGVAL);
+
+				dev_dbg(&ndev->dev,
+				   "%s -> Enabled transmit message buffer %u\n",
+				   __func__, buff_num);
+			} else if (set == DISABLE) {
+				/* Resetting the MsgVal and TxIE bits. */
+				PCH_CAN_BIT_CLEAR((can->io_base +
+						   CAN_IF1_MCONT_OFFSET),
+						  CAN_IF_MCONT_TXIE);
+				PCH_CAN_BIT_CLEAR((can->io_base +
+						   CAN_IF1_ID2_OFFSET),
+						  CAN_ID_MSGVAL);
+
+				dev_dbg(&ndev->dev,
+				  "%s -> Disabled transmit message buffer %u\n",
+				  __func__, buff_num);
+			}
+
+			/* Updating the changes to the message buffer. */
+			iowrite32(buff_num,
+				       (can->io_base + CAN_IF1_CREQ_OFFSET));
+
+			/* Confirming the updation. */
+			counter = COUNTER_LIMIT;
+			while (counter) {
+				if1_creq = (ioread32(can->io_base +
+						CAN_IF1_CREQ_OFFSET)) &
+						CAN_IF_CREQ_BUSY;
+				if (if1_creq == 0)
+					break;
+
+				counter--;
+			}
+
+			if ((counter == 0)) {	/* Updation failed. */
+				dev_err(&ndev->dev,
+					"%s -> Write failed.\n", __func__);
+				retval = -EPERM;
+			}
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_tx_enable_all(int handle, struct net_device *ndev)
+{
+	u32 counter = 0;
+	int retval = 0;
+	u32 i;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle.\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Traversing to obtain the object configured as transmit
+								 object. */
+		for (i = 0; i < (pch_can_tx_buf_size + pch_can_rx_buf_size);
+									i++) {
+			if (pch_msg_obj_conf[i] == MSG_OBJ_TX) {
+				/* Here i denotes the index, however (i+1) is
+							 the object number. */
+				retval =
+				    pch_can_set_tx_enable(handle, (i + 1),
+							  ENABLE, ndev);
+
+				if (retval == -EPERM) {
+					counter++;
+					dev_dbg(&ndev->dev, "%s -> "
+					  "Cannot Enable transmit object %u\n",
+					  __func__, (i + 1));
+				} else {
+					dev_dbg(&ndev->dev, "%s -> "
+					  "Enabled transmit object %u\n",
+					  __func__, (i + 1));
+				}
+			}
+		}
+
+		/* If enabling of all transmit object failed. */
+		if (counter == pch_can_tx_buf_size) {
+			dev_err(&ndev->dev, "%s failed.\n", __func__);
+			retval = -EPERM;
+		}
+
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_tx_disable_all(int handle, struct net_device *ndev)
+{
+	u32 counter = 0;
+	int retval = 0;
+	u32 i;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid Handle.\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Traversing to obtain the object configured as transmit
+								 object. */
+		for (i = 0; i < (pch_can_tx_buf_size + pch_can_tx_buf_size);
+									i++) {
+			if (pch_msg_obj_conf[i] == MSG_OBJ_TX) {
+				/* Here i denotes the index, however (i+1) is
+							 the object number. */
+
+				/* Disabling. */
+				retval =
+				    pch_can_set_tx_enable(handle, (i + 1),
+							  DISABLE, ndev);
+
+				if (retval == -EPERM) {
+					dev_dbg(&ndev->dev,  "%s -> Disabling"
+						" Tx buffer %u failed.\n",
+						__func__, (i + 1));
+					counter++;
+				} else {
+					dev_dbg(&ndev->dev,
+					  "%s -> Disabled transmit object %u\n",
+					  __func__, (i + 1));
+				}
+			}
+		}
+
+		/* If disabling of all the transmit object failed. */
+		if (counter == pch_can_tx_buf_size) {
+			dev_err(&ndev->dev, "%s -> failed.\n", __func__);
+			retval = -EPERM;
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_set_rx_filter(int handle, struct pch_can_rx_filter *filter)
+{
+	u32 reg1;
+	u32 reg2;
+	u32 counter;
+	int retval = 0;
+	u32 if1_creq;
+
+	if ((handle == 0) || (filter == NULL)) {
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		iowrite32(CAN_CMASK_RX_TX_GET,
+				can->io_base + CAN_IF1_CMASK_OFFSET);
+				/* Setting the CMASK for reading */
+		iowrite32(filter->num,
+				can->io_base + CAN_IF1_CREQ_OFFSET);
+				/* Setting CREQ to specified Msg Obj. */
+
+		/* Confirming the read completion. */
+		counter = COUNTER_LIMIT;
+		while (counter) {
+			if1_creq = (ioread32(can->io_base +
+						CAN_IF1_CREQ_OFFSET)) &
+						CAN_IF_CREQ_BUSY;
+			if (if1_creq == 0)
+				break;
+
+			counter--;
+		}
+
+		if ((counter == 0)) {	/* Read Unsuccessful. */
+			retval = -EPERM;
+		} else {	/* read successful. */
+
+			PCH_CAN_BIT_CLEAR((can->io_base +
+					CAN_IF1_ID2_OFFSET), MSK_ALL_THIRTEEN);
+					/* Clearing the bit 0- 12 of ID2 */
+			PCH_CAN_BIT_CLEAR((can->io_base +
+					CAN_IF1_ID2_OFFSET), CAN_ID2_XTD);
+					/* Clearing XTD bit */
+
+			if ((filter->aidr.id_ext == 1)) { /* Extended ID */
+				reg1 = filter->aidr.id & MSK_ALL_SIXTEEN;
+								/* ID1 value. */
+				/* ID2 value with XTD bit set. */
+				reg2 =
+				    (((filter->aidr.
+				       id & (MSK_ALL_THIRTEEN <<
+					     BIT_SHIFT_SIXTEEN))
+				      >> BIT_SHIFT_SIXTEEN) | CAN_ID2_XTD);
+			} else {	/* Standard ID */
+
+				reg1 = 0;
+				reg2 = ((filter->aidr.id & MSK_ALL_ELEVEN) <<
+								BIT_SHIFT_TWO);
+			}
+
+			iowrite32(reg1, (can->io_base + CAN_IF1_ID1_OFFSET));
+			PCH_CAN_BIT_SET((can->io_base +
+						CAN_IF1_ID2_OFFSET), reg2);
+
+			if (filter->umask == 1) {
+				/* If mask has to be set. */
+				PCH_CAN_BIT_CLEAR((can->io_base +
+							CAN_IF1_MASK2_OFFSET),
+							MSK_ALL_THIRTEEN);
+						/* Clearing bit 0-12 */
+				PCH_CAN_BIT_CLEAR((can->io_base +
+							CAN_IF1_MASK2_OFFSET),
+							CAN_MASK2_MDIR_MXTD);
+						/* Clearing Mdir & MXtd */
+
+				if (filter->amr.id_ext == 1) {
+							/* Extended Mask */
+					reg1 = filter->amr.id & MSK_ALL_SIXTEEN;
+							/* Mask1 value */
+					/* Mask2 value with MXtd set */
+					reg2 = (((filter->amr.
+						id & (MSK_ALL_THIRTEEN <<
+						BIT_SHIFT_SIXTEEN))
+						>> BIT_SHIFT_SIXTEEN) |
+						CAN_IF_MASK2_MXTD);
+				} else {
+					reg1 = 0;
+					reg2 = ((filter->amr.id &
+							MSK_ALL_ELEVEN) <<
+							BIT_SHIFT_TWO);
+							/* Mask2 Value */
+				}
+
+				iowrite32(reg1,
+				    (can->io_base + CAN_IF1_MASK1_OFFSET));
+							/* Writing MASK1 */
+				PCH_CAN_BIT_SET((can->io_base +
+						CAN_IF1_MASK2_OFFSET), reg2);
+							/* Writing MASK2 */
+				PCH_CAN_BIT_SET((can->io_base +
+				    CAN_IF1_MCONT_OFFSET), CAN_IF_MCONT_UMASK);
+							/* Setting Umask bit */
+			} else {
+				PCH_CAN_BIT_CLEAR((can->io_base +
+				    CAN_IF1_MCONT_OFFSET), CAN_IF_MCONT_UMASK);
+						/* Resetting Umask bit. */
+			}
+
+			/* Setting CMASK for writing */
+			iowrite32((CAN_CMASK_RDWR | CAN_CMASK_MASK |
+					CAN_CMASK_ARB | CAN_CMASK_CTRL),
+					(can->io_base +
+					CAN_IF1_CMASK_OFFSET));
+			iowrite32(filter->num, (can->io_base +
+					CAN_IF1_CREQ_OFFSET));
+					/* Setting CREQ for specified sg Obj. */
+
+			/* Confirming the write completion. */
+			counter = COUNTER_LIMIT;
+			while (counter) {
+				if1_creq = (ioread32(can->io_base +
+							CAN_IF1_CREQ_OFFSET)) &
+							CAN_IF_CREQ_BUSY;
+				if (if1_creq == 0)
+					break;
+
+				counter--;
+			}
+
+			if (counter == 0) /* Write failed */
+				retval = -EPERM;
+		}
+	}
+
+	return retval;
+}
+
+static int
+pch_can_rx_init_filter(int handle, u32 buff_num, struct net_device *ndev)
+{
+	int retval = 0;
+	struct pch_can_rx_filter filter;
+
+	if (handle == 0) {
+		retval = -EPERM;
+	} else if ((pch_msg_obj_conf[buff_num - 1] != MSG_OBJ_RX) ||
+		 (buff_num > (pch_can_tx_buf_size + pch_can_rx_buf_size))) {
+		/* if invalid buffer number. */
+		dev_err(&ndev->dev,
+			"%s -> Invalid buffer no:%d\n", __func__, buff_num);
+		retval = -EPERM;
+	} else {
+		/* Set all Rx filters to allow all msgs. */
+		filter.amr.id = (u32) 0;
+		filter.amr.id_ext = (u32) 0;
+
+		filter.aidr.id = (u32) 0;
+		filter.aidr.id_ext = (u32) 0;
+
+		filter.num = buff_num;
+		filter.umask = 1;
+
+		retval = pch_can_set_rx_filter(handle, &filter);
+	}
+
+	return retval;
+}
+
+static int pch_can_get_rx_enable(int handle, u32 buff_num, u32 *enable,
+				 struct net_device *ndev)
+{
+	int retval = 0;
+	u32 counter;
+	u32 if1_creq;
+
+	if ((handle == 0) || (enable == NULL)) {
+		dev_err(&ndev->dev,
+			"%s -> Invalid Parameter.\n", __func__);
+		retval = -EPERM;
+	}
+	/* Invalid buffer number. */
+	else if ((pch_msg_obj_conf[buff_num - 1] != MSG_OBJ_RX) ||
+		 (buff_num > (pch_can_tx_buf_size + pch_can_rx_buf_size))) {
+		dev_err(&ndev->dev,
+			"%s -> Message object %u not configured for receive.\n",
+			__func__, buff_num);
+		retval = -EPERM;
+	}
+
+	else {
+		/* Obtaining the remap address fro access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		iowrite32(CAN_CMASK_RX_TX_GET,
+				(can->io_base + CAN_IF1_CMASK_OFFSET));
+		iowrite32(buff_num,
+				(can->io_base + CAN_IF1_CREQ_OFFSET));
+
+		counter = COUNTER_LIMIT;
+		while (counter) {
+			if1_creq = (ioread32((can->io_base +
+						CAN_IF1_CREQ_OFFSET))) &
+						CAN_IF_CREQ_BUSY;
+			if (if1_creq == 0)
+				break;
+
+			counter--;
+		}
+
+		if (counter == 0) {
+			dev_err(&ndev->dev, "%s -> Read Failed.\n", __func__);
+			retval = -EPERM;
+		} else {
+			if (((ioread32(can->io_base +
+					CAN_IF1_ID2_OFFSET)) &
+					CAN_ID_MSGVAL) &&
+					((ioread32(can->io_base +
+					CAN_IF1_MCONT_OFFSET)) &
+					CAN_IF_MCONT_RXIE)) {
+				*enable = ENABLE;
+
+				dev_dbg(&ndev->dev, "%s -> Receive message "
+					"buffer %u is enabled.\n",
+					__func__, buff_num);
+			} else {
+				*enable = DISABLE;
+				dev_dbg(&ndev->dev, "%s -> Receive Message "
+					"buffer %u is disabled.\n",
+					__func__, buff_num);
+			}
+		}
+
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_get_tx_enable(int handle, u32 buff_num, u32 *enable,
+				 struct net_device *ndev)
+{
+	int retval = 0;
+	u32 counter;
+	u32 if1_creq;
+
+	if ((handle == 0) || (enable == NULL)) {
+		dev_err(&ndev->dev,
+			"%s -> Invalid Parameter.\n", __func__);
+		retval = -EPERM;
+	}
+	/* invalid buffer number. */
+	else if ((pch_msg_obj_conf[buff_num - 1] != MSG_OBJ_TX) ||
+		 (buff_num > (pch_can_rx_buf_size + pch_can_tx_buf_size))) {
+		dev_err(&ndev->dev, "%s ->"
+			" Invalid Message "
+			"object %u.\n", __func__, buff_num);
+		retval = -EPERM;
+	} else {
+		/* Obtaining the buffer number for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		iowrite32(CAN_CMASK_RX_TX_GET,
+			       (can->io_base + CAN_IF1_CMASK_OFFSET));
+		iowrite32(buff_num,
+			       (can->io_base + CAN_IF1_CREQ_OFFSET));
+
+		counter = COUNTER_LIMIT;
+		while (counter) {
+			if1_creq = (ioread32(can->io_base +
+						CAN_IF1_CREQ_OFFSET)) &
+						CAN_IF_CREQ_BUSY;
+			if (if1_creq == 0)
+				break;
+
+			counter--;
+		}
+
+		if (counter == 0) {
+			dev_err(&ndev->dev, "%s -> Read Failed.\n", __func__);
+			retval = -EPERM;
+		} else {
+			if (((ioread32(can->io_base +
+					CAN_IF1_ID2_OFFSET)) & CAN_ID_MSGVAL) &&
+					((ioread32(can->io_base +
+					CAN_IF1_MCONT_OFFSET)) &
+					CAN_IF_MCONT_TXIE)) {
+				*enable = ENABLE;
+
+				dev_dbg(&ndev->dev,
+					"%s -> Transmit message buffer %u is "
+					"enabled.\n", __func__, buff_num);
+			} else {
+				*enable = DISABLE;
+
+				dev_dbg(&ndev->dev,
+					"%s -> Transmit message buffer %u is "
+					"disabled.\n", __func__, buff_num);
+			}
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d.\n", __func__, retval);
+	return retval;
+}
+
+/* This function returns whether or not interrupts are pending for the CAN
+ * device.
+*/
+static int pch_can_int_pending(int handle)
+{
+	int retval = 0;
+
+	if (handle ==  0) {
+		retval = -EPERM;
+	} else {
+		/* Obatining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+		retval = (ioread32(can->io_base + CAN_INT_OFFSET) &
+							MSK_ALL_SIXTEEN);
+	}
+
+	return retval;
+}
+
+static int pch_can_set_baud_simple(int handle, enum pch_can_baud baud)
+{
+	u32 reg_val;
+	int retval = 0;
+
+	if (handle == 0) {
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+		u32 offset;
+
+		/* Setting the CCE bit of Can control register for accessing the
+							 Timing Register. */
+		PCH_CAN_BIT_SET((can->io_base + CAN_CONT_OFFSET),
+				CAN_CTRL_CCE);
+
+		/* Calculating the offset of the settings array for the current
+								 clock.  */
+		switch (pch_can_clock) {
+		case 62500:
+			offset = PCH_CAN_CLOCK_62_5_OFFSET;
+			break;
+
+		case 24000:
+			offset = PCH_CAN_CLOCK_24_OFFSET;
+			break;
+
+		case 50000:
+			offset = PCH_CAN_CLOCK_50_OFFSET;
+			break;
+
+			/* The default section will not be invoked since
+			the clock frequency has been validated at the module
+			init procedure. */
+		default:
+			offset = PCH_CAN_CLOCK_DEFAULT_OFFSET;
+			break;
+		}
+
+		/* Getting the appropriate register value. */
+		reg_val = (((can_rec_timing[baud + offset].
+				cfg_bitrate & MSK_BITT_BRP) << BIT_BITT_BRP) |
+				(can_rec_timing[baud + offset].
+				cfg_tseg1 << BIT_BITT_TSEG1) |
+				(can_rec_timing[baud + offset].cfg_tseg2 <<
+				BIT_BITT_TSEG2) |
+				(can_rec_timing[baud + offset].cfg_sjw <<
+				BIT_BITT_SJW));
+
+		/* Writing to Can Timing register. */
+		iowrite32(reg_val, (can->io_base + CAN_BITT_OFFSET));
+		/* Writing to the CAN BRP register. */
+		iowrite32(((can_rec_timing[baud + offset].
+				cfg_bitrate & MSK_BRPE_BRPE) >> BIT_BRPE_BRPE),
+				(can->io_base + CAN_BRPE_OFFSET));
+
+		/* Resetting the CCE bit of the Can control register. */
+		PCH_CAN_BIT_CLEAR((can->io_base + CAN_CONT_OFFSET),
+				  CAN_CTRL_CCE);
+	}
+
+	return retval;
+}
+
+static int pch_can_set_baud_custom(int handle, struct pch_can_timing *timing)
+{
+	u32 reg_val;
+	int retval = 0;
+
+	if ((handle == 0) || (timing == NULL))
+		retval = -EPERM;
+
+	/* max is MAX_BITRATE */
+	else if (timing->bitrate > MAX_BITRATE) {
+		retval = -EPERM;
+	}
+
+	else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Setting the CCE bit of Can control register for accessing the
+							 Can Timing register. */
+		PCH_CAN_BIT_SET((can->io_base + CAN_CONT_OFFSET),
+				CAN_CTRL_CCE);
+
+		/* Obtaining the appropriate register value. */
+		reg_val =
+		    (((timing->cfg_bitrate & MSK_BITT_BRP) << BIT_BITT_BRP) |
+		    (timing->cfg_tseg1 << BIT_BITT_TSEG1) |
+		    (timing->cfg_tseg2 << BIT_BITT_TSEG2) |
+		    (timing->cfg_sjw << BIT_BITT_SJW));
+
+		/* Writing to the timing register. */
+		iowrite32(reg_val, (can->io_base + CAN_BITT_OFFSET));
+		/* Writing to the BRP register. */
+		iowrite32(((timing->cfg_bitrate & MSK_BRPE_BRPE) >>
+					BIT_BRPE_BRPE),
+					(can->io_base + CAN_BRPE_OFFSET));
+
+		/* Resetting the CCE bit. */
+		PCH_CAN_BIT_CLEAR((can->io_base + CAN_CONT_OFFSET),
+								CAN_CTRL_CCE);
+
+	}
+
+	return retval;
+}
+
+static int pch_can_get_baud(int handle, struct pch_can_timing *timing)
+{
+	u32 timing_bitt_reg;
+	u32 timing_brpe_reg;
+	int retval = 0;
+
+	if ((handle == 0) || (timing == NULL)) {
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		timing_bitt_reg = ioread32(can->io_base + CAN_BITT_OFFSET);
+		timing_brpe_reg = ioread32(can->io_base + CAN_BRPE_OFFSET);
+
+		/* Separating the individual part from the values read. */
+		timing->cfg_bitrate = ((timing_bitt_reg & MSK_BITT_BRP) |
+			((timing_brpe_reg & MSK_BRPE_GET) << BIT_BRPE_BRPE));
+		timing->cfg_tseg1 =
+			(timing_bitt_reg & MSK_BITT_TSEG1) >> BIT_BITT_TSEG1;
+		timing->cfg_tseg2 =
+			(timing_bitt_reg & MSK_BITT_TSEG2) >> BIT_BITT_TSEG2;
+		timing->cfg_sjw =
+			(timing_bitt_reg & MSK_BITT_SJW) >> BIT_BITT_SJW;
+	}
+
+	return retval;
+}
+
+static int pch_can_set_rx_buffer_link(int handle, u32 buffer_num, u32 set,
+				      struct net_device *ndev)
+{
+	u32 counter;
+	int retval = 0;
+	u32 if1_creq;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid handle.\n", __func__);
+		retval = -EPERM;
+	} else if ((pch_msg_obj_conf[buffer_num - 1] != MSG_OBJ_RX) ||
+		(buffer_num > (pch_can_rx_buf_size + pch_can_tx_buf_size))) {
+		/* invalid buffer nummber. */
+		dev_err(&ndev->dev, "%s -> Invalid buffer number %u.\n"
+							, __func__, buffer_num);
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Reading the corresponding object. */
+		iowrite32(CAN_CMASK_RX_TX_GET,
+				(can->io_base + CAN_IF1_CMASK_OFFSET));
+		iowrite32(buffer_num,
+				(can->io_base + CAN_IF1_CREQ_OFFSET));
+
+		counter = COUNTER_LIMIT;
+		while (counter) {
+			if1_creq = ioread32((can->io_base +
+							CAN_IF1_CREQ_OFFSET)) &
+							CAN_IF_CREQ_BUSY;
+			if (if1_creq == 0)
+				break;
+
+			counter--;
+		}
+
+		/* Confirming read. */
+		if ((counter == 0)) {
+			dev_err(&ndev->dev, "%s -> Read failed\n", __func__);
+			retval = -EPERM;
+		} else {
+			iowrite32((CAN_CMASK_RDWR | CAN_CMASK_CTRL),
+				(can->io_base + CAN_IF1_CMASK_OFFSET));
+
+			/*
+			Setting/Resetting the EOD bit for Buffer link operation.
+			EOB bit = 1 -> Buffer link disabled.
+			EOB bit = 0 -> Biffer link enabled.
+			*/
+			if (set == ENABLE) {
+				PCH_CAN_BIT_CLEAR((can->io_base +
+				    CAN_IF1_MCONT_OFFSET), CAN_IF_MCONT_EOB);
+				dev_dbg(&ndev->dev,
+					"%s -> Buffer Link enabled.\n",
+					__func__);
+			} else {
+				PCH_CAN_BIT_SET((can->io_base +
+						 CAN_IF1_MCONT_OFFSET),
+						CAN_IF_MCONT_EOB);
+				dev_dbg(&ndev->dev,
+				    "%s -> Buffer Link disabled.\n", __func__);
+			}
+
+			iowrite32(buffer_num,
+				       (can->io_base + CAN_IF1_CREQ_OFFSET));
+
+			counter = COUNTER_LIMIT;
+			while (counter) {
+				if1_creq = ioread32(can->io_base +
+						CAN_IF1_CREQ_OFFSET) &
+						CAN_IF_CREQ_BUSY;
+				if (if1_creq == 0)
+					break;
+
+				counter--;
+			}
+
+			if (counter == 0) {
+				dev_err(&ndev->dev, "%s -> Write failed.\n",
+								__func__);
+				retval = -EPERM;
+			} else {
+				dev_dbg(&ndev->dev,
+					"%s -> Write successful.\n", __func__);
+				retval = 0;
+			}
+
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_get_rx_buffer_link(int handle, u32 buffer_num,
+				      u32 *link, struct net_device *ndev)
+{
+	u32 reg_val;
+	u32 counter;
+	int retval = 0;
+	u32 if1_creq;
+
+	if ((handle == 0) || (link == NULL)) {
+		dev_err(&ndev->dev, "%s -> Invalid Parameter.\n", __func__);
+		retval = -EPERM;
+	} else if ((pch_msg_obj_conf[buffer_num - 1] != MSG_OBJ_RX) ||
+		   (buffer_num > (pch_can_rx_buf_size + pch_can_tx_buf_size))) {
+		dev_err(&ndev->dev,
+		    "%s -> Invalid buffer number %u.\n", __func__, buffer_num);
+		retval = -EPERM;
+	} else {
+		/* Obatining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Reading the corresponding message object. */
+		iowrite32(CAN_CMASK_RX_TX_GET,
+			       (can->io_base + CAN_IF1_CMASK_OFFSET));
+		iowrite32(buffer_num,
+			       (can->io_base + CAN_IF1_CREQ_OFFSET));
+
+		counter = COUNTER_LIMIT;
+		while (counter) {
+			if1_creq = (ioread32((can->io_base +
+				     CAN_IF1_CREQ_OFFSET)) & CAN_IF_CREQ_BUSY);
+			if (if1_creq == 0)
+				break;
+
+			counter--;
+		}
+
+		/* Confirming read. */
+		if ((counter == 0)) {
+			dev_err(&ndev->dev, "%s -> Read Failed.\n", __func__);
+			retval = -EPERM;
+		} else {
+			/* Checking for the EOB bit.
+			   EOB bit = 1 -> Buffer link disabled.
+			   EOB bit = 0 -> Biffer link enabled.
+			 */
+			reg_val = ioread32(can->io_base +
+							CAN_IF1_MCONT_OFFSET);
+			if (reg_val & CAN_IF_MCONT_EOB)
+				*link = DISABLE;
+			else
+				*link = ENABLE;
+			dev_dbg(&ndev->dev, "%s -> EOB bit =  %d\n", __func__,
+			    (reg_val & CAN_IF_MCONT_EOB) >> BIT_SHIFT_SEVEN);
+			dev_dbg(&ndev->dev,
+			    "%s -> Buffer Link =  %u (1 - Set ,0 -> not set)\n",
+			    __func__, *link);
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_get_rx_filter(int handle, struct pch_can_rx_filter *filter,
+				 struct net_device *ndev)
+{
+	u32 reg_val1;
+	u32 reg_val2;
+	u32 counter;
+	int retval = 0;
+	u32 if1_creq;
+
+	if ((handle == 0) || (filter == NULL)) {
+		dev_err(&ndev->dev, "%s -> Invalid Parameter.\n", __func__);
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Preparing to read the specified Msg Obj. */
+		iowrite32(CAN_CMASK_RX_TX_GET,
+				(can->io_base + CAN_IF1_CMASK_OFFSET));
+		iowrite32(filter->num,
+				(can->io_base + CAN_IF1_CREQ_OFFSET));
+
+		/* Confirming the read completion. */
+		counter = COUNTER_LIMIT;
+		while (counter) {
+			if1_creq = (ioread32(can->io_base +
+				CAN_IF1_CREQ_OFFSET)) & CAN_IF_CREQ_BUSY;
+			if (if1_creq == 0)
+				break;
+
+			counter--;
+		}
+
+		if ((counter == 0)) {	/* Read unsuccessful. */
+			dev_err(&ndev->dev,
+				"%s -> Reading of receive buffer %u failed.\n",
+				__func__, filter->num);
+			retval = -EPERM;
+		} else {	/* read successful. */
+
+			/* Checking for Umask */
+			reg_val1 = ioread32((can->io_base +
+							CAN_IF1_MCONT_OFFSET));
+			filter->umask = ((CAN_IF_MCONT_UMASK & reg_val1) >>
+							BIT_SHIFT_TWELVE);
+
+			if (filter->umask == 1) {	/* If Umask is set */
+				/* Getting the Mask data. */
+
+				/* Reading MASK2 register. */
+				reg_val1 = ioread32((can->io_base +
+							CAN_IF1_MASK2_OFFSET));
+
+				if ((CAN_IF_MASK2_MXTD & reg_val1) != 0) {
+					/* Extended Mask set.
+							 Mask ID is 29 bits */
+					reg_val2 = ioread32((can->io_base +
+							CAN_IF1_MASK1_OFFSET));
+
+					/* Extracting the 16 MSB bits of the
+					 29bit ID. */
+					reg_val2 = reg_val2 & MSK_ALL_SIXTEEN;
+					/* Extracting the remaing 13 bits */
+					reg_val1 = reg_val1 & MSK_ALL_THIRTEEN;
+
+					/* Combing them to a single 29bit ID. */
+					reg_val1 =
+						reg_val1 << BIT_SHIFT_SIXTEEN;
+					reg_val1 = reg_val1 | reg_val2;
+
+					filter->amr.id = reg_val1;
+					filter->amr.id_ext = 1;
+				} else { /* Standard Mask 11bit Mask ID */
+
+					/* Extracting the 13 bits of MASK2
+								 register. */
+					reg_val1 = reg_val1 & MSK_ALL_THIRTEEN;
+
+					/* Modifying it to represent 11bit Mask
+									 ID */
+					reg_val1 = reg_val1 >> BIT_SHIFT_TWO;
+
+					filter->amr.id = reg_val1;
+					filter->amr.id_ext = 0;
+				}
+			}
+
+			reg_val1 = ioread32((can->io_base +
+							CAN_IF1_ID2_OFFSET));
+
+			if ((CAN_ID2_XTD & reg_val1) != 0) {	/* Extended ID
+								 29bits */
+				reg_val2 = ioread32((can->io_base +
+							CAN_IF1_ID1_OFFSET));
+
+				/* Extracting the 16 MSB bits of the 29bit
+									 ID. */
+				reg_val2 = reg_val2 & MSK_ALL_SIXTEEN;
+				/* Extracting the remaining 13 bit. */
+				reg_val1 = reg_val1 & MSK_ALL_THIRTEEN;
+
+				/* Combining them to represent 29bit ID. */
+				reg_val1 = reg_val1 << BIT_SHIFT_SIXTEEN;
+				reg_val1 = reg_val1 | reg_val2;
+
+				filter->aidr.id = reg_val1;
+				filter->aidr.id_ext = 1;
+			} else {	/* Standard Id 11bits. */
+
+				/* Extracting the 13 bits of ID2 register */
+				reg_val1 = reg_val1 & MSK_ALL_THIRTEEN;
+				/* Modifying it to represent the 11 bit ID */
+				reg_val1 = reg_val1 >> BIT_SHIFT_TWO;
+
+				filter->aidr.id = reg_val1;
+				filter->aidr.id_ext = 0;
+			}
+
+			dev_dbg(&ndev->dev,
+			  "%s -> Successfully read the filter of Msg Obj %u.\n",
+			  __func__, filter->num);
+		}
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d.\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_clear_buffers(int handle)
+{
+	u32 i;
+	u32 rx_buff_num;
+	u32 tx_buff_num;
+	int retval = 0;
+
+	if (handle == 0) {
+		retval = -EPERM;
+	} else {
+		/* Obatining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		iowrite32(CAN_CMASK_RX_TX_SET,
+			       (can->io_base + CAN_IF1_CMASK_OFFSET));
+		iowrite32(CAN_CMASK_RX_TX_SET,
+			       (can->io_base + CAN_IF2_CMASK_OFFSET));
+
+		iowrite32(MSK_ALL_SIXTEEN,
+			       (can->io_base + CAN_IF1_MASK1_OFFSET));
+		iowrite32(MSK_ALL_SIXTEEN,
+			       (can->io_base + CAN_IF1_MASK2_OFFSET));
+		iowrite32(MSK_ALL_SIXTEEN,
+			       (can->io_base + CAN_IF2_MASK1_OFFSET));
+		iowrite32(MSK_ALL_SIXTEEN,
+			       (can->io_base + CAN_IF2_MASK2_OFFSET));
+
+		iowrite32(0x0, (can->io_base + CAN_IF1_ID1_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF1_ID2_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF2_ID1_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF2_ID2_OFFSET));
+
+		iowrite32(0x0, (can->io_base + CAN_IF1_MCONT_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF2_MCONT_OFFSET));
+
+		iowrite32(0x0, (can->io_base + CAN_IF1_DATAA1_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF1_DATAA2_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF1_DATAB1_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF1_DATAB2_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF2_DATAA1_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF2_DATAA2_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF2_DATAB1_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF2_DATAB2_OFFSET));
+
+		for (i = 1; i <= (MAX_MSG_OBJ / 2); i++) {
+			rx_buff_num = 2 * i;
+			tx_buff_num = (2 * i) - 1;
+
+			iowrite32(rx_buff_num,
+				       (can->io_base + CAN_IF1_CREQ_OFFSET));
+			iowrite32(tx_buff_num,
+				       (can->io_base + CAN_IF2_CREQ_OFFSET));
+
+			mdelay(10);
+		}
+	}
+
+	return retval;
+}
+
+static void pch_can_config_rx_tx_buffers(int handle, struct net_device *ndev)
+{
+	u32 i;
+	u32 counter;
+	u32 if1_creq;
+	u32 if2_creq;
+
+	if (handle != 0) {	/* if handle valid. */
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/*For accssing MsgVal, ID and EOB bit */
+		iowrite32((CAN_CMASK_RDWR | CAN_CMASK_ARB |
+				CAN_CMASK_CTRL),
+			       (can->io_base + CAN_IF1_CMASK_OFFSET));
+		iowrite32((CAN_CMASK_RDWR | CAN_CMASK_ARB |
+				CAN_CMASK_CTRL),
+			       (can->io_base + CAN_IF2_CMASK_OFFSET));
+
+		iowrite32(0x0, (can->io_base + CAN_IF1_ID1_OFFSET));
+		iowrite32(0x0, (can->io_base + CAN_IF1_ID2_OFFSET));
+					/* Resetting DIR bit for reception */
+		iowrite32(0x0, (can->io_base + CAN_IF2_ID1_OFFSET));
+		iowrite32((CAN_ID2_DIR | (MSK_ALL_ELEVEN << 2)),
+					(can->io_base + CAN_IF2_ID2_OFFSET));
+					/* Setting DIR bit for transmission */
+
+		iowrite32(CAN_IF_MCONT_EOB,
+				(can->io_base + CAN_IF1_MCONT_OFFSET));
+					/* Setting EOB bit for receiver */
+		iowrite32(CAN_IF_MCONT_EOB,
+				(can->io_base + CAN_IF2_MCONT_OFFSET));
+					/* Setting EOB bit for transmitter */
+
+		for (i = 0; i < (pch_can_tx_buf_size + pch_can_rx_buf_size);
+									i++) {
+			counter = COUNTER_LIMIT;
+			/* Configure the receive message objects */
+			if (pch_msg_obj_conf[i] == MSG_OBJ_RX) {
+
+				iowrite32((i + 1), (can->io_base +
+							CAN_IF1_CREQ_OFFSET));
+
+				while (counter) {
+					if1_creq = (ioread32(can->io_base +
+							CAN_IF1_CREQ_OFFSET)) &
+							CAN_IF_CREQ_BUSY;
+					if (if1_creq == 0)
+						break;
+
+					counter--;
+				}
+
+				if ((counter == 0)) {
+					dev_dbg(&ndev->dev, "%s ->Config failed"
+					    " for receive message object %u\n",
+					    __func__, (i + 1));
+				}
+			}
+			/* Configure the transmit message objects */
+			else if (pch_msg_obj_conf[i] == MSG_OBJ_TX) {
+				iowrite32((i + 1), (can->io_base +
+							CAN_IF2_CREQ_OFFSET));
+
+				while (counter) {
+					if2_creq = (ioread32(can->io_base +
+							CAN_IF2_CREQ_OFFSET)) &
+							CAN_IF_CREQ_BUSY;
+					if (if2_creq == 0)
+						break;
+
+					counter--;
+				}
+
+				if ((counter == 0)) {
+					dev_dbg(&ndev->dev, "%s ->Config failed"
+					    " for transmit message object %u\n",
+					    __func__, (i + 1));
+				}
+			}
+
+		}
+	}
+}
+
+static int pch_can_open(int handle, enum pch_can_listen_mode listen,
+			enum pch_can_arbiter arbiter, struct net_device *ndev)
+{
+	int retval;
+	s32 i;
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid handle.\n", __func__);
+		retval = -EPERM;
+	} else {
+		do {
+			/* Stopping the Can device. */
+			retval = pch_can_set_run_mode(handle, PCH_CAN_STOP,
+									ndev);
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				    "%s -> pch_can_set_run_mode "
+				    "failed(returned %d).\n", __func__, retval);
+
+				break;
+			}
+			dev_dbg(&ndev->dev,
+			   "%s -> pch_can_set_run_mode invoked successfully.\n",
+			   __func__);
+
+			/* Clearing all the message object buffers. */
+			retval = pch_can_clear_buffers(handle);
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev, "%s ->pch_can_clear_buffers"
+				   " failed(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s ->pch_can_clear_buffers invoked"
+			     " successfully(returned %d).\n", __func__, retval);
+
+			/* Configuring the respective message object as either
+						 receive/transmit object. */
+			pch_can_config_rx_tx_buffers(handle, ndev);
+			dev_dbg(&ndev->dev, "%s -> pch_can_config_rx_tx_buffers"
+					" invoked successfully.\n", __func__);
+
+			/* Initializing filters for receive object. */
+			for (i = 0;
+			     i < (pch_can_tx_buf_size + pch_can_rx_buf_size);
+									i++) {
+				if (pch_msg_obj_conf[i] == MSG_OBJ_RX) {
+					/* Here i denotes the index, however
+						 the object number is (i+1) */
+					retval =
+					    pch_can_rx_init_filter(handle,
+							   (i + 1), ndev);
+
+					if (retval != 0) {
+						dev_err(&ndev->dev,
+						    "pch_can_rx_init_filter "
+						    "failed for msg obj:%d\n",
+						    (i + 1));
+						break;
+					}
+				}
+			}
+			if (retval != 0)
+				break;
+			dev_dbg(&ndev->dev, "%s -> pch_can_rx_init_filter "
+					"invoked successfully.\n", __func__);
+
+			/* Enabling all receive objects. */
+			retval = pch_can_rx_enable_all(handle, ndev);
+
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				    "%s -> pch_can_rx_enable_all "
+				    "failed(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s -> pch_can_rx_enable_all "
+				"invoked successfully(returned %d).\n",
+				__func__, retval);
+
+			/* Enabling all transmit objects. */
+			retval = pch_can_tx_enable_all(handle, ndev);
+
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+					"%s -> pch_can_tx_enable_all failed"
+					"(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s -> pch_can_tx_enable_all "
+				"invoked successfully(returned %d).\n",
+				__func__, retval);
+
+			/* Setting the arbiter mode. */
+			retval = pch_can_set_arbiter_mode(handle, arbiter,
+									ndev);
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				    "%s -> pch_can_set_arbiter_mode "
+				    "failed(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s -> pch_can_set_arbiter_mode "
+				"invoked successfully(returned %d).\n",
+				__func__, retval);
+
+			/* Setting the listen mode. */
+			retval = pch_can_set_listen_mode(handle, listen, ndev);
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				    "%s -> pch_can_set_listen_mode "
+				    "failed(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s -> pch_can_set_listen_mode "
+				"invoked successfully(returned %d).\n",
+				__func__, retval);
+
+			/* Enabling the interrupts. */
+			retval = pch_can_set_int_enables(handle, CAN_ALL, ndev);
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				    "%s -> pch_can_set_int_enables "
+				    "failed(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s -> pch_can_set_int_enables "
+				"invoked successfully(returned %d).\n",
+				__func__, retval);
+
+			/* Setting the restart mode. */
+			retval = pch_can_set_restart_mode(handle, CAN_AUTO,
+									ndev);
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				    "%s -> pch_can_set_restart_mode failed"
+				    "(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s -> pch_can_set_restart_mode "
+				"invoked successfully(returned %d).\n",
+				__func__, retval);
+
+			/* Setting the CAN to run mode. */
+			retval = pch_can_set_run_mode(handle, PCH_CAN_RUN,
+									ndev);
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				    "%s -> pch_can_set_run_mode "
+				    "failed(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s -> pch_can_set_set_run_mode "
+				"invoked successfully(returned %d).\n",
+				__func__, retval);
+
+		} while (false);
+	}
+
+	dev_dbg(&ndev->dev, "%s returns %d.\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_release(int handle, struct net_device *ndev)
+{
+	int retval = 0;
+
+	if (handle == 0) {
+		dev_err(&ndev->dev, "%s -> Invalid handle.\n", __func__);
+		retval = -EPERM;
+	} else {
+		do {
+			/* Stooping the CAN device. */
+			retval = pch_can_set_run_mode(handle, PCH_CAN_STOP,
+									ndev);
+
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+					"%s -> pch_can_set_run_mode failed"
+					"(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s -> pch_can_set_run_mode invoked"
+			    " successfully(returned %d).\n", __func__, retval);
+
+			/* Disabling the interrupts. */
+			retval = pch_can_set_int_enables(handle, CAN_NONE,
+									ndev);
+
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				    "%s -> pch_can_set_int_enables failed"
+				    "(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev, "%s -> pch_can_set_int_enables "
+				"invoked successfully(returned %d).\n",
+				__func__, retval);
+
+			/* Disabling all the receive object. */
+			retval = pch_can_rx_disable_all(handle, ndev);
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				"%s -> pch_can_rx_disable_all "
+				"failed(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev,
+			    "%s -> pch_can_rx_disable_all invoked "
+			    "successfully(returned %d).\n", __func__, retval);
+
+			/* Disabling all the transmit object. */
+			retval = pch_can_tx_disable_all(handle, ndev);
+			if (retval == -EPERM) {
+				dev_err(&ndev->dev,
+				    "%s -> pch_can_tx_disable_all "
+				    "failed(returned %d).\n", __func__, retval);
+				break;
+			}
+			dev_dbg(&ndev->dev,
+			    "%s -> pch_can_tx_disable_all invoked "
+			    "successfully(returned %d).\n", __func__, retval);
+
+		} while (false);
+	}
+
+	dev_dbg(&ndev->dev, "%s returns %d.\n", __func__, retval);
+	return retval;
+}
+
+/* This function clears interrupt(s) from the CAN device. */
+static void pch_can_int_clr(int handle, u32 mask, struct net_device *ndev)
+{
+	u32 counter;
+	u32 rtr;
+	u32 if2_creq;
+
+	if ((handle != 0) && (mask != 0)) {	/* if valid
+								 parameters. */
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Clearing status interrupt. */
+		if (mask == CAN_STATUS_INT) {
+			ioread32((can->io_base + CAN_STAT_OFFSET));
+			dev_dbg(&ndev->dev,
+				"%s -> Status Interrupt cleared.\n", __func__);
+		} else if ((mask > 0) && (mask <= MAX_MSG_OBJ)) {
+			/* Clear interrupt for transmit object */
+			if (pch_msg_obj_conf[mask - 1] == MSG_OBJ_TX) {
+				/* Checking if the transmission is for remote
+								 frame. */
+				rtr = ((ioread32((can->io_base +
+							CAN_IF2_ID2_OFFSET)) &
+							CAN_ID2_DIR) == 0);
+
+				if (rtr == 1) {
+
+					dev_dbg(&ndev->dev,
+					    "%s -> Remote frame transmission "
+					    "interrupt cleared for message"
+					    "object %d.\n", __func__, mask);
+				} else {
+					dev_dbg(&ndev->dev,
+					  "%s -> Data frame transmission "
+					  "interrupt cleared for message "
+					  "object %d.\n", __func__, mask);
+				}
+
+				/* Setting CMASK for clearing interrupts for
+							 frame transmission. */
+				iowrite32((CAN_CMASK_RDWR | CAN_CMASK_CTRL |
+							CAN_CMASK_ARB),
+							(can->io_base +
+							CAN_IF2_CMASK_OFFSET));
+
+				/* Resetting the ID registers. */
+				PCH_CAN_BIT_SET((can->io_base +
+						 CAN_IF2_ID2_OFFSET),
+						(CAN_ID2_DIR |
+						 (MSK_ALL_ELEVEN << 2)));
+				iowrite32(0x0,
+					(can->io_base + CAN_IF2_ID1_OFFSET));
+
+				/* Claring NewDat, TxRqst & IntPnd */
+				PCH_CAN_BIT_CLEAR((can->io_base +
+						   CAN_IF2_MCONT_OFFSET),
+						  (CAN_IF_MCONT_NEWDAT |
+						   CAN_IF_MCONT_INTPND |
+						   CAN_IF_MCONT_TXRQXT));
+
+				iowrite32(mask,
+				       (can->io_base + CAN_IF2_CREQ_OFFSET));
+
+				counter = COUNTER_LIMIT;
+				while (counter) {
+					if2_creq = (ioread32(can->io_base +
+							CAN_IF2_CREQ_OFFSET) &
+							CAN_IF_CREQ_BUSY);
+					if (if2_creq == 0)
+						break;
+
+					counter--;
+				}
+			}
+			/* Clear interrupt for receive object */
+			else if (pch_msg_obj_conf[mask - 1] == MSG_OBJ_RX) {
+				/* Checking if the reception is for remote
+								 frame. */
+				rtr = ((ioread32((can->io_base +
+							CAN_IF2_ID2_OFFSET)) &
+							CAN_ID2_DIR) != 0);
+
+				if (rtr == 1) {	/* if remote frame. */
+					dev_dbg(&ndev->dev,
+						"%s -> Remote frame reception "
+						"interrupt cleared for message "
+						"object %d.\n", __func__, mask);
+				} else {
+					dev_dbg(&ndev->dev,
+					  "%s -> Data frame reception "
+					  "interrupt cleared for message object"
+					  "%d.\n", __func__, mask);
+				}
+
+				/* Setting CMASK for clearing the reception
+								 interrupts. */
+				iowrite32((CAN_CMASK_RDWR | CAN_CMASK_CTRL |
+							CAN_CMASK_ARB),
+							(can->io_base +
+							CAN_IF2_CMASK_OFFSET));
+
+				/* Clearing the Dir bit. */
+				PCH_CAN_BIT_CLEAR((can->io_base +
+							CAN_IF2_ID2_OFFSET),
+							CAN_ID2_DIR);
+
+				/* Clearing NewDat & IntPnd */
+				PCH_CAN_BIT_CLEAR((can->io_base +
+						   CAN_IF2_MCONT_OFFSET),
+						  (CAN_IF_MCONT_NEWDAT |
+						   CAN_IF_MCONT_INTPND));
+
+				iowrite32(mask,
+				       (can->io_base + CAN_IF2_CREQ_OFFSET));
+
+				counter = COUNTER_LIMIT;
+				while (counter) {
+					if2_creq = ioread32(can->io_base +
+							CAN_IF2_CREQ_OFFSET) &
+							CAN_IF_CREQ_BUSY;
+					if (if2_creq == 0)
+						break;
+
+					counter--;
+				}
+
+			}
+		}
+	}
+}
+
+static int pch_can_get_buffer_status(int handle)
+{
+	u32 reg_treq1;
+	u32 reg_treq2;
+	int retval = 0;
+
+	if (handle == 0) {
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Reading the transmission request registers. */
+		reg_treq1 = (ioread32(can->io_base + CAN_TREQ1_OFFSET) &
+							MSK_ALL_SIXTEEN);
+		reg_treq2 = ((ioread32(can->io_base + CAN_TREQ2_OFFSET) &
+					MSK_ALL_SIXTEEN) << BIT_SHIFT_SIXTEEN);
+
+		retval = (reg_treq1 | reg_treq2);
+	}
+
+	return retval;
+}
+
+static int pch_can_msg_tx(int handle, struct pch_can_msg *msg,
+			  struct net_device *ndev)
+{
+	u32 id1 = 0;
+	u32 id2 = 0;
+	u32 data_a1 = 0;
+	u32 data_a2 = 0;
+	u32 data_b1 = 0;
+	u32 data_b2 = 0;
+	u32 tx_disable_counter = 0;
+	u32 buffer_status = 0;
+	u32 tx_buffer_avail = 0;
+	u32 status;
+	u32 i;
+	u32 counter;
+	enum pch_can_run_mode run_mode;
+	int retval = 0;
+	u32 if1_creq;
+
+	if ((handle == 0) || (msg == NULL)) {
+		dev_err(&ndev->dev, "%s -> Invalid Parameter.\n", __func__);
+		retval = -EPERM;
+	}
+
+	else {
+		/* Obatining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		/* Getting the current CAN mode. */
+		pch_can_get_run_mode(handle, &run_mode, ndev);
+
+		/* If CAN is in STOP mode. */
+		if (run_mode != PCH_CAN_RUN) {
+			dev_err(&ndev->dev,
+			  "%s -> CAN stopped on transmit attempt.\n", __func__);
+			retval = -EPERM;
+		} else {
+			unsigned long flags;
+			/* Attaining the lock. */
+			spin_lock_irqsave(&can_os->tx_spinlock, flags);
+
+			/* Getting the message object status. */
+			buffer_status = (u32) pch_can_get_buffer_status(handle);
+
+			/* Getting the free transmit message object. */
+			for (i = 0;
+			     i < (pch_can_rx_buf_size + pch_can_tx_buf_size);
+									i++) {
+				if ((pch_msg_obj_conf[i] == MSG_OBJ_TX)) {
+					/* Checking whether the object is
+								enabled. */
+					pch_can_get_tx_enable(handle,
+								(i + 1),
+								&status, ndev);
+
+					if ((ENABLE == status)) {
+						if ((((buffer_status >> i) & 1)
+									== 0)) {
+							tx_buffer_avail =
+							    (i + 1);
+							break;
+						}
+					} else {
+						tx_disable_counter++;
+					}
+				}
+			}
+
+			/* If no transmit object available. */
+			if (tx_buffer_avail == 0) {
+				dev_dbg(&ndev->dev, "%s -> tx_disable_counter "
+				    "= %d.\n", __func__, tx_disable_counter);
+				/* If no object is enabled. */
+				if ((tx_disable_counter ==
+							pch_can_tx_buf_size)){
+					retval = -EPERM;
+					dev_err(&ndev->dev,
+						"%s -> All transmit buffers "
+						"are disabled.\n", __func__);
+				} else {
+					dev_err(&ndev->dev,
+					    "%s -> No transmit buffer free.\n",
+					    __func__);
+					retval = PCH_CAN_NO_TX_BUFF;
+				}
+			} else {
+				dev_dbg(&ndev->dev,
+				  "%s ->Transmit buffer obtained.\n", __func__);
+
+				/* Reading the message object from the Message
+					 RAM to the Interface register. */
+				iowrite32(CAN_CMASK_RX_TX_GET,
+					       (can->io_base +
+						CAN_IF1_CMASK_OFFSET));
+				iowrite32(tx_buffer_avail,
+					       (can->io_base +
+						CAN_IF1_CREQ_OFFSET));
+
+				/* Confirming the read. */
+				counter = COUNTER_LIMIT;
+				while (counter) {
+					if1_creq = (ioread32(can->io_base +
+							CAN_IF1_CREQ_OFFSET)) &
+							CAN_IF_CREQ_BUSY;
+					if (if1_creq == 0)
+						break;
+
+					counter--;
+				}
+				/* If Read not successful. */
+				if (counter == 0) {
+					pch_can_set_tx_enable(handle,
+								tx_buffer_avail,
+								ENABLE, ndev);
+					retval = -EPERM;
+				} else {
+					/* Setting the CMASK register. */
+					PCH_CAN_BIT_SET((can->io_base +
+							 CAN_IF1_CMASK_OFFSET),
+							CAN_CMASK_ALL);
+
+					/* If ID extended is set. */
+					if (msg->ide == 1) {
+						/* Setting 29 bit ID with XTD
+								 bit set. */
+						id1 =
+						    (msg->id & MSK_ALL_SIXTEEN);
+						id2 =
+						    ((msg->
+						      id & (MSK_ALL_THIRTEEN <<
+							    BIT_SHIFT_SIXTEEN))
+						     >> BIT_SHIFT_SIXTEEN);
+
+						id2 |= CAN_ID2_XTD;
+					} else {
+						/* Setting 11bit ID with XTD bit
+								 reset. */
+						id1 = 0;
+						id2 =
+						    ((msg->
+						      id & MSK_ALL_ELEVEN) <<
+						     BIT_SHIFT_TWO);
+					}
+					PCH_CAN_BIT_CLEAR((can->io_base +
+							   CAN_IF1_ID1_OFFSET),
+							  MSK_ALL_SIXTEEN);
+					PCH_CAN_BIT_CLEAR((can->io_base +
+							   CAN_IF1_ID2_OFFSET),
+							  (MSK_ALL_THIRTEEN |
+							   CAN_ID2_XTD));
+
+					PCH_CAN_BIT_SET((can->io_base +
+							 CAN_IF1_ID1_OFFSET),
+							id1);
+					PCH_CAN_BIT_SET((can->io_base +
+							 CAN_IF1_ID2_OFFSET),
+							id2);
+
+					/* If remote frame has to be
+							 transmitted.. */
+					if (msg->rtr == 1) {
+						PCH_CAN_BIT_CLEAR((
+							can->io_base +
+							CAN_IF1_ID2_OFFSET),
+							CAN_ID2_DIR);
+						msg->dlc = 0;
+
+						dev_dbg(&ndev->dev,
+						  "%s -> Transmitting a remote"
+						  " frame.\n", __func__);
+					} else {	/* Data frame
+							 transmission. */
+
+						msg->dlc &= MSK_ALL_FOUR;
+
+						dev_dbg(&ndev->dev,
+						  "%s -> Transmitting a data "
+						  "frame.\n", __func__);
+					}
+
+					/* Writing the data and the DLC */
+					switch (msg->dlc) {
+					case 0:
+						break;
+
+					case 1:
+						data_a1 = msg->data[0];
+						break;
+					case 2:
+						data_a1 = msg->data[0];
+						data_a1 |=
+						    (((u32) msg->
+						      data[1]) <<
+						     BIT_SHIFT_EIGHT);
+						break;
+					case 3:
+						data_a1 = msg->data[0];
+						data_a1 |=
+						    (((u32) msg->
+						      data[1]) <<
+						     BIT_SHIFT_EIGHT);
+						data_a2 = msg->data[2];
+						break;
+					case 4:
+						data_a1 = msg->data[0];
+						data_a1 |=
+						    (((u32) msg->
+						      data[1]) <<
+						     BIT_SHIFT_EIGHT);
+						data_a2 = msg->data[2];
+						data_a2 |=
+						    (((u32) msg->
+						      data[3]) <<
+						     BIT_SHIFT_EIGHT);
+						break;
+					case 5:
+						data_a1 = msg->data[0];
+						data_a1 |=
+						    (((u32) msg->
+						      data[1]) <<
+						     BIT_SHIFT_EIGHT);
+						data_a2 = msg->data[2];
+						data_a2 |=
+						    (((u32) msg->
+						      data[3]) <<
+						     BIT_SHIFT_EIGHT);
+						data_b1 = msg->data[4];
+						break;
+					case 6:
+						data_a1 = msg->data[0];
+						data_a1 |=
+						    (((u32) msg->
+						      data[1]) <<
+						     BIT_SHIFT_EIGHT);
+						data_a2 = msg->data[2];
+						data_a2 |=
+						    (((u32) msg->
+						      data[3]) <<
+						     BIT_SHIFT_EIGHT);
+						data_b1 = msg->data[4];
+						data_b1 |=
+						    (((u32) msg->
+						      data[5]) <<
+						     BIT_SHIFT_EIGHT);
+						break;
+					case 7:
+						data_a1 = msg->data[0];
+						data_a1 |=
+						    (((u32) msg->
+						      data[1]) <<
+						     BIT_SHIFT_EIGHT);
+						data_a2 = msg->data[2];
+						data_a2 |=
+						    (((u32) msg->
+						      data[3]) <<
+						     BIT_SHIFT_EIGHT);
+						data_b1 = msg->data[4];
+						data_b1 |=
+						    (((u32) msg->
+						      data[5]) <<
+						     BIT_SHIFT_EIGHT);
+						data_b2 = msg->data[6];
+						break;
+					case 8:
+					default:
+						data_a1 = msg->data[0];
+						data_a1 |=
+						    (((u32) msg->
+						      data[1]) <<
+						     BIT_SHIFT_EIGHT);
+						data_a2 = msg->data[2];
+						data_a2 |=
+						    (((u32) msg->
+						      data[3]) <<
+						     BIT_SHIFT_EIGHT);
+						data_b1 = msg->data[4];
+						data_b1 |=
+						    (((u32) msg->
+						      data[5]) <<
+						     BIT_SHIFT_EIGHT);
+						data_b2 = msg->data[6];
+						data_b2 |=
+						    (((u32) msg->
+						      data[7]) <<
+						     BIT_SHIFT_EIGHT);
+						break;
+
+					}
+
+					/* Writing the DATA registers. */
+					iowrite32(data_a1,
+						       (can->io_base +
+							CAN_IF1_DATAA1_OFFSET));
+					iowrite32(data_a2,
+						       (can->io_base +
+							CAN_IF1_DATAA2_OFFSET));
+					iowrite32(data_b1,
+						       (can->io_base +
+							CAN_IF1_DATAB1_OFFSET));
+					iowrite32(data_b2,
+						       (can->io_base +
+							CAN_IF1_DATAB2_OFFSET));
+
+					/* Updating the size of the data. */
+					PCH_CAN_BIT_CLEAR((can->io_base +
+							  CAN_IF1_MCONT_OFFSET),
+							  MSK_ALL_FOUR);
+					PCH_CAN_BIT_SET((can->io_base +
+							 CAN_IF1_MCONT_OFFSET),
+							msg->dlc);
+
+					/* Clearing IntPend, NewDat & TxRqst */
+					PCH_CAN_BIT_CLEAR((can->io_base +
+							CAN_IF1_MCONT_OFFSET),
+							(CAN_IF_MCONT_NEWDAT |
+							CAN_IF_MCONT_INTPND |
+							CAN_IF_MCONT_TXRQXT));
+
+					/* Setting NewDat, TxRqst bits */
+					PCH_CAN_BIT_SET((can->io_base +
+							 CAN_IF1_MCONT_OFFSET),
+							(CAN_IF_MCONT_NEWDAT |
+							 CAN_IF_MCONT_TXRQXT));
+
+					/* Writing the updation to the Message
+								 object. */
+					iowrite32(tx_buffer_avail,
+						       (can->io_base +
+							CAN_IF1_CREQ_OFFSET));
+
+					/* Confirming the updation. */
+					counter = COUNTER_LIMIT;
+					while (counter) {
+						if1_creq = (ioread32(
+							can->io_base +
+							CAN_IF1_CREQ_OFFSET)) &
+							CAN_IF_CREQ_BUSY;
+						if (if1_creq == 0)
+							break;
+
+						counter--;
+					}
+
+					if ((counter == 0)) {
+						retval = -EPERM;
+					} else {
+						dev_dbg(&ndev->dev,
+						  "%s -> Updation of transmit "
+						  "buffer successful.\n"
+						  "Message object enabled "
+						  "for transmission.\n",
+						  __func__);
+					}
+
+				}	/* if message read object successful */
+			}	/* if transmit buffer available */
+
+			/* Releasing the lock. */
+			spin_unlock_irqrestore(&can_os->tx_spinlock, flags);
+		}		/* if device in run mode */
+	}			/* if parameters valid */
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d.\n", __func__, retval);
+	return retval;
+}
+
+/* This function gets a pending message from the CAN device. */
+static int pch_can_rx_dequeue(int handle, struct pch_can_msg *msg,
+			      u32 buff_num, struct net_device *ndev)
+{
+	s32 i;
+	u32 reg;
+	int retval = -EPERM;
+
+	if ((handle == 0) || (msg == NULL)) {
+		dev_err(&ndev->dev, "%s -> Invalid Parameter.\n", __func__);
+	} else if ((pch_msg_obj_conf[buff_num - 1] != MSG_OBJ_RX) ||
+		 (buff_num > (pch_can_rx_buf_size + pch_can_tx_buf_size))) {
+		/* invalid buffer number. */
+		dev_err(&ndev->dev, "%s -> Invalid Buffer number.\n", __func__);
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) handle;
+
+		msg->ide = 0;
+		msg->id = 0;
+		msg->dlc = 0;
+		for (i = 0; i < PCH_CAN_MSG_DATA_LEN;)
+			msg->data[i++] = 0;
+
+		/* Read the ID type. */
+		msg->ide = ((ioread32(can->io_base + CAN_IF2_ID2_OFFSET)) &
+					CAN_ID2_XTD) >> BIT_SHIFT_FOURTEEN;
+
+		/* Extracting the ID. */
+		if (msg->ide == 1) {	/* Extended 29bit ID. */
+			msg->id = (ioread32(can->io_base +
+					CAN_IF2_ID1_OFFSET) & MSK_ALL_SIXTEEN);
+			msg->id |= (((ioread32(can->io_base +
+					CAN_IF2_ID2_OFFSET)) &
+					MSK_ALL_THIRTEEN) << BIT_SHIFT_SIXTEEN);
+		} else {	/* Standard 11bit ID. */
+
+			msg->id = (((ioread32(can->io_base +
+						CAN_IF2_ID2_OFFSET)) &
+						(MSK_ALL_ELEVEN <<
+						BIT_SHIFT_TWO)) >>
+						BIT_SHIFT_TWO);
+		}
+
+		/* Getting the size of the data and the Remote frame bit. */
+		if (msg->rtr == 1) {
+			msg->dlc = 0;
+
+			dev_dbg(&ndev->dev,
+			    "%s -> Remote frame read with message id: %x.\n",
+			    __func__, msg->id);
+		} else {
+			msg->dlc = ((ioread32(can->io_base +
+						CAN_IF2_MCONT_OFFSET)) &
+						MSK_ALL_FOUR);
+
+			dev_dbg(&ndev->dev,
+			    "%s -> Data frame read with message id: %x.\n",
+			    __func__, msg->id);
+		}
+
+		/* Reading back the data. */
+		switch (msg->dlc) {
+		case 0:
+			break;
+
+		case 1:
+			reg = ioread32(can->io_base + CAN_IF2_DATAA1_OFFSET);
+			msg->data[0] = reg & MSK_ALL_EIGHT;
+			break;
+
+		case 2:
+			reg = ioread32(can->io_base + CAN_IF2_DATAA1_OFFSET);
+			msg->data[0] = reg & MSK_ALL_EIGHT;
+			msg->data[1] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+			break;
+
+		case 3:
+			reg = ioread32(can->io_base + CAN_IF2_DATAA1_OFFSET);
+			msg->data[0] = reg & MSK_ALL_EIGHT;
+			msg->data[1] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAA2_OFFSET);
+			msg->data[2] = reg & MSK_ALL_EIGHT;
+			break;
+
+		case 4:
+			reg = ioread32(can->io_base + CAN_IF2_DATAA1_OFFSET);
+			msg->data[0] = reg & MSK_ALL_EIGHT;
+			msg->data[1] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAA2_OFFSET);
+			msg->data[2] = reg & MSK_ALL_EIGHT;
+			msg->data[3] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+			break;
+
+		case 5:
+			reg = ioread32(can->io_base + CAN_IF2_DATAA1_OFFSET);
+			msg->data[0] = reg & MSK_ALL_EIGHT;
+			msg->data[1] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAA2_OFFSET);
+			msg->data[2] = reg & MSK_ALL_EIGHT;
+			msg->data[3] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAB1_OFFSET);
+			msg->data[4] = reg & MSK_ALL_EIGHT;
+			break;
+
+		case 6:
+			reg = ioread32(can->io_base + CAN_IF2_DATAA1_OFFSET);
+			msg->data[0] = reg & MSK_ALL_EIGHT;
+			msg->data[1] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAA2_OFFSET);
+			msg->data[2] = reg & MSK_ALL_EIGHT;
+			msg->data[3] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAB1_OFFSET);
+			msg->data[4] = reg & MSK_ALL_EIGHT;
+			msg->data[5] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+			break;
+
+		case 7:
+			reg = ioread32(can->io_base + CAN_IF2_DATAA1_OFFSET);
+			msg->data[0] = reg & MSK_ALL_EIGHT;
+			msg->data[1] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAA2_OFFSET);
+			msg->data[2] = reg & MSK_ALL_EIGHT;
+			msg->data[3] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAB1_OFFSET);
+			msg->data[4] = reg & MSK_ALL_EIGHT;
+			msg->data[5] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAB2_OFFSET);
+			msg->data[6] = reg & MSK_ALL_EIGHT;
+			break;
+
+		case 8:
+		default:
+			reg = ioread32(can->io_base + CAN_IF2_DATAA1_OFFSET);
+			msg->data[0] = reg & MSK_ALL_EIGHT;
+			msg->data[1] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAA2_OFFSET);
+			msg->data[2] = reg & MSK_ALL_EIGHT;
+			msg->data[3] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAB1_OFFSET);
+			msg->data[4] = reg & MSK_ALL_EIGHT;
+			msg->data[5] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			reg = ioread32(can->io_base + CAN_IF2_DATAB2_OFFSET);
+			msg->data[6] = reg & MSK_ALL_EIGHT;
+			msg->data[7] =
+			    ((reg & (MSK_ALL_EIGHT << BIT_SHIFT_EIGHT))
+			     >> BIT_SHIFT_EIGHT);
+
+			break;
+		}
+		retval = 0;
+	}
+
+	dev_dbg(&ndev->dev, "%s -> Return value: %d\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_reset(struct pch_can_os *can_os)
+{
+	int retval = 0;
+
+	if ((can_os == NULL)) {
+		retval = -EPERM;
+	} else {
+		/* Obtaining the remap address for access. */
+		struct can_hw *can = (struct can_hw *) can_os->can;
+
+		/* write to sw reset register */
+		iowrite32(1, (can->io_base + CAN_SRST_OFFSET));
+		iowrite32(0, (can->io_base + CAN_SRST_OFFSET));
+
+	}
+	return retval;
+}
+
+static irqreturn_t pch_can_handler(int irq, void *dev_id)
+{
+	irqreturn_t retval = IRQ_NONE;
+	u32 int_stat;
+	struct pch_can_os *can_os = (struct pch_can_os *) dev_id;
+	dev_dbg(&can_os->ndev->dev, "%s -> Invoked.\n", __func__);
+
+	int_stat = pch_can_int_pending(can_os->can);
+
+	dev_dbg(&can_os->ndev->dev,
+	  "%s -> pch_can_int_pending returned value: %x\n", __func__, int_stat);
+
+	if ((can_os != NULL) && (int_stat > 0)) {
+		can_os->int_stat = int_stat;
+		(*can_os->can_callback) (can_os);
+
+		dev_dbg(&can_os->ndev->dev,
+		   "%s -> Callback function invoked successfully.\n", __func__);
+
+		retval = IRQ_HANDLED;
+	}
+	return retval;
+}
+
+static void pch_can_log_message(u32 status, struct net_device *ndev)
+{
+	static int cnt;
+
+	switch ((status & MSK_ALL_THREE)) {
+
+	case 0:
+		dev_dbg(&ndev->dev, "%s ->  No Error\n", __func__);
+		break;
+	case 1:
+		dev_err(&ndev->dev, "%s -> Stuff Error\n", __func__);
+		break;
+	case 2:
+		dev_err(&ndev->dev, "%s -> Form Error.\n", __func__);
+		break;
+	case 3:
+		if (cnt % 200 == 0)
+			dev_err(&ndev->dev, "%s -> Ack Error\n", __func__);
+		cnt++;
+		break;
+	case 4:
+		dev_err(&ndev->dev, "%s -> Bit 1 Error\n", __func__);
+		break;
+	case 5:
+		dev_err(&ndev->dev, "%s -> Bit 0 Error.\n", __func__);
+		break;
+	case 6:
+		dev_err(&ndev->dev, "%s -> Crc Error\n", __func__);
+		break;
+	case 7:
+		dev_err(&ndev->dev, "%s -> Undefined Error\n", __func__);
+		break;
+	default:
+		break;
+	}
+}
+
+static void pch_can_entcb(void (*pch_can_cb) (struct pch_can_os *),
+			  struct pch_can_os *p_can_os, struct net_device *ndev)
+{
+	if ((pch_can_cb != NULL) && (p_can_os != NULL)) {
+		p_can_os->can_callback = pch_can_cb;
+		dev_dbg(&ndev->dev,
+		    "%s -> Callback function set successful.\n", __func__);
+	} else {
+		dev_err(&ndev->dev,
+		    "%s -> Callback function set unsuccessful.\n", __func__);
+	}
+}
+
+static void pch_can_callback(struct pch_can_os *can_os)
+{
+	u32 int_stat;
+	u32 reg;
+	u32 reg_stat;
+	u32 counter;
+	struct pch_can_msg receive_msg;
+	struct can_hw *can = (struct can_hw *) (can_os->can);
+	int retval = 0;
+	u32 if2_creq;
+	enum pch_can_auto_restart restart_mode = 0;
+
+
+	/* Get the interrupt status */
+	int_stat = can_os->int_stat;
+	can_os->int_stat = 0;
+
+	/* Checking for status interrupt */
+	if (int_stat == CAN_STATUS_INT) {
+		/* Reading of the CANSTAT register. */
+		reg_stat = ioread32((can->io_base + CAN_STAT_OFFSET));
+		reg_stat = reg_stat & MSK_ALL_EIGHT;
+		dev_dbg(&can_os->ndev->dev,
+			"%s -> Status Register: %x.\n", __func__, reg_stat);
+
+		/* If recovered from Bus-Off interrupt. */
+		if ((reg_stat == 0) && (can_os->bus_off_interrupt == 1)) {
+			can_os->bus_off_interrupt = 0;
+			pch_can_tx_enable_all(can_os->can, can_os->ndev);
+			pch_can_rx_enable_all(can_os->can, can_os->ndev);
+
+			dev_err(&can_os->ndev->dev,
+				"%s -> Bus off stage recovered.\n", __func__);
+		} else {
+			/* Bus off interrupt. */
+			if (reg_stat & ((u32) 1 << BIT_SHIFT_SEVEN)) {
+				if (can_os->bus_off_interrupt == 0) {
+
+					dev_err(&can_os->ndev->dev,
+						"%s -> Bus off "
+						"interrupt.\n", __func__);
+
+					pch_can_tx_disable_all(can_os->can,
+								can_os->ndev);
+					pch_can_rx_disable_all(can_os->can,
+								can_os->ndev);
+
+					pch_can_get_restart_mode(can_os->can,
+						&restart_mode, can_os->ndev);
+
+					if (restart_mode == CAN_AUTO) {
+						can_os->bus_off_interrupt = 1;
+						pch_can_set_run_mode(
+							can_os->can,
+							PCH_CAN_RUN,
+							can_os->ndev);
+						dev_dbg(&can_os->ndev->dev,
+						    "%s -> Device restarted.\n",
+						    __func__);
+					}
+				}
+			}
+			/* EWarn interrupt. */
+			if ((reg_stat & ((u32) 1 << BIT_SHIFT_SIX)) != 0) {
+				dev_info(&can_os->ndev->dev,
+					"%s -> EWarn interrupt.\n", __func__);
+			}
+			/* EPass interrupt. */
+			if ((reg_stat & ((u32) 1 << BIT_SHIFT_FIVE)) != 0) {
+				dev_dbg(&can_os->ndev->dev,
+					"%s -> EPass interrupt.\n", __func__);
+			}
+			/* RxOK interrupt. */
+			if ((reg_stat & ((u32) 1 << BIT_SHIFT_FOUR)) != 0) {
+				dev_dbg(&can_os->ndev->dev,
+					"%s -> RxOK interrupt.\n", __func__);
+				reg_stat =
+				    reg_stat & ~((u32) 1 << BIT_SHIFT_FOUR);
+			}
+			/* TxOK interrupt */
+			if ((reg_stat & ((u32) 1 << BIT_SHIFT_THREE)) != 0) {
+				dev_dbg(&can_os->ndev->dev,
+					"%s -> TxOK interrupt.\n", __func__);
+				reg_stat =
+				    reg_stat & ~((u32) 1 << BIT_SHIFT_THREE);
+			}
+			/* Error status */
+			pch_can_log_message((reg_stat & MSK_ALL_THREE),
+								can_os->ndev);
+			reg_stat = reg_stat & ~(MSK_ALL_THREE);
+
+			/* Clearing status register interrupt bits. */
+			iowrite32(reg_stat,
+					(can->io_base + CAN_STAT_OFFSET));
+
+			int_stat = pch_can_int_pending(can_os->can);
+		}
+	}
+
+	/* Message object interrupt. */
+	if ((int_stat > 0) && (int_stat <= MAX_MSG_OBJ)) {
+		/* Reading the messsage object from the Message RAM to the
+							 interface registers. */
+		iowrite32(CAN_CMASK_RX_TX_GET,
+			       (can->io_base + CAN_IF2_CMASK_OFFSET));
+		iowrite32((int_stat),
+			       (can->io_base + CAN_IF2_CREQ_OFFSET));
+
+		/* Confirming the read. */
+		counter = COUNTER_LIMIT;
+		while (counter) {
+			if2_creq = (ioread32(can->io_base +
+						CAN_IF2_CREQ_OFFSET)) &
+						CAN_IF_CREQ_BUSY;
+
+			if (if2_creq == 0)
+				break;
+
+			counter--;
+		}
+
+		if (counter > 0) {	/* If read successful. */
+			/* Reading the MCONT register. */
+			reg = ioread32((can->io_base +
+							CAN_IF2_MCONT_OFFSET));
+			reg &= MSK_ALL_SIXTEEN;
+
+			/* If MsgLost bit set. */
+			if ((reg & CAN_IF_MCONT_MSGLOST) != 0) {
+				PCH_CAN_BIT_CLEAR((can->io_base +
+						   CAN_IF2_MCONT_OFFSET),
+						  CAN_IF_MCONT_MSGLOST);
+
+				dev_err(&can_os->ndev->dev,
+				    "%s -> Message object %d has "
+				    "been overwritten.\n", __func__, int_stat);
+			}
+
+			/* Read the direction bit for determination of remote
+						 frame during reception. */
+			receive_msg.rtr = ((ioread32((can->io_base +
+							CAN_IF2_ID2_OFFSET)) &
+							CAN_ID2_DIR) != 0);
+
+			/* Clearing interrupts. */
+			pch_can_int_clr(can_os->can, int_stat, can_os->ndev);
+			dev_dbg(&can_os->ndev->dev,
+			    "%s -> pch_can_int_clr invoked successfully.\n",
+			    __func__);
+
+			/* Hanlde reception interrupt */
+			if (pch_msg_obj_conf[int_stat - 1] == MSG_OBJ_RX) {
+				/* If new data arrived */
+				if ((reg & CAN_IF_MCONT_NEWDAT) != 0) {
+					/* Reading the message object content.*/
+					retval =
+					    pch_can_rx_dequeue(can_os->can,
+							&receive_msg,
+							int_stat, can_os->ndev);
+
+					if (retval == 0) {
+						struct sk_buff *skb;
+						struct can_frame *cf;
+						struct net_device_stats *stats;
+						stats = &(can_os->ndev->stats);
+						/* create zero'ed CAN frame
+								 buffer */
+						skb = alloc_can_skb
+							(can_os->ndev, &cf);
+						if (skb == NULL)
+							return;
+
+						if (receive_msg.ide) {
+							cf->can_id =
+							    ((receive_msg.id) &
+							    0x1fffffff) |
+							    0x80000000;
+						} else { /* Standard*/
+							cf->can_id =
+							    ((receive_msg.id) &
+							    0x00000fff);
+						}
+						if (receive_msg.rtr)
+							cf->can_id |=
+								0x40000000;
+						cf->can_dlc = receive_msg.dlc;
+						memcpy(cf->data,
+							receive_msg.data, 8);
+						netif_rx(skb);
+						stats->rx_packets++;
+						stats->rx_bytes += cf->can_dlc;
+
+					}
+					dev_dbg(&can_os->ndev->dev,
+					  "%s -> Reception interrupt handled "
+					  "for receive message object %u.\n",
+					  __func__, int_stat);
+				}
+
+			}
+			/* Hanlde transmission interrupt */
+			else if (pch_msg_obj_conf[int_stat - 1] == MSG_OBJ_TX) {
+				can_get_echo_skb(can_os->ndev, 0);
+				netif_wake_queue(can_os->ndev);
+
+				dev_dbg(&can_os->ndev->dev,
+				  "%s -> Transmission interrupt handled for "
+				  "transmit message object %u.\n",
+				  __func__, int_stat);
+			}
+		}
+	}
+}
+
+static void pch_can_start(struct net_device *ndev)
+{
+	struct pch_can_priv *priv = netdev_priv(ndev);
+
+	pch_can_reset(priv->pch_can_os_p);
+
+	return;
+}
+
+static int pch_can_do_set_mode(struct net_device *ndev, enum can_mode mode)
+{
+	int ret = 0;
+
+	switch (mode) {
+	case CAN_MODE_START:
+		pch_can_start(ndev);
+		netif_wake_queue(ndev);
+		break;
+	default:
+		ret = -EOPNOTSUPP;
+		break;
+	}
+
+	return ret;
+}
+
+static int pch_can_get_state(const struct net_device *ndev,
+			     enum can_state *state)
+{
+	struct pch_can_priv *priv = netdev_priv(ndev);
+
+	*state = priv->can.state;
+	return 0;
+}
+
+static int get_baud_id(int baud_bps)
+{
+	int id;
+	switch (baud_bps) {
+	case 10000:/* 10kbps*/
+		id = PCH_CAN_BAUD_10;
+		break;
+	case 20000:
+		id = PCH_CAN_BAUD_20;
+		break;
+	case 50000:
+		id = PCH_CAN_BAUD_50;
+		break;
+	case 125000:
+		id = PCH_CAN_BAUD_125;
+		break;
+	case 250000:
+		id = PCH_CAN_BAUD_250;
+		break;
+	case 500000:
+		id = PCH_CAN_BAUD_500;
+		break;
+	case 800000:
+		id = PCH_CAN_BAUD_800;
+		break;
+	case 1000000:
+		id = PCH_CAN_BAUD_1000;
+		break;
+	default:
+		id = -1;
+	}
+	return id;
+}
+
+static int pch_set_bittiming(struct net_device *ndev)
+{
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct pch_can_os *dev_can_os = priv->pch_can_os_p;
+	const struct can_bittiming *bt = &priv->can.bittiming;
+	struct pch_can_timing pch_can_timing_data;
+	int baurate_id;
+	enum pch_can_run_mode curr_mode;
+	int retval;
+
+	memset(&pch_can_timing_data, 0, sizeof(pch_can_timing_data));
+	pch_can_timing_data.bitrate = bt->bitrate/1000; /* bps to Kbps */
+	pch_can_timing_data.cfg_bitrate = (bt->tq) / (1000000/pch_can_clock);
+							/* Tq to BRP */
+	pch_can_timing_data.cfg_tseg1 = bt->phase_seg1;
+	pch_can_timing_data.cfg_tseg2 = bt->phase_seg2;
+	pch_can_timing_data.cfg_sjw = bt->sjw;
+	pch_can_timing_data.smpl_mode = bt->sample_point;
+	pch_can_timing_data.edge_mode = 0;
+
+	pch_can_get_run_mode(dev_can_os->can,
+				   &curr_mode, ndev);
+	if (curr_mode == PCH_CAN_RUN)
+		pch_can_set_run_mode(dev_can_os->can,
+					   PCH_CAN_STOP, ndev);
+
+	baurate_id = get_baud_id(bt->bitrate);
+	if (baurate_id == -1)
+		retval = pch_can_set_baud_custom(dev_can_os->can,
+							 &pch_can_timing_data);
+	else
+		retval = pch_can_set_baud_simple(dev_can_os->can, baurate_id);
+	if (curr_mode == PCH_CAN_RUN)
+		pch_can_set_run_mode(dev_can_os->can,
+					   PCH_CAN_RUN, ndev);
+
+	return 0;
+}
+
+static int pch_open(struct net_device *ndev)
+{
+	int err;
+	int retval;
+	int ret;
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct pch_can_os *dev_can_os = priv->pch_can_os_p;
+
+	ret = mutex_lock_interruptible(&pch_can_mutex);
+	if (ret)
+		return -ERESTARTSYS;
+
+	retval = pch_can_open(dev_can_os->can,
+			      PCH_CAN_ACTIVE, PCH_CAN_FIXED_PRIORITY, ndev);
+	if (retval != 0) {
+		dev_err(&ndev->dev,
+			"%s -> pch_can_open failed (returned %d).\n",
+			__func__, retval);
+	} else {
+		dev_dbg(&ndev->dev,
+		    "%s -> pch_can_open invoked successfully (returned %d).\n",
+		    __func__, retval);
+
+		dev_can_os->rx_fifo = create_can_fifo(NUM_NODES, ndev);
+
+		if (!(dev_can_os->rx_fifo)) {
+			dev_err(&ndev->dev, "%s -> create_can_fifo failed.\n",
+								__func__);
+
+			pch_can_release(dev_can_os->can, ndev);
+			dev_dbg(&ndev->dev,
+				"%s -> pch_can_release invoked successfully.\n",
+				__func__);
+
+			retval = -EPERM;
+		} else {
+			dev_dbg(&ndev->dev,
+				"%s -> create_can_fifo invoked successfully.\n",
+				__func__);
+
+			/* Registering the callback function for
+						 interrupt handling. */
+			pch_can_entcb(pch_can_callback, dev_can_os, ndev);
+			dev_dbg(&ndev->dev,
+				"%s -> pch_can_entcb invoked successfully.\n",
+				__func__);
+
+			err = pci_enable_msi(dev_can_os->dev);
+			if (err != 0) {
+				priv->have_msi = 0;
+				dev_err(&ndev->dev, "Unable to allocate MSI "
+						"interrupt Error: %d\n", err);
+
+			} else {
+				priv->have_msi = 1;
+			}
+
+			/* Update IRQ value */
+			dev_can_os->irq = dev_can_os->dev->irq;
+			ndev->irq = dev_can_os->dev->irq;
+
+			/* Regsitering the interrupt. */
+			retval =
+			    request_irq(dev_can_os->dev->irq,
+					pch_can_handler, IRQF_SHARED,
+					ndev->name, dev_can_os
+			    );
+
+			if (retval != 0) {
+				pch_can_release(dev_can_os->can, ndev);
+				delete_can_fifo(dev_can_os->rx_fifo, ndev);
+				dev_can_os->rx_fifo = 0;
+				dev_can_os->can_callback = NULL;
+
+				dev_err(&ndev->dev,
+					"%s -> request_irq failed on irq %d"
+					"(returned %d).\n",
+					__func__, dev_can_os->irq, retval);
+			} else {
+				dev_dbg(&ndev->dev, "%s -> request_irq invoked "
+					"successfully(returned %d).\n",
+					__func__, retval);
+
+				/* Assuming that no bus off
+							 interrupt. */
+				dev_can_os->bus_off_interrupt = 0;
+				dev_can_os->write_wait_flag = 0;
+
+				/* Setting the block mode. */
+				dev_can_os->block_mode = 1;
+
+				dev_can_os->opened = 1;
+
+				/* Storing the can structure for further
+								 use. */
+				retval = 0;
+			}
+		}
+	}
+
+	/* Open common can device */
+	err = open_candev(ndev);
+	if (err) {
+		mutex_unlock(&pch_can_mutex);
+		dev_err(ndev->dev.parent, "open_candev() failed %d\n", err);
+		free_irq(ndev->irq, dev_can_os);
+		return err;
+	}
+
+	netif_start_queue(ndev);
+
+	mutex_unlock(&pch_can_mutex);
+	return 0;
+}
+
+static int pch_close(struct net_device *ndev)
+{
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct pch_can_os *can_os = priv->pch_can_os_p;
+
+	netif_stop_queue(ndev);
+	close_candev(ndev);
+	free_irq(ndev->irq, can_os);
+	if (priv->have_msi != 0)
+		pci_disable_msi(can_os->dev);
+
+	delete_can_fifo(can_os->rx_fifo, ndev);
+	pch_can_release(can_os->can, ndev);
+	can_os->opened = 0;
+	can_os->rx_fifo = 0;
+	can_os->can_callback = NULL;
+
+	return 0;
+}
+
+static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	int err;		/* error variable. */
+	int ret;
+	struct pch_can_msg msg;	/* The message object for writing. */
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct pch_can_os *can_os = priv->pch_can_os_p;
+	struct can_frame *canframe_dat = (struct can_frame *)skb->data;
+	struct net_device_stats *stats = &ndev->stats;
+
+	ret = mutex_lock_interruptible(&pch_can_mutex);
+	if (ret)
+		return -ERESTARTSYS;
+
+	/* Translate CAN core format to CAN PCH's HW format */
+	memset(&msg, 0, sizeof(msg));
+	msg.ide = canframe_dat->can_id & 0x80000000;
+	if (canframe_dat->can_id & 0x80000000) {
+		msg.ide = 1;
+		msg.id =  canframe_dat->can_id & 0x1fffffff;/* Extended
+								Message */
+	} else {
+		msg.ide = 0;
+		msg.id =  canframe_dat->can_id & 0x00000fff;/* Standard
+								Message */
+
+	}
+
+	msg.dlc = canframe_dat->can_dlc;
+	memcpy(&msg.data, canframe_dat->data, 8);
+
+	if (canframe_dat->can_id & 0x40000000)
+		msg.rtr = 1;
+	else
+		msg.rtr = 0;
+
+	/* If device suspended. */
+	if ((can_os->is_suspending) == 1) {
+		dev_err(&ndev->dev,
+				"%s -> Device is in suspend mode.\n", __func__);
+		dev_dbg(&ndev->dev, "%s returns %d\n", __func__, -EAGAIN);
+		err = -EAGAIN;
+		goto err_out;
+	}
+
+	can_put_echo_skb(skb, ndev, 0);
+	err = pch_can_msg_tx(can_os->can, &msg, ndev);
+
+	if ((err != 0)) {
+		/* Transmission failed due to unavailability of transmit object
+						 and it is block mode. */
+		if ((err == PCH_CAN_NO_TX_BUFF) && (can_os->block_mode == 1)) {
+			dev_dbg(&ndev->dev, "%s -> Waiting for "
+					"transmit message object.\n", __func__);
+
+			/* Transmitting again. */
+			err = pch_can_msg_tx(can_os->can, &msg, ndev);
+
+			/* If again error. */
+			if (err != 0) {
+				dev_err(&ndev->dev,
+				    "%s -> Transmit failed after 2 attempts.\n",
+				    __func__);
+				dev_dbg(&ndev->dev, "%s returns %d\n",
+							__func__, -EPERM);
+				err = -EPERM;
+				goto err_out;
+			}
+		} else {	/* If failed due to some other reasons. */
+			dev_err(&ndev->dev,
+			    "%s -> Write from CAN device failed %d.\n",
+			    __func__, -EIO);
+			dev_dbg(&ndev->dev, "%s returns %d\n", __func__, -EIO);
+			err = -EIO;
+			goto err_out;
+		}
+	}
+	dev_dbg(&ndev->dev,
+		"%s -> Message send for transmission successfully.\n"
+		"The transmitted Message is :\n"
+		"Msg ID   : 0x%x\n"
+		"EXT ID   : %hu\n"
+		"Msg Size : %hu\n"
+		"Rment    : %hu\n"
+		"Dat Byt1 : 0x%x\n"
+		"Dat Byt2 : 0x%x\n"
+		"Dat Byt3 : 0x%x\n"
+		"Dat Byt4 : 0x%x\n"
+		"Dat Byt5 : 0x%x\n"
+		"Dat Byt6 : 0x%x\n"
+		"Dat Byt7 : 0x%x\n"
+		"Dat Byt8 : 0x%x\n"
+		"Write from CAN device successful ( returns %d).",
+		__func__, msg.id, msg.ide, msg.dlc, msg.rtr, msg.data[0],
+		msg.data[1], msg.data[2], msg.data[3], msg.data[4], msg.data[5],
+		msg.data[6], msg.data[7], sizeof(struct pch_can_msg));
+
+	stats->tx_bytes += canframe_dat->can_dlc;
+	stats->tx_packets++;
+
+	mutex_unlock(&pch_can_mutex);
+	return NETDEV_TX_OK;
+
+err_out:
+	mutex_unlock(&pch_can_mutex);
+	return err;
+}
+
+static const struct net_device_ops pch_can_netdev_ops = {
+	.ndo_open		= pch_open,
+	.ndo_stop		= pch_close,
+	.ndo_start_xmit		= pch_xmit,
+};
+
+static void __devexit pch_can_remove(struct pci_dev *pdev)
+{
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct pch_can_priv *priv = netdev_priv(ndev);
+	struct pch_can_os *can_os = priv->pch_can_os_p;
+
+	unregister_candev(ndev);
+	pch_can_destroy(can_os->can, ndev);
+	pci_iounmap(pdev, (void *)priv->base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	free_candev(priv->ndev);
+	can_free_echo_skb(ndev, 0);
+	platform_set_drvdata(pdev, NULL);
+}
+
+#ifdef CONFIG_PM
+static int pch_can_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int i;			/* Counter variable. */
+	int retval;		/* Return value. */
+/*      struct pch_can_os *can_os = pdev->dev.driver_data; */
+	struct pch_can_os *can_os =
+			(struct pch_can_os *) dev_get_drvdata(&pdev->dev);
+
+	/* If the device is opened get the current run mode. */
+	if (can_os->opened == 1) {
+		/* Save the Run Mode. */
+		pch_can_get_run_mode(can_os->can, &(can_os->run_mode),
+								can_os->ndev);
+	}
+
+	/* Stop the CAN controller */
+	pch_can_set_run_mode(can_os->can, PCH_CAN_STOP, can_os->ndev);
+
+	/* Indicate that we are aboutto/in suspend */
+	can_os->is_suspending = 1;
+
+	if (can_os->opened == 1) {
+		u32 buf_stat;	/* Variable for reading the transmit buffer
+								 status. */
+		u32 counter = 0xFFFFFF;
+
+		/*
+		   Waiting for all transmission to complete.
+		   This is done by checking the TXQST pending
+		    register. The loop teriminates when no
+		    transmission is pending.
+		 */
+		while (counter) {
+			buf_stat = pch_can_get_buffer_status(can_os->can);
+			if (buf_stat == 0)
+				break;
+
+			counter--;
+		}
+
+		if (counter > 0) {
+			dev_dbg(&pdev->dev,
+			    "%s -> No transmission is pending.\n", __func__);
+		} else {
+			dev_err(&pdev->dev,
+				"%s -> Transmission time out.\n", __func__);
+		}
+
+		/* Save interrupt configuration and then disable them */
+		pch_can_get_int_enables(can_os->can,
+					      &(can_os->int_enables));
+		pch_can_set_int_enables(can_os->can, CAN_DISABLE, can_os->ndev);
+
+		/* Save Tx buffer enable state */
+		for (i = 0; i < (pch_can_tx_buf_size + pch_can_rx_buf_size);
+									i++) {
+			if (pch_msg_obj_conf[i] == MSG_OBJ_TX) {
+				/* Here i is the index, however (i+1) is object
+								 number. */
+				pch_can_get_tx_enable(can_os->can,
+							(i + 1),
+							&(can_os->tx_enable[i]),
+							can_os->ndev);
+			}
+		}
+
+		/* Disable all Transmit buffers */
+		pch_can_tx_disable_all(can_os->can, can_os->ndev);
+
+		/* Save Rx buffer enable state */
+		for (i = 0; i < (pch_can_tx_buf_size + pch_can_rx_buf_size);
+									i++) {
+			if (pch_msg_obj_conf[i] == MSG_OBJ_RX) {
+				/* Here i is the index, however (i+1) is object
+								 number. */
+
+				pch_can_get_rx_enable(can_os->can,
+							(i + 1),
+							&(can_os->rx_enable[i]),
+							can_os->ndev);
+				pch_can_get_rx_buffer_link(can_os->can,
+							(i + 1),
+							&(can_os->rx_link[i]),
+							can_os->ndev);
+
+				/* Save Rx Filters */
+				can_os->rx_filter[i].num = (i + 1);
+				pch_can_get_rx_filter(can_os->can,
+							&(can_os->rx_filter[i]),
+							can_os->ndev);
+			}
+		}
+
+		/* Disable all Receive buffers */
+		pch_can_rx_disable_all(can_os->can, can_os->ndev);
+
+		/* Save Context */
+		pch_can_get_baud(can_os->can, &(can_os->timing));
+								/* Timing. */
+		pch_can_get_listen_mode(can_os->can,
+					&(can_os->listen_mode), can_os->ndev);
+							/* Listen mode  */
+		pch_can_get_arbiter_mode(can_os->can,
+					&(can_os->arbiter_mode), can_os->ndev);
+							/* Arbiter mode */
+
+	}
+
+	retval = pci_save_state(pdev);
+
+	if (retval != 0) {
+		/* Indicate that we have not suspended */
+		can_os->is_suspending = 0;
+
+		dev_err(&pdev->dev,
+			"%s -> pci_save_state failed(returned %d).\n",
+			__func__, retval);
+	} else {
+		dev_dbg(&pdev->dev,
+			"%s -> pci_save_state successful(returned %d).\n",
+			__func__, retval);
+
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+		dev_dbg(&pdev->dev,
+		    "%s -> pci_enable_wake invoked successfully.\n", __func__);
+
+		pci_disable_device(pdev);
+		dev_dbg(&pdev->dev,
+		  "%s -> pci_disable_device invoked successfully.\n", __func__);
+
+		pci_set_power_state(pdev, pci_choose_state(pdev, state));
+		dev_dbg(&pdev->dev,
+		 "%s -> pci_set_power_state invoked successfully.\n", __func__);
+	}
+
+	dev_dbg(&pdev->dev, "%s returns %d.\n", __func__, retval);
+	return retval;
+}
+
+static int pch_can_resume(struct pci_dev *pdev)
+{
+	int i;			/* Counter variable. */
+	int retval;		/* Return variable. */
+	struct pch_can_os *can_os =
+			(struct pch_can_os *) dev_get_drvdata(&pdev->dev);
+
+	pci_set_power_state(pdev, PCI_D0);
+	dev_dbg(&pdev->dev,
+	    "pch_can_resume -> pci_set_power_state invoked successfully.\n");
+
+	pci_restore_state(pdev);
+	dev_dbg(&pdev->dev,
+		"pch_can_resume -> pci_restore_state invoked successfully.\n");
+
+	retval = pci_enable_device(pdev);
+	if (retval != 0) {
+		dev_err(&pdev->dev,
+		"pch_can_resume -> pci_enable_device failed(returned %d).\n",
+		retval);
+	}
+
+	else {
+		dev_dbg(&pdev->dev, "pch_can_resume -> pci_enable_device"
+				" invoked successfully(returned %d)\n", retval);
+		pci_enable_wake(pdev, PCI_D3hot, 0);
+
+		/* Disabling all interrupts. */
+		pch_can_set_int_enables(can_os->can, CAN_DISABLE, can_os->ndev);
+
+		/* Setting the CAN device in Stop Mode. */
+		pch_can_set_run_mode(can_os->can, PCH_CAN_STOP, can_os->ndev);
+
+		/* Configuring the transmit and receive buffers. */
+		pch_can_config_rx_tx_buffers(can_os->can, can_os->ndev);
+		dev_dbg(&pdev->dev, "pch_can_resume -> "
+			"pch_can_config_rx_tx_buffers invoked successfully.\n");
+
+		if (can_os->opened == 1) {
+			/* Restore the CAN state */
+			pch_can_set_baud_custom(can_os->can, &(can_os->timing));
+								/* Timing */
+			pch_can_set_listen_mode(
+				can_os->can, can_os->listen_mode, can_os->ndev);
+							/* Listen/Active */
+			pch_can_set_arbiter_mode(can_os->can,
+					can_os->arbiter_mode, can_os->ndev);
+							/* Arbiter mode */
+
+			/* Enabling the transmit buffer. */
+			for (i = 0;
+			     i < (pch_can_tx_buf_size + pch_can_rx_buf_size);
+									i++) {
+				if (pch_msg_obj_conf[i] == MSG_OBJ_TX) {
+					/* Here i is the index, however (i+1) is
+							 object number. */
+					pch_can_set_tx_enable(can_os->can,
+							(i + 1),
+							can_os->tx_enable[i],
+							can_os->ndev);
+				}
+			}
+
+			/* Configuring the receive buffer and enabling them. */
+			for (i = 0;
+			     i < (pch_can_tx_buf_size + pch_can_rx_buf_size);
+									i++) {
+				if (pch_msg_obj_conf[i] == MSG_OBJ_RX) {
+					/* Here i is the index, however (i+1) is
+							 object number. */
+
+					/* Restore buffer link */
+					pch_can_set_rx_buffer_link(can_os->can,
+							(i + 1),
+							can_os->rx_link[i],
+							can_os->ndev);
+
+					/* Restore Rx Filters */
+					can_os->rx_filter[i].num = (i + 1);
+					pch_can_set_rx_filter(can_os->can,
+						       &(can_os->rx_filter[i]));
+
+					/* Restore buffer enables */
+					pch_can_set_rx_enable(can_os->can,
+							(i + 1),
+							can_os->rx_enable[i],
+							can_os->ndev);
+				}
+			}
+
+			/* Enable CAN Interrupts */
+			pch_can_set_int_custom(can_os->can,
+						     can_os->int_enables);
+
+			/* Restore Run Mode */
+			pch_can_set_run_mode(can_os->can,
+						can_os->run_mode, can_os->ndev);
+		}
+		/* if opened */
+		can_os->is_suspending = 0;
+	}			/* else */
+
+	dev_dbg(&pdev->dev, "pch_can_resume returns %d\n", retval);
+	return retval;
+}
+#else
+#define pch_can_suspend NULL
+#define pch_can_resume NULL
+#endif
+
+static int __devinit pch_can_probe(struct pci_dev *pdev,
+				   const struct pci_device_id *id)
+{
+	struct net_device *ndev;
+	struct pch_can_priv *priv;
+	unsigned int can_num = 0;	/* Variable to denote the CAN */
+	int rc;
+	int index;
+
+	ndev = alloc_candev(sizeof(struct pch_can_priv), 1);
+	if (!ndev)
+		return -ENOMEM;
+	SET_NETDEV_DEV(ndev, &pdev->dev);
+
+	priv = netdev_priv(ndev);
+
+	priv->ndev = ndev;
+
+	priv->can.bittiming_const = &pch_can_bittiming_const;
+	priv->can.do_set_bittiming = &pch_set_bittiming;
+	priv->can.do_set_mode = pch_can_do_set_mode;
+	priv->can.do_get_state = pch_can_get_state;
+	priv->can.clock.freq = pch_can_clock * 1000;
+					/* Unit is Hz(pch_can_clock is KHz) */
+	priv->pch_can_os_p = &can_os[can_num];
+	ndev->flags |= (IFF_NOARP | IFF_ECHO);
+	platform_set_drvdata(pdev, ndev);
+	ndev->netdev_ops = &pch_can_netdev_ops;
+	rc = pci_enable_device(pdev);
+	if (rc)
+		goto err_out_free;
+
+	rc = pci_request_regions(pdev, DRIVER_NAME);
+	if (rc)
+		goto err_out_disable;
+
+	can_os[can_num].pci_remap = pci_iomap(pdev, 1, 0);
+	if (can_os[can_num].pci_remap == 0) {
+		rc = -EIO;
+		goto err_out_res;
+	}
+
+	/* Creating the device handle denoting the remap base address. */
+	can_os[can_num].can = pch_can_create((void *)can_os[can_num].pci_remap,
+									ndev);
+
+	/* If handle creation fails. */
+	if (can_os[can_num].can == 0) {
+		dev_err(&pdev->dev,
+			"%s -> pch_can_create failed.\n", __func__);
+		rc = -EPERM;
+		goto err_out_iomap;
+	}
+
+	/* Can number (index to the structure) */
+	can_os[can_num].can_num = can_num;
+	can_os[can_num].irq = pdev->irq;/* IRQ allocated to this device. */
+	ndev->irq = pdev->irq;
+	can_os[can_num].dev = pdev;/* Reference to pci_device structure. */
+	can_os[can_num].opened = 0;/* Open flag denoting the device usage. */
+	can_os[can_num].is_suspending = 0;/* Flag denoting the suspend stage. */
+	can_os[can_num].ndev = ndev;
+
+	priv->base = (void *)can_os[can_num].pci_remap;
+
+	for (index = 0; index < pch_can_rx_buf_size;)
+		pch_msg_obj_conf[index++] = MSG_OBJ_RX;
+
+	for (index = index;
+	     index < (pch_can_rx_buf_size + pch_can_tx_buf_size);)
+		pch_msg_obj_conf[index++] = MSG_OBJ_TX;
+
+	rc = register_candev(ndev);
+	if (rc)
+		goto err_out_reg_candev;
+
+	return 0;
+
+err_out_reg_candev:
+	pch_can_destroy(can_os->can, ndev);
+err_out_iomap:
+	pci_iounmap(pdev, (void *)can_os[can_num].pci_remap);
+err_out_res:
+	pci_release_regions(pdev);
+err_out_disable:
+	pci_disable_device(pdev);
+err_out_free:
+	free_candev(ndev);
+
+	return rc;
+}
+
+static struct pci_driver pch_can_pcidev = {
+	.name = MODULE_NAME,
+	.id_table = pch_can_pcidev_id,
+	.probe = pch_can_probe,
+	.remove = __devexit_p(pch_can_remove),
+	.suspend = pch_can_suspend,
+	.resume = pch_can_resume,
+};
+
+static int __init pch_can_pci_init(void)
+{
+	return pci_register_driver(&pch_can_pcidev);
+}
+
+static void __exit pch_can_pci_exit(void)
+{
+	/* Unregistering the registered PCI Driver. */
+	pci_unregister_driver(&pch_can_pcidev);
+}
+
+MODULE_DESCRIPTION("Controller Area Network Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.94");
+
+module_param_named(pch_can_rx_buf_size, pch_can_rx_buf_size, int, 444);
+module_param_named(pch_can_tx_buf_size, pch_can_tx_buf_size, int, 444);
+module_param_named(pch_can_clock, pch_can_clock, int, 444);
+MODULE_DEVICE_TABLE(pci, pch_can_pcidev_id);
+
+module_init(pch_can_pci_init);
+module_exit(pch_can_pci_exit);
diff --git a/drivers/net/can/pch_can.h b/drivers/net/can/pch_can.h
new file mode 100644
index 0000000..88a9559
--- /dev/null
+++ b/drivers/net/can/pch_can.h
@@ -0,0 +1,435 @@
+/*
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __PCH_CAN_H__
+#define __PCH_CAN_H__
+
+#define MAX_CAN_DEVICES		1
+#define MAX_BITRATE		0x3e8
+#define NUM_NODES		2000	/* Maximum number of
+						 Software FIFO nodes. */
+#define MAX_MSG_OBJ		32
+#define MSG_OBJ_RX		0 /* The receive message object flag. */
+#define MSG_OBJ_TX		1 /* The transmit message object flag. */
+
+#define ENABLE			1 /* The enable flag */
+#define DISABLE			0 /* The disable flag */
+#define CAN_CTRL_INIT		0x0001 /* The INIT bit of CANCONT register. */
+#define CAN_CTRL_IE		0x0002 /* The IE bit of CAN control register */
+#define CAN_CTRL_SIE		0x0004
+#define CAN_CTRL_EIE		0x0008
+#define CAN_CTRL_DAR		0x0020
+#define CAN_CTRL_IE_SIE_EIE	0x000e
+#define CAN_CTRL_CCE		0x0040
+#define CAN_CTRL_OPT		0x0080 /* The OPT bit of CANCONT register. */
+#define CAN_OPT_SILENT		0x0008 /* The Silent bit of CANOPT register. */
+#define CAN_CMASK_RX_TX_SET	0x00f3
+#define CAN_CMASK_RX_TX_GET	0x0073
+#define CAN_CMASK_ALL		0xff
+#define CAN_CMASK_RDWR		0x80
+#define CAN_CMASK_ARB		0x20
+#define CAN_CMASK_CTRL		0x10
+#define CAN_CMASK_MASK		0x40
+#define CAN_CMASK_CLPNT		0x08
+
+#define CAN_CMASK_NEWINT	0x04 /* The TxRqst/NewDat bit for the CMASK
+					register. */
+
+#define CAN_IF_MCONT_NEWDAT	0x8000 /* The NewDat bit of the MCONT
+					  register. */
+
+#define CAN_IF_MCONT_INTPND	0x2000 /* The IntPnd bit of the MCONT
+					  register. */
+
+#define CAN_IF_MCONT_UMASK		0x1000
+#define CAN_IF_MCONT_TXIE		0x0800
+#define CAN_IF_MCONT_RXIE		0x0400
+#define CAN_IF_MCONT_RMTEN		0x0200
+#define CAN_IF_MCONT_TXRQXT		0x0100
+#define CAN_IF_MCONT_EOB		0x0080
+#define CAN_IF_MCONT_MSGLOST		0x4000
+#define CAN_MASK2_MDIR_MXTD		0xc000
+#define CAN_ID2_MSGVAL_XTD_DIR		0xe000
+#define CAN_ID2_MSGVAL_DIR		0xa000
+#define CAN_ID2_DIR			0x2000
+#define CAN_ID_MSGVAL			0x8000
+#define CAN_IF_MASK2_MDIR		((u32)1 << 14)
+#define CAN_IF_MASK2_MXTD		((u32)1 << 15)
+
+#define CAN_STATUS_INT			0x8000 /* The status interrupt value of
+						  the CAN device. */
+
+#define CAN_IF_CREQ_BUSY		0x8000 /* The Busy flag bit of the CREQ
+						  register. */
+
+#define CAN_ID2_XTD			0x4000 /* The Xtd bit of ID2
+						  register. */
+
+#define CAN_SRST_BIT			0x0001
+#define CAN_CONT_OFFSET			0x00	/*Can Control register */
+#define CAN_STAT_OFFSET			0x04
+#define CAN_ERRC_OFFSET			0x08
+#define CAN_BITT_OFFSET			0x0c
+#define CAN_INT_OFFSET			0x010
+#define CAN_OPT_OFFSET			0x14	/*Extended function register */
+#define CAN_BRPE_OFFSET			0x18
+
+/* Message interface one (IF1) registers */
+#define CAN_IF1_CREQ_OFFSET		0x020
+#define CAN_IF1_CMASK_OFFSET		0x024
+#define CAN_IF1_ID1_OFFSET		0x030
+#define CAN_IF1_ID2_OFFSET		0x034
+#define CAN_IF1_MCONT_OFFSET		0x038
+#define CAN_IF1_DATAA1_OFFSET		0x03C
+#define CAN_IF1_DATAA2_OFFSET		0x040
+#define CAN_IF1_DATAB1_OFFSET		0x044
+#define CAN_IF1_DATAB2_OFFSET		0x048
+#define CAN_IF1_MASK1_OFFSET		0x028
+#define CAN_IF1_MASK2_OFFSET		0x02c
+#define CAN_IF2_CREQ_OFFSET		0x080
+#define CAN_IF2_CMASK_OFFSET		0x084
+#define CAN_IF2_ID1_OFFSET		0x090
+#define CAN_IF2_ID2_OFFSET		0x094
+#define CAN_IF2_MCONT_OFFSET		0x098
+#define CAN_IF2_DATAA1_OFFSET		0x09c
+#define CAN_IF2_DATAA2_OFFSET		0x0a0
+#define CAN_IF2_DATAB1_OFFSET		0x0a4
+#define CAN_IF2_DATAB2_OFFSET		0x0a8
+#define CAN_IF2_MASK1_OFFSET		0x088
+#define CAN_IF2_MASK2_OFFSET		0x08c
+#define CAN_TREQ1_OFFSET		0x100
+#define CAN_TREQ2_OFFSET		0x104
+#define CAN_SRST_OFFSET			0x1FC
+#define BIT_SHIFT_ONE			1
+#define BIT_SHIFT_TWO			2
+#define BIT_SHIFT_THREE			3
+#define BIT_SHIFT_FOUR			4
+#define BIT_SHIFT_FIVE			5
+#define BIT_SHIFT_SIX			6
+#define BIT_SHIFT_SEVEN			7
+#define BIT_SHIFT_EIGHT			8
+#define BIT_SHIFT_TWELVE		12
+#define BIT_SHIFT_THIRTEEN		13
+#define BIT_SHIFT_FOURTEEN		14
+#define BIT_SHIFT_FIFTEEN		15
+#define BIT_SHIFT_SIXTEEN		16
+
+/* bit position of certain controller bits. */
+#define BIT_BITT_BRP			0
+#define BIT_BITT_SJW			6
+#define BIT_BITT_TSEG1			8
+#define BIT_BITT_TSEG2			12
+#define BIT_IF1_MCONT_RXIE		10
+#define BIT_IF2_MCONT_TXIE		11
+#define BIT_BRPE_BRPE			6
+#define BIT_ES_TXERRCNT			0
+#define BIT_ES_RXERRCNT			8
+#define MSK_BITT_BRP			0x3f
+#define MSK_BITT_SJW			0xc0
+#define MSK_BITT_TSEG1			0xf00
+#define MSK_BITT_TSEG2			0x7000
+#define MSK_BRPE_BRPE			0x3c0
+#define MSK_BRPE_GET			0x0f
+#define MSK_CTRL_IE_SIE_EIE		0x07
+#define MSK_MCONT_TXIE			0x08
+#define MSK_MCONT_RXIE			0x10
+#define MSK_ALL_THREE			0x07
+#define MSK_ALL_FOUR			0x0f
+#define MSK_ALL_EIGHT			0xff
+#define MSK_ALL_ELEVEN			0x7ff
+#define MSK_ALL_THIRTEEN		0x1fff
+#define MSK_ALL_SIXTEEN			0xffff
+
+/* Error */
+#define MSK_ES_TXERRCNT	((u32)0xff << BIT_ES_TXERRCNT)	/* Tx err count */
+#define MSK_ES_RXERRCNT	((u32)0x7f << BIT_ES_RXERRCNT)	/* Rx err count */
+
+#define PCH_CAN_BIT_SET(reg, bitmask)	\
+		(iowrite32((ioread32((reg)) | ((u32)(bitmask))), (reg)))
+#define PCH_CAN_BIT_CLEAR(reg, bitmask)	\
+		(iowrite32((ioread32((reg)) & ~((u32)(bitmask))), (reg)))
+
+#define PCH_CAN_NO_TX_BUFF		1 /* The flag value for denoting the
+					     unavailability of the transmit
+					     message object. */
+
+#define ERROR_COUNT			96
+#define PCH_CAN_MSG_DATA_LEN		8	/* CAN Msg data length */
+
+#define PCH_CAN_FIFO_NOT_EMPTY		0
+#define PCH_CAN_FIFO_EMPTY		1
+#define PCH_CAN_FIFO_FULL		2
+#define PCH_CAN_NULL			NULL
+
+#define PCI_DEVICE_ID_INTEL_PCH1_CAN	0x8818
+#define DRIVER_NAME			"can"
+
+#define PCH_CAN_CLOCK_DEFAULT_OFFSET	0
+#define PCH_CAN_CLOCK_62_5_OFFSET	0
+#define PCH_CAN_CLOCK_24_OFFSET		8
+#define PCH_CAN_CLOCK_50_OFFSET		16
+
+#define COUNTER_LIMIT 0xFFFF
+
+#define MODULE_NAME "pch_can"
+
+enum pch_can_listen_mode {
+	PCH_CAN_ACTIVE = 0,
+	PCH_CAN_LISTEN
+};
+
+enum pch_can_run_mode {
+	PCH_CAN_STOP = 0,
+	PCH_CAN_RUN
+};
+
+enum pch_can_arbiter {
+	PCH_CAN_ROUND_ROBIN = 0,
+	PCH_CAN_FIXED_PRIORITY
+};
+
+enum pch_can_auto_restart {
+	CAN_MANUAL = 0,
+	CAN_AUTO
+};
+
+enum pch_can_baud {
+	PCH_CAN_BAUD_10 = 0,
+	PCH_CAN_BAUD_20,
+	PCH_CAN_BAUD_50,
+	PCH_CAN_BAUD_125,
+	PCH_CAN_BAUD_250,
+	PCH_CAN_BAUD_500,
+	PCH_CAN_BAUD_800,
+	PCH_CAN_BAUD_1000
+};
+
+enum pch_can_interrupt {
+	CAN_ENABLE,
+	CAN_DISABLE,
+	CAN_ALL,
+	CAN_NONE
+};
+
+/**
+ * struct pch_can_msg - CAN message structure
+ * @ide:	Standard/extended msg
+ * @id:		11 or 29 bit msg id
+ * @dlc:	Size of data
+ * @data:	Message pay load
+ * @rtr:	RTR message
+ */
+struct pch_can_msg {
+	unsigned short ide;
+	unsigned int id;
+	unsigned short dlc;
+	unsigned char data[PCH_CAN_MSG_DATA_LEN];
+	unsigned short rtr;
+};
+
+/**
+ * pch_can_timing - CAN bittiming structure
+ * @bitrate:	Bitrate (kbps)
+ * @cfg_bitrate:	Bitrate
+ * @cfg_tseg1:	Tseg1
+ * @cfg_tseg2:	Tseg2
+ * @cfg_sjw:	Sync jump width
+ * @smpl_mode:	Sampling mode
+ * @edge_mode:	Edge R / D
+ */
+struct pch_can_timing {
+	unsigned int bitrate;
+	unsigned int cfg_bitrate;
+	unsigned int cfg_tseg1;
+	unsigned int cfg_tseg2;
+	unsigned int cfg_sjw;
+	unsigned int smpl_mode;
+	unsigned int edge_mode;
+};
+
+/**
+ * struct pch_can_error - CAN error structure
+ * @rxgte96:	Rx err cnt >=96
+ * @txgte96:	Tx err cnt >=96
+ * @error_stat:	Error state of CAN node,
+ *		00=error active (normal)
+ *		01=error passive
+ *		1x=bus off
+ * @rx_err_cnt:	Rx error count
+ * @tx_err_cnt:	Tx error count
+ */
+struct pch_can_error {
+	unsigned int rxgte96;
+	unsigned int txgte96;
+	unsigned int error_stat;
+	unsigned int rx_err_cnt;
+	unsigned int tx_err_cnt;
+};
+
+/**
+ * struct pch_can_acc_filter - CAN Filter structure
+ * @id:		The id/mask data
+ * @id_ext:	Standard/extended ID
+ * @rtr:	RTR message
+ */
+struct pch_can_acc_filter {
+	unsigned int id;
+	unsigned int id_ext;
+	unsigned int rtr;
+};
+
+/**
+ * struct pch_can_rx_filter - CAN RX filter
+ * @num:	Filter number
+ * @umask:	UMask value
+ * @amr:	Acceptance Mask Reg
+ * @aidr:	Acceptance Control Reg
+ */
+struct pch_can_rx_filter {
+	unsigned int num;
+	unsigned int umask;
+	struct pch_can_acc_filter amr;
+	struct pch_can_acc_filter aidr;
+};
+
+/**
+ * struct pch_can_os - structure to store the CAN device information.
+ * @can:		CAN: device handle
+ * @opened:		Linux opened device
+ * @can_num:		Linux: CAN Number
+ * @pci_remap:		Linux: MMap regs
+ * @dev:		Linux: PCI Device
+ * @irq:		Linux: IRQ
+ * @block_mode:		Blocking / non-blocking
+ * @rx_fifo:		Rx FIFO
+ * @read_wait_queue:	Linux: Read wait queue
+ * @write_wait_queue:	Linux: Write wait queue
+ * @write_wait_flag:	Linux: Write wait flag
+ * @read_wait_flag:	Linux: Read wait flag
+ * @open_spinlock:	Linux: Open lock variable
+ * @is_suspending:	Linux: Is suspending state
+ * @inode:		Linux: inode
+ * @timing:		CAN: timing
+ * @run_mode:		CAN: run mode
+ * @listen_mode:	CAN: listen mode
+ * @arbiter_mode:	CAN: arbiter mode
+ * @tx_enable:		CAN: Tx buffer state
+ * @rx_enable:		CAN: Rx buffer state
+ * @rx_link:		CAN: Rx link set
+ * @int_enables:	CAN: ints enabled
+ * @int_stat:		CAN: int status
+ * @bus_off_interrupt:	CAN: Buss off int flag
+ * @rx_filter:		CAN: Rx filters
+ * @can_callback:	CAN: callback function pointer
+ * @ndev:		net_device pointer
+ * @tx_spinlock:	CAN: transmission lock variable
+ */
+struct pch_can_os {
+	int can;
+	unsigned int opened;
+	unsigned int can_num;
+	void __iomem *pci_remap;
+	struct pci_dev *dev;
+	unsigned int irq;
+	int block_mode;
+	int rx_fifo;
+	wait_queue_head_t read_wait_queue;
+	wait_queue_head_t write_wait_queue;
+	unsigned int write_wait_flag;
+	unsigned int read_wait_flag;
+	spinlock_t open_spinlock;
+	unsigned int is_suspending;
+	struct inode *inode;
+	struct pch_can_timing timing;
+	enum pch_can_run_mode run_mode;
+	enum pch_can_listen_mode listen_mode;
+	enum pch_can_arbiter arbiter_mode;
+	unsigned int tx_enable[MAX_MSG_OBJ];
+	unsigned int rx_enable[MAX_MSG_OBJ];
+	unsigned int rx_link[MAX_MSG_OBJ];
+	unsigned int int_enables;
+	unsigned int int_stat;
+	unsigned int bus_off_interrupt;
+	struct pch_can_rx_filter rx_filter[MAX_MSG_OBJ];
+	void (*can_callback) (struct pch_can_os *);
+	struct net_device *ndev;
+	spinlock_t tx_spinlock;
+};
+
+/**
+ * struct pch_can_priv - CAN driver private data structure
+ * @can:		MUST be first member/field
+ * @ndev:		Pointer to net_device structure
+ * @clk:		unused
+ * @base:		Base address
+ * @scc_ram_offset:	unused
+ * @hecc_ram_offset:	unused
+ * @mbx_offset:		unused
+ * @int_line:		unused
+ * @mbx_lock:		unused
+ * @tx_head:		unused
+ * @tx_tail:		unused
+ * @rx_next:		unused
+ * @pch_can_os_p:	Pointer to CAN device information
+ * @have_msi:		PCI MSI mode flag
+ *
+ * Longer description of this structure.
+ */
+struct pch_can_priv {
+	struct can_priv can;
+	struct net_device *ndev;
+	struct clk *clk;
+	void __iomem *base;
+	u32 scc_ram_offset;
+	u32 hecc_ram_offset;
+	u32 mbx_offset;
+	u32 int_line;
+	spinlock_t mbx_lock;
+	u32 tx_head;
+	u32 tx_tail;
+	u32 rx_next;
+	struct pch_can_os *pch_can_os_p;
+	unsigned int have_msi;
+};
+
+/**
+ * struct can_fifo_item - FIFO Item structure
+ * @msg:	The msg object
+ * @next:	The next pointer
+ */
+struct can_fifo_item {
+	struct pch_can_msg msg;
+	struct can_fifo_item *next;
+};
+
+/**
+ * struct can_fifo - CAN FIFO structure
+ * @head:	The node where insertion can be done
+ * @tail:	The node where reading can be done
+ * @size:	The number of FIFO nodes
+ */
+struct can_fifo {
+	struct can_fifo_item *head;
+	struct can_fifo_item *tail;
+	unsigned int size;
+};
+
+/* This structure defines format for the storage of base address */
+struct can_hw {
+	void __iomem *io_base;
+};
+#endif /* __PCH_CAN_H__ */
-- 1.6.0.6


[-- Attachment #1.2: Type: text/html, Size: 130674 bytes --]

[-- Attachment #2: Type: text/plain, Size: 163 bytes --]

_______________________________________________
MeeGo-dev mailing list
MeeGo-dev-WXzIur8shnEAvxtiuMwx3w@public.gmane.org
http://lists.meego.com/listinfo/meego-dev

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found] ` <4C61EDE5.4030505-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
@ 2010-08-11 10:37   ` Daniel Baluta
  2010-08-12  1:42     ` Wang, Qi
  2010-08-11 12:31   ` Wolfgang Grandegger
  2010-08-11 13:04   ` Marc Kleine-Budde
  2 siblings, 1 reply; 40+ messages in thread
From: Daniel Baluta @ 2010-08-11 10:37 UTC (permalink / raw)
  To: Masayuki Ohtak
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	gregkh-l3A5Bk7waGM, yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	meego-dev-WXzIur8shnEAvxtiuMwx3w, arjan-VuQAYsv1563Yd54FQh9/CA,
	Wolfgang Grandegger

Hi,

2010/8/11 Masayuki Ohtak <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>:
> CAN driver of Topcliff PCH
>
> Topcliff PCH is the platform controller hub that is going to be used in
> Intel's upcoming general embedded platform. All IO peripherals in
> Topcliff PCH are actually devices sitting on AMBA bus.
> Topcliff PCH has CAN I/F. This driver enables CAN function.
>
> Signed-off-by: Masayuki Ohtake <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>

I have a few questions:

1. Is your code based on Intel's CAN EP80579 ([1]) ?
2. Why don't you use kernel existing kfifo infrastructure? ([2]).
3. Can you provide a pointer to Topcliff PCH CAN I/F datasheet ?

thanks,
Daniel.

[1] http://www.intel.com/design/intarch/ep80579/sw_tools.htm
[2] http://lxr.linux.no/#linux+v2.6.35/kernel/kfifo.c

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found] ` <4C61EDE5.4030505-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
  2010-08-11 10:37   ` Daniel Baluta
@ 2010-08-11 12:31   ` Wolfgang Grandegger
       [not found]     ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA26CC@shsmsx501.ccr.corp.intel.com>
  2010-08-11 13:04   ` Marc Kleine-Budde
  2 siblings, 1 reply; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-08-11 12:31 UTC (permalink / raw)
  To: Masayuki Ohtak
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	gregkh-l3A5Bk7waGM, yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	meego-dev-WXzIur8shnEAvxtiuMwx3w, arjan-VuQAYsv1563Yd54FQh9/CA

Hello,

On 08/11/2010 02:25 AM, Masayuki Ohtak wrote:
> CAN driver of Topcliff PCH
> 
> Topcliff PCH is the platform controller hub that is going to be used in
> Intel's upcoming general embedded platform. All IO peripherals in
> Topcliff PCH are actually devices sitting on AMBA bus. 

That's interesting. Where can I/we find more information about this CAN
controller, e.g. data-sheets. It seems to have a few interesting
features (message scheduler, etc.).

> Topcliff PCH has CAN I/F. This driver enables CAN function.
> 
> Signed-off-by: Masayuki Ohtake <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>

Thanks for your contribution. Unfortunately, there are many issues,
especially the driver is not yet conform with the Socket-CAN driver API:

- My first observation was:

  $ wc -l pch_can.c
  4076 pch_can.c
  $ grep dev_dbg pch_can.c | wc -l
  143

  That's a lot of code, mainly debugging code, I think. This needs to
  be cleaned up sooner than later. dev_dbg's should be restricted to a
  few useful for the real users.

- The values for the hw-specific bit-timing registers should be derived
  from the calculated values in "priv->can.bittiming":

  http://lxr.linux.no/#linux+v2.6.35/include/linux/can/netlink.h#L17

- The driver should handle state changes and communicate them to the
  user space via error messages, if possible.

- The driver should report errors to the user space via error messages.

- Bus errors seem not to be handled properly.I'm missing can_bus_off().
  Does the controller recover from bus-off automatically?

- I see that the driver uses many TX and RX objects. How do you avoid
  out-of-order transmission and reception?

- Various CAN controller modes, like listen_only and loopback can be
  handled via "priv->can.ctrlmode". Please use that interface if
  appropriate.

- Please use a structure to describe the register layout, instead of
  defines to profit from type checking.

- As you are at it, please also fix coding style issues, especially for
  comments as described here:

  http://lxr.linux.no/#linux+v2.6.35/Documentation/CodingStyle#L425

You can take the SJA1000 driver as example. Further useful information
is here:

 http://lxr.linux.no/#linux+v2.6.35/Documentation/networking/can.txt
 http://svn.berlios.de/wsvn/socketcan/trunk/README.submitting-patches

It follows a quick review. It's to early for a detailed one:

...

> +/* Array to store the timing settings. */
> +static struct pch_can_timing can_rec_timing[] = {
> +	/* <Baud rate>   <BRP>   <TS1>   <TS2>   <SJW> */
> +	/* settings for 62.5MHz */
> +	{0xa, 0x250, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 10 kbits/s */
> +	{0x14, 0x8D, 0xB, 0x5, 0x0, 0x0, 0x0},	/* < 20 kbits/s */
> +	{0x32, 0x5C, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 50 kbits/s */
> +	{0x7d, 0x18, 0xC, 0x5, 0x0, 0x0, 0x0},	/* < 125 kbits/s */
> +	{0xfa, 0x18, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 250 kbits/s */
> +	{0x1f4, 0x8, 0x9, 0x2, 0x0, 0x0, 0x0},	/* < 500 kbits/s */
> +	{0x320, 0x5, 0x8, 0x2, 0x0, 0x0, 0x0},	/* < 800 kbits/s  */
> +	{0x3e8, 0x2, 0xC, 0x6, 0x0, 0x0, 0x0},	/* < 1000 kbits/s */
> +
> +	/* settings for 24MHz */
> +	{0xa, 0xCF, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 10 kbits/s */
> +	{0x14, 0x57, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 20 kbits/s */
> +	{0x32, 0xF, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 50 kbits/s */
> +	{0x7d, 0xF, 0x8, 0x1, 0x0, 0x0, 0x0},	/* < 125 kbits/s */
> +	{0xfa, 0x7, 0x8, 0x1, 0x0, 0x0, 0x0},	/* < 250 kbits/s */
> +	{0x1f4, 0x3, 0x8, 0x1, 0x0, 0x0, 0x0},	/* < 500 kbits/s */
> +	{0x320, 0x2, 0x7, 0x0, 0x0, 0x0, 0x0},	/* < 800 kbits/s  */
> +	{0x3e8, 0x1, 0x8, 0x1, 0x0, 0x0, 0x0},	/* < 1000 kbits/s */
> +
> +	/* settings for 50MHz */
> +	{0xa, 0xFA, 0xC, 0x5, 0x1, 0x0, 0x0},	/* < 10 kbits/s */
> +	{0x14, 0x7D, 0xC, 0x5, 0x1, 0x0, 0x0},	/* < 20 kbits/s */
> +	{0x32, 0x32, 0xF, 0x2, 0x0, 0x0, 0x0},	/* < 50 kbits/s */
> +	{0x7d, 0x19, 0xC, 0x1, 0x0, 0x0, 0x0},	/* < 125 kbits/s */
> +	{0xfa, 0xA, 0xF, 0x2, 0x0, 0x0, 0x0},	/* < 250 kbits/s */
> +	{0x1f4, 0x5, 0xF, 0x2, 0x0, 0x0, 0x0},	/* < 500 kbits/s */
> +	{0x320, 0x5, 0x8, 0x2, 0x1, 0x0, 0x0},	/* < 800 kbits/s  */
> +	{0x3e8, 0x2, 0xF, 0x7, 0x0, 0x0, 0x0}	/* < 1000 kbits/s */
> +	/* Add the new clock settings here. */
> +};

Can't the register values be determined from the calculated one in
"priv->can.bittiming"? See comment above. Be aware the the user might
want to set custom values as described here:

http://lxr.linux.no/#linux+v2.6.35/Documentation/networking/can.txt#L730

> +
> +static DEFINE_MUTEX(pch_can_mutex);

What is this mutex good for. At a first glance, I don't think it's needed.

> +
> +#ifdef PCH_CAN_FIFO_MODE

The functions above are not used anywhere! Dead code? Please clean up.

> +static int check_can_fifo_status(int handle)
> +{
> +	int ret_val;
> +	struct can_fifo *f = (struct can_fifo *) handle;
> +
> +	if (f->head == f->tail)
> +		ret_val = PCH_CAN_FIFO_EMPTY;
> +	else if (f->head->next == f->tail)
> +		ret_val = PCH_CAN_FIFO_FULL;
> +	else
> +		ret_val = PCH_CAN_FIFO_NOT_EMPTY;
> +
> +	return ret_val;
> +}
> +

...

> +static netdev_tx_t pch_xmit(struct sk_buff *skb, struct net_device *ndev)
> +{
> +	int err;		/* error variable. */
> +	int ret;
> +	struct pch_can_msg msg;	/* The message object for writing. */
> +	struct pch_can_priv *priv = netdev_priv(ndev);
> +	struct pch_can_os *can_os = priv->pch_can_os_p;
> +	struct can_frame *canframe_dat = (struct can_frame *)skb->data;
> +	struct net_device_stats *stats = &ndev->stats;
> +
> +	ret = mutex_lock_interruptible(&pch_can_mutex);
> +	if (ret)
> +		return -ERESTARTSYS;


This is an invalid return code.

> +
> +	/* Translate CAN core format to CAN PCH's HW format */
> +	memset(&msg, 0, sizeof(msg));
> +	msg.ide = canframe_dat->can_id & 0x80000000;
> +	if (canframe_dat->can_id & 0x80000000) {
> +		msg.ide = 1;
> +		msg.id =  canframe_dat->can_id & 0x1fffffff;/* Extended
> +								Message */
> +	} else {
> +		msg.ide = 0;
> +		msg.id =  canframe_dat->can_id & 0x00000fff;/* Standard
> +								Message */
> +
> +	}
> +
> +	msg.dlc = canframe_dat->can_dlc;
> +	memcpy(&msg.data, canframe_dat->data, 8);
> +
> +	if (canframe_dat->can_id & 0x40000000)
> +		msg.rtr = 1;
> +	else
> +		msg.rtr = 0;
> +
> +	/* If device suspended. */
> +	if ((can_os->is_suspending) == 1) {
> +		dev_err(&ndev->dev,
> +				"%s -> Device is in suspend mode.\n", __func__);
> +		dev_dbg(&ndev->dev, "%s returns %d\n", __func__, -EAGAIN);
> +		err = -EAGAIN;
> +		goto err_out;
> +	}
> +
> +	can_put_echo_skb(skb, ndev, 0);

This will not work, as you are using more than one TX object.



> +MODULE_DESCRIPTION("Controller Area Network Driver");
> +MODULE_LICENSE("GPL");
> +MODULE_VERSION("0.94");

> +module_param_named(pch_can_rx_buf_size, pch_can_rx_buf_size, int, 444);
> +module_param_named(pch_can_tx_buf_size, pch_can_tx_buf_size, int, 444);
> +module_param_named(pch_can_clock, pch_can_clock, int, 444);
> +MODULE_DEVICE_TABLE(pci, pch_can_pcidev_id);

Please move these calls up to the beginning where the variables are
defined and provide a proper description.

> +
> +module_init(pch_can_pci_init);
> +module_exit(pch_can_pci_exit);
> diff --git a/drivers/net/can/pch_can.h b/drivers/net/can/pch_can.h
> new file mode 100644
> index 0000000..88a9559
> --- /dev/null
> +++ b/drivers/net/can/pch_can.h

...

> +/**
> + * struct pch_can_msg - CAN message structure
> + * @ide:	Standard/extended msg
> + * @id:		11 or 29 bit msg id
> + * @dlc:	Size of data
> + * @data:	Message pay load
> + * @rtr:	RTR message
> + */
> +struct pch_can_msg {
> +	unsigned short ide;
> +	unsigned int id;
> +	unsigned short dlc;
> +	unsigned char data[PCH_CAN_MSG_DATA_LEN];
> +	unsigned short rtr;
> +};

Hm, why you can't use "struct can_frame".

> +
> +/**
> + * pch_can_timing - CAN bittiming structure
> + * @bitrate:	Bitrate (kbps)
> + * @cfg_bitrate:	Bitrate
> + * @cfg_tseg1:	Tseg1
> + * @cfg_tseg2:	Tseg2
> + * @cfg_sjw:	Sync jump width
> + * @smpl_mode:	Sampling mode
> + * @edge_mode:	Edge R / D
> + */
> +struct pch_can_timing {
> +	unsigned int bitrate;
> +	unsigned int cfg_bitrate;
> +	unsigned int cfg_tseg1;
> +	unsigned int cfg_tseg2;
> +	unsigned int cfg_sjw;
> +	unsigned int smpl_mode;
> +	unsigned int edge_mode;
> +};

Ditto.

> +/**
> + * struct pch_can_error - CAN error structure
> + * @rxgte96:	Rx err cnt >=96
> + * @txgte96:	Tx err cnt >=96
> + * @error_stat:	Error state of CAN node,
> + *		00=error active (normal)
> + *		01=error passive
> + *		1x=bus off
> + * @rx_err_cnt:	Rx error count
> + * @tx_err_cnt:	Tx error count
> + */
> +struct pch_can_error {
> +	unsigned int rxgte96;
> +	unsigned int txgte96;
> +	unsigned int error_stat;
> +	unsigned int rx_err_cnt;
> +	unsigned int tx_err_cnt;
> +};
> +
> +/**
> + * struct pch_can_acc_filter - CAN Filter structure
> + * @id:		The id/mask data
> + * @id_ext:	Standard/extended ID
> + * @rtr:	RTR message
> + */
> +struct pch_can_acc_filter {
> +	unsigned int id;
> +	unsigned int id_ext;
> +	unsigned int rtr;
> +};
> +
> +/**
> + * struct pch_can_rx_filter - CAN RX filter
> + * @num:	Filter number
> + * @umask:	UMask value
> + * @amr:	Acceptance Mask Reg
> + * @aidr:	Acceptance Control Reg
> + */
> +struct pch_can_rx_filter {
> +	unsigned int num;
> +	unsigned int umask;
> +	struct pch_can_acc_filter amr;
> +	struct pch_can_acc_filter aidr;
> +};
> +
> +/**
> + * struct pch_can_os - structure to store the CAN device information.
> + * @can:		CAN: device handle
> + * @opened:		Linux opened device
> + * @can_num:		Linux: CAN Number
> + * @pci_remap:		Linux: MMap regs
> + * @dev:		Linux: PCI Device
> + * @irq:		Linux: IRQ
> + * @block_mode:		Blocking / non-blocking
> + * @rx_fifo:		Rx FIFO
> + * @read_wait_queue:	Linux: Read wait queue
> + * @write_wait_queue:	Linux: Write wait queue
> + * @write_wait_flag:	Linux: Write wait flag
> + * @read_wait_flag:	Linux: Read wait flag
> + * @open_spinlock:	Linux: Open lock variable
> + * @is_suspending:	Linux: Is suspending state
> + * @inode:		Linux: inode
> + * @timing:		CAN: timing
> + * @run_mode:		CAN: run mode
> + * @listen_mode:	CAN: listen mode
> + * @arbiter_mode:	CAN: arbiter mode
> + * @tx_enable:		CAN: Tx buffer state
> + * @rx_enable:		CAN: Rx buffer state
> + * @rx_link:		CAN: Rx link set
> + * @int_enables:	CAN: ints enabled
> + * @int_stat:		CAN: int status
> + * @bus_off_interrupt:	CAN: Buss off int flag
> + * @rx_filter:		CAN: Rx filters
> + * @can_callback:	CAN: callback function pointer
> + * @ndev:		net_device pointer
> + * @tx_spinlock:	CAN: transmission lock variable
> + */
> +struct pch_can_os {
> +	int can;
> +	unsigned int opened;
> +	unsigned int can_num;
> +	void __iomem *pci_remap;
> +	struct pci_dev *dev;
> +	unsigned int irq;
> +	int block_mode;
> +	int rx_fifo;
> +	wait_queue_head_t read_wait_queue;
> +	wait_queue_head_t write_wait_queue;
> +	unsigned int write_wait_flag;
> +	unsigned int read_wait_flag;
> +	spinlock_t open_spinlock;
> +	unsigned int is_suspending;
> +	struct inode *inode;
> +	struct pch_can_timing timing;
> +	enum pch_can_run_mode run_mode;
> +	enum pch_can_listen_mode listen_mode;
> +	enum pch_can_arbiter arbiter_mode;
> +	unsigned int tx_enable[MAX_MSG_OBJ];
> +	unsigned int rx_enable[MAX_MSG_OBJ];
> +	unsigned int rx_link[MAX_MSG_OBJ];
> +	unsigned int int_enables;
> +	unsigned int int_stat;
> +	unsigned int bus_off_interrupt;
> +	struct pch_can_rx_filter rx_filter[MAX_MSG_OBJ];
> +	void (*can_callback) (struct pch_can_os *);
> +	struct net_device *ndev;
> +	spinlock_t tx_spinlock;
> +};
> +
> +/**
> + * struct pch_can_priv - CAN driver private data structure
> + * @can:		MUST be first member/field
> + * @ndev:		Pointer to net_device structure
> + * @clk:		unused
> + * @base:		Base address
> + * @scc_ram_offset:	unused
> + * @hecc_ram_offset:	unused
> + * @mbx_offset:		unused
> + * @int_line:		unused
> + * @mbx_lock:		unused
> + * @tx_head:		unused
> + * @tx_tail:		unused
> + * @rx_next:		unused

Hm, if it's not used, what is it then good for? I stop reviewing here.
It seems that you ported an existing driver to Linux!? I'm looking
forward for an optimized and efficient solution.

Thanks,

Wolfgang.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found] ` <4C61EDE5.4030505-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
  2010-08-11 10:37   ` Daniel Baluta
  2010-08-11 12:31   ` Wolfgang Grandegger
@ 2010-08-11 13:04   ` Marc Kleine-Budde
  2010-09-13 12:07     ` Masayuki Ohtake
  2 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2010-08-11 13:04 UTC (permalink / raw)
  To: Masayuki Ohtak
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	gregkh-l3A5Bk7waGM, yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	meego-dev-WXzIur8shnEAvxtiuMwx3w, arjan-VuQAYsv1563Yd54FQh9/CA,
	Wolfgang Grandegger


[-- Attachment #1.1: Type: text/plain, Size: 2538 bytes --]

Masayuki Ohtak wrote:
> CAN driver of Topcliff PCH
> 
> Topcliff PCH is the platform controller hub that is going to be used in
> Intel's upcoming general embedded platform. All IO peripherals in
> Topcliff PCH are actually devices sitting on AMBA bus. 
> Topcliff PCH has CAN I/F. This driver enables CAN function.

Thanks for your contribution. Some remarks in addition to Wolfgang's.

- Try to send patches directly with git send-email
- Rebase your tree to net-next-2.6.
- don't use global variables
- don't use that "int handle", e.g.:

> static int pch_can_msg_tx(int handle, struct pch_can_msg *msg,
> 			  struct net_device *ndev)
> {
> 	u32 id1 = 0;
> 	u32 id2 = 0;
> 	u32 data_a1 = 0;
> 	u32 data_a2 = 0;
> 	u32 data_b1 = 0;
> 	u32 data_b2 = 0;
> 	u32 tx_disable_counter = 0;
> 	u32 buffer_status = 0;
> 	u32 tx_buffer_avail = 0;
> 	u32 status;
> 	u32 i;
> 	u32 counter;
> 	enum pch_can_run_mode run_mode;
> 	int retval = 0;
> 	u32 if1_creq;
> 
> 	if ((handle == 0) || (msg == NULL)) {
> 		dev_err(&ndev->dev, "%s -> Invalid Parameter.\n", __func__);
> 		retval = -EPERM;
> 	}
> 
> 	else {
> 		/* Obatining the remap address for access. */
> 		struct can_hw *can = (struct can_hw *) handle;
> 

use a proper struct. There are numerous drawbacks, no type safety it's
not 64 safe, bad style,...

- there are several checks for handle against 0 that make no real sense

- clean up you error paths:

if (error) {
	/* error handling */
} else {
	/* do real work */
}

This leads to a big indention level in the interesting code path, making
it very hard to read. Please rework your code this way:

if (error) {
	/* error handling */
	return error;
	/* or */
	goto out_handle_error;
}

/* do real work */

- get rid of the intermediate struct pch_can_msg:
  Your data path is:
  struct can_frame -> struct pch_can_msg -> registers
  write from struct can_frame into registers directly

- what's the purpose of "p_can_os->can_callback", call the function
  directly from the interrupt handler

- implement NAPI

- get rid of "1 << BIT_SHIFT_SIX" and friend,
  use "1 << 6" or "BIT(6)" if you like defines

- use defines to set bits in struct can_frame can_id

cheers, Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 260 bytes --]

[-- Attachment #2: Type: text/plain, Size: 188 bytes --]

_______________________________________________
Socketcan-core mailing list
Socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org
https://lists.berlios.de/mailman/listinfo/socketcan-core

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-08-11 10:37   ` Daniel Baluta
@ 2010-08-12  1:42     ` Wang, Qi
  2010-08-12  2:04       ` Greg KH
                         ` (2 more replies)
  0 siblings, 3 replies; 40+ messages in thread
From: Wang, Qi @ 2010-08-12  1:42 UTC (permalink / raw)
  To: Daniel Baluta, Masayuki Ohtak
  Cc: meego-dev, Wolfgang Grandegger, socketcan-core, netdev, Khor,
	Andrew Chih Howe, gregkh, arjan, Wang, Yong Y

> -----Original Message-----
> From: Daniel Baluta [mailto:daniel.baluta@gmail.com]
> Sent: Wednesday, August 11, 2010 6:37 PM
> To: Masayuki Ohtak
> Cc: meego-dev@meego.com; Wolfgang Grandegger;
> socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew Chih
> Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Qi; Wang, Yong Y
> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> 
> Hi,
> 
> 2010/8/11 Masayuki Ohtak <masa-korg@dsn.okisemi.com>:
> > CAN driver of Topcliff PCH
> >
> > Topcliff PCH is the platform controller hub that is going to be used in
> > Intel's upcoming general embedded platform. All IO peripherals in
> > Topcliff PCH are actually devices sitting on AMBA bus.
> > Topcliff PCH has CAN I/F. This driver enables CAN function.
> >
> > Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> 
> I have a few questions:
> 
> 1. Is your code based on Intel's CAN EP80579 ([1]) ?
No.
> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
Just take a look at kfifo.h. This structure has been changed. I remembered there was a spin_lock from kfifo previously. Currently it's been removed, good.
OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to use this structure and APIs?

Daniel,

We're anxious to integrate those codes now. Perhaps it'll take us quite a long time to use kfifo. How about implementing it with the next version?

Best Regards,
Qi.

> 3. Can you provide a pointer to Topcliff PCH CAN I/F datasheet ?
Currently this datasheet isn't open.
> 
> thanks,
> Daniel.
> 
> [1] http://www.intel.com/design/intarch/ep80579/sw_tools.htm
> [2] http://lxr.linux.no/#linux+v2.6.35/kernel/kfifo.c

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-08-12  1:42     ` Wang, Qi
@ 2010-08-12  2:04       ` Greg KH
  2010-08-12  2:13         ` Wang, Qi
       [not found]         ` <20100812020414.GD14121-l3A5Bk7waGM@public.gmane.org>
  2010-08-12  2:39       ` Masayuki Ohtake
       [not found]       ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA26EB-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2 siblings, 2 replies; 40+ messages in thread
From: Greg KH @ 2010-08-12  2:04 UTC (permalink / raw)
  To: Wang, Qi
  Cc: Daniel Baluta, Masayuki Ohtak, meego-dev, Wolfgang Grandegger,
	socketcan-core, netdev, Khor, Andrew Chih Howe, arjan, Wang,
	Yong Y

On Thu, Aug 12, 2010 at 09:42:27AM +0800, Wang, Qi wrote:
> > -----Original Message-----
> > From: Daniel Baluta [mailto:daniel.baluta@gmail.com]
> > Sent: Wednesday, August 11, 2010 6:37 PM
> > To: Masayuki Ohtak
> > Cc: meego-dev@meego.com; Wolfgang Grandegger;
> > socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew Chih
> > Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Qi; Wang, Yong Y
> > Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> > 
> > Hi,
> > 
> > 2010/8/11 Masayuki Ohtak <masa-korg@dsn.okisemi.com>:
> > > CAN driver of Topcliff PCH
> > >
> > > Topcliff PCH is the platform controller hub that is going to be used in
> > > Intel's upcoming general embedded platform. All IO peripherals in
> > > Topcliff PCH are actually devices sitting on AMBA bus.
> > > Topcliff PCH has CAN I/F. This driver enables CAN function.
> > >
> > > Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> > 
> > I have a few questions:
> > 
> > 1. Is your code based on Intel's CAN EP80579 ([1]) ?
> No.
> > 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> Just take a look at kfifo.h. This structure has been changed. I
> remembered there was a spin_lock from kfifo previously. Currently it's
> been removed, good.
> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to use this structure and APIs?
> 
> Daniel,
> 
> We're anxious to integrate those codes now. Perhaps it'll take us
> quite a long time to use kfifo. How about implementing it with the
> next version?

What do you mean by this?  Code isn't merged into the tree unless it is
correct.  Please fix this now, it's not that big of a deal.

> > 3. Can you provide a pointer to Topcliff PCH CAN I/F datasheet ?
> Currently this datasheet isn't open.

Even under NDA?  The Linux foundation offers a service to allow
developers access to data sheets so that they can do kernel development
and code review.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-08-12  2:04       ` Greg KH
@ 2010-08-12  2:13         ` Wang, Qi
       [not found]         ` <20100812020414.GD14121-l3A5Bk7waGM@public.gmane.org>
  1 sibling, 0 replies; 40+ messages in thread
From: Wang, Qi @ 2010-08-12  2:13 UTC (permalink / raw)
  To: Khor, Andrew Chih Howe, Masayuki Ohtak
  Cc: Daniel Baluta, meego-dev, Wolfgang Grandegger, socketcan-core,
	netdev, arjan, Wang, Yong Y, Greg KH

> -----Original Message-----
> From: Greg KH [mailto:gregkh@suse.de]
> Sent: Thursday, August 12, 2010 10:04 AM
> To: Wang, Qi
> Cc: Daniel Baluta; Masayuki Ohtak; meego-dev@meego.com; Wolfgang
> Grandegger; socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor,
> Andrew Chih Howe; arjan@linux.intel.com; Wang, Yong Y
> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> 
> On Thu, Aug 12, 2010 at 09:42:27AM +0800, Wang, Qi wrote:
> > > -----Original Message-----
> > > From: Daniel Baluta [mailto:daniel.baluta@gmail.com]
> > > Sent: Wednesday, August 11, 2010 6:37 PM
> > > To: Masayuki Ohtak
> > > Cc: meego-dev@meego.com; Wolfgang Grandegger;
> > > socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew
> Chih
> > > Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Qi; Wang, Yong Y
> > > Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to
> 2.6.35
> > >
> > > Hi,
> > >
> > > 2010/8/11 Masayuki Ohtak <masa-korg@dsn.okisemi.com>:
> > > > CAN driver of Topcliff PCH
> > > >
> > > > Topcliff PCH is the platform controller hub that is going to be used in
> > > > Intel's upcoming general embedded platform. All IO peripherals in
> > > > Topcliff PCH are actually devices sitting on AMBA bus.
> > > > Topcliff PCH has CAN I/F. This driver enables CAN function.
> > > >
> > > > Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> > >
> > > I have a few questions:
> > >
> > > 1. Is your code based on Intel's CAN EP80579 ([1]) ?
> > No.
> > > 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> > Just take a look at kfifo.h. This structure has been changed. I
> > remembered there was a spin_lock from kfifo previously. Currently it's
> > been removed, good.
> > OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to
> use this structure and APIs?
> >
> > Daniel,
> >
> > We're anxious to integrate those codes now. Perhaps it'll take us
> > quite a long time to use kfifo. How about implementing it with the
> > next version?
> 
> What do you mean by this?  Code isn't merged into the tree unless it is
> correct.  Please fix this now, it's not that big of a deal.

Hi Ohtak-san,

Would you please use kfifo structure? It'll take you some time to study it, but it's a good structure.
> 
> > > 3. Can you provide a pointer to Topcliff PCH CAN I/F datasheet ?
> > Currently this datasheet isn't open.
> 
> Even under NDA?  The Linux foundation offers a service to allow
> developers access to data sheets so that they can do kernel development
> and code review.
Hi Andrew,

Can ECG share those datasheet to the open source? Only with that datasheet, the upstream can review the source codes from OKI.

Best Regards,
Qi

> 
> thanks,
> 
> greg k-h

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-08-12  1:42     ` Wang, Qi
  2010-08-12  2:04       ` Greg KH
@ 2010-08-12  2:39       ` Masayuki Ohtake
       [not found]       ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA26EB-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2 siblings, 0 replies; 40+ messages in thread
From: Masayuki Ohtake @ 2010-08-12  2:39 UTC (permalink / raw)
  To: Daniel Baluta, Wang, Qi
  Cc: Wang, Yong Y, arjan, gregkh, Khor, Andrew Chih Howe, netdev,
	socketcan-core, Wolfgang Grandegger, meego-dev

Hi Qi-san

> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to use this structure and APIs?

Thank you for your answer.
We will start doing the above next week.

Thanks, Ohtake
----- Original Message ----- 
From: "Wang, Qi" <qi.wang@intel.com>
To: "Daniel Baluta" <daniel.baluta@gmail.com>; "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: <meego-dev@meego.com>; "Wolfgang Grandegger" <wg@grandegger.com>; <socketcan-core@lists.berlios.de>;
<netdev@vger.kernel.org>; "Khor, Andrew Chih Howe" <andrew.chih.howe.khor@intel.com>; <gregkh@suse.de>;
<arjan@linux.intel.com>; "Wang, Yong Y" <yong.y.wang@intel.com>
Sent: Thursday, August 12, 2010 10:42 AM
Subject: RE: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35


> > -----Original Message-----
> > From: Daniel Baluta [mailto:daniel.baluta@gmail.com]
> > Sent: Wednesday, August 11, 2010 6:37 PM
> > To: Masayuki Ohtak
> > Cc: meego-dev@meego.com; Wolfgang Grandegger;
> > socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew Chih
> > Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Qi; Wang, Yong Y
> > Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> >
> > Hi,
> >
> > 2010/8/11 Masayuki Ohtak <masa-korg@dsn.okisemi.com>:
> > > CAN driver of Topcliff PCH
> > >
> > > Topcliff PCH is the platform controller hub that is going to be used in
> > > Intel's upcoming general embedded platform. All IO peripherals in
> > > Topcliff PCH are actually devices sitting on AMBA bus.
> > > Topcliff PCH has CAN I/F. This driver enables CAN function.
> > >
> > > Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> >
> > I have a few questions:
> >
> > 1. Is your code based on Intel's CAN EP80579 ([1]) ?
> No.
> > 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> Just take a look at kfifo.h. This structure has been changed. I remembered there was a spin_lock from kfifo
previously. Currently it's been removed, good.
> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to use this structure and APIs?
>
> Daniel,
>
> We're anxious to integrate those codes now. Perhaps it'll take us quite a long time to use kfifo. How about
implementing it with the next version?
>
> Best Regards,
> Qi.
>
> > 3. Can you provide a pointer to Topcliff PCH CAN I/F datasheet ?
> Currently this datasheet isn't open.
> >
> > thanks,
> > Daniel.
> >
> > [1] http://www.intel.com/design/intarch/ep80579/sw_tools.htm
> > [2] http://lxr.linux.no/#linux+v2.6.35/kernel/kfifo.c
>



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]       ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA26EB-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2010-08-12  5:17         ` Daniel Baluta
  2010-08-12  9:03         ` Wolfgang Grandegger
  1 sibling, 0 replies; 40+ messages in thread
From: Daniel Baluta @ 2010-08-12  5:17 UTC (permalink / raw)
  To: Wang, Qi
  Cc: Khor, Andrew Chih Howe, socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, gregkh-l3A5Bk7waGM, Wang, Yong Y,
	Masayuki Ohtak, meego-dev-WXzIur8shnEAvxtiuMwx3w,
	arjan-VuQAYsv1563Yd54FQh9/CA, Wolfgang Grandegger

>> 1. Is your code based on Intel's CAN EP80579 ([1]) ?
> No.

I want in the near future to write a Socket-CAN based driver for CAN EP80579.
As far as I've seen from your implementation there are a lot of
similarities between these
two drivers. Perhaps we can built a core part to both benefit from it.

>> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> Just take a look at kfifo.h. This structure has been changed. I remembered there was a spin_lock from kfifo previously. Currently it's been removed, good.
Inded, the kfifo infrastructure has suffered great reworkings in the
latest kernel versions, but this
is not an excuse to not use it.
> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to use this structure and APIs?
>
> Daniel,
>
> We're anxious to integrate those codes now. Perhaps it'll take us quite a long time to use kfifo. How about implementing it with the next version?

In my opinion, as it looks now your code will never be accepted by the
SocketCAN maintainers.

thanks,
Daniel.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]         ` <20100812020414.GD14121-l3A5Bk7waGM@public.gmane.org>
@ 2010-08-12  6:25           ` Oliver Hartkopp
  2010-08-12  6:29             ` Wang, Qi
  0 siblings, 1 reply; 40+ messages in thread
From: Oliver Hartkopp @ 2010-08-12  6:25 UTC (permalink / raw)
  To: Wang, Qi
  Cc: Khor, Andrew Chih Howe, socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, Greg KH, Wang, Yong Y,
	Masayuki Ohtak, meego-dev-WXzIur8shnEAvxtiuMwx3w,
	arjan-VuQAYsv1563Yd54FQh9/CA, Wolfgang Grandegger

On 12.08.2010 04:04, Greg KH wrote:
> On Thu, Aug 12, 2010 at 09:42:27AM +0800, Wang, Qi wrote:

>>> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
>> Just take a look at kfifo.h. This structure has been changed. I
>> remembered there was a spin_lock from kfifo previously. Currently it's
>> been removed, good.
>> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to use this structure and APIs?
>>
>> Daniel,
>>
>> We're anxious to integrate those codes now. Perhaps it'll take us
>> quite a long time to use kfifo. How about implementing it with the
>> next version?
> 
> What do you mean by this?  Code isn't merged into the tree unless it is
> correct.  Please fix this now, it's not that big of a deal.
> 

Hello Qi,

i generally wonder what this FIFO is used for??

For me it looks like a artifact from a former chardev implementation, as
several other code sniplets do (see comments from Wolfgang and Marc).

The network driver model is used for CAN drivers and therefore all the
infrastructure for queueing inbound and outbound network traffic should be
used from the Kernel like all other CAN drivers and all other ethernet drivers do.

Additionally there is a powerful infrastructure to support the special
functions of CAN netdevices (like setting of bittimings, listen-only modes, or
to produce CAN driver states etc.), that's part of the CAN drivers in
drivers/net/can/ since it has gone mainline.

CAN netdevices are intentionally dumb (like the original ethernet adapters).
This allows a simple driver interface between the kernel and the hardware
driver, e.g. for queueing CAN frames. CAN drivers don't use any hardware
rx-filtering(!) due to multiuser requirements and it's a vital requirement
that the frames are not re-ordered on sending (by the 'some magic' CAN
controller dealing with CAN-ID priorities, e.g. see tx-path in the MSCAN driver).

>From my perspective about 70% of your code is obsolete, as you implemented
tricky details (like FIFOs, bittiming tables or magic filter handlings),
that's not needed at all.

Please take a look at the SJA1000 driver (for a low complex CAN controller) or
at the TI driver (for a higher complex CAN controller) how these drivers
handle the specialties of each hardware. And read some documentation in
Documentation/networking/can.txt to get an impression about the concepts of
the CAN implementation in the Linux Kernel and the CAN netdevices.

I strongly assume that your driver would be about 30 kBytes of code fitting
into a single c-file like the ti_hecc.c does. And that's definitely easier for
us to review and easier for you to maintain in the future ...

Thanks & best regards,
Oliver

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-08-12  6:25           ` Oliver Hartkopp
@ 2010-08-12  6:29             ` Wang, Qi
  0 siblings, 0 replies; 40+ messages in thread
From: Wang, Qi @ 2010-08-12  6:29 UTC (permalink / raw)
  To: Oliver Hartkopp
  Cc: Greg KH, Daniel Baluta, Masayuki Ohtak, meego-dev,
	Wolfgang Grandegger, socketcan-core, netdev, Khor,
	Andrew Chih Howe, arjan, Wang, Yong Y

> -----Original Message-----
> From: Oliver Hartkopp [mailto:socketcan@hartkopp.net]
> Sent: Thursday, August 12, 2010 2:26 PM
> To: Wang, Qi
> Cc: Greg KH; Daniel Baluta; Masayuki Ohtak; meego-dev@meego.com;
> Wolfgang Grandegger; socketcan-core@lists.berlios.de;
> netdev@vger.kernel.org; Khor, Andrew Chih Howe; arjan@linux.intel.com;
> Wang, Yong Y
> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> 
> On 12.08.2010 04:04, Greg KH wrote:
> > On Thu, Aug 12, 2010 at 09:42:27AM +0800, Wang, Qi wrote:
> 
> >>> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> >> Just take a look at kfifo.h. This structure has been changed. I
> >> remembered there was a spin_lock from kfifo previously. Currently it's
> >> been removed, good.
> >> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to
> use this structure and APIs?
> >>
> >> Daniel,
> >>
> >> We're anxious to integrate those codes now. Perhaps it'll take us
> >> quite a long time to use kfifo. How about implementing it with the
> >> next version?
> >
> > What do you mean by this?  Code isn't merged into the tree unless it is
> > correct.  Please fix this now, it's not that big of a deal.
> >
> 
> Hello Qi,
> 
> i generally wonder what this FIFO is used for??
> 
> For me it looks like a artifact from a former chardev implementation, as
> several other code sniplets do (see comments from Wolfgang and Marc).
> 
> The network driver model is used for CAN drivers and therefore all the
> infrastructure for queueing inbound and outbound network traffic should be
> used from the Kernel like all other CAN drivers and all other ethernet drivers
> do.
> 
> Additionally there is a powerful infrastructure to support the special
> functions of CAN netdevices (like setting of bittimings, listen-only modes, or
> to produce CAN driver states etc.), that's part of the CAN drivers in
> drivers/net/can/ since it has gone mainline.
> 
> CAN netdevices are intentionally dumb (like the original ethernet adapters).
> This allows a simple driver interface between the kernel and the hardware
> driver, e.g. for queueing CAN frames. CAN drivers don't use any hardware
> rx-filtering(!) due to multiuser requirements and it's a vital requirement
> that the frames are not re-ordered on sending (by the 'some magic' CAN
> controller dealing with CAN-ID priorities, e.g. see tx-path in the MSCAN driver).
> 
> From my perspective about 70% of your code is obsolete, as you implemented
> tricky details (like FIFOs, bittiming tables or magic filter handlings),
> that's not needed at all.
> 
> Please take a look at the SJA1000 driver (for a low complex CAN controller) or
> at the TI driver (for a higher complex CAN controller) how these drivers
> handle the specialties of each hardware. And read some documentation in
> Documentation/networking/can.txt to get an impression about the concepts of
> the CAN implementation in the Linux Kernel and the CAN netdevices.
> 
> I strongly assume that your driver would be about 30 kBytes of code fitting
> into a single c-file like the ti_hecc.c does. And that's definitely easier for
> us to review and easier for you to maintain in the future ...
> 
> Thanks & best regards,
> Oliver
Thank you for your commits.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]       ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA26EB-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2010-08-12  5:17         ` Daniel Baluta
@ 2010-08-12  9:03         ` Wolfgang Grandegger
  2010-08-13  0:23           ` Wang, Qi
  1 sibling, 1 reply; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-08-12  9:03 UTC (permalink / raw)
  To: Wang, Qi
  Cc: Khor, Andrew Chih Howe, socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, gregkh-l3A5Bk7waGM, Wang, Yong Y,
	Masayuki Ohtak, meego-dev-WXzIur8shnEAvxtiuMwx3w,
	arjan-VuQAYsv1563Yd54FQh9/CA

On 08/12/2010 03:42 AM, Wang, Qi wrote:
>> -----Original Message-----
>> From: Daniel Baluta [mailto:daniel.baluta-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org]
>> Sent: Wednesday, August 11, 2010 6:37 PM
>> To: Masayuki Ohtak
>> Cc: meego-dev-WXzIur8shnEAvxtiuMwx3w@public.gmane.org; Wolfgang Grandegger;
>> socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org; netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Khor, Andrew Chih
>> Howe; gregkh-l3A5Bk7waGM@public.gmane.org; arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org; Wang, Qi; Wang, Yong Y
>> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
>>
>> Hi,
>>
>> 2010/8/11 Masayuki Ohtak <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>:
>>> CAN driver of Topcliff PCH
>>>
>>> Topcliff PCH is the platform controller hub that is going to be used in
>>> Intel's upcoming general embedded platform. All IO peripherals in
>>> Topcliff PCH are actually devices sitting on AMBA bus.
>>> Topcliff PCH has CAN I/F. This driver enables CAN function.
>>>
>>> Signed-off-by: Masayuki Ohtake <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
>>
>> I have a few questions:
>>
>> 1. Is your code based on Intel's CAN EP80579 ([1]) ?
> No.

For curiosity, is the controller similar to the OKI MSM9225 or ML9620?

>> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> Just take a look at kfifo.h. This structure has been changed. I remembered there was a spin_lock from kfifo previously. Currently it's been removed, good.
> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to use this structure and APIs?

As I see it, the code related to that fifo is not used (== dead code)?

> Daniel,
> 
> We're anxious to integrate those codes now. Perhaps it'll take us quite a long time to use kfifo. How about implementing it with the next version?

See above. What do you mean with the next version. The driver posted by
Masayuki is far away from being accepted as it does not yet comply with
the Socket-CAN driver API, to say the least.

Wolfgang.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* RE: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-08-12  9:03         ` Wolfgang Grandegger
@ 2010-08-13  0:23           ` Wang, Qi
       [not found]             ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA2AB1-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: Wang, Qi @ 2010-08-13  0:23 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Daniel Baluta, Masayuki Ohtak, meego-dev, socketcan-core, netdev,
	Khor, Andrew Chih Howe, gregkh, arjan, Wang, Yong Y

> -----Original Message-----
> From: Wolfgang Grandegger [mailto:wg@grandegger.com]
> Sent: Thursday, August 12, 2010 5:04 PM
> To: Wang, Qi
> Cc: Daniel Baluta; Masayuki Ohtak; meego-dev@meego.com;
> socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew Chih
> Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Yong Y
> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> 
> On 08/12/2010 03:42 AM, Wang, Qi wrote:
> >> -----Original Message-----
> >> From: Daniel Baluta [mailto:daniel.baluta@gmail.com]
> >> Sent: Wednesday, August 11, 2010 6:37 PM
> >> To: Masayuki Ohtak
> >> Cc: meego-dev@meego.com; Wolfgang Grandegger;
> >> socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew
> Chih
> >> Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Qi; Wang, Yong Y
> >> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> >>
> >> Hi,
> >>
> >> 2010/8/11 Masayuki Ohtak <masa-korg@dsn.okisemi.com>:
> >>> CAN driver of Topcliff PCH
> >>>
> >>> Topcliff PCH is the platform controller hub that is going to be used in
> >>> Intel's upcoming general embedded platform. All IO peripherals in
> >>> Topcliff PCH are actually devices sitting on AMBA bus.
> >>> Topcliff PCH has CAN I/F. This driver enables CAN function.
> >>>
> >>> Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> >>
> >> I have a few questions:
> >>
> >> 1. Is your code based on Intel's CAN EP80579 ([1]) ?
> > No.
> 
> For curiosity, is the controller similar to the OKI MSM9225 or ML9620?
The Topcliff IOH is developed by OKI actually.

> 
> >> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> > Just take a look at kfifo.h. This structure has been changed. I remembered
> there was a spin_lock from kfifo previously. Currently it's been removed, good.
> > OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to
> use this structure and APIs?
> 
> As I see it, the code related to that fifo is not used (== dead code)?
I'm not familiar with kfifo structure, and I didn't like it because there need a spin_lock to use it.
> 
> > Daniel,
> >
> > We're anxious to integrate those codes now. Perhaps it'll take us quite a long
> time to use kfifo. How about implementing it with the next version?
> 
> See above. What do you mean with the next version. The driver posted by
> Masayuki is far away from being accepted as it does not yet comply with
> the Socket-CAN driver API, to say the least.
I've few experience on CAN driver and it's also the first time for OKI-san to write Can driver. Would you please give us a reference and we'll follow it up. We only read 'can.txt' from kernel document. Thank you for your help in advance.
> 
> Wolfgang.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]             ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA2AB1-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
@ 2010-08-13  6:11               ` Daniel Baluta
  2010-08-13 10:58               ` Wolfgang Grandegger
  1 sibling, 0 replies; 40+ messages in thread
From: Daniel Baluta @ 2010-08-13  6:11 UTC (permalink / raw)
  To: Wang, Qi
  Cc: Khor, Andrew Chih Howe, socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	netdev-u79uwXL29TY76Z2rM5mHXA, gregkh-l3A5Bk7waGM, Wang, Yong Y,
	Masayuki Ohtak, meego-dev-WXzIur8shnEAvxtiuMwx3w,
	arjan-VuQAYsv1563Yd54FQh9/CA, Wolfgang Grandegger

Hi,
> I'm not familiar with kfifo structure, and I didn't like it because there need a spin_lock to use it.

It seems that you don't need to use your own kfifo. Socket-CAN core has
it's internal queues, you only have to fit in this infrastructure.

>>
>> > Daniel,
>> >
>> > We're anxious to integrate those codes now. Perhaps it'll take us quite a long
>> time to use kfifo. How about implementing it with the next version?
>>
>> See above. What do you mean with the next version. The driver posted by
>> Masayuki is far away from being accepted as it does not yet comply with
>> the Socket-CAN driver API, to say the least.
> I've few experience on CAN driver and it's also the first time for OKI-san to write Can driver. Would you please give us a reference and we'll follow it up. We only read 'can.txt' from kernel document. Thank you for your help in advance.

Oliver's email should be your starting point. Read the code from net/can and see
how other drivers are built.

As I previously said I'm interested in writing a driver for CAN
EP80579 controller,
but the start is pretty slow. Since your controller seems to be pretty
similar we
can do some things in common.

I can help you, if you send me a pointer to your CAN controller
datasheet + eventually
grant me access to your repo.

thanks,
Daniel.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]             ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA2AB1-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
  2010-08-13  6:11               ` Daniel Baluta
@ 2010-08-13 10:58               ` Wolfgang Grandegger
  2010-08-20  6:01                 ` Masayuki Ohtake
  1 sibling, 1 reply; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-08-13 10:58 UTC (permalink / raw)
  To: Wang, Qi
  Cc: Khor, Andrew Chih Howe, Masayuki Ohtak,
	netdev-u79uwXL29TY76Z2rM5mHXA, gregkh-l3A5Bk7waGM, Wang, Yong Y,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	meego-dev-WXzIur8shnEAvxtiuMwx3w, arjan-VuQAYsv1563Yd54FQh9/CA

On 08/13/2010 02:23 AM, Wang, Qi wrote:
>> -----Original Message-----
>> From: Wolfgang Grandegger [mailto:wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org]
>> Sent: Thursday, August 12, 2010 5:04 PM
>> To: Wang, Qi
>> Cc: Daniel Baluta; Masayuki Ohtak; meego-dev-WXzIur8shnEAvxtiuMwx3w@public.gmane.org;
>> socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org; netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Khor, Andrew Chih
>> Howe; gregkh-l3A5Bk7waGM@public.gmane.org; arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org; Wang, Yong Y
>> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
>>
>> On 08/12/2010 03:42 AM, Wang, Qi wrote:
>>>> -----Original Message-----
>>>> From: Daniel Baluta [mailto:daniel.baluta-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org]
>>>> Sent: Wednesday, August 11, 2010 6:37 PM
>>>> To: Masayuki Ohtak
>>>> Cc: meego-dev-WXzIur8shnEAvxtiuMwx3w@public.gmane.org; Wolfgang Grandegger;
>>>> socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org; netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org; Khor, Andrew
>> Chih
>>>> Howe; gregkh-l3A5Bk7waGM@public.gmane.org; arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org; Wang, Qi; Wang, Yong Y
>>>> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
>>>>
>>>> Hi,
>>>>
>>>> 2010/8/11 Masayuki Ohtak <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>:
>>>>> CAN driver of Topcliff PCH
>>>>>
>>>>> Topcliff PCH is the platform controller hub that is going to be used in
>>>>> Intel's upcoming general embedded platform. All IO peripherals in
>>>>> Topcliff PCH are actually devices sitting on AMBA bus.
>>>>> Topcliff PCH has CAN I/F. This driver enables CAN function.
>>>>>
>>>>> Signed-off-by: Masayuki Ohtake <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
>>>>
>>>> I have a few questions:
>>>>
>>>> 1. Is your code based on Intel's CAN EP80579 ([1]) ?
>>> No.
>>
>> For curiosity, is the controller similar to the OKI MSM9225 or ML9620?
> The Topcliff IOH is developed by OKI actually.
> 
>>
>>>> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
>>> Just take a look at kfifo.h. This structure has been changed. I remembered
>> there was a spin_lock from kfifo previously. Currently it's been removed, good.
>>> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to
>> use this structure and APIs?
>>
>> As I see it, the code related to that fifo is not used (== dead code)?
> I'm not familiar with kfifo structure, and I didn't like it because there need a spin_lock to use it.
>>
>>> Daniel,
>>>
>>> We're anxious to integrate those codes now. Perhaps it'll take us quite a long
>> time to use kfifo. How about implementing it with the next version?
>>
>> See above. What do you mean with the next version. The driver posted by
>> Masayuki is far away from being accepted as it does not yet comply with
>> the Socket-CAN driver API, to say the least.
> I've few experience on CAN driver and it's also the first time for OKI-san to write Can driver. Would you please give us a reference and we'll follow it up. We only read 'can.txt' from kernel document. Thank you for your help in advance.

You are welcome. I think I/we already gave useful hints on what is
missing and what examples to follow.

Wolfgang.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-08-13 10:58               ` Wolfgang Grandegger
@ 2010-08-20  6:01                 ` Masayuki Ohtake
       [not found]                   ` <000f01cb402d$34b675b0$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: Masayuki Ohtake @ 2010-08-20  6:01 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Wang, Qi, arjan, meego-dev, Wang, Yong Y, gregkh, netdev,
	socketcan-core, Khor, Andrew Chih Howe, Morinaga

Hi Wolfgang,

> >>>> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> >>> Just take a look at kfifo.h. This structure has been changed. I remembered
> >> there was a spin_lock from kfifo previously. Currently it's been removed, good.
> >>> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to
> >> use this structure and APIs?
> >>
> >> As I see it, the code related to that fifo is not used (== dead code)?
> > I'm not familiar with kfifo structure, and I didn't like it because there need a spin_lock to use it.

We are about to study kfifo infra structure.
I have a question.

It seems all CAN drivers accepted by upstream don't use kfifo infrastructure, right ?
(I couldn't see message with "grep kfifo * in drivers/net/can")

If yes, why should we use the kfifo ?
If no, please show me the kfifo reference driver

Thanks, Ohtake(OKISEMI)
----- Original Message ----- 
From: "Wolfgang Grandegger" <wg@grandegger.com>
To: "Wang, Qi" <qi.wang@intel.com>
Cc: "Khor, Andrew Chih Howe" <andrew.chih.howe.khor@intel.com>; <socketcan-core@lists.berlios.de>;
<netdev@vger.kernel.org>; <gregkh@suse.de>; "Wang, Yong Y" <yong.y.wang@intel.com>; "Masayuki Ohtak"
<masa-korg@dsn.okisemi.com>; <meego-dev@meego.com>; <arjan@linux.intel.com>
Sent: Friday, August 13, 2010 7:58 PM
Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35


> On 08/13/2010 02:23 AM, Wang, Qi wrote:
> >> -----Original Message-----
> >> From: Wolfgang Grandegger [mailto:wg@grandegger.com]
> >> Sent: Thursday, August 12, 2010 5:04 PM
> >> To: Wang, Qi
> >> Cc: Daniel Baluta; Masayuki Ohtak; meego-dev@meego.com;
> >> socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew Chih
> >> Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Yong Y
> >> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> >>
> >> On 08/12/2010 03:42 AM, Wang, Qi wrote:
> >>>> -----Original Message-----
> >>>> From: Daniel Baluta [mailto:daniel.baluta@gmail.com]
> >>>> Sent: Wednesday, August 11, 2010 6:37 PM
> >>>> To: Masayuki Ohtak
> >>>> Cc: meego-dev@meego.com; Wolfgang Grandegger;
> >>>> socketcan-core@lists.berlios.de; netdev@vger.kernel.org; Khor, Andrew
> >> Chih
> >>>> Howe; gregkh@suse.de; arjan@linux.intel.com; Wang, Qi; Wang, Yong Y
> >>>> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> >>>>
> >>>> Hi,
> >>>>
> >>>> 2010/8/11 Masayuki Ohtak <masa-korg@dsn.okisemi.com>:
> >>>>> CAN driver of Topcliff PCH
> >>>>>
> >>>>> Topcliff PCH is the platform controller hub that is going to be used in
> >>>>> Intel's upcoming general embedded platform. All IO peripherals in
> >>>>> Topcliff PCH are actually devices sitting on AMBA bus.
> >>>>> Topcliff PCH has CAN I/F. This driver enables CAN function.
> >>>>>
> >>>>> Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> >>>>
> >>>> I have a few questions:
> >>>>
> >>>> 1. Is your code based on Intel's CAN EP80579 ([1]) ?
> >>> No.
> >>
> >> For curiosity, is the controller similar to the OKI MSM9225 or ML9620?
> > The Topcliff IOH is developed by OKI actually.
> >
> >>
> >>>> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> >>> Just take a look at kfifo.h. This structure has been changed. I remembered
> >> there was a spin_lock from kfifo previously. Currently it's been removed, good.
> >>> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to
> >> use this structure and APIs?
> >>
> >> As I see it, the code related to that fifo is not used (== dead code)?
> > I'm not familiar with kfifo structure, and I didn't like it because there need a spin_lock to use it.
> >>
> >>> Daniel,
> >>>
> >>> We're anxious to integrate those codes now. Perhaps it'll take us quite a long
> >> time to use kfifo. How about implementing it with the next version?
> >>
> >> See above. What do you mean with the next version. The driver posted by
> >> Masayuki is far away from being accepted as it does not yet comply with
> >> the Socket-CAN driver API, to say the least.
> > I've few experience on CAN driver and it's also the first time for OKI-san to write Can driver. Would you please
give us a reference and we'll follow it up. We only read 'can.txt' from kernel document. Thank you for your help in
advance.
>
> You are welcome. I think I/we already gave useful hints on what is
> missing and what examples to follow.
>
> Wolfgang.
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]                   ` <000f01cb402d$34b675b0$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
@ 2010-08-20  7:59                     ` Wolfgang Grandegger
  2010-08-20  8:37                       ` Masayuki Ohtake
  0 siblings, 1 reply; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-08-20  7:59 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: Khor, Andrew Chih Howe, Wang, Qi, netdev-u79uwXL29TY76Z2rM5mHXA,
	gregkh-l3A5Bk7waGM, Wang, Yong Y,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Morinaga,
	meego-dev-WXzIur8shnEAvxtiuMwx3w, arjan-VuQAYsv1563Yd54FQh9/CA

Hi Ohtake,

On 08/20/2010 08:01 AM, Masayuki Ohtake wrote:
> Hi Wolfgang,
> 
>>>>>> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
>>>>> Just take a look at kfifo.h. This structure has been changed. I remembered
>>>> there was a spin_lock from kfifo previously. Currently it's been removed, good.
>>>>> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to
>>>> use this structure and APIs?
>>>>
>>>> As I see it, the code related to that fifo is not used (== dead code)?
>>> I'm not familiar with kfifo structure, and I didn't like it because there need a spin_lock to use it.
> 
> We are about to study kfifo infra structure.
> I have a question.
> 
> It seems all CAN drivers accepted by upstream don't use kfifo infrastructure, right ?

Right!

> (I couldn't see message with "grep kfifo * in drivers/net/can")
> 
> If yes, why should we use the kfifo ?
> If no, please show me the kfifo reference driver

Sorry, nobody (of the socketcan core developers) said that kfifo should
be used. We believe, that an additional queuing of CAN messages is *not*
needed at all. Just eliminate the related code and follow more closely
the existing mainline drivers.

Wolfgang.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-08-20  7:59                     ` Wolfgang Grandegger
@ 2010-08-20  8:37                       ` Masayuki Ohtake
  0 siblings, 0 replies; 40+ messages in thread
From: Masayuki Ohtake @ 2010-08-20  8:37 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Wang, Qi, arjan, meego-dev, Wang, Yong Y, gregkh, netdev,
	socketcan-core, Khor, Andrew Chih Howe, Morinaga

Hi Wolfgang,

Thank you for your comment.
We don't use kfifo infrastructure but brush up with current framework.

Thanks, Ohtake(OKISEMI)
----- Original Message ----- 
From: "Wolfgang Grandegger" <wg@grandegger.com>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "Wang, Qi" <qi.wang@intel.com>; <arjan@linux.intel.com>; <meego-dev@meego.com>; "Wang, Yong Y"
<yong.y.wang@intel.com>; <gregkh@suse.de>; <netdev@vger.kernel.org>; <socketcan-core@lists.berlios.de>; "Khor, Andrew
Chih Howe" <andrew.chih.howe.khor@intel.com>; "Morinaga" <morinaga526@dsn.okisemi.com>
Sent: Friday, August 20, 2010 4:59 PM
Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35


> Hi Ohtake,
>
> On 08/20/2010 08:01 AM, Masayuki Ohtake wrote:
> > Hi Wolfgang,
> >
> >>>>>> 2. Why don't you use kernel existing kfifo infrastructure? ([2]).
> >>>>> Just take a look at kfifo.h. This structure has been changed. I remembered
> >>>> there was a spin_lock from kfifo previously. Currently it's been removed, good.
> >>>>> OKI-sans, would you please take a look at ./include/linux/kfifo.h, and try to
> >>>> use this structure and APIs?
> >>>>
> >>>> As I see it, the code related to that fifo is not used (== dead code)?
> >>> I'm not familiar with kfifo structure, and I didn't like it because there need a spin_lock to use it.
> >
> > We are about to study kfifo infra structure.
> > I have a question.
> >
> > It seems all CAN drivers accepted by upstream don't use kfifo infrastructure, right ?
>
> Right!
>
> > (I couldn't see message with "grep kfifo * in drivers/net/can")
> >
> > If yes, why should we use the kfifo ?
> > If no, please show me the kfifo reference driver
>
> Sorry, nobody (of the socketcan core developers) said that kfifo should
> be used. We believe, that an additional queuing of CAN messages is *not*
> needed at all. Just eliminate the related code and follow more closely
> the existing mainline drivers.
>
> Wolfgang.
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]         ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA29DF@shsmsx501.ccr.corp.intel.com>
@ 2010-09-01  7:45           ` Masayuki Ohtake
  2010-09-01 17:04               ` Oliver Hartkopp
  2010-09-01 18:51               ` Wolfgang Grandegger
  0 siblings, 2 replies; 40+ messages in thread
From: Masayuki Ohtake @ 2010-09-01  7:45 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Wang, Yong Y, arjan, gregkh, Qi, Andrew Chih Howe,
	ML linux-kernel, ML netdev, socketcan-core, Samuel Ortiz,
	Barry Song, Christian Pellegrin, Wolfram Sang,
	"David S. Miller"

Sorry, for late response.
----- Original Message ----- 
From: "Wang, Qi" <qi.wang@intel.com>
To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: "Khor, Andrew Chih Howe" <andrew.chih.howe.khor@intel.com>; <gregkh@suse.de>; <arjan@linux.intel.com>; "Wang, Yong
Y" <yong.y.wang@intel.com>; "Wolfgang Grandegger" <wg@grandegger.com>
Sent: Thursday, August 12, 2010 6:00 PM
Subject: RE: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35


> Hi Ohtak-san,
>
> Would you please answer the question from Wolfgang?
>
> Best Regards,
> Qi.
>
> > -----Original Message-----
> > From: Wolfgang Grandegger [mailto:wg@grandegger.com]
> > Sent: Thursday, August 12, 2010 4:55 PM
> > To: Wang, Qi
> > Cc: Masayuki Ohtak; Khor, Andrew Chih Howe; gregkh@suse.de;
> > arjan@linux.intel.com; Wang, Yong Y
> > Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> >
> > On 08/12/2010 03:29 AM, Wang, Qi wrote:
> > >> -----Original Message-----
> > >> From: Wolfgang Grandegger [mailto:wg@grandegger.com]
> > >> Sent: Wednesday, August 11, 2010 8:31 PM
> > >> To: Masayuki Ohtak
> > >> Cc: meego-dev@meego.com; socketcan-core@lists.berlios.de;
> > >> netdev@vger.kernel.org; Khor, Andrew Chih Howe; gregkh@suse.de;
> > >> arjan@linux.intel.com; Wang, Qi; Wang, Yong Y
> > >> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> > >>
> > >> Hello,
> > >>
> > >> On 08/11/2010 02:25 AM, Masayuki Ohtak wrote:
> > >>> CAN driver of Topcliff PCH
> > >>>
> > >>> Topcliff PCH is the platform controller hub that is going to be used in
> > >>> Intel's upcoming general embedded platform. All IO peripherals in
> > >>> Topcliff PCH are actually devices sitting on AMBA bus.
> > >>
> > >> That's interesting. Where can I/we find more information about this CAN
> > >> controller, e.g. data-sheets. It seems to have a few interesting
> > >> features (message scheduler, etc.).
> > >
> > > I remove all the maillist, and show you something about this platform.
> >
> > Like Greg, I also prefer the public discussion.
> >
> > >
> > > Topcliff PCH is connected with Tunnelcreak (A kind of ATOM-based processor,
> > which integrate Memory controller, GFX and RC). And Topcliff is a kind of
> > stand-alone ARM-based processor, so it has AMBA-based peripherals, such as
> > CAN, GBE, I2C.
> > >
> > > Topcliff connected with Tunnelcreak via PCIe x1 lane. And PCH_PHUB works
> > as a gateway, which transform PCIe transaction to AMBA transaction, and vice
> > versa.
> > >
> > > The datasheet of those two chips aren't open now.
> >
> > Thanks for the info.
> >
> > >>> Topcliff PCH has CAN I/F. This driver enables CAN function.
> > >>>
> > >>> Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> > >>
> > >> Thanks for your contribution. Unfortunately, there are many issues,
> > >> especially the driver is not yet conform with the Socket-CAN driver API:
> > >>
> > >> - My first observation was:
> > >>
> > >>   $ wc -l pch_can.c
> > >>   4076 pch_can.c
> > >>   $ grep dev_dbg pch_can.c | wc -l
> > >>   143
> > >>
> > >>   That's a lot of code, mainly debugging code, I think. This needs to
> > >>   be cleaned up sooner than later. dev_dbg's should be restricted to a
> > >>   few useful for the real users.

We will reduce dev_dbg code.

> > >>
> > >> - The values for the hw-specific bit-timing registers should be derived
> > >>   from the calculated values in "priv->can.bittiming":
> > >>
> > >>   http://lxr.linux.no/#linux+v2.6.35/include/linux/can/netlink.h#L17
> > >>

I show current pch_can code below.

+static int pch_set_bittiming(struct net_device *ndev)
+{
+ struct pch_can_priv *priv = netdev_priv(ndev);
+ struct pch_can_os *dev_can_os = priv->pch_can_os_p;
+ const struct can_bittiming *bt = &priv->can.bittiming;

Is the above TRUE, isn't it ?

> > >> - The driver should handle state changes and communicate them to the
> > >>   user space via error messages, if possible.
> > >>
What's "state chage" mean ?

> > >> - The driver should report errors to the user space via error messages.
> > >>
Is the above mean using alloc_can_err_skb and set error info and notify to kernel with netif_rx ?


> > >> - Bus errors seem not to be handled properly.I'm missing can_bus_off().
> > >>   Does the controller recover from bus-off automatically?
No.
CAN driver recovers from Bus-off state.

> > >>
> > >> - I see that the driver uses many TX and RX objects. How do you avoid
> > >>   out-of-order transmission and reception?
> > > What do you mean out-of-order RX and TX?
> > > Atom processor only supports in-order execution, and PCIe-based peripherals
> > can solve it with consumer-producer model. Actually IC designer will take care
> > of out-of-order PCIe CPLD transaction.
> >
> > I mean out-of-order transmission to or from the CAN bus. This is handled
> > by the CAN controller hardware. It has nothing to to with the processor.
Cannot avoid occurring rx or tx our-of-order.

Thanks, Ohtake(OKISemi)




^ permalink raw reply	[flat|nested] 40+ messages in thread

* out-of-order tx objects - was Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
@ 2010-09-01 17:04               ` Oliver Hartkopp
  0 siblings, 0 replies; 40+ messages in thread
From: Oliver Hartkopp @ 2010-09-01 17:04 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: Wolfgang Grandegger, Wang, Yong Y, arjan, gregkh, Qi,
	Andrew Chih Howe, ML linux-kernel, ML netdev, socketcan-core,
	Samuel Ortiz, Barry Song, Christian Pellegrin, Wolfram Sang,
	David S. Miller

Hello Ohtake,

i'm only picking up the out-of-order issue here ...

On 01.09.2010 09:45, Masayuki Ohtake wrote:

>>>>> - I see that the driver uses many TX and RX objects. How do you avoid
>>>>>   out-of-order transmission and reception?
>>>> What do you mean out-of-order RX and TX?
>>>> Atom processor only supports in-order execution, and PCIe-based peripherals
>>> can solve it with consumer-producer model. Actually IC designer will take care
>>> of out-of-order PCIe CPLD transaction.
>>>
>>> I mean out-of-order transmission to or from the CAN bus. This is handled
>>> by the CAN controller hardware. It has nothing to to with the processor.
> Cannot avoid occurring rx or tx our-of-order.

The CAN frames that are sent by the local system have to touch the wire in the
same order as you put them into the socket as user.

An example:

You send CAN-frames with CAN Identifiers via can-raw sockets

0x123
0x456
0x010

and of course you expect these frames sent in exactly this order.
This is easy to archive as you get each of these CAN frames out of the
netdevices tx-queue in this order.

The problems comes up when you use multiple "tx objects" of your CAN
controller. Some CAN controllers have a "magic intelligence" that leads to
some re-ordering according to the CAN-Identifiers priority.

E.g.

0x123
0x456
0x010

leads to

0x123
0x010
0x456

because you pushed these CAN-frames into different tx objects and the CAN
controller sorts them on its own by priority. For CAN newbies: A lower CAN-ID
value has a higher priority in arbitration on the *physical* layer.

In the example above the CAN controller checks after sending the 0x123 CAN
frame if there's a priority order in the tx objects that are ready to send,
and selects 0x010 ...

This behaviour might be interesting in single-user/single-application
environments - but it is just wrong in multi-user systems where several
different applications use the (same) CAN bus. Standard networking behaviour.

Please ensure that the CAN frame order given by the tx-queue of the Linux
kernel netdevice infrastructure is send on the wire in the same order.

This usually leads to the use of ONLY ONE tx object of your CAN controller.
Probably you can use two tx objects to increase the throughput if this does
not have any impact to the frame order. See your controllers documentation for
details about this tx object behaviour.

I hope this makes the question of Wolfgang a bit clearer :-)

Regards,
Oliver

^ permalink raw reply	[flat|nested] 40+ messages in thread

* out-of-order tx objects - was Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
@ 2010-09-01 17:04               ` Oliver Hartkopp
  0 siblings, 0 replies; 40+ messages in thread
From: Oliver Hartkopp @ 2010-09-01 17:04 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: Andrew Chih Howe, Qi, ML netdev, gregkh-l3A5Bk7waGM, Wang,
	Yong Y, ML linux-kernel, socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	Christian Pellegrin, arjan-VuQAYsv1563Yd54FQh9/CA,
	David S. Miller, Wolfgang Grandegger, Samuel Ortiz

Hello Ohtake,

i'm only picking up the out-of-order issue here ...

On 01.09.2010 09:45, Masayuki Ohtake wrote:

>>>>> - I see that the driver uses many TX and RX objects. How do you avoid
>>>>>   out-of-order transmission and reception?
>>>> What do you mean out-of-order RX and TX?
>>>> Atom processor only supports in-order execution, and PCIe-based peripherals
>>> can solve it with consumer-producer model. Actually IC designer will take care
>>> of out-of-order PCIe CPLD transaction.
>>>
>>> I mean out-of-order transmission to or from the CAN bus. This is handled
>>> by the CAN controller hardware. It has nothing to to with the processor.
> Cannot avoid occurring rx or tx our-of-order.

The CAN frames that are sent by the local system have to touch the wire in the
same order as you put them into the socket as user.

An example:

You send CAN-frames with CAN Identifiers via can-raw sockets

0x123
0x456
0x010

and of course you expect these frames sent in exactly this order.
This is easy to archive as you get each of these CAN frames out of the
netdevices tx-queue in this order.

The problems comes up when you use multiple "tx objects" of your CAN
controller. Some CAN controllers have a "magic intelligence" that leads to
some re-ordering according to the CAN-Identifiers priority.

E.g.

0x123
0x456
0x010

leads to

0x123
0x010
0x456

because you pushed these CAN-frames into different tx objects and the CAN
controller sorts them on its own by priority. For CAN newbies: A lower CAN-ID
value has a higher priority in arbitration on the *physical* layer.

In the example above the CAN controller checks after sending the 0x123 CAN
frame if there's a priority order in the tx objects that are ready to send,
and selects 0x010 ...

This behaviour might be interesting in single-user/single-application
environments - but it is just wrong in multi-user systems where several
different applications use the (same) CAN bus. Standard networking behaviour.

Please ensure that the CAN frame order given by the tx-queue of the Linux
kernel netdevice infrastructure is send on the wire in the same order.

This usually leads to the use of ONLY ONE tx object of your CAN controller.
Probably you can use two tx objects to increase the throughput if this does
not have any impact to the frame order. See your controllers documentation for
details about this tx object behaviour.

I hope this makes the question of Wolfgang a bit clearer :-)

Regards,
Oliver

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
@ 2010-09-01 18:51               ` Wolfgang Grandegger
  0 siblings, 0 replies; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-09-01 18:51 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: Andrew Chih Howe, Qi, ML netdev, gregkh, ML linux-kernel, Wang,
	Yong Y, socketcan-core, arjan, David S. Miller,
	Christian Pellegrin, Samuel Ortiz

Hello,

On 09/01/2010 09:45 AM, Masayuki Ohtake wrote:
> Sorry, for late response.
> ----- Original Message ----- 
> From: "Wang, Qi" <qi.wang@intel.com>
> To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
> Cc: "Khor, Andrew Chih Howe" <andrew.chih.howe.khor@intel.com>; <gregkh@suse.de>; <arjan@linux.intel.com>; "Wang, Yong
> Y" <yong.y.wang@intel.com>; "Wolfgang Grandegger" <wg@grandegger.com>
> Sent: Thursday, August 12, 2010 6:00 PM
> Subject: RE: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
...
>>>>> - The values for the hw-specific bit-timing registers should be derived
>>>>>   from the calculated values in "priv->can.bittiming":
>>>>>
>>>>>   http://lxr.linux.no/#linux+v2.6.35/include/linux/can/netlink.h#L17
>>>>>
> 
> I show current pch_can code below.
> 
> +static int pch_set_bittiming(struct net_device *ndev)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct pch_can_os *dev_can_os = priv->pch_can_os_p;
> + const struct can_bittiming *bt = &priv->can.bittiming;
> 
> Is the above TRUE, isn't it ?

The code fragment looks good. In that function you should then *derive*
the values of the bit-timing registers from the data fields of "bt". For
the SJA1000, you find the code here:

http://lxr.linux.no/#linux+v2.6.35/drivers/net/can/sja1000/sja1000.c#L202

>>>>> - The driver should handle state changes and communicate them to the
>>>>>   user space via error messages, if possible.
>>>>>
> What's "state chage" mean ?

Googling for "can bis states" returned:

http://www.softing.com/home/en/industrial-automation/products/can-bus/more-can-bus/error-handling/error-states.php?navanchor=3010510

The CAN controller usually triggers an interrupt when the state changes,
which allows the driver to track the CAN state and deliver that
information to the user space.

>>>>> - The driver should report errors to the user space via error messages.
>>>>>
> Is the above mean using alloc_can_err_skb and set error info and notify to kernel with netif_rx ?

Yes. Please search "Documentation/networking/can.txt" for "error frames"
for further information.

>>>>> - Bus errors seem not to be handled properly.I'm missing can_bus_off().
>>>>>   Does the controller recover from bus-off automatically?
> No.
> CAN driver recovers from Bus-off state.

You mean: "It does *not" recover automatically"! Right?

> 
>>>>>
>>>>> - I see that the driver uses many TX and RX objects. How do you avoid
>>>>>   out-of-order transmission and reception?
>>>> What do you mean out-of-order RX and TX?
>>>> Atom processor only supports in-order execution, and PCIe-based peripherals
>>> can solve it with consumer-producer model. Actually IC designer will take care
>>> of out-of-order PCIe CPLD transaction.
>>>
>>> I mean out-of-order transmission to or from the CAN bus. This is handled
>>> by the CAN controller hardware. It has nothing to to with the processor.
> Cannot avoid occurring rx or tx our-of-order.

It is a *requirement* as Oliver already pointed out. It's easy to
achieve if just one TX object is used but it might be tricky with more
than one.

Wolfgang.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
@ 2010-09-01 18:51               ` Wolfgang Grandegger
  0 siblings, 0 replies; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-09-01 18:51 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: Andrew Chih Howe, Qi, ML netdev, gregkh-l3A5Bk7waGM, Wang,
	Yong Y, ML linux-kernel, socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	arjan-VuQAYsv1563Yd54FQh9/CA, David S. Miller,
	Christian Pellegrin, Samuel Ortiz

Hello,

On 09/01/2010 09:45 AM, Masayuki Ohtake wrote:
> Sorry, for late response.
> ----- Original Message ----- 
> From: "Wang, Qi" <qi.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> To: "Masayuki Ohtak" <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
> Cc: "Khor, Andrew Chih Howe" <andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <gregkh-l3A5Bk7waGM@public.gmane.org>; <arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>; "Wang, Yong
> Y" <yong.y.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; "Wolfgang Grandegger" <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
> Sent: Thursday, August 12, 2010 6:00 PM
> Subject: RE: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
...
>>>>> - The values for the hw-specific bit-timing registers should be derived
>>>>>   from the calculated values in "priv->can.bittiming":
>>>>>
>>>>>   http://lxr.linux.no/#linux+v2.6.35/include/linux/can/netlink.h#L17
>>>>>
> 
> I show current pch_can code below.
> 
> +static int pch_set_bittiming(struct net_device *ndev)
> +{
> + struct pch_can_priv *priv = netdev_priv(ndev);
> + struct pch_can_os *dev_can_os = priv->pch_can_os_p;
> + const struct can_bittiming *bt = &priv->can.bittiming;
> 
> Is the above TRUE, isn't it ?

The code fragment looks good. In that function you should then *derive*
the values of the bit-timing registers from the data fields of "bt". For
the SJA1000, you find the code here:

http://lxr.linux.no/#linux+v2.6.35/drivers/net/can/sja1000/sja1000.c#L202

>>>>> - The driver should handle state changes and communicate them to the
>>>>>   user space via error messages, if possible.
>>>>>
> What's "state chage" mean ?

Googling for "can bis states" returned:

http://www.softing.com/home/en/industrial-automation/products/can-bus/more-can-bus/error-handling/error-states.php?navanchor=3010510

The CAN controller usually triggers an interrupt when the state changes,
which allows the driver to track the CAN state and deliver that
information to the user space.

>>>>> - The driver should report errors to the user space via error messages.
>>>>>
> Is the above mean using alloc_can_err_skb and set error info and notify to kernel with netif_rx ?

Yes. Please search "Documentation/networking/can.txt" for "error frames"
for further information.

>>>>> - Bus errors seem not to be handled properly.I'm missing can_bus_off().
>>>>>   Does the controller recover from bus-off automatically?
> No.
> CAN driver recovers from Bus-off state.

You mean: "It does *not" recover automatically"! Right?

> 
>>>>>
>>>>> - I see that the driver uses many TX and RX objects. How do you avoid
>>>>>   out-of-order transmission and reception?
>>>> What do you mean out-of-order RX and TX?
>>>> Atom processor only supports in-order execution, and PCIe-based peripherals
>>> can solve it with consumer-producer model. Actually IC designer will take care
>>> of out-of-order PCIe CPLD transaction.
>>>
>>> I mean out-of-order transmission to or from the CAN bus. This is handled
>>> by the CAN controller hardware. It has nothing to to with the processor.
> Cannot avoid occurring rx or tx our-of-order.

It is a *requirement* as Oliver already pointed out. It's easy to
achieve if just one TX object is used but it might be tricky with more
than one.

Wolfgang.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-09-01 18:51               ` Wolfgang Grandegger
@ 2010-09-02  3:19                 ` Masayuki Ohtake
  -1 siblings, 0 replies; 40+ messages in thread
From: Masayuki Ohtake @ 2010-09-02  3:19 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Samuel Ortiz, Christian Pellegrin, David S. Miller, arjan,
	socketcan-core, Wang, Yong Y, ML linux-kernel, gregkh, ML netdev,
	Qi, Andrew Chih Howe, Morinaga

----- Original Message ----- 
From: "Wolfgang Grandegger" <wg@grandegger.com>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "Andrew Chih Howe" <andrew.chih.howe.khor@intel.com>; "Qi" <qi.wang@intel.com>; "ML netdev"
<netdev@vger.kernel.org>; <gregkh@suse.de>; "ML linux-kernel" <linux-kernel@vger.kernel.org>; "Wang, Yong Y"
<yong.y.wang@intel.com>; <socketcan-core@lists.berlios.de>; <arjan@linux.intel.com>; "David S. Miller"
<davem@davemloft.net>; "Christian Pellegrin" <chripell@fsfe.org>; "Samuel Ortiz" <sameo@linux.intel.com>
Sent: Thursday, September 02, 2010 3:51 AM
Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35

> ...
> >>>>> - The values for the hw-specific bit-timing registers should be derived
> >>>>>   from the calculated values in "priv->can.bittiming":
> >>>>>
> >>>>>   http://lxr.linux.no/#linux+v2.6.35/include/linux/can/netlink.h#L17
> >>>>>
> >
> > I show current pch_can code below.
> >
> > +static int pch_set_bittiming(struct net_device *ndev)
> > +{
> > + struct pch_can_priv *priv = netdev_priv(ndev);
> > + struct pch_can_os *dev_can_os = priv->pch_can_os_p;
> > + const struct can_bittiming *bt = &priv->can.bittiming;
> >
> > Is the above TRUE, isn't it ?
>
> The code fragment looks good. In that function you should then *derive*
> the values of the bit-timing registers from the data fields of "bt". For
> the SJA1000, you find the code here:
>
> http://lxr.linux.no/#linux+v2.6.35/drivers/net/can/sja1000/sja1000.c#L202
>

I can't understand the your saying.
I think our can driver is implemented like your saying.

In function "pch_set_bittiming", get the value of the bit-timing registers from
the data fields of "bt" at "pch_can_set_baud_custom" or "pch_can_set_baud_simple".

Could you indicate in more detail ?


> >>>>> - The driver should handle state changes and communicate them to the
> >>>>>   user space via error messages, if possible.
> >>>>>
> > What's "state chage" mean ?
>
> Googling for "can bis states" returned:
>
>
http://www.softing.com/home/en/industrial-automation/products/can-bus/more-can-bus/error-handling/error-states.php?navanchor=3010510
>
> The CAN controller usually triggers an interrupt when the state changes,
> which allows the driver to track the CAN state and deliver that
> information to the user space.

I could understand your saying.
In our current code, our driver can detect state change, but doesn't notify to
can-core module or kennel protocol stack.
We will modify our driver to notify to these.

>
> >>>>> - The driver should report errors to the user space via error messages.
> >>>>>
> > Is the above mean using alloc_can_err_skb and set error info and notify to kernel with netif_rx ?
>
> Yes. Please search "Documentation/networking/can.txt" for "error frames"
> for further information.

I understand.
We will modify.

>
> >>>>> - Bus errors seem not to be handled properly.I'm missing can_bus_off().
> >>>>>   Does the controller recover from bus-off automatically?
> > No.
> > CAN driver recovers from Bus-off state.
>
> You mean: "It does *not" recover automatically"! Right?

I meant like below.
CAN-HW itself can't recover from bus-off state automatically.
Cooperate with CAN driver, CAN HW can do automatically.

>
> >
> >>>>>
> >>>>> - I see that the driver uses many TX and RX objects. How do you avoid
> >>>>>   out-of-order transmission and reception?
> >>>> What do you mean out-of-order RX and TX?
> >>>> Atom processor only supports in-order execution, and PCIe-based peripherals
> >>> can solve it with consumer-producer model. Actually IC designer will take care
> >>> of out-of-order PCIe CPLD transaction.
> >>>
> >>> I mean out-of-order transmission to or from the CAN bus. This is handled
> >>> by the CAN controller hardware. It has nothing to to with the processor.
> > Cannot avoid occurring rx or tx our-of-order.
>
> It is a *requirement* as Oliver already pointed out. It's easy to
> achieve if just one TX object is used but it might be tricky with more
> than one.

I agree with your indication.
We will modify so that our CAN driver has only one tx/rx each object.

Thanks, Ohtake(OKISemi)



^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
@ 2010-09-02  3:19                 ` Masayuki Ohtake
  0 siblings, 0 replies; 40+ messages in thread
From: Masayuki Ohtake @ 2010-09-02  3:19 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Andrew Chih Howe, Samuel Ortiz, ML netdev, gregkh-l3A5Bk7waGM,
	Wang, Yong Y, ML linux-kernel,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Morinaga,
	arjan-VuQAYsv1563Yd54FQh9/CA, David S. Miller,
	Christian Pellegrin, Qi

----- Original Message ----- 
From: "Wolfgang Grandegger" <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
To: "Masayuki Ohtake" <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Cc: "Andrew Chih Howe" <andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; "Qi" <qi.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; "ML netdev"
<netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; <gregkh-l3A5Bk7waGM@public.gmane.org>; "ML linux-kernel" <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; "Wang, Yong Y"
<yong.y.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org>; <arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>; "David S. Miller"
<davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>; "Christian Pellegrin" <chripell-VaTbYqLCNhc@public.gmane.org>; "Samuel Ortiz" <sameo-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Sent: Thursday, September 02, 2010 3:51 AM
Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35

> ...
> >>>>> - The values for the hw-specific bit-timing registers should be derived
> >>>>>   from the calculated values in "priv->can.bittiming":
> >>>>>
> >>>>>   http://lxr.linux.no/#linux+v2.6.35/include/linux/can/netlink.h#L17
> >>>>>
> >
> > I show current pch_can code below.
> >
> > +static int pch_set_bittiming(struct net_device *ndev)
> > +{
> > + struct pch_can_priv *priv = netdev_priv(ndev);
> > + struct pch_can_os *dev_can_os = priv->pch_can_os_p;
> > + const struct can_bittiming *bt = &priv->can.bittiming;
> >
> > Is the above TRUE, isn't it ?
>
> The code fragment looks good. In that function you should then *derive*
> the values of the bit-timing registers from the data fields of "bt". For
> the SJA1000, you find the code here:
>
> http://lxr.linux.no/#linux+v2.6.35/drivers/net/can/sja1000/sja1000.c#L202
>

I can't understand the your saying.
I think our can driver is implemented like your saying.

In function "pch_set_bittiming", get the value of the bit-timing registers from
the data fields of "bt" at "pch_can_set_baud_custom" or "pch_can_set_baud_simple".

Could you indicate in more detail ?


> >>>>> - The driver should handle state changes and communicate them to the
> >>>>>   user space via error messages, if possible.
> >>>>>
> > What's "state chage" mean ?
>
> Googling for "can bis states" returned:
>
>
http://www.softing.com/home/en/industrial-automation/products/can-bus/more-can-bus/error-handling/error-states.php?navanchor=3010510
>
> The CAN controller usually triggers an interrupt when the state changes,
> which allows the driver to track the CAN state and deliver that
> information to the user space.

I could understand your saying.
In our current code, our driver can detect state change, but doesn't notify to
can-core module or kennel protocol stack.
We will modify our driver to notify to these.

>
> >>>>> - The driver should report errors to the user space via error messages.
> >>>>>
> > Is the above mean using alloc_can_err_skb and set error info and notify to kernel with netif_rx ?
>
> Yes. Please search "Documentation/networking/can.txt" for "error frames"
> for further information.

I understand.
We will modify.

>
> >>>>> - Bus errors seem not to be handled properly.I'm missing can_bus_off().
> >>>>>   Does the controller recover from bus-off automatically?
> > No.
> > CAN driver recovers from Bus-off state.
>
> You mean: "It does *not" recover automatically"! Right?

I meant like below.
CAN-HW itself can't recover from bus-off state automatically.
Cooperate with CAN driver, CAN HW can do automatically.

>
> >
> >>>>>
> >>>>> - I see that the driver uses many TX and RX objects. How do you avoid
> >>>>>   out-of-order transmission and reception?
> >>>> What do you mean out-of-order RX and TX?
> >>>> Atom processor only supports in-order execution, and PCIe-based peripherals
> >>> can solve it with consumer-producer model. Actually IC designer will take care
> >>> of out-of-order PCIe CPLD transaction.
> >>>
> >>> I mean out-of-order transmission to or from the CAN bus. This is handled
> >>> by the CAN controller hardware. It has nothing to to with the processor.
> > Cannot avoid occurring rx or tx our-of-order.
>
> It is a *requirement* as Oliver already pointed out. It's easy to
> achieve if just one TX object is used but it might be tricky with more
> than one.

I agree with your indication.
We will modify so that our CAN driver has only one tx/rx each object.

Thanks, Ohtake(OKISemi)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
@ 2010-09-02  6:32                   ` Wolfgang Grandegger
  0 siblings, 0 replies; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-09-02  6:32 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: Andrew Chih Howe, Samuel Ortiz, ML netdev, gregkh, Wang, Yong Y,
	ML linux-kernel, socketcan-core, Morinaga, arjan,
	David S. Miller, Christian Pellegrin, Qi

On 09/02/2010 05:19 AM, Masayuki Ohtake wrote:
> ----- Original Message ----- 
> From: "Wolfgang Grandegger" <wg@grandegger.com>
> To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
> Cc: "Andrew Chih Howe" <andrew.chih.howe.khor@intel.com>; "Qi" <qi.wang@intel.com>; "ML netdev"
> <netdev@vger.kernel.org>; <gregkh@suse.de>; "ML linux-kernel" <linux-kernel@vger.kernel.org>; "Wang, Yong Y"
> <yong.y.wang@intel.com>; <socketcan-core@lists.berlios.de>; <arjan@linux.intel.com>; "David S. Miller"
> <davem@davemloft.net>; "Christian Pellegrin" <chripell@fsfe.org>; "Samuel Ortiz" <sameo@linux.intel.com>
> Sent: Thursday, September 02, 2010 3:51 AM
> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> 
>> ...
>>>>>>> - The values for the hw-specific bit-timing registers should be derived
>>>>>>>   from the calculated values in "priv->can.bittiming":
>>>>>>>
>>>>>>>   http://lxr.linux.no/#linux+v2.6.35/include/linux/can/netlink.h#L17
>>>>>>>
>>>
>>> I show current pch_can code below.
>>>
>>> +static int pch_set_bittiming(struct net_device *ndev)
>>> +{
>>> + struct pch_can_priv *priv = netdev_priv(ndev);
>>> + struct pch_can_os *dev_can_os = priv->pch_can_os_p;
>>> + const struct can_bittiming *bt = &priv->can.bittiming;
>>>
>>> Is the above TRUE, isn't it ?
>>
>> The code fragment looks good. In that function you should then *derive*
>> the values of the bit-timing registers from the data fields of "bt". For
>> the SJA1000, you find the code here:
>>
>> http://lxr.linux.no/#linux+v2.6.35/drivers/net/can/sja1000/sja1000.c#L202
>>
> 
> I can't understand the your saying.
> I think our can driver is implemented like your saying.
> 
> In function "pch_set_bittiming", get the value of the bit-timing registers from
> the data fields of "bt" at "pch_can_set_baud_custom" or "pch_can_set_baud_simple".

Please *remove* "pch_can_set_baud_custom" or "pch_can_set_baud_simple"
and use the fields of "const struct can_bittiming *bt" *directly*:

  /* Getting the appropriate register value. */
  reg_val = (((bt->brp & MSK_BITT_BRP) << BIT_BITT_BRP) |
	    ((bt->prop_seg + bt->phase_seg1 - 1) << BIT_BITT_TSEG1) |
            ...

> Could you indicate in more detail ?

Please have a closer look to the link mentioned above.

>>>>>>> - The driver should handle state changes and communicate them to the
>>>>>>>   user space via error messages, if possible.
>>>>>>>
>>> What's "state chage" mean ?
>>
>> Googling for "can bis states" returned:
>>
>>
> http://www.softing.com/home/en/industrial-automation/products/can-bus/more-can-bus/error-handling/error-states.php?navanchor=3010510
>>
>> The CAN controller usually triggers an interrupt when the state changes,
>> which allows the driver to track the CAN state and deliver that
>> information to the user space.
> 
> I could understand your saying.
> In our current code, our driver can detect state change, but doesn't notify to
> can-core module or kennel protocol stack.
> We will modify our driver to notify to these.

The code is your friend. Please have a more detailed look to the SJA1000
driver, e.g. search it for "state".

Wolfgang.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
@ 2010-09-02  6:32                   ` Wolfgang Grandegger
  0 siblings, 0 replies; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-09-02  6:32 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: Andrew Chih Howe, Samuel Ortiz, ML netdev, gregkh-l3A5Bk7waGM,
	ML linux-kernel, Wang, Yong Y,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Morinaga,
	arjan-VuQAYsv1563Yd54FQh9/CA, David S. Miller,
	Christian Pellegrin, Qi

On 09/02/2010 05:19 AM, Masayuki Ohtake wrote:
> ----- Original Message ----- 
> From: "Wolfgang Grandegger" <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
> To: "Masayuki Ohtake" <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
> Cc: "Andrew Chih Howe" <andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; "Qi" <qi.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; "ML netdev"
> <netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; <gregkh-l3A5Bk7waGM@public.gmane.org>; "ML linux-kernel" <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; "Wang, Yong Y"
> <yong.y.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org>; <arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>; "David S. Miller"
> <davem-fT/PcQaiUtIeIZ0/mPfg9Q@public.gmane.org>; "Christian Pellegrin" <chripell-VaTbYqLCNhc@public.gmane.org>; "Samuel Ortiz" <sameo-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> Sent: Thursday, September 02, 2010 3:51 AM
> Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
> 
>> ...
>>>>>>> - The values for the hw-specific bit-timing registers should be derived
>>>>>>>   from the calculated values in "priv->can.bittiming":
>>>>>>>
>>>>>>>   http://lxr.linux.no/#linux+v2.6.35/include/linux/can/netlink.h#L17
>>>>>>>
>>>
>>> I show current pch_can code below.
>>>
>>> +static int pch_set_bittiming(struct net_device *ndev)
>>> +{
>>> + struct pch_can_priv *priv = netdev_priv(ndev);
>>> + struct pch_can_os *dev_can_os = priv->pch_can_os_p;
>>> + const struct can_bittiming *bt = &priv->can.bittiming;
>>>
>>> Is the above TRUE, isn't it ?
>>
>> The code fragment looks good. In that function you should then *derive*
>> the values of the bit-timing registers from the data fields of "bt". For
>> the SJA1000, you find the code here:
>>
>> http://lxr.linux.no/#linux+v2.6.35/drivers/net/can/sja1000/sja1000.c#L202
>>
> 
> I can't understand the your saying.
> I think our can driver is implemented like your saying.
> 
> In function "pch_set_bittiming", get the value of the bit-timing registers from
> the data fields of "bt" at "pch_can_set_baud_custom" or "pch_can_set_baud_simple".

Please *remove* "pch_can_set_baud_custom" or "pch_can_set_baud_simple"
and use the fields of "const struct can_bittiming *bt" *directly*:

  /* Getting the appropriate register value. */
  reg_val = (((bt->brp & MSK_BITT_BRP) << BIT_BITT_BRP) |
	    ((bt->prop_seg + bt->phase_seg1 - 1) << BIT_BITT_TSEG1) |
            ...

> Could you indicate in more detail ?

Please have a closer look to the link mentioned above.

>>>>>>> - The driver should handle state changes and communicate them to the
>>>>>>>   user space via error messages, if possible.
>>>>>>>
>>> What's "state chage" mean ?
>>
>> Googling for "can bis states" returned:
>>
>>
> http://www.softing.com/home/en/industrial-automation/products/can-bus/more-can-bus/error-handling/error-states.php?navanchor=3010510
>>
>> The CAN controller usually triggers an interrupt when the state changes,
>> which allows the driver to track the CAN state and deliver that
>> information to the user space.
> 
> I could understand your saying.
> In our current code, our driver can detect state change, but doesn't notify to
> can-core module or kennel protocol stack.
> We will modify our driver to notify to these.

The code is your friend. Please have a more detailed look to the SJA1000
driver, e.g. search it for "state".

Wolfgang.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-08-11 13:04   ` Marc Kleine-Budde
@ 2010-09-13 12:07     ` Masayuki Ohtake
       [not found]       ` <005f01cb533e$5c21d530$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: Masayuki Ohtake @ 2010-09-13 12:07 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	gregkh-l3A5Bk7waGM, yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Morinaga,
	meego-dev-WXzIur8shnEAvxtiuMwx3w, arjan-VuQAYsv1563Yd54FQh9/CA,
	Wolfgang Grandegger

----- Original Message ----- 
From: "Marc Kleine-Budde" <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
To: "Masayuki Ohtak" <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Cc: <meego-dev-WXzIur8shnEAvxtiuMwx3w@public.gmane.org>; "Wolfgang Grandegger" <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>; <socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org>;
<netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; <andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <gregkh-l3A5Bk7waGM@public.gmane.org>; <arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>;
<qi.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <yong.y.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Sent: Wednesday, August 11, 2010 10:04 PM
Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35


Hi Marc,

> - Try to send patches directly with git send-email
In our network environment, we can't use send-email.

> - don't use global variables
I have modified so that our patch doesn't use global variable except module parameter.

> - don't use that "int handle", e.g.:
I have deleted.


> - get rid of the intermediate struct pch_can_msg:
>   Your data path is:
>   struct can_frame -> struct pch_can_msg -> registers
>   write from struct can_frame into registers directly
Since Topcliff CAN HW register assign is different from struct can_frame,
I think intermediate structure is necessary.

> - what's the purpose of "p_can_os->can_callback", call the function
>   directly from the interrupt handler
I have deleted

> - implement NAPI
Since Topcliff CAN HW register has only single rx buffer,
I think NAPI is unnecessary.

> - get rid of "1 << BIT_SHIFT_SIX" and friend,
>   use "1 << 6" or "BIT(6)" if you like defines
I have modified.

> - use defines to set bits in struct can_frame can_id
I have modified.

I will resubmit modified our CAN patch soon.

Thanks, Ohtake(OKISemi)

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]       ` <005f01cb533e$5c21d530$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
@ 2010-09-13 12:29         ` Marc Kleine-Budde
  2010-09-14  0:46           ` Masayuki Ohtake
  2010-09-13 15:22         ` Greg KH
  1 sibling, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2010-09-13 12:29 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	gregkh-l3A5Bk7waGM, yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Morinaga,
	meego-dev-WXzIur8shnEAvxtiuMwx3w, arjan-VuQAYsv1563Yd54FQh9/CA,
	Wolfgang Grandegger

On 09/13/2010 02:07 PM, Masayuki Ohtake wrote:
>> - Try to send patches directly with git send-email
> In our network environment, we can't use send-email.

that's bad...talk to your IT department :)

>> - don't use global variables
> I have modified so that our patch doesn't use global variable except module parameter.
>
>> - don't use that "int handle", e.g.:
> I have deleted.
>
>
>> - get rid of the intermediate struct pch_can_msg:
>>    Your data path is:
>>    struct can_frame ->  struct pch_can_msg ->  registers
>>    write from struct can_frame into registers directly
> Since Topcliff CAN HW register assign is different from struct can_frame,
> I think intermediate structure is necessary.

I don't see any reason for this. No other driver has an intermediate 
struct. Look at the other drivers.

>> - what's the purpose of "p_can_os->can_callback", call the function
>>    directly from the interrupt handler
> I have deleted
>
>> - implement NAPI
> Since Topcliff CAN HW register has only single rx buffer,
> I think NAPI is unnecessary.

Doesn't matter. Please try to implement it.

>> - get rid of "1<<  BIT_SHIFT_SIX" and friend,
>>    use "1<<  6" or "BIT(6)" if you like defines
> I have modified.
>
>> - use defines to set bits in struct can_frame can_id
> I have modified.
>
> I will resubmit modified our CAN patch soon.
>
> Thanks, Ohtake(OKISemi)

cheers, Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]       ` <005f01cb533e$5c21d530$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
  2010-09-13 12:29         ` Marc Kleine-Budde
@ 2010-09-13 15:22         ` Greg KH
  2010-09-14  8:48           ` Masayuki Ohtake
  1 sibling, 1 reply; 40+ messages in thread
From: Greg KH @ 2010-09-13 15:22 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
	Morinaga, meego-dev-WXzIur8shnEAvxtiuMwx3w,
	arjan-VuQAYsv1563Yd54FQh9/CA, Wolfgang Grandegger

On Mon, Sep 13, 2010 at 09:07:44PM +0900, Masayuki Ohtake wrote:
> > - Try to send patches directly with git send-email
> In our network environment, we can't use send-email.

Then try setting up a Linux server to handle email issues to prevent
patches from going through Exchange, which is known to corrupt patches.
Lots of other companies do this for Linux development, including
Microsoft :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-09-13 12:29         ` Marc Kleine-Budde
@ 2010-09-14  0:46           ` Masayuki Ohtake
  2010-09-14  7:08             ` Marc Kleine-Budde
       [not found]             ` <003a01cb53a6$4ca724d0$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
  0 siblings, 2 replies; 40+ messages in thread
From: Masayuki Ohtake @ 2010-09-14  0:46 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	gregkh-l3A5Bk7waGM, yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Morinaga,
	meego-dev-WXzIur8shnEAvxtiuMwx3w, arjan-VuQAYsv1563Yd54FQh9/CA,
	Wolfgang Grandegger

Hi Marc,

>>> - implement NAPI
>> Since Topcliff CAN HW register has only single rx buffer,
>> I think NAPI is unnecessary.

> Doesn't matter. Please try to implement it.

Our CAN driver must pull received data from CAN-HW rx buffer as fast as it can
so that the received data is not over-written by next received data.
In case of implemented with NAPI,
since NAPI has time-lagging after receiving first packet,
probability of over-written(discarded) buffer is to be high.
Thus, for our CAN HW, we should NOT implement with NAPI but normal "netif_rx".

Thanks, Ohtake(OKISemi)

----- Original Message ----- 
From: "Marc Kleine-Budde" <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>
To: "Masayuki Ohtake" <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Cc: <andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <qi.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; <gregkh-l3A5Bk7waGM@public.gmane.org>;
<yong.y.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org>; "Morinaga" <morinaga526-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>;
<meego-dev-WXzIur8shnEAvxtiuMwx3w@public.gmane.org>; <arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>; "Wolfgang Grandegger" <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
Sent: Monday, September 13, 2010 9:29 PM
Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35


> On 09/13/2010 02:07 PM, Masayuki Ohtake wrote:
> >> - Try to send patches directly with git send-email
> > In our network environment, we can't use send-email.
>
> that's bad...talk to your IT department :)
>
> >> - don't use global variables
> > I have modified so that our patch doesn't use global variable except module parameter.
> >
> >> - don't use that "int handle", e.g.:
> > I have deleted.
> >
> >
> >> - get rid of the intermediate struct pch_can_msg:
> >>    Your data path is:
> >>    struct can_frame ->  struct pch_can_msg ->  registers
> >>    write from struct can_frame into registers directly
> > Since Topcliff CAN HW register assign is different from struct can_frame,
> > I think intermediate structure is necessary.
>
> I don't see any reason for this. No other driver has an intermediate
> struct. Look at the other drivers.
>
> >> - what's the purpose of "p_can_os->can_callback", call the function
> >>    directly from the interrupt handler
> > I have deleted
> >
> >> - implement NAPI
> > Since Topcliff CAN HW register has only single rx buffer,
> > I think NAPI is unnecessary.
>
> Doesn't matter. Please try to implement it.
>
> >> - get rid of "1<<  BIT_SHIFT_SIX" and friend,
> >>    use "1<<  6" or "BIT(6)" if you like defines
> > I have modified.
> >
> >> - use defines to set bits in struct can_frame can_id
> > I have modified.
> >
> > I will resubmit modified our CAN patch soon.
> >
> > Thanks, Ohtake(OKISemi)
>
> cheers, Marc
>
> -- 
> Pengutronix e.K.                  | Marc Kleine-Budde           |
> Industrial Linux Solutions        | Phone: +49-231-2826-924     |
> Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
> Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |
>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-09-14  0:46           ` Masayuki Ohtake
@ 2010-09-14  7:08             ` Marc Kleine-Budde
       [not found]             ` <003a01cb53a6$4ca724d0$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
  1 sibling, 0 replies; 40+ messages in thread
From: Marc Kleine-Budde @ 2010-09-14  7:08 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: Wolfgang Grandegger, arjan, meego-dev, Morinaga, socketcan-core,
	yong.y.wang, gregkh, netdev, qi.wang, andrew.chih.howe.khor

[-- Attachment #1: Type: text/plain, Size: 1086 bytes --]

On 09/14/2010 02:46 AM, Masayuki Ohtake wrote:

>>>> - implement NAPI
>>> Since Topcliff CAN HW register has only single rx buffer,
>>> I think NAPI is unnecessary.
> 
>> Doesn't matter. Please try to implement it.
> 
> Our CAN driver must pull received data from CAN-HW rx buffer as fast as it can
> so that the received data is not over-written by next received data.
> In case of implemented with NAPI,
> since NAPI has time-lagging after receiving first packet,
> probability of over-written(discarded) buffer is to be high.
> Thus, for our CAN HW, we should NOT implement with NAPI but normal "netif_rx".

Okay, point taken.

Regarding the one and only rx buffer. Is it a driver or a hardware
limitation?

BTW: Are the datasheets of this CAN core available somewhere?

cheers Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-09-13 15:22         ` Greg KH
@ 2010-09-14  8:48           ` Masayuki Ohtake
       [not found]             ` <00ca01cb53e9$a50c1930$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: Masayuki Ohtake @ 2010-09-14  8:48 UTC (permalink / raw)
  To: Greg KH
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
	Morinaga, meego-dev-WXzIur8shnEAvxtiuMwx3w,
	arjan-VuQAYsv1563Yd54FQh9/CA, Wolfgang Grandegger

Hi Greg,

> Then try setting up a Linux server to handle email issues to prevent
> patches from going through Exchange, which is known to corrupt patches.
We want to use "git send-email".
I have already installed "git send-email".
What's else setting we need ?

Thanks, Ohtake(OKISemi)
----- Original Message ----- 
From: "Greg KH" <gregkh-l3A5Bk7waGM@public.gmane.org>
To: "Masayuki Ohtake" <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Cc: "Marc Kleine-Budde" <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>; <meego-dev-WXzIur8shnEAvxtiuMwx3w@public.gmane.org>; "Wolfgang Grandegger" <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>;
<socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org>; <netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; <andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>;
<qi.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <yong.y.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; "Morinaga" <morinaga526-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Sent: Tuesday, September 14, 2010 12:22 AM
Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35


> On Mon, Sep 13, 2010 at 09:07:44PM +0900, Masayuki Ohtake wrote:
> > > - Try to send patches directly with git send-email
> > In our network environment, we can't use send-email.
>
> Then try setting up a Linux server to handle email issues to prevent
> patches from going through Exchange, which is known to corrupt patches.
> Lots of other companies do this for Linux development, including
> Microsoft :)
>
> thanks,
>
> greg k-h
>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]             ` <00ca01cb53e9$a50c1930$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
@ 2010-09-14 13:10               ` Greg KH
  2010-09-15  1:21                 ` Masayuki Ohtake
  0 siblings, 1 reply; 40+ messages in thread
From: Greg KH @ 2010-09-14 13:10 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
	Morinaga, meego-dev-WXzIur8shnEAvxtiuMwx3w,
	arjan-VuQAYsv1563Yd54FQh9/CA, Wolfgang Grandegger

On Tue, Sep 14, 2010 at 05:48:43PM +0900, Masayuki Ohtake wrote:
> Hi Greg,
> 
> > Then try setting up a Linux server to handle email issues to prevent
> > patches from going through Exchange, which is known to corrupt patches.
> We want to use "git send-email".
> I have already installed "git send-email".
> What's else setting we need ?

You just need to use it then :)

Read the documention on how to do so, it is quite detailed.

good luck,

greg k-h

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-09-14 13:10               ` Greg KH
@ 2010-09-15  1:21                 ` Masayuki Ohtake
  0 siblings, 0 replies; 40+ messages in thread
From: Masayuki Ohtake @ 2010-09-15  1:21 UTC (permalink / raw)
  To: Greg KH
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
	Morinaga, meego-dev-WXzIur8shnEAvxtiuMwx3w,
	arjan-VuQAYsv1563Yd54FQh9/CA, Wolfgang Grandegger

Hi Greg,

We have already tried to execute "git send-email" for sending our patch.
Command "git send-email" returns success message,
but destination email client can't receive the patch.
We will continue analyzing so that "git send-email" works well.

Thanks, Ohtake(OKISemi)
----- Original Message ----- 
From: "Greg KH" <gregkh-l3A5Bk7waGM@public.gmane.org>
To: "Masayuki Ohtake" <masa-korg-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Cc: "Marc Kleine-Budde" <mkl-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org>; <meego-dev-WXzIur8shnEAvxtiuMwx3w@public.gmane.org>; "Wolfgang Grandegger" <wg-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>;
<socketcan-core-0fE9KPoRgkgATYTw5x5z8w@public.gmane.org>; <netdev-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>; <andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <arjan-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>;
<qi.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; <yong.y.wang-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>; "Morinaga" <morinaga526-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
Sent: Tuesday, September 14, 2010 10:10 PM
Subject: Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35


> On Tue, Sep 14, 2010 at 05:48:43PM +0900, Masayuki Ohtake wrote:
> > Hi Greg,
> >
> > > Then try setting up a Linux server to handle email issues to prevent
> > > patches from going through Exchange, which is known to corrupt patches.
> > We want to use "git send-email".
> > I have already installed "git send-email".
> > What's else setting we need ?
>
> You just need to use it then :)
>
> Read the documention on how to do so, it is quite detailed.
>
> good luck,
>
> greg k-h
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]             ` <003a01cb53a6$4ca724d0$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
@ 2010-09-15  7:42               ` Wolfgang Grandegger
       [not found]                 ` <4C9078D3.50300-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
  0 siblings, 1 reply; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-09-15  7:42 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	gregkh-l3A5Bk7waGM, yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w, Marc Kleine-Budde,
	Morinaga, meego-dev-WXzIur8shnEAvxtiuMwx3w,
	arjan-VuQAYsv1563Yd54FQh9/CA

On 09/14/2010 02:46 AM, Masayuki Ohtake wrote:
> Hi Marc,
> 
>>>> - implement NAPI
>>> Since Topcliff CAN HW register has only single rx buffer,
>>> I think NAPI is unnecessary.
> 
>> Doesn't matter. Please try to implement it.
> 
> Our CAN driver must pull received data from CAN-HW rx buffer as fast as it can
> so that the received data is not over-written by next received data.
> In case of implemented with NAPI,
> since NAPI has time-lagging after receiving first packet,
> probability of over-written(discarded) buffer is to be high.
> Thus, for our CAN HW, we should NOT implement with NAPI but normal "netif_rx".

True, if you just use one RX-Object. But it just helps a little bit and
it would be much better to use the buffering on RX messages in the CAN
controller hardware, either by using more than one RX object, or
combining RX objects to a FIFO, or whatever your CAN controller supports.

Wolfgang.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
       [not found]                 ` <4C9078D3.50300-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
@ 2010-09-15  9:42                   ` Oliver Hartkopp
  2010-09-15 10:55                     ` Wolfgang Grandegger
  0 siblings, 1 reply; 40+ messages in thread
From: Oliver Hartkopp @ 2010-09-15  9:42 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: andrew.chih.howe.khor-ral2JQCrhuEAvxtiuMwx3w,
	socketcan-core-0fE9KPoRgkgATYTw5x5z8w,
	qi.wang-ral2JQCrhuEAvxtiuMwx3w, netdev-u79uwXL29TY76Z2rM5mHXA,
	gregkh-l3A5Bk7waGM, yong.y.wang-ral2JQCrhuEAvxtiuMwx3w,
	Masayuki Ohtake, Marc Kleine-Budde, Morinaga,
	meego-dev-WXzIur8shnEAvxtiuMwx3w, arjan-VuQAYsv1563Yd54FQh9/CA

On 15.09.2010 09:42, Wolfgang Grandegger wrote:
> On 09/14/2010 02:46 AM, Masayuki Ohtake wrote:
>> Hi Marc,
>>
>>>>> - implement NAPI
>>>> Since Topcliff CAN HW register has only single rx buffer,
>>>> I think NAPI is unnecessary.
>>
>>> Doesn't matter. Please try to implement it.
>>
>> Our CAN driver must pull received data from CAN-HW rx buffer as fast as it can
>> so that the received data is not over-written by next received data.
>> In case of implemented with NAPI,
>> since NAPI has time-lagging after receiving first packet,
>> probability of over-written(discarded) buffer is to be high.
>> Thus, for our CAN HW, we should NOT implement with NAPI but normal "netif_rx".
> 
> True, if you just use one RX-Object. But it just helps a little bit and
> it would be much better to use the buffering on RX messages in the CAN
> controller hardware, either by using more than one RX object, or
> combining RX objects to a FIFO, or whatever your CAN controller supports.

Good point!

As long as the order of the received CAN frames is not shuffled (-> plain FIFO
behaviour) using more than one RX buffer is a good idea.

Just a remark:

During the IDF the informations about the Topcliff Controller Hub have been
reworked, so that some of the documentation became available for the public:

http://edc.intel.com/Platforms/Atom-E6xx/#hardware

Especially the Datasheet for the Platform Controller Hub EG20T can be found:

http://download.intel.com/embedded/chipsets/datasheet/324211.pdf

In chapter 13 there are some details about the CAN controller.

Regards,
Oliver

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-09-15  9:42                   ` Oliver Hartkopp
@ 2010-09-15 10:55                     ` Wolfgang Grandegger
  2010-09-15 12:04                       ` Marc Kleine-Budde
  0 siblings, 1 reply; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-09-15 10:55 UTC (permalink / raw)
  To: Oliver Hartkopp
  Cc: andrew.chih.howe.khor, socketcan-core, qi.wang, netdev, gregkh,
	yong.y.wang, Masayuki Ohtake, Marc Kleine-Budde, Morinaga,
	meego-dev, arjan

On 09/15/2010 11:42 AM, Oliver Hartkopp wrote:
> On 15.09.2010 09:42, Wolfgang Grandegger wrote:
>> On 09/14/2010 02:46 AM, Masayuki Ohtake wrote:
>>> Hi Marc,
>>>
>>>>>> - implement NAPI
>>>>> Since Topcliff CAN HW register has only single rx buffer,
>>>>> I think NAPI is unnecessary.
>>>
>>>> Doesn't matter. Please try to implement it.
>>>
>>> Our CAN driver must pull received data from CAN-HW rx buffer as fast as it can
>>> so that the received data is not over-written by next received data.
>>> In case of implemented with NAPI,
>>> since NAPI has time-lagging after receiving first packet,
>>> probability of over-written(discarded) buffer is to be high.
>>> Thus, for our CAN HW, we should NOT implement with NAPI but normal "netif_rx".
>>
>> True, if you just use one RX-Object. But it just helps a little bit and
>> it would be much better to use the buffering on RX messages in the CAN
>> controller hardware, either by using more than one RX object, or
>> combining RX objects to a FIFO, or whatever your CAN controller supports.
> 
> Good point!
> 
> As long as the order of the received CAN frames is not shuffled (-> plain FIFO
> behaviour) using more than one RX buffer is a good idea.
> 
> Just a remark:
> 
> During the IDF the informations about the Topcliff Controller Hub have been
> reworked, so that some of the documentation became available for the public:
> 
> http://edc.intel.com/Platforms/Atom-E6xx/#hardware
> 
> Especially the Datasheet for the Platform Controller Hub EG20T can be found:
> 
> http://download.intel.com/embedded/chipsets/datasheet/324211.pdf
> 
> In chapter 13 there are some details about the CAN controller.

Ah, thanks for the link. The CAN controller seems then to be similar to
the OKI MSM9225B.

Wolfgang.


^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-09-15 10:55                     ` Wolfgang Grandegger
@ 2010-09-15 12:04                       ` Marc Kleine-Budde
  2010-09-15 12:11                         ` Wolfgang Grandegger
  0 siblings, 1 reply; 40+ messages in thread
From: Marc Kleine-Budde @ 2010-09-15 12:04 UTC (permalink / raw)
  To: Wolfgang Grandegger
  Cc: Oliver Hartkopp, andrew.chih.howe.khor, socketcan-core, qi.wang,
	netdev, gregkh, yong.y.wang, Masayuki Ohtake, Morinaga,
	meego-dev, arjan

[-- Attachment #1: Type: text/plain, Size: 1109 bytes --]

On 09/15/2010 12:55 PM, Wolfgang Grandegger wrote:
>> Just a remark:
>>
>> During the IDF the informations about the Topcliff Controller Hub have been
>> reworked, so that some of the documentation became available for the public:
>>
>> http://edc.intel.com/Platforms/Atom-E6xx/#hardware
>>
>> Especially the Datasheet for the Platform Controller Hub EG20T can be found:
>>
>> http://download.intel.com/embedded/chipsets/datasheet/324211.pdf
>>
>> In chapter 13 there are some details about the CAN controller.
> 
> Ah, thanks for the link. The CAN controller seems then to be similar to
> the OKI MSM9225B.

According to the datasheet for the msm9225 I found, the chip has got an
8 bit interface (mmap'ed or spi). The Intel is 32 bit based (most, maybe
all, upper 16 bit are marked as reserverd).

cheers, Marc
-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35
  2010-09-15 12:04                       ` Marc Kleine-Budde
@ 2010-09-15 12:11                         ` Wolfgang Grandegger
  0 siblings, 0 replies; 40+ messages in thread
From: Wolfgang Grandegger @ 2010-09-15 12:11 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Oliver Hartkopp, andrew.chih.howe.khor, socketcan-core, qi.wang,
	netdev, gregkh, yong.y.wang, Masayuki Ohtake, Morinaga,
	meego-dev, arjan

On 09/15/2010 02:04 PM, Marc Kleine-Budde wrote:
> On 09/15/2010 12:55 PM, Wolfgang Grandegger wrote:
>>> Just a remark:
>>>
>>> During the IDF the informations about the Topcliff Controller Hub have been
>>> reworked, so that some of the documentation became available for the public:
>>>
>>> http://edc.intel.com/Platforms/Atom-E6xx/#hardware
>>>
>>> Especially the Datasheet for the Platform Controller Hub EG20T can be found:
>>>
>>> http://download.intel.com/embedded/chipsets/datasheet/324211.pdf
>>>
>>> In chapter 13 there are some details about the CAN controller.
>>
>> Ah, thanks for the link. The CAN controller seems then to be similar to
>> the OKI MSM9225B.
> 
> According to the datasheet for the msm9225 I found, the chip has got an
> 8 bit interface (mmap'ed or spi). The Intel is 32 bit based (most, maybe
> all, upper 16 bit are marked as reserverd).

I said *similar*, especially in respect to ability of combining RX
message objects to a fifo.

Wolfgang.


^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2010-09-15 12:10 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-08-11  0:25 [MeeGo-Dev][PATCH] Topcliff: Update PCH_CAN driver to 2.6.35 Masayuki Ohtak
     [not found] ` <4C61EDE5.4030505-ECg8zkTtlr0C6LszWs/t0g@public.gmane.org>
2010-08-11 10:37   ` Daniel Baluta
2010-08-12  1:42     ` Wang, Qi
2010-08-12  2:04       ` Greg KH
2010-08-12  2:13         ` Wang, Qi
     [not found]         ` <20100812020414.GD14121-l3A5Bk7waGM@public.gmane.org>
2010-08-12  6:25           ` Oliver Hartkopp
2010-08-12  6:29             ` Wang, Qi
2010-08-12  2:39       ` Masayuki Ohtake
     [not found]       ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA26EB-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2010-08-12  5:17         ` Daniel Baluta
2010-08-12  9:03         ` Wolfgang Grandegger
2010-08-13  0:23           ` Wang, Qi
     [not found]             ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA2AB1-QQHDSDV1ERZpB2pF5aRoyrfspsVTdybXVpNB7YpNyf8@public.gmane.org>
2010-08-13  6:11               ` Daniel Baluta
2010-08-13 10:58               ` Wolfgang Grandegger
2010-08-20  6:01                 ` Masayuki Ohtake
     [not found]                   ` <000f01cb402d$34b675b0$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
2010-08-20  7:59                     ` Wolfgang Grandegger
2010-08-20  8:37                       ` Masayuki Ohtake
2010-08-11 12:31   ` Wolfgang Grandegger
     [not found]     ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA26CC@shsmsx501.ccr.corp.intel.com>
     [not found]       ` <4C63B6C9.5050804@grandegger.com>
     [not found]         ` <D5AB6E638E5A3E4B8F4406B113A5A19A28EA29DF@shsmsx501.ccr.corp.intel.com>
2010-09-01  7:45           ` Masayuki Ohtake
2010-09-01 17:04             ` out-of-order tx objects - was " Oliver Hartkopp
2010-09-01 17:04               ` Oliver Hartkopp
2010-09-01 18:51             ` Wolfgang Grandegger
2010-09-01 18:51               ` Wolfgang Grandegger
2010-09-02  3:19               ` Masayuki Ohtake
2010-09-02  3:19                 ` Masayuki Ohtake
2010-09-02  6:32                 ` Wolfgang Grandegger
2010-09-02  6:32                   ` Wolfgang Grandegger
2010-08-11 13:04   ` Marc Kleine-Budde
2010-09-13 12:07     ` Masayuki Ohtake
     [not found]       ` <005f01cb533e$5c21d530$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
2010-09-13 12:29         ` Marc Kleine-Budde
2010-09-14  0:46           ` Masayuki Ohtake
2010-09-14  7:08             ` Marc Kleine-Budde
     [not found]             ` <003a01cb53a6$4ca724d0$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
2010-09-15  7:42               ` Wolfgang Grandegger
     [not found]                 ` <4C9078D3.50300-5Yr1BZd7O62+XT7JhA+gdA@public.gmane.org>
2010-09-15  9:42                   ` Oliver Hartkopp
2010-09-15 10:55                     ` Wolfgang Grandegger
2010-09-15 12:04                       ` Marc Kleine-Budde
2010-09-15 12:11                         ` Wolfgang Grandegger
2010-09-13 15:22         ` Greg KH
2010-09-14  8:48           ` Masayuki Ohtake
     [not found]             ` <00ca01cb53e9$a50c1930$66f8800a-a06+6cuVnkTSQfdrb5gaxUEOCMrvLtNR@public.gmane.org>
2010-09-14 13:10               ` Greg KH
2010-09-15  1:21                 ` Masayuki Ohtake

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.