All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Topcliff PHUB: Generate PacketHub driver
@ 2010-06-07 12:39 Masayuki Ohtak
  2010-06-07 15:05 ` Alan Cox
  2010-06-14 12:09 ` Masayuki Ohtak
  0 siblings, 2 replies; 45+ messages in thread
From: Masayuki Ohtak @ 2010-06-07 12:39 UTC (permalink / raw)
  To: Alan Cox; +Cc: Masayuki Ohtake, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Alan,

We have modified for the following your indication.
Please confirm.

> > +/*!

> > + * @ingroup	PHUB_PCILayerAPI

> > + * @fn		static void __exit pch_phub_pci_exit(void)

> > + * @brief	Provides the functionality of exiting the module

> > + * */



> Can we please do something about all this stuff first so the code is

> easier to review by those not familiar with the kernel format.



> I sent a bit of code out last time that did most of the work



> Alan


Thanks.
Masayuki Ohtake

Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
 linux-2.6.33.1/drivers/char/Kconfig             |   20 +
 linux-2.6.33.1/drivers/char/Makefile            |    4 +
 linux-2.6.33.1/drivers/char/pch_phub/Makefile   |   11 +
 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c | 1232 +++++++++++++++++++++++
 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h |   96 ++
 5 files changed, 1363 insertions(+), 0 deletions(-)
 create mode 100644 linux-2.6.33.1/drivers/char/pch_phub/Makefile
 create mode 100755 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c
 create mode 100755 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h

diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e023682..16a8334 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -4,6 +4,26 @@
 
 menu "Character devices"
 
+config PCH_IEEE1588
+	tristate "PCH IEEE1588"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  PCH IEEE1588 Host controller.
+
+config PCH_PHUB
+        tristate "PCH PHUB"
+        depends on PCI
+        help
+          If you say yes to this option, support will be included for the
+          PCH Packet Hub Host controller.
+
+config PCH_CAN_PCLK_50MHZ
+	bool "CAN PCLK 50MHz"
+	depends on PCH_PHUB
+        help
+          If you say yes to this option, clock is set to 50MHz.(For CAN control)
+
 config VT
 	bool "Virtual terminal" if EMBEDDED
 	depends on !S390
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index f957edf..dc092d0 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -111,6 +111,10 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
 obj-$(CONFIG_JS_RTC)		+= js-rtc.o
 js-rtc-y = rtc.o
 
+obj-$(CONFIG_PCH_IEEE1588)		+= pch_ieee1588/
+
+obj-$(CONFIG_PCH_PHUB)	+= pch_phub/
+
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c
 
diff --git a/drivers/char/pch_phub/Makefile b/drivers/char/pch_phub/Makefile
new file mode 100644
index 0000000..bfe2a2b
--- /dev/null
+++ b/drivers/char/pch_phub/Makefile
@@ -0,0 +1,11 @@
+ifeq ($(CONFIG_PHUB_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_PCH_PHUB) += pch_phub_drv.o
+#to set CAN clock to 50Mhz
+ifdef CONFIG_PCH_CAN_PCLK_50MHZ
+EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
+endif
+
+pch_phub_drv-objs := pch_phub.o
diff --git a/drivers/char/pch_phub/pch_phub.c b/drivers/char/pch_phub/pch_phub.c
new file mode 100755
index 0000000..da5b92e
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.c
@@ -0,0 +1,1232 @@
+/*!
+ * @file pch_phub.c
+ * @brief Provides all the implementation of the interfaces pertaining to
+ *		the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+/* includes */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+
+#include "pch_phub.h"
+
+/*--------------------------------------------
+	macros
+--------------------------------------------*/
+/* Status Register offset */
+#define PHUB_STATUS (0x00)
+/* Control Register offset */
+#define PHUB_CONTROL (0x04)
+/* Time out value for Status Register */
+#define PHUB_TIMEOUT (0x05)
+/* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_ENABLE (0x01)
+/* Disabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE (0x00)
+/* ROM data area start address offset */
+#define PCH_PHUB_ROM_START_ADDR (0x14)
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG (128)
+
+#define PCI_DEVICE_ID_PCH1_PHUB (0x8801)
+
+#define PCH_MINOR_NOS (1)
+#define CLKCFG_CAN_50MHZ (0x12000000)
+#define CLKCFG_CANCLK_MASK (0xFF000000)
+
+#define MODULE_NAME "pch_phub"
+
+#define PCH_READ_REG(a)	ioread32((pch_phub_base_address + a))
+
+#define PCH_WRITE_REG(a, b)	iowrite32(a, (pch_phub_base_address + b))
+
+/*--------------------------------------------
+	global variables
+--------------------------------------------*/
+struct pch_phub_reg {
+	u32 phub_id_reg;		/* PHUB_ID register val */
+	u32 q_pri_val_reg;		/* QUEUE_PRI_VAL register val */
+	u32 rc_q_maxsize_reg;	/* RC_QUEUE_MAXSIZE register val */
+	u32 bri_q_maxsize_reg;	/* BRI_QUEUE_MAXSIZE register val */
+	u32 comp_resp_timeout_reg;	/* COMP_RESP_TIMEOUT register val */
+	u32 bus_slave_control_reg;	/* BUS_SLAVE_CONTROL_REG register val */
+	u32 deadlock_avoid_type_reg; /* DEADLOCK_AVOID_TYPE register val */
+	u32 intpin_reg_wpermit_reg0; /* INTPIN_REG_WPERMIT register 0 val */
+	u32 intpin_reg_wpermit_reg1; /* INTPIN_REG_WPERMIT register 1 val */
+	u32 intpin_reg_wpermit_reg2; /* INTPIN_REG_WPERMIT register 2 val */
+	u32 intpin_reg_wpermit_reg3; /* INTPIN_REG_WPERMIT register 3 val */
+	/* INT_REDUCE_CONTROL registers val */
+	u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+#ifdef PCH_CAN_PCLK_50MHZ
+	u32 clkcfg_reg;		/* CLK CFG register val */
+#endif
+} g_pch_phub_reg;
+
+s32 pch_phub_opencount;	/* check whether opened or not */
+u32 pch_phub_base_address;
+u32 pch_phub_extrom_base_address;
+s32 pch_phub_suspended;
+
+struct device *dev_dbg;
+
+DEFINE_SPINLOCK(pch_phub_lock);	/* for spin lock */
+
+/**
+ * file_operations structure initialization
+ */
+const struct file_operations pch_phub_fops = {
+	.owner = THIS_MODULE,
+	.open = pch_phub_open,
+	.release = pch_phub_release,
+	.ioctl = pch_phub_ioctl,
+};
+
+/* ToDo: major number allocation via module parameter */
+static dev_t pch_phub_dev_no;
+static int pch_phub_major_no;
+static struct cdev pch_phub_dev;
+
+
+/*--------------------------------------------
+	exported function prototypes
+--------------------------------------------*/
+static int __devinit pch_phub_probe(struct pci_dev *pdev, const
+				       struct pci_device_id *id);
+static void __devexit pch_phub_remove(struct pci_dev *pdev);
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
+static int pch_phub_resume(struct pci_dev *pdev);
+
+/*--------------------------------------------
+	structures
+--------------------------------------------*/
+static struct pci_device_id pch_phub_pcidev_id[] = {
+
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+	{0,}
+};
+
+
+static struct pci_driver pch_phub_driver = {
+	.name = "pch_phub",
+	.id_table = pch_phub_pcidev_id,
+	.probe = pch_phub_probe,
+	.remove = __devexit_p(pch_phub_remove),
+#ifdef CONFIG_PM
+	.suspend = pch_phub_suspend,
+	.resume = pch_phub_resume
+#endif
+};
+
+static int __init pch_phub_pci_init(void);
+static void __exit pch_phub_pci_exit(void);
+
+MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
+MODULE_LICENSE("GPL");
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);
+
+
+/*--------------------------------------------
+	functions implementations
+--------------------------------------------*/
+/** pch_phub_read_modify_write_reg - Implements the functionality of reading,
+ * 						modifying and writing register.
+ *  @reg_addr_offset:  Contains the register offset address value
+ *  @data:             Contains the writing value
+ *  @mask:             Contains the mask value
+ */
+void pch_phub_read_modify_write_reg(unsigned long reg_addr_offset,
+				       unsigned long data, unsigned long mask)
+{
+	unsigned long reg_addr = pch_phub_base_address + reg_addr_offset;
+	iowrite32(((ioread32((void __iomem *)reg_addr) & ~mask)) | data,
+			(void __iomem *)reg_addr);
+	return;
+}
+
+
+/** pch_phub_save_reg_conf - saves register configuration
+ */
+void pch_phub_save_reg_conf(void)
+{
+	u32 i = 0;
+
+	dev_dbg(dev_dbg, "pch_phub_save_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	g_pch_phub_reg.phub_id_reg = PCH_READ_REG(PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	g_pch_phub_reg.q_pri_val_reg = PCH_READ_REG(PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	g_pch_phub_reg.rc_q_maxsize_reg =
+	    PCH_READ_REG(PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	g_pch_phub_reg.bri_q_maxsize_reg =
+	    PCH_READ_REG(PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	g_pch_phub_reg.comp_resp_timeout_reg =
+	    PCH_READ_REG(PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	g_pch_phub_reg.bus_slave_control_reg =
+	    PCH_READ_REG(PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	g_pch_phub_reg.deadlock_avoid_type_reg =
+	    PCH_READ_REG(PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	g_pch_phub_reg.intpin_reg_wpermit_reg0 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	g_pch_phub_reg.intpin_reg_wpermit_reg1 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	g_pch_phub_reg.intpin_reg_wpermit_reg2 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	g_pch_phub_reg.intpin_reg_wpermit_reg3 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(dev_dbg, "pch_phub_save_reg_conf : "
+		"g_pch_phub_reg.phub_id_reg=%x, "
+		"g_pch_phub_reg.q_pri_val_reg=%x, "
+		"g_pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"g_pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"g_pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"g_pch_phub_reg.bus_slave_control_reg=%x, "
+		"g_pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		g_pch_phub_reg.phub_id_reg,
+		g_pch_phub_reg.q_pri_val_reg,
+		g_pch_phub_reg.rc_q_maxsize_reg,
+		g_pch_phub_reg.bri_q_maxsize_reg,
+		g_pch_phub_reg.comp_resp_timeout_reg,
+		g_pch_phub_reg.bus_slave_control_reg,
+		g_pch_phub_reg.deadlock_avoid_type_reg,
+		g_pch_phub_reg.intpin_reg_wpermit_reg0,
+		g_pch_phub_reg.intpin_reg_wpermit_reg1,
+		g_pch_phub_reg.intpin_reg_wpermit_reg2,
+		g_pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL registers */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		g_pch_phub_reg.int_reduce_control_reg[i] =
+		    PCH_READ_REG(
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(dev_dbg, "pch_phub_save_reg_conf : "
+			"g_pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, g_pch_phub_reg.int_reduce_control_reg[i]);
+	}
+#ifdef PCH_CAN_PCLK_50MHZ
+	/* save clk cfg register */
+	g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
+#endif
+	return;
+}
+
+/** pch_phub_restore_reg_conf - restore register configuration
+ */
+
+void pch_phub_restore_reg_conf(void)
+{
+	u32 i = 0;
+
+	dev_dbg(dev_dbg, "pch_phub_restore_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	PCH_WRITE_REG(g_pch_phub_reg.phub_id_reg, PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	PCH_WRITE_REG(g_pch_phub_reg.q_pri_val_reg, PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	PCH_WRITE_REG(g_pch_phub_reg.rc_q_maxsize_reg,
+			PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	PCH_WRITE_REG(g_pch_phub_reg.bri_q_maxsize_reg,
+			PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	PCH_WRITE_REG(g_pch_phub_reg.comp_resp_timeout_reg,
+			PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	PCH_WRITE_REG(g_pch_phub_reg.bus_slave_control_reg,
+			PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	PCH_WRITE_REG(g_pch_phub_reg.deadlock_avoid_type_reg,
+			PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	PCH_WRITE_REG(g_pch_phub_reg.intpin_reg_wpermit_reg0,
+			PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	PCH_WRITE_REG(g_pch_phub_reg.intpin_reg_wpermit_reg1,
+			PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	PCH_WRITE_REG(g_pch_phub_reg.intpin_reg_wpermit_reg2,
+			PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	PCH_WRITE_REG(g_pch_phub_reg.intpin_reg_wpermit_reg3,
+			PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(dev_dbg, "pch_phub_save_reg_conf : "
+		"g_pch_phub_reg.phub_id_reg=%x, "
+		"g_pch_phub_reg.q_pri_val_reg=%x, "
+		"g_pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"g_pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"g_pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"g_pch_phub_reg.bus_slave_control_reg=%x, "
+		"g_pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		g_pch_phub_reg.phub_id_reg,
+		g_pch_phub_reg.q_pri_val_reg,
+		g_pch_phub_reg.rc_q_maxsize_reg,
+		g_pch_phub_reg.bri_q_maxsize_reg,
+		g_pch_phub_reg.comp_resp_timeout_reg,
+		g_pch_phub_reg.bus_slave_control_reg,
+		g_pch_phub_reg.deadlock_avoid_type_reg,
+		g_pch_phub_reg.intpin_reg_wpermit_reg0,
+		g_pch_phub_reg.intpin_reg_wpermit_reg1,
+		g_pch_phub_reg.intpin_reg_wpermit_reg2,
+		g_pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL register */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		PCH_WRITE_REG(g_pch_phub_reg.int_reduce_control_reg[i],
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(dev_dbg, "pch_phub_save_reg_conf : "
+			"g_pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, g_pch_phub_reg.int_reduce_control_reg[i]);
+	}
+
+#ifdef PCH_CAN_PCLK_50MHZ
+	/*restore the clock config reg */
+	PCH_WRITE_REG(g_pch_phub_reg.clkcfg_reg, CLKCFG_REG_OFFSET);
+#endif
+
+	return;
+}
+
+/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
+ *  									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+int pch_phub_read_serial_rom(unsigned long offset_address, unsigned char *data)
+{
+	unsigned long mem_addr = pch_phub_extrom_base_address + offset_address;
+
+	dev_dbg(dev_dbg,
+		"pch_phub_read_serial_rom:mem_addr=0x%08x\n", (u32)mem_addr);
+	*data = ioread8((void __iomem *)mem_addr);
+
+	return 0;
+}
+
+/** pch_phub_write_serial_rom - Implements the functionality of writing Serial
+ *  									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+int pch_phub_write_serial_rom(unsigned long offset_address, unsigned char data)
+{
+	int retval = 0;
+	unsigned long mem_addr = pch_phub_extrom_base_address + offset_address;
+	int i = 0;
+	unsigned long word_data = 0;
+
+	dev_dbg(dev_dbg,
+		"pch_phub_write_serial_rom:mem_addr=0x%08x\n", (u32)mem_addr);
+	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE, (void __iomem *)
+			(pch_phub_extrom_base_address + PHUB_CONTROL));
+
+	word_data = ioread32((void __iomem *)(mem_addr & 0xFFFFFFFC));
+	dev_dbg(dev_dbg, "word_data=0x%08x  data=0x%02x\n",
+		 (u32)word_data, data);
+	switch (mem_addr % 4) {
+	case 0:
+		word_data &= 0xFFFFFF00;
+		iowrite32((word_data | (unsigned long)data),
+				(void __iomem *)(mem_addr & 0xFFFFFFFC));
+		break;
+	case 1:
+		word_data &= 0xFFFF00FF;
+		iowrite32((word_data | ((unsigned long)data << 8)),
+				(void __iomem *)(mem_addr & 0xFFFFFFFC));
+		break;
+	case 2:
+		word_data &= 0xFF00FFFF;
+		iowrite32((word_data | ((unsigned long)data << 16)),
+				(void __iomem *)(mem_addr & 0xFFFFFFFC));
+		break;
+	case 3:
+		word_data &= 0x00FFFFFF;
+		iowrite32((word_data | ((unsigned long)data << 24)),
+				(void __iomem *)(mem_addr & 0xFFFFFFFC));
+		break;
+	}
+	while (0x00 !=
+	       ioread8((void __iomem *)
+			 (pch_phub_extrom_base_address + PHUB_STATUS))) {
+		msleep(1);
+		if (PHUB_TIMEOUT == i) {
+			retval = -EPERM;
+			break;
+		}
+		i++;
+	}
+
+	iowrite32(PCH_PHUB_ROM_WRITE_DISABLE, (void __iomem *)
+			(pch_phub_extrom_base_address + PHUB_CONTROL));
+
+	return retval;
+}
+
+/** pch_phub_read_serial_rom_val - Implements the functionality of reading
+ *  							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+int pch_phub_read_serial_rom_val(unsigned long offset_address,
+				    unsigned char *data)
+{
+	int retval = 0;
+	unsigned long mem_addr;
+
+	mem_addr = (offset_address / 4 * 8) + 3 -
+			(offset_address % 4) + PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_read_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_write_serial_rom_val - Implements the functionality of writing
+ *  							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+int pch_phub_write_serial_rom_val(unsigned long offset_address,
+				     unsigned char data)
+{
+	int retval = 0;
+	unsigned long mem_addr;
+
+	mem_addr =
+	    (offset_address / 4 * 8) + 3 - (offset_address % 4) +
+	    PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_write_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ *  						for Gigabit Ethernet MAC address
+ */
+int pch_phub_gbe_serial_rom_conf(void)
+{
+	int retval = 0;
+
+	retval |= pch_phub_write_serial_rom(0x0b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x0a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x09, 0x01);
+	retval |= pch_phub_write_serial_rom(0x08, 0x02);
+
+	retval |= pch_phub_write_serial_rom(0x0f, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0e, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0d, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0c, 0x80);
+
+	retval |= pch_phub_write_serial_rom(0x13, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x12, 0x10);
+	retval |= pch_phub_write_serial_rom(0x11, 0x01);
+	retval |= pch_phub_write_serial_rom(0x10, 0x18);
+
+	retval |= pch_phub_write_serial_rom(0x1b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x1a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x19, 0x01);
+	retval |= pch_phub_write_serial_rom(0x18, 0x19);
+
+	retval |= pch_phub_write_serial_rom(0x23, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x22, 0x10);
+	retval |= pch_phub_write_serial_rom(0x21, 0x01);
+	retval |= pch_phub_write_serial_rom(0x20, 0x3a);
+
+	retval |= pch_phub_write_serial_rom(0x27, 0x01);
+	retval |= pch_phub_write_serial_rom(0x26, 0x00);
+	retval |= pch_phub_write_serial_rom(0x25, 0x00);
+	retval |= pch_phub_write_serial_rom(0x24, 0x00);
+
+	return retval;
+}
+/** pch_phub_read_gbe_mac_addr - Contains the Gigabit Ethernet MAC address
+ *  								offset value
+ *  @offset_address: Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+int pch_phub_read_gbe_mac_addr(unsigned long offset_address,
+				  unsigned char *data)
+{
+	int retval = 0;
+
+	retval = pch_phub_read_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_write_gbe_mac_addr - Write MAC address
+ *  @offset_address: Contains the Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+int pch_phub_write_gbe_mac_addr(unsigned long offset_address,
+				   unsigned char data)
+{
+	int retval = 0;
+
+	retval = pch_phub_gbe_serial_rom_conf();
+	retval |= pch_phub_write_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_open - Implements the Initializing and opening of the Packet Hub
+									 module.
+ *  @inode: Contains the reference of the inode structure
+ *  @file: Contains the reference of the file structure
+ */
+int pch_phub_open(struct inode *inode, struct file *file)
+{
+	int ret;
+
+	spin_lock(&pch_phub_lock);
+	dev_dbg(dev_dbg, "pch_phub_open : open count value = %d",
+		  pch_phub_opencount);
+	if (pch_phub_opencount) {
+		dev_dbg(dev_dbg, "pch_phub_open :  device already opened\n");
+		ret = -EBUSY;
+	} else {
+		pch_phub_opencount++;
+		ret = 0;
+	}
+	spin_unlock(&pch_phub_lock);
+
+	dev_dbg(dev_dbg, "pch_phub_open returns=%d\n", ret);
+	return ret;
+}
+
+/** pch_phub_release - Implements the release functionality of the Packet Hub
+ *  									 module.
+ *  @inode: Contains the reference of the inode structure
+ *  @file: Contains the reference of the file structure
+ */
+int pch_phub_release(struct inode *inode, struct file *file)
+{
+	spin_lock(&pch_phub_lock);
+
+	if (pch_phub_opencount > 0)
+		pch_phub_opencount--;
+	spin_unlock(&pch_phub_lock);
+
+	dev_dbg(dev_dbg, "pch_phub_release : "
+		"pch_phub_opencount=%d  returning=%d\n",
+		pch_phub_opencount, 0);
+	return 0;
+}
+
+/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
+ *  								 Hub module.
+ *  @inode: Contains the reference of the inode structure
+ *  @file: Contains the reference of the file structure
+ *  @cmd: Contains the command value
+ *  @arg: Contains the command argument value
+ */
+#if 0
+int pch_phub_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	int ret_value = 0;
+	struct pch_phub_reqt *p_pch_phub_reqt;
+	unsigned long addr_offset;
+	unsigned long data;
+	unsigned long mask;
+
+	do {
+		if (pch_phub_suspended == true) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"suspend initiated returning =%d\n",
+				-EPERM);
+			ret_value = -EPERM;
+			break;
+		}
+
+		p_pch_phub_reqt = (struct pch_phub_reqt *)arg;
+		ret_value =
+			copy_from_user((void *)&addr_offset,
+				(void *)&p_pch_phub_reqt->addr_offset,
+				sizeof(addr_offset));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_from_user fail returning =%d\n",
+				-EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		dev_dbg(dev_dbg, "pch_phub_ioctl : "
+			"copy_from_user returns =%d\n", ret_value);
+
+		/* Access area check */
+		switch (cmd) {
+		case IOCTL_PHUB_READ_REG:
+		case IOCTL_PHUB_WRITE_REG:
+		case IOCTL_PHUB_READ_MODIFY_WRITE_REG:
+			if (addr_offset >= 0x504)
+				ret_value = -EPERM;
+			break;
+		case IOCTL_PHUB_READ_OROM:
+		case IOCTL_PHUB_WRITE_OROM:
+		case IOCTL_PHUB_READ_MAC_ADDR:
+		case IOCTL_PHUB_WRITE_MAC_ADDR:
+			if (addr_offset >= 0x10000)
+				ret_value = -EPERM;
+			break;
+		}
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"access area is wrong returning =%d\n",
+				-EPERM);
+			break;
+		}
+		/* End of Access area check */
+
+		switch (cmd) {
+		case IOCTL_PHUB_READ_REG:
+			data = PCH_READ_REG(addr_offset);
+			dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+				"PCH_READ_REG successfully\n");
+
+			ret_value =
+			    copy_to_user((void *)&p_pch_phub_reqt->data,
+					 (void *)&data, sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_to_user fail returning =%d\n",
+					-EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			break;
+		case IOCTL_PHUB_WRITE_REG:
+			ret_value = copy_from_user((void *)&data,
+						(void *)&p_pch_phub_reqt->data,
+						sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_from_user fail returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			PCH_WRITE_REG(data, addr_offset);
+			dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+				"PCH_WRITE_REG successfully\n");
+			break;
+		case IOCTL_PHUB_READ_MODIFY_WRITE_REG:
+			ret_value = copy_from_user((void *)&data,
+						   (void *)&p_pch_phub_reqt->
+						   data, sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+						"copy_from_user fail "
+						"returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			ret_value = copy_from_user((void *)&mask,
+						   (void *)&p_pch_phub_reqt->
+						   mask, sizeof(mask));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			pch_phub_read_modify_write_reg(addr_offset, data, mask);
+			dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+				"pch_phub_read_modify_write_reg "
+				"successfully\n");
+			break;
+		case IOCTL_PHUB_READ_OROM:
+			ret_value = pch_phub_read_serial_rom(addr_offset,
+							(unsigned char *)&data);
+			if (ret_value) {
+				dev_dbg(dev_dbg,
+					"pch_phub_ioctl : Invoked "
+					"pch_phub_read_serial_rom "
+					"=%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			} else {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+					"pch_phub_read_serial_rom "
+					"successfully\n");
+			}
+			ret_value = copy_to_user((void *)&p_pch_phub_reqt->
+						 data, (void *)&data,
+						 sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_to_user fail returning "
+					"=%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			break;
+		case IOCTL_PHUB_WRITE_OROM:
+			ret_value =
+			    copy_from_user((void *)&data,
+					   (void *)&p_pch_phub_reqt->
+					   data, sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_from_user fail returning "
+					"=%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			ret_value =
+				pch_phub_write_serial_rom(addr_offset, data);
+			if (ret_value) {
+				dev_dbg(dev_dbg,
+					"pch_phub_ioctl : Invoked "
+					"pch_phub_write_serial_rom "
+					"=%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			} else {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+					"pch_phub_write_serial_rom "
+					"successfully\n");
+			}
+			break;
+		case IOCTL_PHUB_READ_MAC_ADDR:
+			pch_phub_read_gbe_mac_addr(addr_offset,
+					 (unsigned char *)&data);
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_read_gbe_mac_addr successfully\n");
+
+			ret_value =
+			    copy_to_user((void *)&p_pch_phub_reqt->data,
+					 (void *)&data, sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_to_user fail "
+					"returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			break;
+		case IOCTL_PHUB_WRITE_MAC_ADDR:
+			ret_value =
+			    copy_from_user((void *)&data,
+					   (void *)&p_pch_phub_reqt->data,
+					   sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			pch_phub_write_gbe_mac_addr(addr_offset, data);
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+					"pch_phub_write_gbe_mac_addr "
+					"successfully\n");
+			break;
+		default:
+			dev_dbg(dev_dbg, "pch_write_ioctl invalid "
+				"command returning=%d\n", -EINVAL);
+			ret_value = -EINVAL;
+			break;
+		}
+		break;
+
+	} while (0);
+
+
+	dev_dbg(dev_dbg, "pch_write_ioctl returns=%d\n", ret_value);
+	return ret_value;
+}
+#endif
+int pch_phub_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	int ret_value = 0;
+	struct pch_phub_reqt *p_pch_phub_reqt;
+	unsigned long addr_offset;
+	unsigned long data;
+	unsigned long mask;
+
+	if (pch_phub_suspended == true) {
+		dev_dbg(dev_dbg, "pch_phub_ioctl : "
+			"suspend initiated returning =%d\n", -EPERM);
+		ret_value = -EPERM;
+		goto return_ioctrl;
+	}
+
+	p_pch_phub_reqt = (struct pch_phub_reqt *)arg;
+	ret_value = copy_from_user((void *)&addr_offset,
+				(void *)&p_pch_phub_reqt->addr_offset,
+				sizeof(addr_offset));
+	if (ret_value) {
+		dev_dbg(dev_dbg, "pch_phub_ioctl : "
+			"copy_from_user fail returning =%d\n", -EFAULT);
+		ret_value = -EFAULT;
+		goto return_ioctrl;
+	}
+	dev_dbg(dev_dbg, "pch_phub_ioctl : "
+		"copy_from_user returns =%d\n", ret_value);
+
+	/* Access area check */
+	switch (cmd) {
+	case IOCTL_PHUB_READ_REG:
+	case IOCTL_PHUB_WRITE_REG:
+	case IOCTL_PHUB_READ_MODIFY_WRITE_REG:
+		if (addr_offset >= 0x504)
+			ret_value = -EPERM;
+		break;
+	case IOCTL_PHUB_READ_OROM:
+	case IOCTL_PHUB_WRITE_OROM:
+	case IOCTL_PHUB_READ_MAC_ADDR:
+	case IOCTL_PHUB_WRITE_MAC_ADDR:
+		if (addr_offset >= 0x10000)
+			ret_value = -EPERM;
+		break;
+	}
+	if (ret_value) {
+		dev_dbg(dev_dbg, "pch_phub_ioctl : "
+			"access area is wrong returning =%d\n", -EPERM);
+		goto return_ioctrl;
+	}
+	/* End of Access area check */
+
+	switch (cmd) {
+	case IOCTL_PHUB_READ_REG:
+		data = PCH_READ_REG((void __iomem *)addr_offset);
+		dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+			"PCH_READ_REG successfully\n");
+
+		ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
+					 (void *)&data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_to_user fail returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		break;
+	case IOCTL_PHUB_WRITE_REG:
+		ret_value = copy_from_user((void *)&data,
+					(void *)&p_pch_phub_reqt->data,
+					sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_from_user fail returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		PCH_WRITE_REG(data, (void __iomem *)addr_offset);
+		dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+				"PCH_WRITE_REG successfully\n");
+		break;
+	case IOCTL_PHUB_READ_MODIFY_WRITE_REG:
+		ret_value = copy_from_user((void *)&data,
+			   (void *)&p_pch_phub_reqt->data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		ret_value = copy_from_user((void *)&mask,
+			   (void *)&p_pch_phub_reqt->mask, sizeof(mask));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		pch_phub_read_modify_write_reg(addr_offset,
+								 data, mask);
+		dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+			"pch_phub_read_modify_write_reg successfully\n");
+		break;
+	case IOCTL_PHUB_READ_OROM:
+		ret_value = pch_phub_read_serial_rom(addr_offset,
+							(unsigned char *)&data);
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_read_serial_rom =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		} else {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_read_serial_rom successfully\n");
+		}
+		ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
+						(void *)&data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_to_user fail returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		break;
+	case IOCTL_PHUB_WRITE_OROM:
+		ret_value = copy_from_user((void *)&data,
+			   (void *)&p_pch_phub_reqt->data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_from_user fail returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		ret_value = pch_phub_write_serial_rom(addr_offset, data);
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_write_serial_rom =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		} else {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_write_serial_rom successfully\n");
+		}
+		break;
+	case IOCTL_PHUB_READ_MAC_ADDR:
+		pch_phub_read_gbe_mac_addr(addr_offset, (unsigned char *)&data);
+		dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_read_gbe_mac_addr successfully\n");
+
+		ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
+						 (void *)&data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : copy_to_user fail "
+					"returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		break;
+	case IOCTL_PHUB_WRITE_MAC_ADDR:
+		ret_value = copy_from_user((void *)&data,
+			   (void *)&p_pch_phub_reqt->data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		pch_phub_write_gbe_mac_addr(addr_offset, data);
+		dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_write_gbe_mac_addr successfully\n");
+		break;
+	default:
+		dev_dbg(dev_dbg, "pch_write_ioctl invalid "
+				"command returning=%d\n", -EINVAL);
+		ret_value = -EINVAL;
+		break;
+	}
+return_ioctrl:
+	dev_dbg(dev_dbg, "pch_write_ioctl returns=%d\n", ret_value);
+	return ret_value;
+}
+
+/** pch_phub_pci_init - Implements the initialization functionality of
+ *  								 the module.
+ */
+static int __init pch_phub_pci_init(void)
+{
+	s32 ret;
+	ret = pci_register_driver(&pch_phub_driver);
+	dev_dbg(dev_dbg, "pch_phub_pci_init : "
+			"Invoked pci_register_driver successfully   "
+			"returns = %d\n", ret);
+	return ret;
+}
+
+/** pch_phub_pci_exit - Implements the exit functionality of the module.
+ */
+static void __exit pch_phub_pci_exit(void)
+{
+	pci_unregister_driver(&pch_phub_driver);
+	dev_dbg(dev_dbg, "pch_phub_pci_exit : "
+			"Invoked pci_unregister_driver successfully\n");
+}
+
+/** pch_phub_probe - Implements the probe functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @id: Contains the reference of the pci_device_id structure
+ */
+static int __devinit pch_phub_probe(struct pci_dev *pdev,
+				       const struct pci_device_id *id)
+{
+
+	char *DRIVER_NAME = "pch_phub";
+	int ret;
+	unsigned int rom_size;
+
+	dev_dbg = &pdev->dev;
+
+	pch_phub_major_no = (pch_phub_major_no < 0 || pch_phub_major_no > 254) ?
+				0 : pch_phub_major_no;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(dev_dbg, "\npch_phub_probe : pci_enable_device FAILED");
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe : "
+			"pci_enable_device returns %d\n", ret);
+
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret) {
+		dev_dbg(dev_dbg, "pch_phub_probe : pci_request_regions FAILED");
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe : "
+		"pci_request_regions returns %d\n", ret);
+
+	pch_phub_base_address = (unsigned long)pci_iomap(pdev, 1, 0);
+
+	if (pch_phub_base_address == 0) {
+		dev_dbg(dev_dbg, "pch_phub_probe : pci_iomap FAILED");
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe : pci_iomap SUCCESS and value "
+		"in pch_phub_base_address variable is 0x%08x\n",
+		pch_phub_base_address);
+
+	pch_phub_extrom_base_address =
+	    (unsigned long)pci_map_rom(pdev, &rom_size);
+	if (pch_phub_extrom_base_address == 0) {
+		dev_dbg(dev_dbg, "pch_phub_probe : pci_map_rom FAILED");
+		pci_iounmap(pdev, (void *)pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe : "
+		"pci_map_rom SUCCESS and value in "
+		"pch_phub_extrom_base_address variable is 0x%08x\n",
+		pch_phub_extrom_base_address);
+
+	if (pch_phub_major_no) {
+		pch_phub_dev_no = MKDEV(pch_phub_major_no, 0);
+		ret = register_chrdev_region(pch_phub_dev_no,
+					   PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(dev_dbg, "pch_phub_probe : "
+				"register_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+					(void *)pch_phub_extrom_base_address);
+			pci_iounmap(pdev, (void *)pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(dev_dbg, "pch_phub_probe : "
+				"register_chrdev_region returns %d\n", ret);
+	} else {
+		ret = alloc_chrdev_region(&pch_phub_dev_no, 0,
+						PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(dev_dbg, "pch_phub_probe : "
+					"alloc_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+				      (void *)pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				    (void *)pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(dev_dbg, "pch_phub_probe : "
+			"alloc_chrdev_region returns %d\n", ret);
+	}
+
+	cdev_init(&pch_phub_dev, &pch_phub_fops);
+	dev_dbg(dev_dbg, "pch_phub_probe :  cdev_init invoked successfully\n");
+
+	pch_phub_dev.owner = THIS_MODULE;
+	pch_phub_dev.ops = &pch_phub_fops;
+
+	ret = cdev_add(&pch_phub_dev, pch_phub_dev_no, PCH_MINOR_NOS);
+	if (ret) {
+		dev_dbg(dev_dbg, "pch_phub_probe :  cdev_add FAILED");
+		unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+		pci_unmap_rom(pdev, (void *)pch_phub_extrom_base_address);
+		pci_iounmap(pdev, (void *)pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe :  cdev_add returns %d\n", ret);
+
+#ifdef PCH_CAN_PCLK_50MHZ
+	/*set the clock config reg if CAN clock is 50Mhz */
+	dev_dbg(dev_dbg, "pch_phub_probe : invoking "
+		"pch_phub_read_modify_write_reg "
+		"to set CLKCFG reg for CAN clk 50Mhz\n");
+	pch_phub_read_modify_write_reg((unsigned long)CLKCFG_REG_OFFSET,
+					  CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+#endif
+	/* set the prefech value */
+	PCH_WRITE_REG(0x000ffffa, (void __iomem *)0x14);
+	/* set the interrupt delay value */
+	PCH_WRITE_REG(0x25, (void __iomem *)0x44);
+	return 0;
+
+err_probe:
+	dev_dbg(dev_dbg, "pch_phub_probe returns %d\n", ret);
+	return ret;
+}
+
+/** pch_phub_remove - Implements the remove functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+
+	cdev_del(&pch_phub_dev);
+	dev_dbg(dev_dbg, "pch_phub_remove - cdev_del Invoked successfully\n");
+
+	unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+	dev_dbg(dev_dbg, "pch_phub_remove - "
+		"unregister_chrdev_region Invoked successfully\n");
+
+	pci_unmap_rom(pdev, (void *)pch_phub_extrom_base_address);
+
+	pci_iounmap(pdev, (void *)pch_phub_base_address);
+
+	dev_dbg(dev_dbg, "pch_phub_remove - "
+			"pci_iounmap Invoked successfully\n");
+
+	pci_release_regions(pdev);
+	dev_dbg(dev_dbg, "pch_phub_remove - "
+		"pci_release_regions Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(dev_dbg, "pch_phub_remove - "
+		"pci_disable_device Invoked successfully\n");
+
+}
+
+#ifdef CONFIG_PM
+
+/** pch_phub_suspend - Implements the suspend functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @state: Contains the reference of the pm_message_t structure
+ */
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int ret;
+
+	pch_phub_suspended = true;	/* For blocking further IOCTLs */
+
+	pch_phub_save_reg_conf();
+	dev_dbg(dev_dbg, "pch_phub_suspend - "
+		"pch_phub_save_reg_conf Invoked successfully\n");
+
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_dbg(dev_dbg,
+			" pch_phub_suspend -pci_save_state returns-%d\n", ret);
+		return ret;
+	}
+	dev_dbg(dev_dbg, "pch_phub_suspend - pci_save_state returns %d\n", ret);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(dev_dbg, "pch_phub_suspend - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(dev_dbg, "pch_phub_suspend - "
+			"pci_disable_device Invoked successfully\n");
+
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	dev_dbg(dev_dbg, "pch_phub_suspend - "
+			"pci_set_power_state Invoked successfully   "
+			"return = %d\n", 0);
+
+	return 0;
+}
+
+/** pch_phub_resume - Implements the resume functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static int pch_phub_resume(struct pci_dev *pdev)
+{
+
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+		"pci_set_power_state Invoked successfully\n");
+
+	pci_restore_state(pdev);
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+		"pci_restore_state Invoked successfully\n");
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(dev_dbg, "pch_phub_resume-pci_enable_device failed ");
+		return ret;
+	}
+
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+			"pci_enable_device returns -%d\n", ret);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pch_phub_restore_reg_conf();
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+		"pch_phub_restore_reg_conf Invoked successfully\n");
+
+	pch_phub_suspended = false;
+
+	dev_dbg(dev_dbg, "pch_phub_resume  returns- %d\n", 0);
+	return 0;
+}
+#endif /* CONFIG_PM */
diff --git a/drivers/char/pch_phub/pch_phub.h b/drivers/char/pch_phub/pch_phub.h
new file mode 100755
index 0000000..62ed819
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.h
@@ -0,0 +1,96 @@
+#ifndef __PCH_PHUB_H__
+#define __PCH_PHUB_H__
+/*!
+ * @file pch_phub.h
+ * @brief Provides all the interfaces pertaining to the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+#define PHUB_IOCTL_MAGIC 		(0xf7)
+
+/*Outlines the read register function signature.  */
+#define IOCTL_PHUB_READ_REG (_IOW(PHUB_IOCTL_MAGIC, 1, unsigned long))
+
+/*Outlines the write register function signature. */
+#define IOCTL_PHUB_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 2, unsigned long))
+
+/*Outlines the read, modify and write register function signature. */
+#define IOCTL_PHUB_READ_MODIFY_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 3,\
+								 unsigned long))
+
+/*Outlines the read option rom function signature. */
+#define IOCTL_PHUB_READ_OROM (_IOW(PHUB_IOCTL_MAGIC, 4, unsigned long))
+
+/*Outlines the write option rom function signature. */
+#define IOCTL_PHUB_WRITE_OROM (_IOW(PHUB_IOCTL_MAGIC, 5, unsigned long))
+
+/*Outlines the read mac address function signature. */
+#define IOCTL_PHUB_READ_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 6, unsigned long))
+
+/*brief Outlines the write mac address function signature. */
+#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, unsigned long))
+
+
+/* Registers address offset */
+#define PCH_PHUB_PHUB_ID_REG			(void __iomem *)(0x0000)
+#define PCH_PHUB_QUEUE_PRI_VAL_REG			(void __iomem *)(0x0004)
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG		(void __iomem *)(0x0008)
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG		(void __iomem *)(0x000C)
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG		(void __iomem *)(0x0010)
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG		(void __iomem *)(0x0014)
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG		(void __iomem *)(0x0018)
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0		(void __iomem *)(0x0020)
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1		(void __iomem *)(0x0024)
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2		(void __iomem *)(0x0028)
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3		(void __iomem *)(0x002C)
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	(void __iomem *)(0x0040)
+#define CLKCFG_REG_OFFSET           		(void __iomem *)(0x500)
+
+/*structures*/
+/*It is a structure used for perserving information related to the
+ * 							 Packet Hub request.
+ */
+struct pch_phub_reqt {
+	unsigned long addr_offset;	/*specifies the register address
+								 offset */
+	unsigned long data;	/*specifies the data */
+	unsigned long mask;	/*specifies the mask */
+};
+
+/* exported function prototypes */
+int pch_phub_open(struct inode *inode, struct file *file);
+int pch_phub_release(struct inode *inode, struct file *file);
+int pch_phub_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		      unsigned long arg);
+
+/**global variables*/
+extern u32 pch_phub_base_address;	/* base address */
+extern s32 pch_phub_suspended;		/* suspend status */
+
+extern s32 pch_phub_opencount;
+extern spinlock_t pch_phub_lock;
+extern const struct file_operations pch_phub_fops;
+#endif
-- 
1.6.0.6

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-07 12:39 [PATCH] Topcliff PHUB: Generate PacketHub driver Masayuki Ohtak
@ 2010-06-07 15:05 ` Alan Cox
  2010-06-08  0:19   ` Masayuki Ohtake
  2010-06-14 12:09 ` Masayuki Ohtak
  1 sibling, 1 reply; 45+ messages in thread
From: Alan Cox @ 2010-06-07 15:05 UTC (permalink / raw)
  To: Masayuki Ohtak; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

O> +/* Status Register offset */
> +#define PHUB_STATUS (0x00)
> +/* Control Register offset */
> +#define PHUB_CONTROL (0x04)
> +/* Time out value for Status Register */
> +#define PHUB_TIMEOUT (0x05)
> +/* Enabling for writing ROM */
> +#define PCH_PHUB_ROM_WRITE_ENABLE (0x01)
> +/* Disabling for writing ROM */
> +#define PCH_PHUB_ROM_WRITE_DISABLE (0x00)
> +/* ROM data area start address offset */
> +#define PCH_PHUB_ROM_START_ADDR (0x14)
> +/* MAX number of INT_REDUCE_CONTROL registers */
> +#define MAX_NUM_INT_REDUCE_CONTROL_REG (128)
> +
> +#define PCI_DEVICE_ID_PCH1_PHUB (0x8801)
> +
> +#define PCH_MINOR_NOS (1)
> +#define CLKCFG_CAN_50MHZ (0x12000000)
> +#define CLKCFG_CANCLK_MASK (0xFF000000)

Style: constants don't need brackets - might also look more Linux like
tabbed out a bit

> +#define PCH_READ_REG(a)	ioread32((pch_phub_base_address + a))
> +
> +#define PCH_WRITE_REG(a, b)	iowrite32(a, (pch_phub_base_address + b))

These on the other hand do - but not where they are now

	iowrite32((a), pcb_phub_base_address + (b))

(so that if a or b are expressions they are evaluated first)


> +struct pch_phub_reg {
> +	u32 phub_id_reg;		/* PHUB_ID register val */
> +	u32 q_pri_val_reg;		/* QUEUE_PRI_VAL register val */
> +	u32 rc_q_maxsize_reg;	/* RC_QUEUE_MAXSIZE register val */
> +	u32 bri_q_maxsize_reg;	/* BRI_QUEUE_MAXSIZE register val */
> +	u32 comp_resp_timeout_reg;	/* COMP_RESP_TIMEOUT register val */
> +	u32 bus_slave_control_reg;	/* BUS_SLAVE_CONTROL_REG register val */
> +	u32 deadlock_avoid_type_reg; /* DEADLOCK_AVOID_TYPE register val */
> +	u32 intpin_reg_wpermit_reg0; /* INTPIN_REG_WPERMIT register 0 val */
> +	u32 intpin_reg_wpermit_reg1; /* INTPIN_REG_WPERMIT register 1 val */
> +	u32 intpin_reg_wpermit_reg2; /* INTPIN_REG_WPERMIT register 2 val */
> +	u32 intpin_reg_wpermit_reg3; /* INTPIN_REG_WPERMIT register 3 val */
> +	/* INT_REDUCE_CONTROL registers val */
> +	u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
> +#ifdef PCH_CAN_PCLK_50MHZ
> +	u32 clkcfg_reg;		/* CLK CFG register val */
> +#endif
> +} g_pch_phub_reg;

Stylewise the kernel doesn't use the g_ convention that many Windows
people do, so lose the g_

> +s32 pch_phub_opencount;	/* check whether opened or not */
> +u32 pch_phub_base_address;
> +u32 pch_phub_extrom_base_address;
> +s32 pch_phub_suspended;

Any reason these can't be in the struct ?
> +
> +struct device *dev_dbg;

Not a good name for a global variable as it will clash with others 

> +DEFINE_SPINLOCK(pch_phub_lock);	/* for spin lock */

Can this be static or in the struct ?

> +
> +/**
> + * file_operations structure initialization
> + */
> +const struct file_operations pch_phub_fops = {
> +	.owner = THIS_MODULE,
> +	.open = pch_phub_open,
> +	.release = pch_phub_release,
> +	.ioctl = pch_phub_ioctl,
> +};

static const ?

> +/*--------------------------------------------
> +	exported function prototypes
> +--------------------------------------------*/

They start 'static' I don't think they are exportdd !

> +static int __devinit pch_phub_probe(struct pci_dev *pdev, const
> +				       struct pci_device_id *id);
> +static void __devexit pch_phub_remove(struct pci_dev *pdev);
> +static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
> +static int pch_phub_resume(struct pci_dev *pdev);

> +static struct pci_driver pch_phub_driver = {
> +	.name = "pch_phub",
> +	.id_table = pch_phub_pcidev_id,
> +	.probe = pch_phub_probe,
> +	.remove = __devexit_p(pch_phub_remove),
> +#ifdef CONFIG_PM
> +	.suspend = pch_phub_suspend,
> +	.resume = pch_phub_resume
> +#endif
> +};
> +
> +static int __init pch_phub_pci_init(void);
> +static void __exit pch_phub_pci_exit(void);
> +
> +MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
> +MODULE_LICENSE("GPL");
> +module_init(pch_phub_pci_init);
> +module_exit(pch_phub_pci_exit);
> +module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);

If you migrated the module registration/PCI registration to the bottom of
the file you could avoid the forward declations and make the code easier
to follow ?

> +void pch_phub_read_modify_write_reg(unsigned long reg_addr_offset,
> +				       unsigned long data, unsigned long mask)
> +{
> +	unsigned long reg_addr = pch_phub_base_address + reg_addr_offset;
> +	iowrite32(((ioread32((void __iomem *)reg_addr) & ~mask)) | data,
> +			(void __iomem *)reg_addr);

When you have that many casts in a line it's perhaps a hint you have the
types wrong initially. At the very least reg_addr should be void __iomem,
and probably pch_phub_base_address should be 

It would probably make sense to pass a pointer to your struct pch_hub_reg
and use that to hold the base address. Then if you ever get a box with
two in some future design it won't be a disaster

> +void pch_phub_save_reg_conf(void)

Ditto 

> +#ifdef PCH_CAN_PCLK_50MHZ
> +	/* save clk cfg register */
> +	g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
> +#endif

This makes it hard to build one kernel for everything

> +	return;
> +}

> +void pch_phub_restore_reg_conf(void)
> +{
> +	u32 i = 0;

Why = 0, if you do that here you may hide initialisation errors from
future changes ?

> +/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
> + *  									 ROM.
> + *  @offset_address: Contains the Serial ROM address offset value
> + *  @data: Contains the Serial ROM value
> + */
> +int pch_phub_read_serial_rom(unsigned long offset_address, unsigned char *data)
> +{
> +	unsigned long mem_addr = pch_phub_extrom_base_address + offset_address;
> +
> +	dev_dbg(dev_dbg,
> +		"pch_phub_read_serial_rom:mem_addr=0x%08x\n", (u32)mem_addr);
> +	*data = ioread8((void __iomem *)mem_addr);

Same comments about casts



> +int pch_phub_ioctl(struct inode *inode, struct file *file,
> +			unsigned int cmd, unsigned long arg)
> +{
> +	int ret_value = 0;
> +	struct pch_phub_reqt *p_pch_phub_reqt;
> +	unsigned long addr_offset;

This will change size on 32/64bit boxes makign your copy a bit
problematic 

> +	p_pch_phub_reqt = (struct pch_phub_reqt *)arg;
> +	ret_value = copy_from_user((void *)&addr_offset,
> +				(void *)&p_pch_phub_reqt->addr_offset,
> +				sizeof(addr_offset));
> +	if (ret_value) {

> +	/* End of Access area check */

Remember here ioctl isn't single threaded so you may want to double check
some of these

> +struct pch_phub_reqt {
> +	unsigned long addr_offset;	/*specifies the register address
> +								 offset */
> +	unsigned long data;	/*specifies the data */
> +	unsigned long mask;	/*specifies the mask */

If they may need to be long make them u64. That way 32 and 64bit systems
get the same ioctl structure and life is good.

> +};
> +
> +/* exported function prototypes */
> +int pch_phub_open(struct inode *inode, struct file *file);
> +int pch_phub_release(struct inode *inode, struct file *file);
> +int pch_phub_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
> +		      unsigned long arg);

You have various other functions that are not static - if they should be
then make them static

Alan

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-07 15:05 ` Alan Cox
@ 2010-06-08  0:19   ` Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-08  0:19 UTC (permalink / raw)
  To: Alan Cox; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Alan,

Thank you for your comments.
We will integrate your comments to our PHUB by today or tomorrow at the latest.

Ohtake.
----- Original Message ----- 
From: "Alan Cox" <alan@lxorguk.ukuu.org.uk>
To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: "LKML" <linux-kernel@vger.kernel.org>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Intel OTC"
<joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y" <yong.y.wang@intel.com>
Sent: Tuesday, June 08, 2010 12:05 AM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> O> +/* Status Register offset */
> > +#define PHUB_STATUS (0x00)
> > +/* Control Register offset */
> > +#define PHUB_CONTROL (0x04)
> > +/* Time out value for Status Register */
> > +#define PHUB_TIMEOUT (0x05)
> > +/* Enabling for writing ROM */
> > +#define PCH_PHUB_ROM_WRITE_ENABLE (0x01)
> > +/* Disabling for writing ROM */
> > +#define PCH_PHUB_ROM_WRITE_DISABLE (0x00)
> > +/* ROM data area start address offset */
> > +#define PCH_PHUB_ROM_START_ADDR (0x14)
> > +/* MAX number of INT_REDUCE_CONTROL registers */
> > +#define MAX_NUM_INT_REDUCE_CONTROL_REG (128)
> > +
> > +#define PCI_DEVICE_ID_PCH1_PHUB (0x8801)
> > +
> > +#define PCH_MINOR_NOS (1)
> > +#define CLKCFG_CAN_50MHZ (0x12000000)
> > +#define CLKCFG_CANCLK_MASK (0xFF000000)
>
> Style: constants don't need brackets - might also look more Linux like
> tabbed out a bit
>
> > +#define PCH_READ_REG(a) ioread32((pch_phub_base_address + a))
> > +
> > +#define PCH_WRITE_REG(a, b) iowrite32(a, (pch_phub_base_address + b))
>
> These on the other hand do - but not where they are now
>
> iowrite32((a), pcb_phub_base_address + (b))
>
> (so that if a or b are expressions they are evaluated first)
>
>
> > +struct pch_phub_reg {
> > + u32 phub_id_reg; /* PHUB_ID register val */
> > + u32 q_pri_val_reg; /* QUEUE_PRI_VAL register val */
> > + u32 rc_q_maxsize_reg; /* RC_QUEUE_MAXSIZE register val */
> > + u32 bri_q_maxsize_reg; /* BRI_QUEUE_MAXSIZE register val */
> > + u32 comp_resp_timeout_reg; /* COMP_RESP_TIMEOUT register val */
> > + u32 bus_slave_control_reg; /* BUS_SLAVE_CONTROL_REG register val */
> > + u32 deadlock_avoid_type_reg; /* DEADLOCK_AVOID_TYPE register val */
> > + u32 intpin_reg_wpermit_reg0; /* INTPIN_REG_WPERMIT register 0 val */
> > + u32 intpin_reg_wpermit_reg1; /* INTPIN_REG_WPERMIT register 1 val */
> > + u32 intpin_reg_wpermit_reg2; /* INTPIN_REG_WPERMIT register 2 val */
> > + u32 intpin_reg_wpermit_reg3; /* INTPIN_REG_WPERMIT register 3 val */
> > + /* INT_REDUCE_CONTROL registers val */
> > + u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
> > +#ifdef PCH_CAN_PCLK_50MHZ
> > + u32 clkcfg_reg; /* CLK CFG register val */
> > +#endif
> > +} g_pch_phub_reg;
>
> Stylewise the kernel doesn't use the g_ convention that many Windows
> people do, so lose the g_
>
> > +s32 pch_phub_opencount; /* check whether opened or not */
> > +u32 pch_phub_base_address;
> > +u32 pch_phub_extrom_base_address;
> > +s32 pch_phub_suspended;
>
> Any reason these can't be in the struct ?
> > +
> > +struct device *dev_dbg;
>
> Not a good name for a global variable as it will clash with others
>
> > +DEFINE_SPINLOCK(pch_phub_lock); /* for spin lock */
>
> Can this be static or in the struct ?
>
> > +
> > +/**
> > + * file_operations structure initialization
> > + */
> > +const struct file_operations pch_phub_fops = {
> > + .owner = THIS_MODULE,
> > + .open = pch_phub_open,
> > + .release = pch_phub_release,
> > + .ioctl = pch_phub_ioctl,
> > +};
>
> static const ?
>
> > +/*--------------------------------------------
> > + exported function prototypes
> > +--------------------------------------------*/
>
> They start 'static' I don't think they are exportdd !
>
> > +static int __devinit pch_phub_probe(struct pci_dev *pdev, const
> > +        struct pci_device_id *id);
> > +static void __devexit pch_phub_remove(struct pci_dev *pdev);
> > +static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
> > +static int pch_phub_resume(struct pci_dev *pdev);
>
> > +static struct pci_driver pch_phub_driver = {
> > + .name = "pch_phub",
> > + .id_table = pch_phub_pcidev_id,
> > + .probe = pch_phub_probe,
> > + .remove = __devexit_p(pch_phub_remove),
> > +#ifdef CONFIG_PM
> > + .suspend = pch_phub_suspend,
> > + .resume = pch_phub_resume
> > +#endif
> > +};
> > +
> > +static int __init pch_phub_pci_init(void);
> > +static void __exit pch_phub_pci_exit(void);
> > +
> > +MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
> > +MODULE_LICENSE("GPL");
> > +module_init(pch_phub_pci_init);
> > +module_exit(pch_phub_pci_exit);
> > +module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);
>
> If you migrated the module registration/PCI registration to the bottom of
> the file you could avoid the forward declations and make the code easier
> to follow ?
>
> > +void pch_phub_read_modify_write_reg(unsigned long reg_addr_offset,
> > +        unsigned long data, unsigned long mask)
> > +{
> > + unsigned long reg_addr = pch_phub_base_address + reg_addr_offset;
> > + iowrite32(((ioread32((void __iomem *)reg_addr) & ~mask)) | data,
> > + (void __iomem *)reg_addr);
>
> When you have that many casts in a line it's perhaps a hint you have the
> types wrong initially. At the very least reg_addr should be void __iomem,
> and probably pch_phub_base_address should be
>
> It would probably make sense to pass a pointer to your struct pch_hub_reg
> and use that to hold the base address. Then if you ever get a box with
> two in some future design it won't be a disaster
>
> > +void pch_phub_save_reg_conf(void)
>
> Ditto
>
> > +#ifdef PCH_CAN_PCLK_50MHZ
> > + /* save clk cfg register */
> > + g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
> > +#endif
>
> This makes it hard to build one kernel for everything
>
> > + return;
> > +}
>
> > +void pch_phub_restore_reg_conf(void)
> > +{
> > + u32 i = 0;
>
> Why = 0, if you do that here you may hide initialisation errors from
> future changes ?
>
> > +/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
> > + *  ROM.
> > + *  @offset_address: Contains the Serial ROM address offset value
> > + *  @data: Contains the Serial ROM value
> > + */
> > +int pch_phub_read_serial_rom(unsigned long offset_address, unsigned char *data)
> > +{
> > + unsigned long mem_addr = pch_phub_extrom_base_address + offset_address;
> > +
> > + dev_dbg(dev_dbg,
> > + "pch_phub_read_serial_rom:mem_addr=0x%08x\n", (u32)mem_addr);
> > + *data = ioread8((void __iomem *)mem_addr);
>
> Same comments about casts
>
>
>
> > +int pch_phub_ioctl(struct inode *inode, struct file *file,
> > + unsigned int cmd, unsigned long arg)
> > +{
> > + int ret_value = 0;
> > + struct pch_phub_reqt *p_pch_phub_reqt;
> > + unsigned long addr_offset;
>
> This will change size on 32/64bit boxes makign your copy a bit
> problematic
>
> > + p_pch_phub_reqt = (struct pch_phub_reqt *)arg;
> > + ret_value = copy_from_user((void *)&addr_offset,
> > + (void *)&p_pch_phub_reqt->addr_offset,
> > + sizeof(addr_offset));
> > + if (ret_value) {
>
> > + /* End of Access area check */
>
> Remember here ioctl isn't single threaded so you may want to double check
> some of these
>
> > +struct pch_phub_reqt {
> > + unsigned long addr_offset; /*specifies the register address
> > + offset */
> > + unsigned long data; /*specifies the data */
> > + unsigned long mask; /*specifies the mask */
>
> If they may need to be long make them u64. That way 32 and 64bit systems
> get the same ioctl structure and life is good.
>
> > +};
> > +
> > +/* exported function prototypes */
> > +int pch_phub_open(struct inode *inode, struct file *file);
> > +int pch_phub_release(struct inode *inode, struct file *file);
> > +int pch_phub_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
> > +       unsigned long arg);
>
> You have various other functions that are not static - if they should be
> then make them static
>
> Alan
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-07 12:39 [PATCH] Topcliff PHUB: Generate PacketHub driver Masayuki Ohtak
  2010-06-07 15:05 ` Alan Cox
@ 2010-06-14 12:09 ` Masayuki Ohtak
  2010-06-14 12:50   ` Arnd Bergmann
  2010-06-17  2:43   ` Masayuki Ohtak
  1 sibling, 2 replies; 45+ messages in thread
From: Masayuki Ohtak @ 2010-06-14 12:09 UTC (permalink / raw)
  To: Alan Cox; +Cc: Masayuki Ohtak, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi we have modified for your comments.
Please Confirm below.

Thanks. 
Ohtake.


Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
 linux-2.6.33.1/drivers/char/Kconfig             |   25 +
 linux-2.6.33.1/drivers/char/Makefile            |    4 +
 linux-2.6.33.1/drivers/char/pch_phub/Makefile   |   11 +
 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c | 1000 +++++++++++++++++++++++
 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h |   87 ++
 5 files changed, 1127 insertions(+), 0 deletions(-)
 create mode 100644 linux-2.6.33.1/drivers/char/pch_phub/Makefile
 create mode 100755 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c
 create mode 100755 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h

diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e023682..285ce78 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -4,6 +4,31 @@
 
 menu "Character devices"
 
+config PCH_IEEE1588
+	tristate "PCH IEEE1588"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  PCH IEEE1588 Host controller.
+
+config PCH_PHUB
+	tristate "PCH PHUB"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  PCH Packet Hub Host controller.
+	  This driver is for PCH Packet hub driver for Topcliff.
+	  This driver is integrated as built-in.
+	  This driver can access GbE MAC address.
+	  This driver can access HW register.
+	  You can also be integrated as module.
+
+config PCH_CAN_PCLK_50MHZ
+	bool "CAN PCLK 50MHz"
+	depends on PCH_PHUB
+        help
+          If you say yes to this option, clock is set to 50MHz.(For CAN control)
+
 config VT
 	bool "Virtual terminal" if EMBEDDED
 	depends on !S390
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index f957edf..dc092d0 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -111,6 +111,10 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
 obj-$(CONFIG_JS_RTC)		+= js-rtc.o
 js-rtc-y = rtc.o
 
+obj-$(CONFIG_PCH_IEEE1588)		+= pch_ieee1588/
+
+obj-$(CONFIG_PCH_PHUB)	+= pch_phub/
+
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c
 
diff --git a/drivers/char/pch_phub/Makefile b/drivers/char/pch_phub/Makefile
new file mode 100644
index 0000000..bfe2a2b
--- /dev/null
+++ b/drivers/char/pch_phub/Makefile
@@ -0,0 +1,11 @@
+ifeq ($(CONFIG_PHUB_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_PCH_PHUB) += pch_phub_drv.o
+#to set CAN clock to 50Mhz
+ifdef CONFIG_PCH_CAN_PCLK_50MHZ
+EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
+endif
+
+pch_phub_drv-objs := pch_phub.o
diff --git a/drivers/char/pch_phub/pch_phub.c b/drivers/char/pch_phub/pch_phub.c
new file mode 100755
index 0000000..e9f5d4c
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.c
@@ -0,0 +1,1000 @@
+/*!
+ * @file pch_phub.c
+ * @brief Provides all the implementation of the interfaces pertaining to
+ *		the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+/* includes */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+#include "pch_phub.h"
+
+/*--------------------------------------------
+	macros
+--------------------------------------------*/
+/* Status Register offset */
+#define PHUB_STATUS 0x00
+/* Control Register offset */
+#define PHUB_CONTROL 0x04
+/* Time out value for Status Register */
+#define PHUB_TIMEOUT 0x05
+/* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_ENABLE 0x01
+/* Disabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE 0x00
+/* ROM data area start address offset */
+#define PCH_PHUB_ROM_START_ADDR 0x14
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
+
+#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
+
+#define PCH_MINOR_NOS 1
+#define CLKCFG_CAN_50MHZ 0x12000000
+#define CLKCFG_CANCLK_MASK 0xFF000000
+
+#define MODULE_NAME "pch_phub"
+
+#define PCH_READ_REG(a)	ioread32(pch_phub_reg.pch_phub_base_address + (a))
+
+#define PCH_WRITE_REG(a, b) iowrite32((a), pch_phub_reg.pch_phub_base_address +\
+									 (b))
+/*--------------------------------------------
+	global variables
+--------------------------------------------*/
+/**
+ * struct pch_phub_reg_t - PHUB register structure
+ * @phub_id_reg:		 PHUB_ID register val
+ * @q_pri_val_reg:		 QUEUE_PRI_VAL register val
+ * @rc_q_maxsize_reg:	 RC_QUEUE_MAXSIZE register val
+ * @bri_q_maxsize_reg:	 BRI_QUEUE_MAXSIZE register val
+ * @comp_resp_timeout_reg:	 COMP_RESP_TIMEOUT register val
+ * @bus_slave_control_reg:	 BUS_SLAVE_CONTROL_REG register val
+ * @deadlock_avoid_type_reg:  DEADLOCK_AVOID_TYPE register val
+ * @intpin_reg_wpermit_reg0:  INTPIN_REG_WPERMIT register 0 val
+ * @intpin_reg_wpermit_reg1:  INTPIN_REG_WPERMIT register 1 val
+ * @intpin_reg_wpermit_reg2:  INTPIN_REG_WPERMIT register 2 val
+ * @intpin_reg_wpermit_reg3:  INTPIN_REG_WPERMIT register 3 val
+ * @int_reduce_control_reg:	 INT_REDUCE_CONTROL registers val
+ * @clkcfg_reg:		 CLK CFG register val
+ * @pch_phub_opencount:	 check whether opened or not
+ * @pch_phub_base_address:  register base address
+ * @pch_phub_extrom_base_address:  external rom base address
+ * @pch_phub_suspended: PHUB status val
+ */
+struct pch_phub_reg_t {
+	__u32 phub_id_reg;
+	__u32 q_pri_val_reg;
+	__u32 rc_q_maxsize_reg;
+	__u32 bri_q_maxsize_reg;
+	__u32 comp_resp_timeout_reg;
+	__u32 bus_slave_control_reg;
+	__u32 deadlock_avoid_type_reg;
+	__u32 intpin_reg_wpermit_reg0;
+	__u32 intpin_reg_wpermit_reg1;
+	__u32 intpin_reg_wpermit_reg2;
+	__u32 intpin_reg_wpermit_reg3;
+	__u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+#ifdef PCH_CAN_PCLK_50MHZ
+	__u32 clkcfg_reg;
+#endif
+	__s32 pch_phub_opencount;
+	void __iomem *pch_phub_base_address;
+	void __iomem *pch_phub_extrom_base_address;
+	__s32 pch_phub_suspended;
+} pch_phub_reg;
+
+DEFINE_MUTEX(pch_phub_ioctl_mutex);
+
+static DEFINE_SPINLOCK(pch_phub_lock);	/* for spin lock */
+
+/* ToDo: major number allocation via module parameter */
+static dev_t pch_phub_dev_no;
+static __s32 pch_phub_major_no;
+static struct cdev pch_phub_dev;
+
+
+/*--------------------------------------------
+	internal function prototypes
+--------------------------------------------*/
+static __s32 __devinit pch_phub_probe(struct pci_dev *pdev, const
+				       struct pci_device_id *id);
+static void __devexit pch_phub_remove(struct pci_dev *pdev);
+static __s32 pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
+static __s32 pch_phub_resume(struct pci_dev *pdev);
+static __s32 pch_phub_open(struct inode *inode, struct file *file);
+static __s32 pch_phub_release(struct inode *inode, struct file *file);
+static long pch_phub_ioctl(struct file *file, unsigned int cmd,
+							 unsigned long arg);
+static ssize_t pch_phub_read(struct file *, char __user *, size_t, loff_t *);
+static ssize_t pch_phub_write(struct file *, const char __user *,
+							 size_t, loff_t *);
+
+/**
+ * file_operations structure initialization
+ */
+static const struct file_operations pch_phub_fops = {
+	.owner = THIS_MODULE,
+	.open = pch_phub_open,
+	.read = pch_phub_read,
+	.write = pch_phub_write,
+	.release = pch_phub_release,
+	.unlocked_ioctl = pch_phub_ioctl,
+};
+
+/*--------------------------------------------
+	functions implementations
+--------------------------------------------*/
+/** pch_phub_read_modify_write_reg - Implements the functionality of reading,
+ * 						modifying and writing register.
+ *  @reg_addr_offset:  Contains the register offset address value
+ *  @data:             Contains the writing value
+ *  @mask:             Contains the mask value
+ */
+static void pch_phub_read_modify_write_reg(__u32 reg_addr_offset,
+				       __u32 data, __u32 mask)
+{
+	void __iomem *reg_addr = pch_phub_reg.pch_phub_base_address +\
+							 reg_addr_offset;
+	iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+	return;
+}
+
+
+/** pch_phub_save_reg_conf - saves register configuration
+ */
+static void pch_phub_save_reg_conf(struct pci_dev *pdev)
+{
+	__u32 i = 0;
+
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	pch_phub_reg.phub_id_reg = PCH_READ_REG(PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	pch_phub_reg.q_pri_val_reg = PCH_READ_REG(PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	pch_phub_reg.rc_q_maxsize_reg =
+	    PCH_READ_REG(PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	pch_phub_reg.bri_q_maxsize_reg =
+	    PCH_READ_REG(PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	pch_phub_reg.comp_resp_timeout_reg =
+	    PCH_READ_REG(PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	pch_phub_reg.bus_slave_control_reg =
+	    PCH_READ_REG(PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	pch_phub_reg.deadlock_avoid_type_reg =
+	    PCH_READ_REG(PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	pch_phub_reg.intpin_reg_wpermit_reg0 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	pch_phub_reg.intpin_reg_wpermit_reg1 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	pch_phub_reg.intpin_reg_wpermit_reg2 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	pch_phub_reg.intpin_reg_wpermit_reg3 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+		"pch_phub_reg.phub_id_reg=%x, "
+		"pch_phub_reg.q_pri_val_reg=%x, "
+		"pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"pch_phub_reg.bus_slave_control_reg=%x, "
+		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		pch_phub_reg.phub_id_reg,
+		pch_phub_reg.q_pri_val_reg,
+		pch_phub_reg.rc_q_maxsize_reg,
+		pch_phub_reg.bri_q_maxsize_reg,
+		pch_phub_reg.comp_resp_timeout_reg,
+		pch_phub_reg.bus_slave_control_reg,
+		pch_phub_reg.deadlock_avoid_type_reg,
+		pch_phub_reg.intpin_reg_wpermit_reg0,
+		pch_phub_reg.intpin_reg_wpermit_reg1,
+		pch_phub_reg.intpin_reg_wpermit_reg2,
+		pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL registers */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		pch_phub_reg.int_reduce_control_reg[i] =
+		    PCH_READ_REG(
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, pch_phub_reg.int_reduce_control_reg[i]);
+	}
+#ifdef PCH_CAN_PCLK_50MHZ
+	/* save clk cfg register */
+	pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
+#endif
+	return;
+}
+
+/** pch_phub_restore_reg_conf - restore register configuration
+ */
+
+static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
+{
+	__u32 i;
+
+	dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	PCH_WRITE_REG(pch_phub_reg.phub_id_reg, PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	PCH_WRITE_REG(pch_phub_reg.q_pri_val_reg, PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	PCH_WRITE_REG(pch_phub_reg.rc_q_maxsize_reg,
+						PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	PCH_WRITE_REG(pch_phub_reg.bri_q_maxsize_reg,
+						PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	PCH_WRITE_REG(pch_phub_reg.comp_resp_timeout_reg,
+						PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	PCH_WRITE_REG(pch_phub_reg.bus_slave_control_reg,
+						PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	PCH_WRITE_REG(pch_phub_reg.deadlock_avoid_type_reg,
+					PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg0,
+					PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg1,
+					PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg2,
+					PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg3,
+					PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+		"pch_phub_reg.phub_id_reg=%x, "
+		"pch_phub_reg.q_pri_val_reg=%x, "
+		"pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"pch_phub_reg.bus_slave_control_reg=%x, "
+		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		pch_phub_reg.phub_id_reg,
+		pch_phub_reg.q_pri_val_reg,
+		pch_phub_reg.rc_q_maxsize_reg,
+		pch_phub_reg.bri_q_maxsize_reg,
+		pch_phub_reg.comp_resp_timeout_reg,
+		pch_phub_reg.bus_slave_control_reg,
+		pch_phub_reg.deadlock_avoid_type_reg,
+		pch_phub_reg.intpin_reg_wpermit_reg0,
+		pch_phub_reg.intpin_reg_wpermit_reg1,
+		pch_phub_reg.intpin_reg_wpermit_reg2,
+		pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL register */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		PCH_WRITE_REG(pch_phub_reg.int_reduce_control_reg[i],
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, pch_phub_reg.int_reduce_control_reg[i]);
+	}
+
+#ifdef PCH_CAN_PCLK_50MHZ
+	/*restore the clock config reg */
+	PCH_WRITE_REG(pch_phub_reg.clkcfg_reg, CLKCFG_REG_OFFSET);
+#endif
+
+	return;
+}
+
+/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
+ *  									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_read_serial_rom(__u32 offset_address, __u8 *data)
+{
+	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+								 offset_address;
+
+	*data = ioread8(mem_addr);
+
+	return 0;
+}
+
+/** pch_phub_write_serial_rom - Implements the functionality of writing Serial
+ *  									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_write_serial_rom(__u32 offset_address,
+							 __u8 data)
+{
+	__s32 retval = 0;
+	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+						 (offset_address & 0xFFFFFFFC);
+	__s32 i = 0;
+	__u32 word_data = 0;
+
+	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+			pch_phub_reg.pch_phub_extrom_base_address +\
+								 PHUB_CONTROL);
+
+	word_data = ioread32(mem_addr);
+
+	switch (offset_address % 4) {
+	case 0:
+		word_data &= 0xFFFFFF00;
+		iowrite32((word_data | (__u32)data),
+						mem_addr);
+		break;
+	case 1:
+		word_data &= 0xFFFF00FF;
+		iowrite32((word_data | ((__u32)data << 8)),
+						mem_addr);
+		break;
+	case 2:
+		word_data &= 0xFF00FFFF;
+		iowrite32((word_data | ((__u32)data << 16)),
+						mem_addr);
+		break;
+	case 3:
+		word_data &= 0x00FFFFFF;
+		iowrite32((word_data | ((__u32)data << 24)),
+						mem_addr);
+		break;
+	}
+	while (0x00 !=
+	       ioread8(pch_phub_reg.pch_phub_extrom_base_address +\
+							 PHUB_STATUS)) {
+		msleep(1);
+		if (PHUB_TIMEOUT == i) {
+			retval = -EPERM;
+			break;
+		}
+		i++;
+	}
+
+	iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+			pch_phub_reg.pch_phub_extrom_base_address +\
+								 PHUB_CONTROL);
+
+	return retval;
+}
+
+/** pch_phub_read_serial_rom_val - Implements the functionality of reading
+ *  							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_read_serial_rom_val(__u32 offset_address, __u8 *data)
+{
+	__s32 retval = 0;
+	__u32 mem_addr;
+
+	mem_addr = (offset_address / 4 * 8) + 3 -
+			(offset_address % 4) + PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_read_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_write_serial_rom_val - Implements the functionality of writing
+ *  							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_write_serial_rom_val(__u32 offset_address,
+				     __u8 data)
+{
+	__s32 retval = 0;
+	__u32 mem_addr;
+
+	mem_addr =
+	    (offset_address / 4 * 8) + 3 - (offset_address % 4) +
+	    PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_write_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ *  						for Gigabit Ethernet MAC address
+ */
+static __s32 pch_phub_gbe_serial_rom_conf(void)
+{
+	__s32 retval = 0;
+
+	retval |= pch_phub_write_serial_rom(0x0b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x0a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x09, 0x01);
+	retval |= pch_phub_write_serial_rom(0x08, 0x02);
+
+	retval |= pch_phub_write_serial_rom(0x0f, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0e, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0d, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0c, 0x80);
+
+	retval |= pch_phub_write_serial_rom(0x13, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x12, 0x10);
+	retval |= pch_phub_write_serial_rom(0x11, 0x01);
+	retval |= pch_phub_write_serial_rom(0x10, 0x18);
+
+	retval |= pch_phub_write_serial_rom(0x1b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x1a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x19, 0x01);
+	retval |= pch_phub_write_serial_rom(0x18, 0x19);
+
+	retval |= pch_phub_write_serial_rom(0x23, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x22, 0x10);
+	retval |= pch_phub_write_serial_rom(0x21, 0x01);
+	retval |= pch_phub_write_serial_rom(0x20, 0x3a);
+
+	retval |= pch_phub_write_serial_rom(0x27, 0x01);
+	retval |= pch_phub_write_serial_rom(0x26, 0x00);
+	retval |= pch_phub_write_serial_rom(0x25, 0x00);
+	retval |= pch_phub_write_serial_rom(0x24, 0x00);
+
+	return retval;
+}
+
+/** pch_phub_read_gbe_mac_addr - Contains the Gigabit Ethernet MAC address
+ *  								offset value
+ *  @offset_address: Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+static __s32 pch_phub_read_gbe_mac_addr(__u32 offset_address, __u8 *data)
+{
+	__s32 retval = 0;
+
+	retval = pch_phub_read_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_write_gbe_mac_addr - Write MAC address
+ *  @offset_address: Contains the Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+static __s32 pch_phub_write_gbe_mac_addr(__u32 offset_address,
+				   __u8 data)
+{
+	__s32 retval = 0;
+
+	retval = pch_phub_gbe_serial_rom_conf();
+	retval |= pch_phub_write_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_open - Implements the Initializing and opening of the Packet Hub
+									 module.
+ *  @inode: Contains the reference of the inode structure
+ *  @file: Contains the reference of the file structure
+ */
+static __s32 pch_phub_open(struct inode *inode, struct file *file)
+{
+	__s32 ret;
+
+	spin_lock(&pch_phub_lock);
+	if (pch_phub_reg.pch_phub_opencount) {
+		ret = -EBUSY;
+	} else {
+		pch_phub_reg.pch_phub_opencount++;
+		ret = 0;
+	}
+	spin_unlock(&pch_phub_lock);
+
+	return ret;
+}
+/** pch_phub_read - Implements the read functionality of the Packet Hub module.
+ *  @file: Contains the reference of the file structure
+ *  @buf: Usermode buffer pointer
+ *  @size: Usermode buffer size
+ *  @pos: Contains the reference of the file structure
+ */
+
+static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
+								 loff_t *pos)
+{
+	__u32 rom_signature = 0;
+	__u8 rom_length;
+	__s32 ret_value;
+	__u32 tmp;
+	__u8 data;
+	__u32 addr_offset = 0;
+
+	/*Get Rom signature*/
+	pch_phub_read_serial_rom(0x80, (__u8 *)&rom_signature);
+	pch_phub_read_serial_rom(0x81, (__u8 *)&tmp);
+	rom_signature |= (tmp & 0xff) << 8;
+	if (rom_signature == 0xAA55) {
+		pch_phub_read_serial_rom(0x82, &rom_length);
+		if (size > (rom_length * 512)+1)
+			return -ENOMEM;
+
+		for (addr_offset = 0;
+			addr_offset <= ((__u32)rom_length * 512);
+						 addr_offset++) {
+			pch_phub_read_serial_rom(0x80 + addr_offset, &data);
+			ret_value = copy_to_user((void *)&buf[addr_offset],
+							(void *)&data, 1);
+			if (ret_value)
+				return -EFAULT;
+		}
+	} else {
+		return -ENOEXEC;
+	}
+
+	return rom_length * 512 + 1;
+}
+
+/** pch_phub_write - Implements the write functionality of the Packet Hub
+ *  									 module.
+ *  @file: Contains the reference of the file structure
+ *  @buf: Usermode buffer pointer
+ *  @size: Usermode buffer size
+ *  @pos: Contains the reference of the file structure
+ */
+static ssize_t pch_phub_write(struct file *file, const char __user *buf,
+						 size_t size, loff_t *pos)
+{
+	static __u8 data[PCH_PHUB_OROM_SIZE];
+	__s32 ret_value;
+	__u32 addr_offset = 0;
+
+	if (size > PCH_PHUB_OROM_SIZE)
+		size = PCH_PHUB_OROM_SIZE;
+
+	ret_value = copy_from_user(data, buf, size);
+	if (ret_value)
+		return -EFAULT;
+
+	for (addr_offset = 0; addr_offset < size; addr_offset++) {
+		ret_value = pch_phub_write_serial_rom(0x80 + addr_offset,
+							 data[addr_offset]);
+	}
+
+	return size;
+}
+
+
+/** pch_phub_release - Implements the release functionality of the Packet Hub
+ *  									 module.
+ *  @inode: Contains the reference of the inode structure
+ *  @file: Contains the reference of the file structure
+ */
+static __s32 pch_phub_release(struct inode *inode, struct file *file)
+{
+	spin_lock(&pch_phub_lock);
+
+	if (pch_phub_reg.pch_phub_opencount > 0)
+		pch_phub_reg.pch_phub_opencount--;
+	spin_unlock(&pch_phub_lock);
+
+	return 0;
+}
+
+/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
+ *  								 Hub module.
+ *  @inode: Contains the reference of the inode structure
+ *  @file: Contains the reference of the file structure
+ *  @cmd: Contains the command value
+ *  @arg: Contains the command argument value
+ */
+
+
+static long pch_phub_ioctl(struct file *file, unsigned int cmd,
+							 unsigned long arg)
+{
+	__s32 ret_value = 0;
+	struct pch_phub_reqt __user *p_pch_phub_reqt;
+	__u32 data;
+	__u32 mac_addr[2];
+	__s32 ret;
+	__u32 i;
+	void __user *varg = (void __user *)arg;
+
+	ret = mutex_trylock(&pch_phub_ioctl_mutex);
+	if (ret == 0)
+		goto return_ioctrl;/*Can't get mutex lock*/
+
+	if (pch_phub_reg.pch_phub_suspended == true) {
+		ret_value = -EPERM;
+		goto return_ioctrl;
+	}
+
+	p_pch_phub_reqt = (struct pch_phub_reqt *)varg;
+
+	if (ret_value)
+		goto return_ioctrl;
+
+	/* End of Access area check */
+
+
+	switch (cmd) {
+
+	case IOCTL_PHUB_READ_MAC_ADDR:
+		mac_addr[0] = 0;
+		mac_addr[1] = 0;
+		for (i = 0; i < 4; i++) {
+			pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
+			mac_addr[0] |= data << i*8;
+		}
+		for (; i < 6; i++) {
+			pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
+			mac_addr[1] |= data << (i-4)*8;
+		}
+
+		ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
+					 (void *)mac_addr, sizeof(mac_addr));
+		if (ret_value) {
+			ret_value = -EFAULT;
+			break;
+		}
+		break;
+	case IOCTL_PHUB_WRITE_MAC_ADDR:
+		ret_value = get_user(mac_addr[0], &p_pch_phub_reqt->data[0]);
+		ret_value += get_user(mac_addr[1], &p_pch_phub_reqt->data[1]);
+		if (ret_value) {
+			ret_value = -EFAULT;
+			break;
+		}
+		for (i = 0; i < 4; i++) {
+			data = (mac_addr[0] & (0xff << 8*i))>>(8*i);
+			pch_phub_write_gbe_mac_addr(i, data);
+		}
+		for (; i < 6; i++) {
+			data = (mac_addr[1] & (0xff << 8*(i-4)))>>(8*(i-4));
+			pch_phub_write_gbe_mac_addr(i, data);
+		}
+		break;
+	default:
+		ret_value = -EINVAL;
+		break;
+	}
+return_ioctrl:
+	mutex_unlock(&pch_phub_ioctl_mutex);
+	return ret_value;
+}
+
+
+/** pch_phub_probe - Implements the probe functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @id: Contains the reference of the pci_device_id structure
+ */
+static __s32 __devinit pch_phub_probe(struct pci_dev *pdev,
+				       const struct pci_device_id *id)
+{
+
+	char *DRIVER_NAME = "pch_phub";
+	__s32 ret;
+	__u32 rom_size;
+
+	pch_phub_major_no = (pch_phub_major_no < 0 || pch_phub_major_no > 254) ?
+				0 : pch_phub_major_no;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"\npch_phub_probe : pci_enable_device FAILED");
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+			"pci_enable_device returns %d\n", ret);
+
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"pch_phub_probe : pci_request_regions FAILED");
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+		"pci_request_regions returns %d\n", ret);
+
+	pch_phub_reg.pch_phub_base_address = \
+					(void __iomem *)pci_iomap(pdev, 1, 0);
+
+	if (pch_phub_reg.pch_phub_base_address == 0) {
+		dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap FAILED");
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap SUCCESS and value "
+		"in pch_phub_base_address variable is 0x%08x\n",
+		(__u32)pch_phub_reg.pch_phub_base_address);
+
+	pch_phub_reg.pch_phub_extrom_base_address =
+	    (void __iomem *)pci_map_rom(pdev, &rom_size);
+	if (pch_phub_reg.pch_phub_extrom_base_address == 0) {
+		dev_dbg(&pdev->dev, "pch_phub_probe : pci_map_rom FAILED");
+		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+		"pci_map_rom SUCCESS and value in "
+		"pch_phub_extrom_base_address variable is 0x%08x\n",
+		(__u32)pch_phub_reg.pch_phub_extrom_base_address);
+
+	if (pch_phub_major_no) {
+		pch_phub_dev_no = MKDEV(pch_phub_major_no, 0);
+		ret = register_chrdev_region(pch_phub_dev_no,
+					   PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(&pdev->dev, "pch_phub_probe : "
+				"register_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				(void *)pch_phub_reg.pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(&pdev->dev, "pch_phub_probe : "
+				"register_chrdev_region returns %d\n", ret);
+	} else {
+		ret = alloc_chrdev_region(&pch_phub_dev_no, 0,
+						PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(&pdev->dev, "pch_phub_probe : "
+					"alloc_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				    (void *)pch_phub_reg.pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(&pdev->dev, "pch_phub_probe : "
+			"alloc_chrdev_region returns %d\n", ret);
+	}
+
+	cdev_init(&pch_phub_dev, &pch_phub_fops);
+	dev_dbg(&pdev->dev,
+			"pch_phub_probe :  cdev_init invoked successfully\n");
+
+	pch_phub_dev.owner = THIS_MODULE;
+	pch_phub_dev.ops = &pch_phub_fops;
+
+	ret = cdev_add(&pch_phub_dev, pch_phub_dev_no, PCH_MINOR_NOS);
+	if (ret) {
+		dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add FAILED");
+		unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+		pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add returns %d\n", ret);
+
+#ifdef PCH_CAN_PCLK_50MHZ
+	/*set the clock config reg if CAN clock is 50Mhz */
+	dev_dbg(&pdev->dev, "pch_phub_probe : invoking "
+		"pch_phub_read_modify_write_reg "
+		"to set CLKCFG reg for CAN clk 50Mhz\n");
+	pch_phub_read_modify_write_reg((__u32)CLKCFG_REG_OFFSET,
+					  CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+#endif
+	/* set the prefech value */
+	PCH_WRITE_REG(0x000ffffa, 0x14);
+	/* set the interrupt delay value */
+	PCH_WRITE_REG(0x25, 0x44);
+	return 0;
+
+err_probe:
+	dev_dbg(&pdev->dev, "pch_phub_probe returns %d\n", ret);
+	return ret;
+}
+
+/** pch_phub_remove - Implements the remove functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+
+	cdev_del(&pch_phub_dev);
+	dev_dbg(&pdev->dev,
+			"pch_phub_remove - cdev_del Invoked successfully\n");
+
+	unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"unregister_chrdev_region Invoked successfully\n");
+
+	pci_unmap_rom(pdev, (void *)pch_phub_reg.pch_phub_extrom_base_address);
+
+	pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+			"pci_iounmap Invoked successfully\n");
+
+	pci_release_regions(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"pci_release_regions Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"pci_disable_device Invoked successfully\n");
+
+}
+
+#ifdef CONFIG_PM
+
+/** pch_phub_suspend - Implements the suspend functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @state: Contains the reference of the pm_message_t structure
+ */
+static __s32 pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	__s32 ret;
+
+	pch_phub_reg.pch_phub_suspended = true;/* For blocking further IOCTLs */
+
+	pch_phub_save_reg_conf(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+		"pch_phub_save_reg_conf Invoked successfully\n");
+
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+			" pch_phub_suspend -pci_save_state returns-%d\n", ret);
+		return ret;
+	}
+	dev_dbg(&pdev->dev,
+			"pch_phub_suspend - pci_save_state returns %d\n", ret);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_disable_device Invoked successfully\n");
+
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_set_power_state Invoked successfully   "
+			"return = %d\n", 0);
+
+	return 0;
+}
+
+/** pch_phub_resume - Implements the resume functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static __s32 pch_phub_resume(struct pci_dev *pdev)
+{
+
+	__s32 ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pci_set_power_state Invoked successfully\n");
+
+	pci_restore_state(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pci_restore_state Invoked successfully\n");
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"pch_phub_resume-pci_enable_device failed ");
+		return ret;
+	}
+
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+			"pci_enable_device returns -%d\n", ret);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pch_phub_restore_reg_conf(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pch_phub_restore_reg_conf Invoked successfully\n");
+
+	pch_phub_reg.pch_phub_suspended = false;
+
+	dev_dbg(&pdev->dev, "pch_phub_resume  returns- %d\n", 0);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct pci_device_id pch_phub_pcidev_id[] = {
+
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+	{0,}
+};
+
+
+static struct pci_driver pch_phub_driver = {
+	.name = "pch_phub",
+	.id_table = pch_phub_pcidev_id,
+	.probe = pch_phub_probe,
+	.remove = __devexit_p(pch_phub_remove),
+#ifdef CONFIG_PM
+	.suspend = pch_phub_suspend,
+	.resume = pch_phub_resume
+#endif
+};
+
+/** pch_phub_pci_init - Implements the initialization functionality of
+ *  								 the module.
+ */
+static __s32 __init pch_phub_pci_init(void)
+{
+	__s32 ret;
+	ret = pci_register_driver(&pch_phub_driver);
+
+	return ret;
+}
+
+/** pch_phub_pci_exit - Implements the exit functionality of the module.
+ */
+static void __exit pch_phub_pci_exit(void)
+{
+	pci_unregister_driver(&pch_phub_driver);
+
+}
+
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);
+
+MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/char/pch_phub/pch_phub.h b/drivers/char/pch_phub/pch_phub.h
new file mode 100755
index 0000000..4859e2f
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.h
@@ -0,0 +1,87 @@
+#ifndef __PCH_PHUB_H__
+#define __PCH_PHUB_H__
+/*!
+ * @file pch_phub.h
+ * @brief Provides all the interfaces pertaining to the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+#define PHUB_IOCTL_MAGIC 		(0xf7)
+
+/*Outlines the read register function signature.  */
+#define IOCTL_PHUB_READ_REG (_IOW(PHUB_IOCTL_MAGIC, 1, __u32))
+
+/*Outlines the write register function signature. */
+#define IOCTL_PHUB_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 2, __u32))
+
+/*Outlines the read, modify and write register function signature. */
+#define IOCTL_PHUB_READ_MODIFY_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 3,\
+								 __u32))
+
+/*Outlines the read option rom function signature. */
+#define IOCTL_PHUB_READ_OROM (_IOW(PHUB_IOCTL_MAGIC, 4, __u32))
+
+/*Outlines the write option rom function signature. */
+#define IOCTL_PHUB_WRITE_OROM (_IOW(PHUB_IOCTL_MAGIC, 5, __u32))
+
+/*Outlines the read mac address function signature. */
+#define IOCTL_PHUB_READ_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 6, __u32))
+
+/*brief Outlines the write mac address function signature. */
+#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u32))
+
+
+/* Registers address offset */
+#define PCH_PHUB_PHUB_ID_REG			0x0000
+#define PCH_PHUB_QUEUE_PRI_VAL_REG		0x0004
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG		0x0008
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG		0x000C
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG		0x0010
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG		0x0014
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG	0x0018
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0	0x0020
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1	0x0024
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2	0x0028
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3	0x002C
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	0x0040
+#define CLKCFG_REG_OFFSET           		0x500
+
+#define PCH_PHUB_OROM_SIZE 15361
+/**
+ * struct pch_phub_reqt - It is a structure used for perserving information
+ * 					related to the Packet Hub request.
+ * @addr_offset:	specifies the register address offset
+ * @data:	specifies the data
+ * @mask:	specifies the mask
+ *
+ */
+struct pch_phub_reqt {
+	__u32 dev_id;
+	__u32 func_id;
+	__u32 data[2];
+};
+
+#endif
-- 
1.6.0.6


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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-14 12:09 ` Masayuki Ohtak
@ 2010-06-14 12:50   ` Arnd Bergmann
  2010-06-14 23:56     ` Masayuki Ohtake
  2010-06-15  6:25     ` Masayuki Ohtake
  2010-06-17  2:43   ` Masayuki Ohtak
  1 sibling, 2 replies; 45+ messages in thread
From: Arnd Bergmann @ 2010-06-14 12:50 UTC (permalink / raw)
  To: Masayuki Ohtak; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

On Monday 14 June 2010, Masayuki Ohtak wrote:
> Hi we have modified for your comments.
> Please Confirm below.

Looks much better. A few more comments about the new code:

> +#to set CAN clock to 50Mhz
> +ifdef CONFIG_PCH_CAN_PCLK_50MHZ
> +EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
> +endif

This should not be necessary. Just use CONFIG_PCH_CAN_PCLK_50MHZ directly
in the code instead of the extra PCH_CAN_PCLK_50MHZ macro.
> +
> +DEFINE_MUTEX(pch_phub_ioctl_mutex);

This should probable be 'static DEFINE_MUTEX', since the symbol does not
need to be visible in the entire kernel.


> +/*--------------------------------------------
> +	internal function prototypes
> +--------------------------------------------*/
> +static __s32 __devinit pch_phub_probe(struct pci_dev *pdev, const
> +				       struct pci_device_id *id);
> +static void __devexit pch_phub_remove(struct pci_dev *pdev);
> +static __s32 pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
> +static __s32 pch_phub_resume(struct pci_dev *pdev);
> +static __s32 pch_phub_open(struct inode *inode, struct file *file);
> +static __s32 pch_phub_release(struct inode *inode, struct file *file);
> +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> +							 unsigned long arg);
> +static ssize_t pch_phub_read(struct file *, char __user *, size_t, loff_t *);
> +static ssize_t pch_phub_write(struct file *, const char __user *,
> +							 size_t, loff_t *);

My general recommendation would be to reorder all the function
definitions so that you don't need any of these forward declarations.
That is the order used in most parts of the kernel (so you start reading
at the bottom), and it makes it easier to understand the structure of
the code IMHO.

> +/** pch_phub_open - Implements the Initializing and opening of the Packet Hub
> +									 module.
> + *  @inode: Contains the reference of the inode structure
> + *  @file: Contains the reference of the file structure
> + */
> +static __s32 pch_phub_open(struct inode *inode, struct file *file)
> +{
> +	__s32 ret;
> +
> +	spin_lock(&pch_phub_lock);
> +	if (pch_phub_reg.pch_phub_opencount) {
> +		ret = -EBUSY;
> +	} else {
> +		pch_phub_reg.pch_phub_opencount++;
> +		ret = 0;
> +	}
> +	spin_unlock(&pch_phub_lock);
> +
> +	return ret;
> +}

As far as I can tell, there is no longer a reason to prevent multiple
openers. Besides, even if there is only a single user, you might still
have concurrency problems, so the lock does not help and you could remove
the open function entirely.

> +/** pch_phub_read - Implements the read functionality of the Packet Hub module.
> + *  @file: Contains the reference of the file structure
> + *  @buf: Usermode buffer pointer
> + *  @size: Usermode buffer size
> + *  @pos: Contains the reference of the file structure
> + */
> +
> +static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
> +								 loff_t *pos)
> +{
> +	__u32 rom_signature = 0;
> +	__u8 rom_length;
> +	__s32 ret_value;
> +	__u32 tmp;
> +	__u8 data;
> +	__u32 addr_offset = 0;
> +
> +	/*Get Rom signature*/
> +	pch_phub_read_serial_rom(0x80, (__u8 *)&rom_signature);
> +	pch_phub_read_serial_rom(0x81, (__u8 *)&tmp);
> +	rom_signature |= (tmp & 0xff) << 8;
> +	if (rom_signature == 0xAA55) {
> +		pch_phub_read_serial_rom(0x82, &rom_length);
> +		if (size > (rom_length * 512)+1)
> +			return -ENOMEM;
> +
> +		for (addr_offset = 0;
> +			addr_offset <= ((__u32)rom_length * 512);
> +						 addr_offset++) {
> +			pch_phub_read_serial_rom(0x80 + addr_offset, &data);
> +			ret_value = copy_to_user((void *)&buf[addr_offset],
> +							(void *)&data, 1);
> +			if (ret_value)
> +				return -EFAULT;
> +		}
> +	} else {
> +		return -ENOEXEC;
> +	}
> +
> +	return rom_length * 512 + 1;
> +}

This function has multiple problems:

- If the size argument is less than rom_length*512, you access past the
  user-provided buffer.
- When the user does an llseek or pread, the *pos argument is not zero,
  so you should return data from the middle, but you still return data
  from the beginning.
- You don't update the *pos argument with the new position, so you cannot
  continue the read where the first call left.
- Instead of returning -ENOMEM, you should just the data you have (or
  0 for end-of-file).
- ENOEXEC does not seem appropriate either: The user can just check
  these buffer for the signature here, so you just as well return
  whatever you find in the ROM.

> +
> +/** pch_phub_write - Implements the write functionality of the Packet Hub
> + *  									 module.
> + *  @file: Contains the reference of the file structure
> + *  @buf: Usermode buffer pointer
> + *  @size: Usermode buffer size
> + *  @pos: Contains the reference of the file structure
> + */
> +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> +						 size_t size, loff_t *pos)
> +{
> +	static __u8 data[PCH_PHUB_OROM_SIZE];
> +	__s32 ret_value;
> +	__u32 addr_offset = 0;
> +
> +	if (size > PCH_PHUB_OROM_SIZE)
> +		size = PCH_PHUB_OROM_SIZE;
> +
> +	ret_value = copy_from_user(data, buf, size);
> +	if (ret_value)
> +		return -EFAULT;
> +
> +	for (addr_offset = 0; addr_offset < size; addr_offset++) {
> +		ret_value = pch_phub_write_serial_rom(0x80 + addr_offset,
> +							 data[addr_offset]);
> +	}
> +
> +	return size;
> +}

This has the same problems, plus a buffer overflow: You must never have an
array of multiple kilobytes on the stack (data[PCH_PHUB_OROM_SIZE]), because
the stack itself is only a few kilobytes in the kernel. Better use a loop
with copy_from_user like the read function does.

> +/** pch_phub_release - Implements the release functionality of the Packet Hub
> + *  									 module.
> + *  @inode: Contains the reference of the inode structure
> + *  @file: Contains the reference of the file structure
> + */
> +static __s32 pch_phub_release(struct inode *inode, struct file *file)
> +{
> +	spin_lock(&pch_phub_lock);
> +
> +	if (pch_phub_reg.pch_phub_opencount > 0)
> +		pch_phub_reg.pch_phub_opencount--;
> +	spin_unlock(&pch_phub_lock);
> +
> +	return 0;
> +}

When you remove the open function, this one can go away as well.

> +/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
> + *  								 Hub module.
> + *  @inode: Contains the reference of the inode structure
> + *  @file: Contains the reference of the file structure
> + *  @cmd: Contains the command value
> + *  @arg: Contains the command argument value
> + */
> +
> +
> +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> +							 unsigned long arg)
> +{
> +	__s32 ret_value = 0;
> +	struct pch_phub_reqt __user *p_pch_phub_reqt;
> +	__u32 data;
> +	__u32 mac_addr[2];
> +	__s32 ret;
> +	__u32 i;
> +	void __user *varg = (void __user *)arg;
> +
> +	ret = mutex_trylock(&pch_phub_ioctl_mutex);
> +	if (ret == 0)
> +		goto return_ioctrl;/*Can't get mutex lock*/

mutex_trylock is probably not what you want, it returns immediately
when there is another function in the kernel.
mutex_lock_interruptible seems more appropriate, it will block
until the mutex is free or the process gets sent a signal,
which you should handle by returning -ERESTARTSYS.

In either case, you must not jump to return_ioctrl here, because
that will try to release the mutex that you do not hold here,
causing a hang the next time you enter the function.

> +	if (pch_phub_reg.pch_phub_suspended == true) {
> +		ret_value = -EPERM;
> +		goto return_ioctrl;
> +	}
> +
> +	p_pch_phub_reqt = (struct pch_phub_reqt *)varg;
> +
> +	if (ret_value)
> +		goto return_ioctrl;

is always zero here.

> +	/* End of Access area check */
> +
> +
> +	switch (cmd) {
> +
> +	case IOCTL_PHUB_READ_MAC_ADDR:
> +		mac_addr[0] = 0;
> +		mac_addr[1] = 0;
> +		for (i = 0; i < 4; i++) {
> +			pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
> +			mac_addr[0] |= data << i*8;
> +		}
> +		for (; i < 6; i++) {
> +			pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
> +			mac_addr[1] |= data << (i-4)*8;
> +		}
> +
> +		ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
> +					 (void *)mac_addr, sizeof(mac_addr));

p_pch_phub_reqt->data has multiple problems:

- You have the typecast to (void *), which is wrong and unneeded.
- The data structure has no point at all any more when you use only one
  field.

Just make this

	u8 mac_addr[6];
	for (i = 0; i < 4; i++)
		pch_phub_read_gbe_mac_addr(i, &mac_addr[i]);
	ret_value = copy_to_user(varg, mac_addr, sizeof(mac_addr));

> +#define PHUB_IOCTL_MAGIC 		(0xf7)
> +
> +/*Outlines the read register function signature.  */
> +#define IOCTL_PHUB_READ_REG (_IOW(PHUB_IOCTL_MAGIC, 1, __u32))
> +
> +/*Outlines the write register function signature. */
> +#define IOCTL_PHUB_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 2, __u32))
> +
> +/*Outlines the read, modify and write register function signature. */
> +#define IOCTL_PHUB_READ_MODIFY_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 3,\
> +								 __u32))
> +
> +/*Outlines the read option rom function signature. */
> +#define IOCTL_PHUB_READ_OROM (_IOW(PHUB_IOCTL_MAGIC, 4, __u32))
> +
> +/*Outlines the write option rom function signature. */
> +#define IOCTL_PHUB_WRITE_OROM (_IOW(PHUB_IOCTL_MAGIC, 5, __u32))

These should all get removed now.

> +/*Outlines the read mac address function signature. */
> +#define IOCTL_PHUB_READ_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 6, __u32))
> +
> +/*brief Outlines the write mac address function signature. */
> +#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u32))

IOCTL_PHUB_READ_MAC_ADDR needs _IOR instead of _IOW, and the type
is still wrong here. Your code currently has struct pch_phub_reqt
instead of __u32, and if you change the ioctl function as I explained
above, it should become 

#define IOCTL_PHUB_READ_MAC_ADDR (_IOR(PHUB_IOCTL_MAGIC, 6, __u8[6]))
#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u8[6]))

	Arnd

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-14 12:50   ` Arnd Bergmann
@ 2010-06-14 23:56     ` Masayuki Ohtake
  2010-06-15  6:25     ` Masayuki Ohtake
  1 sibling, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-14 23:56 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew, LKML, Alan Cox

Hi Arnd

Thank you for your quick comments.
After modifying, we will resubmit the patch.

Thanks, Ohtake.

----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML" <linux-kernel@vger.kernel.org>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y"
<yong.y.wang@intel.com>
Sent: Monday, June 14, 2010 9:50 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Monday 14 June 2010, Masayuki Ohtak wrote:
> > Hi we have modified for your comments.
> > Please Confirm below.
>
> Looks much better. A few more comments about the new code:
>
> > +#to set CAN clock to 50Mhz
> > +ifdef CONFIG_PCH_CAN_PCLK_50MHZ
> > +EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
> > +endif
>
> This should not be necessary. Just use CONFIG_PCH_CAN_PCLK_50MHZ directly
> in the code instead of the extra PCH_CAN_PCLK_50MHZ macro.
> > +
> > +DEFINE_MUTEX(pch_phub_ioctl_mutex);
>
> This should probable be 'static DEFINE_MUTEX', since the symbol does not
> need to be visible in the entire kernel.
>
>
> > +/*--------------------------------------------
> > + internal function prototypes
> > +--------------------------------------------*/
> > +static __s32 __devinit pch_phub_probe(struct pci_dev *pdev, const
> > +        struct pci_device_id *id);
> > +static void __devexit pch_phub_remove(struct pci_dev *pdev);
> > +static __s32 pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
> > +static __s32 pch_phub_resume(struct pci_dev *pdev);
> > +static __s32 pch_phub_open(struct inode *inode, struct file *file);
> > +static __s32 pch_phub_release(struct inode *inode, struct file *file);
> > +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> > + unsigned long arg);
> > +static ssize_t pch_phub_read(struct file *, char __user *, size_t, loff_t *);
> > +static ssize_t pch_phub_write(struct file *, const char __user *,
> > + size_t, loff_t *);
>
> My general recommendation would be to reorder all the function
> definitions so that you don't need any of these forward declarations.
> That is the order used in most parts of the kernel (so you start reading
> at the bottom), and it makes it easier to understand the structure of
> the code IMHO.
>
> > +/** pch_phub_open - Implements the Initializing and opening of the Packet Hub
> > + module.
> > + *  @inode: Contains the reference of the inode structure
> > + *  @file: Contains the reference of the file structure
> > + */
> > +static __s32 pch_phub_open(struct inode *inode, struct file *file)
> > +{
> > + __s32 ret;
> > +
> > + spin_lock(&pch_phub_lock);
> > + if (pch_phub_reg.pch_phub_opencount) {
> > + ret = -EBUSY;
> > + } else {
> > + pch_phub_reg.pch_phub_opencount++;
> > + ret = 0;
> > + }
> > + spin_unlock(&pch_phub_lock);
> > +
> > + return ret;
> > +}
>
> As far as I can tell, there is no longer a reason to prevent multiple
> openers. Besides, even if there is only a single user, you might still
> have concurrency problems, so the lock does not help and you could remove
> the open function entirely.
>
> > +/** pch_phub_read - Implements the read functionality of the Packet Hub module.
> > + *  @file: Contains the reference of the file structure
> > + *  @buf: Usermode buffer pointer
> > + *  @size: Usermode buffer size
> > + *  @pos: Contains the reference of the file structure
> > + */
> > +
> > +static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
> > + loff_t *pos)
> > +{
> > + __u32 rom_signature = 0;
> > + __u8 rom_length;
> > + __s32 ret_value;
> > + __u32 tmp;
> > + __u8 data;
> > + __u32 addr_offset = 0;
> > +
> > + /*Get Rom signature*/
> > + pch_phub_read_serial_rom(0x80, (__u8 *)&rom_signature);
> > + pch_phub_read_serial_rom(0x81, (__u8 *)&tmp);
> > + rom_signature |= (tmp & 0xff) << 8;
> > + if (rom_signature == 0xAA55) {
> > + pch_phub_read_serial_rom(0x82, &rom_length);
> > + if (size > (rom_length * 512)+1)
> > + return -ENOMEM;
> > +
> > + for (addr_offset = 0;
> > + addr_offset <= ((__u32)rom_length * 512);
> > + addr_offset++) {
> > + pch_phub_read_serial_rom(0x80 + addr_offset, &data);
> > + ret_value = copy_to_user((void *)&buf[addr_offset],
> > + (void *)&data, 1);
> > + if (ret_value)
> > + return -EFAULT;
> > + }
> > + } else {
> > + return -ENOEXEC;
> > + }
> > +
> > + return rom_length * 512 + 1;
> > +}
>
> This function has multiple problems:
>
> - If the size argument is less than rom_length*512, you access past the
>   user-provided buffer.
> - When the user does an llseek or pread, the *pos argument is not zero,
>   so you should return data from the middle, but you still return data
>   from the beginning.
> - You don't update the *pos argument with the new position, so you cannot
>   continue the read where the first call left.
> - Instead of returning -ENOMEM, you should just the data you have (or
>   0 for end-of-file).
> - ENOEXEC does not seem appropriate either: The user can just check
>   these buffer for the signature here, so you just as well return
>   whatever you find in the ROM.
>
> > +
> > +/** pch_phub_write - Implements the write functionality of the Packet Hub
> > + *  module.
> > + *  @file: Contains the reference of the file structure
> > + *  @buf: Usermode buffer pointer
> > + *  @size: Usermode buffer size
> > + *  @pos: Contains the reference of the file structure
> > + */
> > +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> > + size_t size, loff_t *pos)
> > +{
> > + static __u8 data[PCH_PHUB_OROM_SIZE];
> > + __s32 ret_value;
> > + __u32 addr_offset = 0;
> > +
> > + if (size > PCH_PHUB_OROM_SIZE)
> > + size = PCH_PHUB_OROM_SIZE;
> > +
> > + ret_value = copy_from_user(data, buf, size);
> > + if (ret_value)
> > + return -EFAULT;
> > +
> > + for (addr_offset = 0; addr_offset < size; addr_offset++) {
> > + ret_value = pch_phub_write_serial_rom(0x80 + addr_offset,
> > + data[addr_offset]);
> > + }
> > +
> > + return size;
> > +}
>
> This has the same problems, plus a buffer overflow: You must never have an
> array of multiple kilobytes on the stack (data[PCH_PHUB_OROM_SIZE]), because
> the stack itself is only a few kilobytes in the kernel. Better use a loop
> with copy_from_user like the read function does.
>
> > +/** pch_phub_release - Implements the release functionality of the Packet Hub
> > + *  module.
> > + *  @inode: Contains the reference of the inode structure
> > + *  @file: Contains the reference of the file structure
> > + */
> > +static __s32 pch_phub_release(struct inode *inode, struct file *file)
> > +{
> > + spin_lock(&pch_phub_lock);
> > +
> > + if (pch_phub_reg.pch_phub_opencount > 0)
> > + pch_phub_reg.pch_phub_opencount--;
> > + spin_unlock(&pch_phub_lock);
> > +
> > + return 0;
> > +}
>
> When you remove the open function, this one can go away as well.
>
> > +/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
> > + *  Hub module.
> > + *  @inode: Contains the reference of the inode structure
> > + *  @file: Contains the reference of the file structure
> > + *  @cmd: Contains the command value
> > + *  @arg: Contains the command argument value
> > + */
> > +
> > +
> > +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> > + unsigned long arg)
> > +{
> > + __s32 ret_value = 0;
> > + struct pch_phub_reqt __user *p_pch_phub_reqt;
> > + __u32 data;
> > + __u32 mac_addr[2];
> > + __s32 ret;
> > + __u32 i;
> > + void __user *varg = (void __user *)arg;
> > +
> > + ret = mutex_trylock(&pch_phub_ioctl_mutex);
> > + if (ret == 0)
> > + goto return_ioctrl;/*Can't get mutex lock*/
>
> mutex_trylock is probably not what you want, it returns immediately
> when there is another function in the kernel.
> mutex_lock_interruptible seems more appropriate, it will block
> until the mutex is free or the process gets sent a signal,
> which you should handle by returning -ERESTARTSYS.
>
> In either case, you must not jump to return_ioctrl here, because
> that will try to release the mutex that you do not hold here,
> causing a hang the next time you enter the function.
>
> > + if (pch_phub_reg.pch_phub_suspended == true) {
> > + ret_value = -EPERM;
> > + goto return_ioctrl;
> > + }
> > +
> > + p_pch_phub_reqt = (struct pch_phub_reqt *)varg;
> > +
> > + if (ret_value)
> > + goto return_ioctrl;
>
> is always zero here.
>
> > + /* End of Access area check */
> > +
> > +
> > + switch (cmd) {
> > +
> > + case IOCTL_PHUB_READ_MAC_ADDR:
> > + mac_addr[0] = 0;
> > + mac_addr[1] = 0;
> > + for (i = 0; i < 4; i++) {
> > + pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
> > + mac_addr[0] |= data << i*8;
> > + }
> > + for (; i < 6; i++) {
> > + pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
> > + mac_addr[1] |= data << (i-4)*8;
> > + }
> > +
> > + ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
> > + (void *)mac_addr, sizeof(mac_addr));
>
> p_pch_phub_reqt->data has multiple problems:
>
> - You have the typecast to (void *), which is wrong and unneeded.
> - The data structure has no point at all any more when you use only one
>   field.
>
> Just make this
>
> u8 mac_addr[6];
> for (i = 0; i < 4; i++)
> pch_phub_read_gbe_mac_addr(i, &mac_addr[i]);
> ret_value = copy_to_user(varg, mac_addr, sizeof(mac_addr));
>
> > +#define PHUB_IOCTL_MAGIC (0xf7)
> > +
> > +/*Outlines the read register function signature.  */
> > +#define IOCTL_PHUB_READ_REG (_IOW(PHUB_IOCTL_MAGIC, 1, __u32))
> > +
> > +/*Outlines the write register function signature. */
> > +#define IOCTL_PHUB_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 2, __u32))
> > +
> > +/*Outlines the read, modify and write register function signature. */
> > +#define IOCTL_PHUB_READ_MODIFY_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 3,\
> > + __u32))
> > +
> > +/*Outlines the read option rom function signature. */
> > +#define IOCTL_PHUB_READ_OROM (_IOW(PHUB_IOCTL_MAGIC, 4, __u32))
> > +
> > +/*Outlines the write option rom function signature. */
> > +#define IOCTL_PHUB_WRITE_OROM (_IOW(PHUB_IOCTL_MAGIC, 5, __u32))
>
> These should all get removed now.
>
> > +/*Outlines the read mac address function signature. */
> > +#define IOCTL_PHUB_READ_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 6, __u32))
> > +
> > +/*brief Outlines the write mac address function signature. */
> > +#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u32))
>
> IOCTL_PHUB_READ_MAC_ADDR needs _IOR instead of _IOW, and the type
> is still wrong here. Your code currently has struct pch_phub_reqt
> instead of __u32, and if you change the ioctl function as I explained
> above, it should become
>
> #define IOCTL_PHUB_READ_MAC_ADDR (_IOR(PHUB_IOCTL_MAGIC, 6, __u8[6]))
> #define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u8[6]))
>
> Arnd
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-14 12:50   ` Arnd Bergmann
  2010-06-14 23:56     ` Masayuki Ohtake
@ 2010-06-15  6:25     ` Masayuki Ohtake
  2010-06-15 10:42       ` Arnd Bergmann
  1 sibling, 1 reply; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-15  6:25 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Arnd,

>> +#to set CAN clock to 50Mhz
>> +ifdef CONFIG_PCH_CAN_PCLK_50MHZ
>> +EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
>> +endif

>This should not be necessary. Just use CONFIG_PCH_CAN_PCLK_50MHZ directly
>in the code instead of the extra PCH_CAN_PCLK_50MHZ macro.

I have a question. I show the above reason.
In case CAN is integrated as MODULE, macro name is CONFIG_PCH_CAN_PCLK_50MHZ_MODULE.
On the other hand, integrated as built-in, CONFIG_PCH_CAN_PCLK_50MHZ.
To prevent PHUB source code from integrated as MODULE or BUILT-IN,
we re-define macro name in Makefile.

If use CONFIG_PCH_CAN_PCLK_50MHZ directly in the source code,
in case buit-in, behavior is not correct.
But in case module, behavior is not correct.

Please give us your opinion

Thanks,
Ohtake.
----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML" <linux-kernel@vger.kernel.org>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y"
<yong.y.wang@intel.com>
Sent: Monday, June 14, 2010 9:50 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Monday 14 June 2010, Masayuki Ohtak wrote:
> > Hi we have modified for your comments.
> > Please Confirm below.
>
> Looks much better. A few more comments about the new code:
>
> > +#to set CAN clock to 50Mhz
> > +ifdef CONFIG_PCH_CAN_PCLK_50MHZ
> > +EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
> > +endif
>
> This should not be necessary. Just use CONFIG_PCH_CAN_PCLK_50MHZ directly
> in the code instead of the extra PCH_CAN_PCLK_50MHZ macro.
> > +
> > +DEFINE_MUTEX(pch_phub_ioctl_mutex);
>
> This should probable be 'static DEFINE_MUTEX', since the symbol does not
> need to be visible in the entire kernel.
>
>
> > +/*--------------------------------------------
> > + internal function prototypes
> > +--------------------------------------------*/
> > +static __s32 __devinit pch_phub_probe(struct pci_dev *pdev, const
> > +        struct pci_device_id *id);
> > +static void __devexit pch_phub_remove(struct pci_dev *pdev);
> > +static __s32 pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
> > +static __s32 pch_phub_resume(struct pci_dev *pdev);
> > +static __s32 pch_phub_open(struct inode *inode, struct file *file);
> > +static __s32 pch_phub_release(struct inode *inode, struct file *file);
> > +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> > + unsigned long arg);
> > +static ssize_t pch_phub_read(struct file *, char __user *, size_t, loff_t *);
> > +static ssize_t pch_phub_write(struct file *, const char __user *,
> > + size_t, loff_t *);
>
> My general recommendation would be to reorder all the function
> definitions so that you don't need any of these forward declarations.
> That is the order used in most parts of the kernel (so you start reading
> at the bottom), and it makes it easier to understand the structure of
> the code IMHO.
>
> > +/** pch_phub_open - Implements the Initializing and opening of the Packet Hub
> > + module.
> > + *  @inode: Contains the reference of the inode structure
> > + *  @file: Contains the reference of the file structure
> > + */
> > +static __s32 pch_phub_open(struct inode *inode, struct file *file)
> > +{
> > + __s32 ret;
> > +
> > + spin_lock(&pch_phub_lock);
> > + if (pch_phub_reg.pch_phub_opencount) {
> > + ret = -EBUSY;
> > + } else {
> > + pch_phub_reg.pch_phub_opencount++;
> > + ret = 0;
> > + }
> > + spin_unlock(&pch_phub_lock);
> > +
> > + return ret;
> > +}
>
> As far as I can tell, there is no longer a reason to prevent multiple
> openers. Besides, even if there is only a single user, you might still
> have concurrency problems, so the lock does not help and you could remove
> the open function entirely.
>
> > +/** pch_phub_read - Implements the read functionality of the Packet Hub module.
> > + *  @file: Contains the reference of the file structure
> > + *  @buf: Usermode buffer pointer
> > + *  @size: Usermode buffer size
> > + *  @pos: Contains the reference of the file structure
> > + */
> > +
> > +static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
> > + loff_t *pos)
> > +{
> > + __u32 rom_signature = 0;
> > + __u8 rom_length;
> > + __s32 ret_value;
> > + __u32 tmp;
> > + __u8 data;
> > + __u32 addr_offset = 0;
> > +
> > + /*Get Rom signature*/
> > + pch_phub_read_serial_rom(0x80, (__u8 *)&rom_signature);
> > + pch_phub_read_serial_rom(0x81, (__u8 *)&tmp);
> > + rom_signature |= (tmp & 0xff) << 8;
> > + if (rom_signature == 0xAA55) {
> > + pch_phub_read_serial_rom(0x82, &rom_length);
> > + if (size > (rom_length * 512)+1)
> > + return -ENOMEM;
> > +
> > + for (addr_offset = 0;
> > + addr_offset <= ((__u32)rom_length * 512);
> > + addr_offset++) {
> > + pch_phub_read_serial_rom(0x80 + addr_offset, &data);
> > + ret_value = copy_to_user((void *)&buf[addr_offset],
> > + (void *)&data, 1);
> > + if (ret_value)
> > + return -EFAULT;
> > + }
> > + } else {
> > + return -ENOEXEC;
> > + }
> > +
> > + return rom_length * 512 + 1;
> > +}
>
> This function has multiple problems:
>
> - If the size argument is less than rom_length*512, you access past the
>   user-provided buffer.
> - When the user does an llseek or pread, the *pos argument is not zero,
>   so you should return data from the middle, but you still return data
>   from the beginning.
> - You don't update the *pos argument with the new position, so you cannot
>   continue the read where the first call left.
> - Instead of returning -ENOMEM, you should just the data you have (or
>   0 for end-of-file).
> - ENOEXEC does not seem appropriate either: The user can just check
>   these buffer for the signature here, so you just as well return
>   whatever you find in the ROM.
>
> > +
> > +/** pch_phub_write - Implements the write functionality of the Packet Hub
> > + *  module.
> > + *  @file: Contains the reference of the file structure
> > + *  @buf: Usermode buffer pointer
> > + *  @size: Usermode buffer size
> > + *  @pos: Contains the reference of the file structure
> > + */
> > +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> > + size_t size, loff_t *pos)
> > +{
> > + static __u8 data[PCH_PHUB_OROM_SIZE];
> > + __s32 ret_value;
> > + __u32 addr_offset = 0;
> > +
> > + if (size > PCH_PHUB_OROM_SIZE)
> > + size = PCH_PHUB_OROM_SIZE;
> > +
> > + ret_value = copy_from_user(data, buf, size);
> > + if (ret_value)
> > + return -EFAULT;
> > +
> > + for (addr_offset = 0; addr_offset < size; addr_offset++) {
> > + ret_value = pch_phub_write_serial_rom(0x80 + addr_offset,
> > + data[addr_offset]);
> > + }
> > +
> > + return size;
> > +}
>
> This has the same problems, plus a buffer overflow: You must never have an
> array of multiple kilobytes on the stack (data[PCH_PHUB_OROM_SIZE]), because
> the stack itself is only a few kilobytes in the kernel. Better use a loop
> with copy_from_user like the read function does.
>
> > +/** pch_phub_release - Implements the release functionality of the Packet Hub
> > + *  module.
> > + *  @inode: Contains the reference of the inode structure
> > + *  @file: Contains the reference of the file structure
> > + */
> > +static __s32 pch_phub_release(struct inode *inode, struct file *file)
> > +{
> > + spin_lock(&pch_phub_lock);
> > +
> > + if (pch_phub_reg.pch_phub_opencount > 0)
> > + pch_phub_reg.pch_phub_opencount--;
> > + spin_unlock(&pch_phub_lock);
> > +
> > + return 0;
> > +}
>
> When you remove the open function, this one can go away as well.
>
> > +/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
> > + *  Hub module.
> > + *  @inode: Contains the reference of the inode structure
> > + *  @file: Contains the reference of the file structure
> > + *  @cmd: Contains the command value
> > + *  @arg: Contains the command argument value
> > + */
> > +
> > +
> > +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> > + unsigned long arg)
> > +{
> > + __s32 ret_value = 0;
> > + struct pch_phub_reqt __user *p_pch_phub_reqt;
> > + __u32 data;
> > + __u32 mac_addr[2];
> > + __s32 ret;
> > + __u32 i;
> > + void __user *varg = (void __user *)arg;
> > +
> > + ret = mutex_trylock(&pch_phub_ioctl_mutex);
> > + if (ret == 0)
> > + goto return_ioctrl;/*Can't get mutex lock*/
>
> mutex_trylock is probably not what you want, it returns immediately
> when there is another function in the kernel.
> mutex_lock_interruptible seems more appropriate, it will block
> until the mutex is free or the process gets sent a signal,
> which you should handle by returning -ERESTARTSYS.
>
> In either case, you must not jump to return_ioctrl here, because
> that will try to release the mutex that you do not hold here,
> causing a hang the next time you enter the function.
>
> > + if (pch_phub_reg.pch_phub_suspended == true) {
> > + ret_value = -EPERM;
> > + goto return_ioctrl;
> > + }
> > +
> > + p_pch_phub_reqt = (struct pch_phub_reqt *)varg;
> > +
> > + if (ret_value)
> > + goto return_ioctrl;
>
> is always zero here.
>
> > + /* End of Access area check */
> > +
> > +
> > + switch (cmd) {
> > +
> > + case IOCTL_PHUB_READ_MAC_ADDR:
> > + mac_addr[0] = 0;
> > + mac_addr[1] = 0;
> > + for (i = 0; i < 4; i++) {
> > + pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
> > + mac_addr[0] |= data << i*8;
> > + }
> > + for (; i < 6; i++) {
> > + pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
> > + mac_addr[1] |= data << (i-4)*8;
> > + }
> > +
> > + ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
> > + (void *)mac_addr, sizeof(mac_addr));
>
> p_pch_phub_reqt->data has multiple problems:
>
> - You have the typecast to (void *), which is wrong and unneeded.
> - The data structure has no point at all any more when you use only one
>   field.
>
> Just make this
>
> u8 mac_addr[6];
> for (i = 0; i < 4; i++)
> pch_phub_read_gbe_mac_addr(i, &mac_addr[i]);
> ret_value = copy_to_user(varg, mac_addr, sizeof(mac_addr));
>
> > +#define PHUB_IOCTL_MAGIC (0xf7)
> > +
> > +/*Outlines the read register function signature.  */
> > +#define IOCTL_PHUB_READ_REG (_IOW(PHUB_IOCTL_MAGIC, 1, __u32))
> > +
> > +/*Outlines the write register function signature. */
> > +#define IOCTL_PHUB_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 2, __u32))
> > +
> > +/*Outlines the read, modify and write register function signature. */
> > +#define IOCTL_PHUB_READ_MODIFY_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 3,\
> > + __u32))
> > +
> > +/*Outlines the read option rom function signature. */
> > +#define IOCTL_PHUB_READ_OROM (_IOW(PHUB_IOCTL_MAGIC, 4, __u32))
> > +
> > +/*Outlines the write option rom function signature. */
> > +#define IOCTL_PHUB_WRITE_OROM (_IOW(PHUB_IOCTL_MAGIC, 5, __u32))
>
> These should all get removed now.
>
> > +/*Outlines the read mac address function signature. */
> > +#define IOCTL_PHUB_READ_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 6, __u32))
> > +
> > +/*brief Outlines the write mac address function signature. */
> > +#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u32))
>
> IOCTL_PHUB_READ_MAC_ADDR needs _IOR instead of _IOW, and the type
> is still wrong here. Your code currently has struct pch_phub_reqt
> instead of __u32, and if you change the ioctl function as I explained
> above, it should become
>
> #define IOCTL_PHUB_READ_MAC_ADDR (_IOR(PHUB_IOCTL_MAGIC, 6, __u8[6]))
> #define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u8[6]))
>
> Arnd
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-15  6:25     ` Masayuki Ohtake
@ 2010-06-15 10:42       ` Arnd Bergmann
  2010-06-15 12:12         ` Masayuki Ohtake
  0 siblings, 1 reply; 45+ messages in thread
From: Arnd Bergmann @ 2010-06-15 10:42 UTC (permalink / raw)
  To: Masayuki Ohtake; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

On Tuesday 15 June 2010, Masayuki Ohtake wrote:
> >This should not be necessary. Just use CONFIG_PCH_CAN_PCLK_50MHZ directly
> >in the code instead of the extra PCH_CAN_PCLK_50MHZ macro.
> 
> I have a question. I show the above reason.
> In case CAN is integrated as MODULE, macro name is CONFIG_PCH_CAN_PCLK_50MHZ_MODULE.
> On the other hand, integrated as built-in, CONFIG_PCH_CAN_PCLK_50MHZ.
> To prevent PHUB source code from integrated as MODULE or BUILT-IN,
> we re-define macro name in Makefile.
> 
> If use CONFIG_PCH_CAN_PCLK_50MHZ directly in the source code,
> in case buit-in, behavior is not correct.
> But in case module, behavior is not correct.

I don't understand the problem, because you have the definition

config PCH_CAN_PCLK_50MHZ
       bool "CAN PCLK 50MHz"
       depends on PCH_PHUB

which is 'bool', not 'tristate', so it can never be a module.
If you are referring to a dependency on the CAN code that is
not part of this patch, you can express this as

config PCH_CAN_PCLK_50MHZ
       bool "CAN PCLK 50MHz"
       depends on PCH_PHUB || CAN != "n"

This will leave CONFIG_PCH_CAN_PCLK_50MHZ as bool and let it only
get enabled if CONFIG_CAN is either "y" or "m".
Does that answer your question?

	Arnd

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-15 10:42       ` Arnd Bergmann
@ 2010-06-15 12:12         ` Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-15 12:12 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Arnd,

Thank you for your comments.
I can understand your intention.
I misunderstood about Kconfig behavior.

Thanks,
Ohtake.

----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML" <linux-kernel@vger.kernel.org>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y"
<yong.y.wang@intel.com>
Sent: Tuesday, June 15, 2010 7:42 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Tuesday 15 June 2010, Masayuki Ohtake wrote:
> > >This should not be necessary. Just use CONFIG_PCH_CAN_PCLK_50MHZ directly
> > >in the code instead of the extra PCH_CAN_PCLK_50MHZ macro.
> >
> > I have a question. I show the above reason.
> > In case CAN is integrated as MODULE, macro name is CONFIG_PCH_CAN_PCLK_50MHZ_MODULE.
> > On the other hand, integrated as built-in, CONFIG_PCH_CAN_PCLK_50MHZ.
> > To prevent PHUB source code from integrated as MODULE or BUILT-IN,
> > we re-define macro name in Makefile.
> >
> > If use CONFIG_PCH_CAN_PCLK_50MHZ directly in the source code,
> > in case buit-in, behavior is not correct.
> > But in case module, behavior is not correct.
>
> I don't understand the problem, because you have the definition
>
> config PCH_CAN_PCLK_50MHZ
>        bool "CAN PCLK 50MHz"
>        depends on PCH_PHUB
>
> which is 'bool', not 'tristate', so it can never be a module.
> If you are referring to a dependency on the CAN code that is
> not part of this patch, you can express this as
>
> config PCH_CAN_PCLK_50MHZ
>        bool "CAN PCLK 50MHz"
>        depends on PCH_PHUB || CAN != "n"
>
> This will leave CONFIG_PCH_CAN_PCLK_50MHZ as bool and let it only
> get enabled if CONFIG_CAN is either "y" or "m".
> Does that answer your question?
>
> Arnd
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-14 12:09 ` Masayuki Ohtak
  2010-06-14 12:50   ` Arnd Bergmann
@ 2010-06-17  2:43   ` Masayuki Ohtak
  2010-06-17 11:59     ` Arnd Bergmann
  2010-06-18  8:08     ` Wang, Yong Y
  1 sibling, 2 replies; 45+ messages in thread
From: Masayuki Ohtak @ 2010-06-17  2:43 UTC (permalink / raw)
  To: Alan Cox; +Cc: Masayuki Ohtak, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Alan,

We have modified for your comments.
Please Confirm below.

Thanks. 
Ohtake.


Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
 drivers/char/Kconfig             |   25 +
 drivers/char/Makefile            |    4 +
 drivers/char/pch_phub/Makefile   |    7 +
 drivers/char/pch_phub/pch_phub.c |  940 +++++++++++++++++++++++
 drivers/char/pch_phub/pch_phub.h |   58 ++
 5 files changed, 1034 insertions(+), 0 deletions(-)
 create mode 100644 drivers/char/pch_phub/Makefile
 create mode 100755 drivers/char/pch_phub/pch_phub.c
 create mode 100755 drivers/char/pch_phub/pch_phub.h

diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e023682..285ce78 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -4,6 +4,31 @@
 
 menu "Character devices"
 
+config PCH_IEEE1588
+	tristate "PCH IEEE1588"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  PCH IEEE1588 Host controller.
+
+config PCH_PHUB
+	tristate "PCH PHUB"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  PCH Packet Hub Host controller.
+	  This driver is for PCH Packet hub driver for Topcliff.
+	  This driver is integrated as built-in.
+	  This driver can access GbE MAC address.
+	  This driver can access HW register.
+	  You can also be integrated as module.
+
+config PCH_CAN_PCLK_50MHZ
+	bool "CAN PCLK 50MHz"
+	depends on PCH_PHUB
+        help
+          If you say yes to this option, clock is set to 50MHz.(For CAN control)
+
 config VT
 	bool "Virtual terminal" if EMBEDDED
 	depends on !S390
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index f957edf..dc092d0 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -111,6 +111,10 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
 obj-$(CONFIG_JS_RTC)		+= js-rtc.o
 js-rtc-y = rtc.o
 
+obj-$(CONFIG_PCH_IEEE1588)		+= pch_ieee1588/
+
+obj-$(CONFIG_PCH_PHUB)	+= pch_phub/
+
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c
 
diff --git a/drivers/char/pch_phub/Makefile b/drivers/char/pch_phub/Makefile
new file mode 100644
index 0000000..51ce785
--- /dev/null
+++ b/drivers/char/pch_phub/Makefile
@@ -0,0 +1,7 @@
+ifeq ($(CONFIG_PHUB_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_PCH_PHUB) += pch_phub_drv.o
+
+pch_phub_drv-objs := pch_phub.o
diff --git a/drivers/char/pch_phub/pch_phub.c b/drivers/char/pch_phub/pch_phub.c
new file mode 100755
index 0000000..be1bfe2
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.c
@@ -0,0 +1,940 @@
+/*!
+ * @file pch_phub.c
+ * @brief Provides all the implementation of the interfaces pertaining to
+ *		the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+/* includes */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+#include "pch_phub.h"
+
+/*--------------------------------------------
+	macros
+--------------------------------------------*/
+/* Status Register offset */
+#define PHUB_STATUS 0x00
+/* Control Register offset */
+#define PHUB_CONTROL 0x04
+/* Time out value for Status Register */
+#define PHUB_TIMEOUT 0x05
+/* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_ENABLE 0x01
+/* Disabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE 0x00
+/* ROM data area start address offset */
+#define PCH_PHUB_ROM_START_ADDR 0x14
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
+
+#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
+
+#define PCH_MINOR_NOS 1
+#define CLKCFG_CAN_50MHZ 0x12000000
+#define CLKCFG_CANCLK_MASK 0xFF000000
+
+#define MODULE_NAME "pch_phub"
+
+#define PCH_READ_REG(a)	ioread32(pch_phub_reg.pch_phub_base_address + (a))
+
+#define PCH_WRITE_REG(a, b) iowrite32((a), pch_phub_reg.pch_phub_base_address +\
+									 (b))
+/*--------------------------------------------
+	global variables
+--------------------------------------------*/
+/**
+ * struct pch_phub_reg_t - PHUB register structure
+ * @phub_id_reg:		 PHUB_ID register val
+ * @q_pri_val_reg:		 QUEUE_PRI_VAL register val
+ * @rc_q_maxsize_reg:	 RC_QUEUE_MAXSIZE register val
+ * @bri_q_maxsize_reg:	 BRI_QUEUE_MAXSIZE register val
+ * @comp_resp_timeout_reg:	 COMP_RESP_TIMEOUT register val
+ * @bus_slave_control_reg:	 BUS_SLAVE_CONTROL_REG register val
+ * @deadlock_avoid_type_reg:  DEADLOCK_AVOID_TYPE register val
+ * @intpin_reg_wpermit_reg0:  INTPIN_REG_WPERMIT register 0 val
+ * @intpin_reg_wpermit_reg1:  INTPIN_REG_WPERMIT register 1 val
+ * @intpin_reg_wpermit_reg2:  INTPIN_REG_WPERMIT register 2 val
+ * @intpin_reg_wpermit_reg3:  INTPIN_REG_WPERMIT register 3 val
+ * @int_reduce_control_reg:	 INT_REDUCE_CONTROL registers val
+ * @clkcfg_reg:		 CLK CFG register val
+ * @pch_phub_base_address:  register base address
+ * @pch_phub_extrom_base_address:  external rom base address
+ * @pch_phub_suspended: PHUB status val
+ */
+struct pch_phub_reg_t {
+	__u32 phub_id_reg;
+	__u32 q_pri_val_reg;
+	__u32 rc_q_maxsize_reg;
+	__u32 bri_q_maxsize_reg;
+	__u32 comp_resp_timeout_reg;
+	__u32 bus_slave_control_reg;
+	__u32 deadlock_avoid_type_reg;
+	__u32 intpin_reg_wpermit_reg0;
+	__u32 intpin_reg_wpermit_reg1;
+	__u32 intpin_reg_wpermit_reg2;
+	__u32 intpin_reg_wpermit_reg3;
+	__u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+#ifdef CONFIG_PCH_CAN_PCLK_50MHZ
+	__u32 clkcfg_reg;
+#endif
+	void __iomem *pch_phub_base_address;
+	void __iomem *pch_phub_extrom_base_address;
+	__s32 pch_phub_suspended;
+} pch_phub_reg;
+
+static DEFINE_MUTEX(pch_phub_ioctl_mutex);
+
+/* ToDo: major number allocation via module parameter */
+static dev_t pch_phub_dev_no;
+static __s32 pch_phub_major_no;
+static struct cdev pch_phub_dev;
+
+/*--------------------------------------------
+	functions implementations
+--------------------------------------------*/
+/** pch_phub_read_modify_write_reg - Implements the functionality of reading,
+ * 						modifying and writing register.
+ *  @reg_addr_offset:  Contains the register offset address value
+ *  @data:             Contains the writing value
+ *  @mask:             Contains the mask value
+ */
+static void pch_phub_read_modify_write_reg(__u32 reg_addr_offset,
+				       __u32 data, __u32 mask)
+{
+	void __iomem *reg_addr = pch_phub_reg.pch_phub_base_address +\
+							 reg_addr_offset;
+	iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+	return;
+}
+
+
+/** pch_phub_save_reg_conf - saves register configuration
+ */
+static void pch_phub_save_reg_conf(struct pci_dev *pdev)
+{
+	__u32 i = 0;
+
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	pch_phub_reg.phub_id_reg = PCH_READ_REG(PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	pch_phub_reg.q_pri_val_reg = PCH_READ_REG(PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	pch_phub_reg.rc_q_maxsize_reg =
+	    PCH_READ_REG(PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	pch_phub_reg.bri_q_maxsize_reg =
+	    PCH_READ_REG(PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	pch_phub_reg.comp_resp_timeout_reg =
+	    PCH_READ_REG(PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	pch_phub_reg.bus_slave_control_reg =
+	    PCH_READ_REG(PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	pch_phub_reg.deadlock_avoid_type_reg =
+	    PCH_READ_REG(PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	pch_phub_reg.intpin_reg_wpermit_reg0 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	pch_phub_reg.intpin_reg_wpermit_reg1 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	pch_phub_reg.intpin_reg_wpermit_reg2 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	pch_phub_reg.intpin_reg_wpermit_reg3 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+		"pch_phub_reg.phub_id_reg=%x, "
+		"pch_phub_reg.q_pri_val_reg=%x, "
+		"pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"pch_phub_reg.bus_slave_control_reg=%x, "
+		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		pch_phub_reg.phub_id_reg,
+		pch_phub_reg.q_pri_val_reg,
+		pch_phub_reg.rc_q_maxsize_reg,
+		pch_phub_reg.bri_q_maxsize_reg,
+		pch_phub_reg.comp_resp_timeout_reg,
+		pch_phub_reg.bus_slave_control_reg,
+		pch_phub_reg.deadlock_avoid_type_reg,
+		pch_phub_reg.intpin_reg_wpermit_reg0,
+		pch_phub_reg.intpin_reg_wpermit_reg1,
+		pch_phub_reg.intpin_reg_wpermit_reg2,
+		pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL registers */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		pch_phub_reg.int_reduce_control_reg[i] =
+		    PCH_READ_REG(
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, pch_phub_reg.int_reduce_control_reg[i]);
+	}
+#ifdef CONFIG_PCH_CAN_PCLK_50MHZ
+	/* save clk cfg register */
+	pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
+#endif
+	return;
+}
+
+/** pch_phub_restore_reg_conf - restore register configuration
+ */
+
+static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
+{
+	__u32 i;
+
+	dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	PCH_WRITE_REG(pch_phub_reg.phub_id_reg, PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	PCH_WRITE_REG(pch_phub_reg.q_pri_val_reg, PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	PCH_WRITE_REG(pch_phub_reg.rc_q_maxsize_reg,
+						PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	PCH_WRITE_REG(pch_phub_reg.bri_q_maxsize_reg,
+						PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	PCH_WRITE_REG(pch_phub_reg.comp_resp_timeout_reg,
+						PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	PCH_WRITE_REG(pch_phub_reg.bus_slave_control_reg,
+						PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	PCH_WRITE_REG(pch_phub_reg.deadlock_avoid_type_reg,
+					PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg0,
+					PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg1,
+					PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg2,
+					PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	PCH_WRITE_REG(pch_phub_reg.intpin_reg_wpermit_reg3,
+					PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+		"pch_phub_reg.phub_id_reg=%x, "
+		"pch_phub_reg.q_pri_val_reg=%x, "
+		"pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"pch_phub_reg.bus_slave_control_reg=%x, "
+		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		pch_phub_reg.phub_id_reg,
+		pch_phub_reg.q_pri_val_reg,
+		pch_phub_reg.rc_q_maxsize_reg,
+		pch_phub_reg.bri_q_maxsize_reg,
+		pch_phub_reg.comp_resp_timeout_reg,
+		pch_phub_reg.bus_slave_control_reg,
+		pch_phub_reg.deadlock_avoid_type_reg,
+		pch_phub_reg.intpin_reg_wpermit_reg0,
+		pch_phub_reg.intpin_reg_wpermit_reg1,
+		pch_phub_reg.intpin_reg_wpermit_reg2,
+		pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL register */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		PCH_WRITE_REG(pch_phub_reg.int_reduce_control_reg[i],
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, pch_phub_reg.int_reduce_control_reg[i]);
+	}
+
+#ifdef CONFIG_PCH_CAN_PCLK_50MHZ
+	/*restore the clock config reg */
+	PCH_WRITE_REG(pch_phub_reg.clkcfg_reg, CLKCFG_REG_OFFSET);
+#endif
+
+	return;
+}
+
+/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
+ *  									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_read_serial_rom(__u32 offset_address, __u8 *data)
+{
+	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+								 offset_address;
+
+	*data = ioread8(mem_addr);
+
+	return 0;
+}
+
+/** pch_phub_write_serial_rom - Implements the functionality of writing Serial
+ *  									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_write_serial_rom(__u32 offset_address,
+							 __u8 data)
+{
+	__s32 retval = 0;
+	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+						 (offset_address & 0xFFFFFFFC);
+	__s32 i = 0;
+	__u32 word_data = 0;
+
+	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+			pch_phub_reg.pch_phub_extrom_base_address +\
+								 PHUB_CONTROL);
+
+	word_data = ioread32(mem_addr);
+
+	switch (offset_address % 4) {
+	case 0:
+		word_data &= 0xFFFFFF00;
+		iowrite32((word_data | (__u32)data),
+						mem_addr);
+		break;
+	case 1:
+		word_data &= 0xFFFF00FF;
+		iowrite32((word_data | ((__u32)data << 8)),
+						mem_addr);
+		break;
+	case 2:
+		word_data &= 0xFF00FFFF;
+		iowrite32((word_data | ((__u32)data << 16)),
+						mem_addr);
+		break;
+	case 3:
+		word_data &= 0x00FFFFFF;
+		iowrite32((word_data | ((__u32)data << 24)),
+						mem_addr);
+		break;
+	}
+	while (0x00 !=
+	       ioread8(pch_phub_reg.pch_phub_extrom_base_address +\
+							 PHUB_STATUS)) {
+		msleep(1);
+		if (PHUB_TIMEOUT == i) {
+			retval = -EPERM;
+			break;
+		}
+		i++;
+	}
+
+	iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+			pch_phub_reg.pch_phub_extrom_base_address +\
+								 PHUB_CONTROL);
+
+	return retval;
+}
+
+/** pch_phub_read_serial_rom_val - Implements the functionality of reading
+ *  							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_read_serial_rom_val(__u32 offset_address, __u8 *data)
+{
+	__s32 retval = 0;
+	__u32 mem_addr;
+
+	mem_addr = (offset_address / 4 * 8) + 3 -
+			(offset_address % 4) + PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_read_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_write_serial_rom_val - Implements the functionality of writing
+ *  							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static __s32 pch_phub_write_serial_rom_val(__u32 offset_address,
+				     __u8 data)
+{
+	__s32 retval = 0;
+	__u32 mem_addr;
+
+	mem_addr =
+	    (offset_address / 4 * 8) + 3 - (offset_address % 4) +
+	    PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_write_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ *  						for Gigabit Ethernet MAC address
+ */
+static __s32 pch_phub_gbe_serial_rom_conf(void)
+{
+	__s32 retval = 0;
+
+	retval |= pch_phub_write_serial_rom(0x0b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x0a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x09, 0x01);
+	retval |= pch_phub_write_serial_rom(0x08, 0x02);
+
+	retval |= pch_phub_write_serial_rom(0x0f, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0e, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0d, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0c, 0x80);
+
+	retval |= pch_phub_write_serial_rom(0x13, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x12, 0x10);
+	retval |= pch_phub_write_serial_rom(0x11, 0x01);
+	retval |= pch_phub_write_serial_rom(0x10, 0x18);
+
+	retval |= pch_phub_write_serial_rom(0x1b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x1a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x19, 0x01);
+	retval |= pch_phub_write_serial_rom(0x18, 0x19);
+
+	retval |= pch_phub_write_serial_rom(0x23, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x22, 0x10);
+	retval |= pch_phub_write_serial_rom(0x21, 0x01);
+	retval |= pch_phub_write_serial_rom(0x20, 0x3a);
+
+	retval |= pch_phub_write_serial_rom(0x27, 0x01);
+	retval |= pch_phub_write_serial_rom(0x26, 0x00);
+	retval |= pch_phub_write_serial_rom(0x25, 0x00);
+	retval |= pch_phub_write_serial_rom(0x24, 0x00);
+
+	return retval;
+}
+
+/** pch_phub_read_gbe_mac_addr - Contains the Gigabit Ethernet MAC address
+ *  								offset value
+ *  @offset_address: Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+static __s32 pch_phub_read_gbe_mac_addr(__u32 offset_address, __u8 *data)
+{
+	__s32 retval = 0;
+
+	retval = pch_phub_read_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_write_gbe_mac_addr - Write MAC address
+ *  @offset_address: Contains the Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+static __s32 pch_phub_write_gbe_mac_addr(__u32 offset_address,
+				   __u8 data)
+{
+	__s32 retval = 0;
+
+	retval = pch_phub_gbe_serial_rom_conf();
+	retval |= pch_phub_write_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_read - Implements the read functionality of the Packet Hub module.
+ *  @file: Contains the reference of the file structure
+ *  @buf: Usermode buffer pointer
+ *  @size: Usermode buffer size
+ *  @ppos: Contains the reference of the file structure
+ */
+
+static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
+								 loff_t *ppos)
+{
+	__u32 rom_signature = 0;
+	__u8 rom_length;
+	__s32 ret_value;
+	__u32 tmp;
+	__u8 data;
+	__u32 addr_offset = 0;
+	__u32 orom_size;
+	loff_t pos = *ppos;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	/*Get Rom signature*/
+	pch_phub_read_serial_rom(0x80, (__u8 *)&rom_signature);
+	pch_phub_read_serial_rom(0x81, (__u8 *)&tmp);
+	rom_signature |= (tmp & 0xff) << 8;
+	if (rom_signature == 0xAA55) {
+		pch_phub_read_serial_rom(0x82, &rom_length);
+		orom_size = rom_length * 512;
+		if (orom_size < pos)
+			return 0;
+
+		for (addr_offset = 0; addr_offset < size; addr_offset++) {
+			pch_phub_read_serial_rom(0x80 + addr_offset + pos,
+									 &data);
+			ret_value = copy_to_user(&buf[addr_offset], &data, 1);
+			if (ret_value)
+				return -EFAULT;
+
+			if (orom_size < pos + addr_offset) {
+				*ppos += addr_offset;
+				return addr_offset;
+			}
+
+		}
+	} else {
+		return -ENOEXEC;
+	}
+	*ppos += addr_offset;
+	return addr_offset;
+}
+
+/** pch_phub_write - Implements the write functionality of the Packet Hub
+ *  									 module.
+ *  @file: Contains the reference of the file structure
+ *  @buf: Usermode buffer pointer
+ *  @size: Usermode buffer size
+ *  @ppos: Contains the reference of the file structure
+ */
+static ssize_t pch_phub_write(struct file *file, const char __user *buf,
+						 size_t size, loff_t *ppos)
+{
+	static __u32 data;
+	__s32 ret_value;
+	__u32 addr_offset = 0;
+	loff_t pos = *ppos;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	for (addr_offset = 0; addr_offset < size; addr_offset++) {
+		get_user(data, &buf[addr_offset]);
+
+		ret_value = pch_phub_write_serial_rom(0x80 + addr_offset + pos,
+								 data);
+		if (ret_value)
+			return -EFAULT;
+
+		if (PCH_PHUB_OROM_SIZE < pos + addr_offset) {
+			*ppos += addr_offset;
+			return addr_offset;
+		}
+
+	}
+
+	*ppos += addr_offset;
+	return addr_offset;
+}
+
+
+/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
+ *  								 Hub module.
+ *  @inode: Contains the reference of the inode structure
+ *  @file: Contains the reference of the file structure
+ *  @cmd: Contains the command value
+ *  @arg: Contains the command argument value
+ */
+
+
+static long pch_phub_ioctl(struct file *file, unsigned int cmd,
+							 unsigned long arg)
+{
+	__s32 ret_value = 0;
+	__u8 mac_addr[6];
+	__s32 ret;
+	__u32 i;
+	void __user *varg = (void __user *)arg;
+
+	ret = mutex_lock_interruptible(&pch_phub_ioctl_mutex);
+	if (ret) {
+		ret_value = -ERESTARTSYS;
+		goto return_nomutex;
+	}
+
+	if (pch_phub_reg.pch_phub_suspended == true) {
+		ret_value = -EPERM;
+		goto return_ioctrl;
+	}
+
+	switch (cmd) {
+	case IOCTL_PHUB_READ_MAC_ADDR:
+		for (i = 0; i < 6; i++)
+			pch_phub_read_gbe_mac_addr(i, &mac_addr[i]);
+
+		ret_value = copy_to_user(varg,
+					 mac_addr, sizeof(mac_addr));
+		if (ret_value) {
+			ret_value = -EFAULT;
+			goto return_ioctrl;
+		}
+		break;
+
+	case IOCTL_PHUB_WRITE_MAC_ADDR:
+		ret_value = copy_from_user(mac_addr, varg, sizeof(mac_addr));
+
+		if (ret_value) {
+			ret_value = -EFAULT;
+			goto return_ioctrl;
+		}
+		for (i = 0; i < 6; i++)
+			pch_phub_write_gbe_mac_addr(i, mac_addr[i]);
+		break;
+
+	default:
+		ret_value = -EINVAL;
+		break;
+	}
+return_ioctrl:
+	mutex_unlock(&pch_phub_ioctl_mutex);
+return_nomutex:
+	return ret_value;
+}
+
+
+/**
+ * file_operations structure initialization
+ */
+static const struct file_operations pch_phub_fops = {
+	.owner = THIS_MODULE,
+	.read = pch_phub_read,
+	.write = pch_phub_write,
+	.unlocked_ioctl = pch_phub_ioctl,
+};
+
+
+/** pch_phub_probe - Implements the probe functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @id: Contains the reference of the pci_device_id structure
+ */
+static __s32 __devinit pch_phub_probe(struct pci_dev *pdev,
+				       const struct pci_device_id *id)
+{
+
+	char *DRIVER_NAME = "pch_phub";
+	__s32 ret;
+	__u32 rom_size;
+
+	pch_phub_major_no = (pch_phub_major_no < 0 || pch_phub_major_no > 254) ?
+				0 : pch_phub_major_no;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"\npch_phub_probe : pci_enable_device FAILED");
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+			"pci_enable_device returns %d\n", ret);
+
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"pch_phub_probe : pci_request_regions FAILED");
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+		"pci_request_regions returns %d\n", ret);
+
+	pch_phub_reg.pch_phub_base_address = \
+					(void __iomem *)pci_iomap(pdev, 1, 0);
+
+	if (pch_phub_reg.pch_phub_base_address == 0) {
+		dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap FAILED");
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap SUCCESS and value "
+		"in pch_phub_base_address variable is 0x%08x\n",
+		(__u32)pch_phub_reg.pch_phub_base_address);
+
+	pch_phub_reg.pch_phub_extrom_base_address =
+	    (void __iomem *)pci_map_rom(pdev, &rom_size);
+	if (pch_phub_reg.pch_phub_extrom_base_address == 0) {
+		dev_dbg(&pdev->dev, "pch_phub_probe : pci_map_rom FAILED");
+		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+		"pci_map_rom SUCCESS and value in "
+		"pch_phub_extrom_base_address variable is 0x%08x\n",
+		(__u32)pch_phub_reg.pch_phub_extrom_base_address);
+
+	if (pch_phub_major_no) {
+		pch_phub_dev_no = MKDEV(pch_phub_major_no, 0);
+		ret = register_chrdev_region(pch_phub_dev_no,
+					   PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(&pdev->dev, "pch_phub_probe : "
+				"register_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				(void *)pch_phub_reg.pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(&pdev->dev, "pch_phub_probe : "
+				"register_chrdev_region returns %d\n", ret);
+	} else {
+		ret = alloc_chrdev_region(&pch_phub_dev_no, 0,
+						PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(&pdev->dev, "pch_phub_probe : "
+					"alloc_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				    (void *)pch_phub_reg.pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(&pdev->dev, "pch_phub_probe : "
+			"alloc_chrdev_region returns %d\n", ret);
+	}
+
+	cdev_init(&pch_phub_dev, &pch_phub_fops);
+	dev_dbg(&pdev->dev,
+			"pch_phub_probe :  cdev_init invoked successfully\n");
+
+	pch_phub_dev.owner = THIS_MODULE;
+	pch_phub_dev.ops = &pch_phub_fops;
+
+	ret = cdev_add(&pch_phub_dev, pch_phub_dev_no, PCH_MINOR_NOS);
+	if (ret) {
+		dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add FAILED");
+		unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+		pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add returns %d\n", ret);
+
+#ifdef CONFIG_PCH_CAN_PCLK_50MHZ
+	/*set the clock config reg if CAN clock is 50Mhz */
+	dev_dbg(&pdev->dev, "pch_phub_probe : invoking "
+		"pch_phub_read_modify_write_reg "
+		"to set CLKCFG reg for CAN clk 50Mhz\n");
+	pch_phub_read_modify_write_reg((__u32)CLKCFG_REG_OFFSET,
+					  CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+#endif
+	/* set the prefech value */
+	PCH_WRITE_REG(0x000ffffa, 0x14);
+	/* set the interrupt delay value */
+	PCH_WRITE_REG(0x25, 0x44);
+	return 0;
+
+err_probe:
+	dev_dbg(&pdev->dev, "pch_phub_probe returns %d\n", ret);
+	return ret;
+}
+
+/** pch_phub_remove - Implements the remove functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+
+	cdev_del(&pch_phub_dev);
+	dev_dbg(&pdev->dev,
+			"pch_phub_remove - cdev_del Invoked successfully\n");
+
+	unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"unregister_chrdev_region Invoked successfully\n");
+
+	pci_unmap_rom(pdev, (void *)pch_phub_reg.pch_phub_extrom_base_address);
+
+	pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+			"pci_iounmap Invoked successfully\n");
+
+	pci_release_regions(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"pci_release_regions Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"pci_disable_device Invoked successfully\n");
+
+}
+
+#ifdef CONFIG_PM
+
+/** pch_phub_suspend - Implements the suspend functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @state: Contains the reference of the pm_message_t structure
+ */
+static __s32 pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	__s32 ret;
+
+	pch_phub_reg.pch_phub_suspended = true;/* For blocking further IOCTLs */
+
+	pch_phub_save_reg_conf(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+		"pch_phub_save_reg_conf Invoked successfully\n");
+
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+			" pch_phub_suspend -pci_save_state returns-%d\n", ret);
+		return ret;
+	}
+	dev_dbg(&pdev->dev,
+			"pch_phub_suspend - pci_save_state returns %d\n", ret);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_disable_device Invoked successfully\n");
+
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_set_power_state Invoked successfully   "
+			"return = %d\n", 0);
+
+	return 0;
+}
+
+/** pch_phub_resume - Implements the resume functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static __s32 pch_phub_resume(struct pci_dev *pdev)
+{
+
+	__s32 ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pci_set_power_state Invoked successfully\n");
+
+	pci_restore_state(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pci_restore_state Invoked successfully\n");
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"pch_phub_resume-pci_enable_device failed ");
+		return ret;
+	}
+
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+			"pci_enable_device returns -%d\n", ret);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pch_phub_restore_reg_conf(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pch_phub_restore_reg_conf Invoked successfully\n");
+
+	pch_phub_reg.pch_phub_suspended = false;
+
+	dev_dbg(&pdev->dev, "pch_phub_resume  returns- %d\n", 0);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct pci_device_id pch_phub_pcidev_id[] = {
+
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+	{0,}
+};
+
+
+static struct pci_driver pch_phub_driver = {
+	.name = "pch_phub",
+	.id_table = pch_phub_pcidev_id,
+	.probe = pch_phub_probe,
+	.remove = __devexit_p(pch_phub_remove),
+#ifdef CONFIG_PM
+	.suspend = pch_phub_suspend,
+	.resume = pch_phub_resume
+#endif
+};
+
+/** pch_phub_pci_init - Implements the initialization functionality of
+ *  								 the module.
+ */
+static __s32 __init pch_phub_pci_init(void)
+{
+	__s32 ret;
+	ret = pci_register_driver(&pch_phub_driver);
+
+	return ret;
+}
+
+/** pch_phub_pci_exit - Implements the exit functionality of the module.
+ */
+static void __exit pch_phub_pci_exit(void)
+{
+	pci_unregister_driver(&pch_phub_driver);
+
+}
+
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);
+
+MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/char/pch_phub/pch_phub.h b/drivers/char/pch_phub/pch_phub.h
new file mode 100755
index 0000000..25d7c56
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.h
@@ -0,0 +1,58 @@
+#ifndef __PCH_PHUB_H__
+#define __PCH_PHUB_H__
+/*!
+ * @file pch_phub.h
+ * @brief Provides all the interfaces pertaining to the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+#define PHUB_IOCTL_MAGIC 		(0xf7)
+
+/*Outlines the read mac address function signature. */
+#define IOCTL_PHUB_READ_MAC_ADDR (_IOR(PHUB_IOCTL_MAGIC, 6, __u8[6]))
+
+/*brief Outlines the write mac address function signature. */
+#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u8[6]))
+
+
+/* Registers address offset */
+#define PCH_PHUB_PHUB_ID_REG			0x0000
+#define PCH_PHUB_QUEUE_PRI_VAL_REG		0x0004
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG		0x0008
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG		0x000C
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG		0x0010
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG		0x0014
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG	0x0018
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0	0x0020
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1	0x0024
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2	0x0028
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3	0x002C
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	0x0040
+#define CLKCFG_REG_OFFSET           		0x500
+
+#define PCH_PHUB_OROM_SIZE 15360
+
+#endif
-- 
1.6.0.6


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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-17  2:43   ` Masayuki Ohtak
@ 2010-06-17 11:59     ` Arnd Bergmann
  2010-06-17 23:49       ` Masayuki Ohtake
  2010-06-18  8:08     ` Wang, Yong Y
  1 sibling, 1 reply; 45+ messages in thread
From: Arnd Bergmann @ 2010-06-17 11:59 UTC (permalink / raw)
  To: Masayuki Ohtak; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Looks almost good to me now. Some more details (only the -EFAULT return code
is a real issue, the other ones are cosmetic changes):

On Thursday 17 June 2010, Masayuki Ohtak wrote:
> +
> +#define PCH_READ_REG(a)	ioread32(pch_phub_reg.pch_phub_base_address + (a))
> +
> +#define PCH_WRITE_REG(a, b) iowrite32((a), pch_phub_reg.pch_phub_base_address +\
> +									 (b))

I'd recommend just getting rid of these abstractions. You only use
them in one or two functions each, so you can just as well add a local
variable there and do

	void __iomem *p = pch_phub_reg.pch_phub_base_address;
	foo = ioread32(p + foo_offset);
	bar = ioread32(p + bar_offset);
	...

Not really important, but this way it would be more conventional
without having to write extra code.

> +/*--------------------------------------------
> +	global variables
> +--------------------------------------------*/
> +/**
> + * struct pch_phub_reg_t - PHUB register structure
> + * @phub_id_reg:		 PHUB_ID register val
> + * @q_pri_val_reg:		 QUEUE_PRI_VAL register val
> + * @rc_q_maxsize_reg:	 RC_QUEUE_MAXSIZE register val
> + * @bri_q_maxsize_reg:	 BRI_QUEUE_MAXSIZE register val
> + * @comp_resp_timeout_reg:	 COMP_RESP_TIMEOUT register val
> + * @bus_slave_control_reg:	 BUS_SLAVE_CONTROL_REG register val
> + * @deadlock_avoid_type_reg:  DEADLOCK_AVOID_TYPE register val
> + * @intpin_reg_wpermit_reg0:  INTPIN_REG_WPERMIT register 0 val
> + * @intpin_reg_wpermit_reg1:  INTPIN_REG_WPERMIT register 1 val
> + * @intpin_reg_wpermit_reg2:  INTPIN_REG_WPERMIT register 2 val
> + * @intpin_reg_wpermit_reg3:  INTPIN_REG_WPERMIT register 3 val
> + * @int_reduce_control_reg:	 INT_REDUCE_CONTROL registers val
> + * @clkcfg_reg:		 CLK CFG register val
> + * @pch_phub_base_address:  register base address
> + * @pch_phub_extrom_base_address:  external rom base address
> + * @pch_phub_suspended: PHUB status val
> + */
> +struct pch_phub_reg_t {

It would be better to drop the _t postfix on the type name.
By convention, we use this only for typedefs on simple data
types like off_t but not for structures.

> +	__u32 phub_id_reg;
> +	__u32 q_pri_val_reg;
> +	__u32 rc_q_maxsize_reg;

When I told you to change the ioctl arguments to use __u32 instead
of u32, I was only referring to those parts that are in the user-visible
section of the header file. While it does not hurt to use __u32 in
the kernel, you should understand the distinction.

> +/** pch_phub_write - Implements the write functionality of the Packet Hub
> + *  									 module.
> + *  @file: Contains the reference of the file structure
> + *  @buf: Usermode buffer pointer
> + *  @size: Usermode buffer size
> + *  @ppos: Contains the reference of the file structure
> + */
> +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> +						 size_t size, loff_t *ppos)
> +{
> +	static __u32 data;

No need to make data static.

> +	__s32 ret_value;
> +	__u32 addr_offset = 0;
> +	loff_t pos = *ppos;
> +
> +	if (pos < 0)
> +		return -EINVAL;
> +
> +	for (addr_offset = 0; addr_offset < size; addr_offset++) {
> +		get_user(data, &buf[addr_offset]);
> +
> +		ret_value = pch_phub_write_serial_rom(0x80 + addr_offset + pos,
> +								 data);
> +		if (ret_value)
> +			return -EFAULT;

You should return -EFAULT if the get_user() call fails, otherwise you have
a possible security hole. If pch_phub_write_serial_rom fails, the correct
return code would be -EIO.

> +/**
> + * file_operations structure initialization
> + */
> +static const struct file_operations pch_phub_fops = {
> +	.owner = THIS_MODULE,
> +	.read = pch_phub_read,
> +	.write = pch_phub_write,
> +	.unlocked_ioctl = pch_phub_ioctl,
> +};

If would be good to add a line of
	.llseek = default_llseek,
here. I have a patch to change the default llseek method to one
that disallows seeking, so if you add this line, there is one
less driver for me to patch.

	Arnd

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-17 11:59     ` Arnd Bergmann
@ 2010-06-17 23:49       ` Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-17 23:49 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew, LKML, Alan Cox

Hi Arnd,

I will modify for your comments by today or tomorrow.

Thanks,
Ohtake

----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML" <linux-kernel@vger.kernel.org>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y"
<yong.y.wang@intel.com>
Sent: Thursday, June 17, 2010 8:59 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> Looks almost good to me now. Some more details (only the -EFAULT return code
> is a real issue, the other ones are cosmetic changes):
>
> On Thursday 17 June 2010, Masayuki Ohtak wrote:
> > +
> > +#define PCH_READ_REG(a) ioread32(pch_phub_reg.pch_phub_base_address + (a))
> > +
> > +#define PCH_WRITE_REG(a, b) iowrite32((a), pch_phub_reg.pch_phub_base_address +\
> > + (b))
>
> I'd recommend just getting rid of these abstractions. You only use
> them in one or two functions each, so you can just as well add a local
> variable there and do
>
> void __iomem *p = pch_phub_reg.pch_phub_base_address;
> foo = ioread32(p + foo_offset);
> bar = ioread32(p + bar_offset);
> ...
>
> Not really important, but this way it would be more conventional
> without having to write extra code.
>
> > +/*--------------------------------------------
> > + global variables
> > +--------------------------------------------*/
> > +/**
> > + * struct pch_phub_reg_t - PHUB register structure
> > + * @phub_id_reg: PHUB_ID register val
> > + * @q_pri_val_reg: QUEUE_PRI_VAL register val
> > + * @rc_q_maxsize_reg: RC_QUEUE_MAXSIZE register val
> > + * @bri_q_maxsize_reg: BRI_QUEUE_MAXSIZE register val
> > + * @comp_resp_timeout_reg: COMP_RESP_TIMEOUT register val
> > + * @bus_slave_control_reg: BUS_SLAVE_CONTROL_REG register val
> > + * @deadlock_avoid_type_reg:  DEADLOCK_AVOID_TYPE register val
> > + * @intpin_reg_wpermit_reg0:  INTPIN_REG_WPERMIT register 0 val
> > + * @intpin_reg_wpermit_reg1:  INTPIN_REG_WPERMIT register 1 val
> > + * @intpin_reg_wpermit_reg2:  INTPIN_REG_WPERMIT register 2 val
> > + * @intpin_reg_wpermit_reg3:  INTPIN_REG_WPERMIT register 3 val
> > + * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val
> > + * @clkcfg_reg: CLK CFG register val
> > + * @pch_phub_base_address:  register base address
> > + * @pch_phub_extrom_base_address:  external rom base address
> > + * @pch_phub_suspended: PHUB status val
> > + */
> > +struct pch_phub_reg_t {
>
> It would be better to drop the _t postfix on the type name.
> By convention, we use this only for typedefs on simple data
> types like off_t but not for structures.
>
> > + __u32 phub_id_reg;
> > + __u32 q_pri_val_reg;
> > + __u32 rc_q_maxsize_reg;
>
> When I told you to change the ioctl arguments to use __u32 instead
> of u32, I was only referring to those parts that are in the user-visible
> section of the header file. While it does not hurt to use __u32 in
> the kernel, you should understand the distinction.
>
> > +/** pch_phub_write - Implements the write functionality of the Packet Hub
> > + *  module.
> > + *  @file: Contains the reference of the file structure
> > + *  @buf: Usermode buffer pointer
> > + *  @size: Usermode buffer size
> > + *  @ppos: Contains the reference of the file structure
> > + */
> > +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> > + size_t size, loff_t *ppos)
> > +{
> > + static __u32 data;
>
> No need to make data static.
>
> > + __s32 ret_value;
> > + __u32 addr_offset = 0;
> > + loff_t pos = *ppos;
> > +
> > + if (pos < 0)
> > + return -EINVAL;
> > +
> > + for (addr_offset = 0; addr_offset < size; addr_offset++) {
> > + get_user(data, &buf[addr_offset]);
> > +
> > + ret_value = pch_phub_write_serial_rom(0x80 + addr_offset + pos,
> > + data);
> > + if (ret_value)
> > + return -EFAULT;
>
> You should return -EFAULT if the get_user() call fails, otherwise you have
> a possible security hole. If pch_phub_write_serial_rom fails, the correct
> return code would be -EIO.
>
> > +/**
> > + * file_operations structure initialization
> > + */
> > +static const struct file_operations pch_phub_fops = {
> > + .owner = THIS_MODULE,
> > + .read = pch_phub_read,
> > + .write = pch_phub_write,
> > + .unlocked_ioctl = pch_phub_ioctl,
> > +};
>
> If would be good to add a line of
> .llseek = default_llseek,
> here. I have a patch to change the default llseek method to one
> that disallows seeking, so if you add this line, there is one
> less driver for me to patch.
>
> Arnd
>




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

* RE: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-17  2:43   ` Masayuki Ohtak
  2010-06-17 11:59     ` Arnd Bergmann
@ 2010-06-18  8:08     ` Wang, Yong Y
  2010-06-18 11:39       ` Masayuki Ohtake
  1 sibling, 1 reply; 45+ messages in thread
From: Wang, Yong Y @ 2010-06-18  8:08 UTC (permalink / raw)
  To: Masayuki Ohtak; +Cc: LKML, Khor, Andrew Chih Howe, Clark, Joel, Wang, Qi

> +config PCH_IEEE1588
> +	tristate "PCH IEEE1588"
> +	depends on PCI
> +	help
> +	  If you say yes to this option, support will be included for the
> +	  PCH IEEE1588 Host controller.
> +

Is this really supposed to be part of this patch?

> +config PCH_PHUB
> +	tristate "PCH PHUB"
> +	depends on PCI
> +	help
> +	  If you say yes to this option, support will be included for the
> +	  PCH Packet Hub Host controller.
> +	  This driver is for PCH Packet hub driver for Topcliff.
> +	  This driver is integrated as built-in.
> +	  This driver can access GbE MAC address.
> +	  This driver can access HW register.
> +	  You can also be integrated as module.
> +
> +config PCH_CAN_PCLK_50MHZ
> +	bool "CAN PCLK 50MHz"
> +	depends on PCH_PHUB
> +        help
> +          If you say yes to this option, clock is set to 50MHz.(For CAN
> control)
> +

Ohtak-san, I remember you said PCH_CAN_PCLK_50MHZ was in the patch
because you used to have a hw bug. If that hw bug has been fixed, this config
option shall also be removed. Otherwise, you have to build multiple kernel
binaries for different hardware configurations as Alan pointed out.

> diff --git a/drivers/char/Makefile b/drivers/char/Makefile
> index f957edf..dc092d0 100644
> --- a/drivers/char/Makefile
> +++ b/drivers/char/Makefile
> @@ -111,6 +111,10 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
>  obj-$(CONFIG_JS_RTC)		+= js-rtc.o
>  js-rtc-y = rtc.o
> 
> +obj-$(CONFIG_PCH_IEEE1588)		+= pch_ieee1588/
> +

Ditto


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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-18  8:08     ` Wang, Yong Y
@ 2010-06-18 11:39       ` Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-18 11:39 UTC (permalink / raw)
  To: Wang, Yong Y; +Cc: Wang, Qi, Clark, Joel, Khor, Andrew Chih Howe, LKML

Hi Yong Y

>> +config PCH_IEEE1588
>> + tristate "PCH IEEE1588"
>> + depends on PCI
>> + help
>> +   If you say yes to this option, support will be included for the
>> +   PCH IEEE1588 Host controller.
>> +

>Is this really supposed to be part of this patch?

> +obj-$(CONFIG_PCH_IEEE1588) += pch_ieee1588/
> +

Yes, the above is true.
Our driver under 'drivers/char' has patch order restriction.
Firstly, ieee1588 must be patched.
After the above, Phub is able to be patched.

Thus, our Phub patch includes ieee1588 code.

> Ohtak-san, I remember you said PCH_CAN_PCLK_50MHZ was in the patch
> because you used to have a hw bug. If that hw bug has been fixed, this config
> option shall also be removed. Otherwise, you have to build multiple kernel
> binaries for different hardware configurations as Alan pointed out.
Sorry, I gave wrong information to you.
Our CAN HW spec is that works only 50MHz.(Not HW bug)
According to our CAN hw spec, we will delete  'PCH_CAN_PCLK_50MHZ'.

Thanks,
Ohtake

----- Original Message ----- 
From: "Wang, Yong Y" <yong.y.wang@intel.com>
To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: "LKML" <linux-kernel@vger.kernel.org>; "Khor, Andrew Chih Howe" <andrew.chih.howe.khor@intel.com>; "Clark, Joel"
<joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>
Sent: Friday, June 18, 2010 5:08 PM
Subject: RE: [PATCH] Topcliff PHUB: Generate PacketHub driver


> +config PCH_IEEE1588
> + tristate "PCH IEEE1588"
> + depends on PCI
> + help
> +   If you say yes to this option, support will be included for the
> +   PCH IEEE1588 Host controller.
> +

Is this really supposed to be part of this patch?

> +config PCH_PHUB
> + tristate "PCH PHUB"
> + depends on PCI
> + help
> +   If you say yes to this option, support will be included for the
> +   PCH Packet Hub Host controller.
> +   This driver is for PCH Packet hub driver for Topcliff.
> +   This driver is integrated as built-in.
> +   This driver can access GbE MAC address.
> +   This driver can access HW register.
> +   You can also be integrated as module.
> +
> +config PCH_CAN_PCLK_50MHZ
> + bool "CAN PCLK 50MHz"
> + depends on PCH_PHUB
> +        help
> +          If you say yes to this option, clock is set to 50MHz.(For CAN
> control)
> +

Ohtak-san, I remember you said PCH_CAN_PCLK_50MHZ was in the patch
because you used to have a hw bug. If that hw bug has been fixed, this config
option shall also be removed. Otherwise, you have to build multiple kernel
binaries for different hardware configurations as Alan pointed out.

> diff --git a/drivers/char/Makefile b/drivers/char/Makefile
> index f957edf..dc092d0 100644
> --- a/drivers/char/Makefile
> +++ b/drivers/char/Makefile
> @@ -111,6 +111,10 @@ obj-$(CONFIG_PS3_FLASH) += ps3flash.o
>  obj-$(CONFIG_JS_RTC) += js-rtc.o
>  js-rtc-y = rtc.o
>
> +obj-$(CONFIG_PCH_IEEE1588) += pch_ieee1588/
> +

Ditto



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-30 18:28     ` Andy Isaacson
@ 2010-07-01  4:08       ` Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-07-01  4:08 UTC (permalink / raw)
  To: Andy Isaacson
  Cc: Arnd Bergmann, Wang, Yong Y, Wang Qi, Intel OTC, Andrew, Alan Cox, LKML

Hi Andy,

> 1. When writing comments, do not write comments that duplicate the code.
> Instead of writing
Our Phub patch I have resubmitted yesterday have been already modified above.

> 2. your register names are very long.  Since the #define names are
> private to this driver, there's no need to make them extremely
> descriptive.  Instead of naming your registers
> PCH_PHUB_PHUB_ID_REG, you should change the names to be shorter, like
> PHUB_ID_REG or PCH_ID_REG.  This will make your source code much more
> readable by reducing linewrapping.
This was our mistake.
I have modified PCH_PHUB_PHUB_ID_REG to PCH_PHUB_ID_REG.
Our Phub patch I have resubmitted yesterday have been already modified above.

> It sounds like PHUB is a system-level device which provides access to a
> SROM which contains GbE configuration data.  If that is correct, then I
> have two comments:
Yes, SROM has GbE configuration data (GbE mac address) .

>
> 1.  There are many other systems with similar configurations -- MIPS
> SiByte, Alpha SRM, SPARC OpenFirmware, and some ARM systems, just to
> name a few.  None of them expose the SROM as a custom /dev node AFAIK.
> Is there a shared infrastructure that you can implement?
Sorry, I can't understand your intension.
Please give me more detail.

>
> 2. How does your GbE driver get the MAC address from the SPROM?  If
> there is an in-kernel user of the PHUB interface, it might be much
> easier to understand the design.
PHUB HW transfers MAC address(in SROM) data to GbE register to set MAC address when boot processing.

Thanks, Ohtake
----- Original Message ----- 
From: "Andy Isaacson" <adi@hexapodia.org>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "Arnd Bergmann" <arnd@arndb.de>; "Wang, Yong Y" <yong.y.wang@intel.com>; "Wang Qi" <qi.wang@intel.com>; "Intel OTC"
<joel.clark@intel.com>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML"
<linux-kernel@vger.kernel.org>
Sent: Thursday, July 01, 2010 3:28 AM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Wed, Jun 30, 2010 at 02:58:25PM +0900, Masayuki Ohtake wrote:
> > > > + unsigned int i;
> > > > + void __iomem *p = pch_phub_reg.pch_phub_base_address;
> > > > +
> > > > + dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
> > > > + /* to store contents of PHUB_ID register */
> > > > + iowrite32(pch_phub_reg.phub_id_reg, p + PCH_PHUB_PHUB_ID_REG);
> > >
> > > Don't include comments that just duplicate the code.  Also, rename your
> > > constants from PCH_PHUB_PHUB_ to, I dunno, PHUB_ or something.
> >
> > Sorry, I can't understand your intention.
> > Please give us more information.
>
> My mistake, I merged two comments into one paragraph, let me clarify.
>
> 1. When writing comments, do not write comments that duplicate the code.
> Instead of writing
> /* store PHUB_ID */
> iowrite32(..._PHUB_ID_REG);
> /* store PHUB_FOO */
> iowrite32(..._PHUB_FOO_REG);
> you should delete the line-by-line comments and just write
> iowrite32(..._PHUB_ID_REG);
> iowrite32(..._PHUB_FOO_REG);
>
> 2. your register names are very long.  Since the #define names are
> private to this driver, there's no need to make them extremely
> descriptive.  Instead of naming your registers
> PCH_PHUB_PHUB_ID_REG, you should change the names to be shorter, like
> PHUB_ID_REG or PCH_ID_REG.  This will make your source code much more
> readable by reducing linewrapping.
>
> > > I seriously doubt that your device is special enough to warrant a custom
> > > /dev node with proprietary semantics.  If this is just part of an
> > > Ethernet driver, please implement it in drivers/net/; if this is a
> > > generic PROM accessor, there must be some semi-standardized EPROM access
> > > interface but I don't know what it is offhand.
> >
> > Since SROM is not in GbE HW but Phub HW, Phub is not part of Ethernet driver.
> > Packet hub is not generic driver but special device.
>
> It sounds like PHUB is a system-level device which provides access to a
> SROM which contains GbE configuration data.  If that is correct, then I
> have two comments:
>
> 1.  There are many other systems with similar configurations -- MIPS
> SiByte, Alpha SRM, SPARC OpenFirmware, and some ARM systems, just to
> name a few.  None of them expose the SROM as a custom /dev node AFAIK.
> Is there a shared infrastructure that you can implement?
>
> 2. How does your GbE driver get the MAC address from the SPROM?  If
> there is an in-kernel user of the PHUB interface, it might be much
> easier to understand the design.
>
> Thanks for responding to my review so quickly!
> -andy
>




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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-30  5:58   ` Masayuki Ohtake
@ 2010-06-30 18:28     ` Andy Isaacson
  2010-07-01  4:08       ` Masayuki Ohtake
  0 siblings, 1 reply; 45+ messages in thread
From: Andy Isaacson @ 2010-06-30 18:28 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: Arnd Bergmann, Wang, Yong Y, Wang Qi, Intel OTC, Andrew, Alan Cox, LKML

On Wed, Jun 30, 2010 at 02:58:25PM +0900, Masayuki Ohtake wrote:
> > > + unsigned int i;
> > > + void __iomem *p = pch_phub_reg.pch_phub_base_address;
> > > +
> > > + dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
> > > + /* to store contents of PHUB_ID register */
> > > + iowrite32(pch_phub_reg.phub_id_reg, p + PCH_PHUB_PHUB_ID_REG);
> >
> > Don't include comments that just duplicate the code.  Also, rename your
> > constants from PCH_PHUB_PHUB_ to, I dunno, PHUB_ or something.
> 
> Sorry, I can't understand your intention.
> Please give us more information.

My mistake, I merged two comments into one paragraph, let me clarify.

1. When writing comments, do not write comments that duplicate the code.
Instead of writing
	/* store PHUB_ID */
	iowrite32(..._PHUB_ID_REG);
	/* store PHUB_FOO */
	iowrite32(..._PHUB_FOO_REG);
you should delete the line-by-line comments and just write
	iowrite32(..._PHUB_ID_REG);
	iowrite32(..._PHUB_FOO_REG);

2. your register names are very long.  Since the #define names are
private to this driver, there's no need to make them extremely
descriptive.  Instead of naming your registers 
PCH_PHUB_PHUB_ID_REG, you should change the names to be shorter, like
PHUB_ID_REG or PCH_ID_REG.  This will make your source code much more
readable by reducing linewrapping.

> > I seriously doubt that your device is special enough to warrant a custom
> > /dev node with proprietary semantics.  If this is just part of an
> > Ethernet driver, please implement it in drivers/net/; if this is a
> > generic PROM accessor, there must be some semi-standardized EPROM access
> > interface but I don't know what it is offhand.
>
> Since SROM is not in GbE HW but Phub HW, Phub is not part of Ethernet driver.
> Packet hub is not generic driver but special device.

It sounds like PHUB is a system-level device which provides access to a
SROM which contains GbE configuration data.  If that is correct, then I
have two comments:

1.  There are many other systems with similar configurations -- MIPS
SiByte, Alpha SRM, SPARC OpenFirmware, and some ARM systems, just to
name a few.  None of them expose the SROM as a custom /dev node AFAIK.
Is there a shared infrastructure that you can implement?

2. How does your GbE driver get the MAC address from the SPROM?  If
there is an in-kernel user of the PHUB interface, it might be much
easier to understand the design.

Thanks for responding to my review so quickly!
-andy

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-29 23:31 ` Andy Isaacson
@ 2010-06-30  5:58   ` Masayuki Ohtake
  2010-06-30 18:28     ` Andy Isaacson
  0 siblings, 1 reply; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-30  5:58 UTC (permalink / raw)
  To: Andy Isaacson
  Cc: Arnd Bergmann, Wang, Yong Y, Wang Qi, Intel OTC, Andrew, Alan Cox, LKML

Hi Andy

Thank you for your comments.
Please refer to the following inline.
Thanks, Ohtake.

----- Original Message ----- 
From: "Andy Isaacson" <adi@hexapodia.org>
To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: "Arnd Bergmann" <arnd@arndb.de>; "Wang, Yong Y" <yong.y.wang@intel.com>; "Wang Qi" <qi.wang@intel.com>; "Intel OTC"
<joel.clark@intel.com>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML"
<linux-kernel@vger.kernel.org>
Sent: Wednesday, June 30, 2010 8:31 AM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Tue, Jun 22, 2010 at 02:33:01PM +0900, Masayuki Ohtak wrote:
> > +config PCH_PHUB
> > + tristate "PCH PHUB"
> > + depends on PCI
> > + help
> > +   If you say yes to this option, support will be included for the
> > +   PCH Packet Hub Host controller.
> > +   This driver is for PCH Packet hub driver for Topcliff.
>
> "Topcliff" is probably some kind of internal codename; please use a name

Topcliff is not internal codename but external product name.

> that will be visible to customers of this product.  References to what
> kind of device (IEEE standards it implements, what systems it might be
> present on, etc) are also appropriate.

I will add what kinds of device.

>
> > +   This driver is integrated as built-in.
>
> This sentence doesn't parse to me.  What are you trying to say?
>

I will modify above.

> > +   This driver can access GbE MAC address.
> > +   This driver can access HW register.
>
> I think you mean something more like "This driver allows access to the
> GbE MAC address and HW registers of the PCH Packet Hub."
>
> If this is a driver for an Ethernet MAC, what is it doing in
> drivers/char/ ?

In Topcliff, MAC address is in PHUB HW not in GbE HW.

>
> > +   You can also be integrated as module.
>
> Please look at any other tristate and copy the standard wording.

I will modify above.

>
> > +/*!
> > + * @file pch_phub.c
> > + * @brief Provides all the implementation of the interfaces pertaining to
> > + * the Packet Hub module.
>
> We don't normally merge comment markup languages other than kernel-doc.
> Please read Documentation/kernel-doc-nano-HOWTO.txt and follow it.  (Or,
> provide a pointer to documentation and tools for this mysterious markup
> language.)

I will modify above.

>
> > +/*
> > + * History:
> > + * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
> > + *
> > + * created:
> > + * OKI SEMICONDUCTOR 04/14/2010
> > + * modified:
>
> No changelogs in comments, that's what git history is for.

I will modify above.

>
> > +/* includes */
>
> Useless comment.

I will delete above.

>
> > +/*--------------------------------------------
> > + macros
> > +--------------------------------------------*/
>
> More useless comments.

I will delete above.

>
> > +/* Status Register offset */
> > +#define PHUB_STATUS 0x00
> > +/* Control Register offset */
> > +#define PHUB_CONTROL 0x04
>
> I would format this as:
>
> #define PHUB_STATUS     0x00    /* Status Register offset */
> #define PHUB_CONTROL    0x04    /* Control Register offset */
>
> but it's up to you.

I will modify above.

>
> > +struct pch_phub_reg {
> > + unsigned int phub_id_reg;
>
> Since these are used to hold HW-defined data, you should use fixed-size
> types such as u32.  Also, you should consider whether they should be
> marked little endian / big endian.

I will modify above.

>
> > +/* ToDo: major number allocation via module parameter */
> > +static dev_t pch_phub_dev_no;
> > +static int pch_phub_major_no;
> > +static struct cdev pch_phub_dev;
>
> If this is to remain a chardev, use register_chrdev().  You shouldn't
> need a module parameter to configure your device numbers.

I will delete module paramter.

>
> > + void __iomem *reg_addr = pch_phub_reg.pch_phub_base_address +\
> > + reg_addr_offset;
>
> That \ is superfluous.  There are several of these in this file.

I will delete uncecessary '\'.

>
> The indentation on the second line is too large, and the fact that
> "a = b + c" spills onto a second line is a clue that your struct names
> are too long.

We don't modify structure name this time.

>
> > + iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
> > + return;
>
> The return is unneeded if this remains a void function.  (many more
> occurrences.)

I will delete 'return' of  void function.

>
> > +/** pch_phub_restore_reg_conf - restore register configuration
> > + */
>
> Don't use /** unless you're using kernel-doc.

I will modify above.

>
> > + unsigned int i;
> > + void __iomem *p = pch_phub_reg.pch_phub_base_address;
> > +
> > + dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
> > + /* to store contents of PHUB_ID register */
> > + iowrite32(pch_phub_reg.phub_id_reg, p + PCH_PHUB_PHUB_ID_REG);
>
> Don't include comments that just duplicate the code.  Also, rename your
> constants from PCH_PHUB_PHUB_ to, I dunno, PHUB_ or something.

Sorry, I can't understand your intention.
Please give us more information.

>
> > +/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
> > + *  ROM.
> > + *  @offset_address: Contains the Serial ROM address offset value
> > + *  @data: Contains the Serial ROM value
> > + */
>
> This comment is almost correctly formatted, but there are extra words
> and some whitespace problems, and it doesn't document what actually
> happens.

I will modify above.

>
> +/**
> + * pch_phub_read_serial_rom - read PHUB Serial ROM.
> + *  @offset_address:   serial ROM offset to read.
> + *  @data:             pointer at which to store value that was read.
> + */
>
> is more correct.

I will modify above.

>
> Similar problems in several function comments below.
>
> > +static int pch_phub_read_serial_rom(unsigned int offset_address,
> > + unsigned char *data)
>
> The second line is indented too far.  We use 8-space tabstops, so the
> "u" of unsigned is all the way over under the "t" of offset_address.  It
> should either be two tabstops indented, or lined up with the previous
> argument.  (This applies to several functions below too.)

I will modify above.

>
> It should be "u8 *data".

I will modify above.

>
> > + void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
> > + offset_address;
> > +
> > + *data = ioread8(mem_addr);
> > +
> > + return 0;
>
> If this can't fail, why not have it just return the value rather than
> forcing the caller to provide a pointer?  (If you want to be futureproof
> and support errorhandling in the future, that's OK.)

I will modify to void.

>
> > +static int pch_phub_write_serial_rom(unsigned int offset_address,
> > + unsigned char data)
> > +{
> > + int retval = 0;
> > + void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
> > + (offset_address & 0xFFFFFFFC);
> > + int i = 0;
> > + unsigned int word_data = 0;
> > +
> > + iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
> > + pch_phub_reg.pch_phub_extrom_base_address +\
> > + PHUB_CONTROL);
> > +
> > + word_data = ioread32(mem_addr);
> > +
> > + switch (offset_address % 4) {
> > + case 0:
> > + word_data &= 0xFFFFFF00;
> > + iowrite32((word_data | (unsigned int)data),
> > + mem_addr);
> > + break;
>
> This function is much larger than need be.  Remove the 0xFFFFFFFC magic
> number -- something like
>
> #define PCH_WORD_ADDR_MASK (~((1 << 4) - 1))
>
> and implement the byte masking as something like
>
>     pos = (offset_address % 4) * 8;
>     mask = ~(0xFF << pos);
>     iowrite32((word_data & mask) | (u32)data << pos, mem_addr);
>
> (You can keep the switch if there's a significant performance benefit to
> doing so, but please provide measurements.)
I will modify.(This processing is not performance critical.)


>
> This is a read-modify-write cycle -- where is the locking if two users
> try to update the serial ROM simultaneously?  Any required locking
> should be documented in the kernel-doc comment.

I will modify using MUTEX like ioctl.

>
> > + while (0x00 !=
> > +        ioread8(pch_phub_reg.pch_phub_extrom_base_address +\
> > + PHUB_STATUS)) {
> > + msleep(1);
> > + if (PHUB_TIMEOUT == i) {
> > + retval = -EPERM;
> > + break;
> > + }
> > + i++;
>
> Rewrite this as a for loop (and remove the initialization from the
> declaration of i at the top of this function).  I am not sure if
> msleep() is safe here -- what context will this be called from?

This function is called from ioctl context(not interrput).
Thus, I think safe.

>
> > +/** pch_phub_read_serial_rom_val - Implements the functionality of reading
> > + *  Serial ROM value.
> > + *  @offset_address: Contains the Serial ROM address offset value
> > + *  @data: Contains the Serial ROM value
> > + */
> > +static int pch_phub_read_serial_rom_val(unsigned int offset_address,
> > + unsigned char *data)
> > +{
> > + int retval = 0;
> > + unsigned int mem_addr;
> > +
> > + mem_addr = (offset_address / 4 * 8) + 3 -
> > + (offset_address % 4) + PCH_PHUB_ROM_START_ADDR;
>
> Is that formula correct?   It is very suprising.
>
> If it is correct, the formula is bizarre enough to warrant a long
> comment explaining the theory of operation and/or pointing to hardware
> docs.

I will modify the above and add comments.


>
> > +static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
> > + loff_t *ppos)
> > +{
> > + unsigned int rom_signature = 0;
> > + unsigned char rom_length;
> > + int ret_value;
> > + unsigned int tmp;
> > + unsigned char data;
> > + unsigned int addr_offset = 0;
> > + unsigned int orom_size;
> > + loff_t pos = *ppos;
> > +
> > + if (pos < 0)
> > + return -EINVAL;
> > +
> > + /*Get Rom signature*/
> > + pch_phub_read_serial_rom(0x80, (unsigned char *)&rom_signature);
> > + pch_phub_read_serial_rom(0x81, (unsigned char *)&tmp);
>
> I seriously doubt that your device is special enough to warrant a custom
> /dev node with proprietary semantics.  If this is just part of an
> Ethernet driver, please implement it in drivers/net/; if this is a
> generic PROM accessor, there must be some semi-standardized EPROM access
> interface but I don't know what it is offhand.
Since SROM is not in GbE HW but Phub HW, Phub is not part of Ethernet driver.
Packet hub is not generic driver but special device.

>
> -andy
>






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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-22  5:33 Masayuki Ohtak
  2010-06-22 10:33 ` Masayuki Ohtak
  2010-06-22 11:30 ` Arnd Bergmann
@ 2010-06-29 23:31 ` Andy Isaacson
  2010-06-30  5:58   ` Masayuki Ohtake
  2 siblings, 1 reply; 45+ messages in thread
From: Andy Isaacson @ 2010-06-29 23:31 UTC (permalink / raw)
  To: Masayuki Ohtak
  Cc: Arnd Bergmann, Wang, Yong Y, Wang Qi, Intel OTC, Andrew, Alan Cox, LKML

On Tue, Jun 22, 2010 at 02:33:01PM +0900, Masayuki Ohtak wrote:
> +config PCH_PHUB
> +	tristate "PCH PHUB"
> +	depends on PCI
> +	help
> +	  If you say yes to this option, support will be included for the
> +	  PCH Packet Hub Host controller.
> +	  This driver is for PCH Packet hub driver for Topcliff.

"Topcliff" is probably some kind of internal codename; please use a name
that will be visible to customers of this product.  References to what
kind of device (IEEE standards it implements, what systems it might be
present on, etc) are also appropriate.

> +	  This driver is integrated as built-in.

This sentence doesn't parse to me.  What are you trying to say?

> +	  This driver can access GbE MAC address.
> +	  This driver can access HW register.

I think you mean something more like "This driver allows access to the
GbE MAC address and HW registers of the PCH Packet Hub."

If this is a driver for an Ethernet MAC, what is it doing in
drivers/char/ ?

> +	  You can also be integrated as module.

Please look at any other tristate and copy the standard wording.

> +/*!
> + * @file pch_phub.c
> + * @brief Provides all the implementation of the interfaces pertaining to
> + *		the Packet Hub module.

We don't normally merge comment markup languages other than kernel-doc.
Please read Documentation/kernel-doc-nano-HOWTO.txt and follow it.  (Or,
provide a pointer to documentation and tools for this mysterious markup
language.)

> +/*
> + * History:
> + * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
> + *
> + * created:
> + *	OKI SEMICONDUCTOR 04/14/2010
> + * modified:

No changelogs in comments, that's what git history is for.

> +/* includes */

Useless comment.

> +/*--------------------------------------------
> +	macros
> +--------------------------------------------*/

More useless comments.

> +/* Status Register offset */
> +#define PHUB_STATUS 0x00
> +/* Control Register offset */
> +#define PHUB_CONTROL 0x04

I would format this as:

#define PHUB_STATUS     0x00    /* Status Register offset */
#define PHUB_CONTROL    0x04    /* Control Register offset */

but it's up to you.

> +struct pch_phub_reg {
> +	unsigned int phub_id_reg;

Since these are used to hold HW-defined data, you should use fixed-size
types such as u32.  Also, you should consider whether they should be
marked little endian / big endian.

> +/* ToDo: major number allocation via module parameter */
> +static dev_t pch_phub_dev_no;
> +static int pch_phub_major_no;
> +static struct cdev pch_phub_dev;

If this is to remain a chardev, use register_chrdev().  You shouldn't
need a module parameter to configure your device numbers.

> +	void __iomem *reg_addr = pch_phub_reg.pch_phub_base_address +\
> +							 reg_addr_offset;

That \ is superfluous.  There are several of these in this file.

The indentation on the second line is too large, and the fact that
"a = b + c" spills onto a second line is a clue that your struct names
are too long.

> +	iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
> +	return;

The return is unneeded if this remains a void function.  (many more
occurrences.)

> +/** pch_phub_restore_reg_conf - restore register configuration
> + */

Don't use /** unless you're using kernel-doc.

> +	unsigned int i;
> +	void __iomem *p = pch_phub_reg.pch_phub_base_address;
> +
> +	dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
> +	/* to store contents of PHUB_ID register */
> +	iowrite32(pch_phub_reg.phub_id_reg, p + PCH_PHUB_PHUB_ID_REG);

Don't include comments that just duplicate the code.  Also, rename your
constants from PCH_PHUB_PHUB_ to, I dunno, PHUB_ or something.

> +/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
> + *  									 ROM.
> + *  @offset_address: Contains the Serial ROM address offset value
> + *  @data: Contains the Serial ROM value
> + */

This comment is almost correctly formatted, but there are extra words
and some whitespace problems, and it doesn't document what actually
happens.

+/**
+ * pch_phub_read_serial_rom - read PHUB Serial ROM.
+ *  @offset_address:   serial ROM offset to read.
+ *  @data:             pointer at which to store value that was read.
+ */

is more correct.

Similar problems in several function comments below.

> +static int pch_phub_read_serial_rom(unsigned int offset_address,
> +							 unsigned char *data)

The second line is indented too far.  We use 8-space tabstops, so the
"u" of unsigned is all the way over under the "t" of offset_address.  It
should either be two tabstops indented, or lined up with the previous
argument.  (This applies to several functions below too.)

It should be "u8 *data".

> +	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
> +								 offset_address;
> +
> +	*data = ioread8(mem_addr);
> +
> +	return 0;

If this can't fail, why not have it just return the value rather than
forcing the caller to provide a pointer?  (If you want to be futureproof
and support errorhandling in the future, that's OK.)

> +static int pch_phub_write_serial_rom(unsigned int offset_address,
> +							 unsigned char data)
> +{
> +	int retval = 0;
> +	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
> +						 (offset_address & 0xFFFFFFFC);
> +	int i = 0;
> +	unsigned int word_data = 0;
> +
> +	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
> +			pch_phub_reg.pch_phub_extrom_base_address +\
> +								 PHUB_CONTROL);
> +
> +	word_data = ioread32(mem_addr);
> +
> +	switch (offset_address % 4) {
> +	case 0:
> +		word_data &= 0xFFFFFF00;
> +		iowrite32((word_data | (unsigned int)data),
> +						mem_addr);
> +		break;

This function is much larger than need be.  Remove the 0xFFFFFFFC magic
number -- something like

#define PCH_WORD_ADDR_MASK (~((1 << 4) - 1))

and implement the byte masking as something like

    pos = (offset_address % 4) * 8;
    mask = ~(0xFF << pos);
    iowrite32((word_data & mask) | (u32)data << pos, mem_addr);

(You can keep the switch if there's a significant performance benefit to
doing so, but please provide measurements.)

This is a read-modify-write cycle -- where is the locking if two users
try to update the serial ROM simultaneously?  Any required locking
should be documented in the kernel-doc comment.

> +	while (0x00 !=
> +	       ioread8(pch_phub_reg.pch_phub_extrom_base_address +\
> +							 PHUB_STATUS)) {
> +		msleep(1);
> +		if (PHUB_TIMEOUT == i) {
> +			retval = -EPERM;
> +			break;
> +		}
> +		i++;

Rewrite this as a for loop (and remove the initialization from the
declaration of i at the top of this function).  I am not sure if
msleep() is safe here -- what context will this be called from?

> +/** pch_phub_read_serial_rom_val - Implements the functionality of reading
> + *  							 Serial ROM value.
> + *  @offset_address: Contains the Serial ROM address offset value
> + *  @data: Contains the Serial ROM value
> + */
> +static int pch_phub_read_serial_rom_val(unsigned int offset_address,
> +							 unsigned char *data)
> +{
> +	int retval = 0;
> +	unsigned int mem_addr;
> +
> +	mem_addr = (offset_address / 4 * 8) + 3 -
> +			(offset_address % 4) + PCH_PHUB_ROM_START_ADDR;

Is that formula correct?   It is very suprising.

If it is correct, the formula is bizarre enough to warrant a long
comment explaining the theory of operation and/or pointing to hardware
docs.

> +static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
> +								 loff_t *ppos)
> +{
> +	unsigned int rom_signature = 0;
> +	unsigned char rom_length;
> +	int ret_value;
> +	unsigned int tmp;
> +	unsigned char data;
> +	unsigned int addr_offset = 0;
> +	unsigned int orom_size;
> +	loff_t pos = *ppos;
> +
> +	if (pos < 0)
> +		return -EINVAL;
> +
> +	/*Get Rom signature*/
> +	pch_phub_read_serial_rom(0x80, (unsigned char *)&rom_signature);
> +	pch_phub_read_serial_rom(0x81, (unsigned char *)&tmp);

I seriously doubt that your device is special enough to warrant a custom
/dev node with proprietary semantics.  If this is just part of an
Ethernet driver, please implement it in drivers/net/; if this is a
generic PROM accessor, there must be some semi-standardized EPROM access
interface but I don't know what it is offhand.

-andy

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-22 22:12   ` Andrew Morton
@ 2010-06-23  0:31     ` Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-23  0:31 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Arnd Bergmann, Wang, Yong Y, qi.wang, joel.clark,
	andrew.chih.howe.khor, Alan Cox, LKML

Hi Andrew

Thank you for your comments.
We will resubmit modified our patch by tomorrow or day after tomorrow at the latest.

Thanks.
Ohtake
----- Original Message ----- 
From: "Andrew Morton" <akpm@linux-foundation.org>
To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: "Arnd Bergmann" <arnd@arndb.de>; "Wang, Yong Y" <yong.y.wang@intel.com>; <qi.wang@intel.com>;
<joel.clark@intel.com>; <andrew.chih.howe.khor@intel.com>; "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML"
<linux-kernel@vger.kernel.org>
Sent: Wednesday, June 23, 2010 7:12 AM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Tue, 22 Jun 2010 19:33:34 +0900
> Masayuki Ohtak <masa-korg@dsn.okisemi.com> wrote:
>
> > Hi Arnd and Yong Y
> >
> > We have updated phub patch about the following.
> >  * Arnd's commnets
> > * Delete PCH_READ_REG/PCH_WRITE_REG
> > * Delete '_t' prefix
> > * Modify basic type
> > * Delete needless 'static' prefix
> > * Modify returned value
> > * Care returned value of get_user()
> > * Add .llseek line
> >
> >  * Yong Y's comments
> > * Applying to the latest checkpatch(2.6.35)
> > * Delete unused 'DEBUG' macro in Makefile
> > * Delete IEEE1588 lines
> > * Delete 'PCH_CAN_PCLK_50MHZ'
> >
> > Thanks, Ohtake.
> >
> > Kernel=2.6.33.1
> > Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
>
> Please prepare a proper changelog for the patch - one which is suitabe
> for inclusion in the kernel's permanent git record.  Include that
> changelog with each version of the patch, perhaps after alterations.
>
> Please describe the module parameters in that changelog.  Please
> describe the major/minor number handling within the changelog -
> permitting the major number to be specified on the modprobe command
> line is unusual and should be fully described and justified, please.
>
> Please ensure that the changelog tells us what the driver actually
> does!  I don't even know what a "PCH packet hub" _is_ :(
>
> >
> > ...
> >
> > --- /dev/null
> > +++ b/drivers/char/pch_phub/pch_phub.c
> > @@ -0,0 +1,937 @@
> > +/*!
> > + * @file pch_phub.c
> > + * @brief Provides all the implementation of the interfaces pertaining to
> > + * the Packet Hub module.
> > + * @version 1.0.0.0
> > + * @section
>
> This appears to use a markup format whcih the kernel doesn't implement.
>
> > + * 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.
> > + */
> >
> > ...
> >
> > +/** pch_phub_read_modify_write_reg - Implements the functionality of reading,
> > + * modifying and writing register.
> > + *  @reg_addr_offset:  Contains the register offset address value
> > + *  @data:             Contains the writing value
> > + *  @mask:             Contains the mask value
> > + */
>
> kerneldoc comments are usually formatted as
>
> /**
>  *  foo() - do something
>  *  @arg1 ...
>
> I don't know whether the layout whcih this driver uses will be properly
> handled by the kerneldoc tools, but I'd suggest that it all be
> converted to the more usual style for consistency.
>
> > +static void pch_phub_read_modify_write_reg(unsigned int reg_addr_offset,
> > +        unsigned int data, unsigned int mask)
> > +{
> > + void __iomem *reg_addr = pch_phub_reg.pch_phub_base_address +\
> > + reg_addr_offset;
> > + iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
> > + return;
> > +}
> > +
> > +
> > +/** pch_phub_save_reg_conf - saves register configuration
> > + */
>
> The driver has quite a lot of comments which use the kerneldoc toke
> "/**" but which don't really look like they wre intended to be
> kerneldoc comments.  So I'd suggest converting these to plain old comments:
>
> /*
>  * pch_phub_save_reg_conf - saves register configuration
>  */
>
> or
>
> /* pch_phub_save_reg_conf - saves register configuration */
>
>
> or finish off the kerneldoc work by documenting the arguments (and the
> return values, please).
>
> > +static void pch_phub_save_reg_conf(struct pci_dev *pdev)
> > +{
> > + unsigned int i = 0;
> > + void __iomem *p = pch_phub_reg.pch_phub_base_address;
> > +
> > + dev_dbg(&pdev->dev, "pch_phub_save_reg_conf ENTRY\n");
> > + /* to store contents of PHUB_ID register */
> > + pch_phub_reg.phub_id_reg = ioread32(p + PCH_PHUB_PHUB_ID_REG);
> > + /* to store contents of QUEUE_PRI_VAL register */
> > + pch_phub_reg.q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG);
> > + /* to store contents of RC_QUEUE_MAXSIZE register */
> > + pch_phub_reg.rc_q_maxsize_reg =
> > +     ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
> > + /* to store contents of BRI_QUEUE_MAXSIZE register */
> > + pch_phub_reg.bri_q_maxsize_reg =
> > +     ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
> > + /* to store contents of COMP_RESP_TIMEOUT register */
> > + pch_phub_reg.comp_resp_timeout_reg =
> > +     ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
> > + /* to store contents of BUS_SLAVE_CONTROL_REG register */
> > + pch_phub_reg.bus_slave_control_reg =
> > +     ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
> > + /* to store contents of DEADLOCK_AVOID_TYPE register */
> > + pch_phub_reg.deadlock_avoid_type_reg =
> > +     ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
> > + /* to store contents of INTPIN_REG_WPERMIT register 0 */
> > + pch_phub_reg.intpin_reg_wpermit_reg0 =
> > +     ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
> > + /* to store contents of INTPIN_REG_WPERMIT register 1 */
> > + pch_phub_reg.intpin_reg_wpermit_reg1 =
> > +     ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
> > + /* to store contents of INTPIN_REG_WPERMIT register 2 */
> > + pch_phub_reg.intpin_reg_wpermit_reg2 =
> > +     ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
> > + /* to store contents of INTPIN_REG_WPERMIT register 3 */
>
> s/to //g
>
> > + pch_phub_reg.intpin_reg_wpermit_reg3 =
> > +     ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
> > + dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
> > + "pch_phub_reg.phub_id_reg=%x, "
> > + "pch_phub_reg.q_pri_val_reg=%x, "
> > + "pch_phub_reg.rc_q_maxsize_reg=%x, "
> > + "pch_phub_reg.bri_q_maxsize_reg=%x, "
> > + "pch_phub_reg.comp_resp_timeout_reg=%x, "
> > + "pch_phub_reg.bus_slave_control_reg=%x, "
> > + "pch_phub_reg.deadlock_avoid_type_reg=%x, "
> > + "pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
> > + "pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
> > + "pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
> > + "pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
> > + pch_phub_reg.phub_id_reg,
> > + pch_phub_reg.q_pri_val_reg,
> > + pch_phub_reg.rc_q_maxsize_reg,
> > + pch_phub_reg.bri_q_maxsize_reg,
> > + pch_phub_reg.comp_resp_timeout_reg,
> > + pch_phub_reg.bus_slave_control_reg,
> > + pch_phub_reg.deadlock_avoid_type_reg,
> > + pch_phub_reg.intpin_reg_wpermit_reg0,
> > + pch_phub_reg.intpin_reg_wpermit_reg1,
> > + pch_phub_reg.intpin_reg_wpermit_reg2,
> > + pch_phub_reg.intpin_reg_wpermit_reg3);
> > + /* to store contents of INT_REDUCE_CONTROL registers */
> > + for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
> > + pch_phub_reg.int_reduce_control_reg[i] =
> > +     ioread32(p +
> > + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
> > + dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
> > + "pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
> > + i, pch_phub_reg.int_reduce_control_reg[i]);
> > + }
> > + /* save clk cfg register */
> > + pch_phub_reg.clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
> > +
> > + return;
> > +}
> > +
> >
> > ...
> >
> > +static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
> > +{
> > + unsigned int i;
> > + void __iomem *p = pch_phub_reg.pch_phub_base_address;
> > +
> > + dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
> > + /* to store contents of PHUB_ID register */
> > + iowrite32(pch_phub_reg.phub_id_reg, p + PCH_PHUB_PHUB_ID_REG);
> > + /* to store contents of QUEUE_PRI_VAL register */
> > + iowrite32(pch_phub_reg.q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG);
> > + /* to store contents of RC_QUEUE_MAXSIZE register */
> > + iowrite32(pch_phub_reg.rc_q_maxsize_reg,
> > + p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
> > + /* to store contents of BRI_QUEUE_MAXSIZE register */
> > + iowrite32(pch_phub_reg.bri_q_maxsize_reg,
> > + p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
> > + /* to store contents of COMP_RESP_TIMEOUT register */
> > + iowrite32(pch_phub_reg.comp_resp_timeout_reg,
> > + p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
> > + /* to store contents of BUS_SLAVE_CONTROL_REG register */
> > + iowrite32(pch_phub_reg.bus_slave_control_reg,
> > + p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
> > + /* to store contents of DEADLOCK_AVOID_TYPE register */
> > + iowrite32(pch_phub_reg.deadlock_avoid_type_reg,
> > + p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
> > + /* to store contents of INTPIN_REG_WPERMIT register 0 */
> > + iowrite32(pch_phub_reg.intpin_reg_wpermit_reg0,
> > + p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
> > + /* to store contents of INTPIN_REG_WPERMIT register 1 */
> > + iowrite32(pch_phub_reg.intpin_reg_wpermit_reg1,
> > + p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
> > + /* to store contents of INTPIN_REG_WPERMIT register 2 */
> > + iowrite32(pch_phub_reg.intpin_reg_wpermit_reg2,
> > + p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
> > + /* to store contents of INTPIN_REG_WPERMIT register 3 */
> > + iowrite32(pch_phub_reg.intpin_reg_wpermit_reg3,
> > + p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
> > + dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
> > + "pch_phub_reg.phub_id_reg=%x, "
> > + "pch_phub_reg.q_pri_val_reg=%x, "
> > + "pch_phub_reg.rc_q_maxsize_reg=%x, "
> > + "pch_phub_reg.bri_q_maxsize_reg=%x, "
> > + "pch_phub_reg.comp_resp_timeout_reg=%x, "
> > + "pch_phub_reg.bus_slave_control_reg=%x, "
> > + "pch_phub_reg.deadlock_avoid_type_reg=%x, "
> > + "pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
> > + "pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
> > + "pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
> > + "pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
> > + pch_phub_reg.phub_id_reg,
> > + pch_phub_reg.q_pri_val_reg,
> > + pch_phub_reg.rc_q_maxsize_reg,
> > + pch_phub_reg.bri_q_maxsize_reg,
> > + pch_phub_reg.comp_resp_timeout_reg,
> > + pch_phub_reg.bus_slave_control_reg,
> > + pch_phub_reg.deadlock_avoid_type_reg,
> > + pch_phub_reg.intpin_reg_wpermit_reg0,
> > + pch_phub_reg.intpin_reg_wpermit_reg1,
> > + pch_phub_reg.intpin_reg_wpermit_reg2,
> > + pch_phub_reg.intpin_reg_wpermit_reg3);
> > + /* to store contents of INT_REDUCE_CONTROL register */
> > + for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
> > + iowrite32(pch_phub_reg.int_reduce_control_reg[i],
> > + p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
> > + dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
> > + "pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
> > + i, pch_phub_reg.int_reduce_control_reg[i]);
> > + }
> > +
> > + /*restore the clock config reg */
>
> One space after the /*, please.
>
> > + iowrite32(pch_phub_reg.clkcfg_reg, p + CLKCFG_REG_OFFSET);
> > +
> > + return;
> > +}
> > +
> > +/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
> > + * ROM.
> > + *  @offset_address: Contains the Serial ROM address offset value
> > + *  @data: Contains the Serial ROM value
> > + */
> > +static int pch_phub_read_serial_rom(unsigned int offset_address,
> > + unsigned char *data)
> > +{
> > + void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
> > + offset_address;
>
> Unneeded \.  There are several instances of this in the driver.
>
> > + *data = ioread8(mem_addr);
> > +
> > + return 0;
> > +}
> > +
> > +/** pch_phub_write_serial_rom - Implements the functionality of writing Serial
> > + * ROM.
>
> Strange layout.  I don't know what this will look like after kerneldoc
> processing - it might make a mess.  Conventional layout is
>
> /**
>  * pch_phub_write_serial_rom - Implements the functionality of writing Serial ROM.
>
> or
>
> /**
>  * pch_phub_write_serial_rom - Implements the functionality of writing Serial
>  * ROM.
>
> (there are several instances of this).
>
>
> > + *  @offset_address: Contains the Serial ROM address offset value
> > + *  @data: Contains the Serial ROM value
> > + */
> > +static int pch_phub_write_serial_rom(unsigned int offset_address,
> > + unsigned char data)
> > +{
> > + int retval = 0;
> > + void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
> > + (offset_address & 0xFFFFFFFC);
> > + int i = 0;
> > + unsigned int word_data = 0;
> > +
> > + iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
> > + pch_phub_reg.pch_phub_extrom_base_address +\
> > + PHUB_CONTROL);
> > +
> > + word_data = ioread32(mem_addr);
>
> The driver tends to do
>
> int foo = 0;
>
> ...
>
> foo = ...
>
> in quite a lot of places.  The initialisation to zero is harmless - the
> compiler will take it out again.  But it's unusual and jsut adds noise.
>
> The compiler will warn about use of uninitialised variables anyway.  In
> fact this unnecessary initalisation will suppress compiler warnings
> which might have revealed real bugs.  I'd suggest that they all be
> removed (there are quite a lot in this driver).
>
> > + switch (offset_address % 4) {
> > + case 0:
> > + word_data &= 0xFFFFFF00;
> > + iowrite32((word_data | (unsigned int)data),
> > + mem_addr);
> > + break;
> > + case 1:
> > + word_data &= 0xFFFF00FF;
> > + iowrite32((word_data | ((unsigned int)data << 8)),
> > + mem_addr);
> > + break;
> > + case 2:
> > + word_data &= 0xFF00FFFF;
> > + iowrite32((word_data | ((unsigned int)data << 16)),
> > + mem_addr);
> > + break;
> > + case 3:
> > + word_data &= 0x00FFFFFF;
> > + iowrite32((word_data | ((unsigned int)data << 24)),
> > + mem_addr);
> > + break;
> > + }
> > + while (0x00 !=
> > +        ioread8(pch_phub_reg.pch_phub_extrom_base_address +\
> > + PHUB_STATUS)) {
> > + msleep(1);
> > + if (PHUB_TIMEOUT == i) {
> > + retval = -EPERM;
> > + break;
> > + }
> > + i++;
> > + }
> > +
> > + iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
> > + pch_phub_reg.pch_phub_extrom_base_address +\
> > + PHUB_CONTROL);
> > +
> > + return retval;
> > +}
> > +
> >
> > ...
> >
> > +static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
> > + loff_t *ppos)
> > +{
> > + unsigned int rom_signature = 0;
> > + unsigned char rom_length;
> > + int ret_value;
> > + unsigned int tmp;
> > + unsigned char data;
> > + unsigned int addr_offset = 0;
> > + unsigned int orom_size;
> > + loff_t pos = *ppos;
> > +
> > + if (pos < 0)
> > + return -EINVAL;
>
> I think vfs_read() -> rw_verify_area() already did that, so indovidual
> ->read() implementations don't need to check for negative offset.
>
> > + /*Get Rom signature*/
>
> Spaces after /* and before */, please.
>
> > + pch_phub_read_serial_rom(0x80, (unsigned char *)&rom_signature);
> > + pch_phub_read_serial_rom(0x81, (unsigned char *)&tmp);
> > + rom_signature |= (tmp & 0xff) << 8;
> > + if (rom_signature == 0xAA55) {
> > + pch_phub_read_serial_rom(0x82, &rom_length);
> > + orom_size = rom_length * 512;
> > + if (orom_size < pos)
> > + return 0;
> > +
> > + for (addr_offset = 0; addr_offset < size; addr_offset++) {
> > + pch_phub_read_serial_rom(0x80 + addr_offset + pos,
> > + &data);
> > + ret_value = copy_to_user(&buf[addr_offset], &data, 1);
> > + if (ret_value)
> > + return -EFAULT;
> > +
> > + if (orom_size < pos + addr_offset) {
> > + *ppos += addr_offset;
> > + return addr_offset;
> > + }
> > +
> > + }
> > + } else {
> > + return -ENOEXEC;
>
> ENOEXEC means "your executable file doesn't have suitable contents".
> If this error gets propagated to userspace the poor user will be
> wondering who corrupted his ELF files and would be surprised to find
> out that the error in fact came from his packethub driver.
>
> So please use a more appropriate errno here.
>
> > + }
> > + *ppos += addr_offset;
> > + return addr_offset;
> > +}
> > +
> > +/** pch_phub_write - Implements the write functionality of the Packet Hub
> > + * module.
> > + *  @file: Contains the reference of the file structure
> > + *  @buf: Usermode buffer pointer
> > + *  @size: Usermode buffer size
> > + *  @ppos: Contains the reference of the file structure
> > + */
> > +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> > + size_t size, loff_t *ppos)
> > +{
> > + unsigned int data;
> > + int ret_value;
> > + unsigned int addr_offset = 0;
> > + loff_t pos = *ppos;
> > +
> > + if (pos < 0)
> > + return -EINVAL;
>
> vfs_write() already did that.
>
> > + for (addr_offset = 0; addr_offset < size; addr_offset++) {
> > + ret_value = get_user(data, &buf[addr_offset]);
> > + if (ret_value)
> > + return -EFAULT;
> > +
> > + ret_value = pch_phub_write_serial_rom(0x80 + addr_offset + pos,
> > + data);
> > + if (ret_value)
> > + return -EIO;
>
> This overwrites the pch_phub_write_serial_rom() return value.  it's
> generally better to propagate error return values instead of replacing
> them with different ones.
>
> otoh pch_phub_write_serial_rom() can return -EPERM.  "Operation not
> permitted.  An attempt was made to perform an operation limited to
> processes with appropriate privileges or to the owner of a file or
> other resource.".  That doesn't sound like an appropriate errno for a
> driver to use?
>
> > + if (PCH_PHUB_OROM_SIZE < pos + addr_offset) {
> > + *ppos += addr_offset;
> > + return addr_offset;
> > + }
> > +
> > + }
> > +
> > + *ppos += addr_offset;
> > + return addr_offset;
> > +}
> > +
> > +
> > +/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
> > + * Hub module.
> > + *  @inode: Contains the reference of the inode structure
> > + *  @file: Contains the reference of the file structure
> > + *  @cmd: Contains the command value
> > + *  @arg: Contains the command argument value
> > + */
> > +
> > +
> > +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> > + unsigned long arg)
> > +{
> > + int ret_value = 0;
> > + __u8 mac_addr[6];
> > + int ret;
> > + unsigned int i;
> > + void __user *varg = (void __user *)arg;
> > +
> > + ret = mutex_lock_interruptible(&pch_phub_ioctl_mutex);
> > + if (ret) {
> > + ret_value = -ERESTARTSYS;
> > + goto return_nomutex;
> > + }
>
> A plain old `return -ERESTARTSYS' is OK here.
>
> > + if (pch_phub_reg.pch_phub_suspended == true) {
> > + ret_value = -EPERM;
>
> EPERM?
>
> > + goto return_ioctrl;
> > + }
> > +
> > + switch (cmd) {
> > + case IOCTL_PHUB_READ_MAC_ADDR:
> > + for (i = 0; i < 6; i++)
> > + pch_phub_read_gbe_mac_addr(i, &mac_addr[i]);
> > +
> > + ret_value = copy_to_user(varg,
> > + mac_addr, sizeof(mac_addr));
> > + if (ret_value) {
> > + ret_value = -EFAULT;
> > + goto return_ioctrl;
> > + }
>
> The goto is unneeded.
>
> > + break;
> > +
> > + case IOCTL_PHUB_WRITE_MAC_ADDR:
> > + ret_value = copy_from_user(mac_addr, varg, sizeof(mac_addr));
> > +
> > + if (ret_value) {
> > + ret_value = -EFAULT;
> > + goto return_ioctrl;
> > + }
>
> Could do a `break'.
>
> > + for (i = 0; i < 6; i++)
> > + pch_phub_write_gbe_mac_addr(i, mac_addr[i]);
> > + break;
> > +
> > + default:
> > + ret_value = -EINVAL;
> > + break;
> > + }
> > +return_ioctrl:
> > + mutex_unlock(&pch_phub_ioctl_mutex);
> > +return_nomutex:
> > + return ret_value;
> > +}
> > +
> > +
> > +/**
> > + * file_operations structure initialization
> > + */
>
> That's not a kerneldoc comment, but it has the /** kerneldoc token.
>
> > +static const struct file_operations pch_phub_fops = {
> > + .owner = THIS_MODULE,
> > + .read = pch_phub_read,
> > + .write = pch_phub_write,
> > + .unlocked_ioctl = pch_phub_ioctl,
> > + .llseek = default_llseek
> > +};
> > +
> > +
> > +/** pch_phub_probe - Implements the probe functionality of the module.
> > + *  @pdev: Contains the reference of the pci_dev structure
> > + *  @id: Contains the reference of the pci_device_id structure
> > + */
> > +static int __devinit pch_phub_probe(struct pci_dev *pdev,
> > +        const struct pci_device_id *id)
> > +{
> > + char *DRIVER_NAME = "pch_phub";
>
> hm, why was that upper case?
>
> Maybe use MODULE_NAME instead?  Or
>
> static const char driver_name[] = "pch_phub";
>
> > + int ret;
> > + unsigned int rom_size;
> > +
> > + pch_phub_major_no = (pch_phub_major_no < 0 || pch_phub_major_no > 254) ?
> > + 0 : pch_phub_major_no;
>
> This looks odd - should be explained in code comments and/or changelog.
>
> > + ret = pci_enable_device(pdev);
> > + if (ret) {
> > + dev_dbg(&pdev->dev,
> > + "\npch_phub_probe : pci_enable_device FAILED");
> > + goto err_probe;
> > + }
> > + dev_dbg(&pdev->dev, "pch_phub_probe : "
> > + "pci_enable_device returns %d\n", ret);
> > +
> > + ret = pci_request_regions(pdev, DRIVER_NAME);
> > + if (ret) {
> > + dev_dbg(&pdev->dev,
> > + "pch_phub_probe : pci_request_regions FAILED");
> > + pci_disable_device(pdev);
> > + goto err_probe;
> > + }
> > + dev_dbg(&pdev->dev, "pch_phub_probe : "
> > + "pci_request_regions returns %d\n", ret);
> > +
> > + pch_phub_reg.pch_phub_base_address = \
> > + (void __iomem *)pci_iomap(pdev, 1, 0);
>
> Unneeded and undesirable typeast.
>
> > + if (pch_phub_reg.pch_phub_base_address == 0) {
> > + dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap FAILED");
> > + pci_release_regions(pdev);
> > + pci_disable_device(pdev);
> > + ret = -ENOMEM;
> > + goto err_probe;
> > + }
> > + dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap SUCCESS and value "
> > + "in pch_phub_base_address variable is 0x%08x\n",
> > + (unsigned int)pch_phub_reg.pch_phub_base_address);
> > +
> > + pch_phub_reg.pch_phub_extrom_base_address =
> > +     (void __iomem *)pci_map_rom(pdev, &rom_size);
>
> Ditto
>
> > + if (pch_phub_reg.pch_phub_extrom_base_address == 0) {
> > + dev_dbg(&pdev->dev, "pch_phub_probe : pci_map_rom FAILED");
> > + pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
> > + pci_release_regions(pdev);
> > + pci_disable_device(pdev);
>
> This is getting painful.  I'd suggest removal of the duplicated code
> via the standard `goto out_iounmap' unwinding approach.
>
> > + ret = -ENOMEM;
> > + goto err_probe;
> > + }
> > + dev_dbg(&pdev->dev, "pch_phub_probe : "
> > + "pci_map_rom SUCCESS and value in "
> > + "pch_phub_extrom_base_address variable is 0x%08x\n",
> > + (unsigned int)pch_phub_reg.pch_phub_extrom_base_address);
> > +
> > + if (pch_phub_major_no) {
> > + pch_phub_dev_no = MKDEV(pch_phub_major_no, 0);
> > + ret = register_chrdev_region(pch_phub_dev_no,
> > +    PCH_MINOR_NOS, DRIVER_NAME);
> > + if (ret) {
> > + dev_dbg(&pdev->dev, "pch_phub_probe : "
> > + "register_chrdev_region FAILED");
> > + pci_unmap_rom(pdev,
> > + (void *)pch_phub_reg.pch_phub_extrom_base_address);
> > + pci_iounmap(pdev,
> > + (void *)pch_phub_reg.pch_phub_base_address);
>
> More unneeded typecasts.
>
> > + pci_release_regions(pdev);
> > + pci_disable_device(pdev);
> > + goto err_probe;
> > + }
> > + dev_dbg(&pdev->dev, "pch_phub_probe : "
> > + "register_chrdev_region returns %d\n", ret);
> > + } else {
> > + ret = alloc_chrdev_region(&pch_phub_dev_no, 0,
> > + PCH_MINOR_NOS, DRIVER_NAME);
> > + if (ret) {
> > + dev_dbg(&pdev->dev, "pch_phub_probe : "
> > + "alloc_chrdev_region FAILED");
> > + pci_unmap_rom(pdev,
> > + (void *)pch_phub_reg.pch_phub_extrom_base_address);
> > + pci_iounmap(pdev,
> > +     (void *)pch_phub_reg.pch_phub_base_address);
>
> more..
>
> > + pci_release_regions(pdev);
> > + pci_disable_device(pdev);
> > + goto err_probe;
> > + }
> > + dev_dbg(&pdev->dev, "pch_phub_probe : "
> > + "alloc_chrdev_region returns %d\n", ret);
> > + }
> > +
> > + cdev_init(&pch_phub_dev, &pch_phub_fops);
> > + dev_dbg(&pdev->dev,
> > + "pch_phub_probe :  cdev_init invoked successfully\n");
> > +
> > + pch_phub_dev.owner = THIS_MODULE;
> > + pch_phub_dev.ops = &pch_phub_fops;
> > +
> > + ret = cdev_add(&pch_phub_dev, pch_phub_dev_no, PCH_MINOR_NOS);
> > + if (ret) {
> > + dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add FAILED");
> > + unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
> > + pci_unmap_rom(pdev,
> > + (void *)pch_phub_reg.pch_phub_extrom_base_address);
> > + pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
> > + pci_release_regions(pdev);
> > + pci_disable_device(pdev);
> > + goto err_probe;
> > + }
> > + dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add returns %d\n", ret);
> > +
> > + /*set the clock config reg if CAN clock is 50Mhz */
> > + dev_dbg(&pdev->dev, "pch_phub_probe : invoking "
> > + "pch_phub_read_modify_write_reg "
> > + "to set CLKCFG reg for CAN clk 50Mhz\n");
> > + pch_phub_read_modify_write_reg((unsigned int)CLKCFG_REG_OFFSET,
> > +   CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
> > +
> > + /* set the prefech value */
> > + iowrite32(0x000ffffa, pch_phub_reg.pch_phub_base_address + 0x14);
> > + /* set the interrupt delay value */
> > + iowrite32(0x25, pch_phub_reg.pch_phub_base_address + 0x44);
> > + return 0;
> > +
> > +err_probe:
> > + dev_dbg(&pdev->dev, "pch_phub_probe returns %d\n", ret);
> > + return ret;
> > +}
> > +
> >
> > ...
> >
> > +#ifdef CONFIG_PM
> > +
> > +/** pch_phub_suspend - Implements the suspend functionality of the module.
> > + *  @pdev: Contains the reference of the pci_dev structure
> > + *  @state: Contains the reference of the pm_message_t structure
> > + */
> > +static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
> > +{
> > + int ret;
> > +
> > + pch_phub_reg.pch_phub_suspended = true;/* For blocking further IOCTLs */
> > +
> > + pch_phub_save_reg_conf(pdev);
> > + dev_dbg(&pdev->dev, "pch_phub_suspend - "
> > + "pch_phub_save_reg_conf Invoked successfully\n");
> > +
> > + ret = pci_save_state(pdev);
> > + if (ret) {
> > + dev_dbg(&pdev->dev,
> > + " pch_phub_suspend -pci_save_state returns-%d\n", ret);
> > + return ret;
> > + }
> > + dev_dbg(&pdev->dev,
> > + "pch_phub_suspend - pci_save_state returns %d\n", ret);
> > + pci_enable_wake(pdev, PCI_D3hot, 0);
> > + dev_dbg(&pdev->dev, "pch_phub_suspend - "
> > + "pci_enable_wake Invoked successfully\n");
> > +
> > + pci_disable_device(pdev);
> > + dev_dbg(&pdev->dev, "pch_phub_suspend - "
> > + "pci_disable_device Invoked successfully\n");
> > +
> > + pci_set_power_state(pdev, pci_choose_state(pdev, state));
> > + dev_dbg(&pdev->dev, "pch_phub_suspend - "
> > + "pci_set_power_state Invoked successfully   "
> > + "return = %d\n", 0);
> > +
> > + return 0;
> > +}
> > +
> > +/** pch_phub_resume - Implements the resume functionality of the module.
> > + *  @pdev: Contains the reference of the pci_dev structure
> > + */
> > +static int pch_phub_resume(struct pci_dev *pdev)
> > +{
> > +
> > + int ret;
> > +
> > + pci_set_power_state(pdev, PCI_D0);
> > + dev_dbg(&pdev->dev, "pch_phub_resume - "
> > + "pci_set_power_state Invoked successfully\n");
> > +
> > + pci_restore_state(pdev);
> > + dev_dbg(&pdev->dev, "pch_phub_resume - "
> > + "pci_restore_state Invoked successfully\n");
> > +
> > + ret = pci_enable_device(pdev);
> > + if (ret) {
> > + dev_dbg(&pdev->dev,
> > + "pch_phub_resume-pci_enable_device failed ");
> > + return ret;
> > + }
> > +
> > + dev_dbg(&pdev->dev, "pch_phub_resume - "
> > + "pci_enable_device returns -%d\n", ret);
> > +
> > + pci_enable_wake(pdev, PCI_D3hot, 0);
> > + dev_dbg(&pdev->dev, "pch_phub_resume - "
> > + "pci_enable_wake Invoked successfully\n");
> > +
> > + pch_phub_restore_reg_conf(pdev);
> > + dev_dbg(&pdev->dev, "pch_phub_resume - "
> > + "pch_phub_restore_reg_conf Invoked successfully\n");
> > +
> > + pch_phub_reg.pch_phub_suspended = false;
> > +
> > + dev_dbg(&pdev->dev, "pch_phub_resume  returns- %d\n", 0);
> > + return 0;
> > +}
>
> Here you can put
>
> #else
> #define pch_phub_suspend NULL
> #define pch_phub_resume NULL
>
> > +#endif /* CONFIG_PM */
> > +
> > +static struct pci_device_id pch_phub_pcidev_id[] = {
> > +
> > + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
> > + {0,}
> > +};
> > +
> > +
> > +static struct pci_driver pch_phub_driver = {
> > + .name = "pch_phub",
> > + .id_table = pch_phub_pcidev_id,
> > + .probe = pch_phub_probe,
> > + .remove = __devexit_p(pch_phub_remove),
> > +#ifdef CONFIG_PM
> > + .suspend = pch_phub_suspend,
> > + .resume = pch_phub_resume
> > +#endif
>
> and then remove this ifdef.
>
> >
> > ...
> >
> > --- /dev/null
> > +++ b/drivers/char/pch_phub/pch_phub.h
> > @@ -0,0 +1,58 @@
> > +#ifndef __PCH_PHUB_H__
> > +#define __PCH_PHUB_H__
> > +/*!
> > + * @file pch_phub.h
> > + * @brief Provides all the interfaces pertaining to the Packet Hub module.
> > + * @version 1.0.0.0
> > + * @section
>
> ?
>
> > + * 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.
> > + */
> > +
> > +/*
> > + * History:
> > + * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
> > + *
> > + * created:
> > + * OKI SEMICONDUCTOR 04/14/2010
> > + * modified:
> > + *
> > + */
> > +
> > +#define PHUB_IOCTL_MAGIC (0xf7)
> > +
> > +/*Outlines the read mac address function signature. */
>
> Space after /*, please (check the whole patch)
>
> > +#define IOCTL_PHUB_READ_MAC_ADDR (_IOR(PHUB_IOCTL_MAGIC, 6, __u8[6]))
> > +
> > +/*brief Outlines the write mac address function signature. */
> > +#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u8[6]))
>
> "brief"?
>
> I didn't notice any documentation for these ioctls anywhere?
>
> > +
> > +/* Registers address offset */
> > +#define PCH_PHUB_PHUB_ID_REG 0x0000
> > +#define PCH_PHUB_QUEUE_PRI_VAL_REG 0x0004
> > +#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG 0x0008
> > +#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG 0x000C
> > +#define PCH_PHUB_COMP_RESP_TIMEOUT_REG 0x0010
> > +#define PCH_PHUB_BUS_SLAVE_CONTROL_REG 0x0014
> > +#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG 0x0018
> > +#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0 0x0020
> > +#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1 0x0024
> > +#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2 0x0028
> > +#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3 0x002C
> > +#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE 0x0040
> > +#define CLKCFG_REG_OFFSET 0x500
> > +
> > +#define PCH_PHUB_OROM_SIZE 15360
> > +
> > +#endif
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-22 10:33 ` Masayuki Ohtak
@ 2010-06-22 22:12   ` Andrew Morton
  2010-06-23  0:31     ` Masayuki Ohtake
  0 siblings, 1 reply; 45+ messages in thread
From: Andrew Morton @ 2010-06-22 22:12 UTC (permalink / raw)
  To: Masayuki Ohtak
  Cc: Arnd Bergmann, Wang, Yong Y, qi.wang, joel.clark,
	andrew.chih.howe.khor, Alan Cox, LKML

On Tue, 22 Jun 2010 19:33:34 +0900
Masayuki Ohtak <masa-korg@dsn.okisemi.com> wrote:

> Hi Arnd and Yong Y
> 
> We have updated phub patch about the following.
>  * Arnd's commnets
> 	 * Delete PCH_READ_REG/PCH_WRITE_REG
> 	 * Delete '_t' prefix
> 	 * Modify basic type
> 	 * Delete needless 'static' prefix
> 	 * Modify returned value
> 	 * Care returned value of get_user()
> 	 * Add .llseek line
> 
>  * Yong Y's comments
> 	 * Applying to the latest checkpatch(2.6.35)
> 	 * Delete unused 'DEBUG' macro in Makefile
> 	 * Delete IEEE1588 lines
> 	 * Delete 'PCH_CAN_PCLK_50MHZ'
> 
> Thanks, Ohtake.
> 
> Kernel=2.6.33.1
> Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>

Please prepare a proper changelog for the patch - one which is suitabe
for inclusion in the kernel's permanent git record.  Include that
changelog with each version of the patch, perhaps after alterations.

Please describe the module parameters in that changelog.  Please
describe the major/minor number handling within the changelog -
permitting the major number to be specified on the modprobe command
line is unusual and should be fully described and justified, please.

Please ensure that the changelog tells us what the driver actually
does!  I don't even know what a "PCH packet hub" _is_ :(

>
> ...
>
> --- /dev/null
> +++ b/drivers/char/pch_phub/pch_phub.c
> @@ -0,0 +1,937 @@
> +/*!
> + * @file pch_phub.c
> + * @brief Provides all the implementation of the interfaces pertaining to
> + *		the Packet Hub module.
> + * @version 1.0.0.0
> + * @section

This appears to use a markup format whcih the kernel doesn't implement.

> + * 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.
> + */
>
> ...
>
> +/** pch_phub_read_modify_write_reg - Implements the functionality of reading,
> + *					 modifying and writing register.
> + *  @reg_addr_offset:  Contains the register offset address value
> + *  @data:             Contains the writing value
> + *  @mask:             Contains the mask value
> + */

kerneldoc comments are usually formatted as

/**
 *  foo() - do something
 *  @arg1 ...

I don't know whether the layout whcih this driver uses will be properly
handled by the kerneldoc tools, but I'd suggest that it all be
converted to the more usual style for consistency.

> +static void pch_phub_read_modify_write_reg(unsigned int reg_addr_offset,
> +				       unsigned int data, unsigned int mask)
> +{
> +	void __iomem *reg_addr = pch_phub_reg.pch_phub_base_address +\
> +							 reg_addr_offset;
> +	iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
> +	return;
> +}
> +
> +
> +/** pch_phub_save_reg_conf - saves register configuration
> + */

The driver has quite a lot of comments which use the kerneldoc toke
"/**" but which don't really look like they wre intended to be
kerneldoc comments.  So I'd suggest converting these to plain old comments:

/*
 * pch_phub_save_reg_conf - saves register configuration
 */

or

/* pch_phub_save_reg_conf - saves register configuration */


or finish off the kerneldoc work by documenting the arguments (and the
return values, please).

> +static void pch_phub_save_reg_conf(struct pci_dev *pdev)
> +{
> +	unsigned int i = 0;
> +	void __iomem *p = pch_phub_reg.pch_phub_base_address;
> +
> +	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf ENTRY\n");
> +	/* to store contents of PHUB_ID register */
> +	pch_phub_reg.phub_id_reg = ioread32(p + PCH_PHUB_PHUB_ID_REG);
> +	/* to store contents of QUEUE_PRI_VAL register */
> +	pch_phub_reg.q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG);
> +	/* to store contents of RC_QUEUE_MAXSIZE register */
> +	pch_phub_reg.rc_q_maxsize_reg =
> +	    ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
> +	/* to store contents of BRI_QUEUE_MAXSIZE register */
> +	pch_phub_reg.bri_q_maxsize_reg =
> +	    ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
> +	/* to store contents of COMP_RESP_TIMEOUT register */
> +	pch_phub_reg.comp_resp_timeout_reg =
> +	    ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
> +	/* to store contents of BUS_SLAVE_CONTROL_REG register */
> +	pch_phub_reg.bus_slave_control_reg =
> +	    ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
> +	/* to store contents of DEADLOCK_AVOID_TYPE register */
> +	pch_phub_reg.deadlock_avoid_type_reg =
> +	    ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
> +	/* to store contents of INTPIN_REG_WPERMIT register 0 */
> +	pch_phub_reg.intpin_reg_wpermit_reg0 =
> +	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
> +	/* to store contents of INTPIN_REG_WPERMIT register 1 */
> +	pch_phub_reg.intpin_reg_wpermit_reg1 =
> +	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
> +	/* to store contents of INTPIN_REG_WPERMIT register 2 */
> +	pch_phub_reg.intpin_reg_wpermit_reg2 =
> +	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
> +	/* to store contents of INTPIN_REG_WPERMIT register 3 */

s/to //g

> +	pch_phub_reg.intpin_reg_wpermit_reg3 =
> +	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
> +	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
> +		"pch_phub_reg.phub_id_reg=%x, "
> +		"pch_phub_reg.q_pri_val_reg=%x, "
> +		"pch_phub_reg.rc_q_maxsize_reg=%x, "
> +		"pch_phub_reg.bri_q_maxsize_reg=%x, "
> +		"pch_phub_reg.comp_resp_timeout_reg=%x, "
> +		"pch_phub_reg.bus_slave_control_reg=%x, "
> +		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
> +		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
> +		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
> +		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
> +		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
> +		pch_phub_reg.phub_id_reg,
> +		pch_phub_reg.q_pri_val_reg,
> +		pch_phub_reg.rc_q_maxsize_reg,
> +		pch_phub_reg.bri_q_maxsize_reg,
> +		pch_phub_reg.comp_resp_timeout_reg,
> +		pch_phub_reg.bus_slave_control_reg,
> +		pch_phub_reg.deadlock_avoid_type_reg,
> +		pch_phub_reg.intpin_reg_wpermit_reg0,
> +		pch_phub_reg.intpin_reg_wpermit_reg1,
> +		pch_phub_reg.intpin_reg_wpermit_reg2,
> +		pch_phub_reg.intpin_reg_wpermit_reg3);
> +	/* to store contents of INT_REDUCE_CONTROL registers */
> +	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
> +		pch_phub_reg.int_reduce_control_reg[i] =
> +		    ioread32(p +
> +			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
> +		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
> +			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
> +			i, pch_phub_reg.int_reduce_control_reg[i]);
> +	}
> +	/* save clk cfg register */
> +	pch_phub_reg.clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
> +
> +	return;
> +}
> +
>
> ...
>
> +static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
> +{
> +	unsigned int i;
> +	void __iomem *p = pch_phub_reg.pch_phub_base_address;
> +
> +	dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
> +	/* to store contents of PHUB_ID register */
> +	iowrite32(pch_phub_reg.phub_id_reg, p + PCH_PHUB_PHUB_ID_REG);
> +	/* to store contents of QUEUE_PRI_VAL register */
> +	iowrite32(pch_phub_reg.q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG);
> +	/* to store contents of RC_QUEUE_MAXSIZE register */
> +	iowrite32(pch_phub_reg.rc_q_maxsize_reg,
> +					p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
> +	/* to store contents of BRI_QUEUE_MAXSIZE register */
> +	iowrite32(pch_phub_reg.bri_q_maxsize_reg,
> +					p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
> +	/* to store contents of COMP_RESP_TIMEOUT register */
> +	iowrite32(pch_phub_reg.comp_resp_timeout_reg,
> +					p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
> +	/* to store contents of BUS_SLAVE_CONTROL_REG register */
> +	iowrite32(pch_phub_reg.bus_slave_control_reg,
> +					p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
> +	/* to store contents of DEADLOCK_AVOID_TYPE register */
> +	iowrite32(pch_phub_reg.deadlock_avoid_type_reg,
> +					p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
> +	/* to store contents of INTPIN_REG_WPERMIT register 0 */
> +	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg0,
> +					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
> +	/* to store contents of INTPIN_REG_WPERMIT register 1 */
> +	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg1,
> +					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
> +	/* to store contents of INTPIN_REG_WPERMIT register 2 */
> +	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg2,
> +					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
> +	/* to store contents of INTPIN_REG_WPERMIT register 3 */
> +	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg3,
> +					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
> +	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
> +		"pch_phub_reg.phub_id_reg=%x, "
> +		"pch_phub_reg.q_pri_val_reg=%x, "
> +		"pch_phub_reg.rc_q_maxsize_reg=%x, "
> +		"pch_phub_reg.bri_q_maxsize_reg=%x, "
> +		"pch_phub_reg.comp_resp_timeout_reg=%x, "
> +		"pch_phub_reg.bus_slave_control_reg=%x, "
> +		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
> +		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
> +		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
> +		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
> +		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
> +		pch_phub_reg.phub_id_reg,
> +		pch_phub_reg.q_pri_val_reg,
> +		pch_phub_reg.rc_q_maxsize_reg,
> +		pch_phub_reg.bri_q_maxsize_reg,
> +		pch_phub_reg.comp_resp_timeout_reg,
> +		pch_phub_reg.bus_slave_control_reg,
> +		pch_phub_reg.deadlock_avoid_type_reg,
> +		pch_phub_reg.intpin_reg_wpermit_reg0,
> +		pch_phub_reg.intpin_reg_wpermit_reg1,
> +		pch_phub_reg.intpin_reg_wpermit_reg2,
> +		pch_phub_reg.intpin_reg_wpermit_reg3);
> +	/* to store contents of INT_REDUCE_CONTROL register */
> +	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
> +		iowrite32(pch_phub_reg.int_reduce_control_reg[i],
> +			p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
> +		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
> +			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
> +			i, pch_phub_reg.int_reduce_control_reg[i]);
> +	}
> +
> +	/*restore the clock config reg */

One space after the /*, please.

> +	iowrite32(pch_phub_reg.clkcfg_reg, p + CLKCFG_REG_OFFSET);
> +
> +	return;
> +}
> +
> +/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
> + *									 ROM.
> + *  @offset_address: Contains the Serial ROM address offset value
> + *  @data: Contains the Serial ROM value
> + */
> +static int pch_phub_read_serial_rom(unsigned int offset_address,
> +							 unsigned char *data)
> +{
> +	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
> +								 offset_address;

Unneeded \.  There are several instances of this in the driver.

> +	*data = ioread8(mem_addr);
> +
> +	return 0;
> +}
> +
> +/** pch_phub_write_serial_rom - Implements the functionality of writing Serial
> + *									 ROM.

Strange layout.  I don't know what this will look like after kerneldoc
processing - it might make a mess.  Conventional layout is

/**
 * pch_phub_write_serial_rom - Implements the functionality of writing Serial ROM.

or

/**
 * pch_phub_write_serial_rom - Implements the functionality of writing Serial
 * ROM.

(there are several instances of this).


> + *  @offset_address: Contains the Serial ROM address offset value
> + *  @data: Contains the Serial ROM value
> + */
> +static int pch_phub_write_serial_rom(unsigned int offset_address,
> +							 unsigned char data)
> +{
> +	int retval = 0;
> +	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
> +						 (offset_address & 0xFFFFFFFC);
> +	int i = 0;
> +	unsigned int word_data = 0;
> +
> +	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
> +			pch_phub_reg.pch_phub_extrom_base_address +\
> +								 PHUB_CONTROL);
> +
> +	word_data = ioread32(mem_addr);

The driver tends to do

	int foo = 0;

	...

	foo = ...

in quite a lot of places.  The initialisation to zero is harmless - the
compiler will take it out again.  But it's unusual and jsut adds noise.

The compiler will warn about use of uninitialised variables anyway.  In
fact this unnecessary initalisation will suppress compiler warnings
which might have revealed real bugs.  I'd suggest that they all be
removed (there are quite a lot in this driver).

> +	switch (offset_address % 4) {
> +	case 0:
> +		word_data &= 0xFFFFFF00;
> +		iowrite32((word_data | (unsigned int)data),
> +						mem_addr);
> +		break;
> +	case 1:
> +		word_data &= 0xFFFF00FF;
> +		iowrite32((word_data | ((unsigned int)data << 8)),
> +						mem_addr);
> +		break;
> +	case 2:
> +		word_data &= 0xFF00FFFF;
> +		iowrite32((word_data | ((unsigned int)data << 16)),
> +						mem_addr);
> +		break;
> +	case 3:
> +		word_data &= 0x00FFFFFF;
> +		iowrite32((word_data | ((unsigned int)data << 24)),
> +						mem_addr);
> +		break;
> +	}
> +	while (0x00 !=
> +	       ioread8(pch_phub_reg.pch_phub_extrom_base_address +\
> +							 PHUB_STATUS)) {
> +		msleep(1);
> +		if (PHUB_TIMEOUT == i) {
> +			retval = -EPERM;
> +			break;
> +		}
> +		i++;
> +	}
> +
> +	iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
> +			pch_phub_reg.pch_phub_extrom_base_address +\
> +								 PHUB_CONTROL);
> +
> +	return retval;
> +}
> +
>
> ...
>
> +static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
> +								 loff_t *ppos)
> +{
> +	unsigned int rom_signature = 0;
> +	unsigned char rom_length;
> +	int ret_value;
> +	unsigned int tmp;
> +	unsigned char data;
> +	unsigned int addr_offset = 0;
> +	unsigned int orom_size;
> +	loff_t pos = *ppos;
> +
> +	if (pos < 0)
> +		return -EINVAL;

I think vfs_read() -> rw_verify_area() already did that, so indovidual
->read() implementations don't need to check for negative offset.

> +	/*Get Rom signature*/

Spaces after /* and before */, please.

> +	pch_phub_read_serial_rom(0x80, (unsigned char *)&rom_signature);
> +	pch_phub_read_serial_rom(0x81, (unsigned char *)&tmp);
> +	rom_signature |= (tmp & 0xff) << 8;
> +	if (rom_signature == 0xAA55) {
> +		pch_phub_read_serial_rom(0x82, &rom_length);
> +		orom_size = rom_length * 512;
> +		if (orom_size < pos)
> +			return 0;
> +
> +		for (addr_offset = 0; addr_offset < size; addr_offset++) {
> +			pch_phub_read_serial_rom(0x80 + addr_offset + pos,
> +									 &data);
> +			ret_value = copy_to_user(&buf[addr_offset], &data, 1);
> +			if (ret_value)
> +				return -EFAULT;
> +
> +			if (orom_size < pos + addr_offset) {
> +				*ppos += addr_offset;
> +				return addr_offset;
> +			}
> +
> +		}
> +	} else {
> +		return -ENOEXEC;

ENOEXEC means "your executable file doesn't have suitable contents". 
If this error gets propagated to userspace the poor user will be
wondering who corrupted his ELF files and would be surprised to find
out that the error in fact came from his packethub driver.

So please use a more appropriate errno here.

> +	}
> +	*ppos += addr_offset;
> +	return addr_offset;
> +}
> +
> +/** pch_phub_write - Implements the write functionality of the Packet Hub
> + *									 module.
> + *  @file: Contains the reference of the file structure
> + *  @buf: Usermode buffer pointer
> + *  @size: Usermode buffer size
> + *  @ppos: Contains the reference of the file structure
> + */
> +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> +						 size_t size, loff_t *ppos)
> +{
> +	unsigned int data;
> +	int ret_value;
> +	unsigned int addr_offset = 0;
> +	loff_t pos = *ppos;
> +
> +	if (pos < 0)
> +		return -EINVAL;

vfs_write() already did that.

> +	for (addr_offset = 0; addr_offset < size; addr_offset++) {
> +		ret_value = get_user(data, &buf[addr_offset]);
> +		if (ret_value)
> +			return -EFAULT;
> +
> +		ret_value = pch_phub_write_serial_rom(0x80 + addr_offset + pos,
> +								 data);
> +		if (ret_value)
> +			return -EIO;

This overwrites the pch_phub_write_serial_rom() return value.  it's
generally better to propagate error return values instead of replacing
them with different ones.

otoh pch_phub_write_serial_rom() can return -EPERM.  "Operation not
permitted.  An attempt was made to perform an operation limited to
processes with appropriate privileges or to the owner of a file or
other resource.".  That doesn't sound like an appropriate errno for a
driver to use?

> +		if (PCH_PHUB_OROM_SIZE < pos + addr_offset) {
> +			*ppos += addr_offset;
> +			return addr_offset;
> +		}
> +
> +	}
> +
> +	*ppos += addr_offset;
> +	return addr_offset;
> +}
> +
> +
> +/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
> + *								 Hub module.
> + *  @inode: Contains the reference of the inode structure
> + *  @file: Contains the reference of the file structure
> + *  @cmd: Contains the command value
> + *  @arg: Contains the command argument value
> + */
> +
> +
> +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> +							 unsigned long arg)
> +{
> +	int ret_value = 0;
> +	__u8 mac_addr[6];
> +	int ret;
> +	unsigned int i;
> +	void __user *varg = (void __user *)arg;
> +
> +	ret = mutex_lock_interruptible(&pch_phub_ioctl_mutex);
> +	if (ret) {
> +		ret_value = -ERESTARTSYS;
> +		goto return_nomutex;
> +	}

A plain old `return -ERESTARTSYS' is OK here.

> +	if (pch_phub_reg.pch_phub_suspended == true) {
> +		ret_value = -EPERM;

EPERM?

> +		goto return_ioctrl;
> +	}
> +
> +	switch (cmd) {
> +	case IOCTL_PHUB_READ_MAC_ADDR:
> +		for (i = 0; i < 6; i++)
> +			pch_phub_read_gbe_mac_addr(i, &mac_addr[i]);
> +
> +		ret_value = copy_to_user(varg,
> +					 mac_addr, sizeof(mac_addr));
> +		if (ret_value) {
> +			ret_value = -EFAULT;
> +			goto return_ioctrl;
> +		}

The goto is unneeded.

> +		break;
> +
> +	case IOCTL_PHUB_WRITE_MAC_ADDR:
> +		ret_value = copy_from_user(mac_addr, varg, sizeof(mac_addr));
> +
> +		if (ret_value) {
> +			ret_value = -EFAULT;
> +			goto return_ioctrl;
> +		}

Could do a `break'.

> +		for (i = 0; i < 6; i++)
> +			pch_phub_write_gbe_mac_addr(i, mac_addr[i]);
> +		break;
> +
> +	default:
> +		ret_value = -EINVAL;
> +		break;
> +	}
> +return_ioctrl:
> +	mutex_unlock(&pch_phub_ioctl_mutex);
> +return_nomutex:
> +	return ret_value;
> +}
> +
> +
> +/**
> + * file_operations structure initialization
> + */

That's not a kerneldoc comment, but it has the /** kerneldoc token.

> +static const struct file_operations pch_phub_fops = {
> +	.owner = THIS_MODULE,
> +	.read = pch_phub_read,
> +	.write = pch_phub_write,
> +	.unlocked_ioctl = pch_phub_ioctl,
> +	.llseek = default_llseek
> +};
> +
> +
> +/** pch_phub_probe - Implements the probe functionality of the module.
> + *  @pdev: Contains the reference of the pci_dev structure
> + *  @id: Contains the reference of the pci_device_id structure
> + */
> +static int __devinit pch_phub_probe(struct pci_dev *pdev,
> +				       const struct pci_device_id *id)
> +{
> +	char *DRIVER_NAME = "pch_phub";

hm, why was that upper case?

Maybe use MODULE_NAME instead?  Or

	static const char driver_name[] = "pch_phub";

> +	int ret;
> +	unsigned int rom_size;
> +
> +	pch_phub_major_no = (pch_phub_major_no < 0 || pch_phub_major_no > 254) ?
> +				0 : pch_phub_major_no;

This looks odd - should be explained in code comments and/or changelog.

> +	ret = pci_enable_device(pdev);
> +	if (ret) {
> +		dev_dbg(&pdev->dev,
> +				"\npch_phub_probe : pci_enable_device FAILED");
> +		goto err_probe;
> +	}
> +	dev_dbg(&pdev->dev, "pch_phub_probe : "
> +			"pci_enable_device returns %d\n", ret);
> +
> +	ret = pci_request_regions(pdev, DRIVER_NAME);
> +	if (ret) {
> +		dev_dbg(&pdev->dev,
> +				"pch_phub_probe : pci_request_regions FAILED");
> +		pci_disable_device(pdev);
> +		goto err_probe;
> +	}
> +	dev_dbg(&pdev->dev, "pch_phub_probe : "
> +		"pci_request_regions returns %d\n", ret);
> +
> +	pch_phub_reg.pch_phub_base_address = \
> +					(void __iomem *)pci_iomap(pdev, 1, 0);

Unneeded and undesirable typeast.

> +	if (pch_phub_reg.pch_phub_base_address == 0) {
> +		dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap FAILED");
> +		pci_release_regions(pdev);
> +		pci_disable_device(pdev);
> +		ret = -ENOMEM;
> +		goto err_probe;
> +	}
> +	dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap SUCCESS and value "
> +		"in pch_phub_base_address variable is 0x%08x\n",
> +		(unsigned int)pch_phub_reg.pch_phub_base_address);
> +
> +	pch_phub_reg.pch_phub_extrom_base_address =
> +	    (void __iomem *)pci_map_rom(pdev, &rom_size);

Ditto

> +	if (pch_phub_reg.pch_phub_extrom_base_address == 0) {
> +		dev_dbg(&pdev->dev, "pch_phub_probe : pci_map_rom FAILED");
> +		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
> +		pci_release_regions(pdev);
> +		pci_disable_device(pdev);

This is getting painful.  I'd suggest removal of the duplicated code
via the standard `goto out_iounmap' unwinding approach.

> +		ret = -ENOMEM;
> +		goto err_probe;
> +	}
> +	dev_dbg(&pdev->dev, "pch_phub_probe : "
> +		"pci_map_rom SUCCESS and value in "
> +		"pch_phub_extrom_base_address variable is 0x%08x\n",
> +		(unsigned int)pch_phub_reg.pch_phub_extrom_base_address);
> +
> +	if (pch_phub_major_no) {
> +		pch_phub_dev_no = MKDEV(pch_phub_major_no, 0);
> +		ret = register_chrdev_region(pch_phub_dev_no,
> +					   PCH_MINOR_NOS, DRIVER_NAME);
> +		if (ret) {
> +			dev_dbg(&pdev->dev, "pch_phub_probe : "
> +				"register_chrdev_region FAILED");
> +			pci_unmap_rom(pdev,
> +			(void *)pch_phub_reg.pch_phub_extrom_base_address);
> +			pci_iounmap(pdev,
> +				(void *)pch_phub_reg.pch_phub_base_address);

More unneeded typecasts.

> +			pci_release_regions(pdev);
> +			pci_disable_device(pdev);
> +			goto err_probe;
> +		}
> +		dev_dbg(&pdev->dev, "pch_phub_probe : "
> +				"register_chrdev_region returns %d\n", ret);
> +	} else {
> +		ret = alloc_chrdev_region(&pch_phub_dev_no, 0,
> +						PCH_MINOR_NOS, DRIVER_NAME);
> +		if (ret) {
> +			dev_dbg(&pdev->dev, "pch_phub_probe : "
> +					"alloc_chrdev_region FAILED");
> +			pci_unmap_rom(pdev,
> +			(void *)pch_phub_reg.pch_phub_extrom_base_address);
> +			pci_iounmap(pdev,
> +				    (void *)pch_phub_reg.pch_phub_base_address);

more..

> +			pci_release_regions(pdev);
> +			pci_disable_device(pdev);
> +			goto err_probe;
> +		}
> +		dev_dbg(&pdev->dev, "pch_phub_probe : "
> +			"alloc_chrdev_region returns %d\n", ret);
> +	}
> +
> +	cdev_init(&pch_phub_dev, &pch_phub_fops);
> +	dev_dbg(&pdev->dev,
> +			"pch_phub_probe :  cdev_init invoked successfully\n");
> +
> +	pch_phub_dev.owner = THIS_MODULE;
> +	pch_phub_dev.ops = &pch_phub_fops;
> +
> +	ret = cdev_add(&pch_phub_dev, pch_phub_dev_no, PCH_MINOR_NOS);
> +	if (ret) {
> +		dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add FAILED");
> +		unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
> +		pci_unmap_rom(pdev,
> +			(void *)pch_phub_reg.pch_phub_extrom_base_address);
> +		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
> +		pci_release_regions(pdev);
> +		pci_disable_device(pdev);
> +		goto err_probe;
> +	}
> +	dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add returns %d\n", ret);
> +
> +	/*set the clock config reg if CAN clock is 50Mhz */
> +	dev_dbg(&pdev->dev, "pch_phub_probe : invoking "
> +		"pch_phub_read_modify_write_reg "
> +		"to set CLKCFG reg for CAN clk 50Mhz\n");
> +	pch_phub_read_modify_write_reg((unsigned int)CLKCFG_REG_OFFSET,
> +					  CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
> +
> +	/* set the prefech value */
> +	iowrite32(0x000ffffa, pch_phub_reg.pch_phub_base_address + 0x14);
> +	/* set the interrupt delay value */
> +	iowrite32(0x25, pch_phub_reg.pch_phub_base_address + 0x44);
> +	return 0;
> +
> +err_probe:
> +	dev_dbg(&pdev->dev, "pch_phub_probe returns %d\n", ret);
> +	return ret;
> +}
> +
>
> ...
>
> +#ifdef CONFIG_PM
> +
> +/** pch_phub_suspend - Implements the suspend functionality of the module.
> + *  @pdev: Contains the reference of the pci_dev structure
> + *  @state: Contains the reference of the pm_message_t structure
> + */
> +static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
> +{
> +	int ret;
> +
> +	pch_phub_reg.pch_phub_suspended = true;/* For blocking further IOCTLs */
> +
> +	pch_phub_save_reg_conf(pdev);
> +	dev_dbg(&pdev->dev, "pch_phub_suspend - "
> +		"pch_phub_save_reg_conf Invoked successfully\n");
> +
> +	ret = pci_save_state(pdev);
> +	if (ret) {
> +		dev_dbg(&pdev->dev,
> +			" pch_phub_suspend -pci_save_state returns-%d\n", ret);
> +		return ret;
> +	}
> +	dev_dbg(&pdev->dev,
> +			"pch_phub_suspend - pci_save_state returns %d\n", ret);
> +	pci_enable_wake(pdev, PCI_D3hot, 0);
> +	dev_dbg(&pdev->dev, "pch_phub_suspend - "
> +			"pci_enable_wake Invoked successfully\n");
> +
> +	pci_disable_device(pdev);
> +	dev_dbg(&pdev->dev, "pch_phub_suspend - "
> +			"pci_disable_device Invoked successfully\n");
> +
> +	pci_set_power_state(pdev, pci_choose_state(pdev, state));
> +	dev_dbg(&pdev->dev, "pch_phub_suspend - "
> +			"pci_set_power_state Invoked successfully   "
> +			"return = %d\n", 0);
> +
> +	return 0;
> +}
> +
> +/** pch_phub_resume - Implements the resume functionality of the module.
> + *  @pdev: Contains the reference of the pci_dev structure
> + */
> +static int pch_phub_resume(struct pci_dev *pdev)
> +{
> +
> +	int ret;
> +
> +	pci_set_power_state(pdev, PCI_D0);
> +	dev_dbg(&pdev->dev, "pch_phub_resume - "
> +		"pci_set_power_state Invoked successfully\n");
> +
> +	pci_restore_state(pdev);
> +	dev_dbg(&pdev->dev, "pch_phub_resume - "
> +		"pci_restore_state Invoked successfully\n");
> +
> +	ret = pci_enable_device(pdev);
> +	if (ret) {
> +		dev_dbg(&pdev->dev,
> +				"pch_phub_resume-pci_enable_device failed ");
> +		return ret;
> +	}
> +
> +	dev_dbg(&pdev->dev, "pch_phub_resume - "
> +			"pci_enable_device returns -%d\n", ret);
> +
> +	pci_enable_wake(pdev, PCI_D3hot, 0);
> +	dev_dbg(&pdev->dev, "pch_phub_resume - "
> +			"pci_enable_wake Invoked successfully\n");
> +
> +	pch_phub_restore_reg_conf(pdev);
> +	dev_dbg(&pdev->dev, "pch_phub_resume - "
> +		"pch_phub_restore_reg_conf Invoked successfully\n");
> +
> +	pch_phub_reg.pch_phub_suspended = false;
> +
> +	dev_dbg(&pdev->dev, "pch_phub_resume  returns- %d\n", 0);
> +	return 0;
> +}

Here you can put

#else
#define pch_phub_suspend NULL
#define pch_phub_resume NULL

> +#endif /* CONFIG_PM */
> +
> +static struct pci_device_id pch_phub_pcidev_id[] = {
> +
> +	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
> +	{0,}
> +};
> +
> +
> +static struct pci_driver pch_phub_driver = {
> +	.name = "pch_phub",
> +	.id_table = pch_phub_pcidev_id,
> +	.probe = pch_phub_probe,
> +	.remove = __devexit_p(pch_phub_remove),
> +#ifdef CONFIG_PM
> +	.suspend = pch_phub_suspend,
> +	.resume = pch_phub_resume
> +#endif

and then remove this ifdef.

>
> ...
>
> --- /dev/null
> +++ b/drivers/char/pch_phub/pch_phub.h
> @@ -0,0 +1,58 @@
> +#ifndef __PCH_PHUB_H__
> +#define __PCH_PHUB_H__
> +/*!
> + * @file pch_phub.h
> + * @brief Provides all the interfaces pertaining to the Packet Hub module.
> + * @version 1.0.0.0
> + * @section

?

> + * 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.
> + */
> +
> +/*
> + * History:
> + * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
> + *
> + * created:
> + *	OKI SEMICONDUCTOR 04/14/2010
> + * modified:
> + *
> + */
> +
> +#define PHUB_IOCTL_MAGIC		(0xf7)
> +
> +/*Outlines the read mac address function signature. */

Space after /*, please (check the whole patch)

> +#define IOCTL_PHUB_READ_MAC_ADDR (_IOR(PHUB_IOCTL_MAGIC, 6, __u8[6]))
> +
> +/*brief Outlines the write mac address function signature. */
> +#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u8[6]))

"brief"?

I didn't notice any documentation for these ioctls anywhere?

> +
> +/* Registers address offset */
> +#define PCH_PHUB_PHUB_ID_REG			0x0000
> +#define PCH_PHUB_QUEUE_PRI_VAL_REG		0x0004
> +#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG		0x0008
> +#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG		0x000C
> +#define PCH_PHUB_COMP_RESP_TIMEOUT_REG		0x0010
> +#define PCH_PHUB_BUS_SLAVE_CONTROL_REG		0x0014
> +#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG	0x0018
> +#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0	0x0020
> +#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1	0x0024
> +#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2	0x0028
> +#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3	0x002C
> +#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	0x0040
> +#define CLKCFG_REG_OFFSET			0x500
> +
> +#define PCH_PHUB_OROM_SIZE 15360
> +
> +#endif


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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-22 11:30 ` Arnd Bergmann
@ 2010-06-22 13:52   ` Yong Wang
  0 siblings, 0 replies; 45+ messages in thread
From: Yong Wang @ 2010-06-22 13:52 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Arnd Bergmann, Masayuki Ohtak, Wang, Yong Y, Wang Qi, Intel OTC,
	Andrew, Alan Cox, LKML

On Tue, Jun 22, 2010 at 01:30:39PM +0200, Arnd Bergmann wrote:
> On Tuesday 22 June 2010, Masayuki Ohtak wrote:
> > Hi, Arnd and Yong Y
> > 
> > I have released Phub patch file.
> > Please confirm below.
> 
> You have addressed all of my comments, the driver looks ready
> for inclusion from my perspective.
> 
> > Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> 
> Acked-by: Arnd Bergmann <arnd@arndb.de>

Hi Andrew,

Are you going to take this patch? Or could you please let us know which
maintainer will do?

Thanks
-Yong


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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-22  5:33 Masayuki Ohtak
  2010-06-22 10:33 ` Masayuki Ohtak
@ 2010-06-22 11:30 ` Arnd Bergmann
  2010-06-22 13:52   ` Yong Wang
  2010-06-29 23:31 ` Andy Isaacson
  2 siblings, 1 reply; 45+ messages in thread
From: Arnd Bergmann @ 2010-06-22 11:30 UTC (permalink / raw)
  To: Masayuki Ohtak
  Cc: Wang, Yong Y, Wang Qi", Intel OTC", Andrew", Alan Cox, LKML

On Tuesday 22 June 2010, Masayuki Ohtak wrote:
> Hi, Arnd and Yong Y
> 
> I have released Phub patch file.
> Please confirm below.

You have addressed all of my comments, the driver looks ready
for inclusion from my perspective.

> Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>

Acked-by: Arnd Bergmann <arnd@arndb.de>

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-22  5:33 Masayuki Ohtak
@ 2010-06-22 10:33 ` Masayuki Ohtak
  2010-06-22 22:12   ` Andrew Morton
  2010-06-22 11:30 ` Arnd Bergmann
  2010-06-29 23:31 ` Andy Isaacson
  2 siblings, 1 reply; 45+ messages in thread
From: Masayuki Ohtak @ 2010-06-22 10:33 UTC (permalink / raw)
  To: Arnd Bergmann, Wang, Yong Y
  Cc: qi.wang, joel.clark, andrew.chih.howe.khor, Alan Cox, LKML

Hi Arnd and Yong Y

We have updated phub patch about the following.
 * Arnd's commnets
	 * Delete PCH_READ_REG/PCH_WRITE_REG
	 * Delete '_t' prefix
	 * Modify basic type
	 * Delete needless 'static' prefix
	 * Modify returned value
	 * Care returned value of get_user()
	 * Add .llseek line

 * Yong Y's comments
	 * Applying to the latest checkpatch(2.6.35)
	 * Delete unused 'DEBUG' macro in Makefile
	 * Delete IEEE1588 lines
	 * Delete 'PCH_CAN_PCLK_50MHZ'

Thanks, Ohtake.

Kernel=2.6.33.1
Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
 drivers/char/Kconfig             |   12 +
 drivers/char/Makefile            |    2 +
 drivers/char/pch_phub/Makefile   |    3 +
 drivers/char/pch_phub/pch_phub.c |  937 ++++++++++++++++++++++++++++++++++++++
 drivers/char/pch_phub/pch_phub.h |   58 +++
 5 files changed, 1012 insertions(+), 0 deletions(-)
 create mode 100644 drivers/char/pch_phub/Makefile
 create mode 100755 drivers/char/pch_phub/pch_phub.c
 create mode 100755 drivers/char/pch_phub/pch_phub.h

diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e023682..7ff728a 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -4,6 +4,18 @@
 
 menu "Character devices"
 
+config PCH_PHUB
+	tristate "PCH PHUB"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  PCH Packet Hub Host controller.
+	  This driver is for PCH Packet hub driver for Topcliff.
+	  This driver is integrated as built-in.
+	  This driver can access GbE MAC address.
+	  This driver can access HW register.
+	  You can also be integrated as module.
+
 config VT
 	bool "Virtual terminal" if EMBEDDED
 	depends on !S390
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index f957edf..1e3eb6c 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -111,6 +111,8 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
 obj-$(CONFIG_JS_RTC)		+= js-rtc.o
 js-rtc-y = rtc.o
 
+obj-$(CONFIG_PCH_PHUB)	+= pch_phub/
+
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c
 
diff --git a/drivers/char/pch_phub/Makefile b/drivers/char/pch_phub/Makefile
new file mode 100644
index 0000000..93aaffe
--- /dev/null
+++ b/drivers/char/pch_phub/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_PCH_PHUB) += pch_phub_drv.o
+
+pch_phub_drv-objs := pch_phub.o
diff --git a/drivers/char/pch_phub/pch_phub.c b/drivers/char/pch_phub/pch_phub.c
new file mode 100755
index 0000000..1590d6b
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.c
@@ -0,0 +1,937 @@
+/*!
+ * @file pch_phub.c
+ * @brief Provides all the implementation of the interfaces pertaining to
+ *		the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+/* includes */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+#include "pch_phub.h"
+
+/*--------------------------------------------
+	macros
+--------------------------------------------*/
+/* Status Register offset */
+#define PHUB_STATUS 0x00
+/* Control Register offset */
+#define PHUB_CONTROL 0x04
+/* Time out value for Status Register */
+#define PHUB_TIMEOUT 0x05
+/* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_ENABLE 0x01
+/* Disabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE 0x00
+/* ROM data area start address offset */
+#define PCH_PHUB_ROM_START_ADDR 0x14
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
+
+#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
+
+#define PCH_MINOR_NOS 1
+#define CLKCFG_CAN_50MHZ 0x12000000
+#define CLKCFG_CANCLK_MASK 0xFF000000
+
+#define MODULE_NAME "pch_phub"
+
+/*--------------------------------------------
+	global variables
+--------------------------------------------*/
+/**
+ * struct pch_phub_reg - PHUB register structure
+ * @phub_id_reg:		 PHUB_ID register val
+ * @q_pri_val_reg:		 QUEUE_PRI_VAL register val
+ * @rc_q_maxsize_reg:	 RC_QUEUE_MAXSIZE register val
+ * @bri_q_maxsize_reg:	 BRI_QUEUE_MAXSIZE register val
+ * @comp_resp_timeout_reg:	 COMP_RESP_TIMEOUT register val
+ * @bus_slave_control_reg:	 BUS_SLAVE_CONTROL_REG register val
+ * @deadlock_avoid_type_reg:  DEADLOCK_AVOID_TYPE register val
+ * @intpin_reg_wpermit_reg0:  INTPIN_REG_WPERMIT register 0 val
+ * @intpin_reg_wpermit_reg1:  INTPIN_REG_WPERMIT register 1 val
+ * @intpin_reg_wpermit_reg2:  INTPIN_REG_WPERMIT register 2 val
+ * @intpin_reg_wpermit_reg3:  INTPIN_REG_WPERMIT register 3 val
+ * @int_reduce_control_reg:	 INT_REDUCE_CONTROL registers val
+ * @clkcfg_reg:		 CLK CFG register val
+ * @pch_phub_base_address:  register base address
+ * @pch_phub_extrom_base_address:  external rom base address
+ * @pch_phub_suspended: PHUB status val
+ */
+struct pch_phub_reg {
+	unsigned int phub_id_reg;
+	unsigned int q_pri_val_reg;
+	unsigned int rc_q_maxsize_reg;
+	unsigned int bri_q_maxsize_reg;
+	unsigned int comp_resp_timeout_reg;
+	unsigned int bus_slave_control_reg;
+	unsigned int deadlock_avoid_type_reg;
+	unsigned int intpin_reg_wpermit_reg0;
+	unsigned int intpin_reg_wpermit_reg1;
+	unsigned int intpin_reg_wpermit_reg2;
+	unsigned int intpin_reg_wpermit_reg3;
+	unsigned int int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+	unsigned int clkcfg_reg;
+	void __iomem *pch_phub_base_address;
+	void __iomem *pch_phub_extrom_base_address;
+	int pch_phub_suspended;
+} pch_phub_reg;
+
+static DEFINE_MUTEX(pch_phub_ioctl_mutex);
+
+/* ToDo: major number allocation via module parameter */
+static dev_t pch_phub_dev_no;
+static int pch_phub_major_no;
+static struct cdev pch_phub_dev;
+
+/*--------------------------------------------
+	functions implementations
+--------------------------------------------*/
+/** pch_phub_read_modify_write_reg - Implements the functionality of reading,
+ *					 modifying and writing register.
+ *  @reg_addr_offset:  Contains the register offset address value
+ *  @data:             Contains the writing value
+ *  @mask:             Contains the mask value
+ */
+static void pch_phub_read_modify_write_reg(unsigned int reg_addr_offset,
+				       unsigned int data, unsigned int mask)
+{
+	void __iomem *reg_addr = pch_phub_reg.pch_phub_base_address +\
+							 reg_addr_offset;
+	iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+	return;
+}
+
+
+/** pch_phub_save_reg_conf - saves register configuration
+ */
+static void pch_phub_save_reg_conf(struct pci_dev *pdev)
+{
+	unsigned int i = 0;
+	void __iomem *p = pch_phub_reg.pch_phub_base_address;
+
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	pch_phub_reg.phub_id_reg = ioread32(p + PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	pch_phub_reg.q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	pch_phub_reg.rc_q_maxsize_reg =
+	    ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	pch_phub_reg.bri_q_maxsize_reg =
+	    ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	pch_phub_reg.comp_resp_timeout_reg =
+	    ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	pch_phub_reg.bus_slave_control_reg =
+	    ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	pch_phub_reg.deadlock_avoid_type_reg =
+	    ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	pch_phub_reg.intpin_reg_wpermit_reg0 =
+	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	pch_phub_reg.intpin_reg_wpermit_reg1 =
+	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	pch_phub_reg.intpin_reg_wpermit_reg2 =
+	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	pch_phub_reg.intpin_reg_wpermit_reg3 =
+	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+		"pch_phub_reg.phub_id_reg=%x, "
+		"pch_phub_reg.q_pri_val_reg=%x, "
+		"pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"pch_phub_reg.bus_slave_control_reg=%x, "
+		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		pch_phub_reg.phub_id_reg,
+		pch_phub_reg.q_pri_val_reg,
+		pch_phub_reg.rc_q_maxsize_reg,
+		pch_phub_reg.bri_q_maxsize_reg,
+		pch_phub_reg.comp_resp_timeout_reg,
+		pch_phub_reg.bus_slave_control_reg,
+		pch_phub_reg.deadlock_avoid_type_reg,
+		pch_phub_reg.intpin_reg_wpermit_reg0,
+		pch_phub_reg.intpin_reg_wpermit_reg1,
+		pch_phub_reg.intpin_reg_wpermit_reg2,
+		pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL registers */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		pch_phub_reg.int_reduce_control_reg[i] =
+		    ioread32(p +
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, pch_phub_reg.int_reduce_control_reg[i]);
+	}
+	/* save clk cfg register */
+	pch_phub_reg.clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
+
+	return;
+}
+
+/** pch_phub_restore_reg_conf - restore register configuration
+ */
+
+static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
+{
+	unsigned int i;
+	void __iomem *p = pch_phub_reg.pch_phub_base_address;
+
+	dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	iowrite32(pch_phub_reg.phub_id_reg, p + PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	iowrite32(pch_phub_reg.q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	iowrite32(pch_phub_reg.rc_q_maxsize_reg,
+					p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	iowrite32(pch_phub_reg.bri_q_maxsize_reg,
+					p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	iowrite32(pch_phub_reg.comp_resp_timeout_reg,
+					p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	iowrite32(pch_phub_reg.bus_slave_control_reg,
+					p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	iowrite32(pch_phub_reg.deadlock_avoid_type_reg,
+					p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg0,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg1,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg2,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg3,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+		"pch_phub_reg.phub_id_reg=%x, "
+		"pch_phub_reg.q_pri_val_reg=%x, "
+		"pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"pch_phub_reg.bus_slave_control_reg=%x, "
+		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		pch_phub_reg.phub_id_reg,
+		pch_phub_reg.q_pri_val_reg,
+		pch_phub_reg.rc_q_maxsize_reg,
+		pch_phub_reg.bri_q_maxsize_reg,
+		pch_phub_reg.comp_resp_timeout_reg,
+		pch_phub_reg.bus_slave_control_reg,
+		pch_phub_reg.deadlock_avoid_type_reg,
+		pch_phub_reg.intpin_reg_wpermit_reg0,
+		pch_phub_reg.intpin_reg_wpermit_reg1,
+		pch_phub_reg.intpin_reg_wpermit_reg2,
+		pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL register */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		iowrite32(pch_phub_reg.int_reduce_control_reg[i],
+			p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, pch_phub_reg.int_reduce_control_reg[i]);
+	}
+
+	/*restore the clock config reg */
+	iowrite32(pch_phub_reg.clkcfg_reg, p + CLKCFG_REG_OFFSET);
+
+	return;
+}
+
+/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
+ *									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static int pch_phub_read_serial_rom(unsigned int offset_address,
+							 unsigned char *data)
+{
+	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+								 offset_address;
+
+	*data = ioread8(mem_addr);
+
+	return 0;
+}
+
+/** pch_phub_write_serial_rom - Implements the functionality of writing Serial
+ *									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static int pch_phub_write_serial_rom(unsigned int offset_address,
+							 unsigned char data)
+{
+	int retval = 0;
+	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+						 (offset_address & 0xFFFFFFFC);
+	int i = 0;
+	unsigned int word_data = 0;
+
+	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+			pch_phub_reg.pch_phub_extrom_base_address +\
+								 PHUB_CONTROL);
+
+	word_data = ioread32(mem_addr);
+
+	switch (offset_address % 4) {
+	case 0:
+		word_data &= 0xFFFFFF00;
+		iowrite32((word_data | (unsigned int)data),
+						mem_addr);
+		break;
+	case 1:
+		word_data &= 0xFFFF00FF;
+		iowrite32((word_data | ((unsigned int)data << 8)),
+						mem_addr);
+		break;
+	case 2:
+		word_data &= 0xFF00FFFF;
+		iowrite32((word_data | ((unsigned int)data << 16)),
+						mem_addr);
+		break;
+	case 3:
+		word_data &= 0x00FFFFFF;
+		iowrite32((word_data | ((unsigned int)data << 24)),
+						mem_addr);
+		break;
+	}
+	while (0x00 !=
+	       ioread8(pch_phub_reg.pch_phub_extrom_base_address +\
+							 PHUB_STATUS)) {
+		msleep(1);
+		if (PHUB_TIMEOUT == i) {
+			retval = -EPERM;
+			break;
+		}
+		i++;
+	}
+
+	iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+			pch_phub_reg.pch_phub_extrom_base_address +\
+								 PHUB_CONTROL);
+
+	return retval;
+}
+
+/** pch_phub_read_serial_rom_val - Implements the functionality of reading
+ *							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static int pch_phub_read_serial_rom_val(unsigned int offset_address,
+							 unsigned char *data)
+{
+	int retval = 0;
+	unsigned int mem_addr;
+
+	mem_addr = (offset_address / 4 * 8) + 3 -
+			(offset_address % 4) + PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_read_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_write_serial_rom_val - Implements the functionality of writing
+ *							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static int pch_phub_write_serial_rom_val(unsigned int offset_address,
+				     unsigned char data)
+{
+	int retval = 0;
+	unsigned int mem_addr;
+
+	mem_addr =
+	    (offset_address / 4 * 8) + 3 - (offset_address % 4) +
+	    PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_write_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ *					 for Gigabit Ethernet MAC address
+ */
+static int pch_phub_gbe_serial_rom_conf(void)
+{
+	int retval = 0;
+
+	retval |= pch_phub_write_serial_rom(0x0b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x0a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x09, 0x01);
+	retval |= pch_phub_write_serial_rom(0x08, 0x02);
+
+	retval |= pch_phub_write_serial_rom(0x0f, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0e, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0d, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0c, 0x80);
+
+	retval |= pch_phub_write_serial_rom(0x13, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x12, 0x10);
+	retval |= pch_phub_write_serial_rom(0x11, 0x01);
+	retval |= pch_phub_write_serial_rom(0x10, 0x18);
+
+	retval |= pch_phub_write_serial_rom(0x1b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x1a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x19, 0x01);
+	retval |= pch_phub_write_serial_rom(0x18, 0x19);
+
+	retval |= pch_phub_write_serial_rom(0x23, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x22, 0x10);
+	retval |= pch_phub_write_serial_rom(0x21, 0x01);
+	retval |= pch_phub_write_serial_rom(0x20, 0x3a);
+
+	retval |= pch_phub_write_serial_rom(0x27, 0x01);
+	retval |= pch_phub_write_serial_rom(0x26, 0x00);
+	retval |= pch_phub_write_serial_rom(0x25, 0x00);
+	retval |= pch_phub_write_serial_rom(0x24, 0x00);
+
+	return retval;
+}
+
+/** pch_phub_read_gbe_mac_addr - Contains the Gigabit Ethernet MAC address
+ *							 offset value
+ *  @offset_address: Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+static int pch_phub_read_gbe_mac_addr(unsigned int offset_address,
+							 unsigned char *data)
+{
+	int retval = 0;
+
+	retval = pch_phub_read_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_write_gbe_mac_addr - Write MAC address
+ *  @offset_address: Contains the Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+static int pch_phub_write_gbe_mac_addr(unsigned int offset_address,
+				   unsigned char data)
+{
+	int retval = 0;
+
+	retval = pch_phub_gbe_serial_rom_conf();
+	retval |= pch_phub_write_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_read - Implements the read functionality of the Packet Hub module.
+ *  @file: Contains the reference of the file structure
+ *  @buf: Usermode buffer pointer
+ *  @size: Usermode buffer size
+ *  @ppos: Contains the reference of the file structure
+ */
+
+static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
+								 loff_t *ppos)
+{
+	unsigned int rom_signature = 0;
+	unsigned char rom_length;
+	int ret_value;
+	unsigned int tmp;
+	unsigned char data;
+	unsigned int addr_offset = 0;
+	unsigned int orom_size;
+	loff_t pos = *ppos;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	/*Get Rom signature*/
+	pch_phub_read_serial_rom(0x80, (unsigned char *)&rom_signature);
+	pch_phub_read_serial_rom(0x81, (unsigned char *)&tmp);
+	rom_signature |= (tmp & 0xff) << 8;
+	if (rom_signature == 0xAA55) {
+		pch_phub_read_serial_rom(0x82, &rom_length);
+		orom_size = rom_length * 512;
+		if (orom_size < pos)
+			return 0;
+
+		for (addr_offset = 0; addr_offset < size; addr_offset++) {
+			pch_phub_read_serial_rom(0x80 + addr_offset + pos,
+									 &data);
+			ret_value = copy_to_user(&buf[addr_offset], &data, 1);
+			if (ret_value)
+				return -EFAULT;
+
+			if (orom_size < pos + addr_offset) {
+				*ppos += addr_offset;
+				return addr_offset;
+			}
+
+		}
+	} else {
+		return -ENOEXEC;
+	}
+	*ppos += addr_offset;
+	return addr_offset;
+}
+
+/** pch_phub_write - Implements the write functionality of the Packet Hub
+ *									 module.
+ *  @file: Contains the reference of the file structure
+ *  @buf: Usermode buffer pointer
+ *  @size: Usermode buffer size
+ *  @ppos: Contains the reference of the file structure
+ */
+static ssize_t pch_phub_write(struct file *file, const char __user *buf,
+						 size_t size, loff_t *ppos)
+{
+	unsigned int data;
+	int ret_value;
+	unsigned int addr_offset = 0;
+	loff_t pos = *ppos;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	for (addr_offset = 0; addr_offset < size; addr_offset++) {
+		ret_value = get_user(data, &buf[addr_offset]);
+		if (ret_value)
+			return -EFAULT;
+
+		ret_value = pch_phub_write_serial_rom(0x80 + addr_offset + pos,
+								 data);
+		if (ret_value)
+			return -EIO;
+
+		if (PCH_PHUB_OROM_SIZE < pos + addr_offset) {
+			*ppos += addr_offset;
+			return addr_offset;
+		}
+
+	}
+
+	*ppos += addr_offset;
+	return addr_offset;
+}
+
+
+/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
+ *								 Hub module.
+ *  @inode: Contains the reference of the inode structure
+ *  @file: Contains the reference of the file structure
+ *  @cmd: Contains the command value
+ *  @arg: Contains the command argument value
+ */
+
+
+static long pch_phub_ioctl(struct file *file, unsigned int cmd,
+							 unsigned long arg)
+{
+	int ret_value = 0;
+	__u8 mac_addr[6];
+	int ret;
+	unsigned int i;
+	void __user *varg = (void __user *)arg;
+
+	ret = mutex_lock_interruptible(&pch_phub_ioctl_mutex);
+	if (ret) {
+		ret_value = -ERESTARTSYS;
+		goto return_nomutex;
+	}
+
+	if (pch_phub_reg.pch_phub_suspended == true) {
+		ret_value = -EPERM;
+		goto return_ioctrl;
+	}
+
+	switch (cmd) {
+	case IOCTL_PHUB_READ_MAC_ADDR:
+		for (i = 0; i < 6; i++)
+			pch_phub_read_gbe_mac_addr(i, &mac_addr[i]);
+
+		ret_value = copy_to_user(varg,
+					 mac_addr, sizeof(mac_addr));
+		if (ret_value) {
+			ret_value = -EFAULT;
+			goto return_ioctrl;
+		}
+		break;
+
+	case IOCTL_PHUB_WRITE_MAC_ADDR:
+		ret_value = copy_from_user(mac_addr, varg, sizeof(mac_addr));
+
+		if (ret_value) {
+			ret_value = -EFAULT;
+			goto return_ioctrl;
+		}
+		for (i = 0; i < 6; i++)
+			pch_phub_write_gbe_mac_addr(i, mac_addr[i]);
+		break;
+
+	default:
+		ret_value = -EINVAL;
+		break;
+	}
+return_ioctrl:
+	mutex_unlock(&pch_phub_ioctl_mutex);
+return_nomutex:
+	return ret_value;
+}
+
+
+/**
+ * file_operations structure initialization
+ */
+static const struct file_operations pch_phub_fops = {
+	.owner = THIS_MODULE,
+	.read = pch_phub_read,
+	.write = pch_phub_write,
+	.unlocked_ioctl = pch_phub_ioctl,
+	.llseek = default_llseek
+};
+
+
+/** pch_phub_probe - Implements the probe functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @id: Contains the reference of the pci_device_id structure
+ */
+static int __devinit pch_phub_probe(struct pci_dev *pdev,
+				       const struct pci_device_id *id)
+{
+	char *DRIVER_NAME = "pch_phub";
+	int ret;
+	unsigned int rom_size;
+
+	pch_phub_major_no = (pch_phub_major_no < 0 || pch_phub_major_no > 254) ?
+				0 : pch_phub_major_no;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"\npch_phub_probe : pci_enable_device FAILED");
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+			"pci_enable_device returns %d\n", ret);
+
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"pch_phub_probe : pci_request_regions FAILED");
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+		"pci_request_regions returns %d\n", ret);
+
+	pch_phub_reg.pch_phub_base_address = \
+					(void __iomem *)pci_iomap(pdev, 1, 0);
+
+	if (pch_phub_reg.pch_phub_base_address == 0) {
+		dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap FAILED");
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap SUCCESS and value "
+		"in pch_phub_base_address variable is 0x%08x\n",
+		(unsigned int)pch_phub_reg.pch_phub_base_address);
+
+	pch_phub_reg.pch_phub_extrom_base_address =
+	    (void __iomem *)pci_map_rom(pdev, &rom_size);
+	if (pch_phub_reg.pch_phub_extrom_base_address == 0) {
+		dev_dbg(&pdev->dev, "pch_phub_probe : pci_map_rom FAILED");
+		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+		"pci_map_rom SUCCESS and value in "
+		"pch_phub_extrom_base_address variable is 0x%08x\n",
+		(unsigned int)pch_phub_reg.pch_phub_extrom_base_address);
+
+	if (pch_phub_major_no) {
+		pch_phub_dev_no = MKDEV(pch_phub_major_no, 0);
+		ret = register_chrdev_region(pch_phub_dev_no,
+					   PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(&pdev->dev, "pch_phub_probe : "
+				"register_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				(void *)pch_phub_reg.pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(&pdev->dev, "pch_phub_probe : "
+				"register_chrdev_region returns %d\n", ret);
+	} else {
+		ret = alloc_chrdev_region(&pch_phub_dev_no, 0,
+						PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(&pdev->dev, "pch_phub_probe : "
+					"alloc_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				    (void *)pch_phub_reg.pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(&pdev->dev, "pch_phub_probe : "
+			"alloc_chrdev_region returns %d\n", ret);
+	}
+
+	cdev_init(&pch_phub_dev, &pch_phub_fops);
+	dev_dbg(&pdev->dev,
+			"pch_phub_probe :  cdev_init invoked successfully\n");
+
+	pch_phub_dev.owner = THIS_MODULE;
+	pch_phub_dev.ops = &pch_phub_fops;
+
+	ret = cdev_add(&pch_phub_dev, pch_phub_dev_no, PCH_MINOR_NOS);
+	if (ret) {
+		dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add FAILED");
+		unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+		pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add returns %d\n", ret);
+
+	/*set the clock config reg if CAN clock is 50Mhz */
+	dev_dbg(&pdev->dev, "pch_phub_probe : invoking "
+		"pch_phub_read_modify_write_reg "
+		"to set CLKCFG reg for CAN clk 50Mhz\n");
+	pch_phub_read_modify_write_reg((unsigned int)CLKCFG_REG_OFFSET,
+					  CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+
+	/* set the prefech value */
+	iowrite32(0x000ffffa, pch_phub_reg.pch_phub_base_address + 0x14);
+	/* set the interrupt delay value */
+	iowrite32(0x25, pch_phub_reg.pch_phub_base_address + 0x44);
+	return 0;
+
+err_probe:
+	dev_dbg(&pdev->dev, "pch_phub_probe returns %d\n", ret);
+	return ret;
+}
+
+/** pch_phub_remove - Implements the remove functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+
+	cdev_del(&pch_phub_dev);
+	dev_dbg(&pdev->dev,
+			"pch_phub_remove - cdev_del Invoked successfully\n");
+
+	unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"unregister_chrdev_region Invoked successfully\n");
+
+	pci_unmap_rom(pdev, (void *)pch_phub_reg.pch_phub_extrom_base_address);
+
+	pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+			"pci_iounmap Invoked successfully\n");
+
+	pci_release_regions(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"pci_release_regions Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"pci_disable_device Invoked successfully\n");
+
+}
+
+#ifdef CONFIG_PM
+
+/** pch_phub_suspend - Implements the suspend functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @state: Contains the reference of the pm_message_t structure
+ */
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int ret;
+
+	pch_phub_reg.pch_phub_suspended = true;/* For blocking further IOCTLs */
+
+	pch_phub_save_reg_conf(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+		"pch_phub_save_reg_conf Invoked successfully\n");
+
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+			" pch_phub_suspend -pci_save_state returns-%d\n", ret);
+		return ret;
+	}
+	dev_dbg(&pdev->dev,
+			"pch_phub_suspend - pci_save_state returns %d\n", ret);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_disable_device Invoked successfully\n");
+
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_set_power_state Invoked successfully   "
+			"return = %d\n", 0);
+
+	return 0;
+}
+
+/** pch_phub_resume - Implements the resume functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static int pch_phub_resume(struct pci_dev *pdev)
+{
+
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pci_set_power_state Invoked successfully\n");
+
+	pci_restore_state(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pci_restore_state Invoked successfully\n");
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"pch_phub_resume-pci_enable_device failed ");
+		return ret;
+	}
+
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+			"pci_enable_device returns -%d\n", ret);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pch_phub_restore_reg_conf(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pch_phub_restore_reg_conf Invoked successfully\n");
+
+	pch_phub_reg.pch_phub_suspended = false;
+
+	dev_dbg(&pdev->dev, "pch_phub_resume  returns- %d\n", 0);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct pci_device_id pch_phub_pcidev_id[] = {
+
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+	{0,}
+};
+
+
+static struct pci_driver pch_phub_driver = {
+	.name = "pch_phub",
+	.id_table = pch_phub_pcidev_id,
+	.probe = pch_phub_probe,
+	.remove = __devexit_p(pch_phub_remove),
+#ifdef CONFIG_PM
+	.suspend = pch_phub_suspend,
+	.resume = pch_phub_resume
+#endif
+};
+
+/** pch_phub_pci_init - Implements the initialization functionality of
+ *								 the module.
+ */
+static int __init pch_phub_pci_init(void)
+{
+	int ret;
+	ret = pci_register_driver(&pch_phub_driver);
+
+	return ret;
+}
+
+/** pch_phub_pci_exit - Implements the exit functionality of the module.
+ */
+static void __exit pch_phub_pci_exit(void)
+{
+	pci_unregister_driver(&pch_phub_driver);
+
+}
+
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);
+
+MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/char/pch_phub/pch_phub.h b/drivers/char/pch_phub/pch_phub.h
new file mode 100755
index 0000000..83986d9
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.h
@@ -0,0 +1,58 @@
+#ifndef __PCH_PHUB_H__
+#define __PCH_PHUB_H__
+/*!
+ * @file pch_phub.h
+ * @brief Provides all the interfaces pertaining to the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+#define PHUB_IOCTL_MAGIC		(0xf7)
+
+/*Outlines the read mac address function signature. */
+#define IOCTL_PHUB_READ_MAC_ADDR (_IOR(PHUB_IOCTL_MAGIC, 6, __u8[6]))
+
+/*brief Outlines the write mac address function signature. */
+#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u8[6]))
+
+
+/* Registers address offset */
+#define PCH_PHUB_PHUB_ID_REG			0x0000
+#define PCH_PHUB_QUEUE_PRI_VAL_REG		0x0004
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG		0x0008
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG		0x000C
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG		0x0010
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG		0x0014
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG	0x0018
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0	0x0020
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1	0x0024
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2	0x0028
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3	0x002C
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	0x0040
+#define CLKCFG_REG_OFFSET			0x500
+
+#define PCH_PHUB_OROM_SIZE 15360
+
+#endif
-- 
1.6.0.6


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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
@ 2010-06-22  5:33 Masayuki Ohtak
  2010-06-22 10:33 ` Masayuki Ohtak
                   ` (2 more replies)
  0 siblings, 3 replies; 45+ messages in thread
From: Masayuki Ohtak @ 2010-06-22  5:33 UTC (permalink / raw)
  To: Arnd Bergmann, Wang, Yong Y, Wang Qi"
  Cc: Intel OTC", Andrew", Alan Cox, LKML

Hi, Arnd and Yong Y

I have released Phub patch file.
Please confirm below.

Thanks, Ohtake.

Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
 drivers/char/Kconfig             |   12 +
 drivers/char/Makefile            |    2 +
 drivers/char/pch_phub/Makefile   |    7 +
 drivers/char/pch_phub/pch_phub.c |  937 +++++++++++++++++++++++
 drivers/char/pch_phub/pch_phub.h |   58 ++
 5 files changed, 1016 insertions(+), 0 deletions(-)
 create mode 100644 drivers/char/pch_phub/Makefile
 create mode 100755 drivers/char/pch_phub/pch_phub.c
 create mode 100755 drivers/char/pch_phub/pch_phub.h

diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index e023682..7ff728a 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -4,6 +4,18 @@
 
 menu "Character devices"
 
+config PCH_PHUB
+	tristate "PCH PHUB"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  PCH Packet Hub Host controller.
+	  This driver is for PCH Packet hub driver for Topcliff.
+	  This driver is integrated as built-in.
+	  This driver can access GbE MAC address.
+	  This driver can access HW register.
+	  You can also be integrated as module.
+
 config VT
 	bool "Virtual terminal" if EMBEDDED
 	depends on !S390
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index f957edf..1e3eb6c 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -111,6 +111,8 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
 obj-$(CONFIG_JS_RTC)		+= js-rtc.o
 js-rtc-y = rtc.o
 
+obj-$(CONFIG_PCH_PHUB)	+= pch_phub/
+
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c
 
diff --git a/drivers/char/pch_phub/Makefile b/drivers/char/pch_phub/Makefile
new file mode 100644
index 0000000..51ce785
--- /dev/null
+++ b/drivers/char/pch_phub/Makefile
@@ -0,0 +1,7 @@
+ifeq ($(CONFIG_PHUB_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_PCH_PHUB) += pch_phub_drv.o
+
+pch_phub_drv-objs := pch_phub.o
diff --git a/drivers/char/pch_phub/pch_phub.c b/drivers/char/pch_phub/pch_phub.c
new file mode 100755
index 0000000..6993182
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.c
@@ -0,0 +1,937 @@
+/*!
+ * @file pch_phub.c
+ * @brief Provides all the implementation of the interfaces pertaining to
+ *		the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+/* includes */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+#include "pch_phub.h"
+
+/*--------------------------------------------
+	macros
+--------------------------------------------*/
+/* Status Register offset */
+#define PHUB_STATUS 0x00
+/* Control Register offset */
+#define PHUB_CONTROL 0x04
+/* Time out value for Status Register */
+#define PHUB_TIMEOUT 0x05
+/* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_ENABLE 0x01
+/* Disabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE 0x00
+/* ROM data area start address offset */
+#define PCH_PHUB_ROM_START_ADDR 0x14
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG 128
+
+#define PCI_DEVICE_ID_PCH1_PHUB 0x8801
+
+#define PCH_MINOR_NOS 1
+#define CLKCFG_CAN_50MHZ 0x12000000
+#define CLKCFG_CANCLK_MASK 0xFF000000
+
+#define MODULE_NAME "pch_phub"
+
+/*--------------------------------------------
+	global variables
+--------------------------------------------*/
+/**
+ * struct pch_phub_reg - PHUB register structure
+ * @phub_id_reg:		 PHUB_ID register val
+ * @q_pri_val_reg:		 QUEUE_PRI_VAL register val
+ * @rc_q_maxsize_reg:	 RC_QUEUE_MAXSIZE register val
+ * @bri_q_maxsize_reg:	 BRI_QUEUE_MAXSIZE register val
+ * @comp_resp_timeout_reg:	 COMP_RESP_TIMEOUT register val
+ * @bus_slave_control_reg:	 BUS_SLAVE_CONTROL_REG register val
+ * @deadlock_avoid_type_reg:  DEADLOCK_AVOID_TYPE register val
+ * @intpin_reg_wpermit_reg0:  INTPIN_REG_WPERMIT register 0 val
+ * @intpin_reg_wpermit_reg1:  INTPIN_REG_WPERMIT register 1 val
+ * @intpin_reg_wpermit_reg2:  INTPIN_REG_WPERMIT register 2 val
+ * @intpin_reg_wpermit_reg3:  INTPIN_REG_WPERMIT register 3 val
+ * @int_reduce_control_reg:	 INT_REDUCE_CONTROL registers val
+ * @clkcfg_reg:		 CLK CFG register val
+ * @pch_phub_base_address:  register base address
+ * @pch_phub_extrom_base_address:  external rom base address
+ * @pch_phub_suspended: PHUB status val
+ */
+struct pch_phub_reg {
+	unsigned int phub_id_reg;
+	unsigned int q_pri_val_reg;
+	unsigned int rc_q_maxsize_reg;
+	unsigned int bri_q_maxsize_reg;
+	unsigned int comp_resp_timeout_reg;
+	unsigned int bus_slave_control_reg;
+	unsigned int deadlock_avoid_type_reg;
+	unsigned int intpin_reg_wpermit_reg0;
+	unsigned int intpin_reg_wpermit_reg1;
+	unsigned int intpin_reg_wpermit_reg2;
+	unsigned int intpin_reg_wpermit_reg3;
+	unsigned int int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+	unsigned int clkcfg_reg;
+	void __iomem *pch_phub_base_address;
+	void __iomem *pch_phub_extrom_base_address;
+	int pch_phub_suspended;
+} pch_phub_reg;
+
+static DEFINE_MUTEX(pch_phub_ioctl_mutex);
+
+/* ToDo: major number allocation via module parameter */
+static dev_t pch_phub_dev_no;
+static int pch_phub_major_no;
+static struct cdev pch_phub_dev;
+
+/*--------------------------------------------
+	functions implementations
+--------------------------------------------*/
+/** pch_phub_read_modify_write_reg - Implements the functionality of reading,
+ * 						modifying and writing register.
+ *  @reg_addr_offset:  Contains the register offset address value
+ *  @data:             Contains the writing value
+ *  @mask:             Contains the mask value
+ */
+static void pch_phub_read_modify_write_reg(unsigned int reg_addr_offset,
+				       unsigned int data, unsigned int mask)
+{
+	void __iomem *reg_addr = pch_phub_reg.pch_phub_base_address +\
+							 reg_addr_offset;
+	iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+	return;
+}
+
+
+/** pch_phub_save_reg_conf - saves register configuration
+ */
+static void pch_phub_save_reg_conf(struct pci_dev *pdev)
+{
+	unsigned int i = 0;
+	void __iomem *p = pch_phub_reg.pch_phub_base_address;
+
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	pch_phub_reg.phub_id_reg = ioread32(p + PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	pch_phub_reg.q_pri_val_reg = ioread32(p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	pch_phub_reg.rc_q_maxsize_reg =
+	    ioread32(p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	pch_phub_reg.bri_q_maxsize_reg =
+	    ioread32(p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	pch_phub_reg.comp_resp_timeout_reg =
+	    ioread32(p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	pch_phub_reg.bus_slave_control_reg =
+	    ioread32(p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	pch_phub_reg.deadlock_avoid_type_reg =
+	    ioread32(p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	pch_phub_reg.intpin_reg_wpermit_reg0 =
+	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	pch_phub_reg.intpin_reg_wpermit_reg1 =
+	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	pch_phub_reg.intpin_reg_wpermit_reg2 =
+	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	pch_phub_reg.intpin_reg_wpermit_reg3 =
+	    ioread32(p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+		"pch_phub_reg.phub_id_reg=%x, "
+		"pch_phub_reg.q_pri_val_reg=%x, "
+		"pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"pch_phub_reg.bus_slave_control_reg=%x, "
+		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		pch_phub_reg.phub_id_reg,
+		pch_phub_reg.q_pri_val_reg,
+		pch_phub_reg.rc_q_maxsize_reg,
+		pch_phub_reg.bri_q_maxsize_reg,
+		pch_phub_reg.comp_resp_timeout_reg,
+		pch_phub_reg.bus_slave_control_reg,
+		pch_phub_reg.deadlock_avoid_type_reg,
+		pch_phub_reg.intpin_reg_wpermit_reg0,
+		pch_phub_reg.intpin_reg_wpermit_reg1,
+		pch_phub_reg.intpin_reg_wpermit_reg2,
+		pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL registers */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		pch_phub_reg.int_reduce_control_reg[i] =
+		    ioread32(p +
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, pch_phub_reg.int_reduce_control_reg[i]);
+	}
+	/* save clk cfg register */
+	pch_phub_reg.clkcfg_reg = ioread32(p + CLKCFG_REG_OFFSET);
+
+	return;
+}
+
+/** pch_phub_restore_reg_conf - restore register configuration
+ */
+
+static void pch_phub_restore_reg_conf(struct pci_dev *pdev)
+{
+	unsigned int i;
+	void __iomem *p = pch_phub_reg.pch_phub_base_address;
+
+	dev_dbg(&pdev->dev, "pch_phub_restore_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	iowrite32(pch_phub_reg.phub_id_reg, p + PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	iowrite32(pch_phub_reg.q_pri_val_reg, p + PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	iowrite32(pch_phub_reg.rc_q_maxsize_reg,
+					p + PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	iowrite32(pch_phub_reg.bri_q_maxsize_reg,
+					p + PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	iowrite32(pch_phub_reg.comp_resp_timeout_reg,
+					p + PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	iowrite32(pch_phub_reg.bus_slave_control_reg,
+					p + PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	iowrite32(pch_phub_reg.deadlock_avoid_type_reg,
+					p + PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg0,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg1,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg2,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	iowrite32(pch_phub_reg.intpin_reg_wpermit_reg3,
+					p + PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+		"pch_phub_reg.phub_id_reg=%x, "
+		"pch_phub_reg.q_pri_val_reg=%x, "
+		"pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"pch_phub_reg.bus_slave_control_reg=%x, "
+		"pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		pch_phub_reg.phub_id_reg,
+		pch_phub_reg.q_pri_val_reg,
+		pch_phub_reg.rc_q_maxsize_reg,
+		pch_phub_reg.bri_q_maxsize_reg,
+		pch_phub_reg.comp_resp_timeout_reg,
+		pch_phub_reg.bus_slave_control_reg,
+		pch_phub_reg.deadlock_avoid_type_reg,
+		pch_phub_reg.intpin_reg_wpermit_reg0,
+		pch_phub_reg.intpin_reg_wpermit_reg1,
+		pch_phub_reg.intpin_reg_wpermit_reg2,
+		pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL register */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		iowrite32(pch_phub_reg.int_reduce_control_reg[i],
+			p + PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(&pdev->dev, "pch_phub_save_reg_conf : "
+			"pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, pch_phub_reg.int_reduce_control_reg[i]);
+	}
+
+	/*restore the clock config reg */
+	iowrite32(pch_phub_reg.clkcfg_reg, p + CLKCFG_REG_OFFSET);
+
+	return;
+}
+
+/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
+ *  									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static int pch_phub_read_serial_rom(unsigned int offset_address,
+							 unsigned char *data)
+{
+	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+								 offset_address;
+
+	*data = ioread8(mem_addr);
+
+	return 0;
+}
+
+/** pch_phub_write_serial_rom - Implements the functionality of writing Serial
+ *  									 ROM.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static int pch_phub_write_serial_rom(unsigned int offset_address,
+							 unsigned char data)
+{
+	int retval = 0;
+	void __iomem *mem_addr = pch_phub_reg.pch_phub_extrom_base_address +\
+						 (offset_address & 0xFFFFFFFC);
+	int i = 0;
+	unsigned int word_data = 0;
+
+	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+			pch_phub_reg.pch_phub_extrom_base_address +\
+								 PHUB_CONTROL);
+
+	word_data = ioread32(mem_addr);
+
+	switch (offset_address % 4) {
+	case 0:
+		word_data &= 0xFFFFFF00;
+		iowrite32((word_data | (unsigned int)data),
+						mem_addr);
+		break;
+	case 1:
+		word_data &= 0xFFFF00FF;
+		iowrite32((word_data | ((unsigned int)data << 8)),
+						mem_addr);
+		break;
+	case 2:
+		word_data &= 0xFF00FFFF;
+		iowrite32((word_data | ((unsigned int)data << 16)),
+						mem_addr);
+		break;
+	case 3:
+		word_data &= 0x00FFFFFF;
+		iowrite32((word_data | ((unsigned int)data << 24)),
+						mem_addr);
+		break;
+	}
+	while (0x00 !=
+	       ioread8(pch_phub_reg.pch_phub_extrom_base_address +\
+							 PHUB_STATUS)) {
+		msleep(1);
+		if (PHUB_TIMEOUT == i) {
+			retval = -EPERM;
+			break;
+		}
+		i++;
+	}
+
+	iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+			pch_phub_reg.pch_phub_extrom_base_address +\
+								 PHUB_CONTROL);
+
+	return retval;
+}
+
+/** pch_phub_read_serial_rom_val - Implements the functionality of reading
+ *  							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static int pch_phub_read_serial_rom_val(unsigned int offset_address,
+							 unsigned char *data)
+{
+	int retval = 0;
+	unsigned int mem_addr;
+
+	mem_addr = (offset_address / 4 * 8) + 3 -
+			(offset_address % 4) + PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_read_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_write_serial_rom_val - Implements the functionality of writing
+ *  							 Serial ROM value.
+ *  @offset_address: Contains the Serial ROM address offset value
+ *  @data: Contains the Serial ROM value
+ */
+static int pch_phub_write_serial_rom_val(unsigned int offset_address,
+				     unsigned char data)
+{
+	int retval = 0;
+	unsigned int mem_addr;
+
+	mem_addr =
+	    (offset_address / 4 * 8) + 3 - (offset_address % 4) +
+	    PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_write_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/** pch_phub_gbe_serial_rom_conf - makes Serial ROM header format configuration
+ *  						for Gigabit Ethernet MAC address
+ */
+static int pch_phub_gbe_serial_rom_conf(void)
+{
+	int retval = 0;
+
+	retval |= pch_phub_write_serial_rom(0x0b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x0a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x09, 0x01);
+	retval |= pch_phub_write_serial_rom(0x08, 0x02);
+
+	retval |= pch_phub_write_serial_rom(0x0f, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0e, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0d, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0c, 0x80);
+
+	retval |= pch_phub_write_serial_rom(0x13, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x12, 0x10);
+	retval |= pch_phub_write_serial_rom(0x11, 0x01);
+	retval |= pch_phub_write_serial_rom(0x10, 0x18);
+
+	retval |= pch_phub_write_serial_rom(0x1b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x1a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x19, 0x01);
+	retval |= pch_phub_write_serial_rom(0x18, 0x19);
+
+	retval |= pch_phub_write_serial_rom(0x23, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x22, 0x10);
+	retval |= pch_phub_write_serial_rom(0x21, 0x01);
+	retval |= pch_phub_write_serial_rom(0x20, 0x3a);
+
+	retval |= pch_phub_write_serial_rom(0x27, 0x01);
+	retval |= pch_phub_write_serial_rom(0x26, 0x00);
+	retval |= pch_phub_write_serial_rom(0x25, 0x00);
+	retval |= pch_phub_write_serial_rom(0x24, 0x00);
+
+	return retval;
+}
+
+/** pch_phub_read_gbe_mac_addr - Contains the Gigabit Ethernet MAC address
+ *  								offset value
+ *  @offset_address: Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+static int pch_phub_read_gbe_mac_addr(unsigned int offset_address,
+							 unsigned char *data)
+{
+	int retval = 0;
+
+	retval = pch_phub_read_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_write_gbe_mac_addr - Write MAC address
+ *  @offset_address: Contains the Gigabit Ethernet MAC address offset value
+ *  @data: Contains the Gigabit Ethernet MAC address value
+ */
+static int pch_phub_write_gbe_mac_addr(unsigned int offset_address,
+				   unsigned char data)
+{
+	int retval = 0;
+
+	retval = pch_phub_gbe_serial_rom_conf();
+	retval |= pch_phub_write_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/** pch_phub_read - Implements the read functionality of the Packet Hub module.
+ *  @file: Contains the reference of the file structure
+ *  @buf: Usermode buffer pointer
+ *  @size: Usermode buffer size
+ *  @ppos: Contains the reference of the file structure
+ */
+
+static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
+								 loff_t *ppos)
+{
+	unsigned int rom_signature = 0;
+	unsigned char rom_length;
+	int ret_value;
+	unsigned int tmp;
+	unsigned char data;
+	unsigned int addr_offset = 0;
+	unsigned int orom_size;
+	loff_t pos = *ppos;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	/*Get Rom signature*/
+	pch_phub_read_serial_rom(0x80, (unsigned char *)&rom_signature);
+	pch_phub_read_serial_rom(0x81, (unsigned char *)&tmp);
+	rom_signature |= (tmp & 0xff) << 8;
+	if (rom_signature == 0xAA55) {
+		pch_phub_read_serial_rom(0x82, &rom_length);
+		orom_size = rom_length * 512;
+		if (orom_size < pos)
+			return 0;
+
+		for (addr_offset = 0; addr_offset < size; addr_offset++) {
+			pch_phub_read_serial_rom(0x80 + addr_offset + pos,
+									 &data);
+			ret_value = copy_to_user(&buf[addr_offset], &data, 1);
+			if (ret_value)
+				return -EFAULT;
+
+			if (orom_size < pos + addr_offset) {
+				*ppos += addr_offset;
+				return addr_offset;
+			}
+
+		}
+	} else {
+		return -ENOEXEC;
+	}
+	*ppos += addr_offset;
+	return addr_offset;
+}
+
+/** pch_phub_write - Implements the write functionality of the Packet Hub
+ *  									 module.
+ *  @file: Contains the reference of the file structure
+ *  @buf: Usermode buffer pointer
+ *  @size: Usermode buffer size
+ *  @ppos: Contains the reference of the file structure
+ */
+static ssize_t pch_phub_write(struct file *file, const char __user *buf,
+						 size_t size, loff_t *ppos)
+{
+	unsigned int data;
+	int ret_value;
+	unsigned int addr_offset = 0;
+	loff_t pos = *ppos;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	for (addr_offset = 0; addr_offset < size; addr_offset++) {
+		ret_value = get_user(data, &buf[addr_offset]);
+		if (ret_value)
+			return -EFAULT;
+
+		ret_value = pch_phub_write_serial_rom(0x80 + addr_offset + pos,
+								 data);
+		if (ret_value)
+			return -EIO;
+
+		if (PCH_PHUB_OROM_SIZE < pos + addr_offset) {
+			*ppos += addr_offset;
+			return addr_offset;
+		}
+
+	}
+
+	*ppos += addr_offset;
+	return addr_offset;
+}
+
+
+/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
+ *  								 Hub module.
+ *  @inode: Contains the reference of the inode structure
+ *  @file: Contains the reference of the file structure
+ *  @cmd: Contains the command value
+ *  @arg: Contains the command argument value
+ */
+
+
+static long pch_phub_ioctl(struct file *file, unsigned int cmd,
+							 unsigned long arg)
+{
+	int ret_value = 0;
+	__u8 mac_addr[6];
+	int ret;
+	unsigned int i;
+	void __user *varg = (void __user *)arg;
+
+	ret = mutex_lock_interruptible(&pch_phub_ioctl_mutex);
+	if (ret) {
+		ret_value = -ERESTARTSYS;
+		goto return_nomutex;
+	}
+
+	if (pch_phub_reg.pch_phub_suspended == true) {
+		ret_value = -EPERM;
+		goto return_ioctrl;
+	}
+
+	switch (cmd) {
+	case IOCTL_PHUB_READ_MAC_ADDR:
+		for (i = 0; i < 6; i++)
+			pch_phub_read_gbe_mac_addr(i, &mac_addr[i]);
+
+		ret_value = copy_to_user(varg,
+					 mac_addr, sizeof(mac_addr));
+		if (ret_value) {
+			ret_value = -EFAULT;
+			goto return_ioctrl;
+		}
+		break;
+
+	case IOCTL_PHUB_WRITE_MAC_ADDR:
+		ret_value = copy_from_user(mac_addr, varg, sizeof(mac_addr));
+
+		if (ret_value) {
+			ret_value = -EFAULT;
+			goto return_ioctrl;
+		}
+		for (i = 0; i < 6; i++)
+			pch_phub_write_gbe_mac_addr(i, mac_addr[i]);
+		break;
+
+	default:
+		ret_value = -EINVAL;
+		break;
+	}
+return_ioctrl:
+	mutex_unlock(&pch_phub_ioctl_mutex);
+return_nomutex:
+	return ret_value;
+}
+
+
+/**
+ * file_operations structure initialization
+ */
+static const struct file_operations pch_phub_fops = {
+	.owner = THIS_MODULE,
+	.read = pch_phub_read,
+	.write = pch_phub_write,
+	.unlocked_ioctl = pch_phub_ioctl,
+	.llseek = default_llseek
+};
+
+
+/** pch_phub_probe - Implements the probe functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @id: Contains the reference of the pci_device_id structure
+ */
+static int __devinit pch_phub_probe(struct pci_dev *pdev,
+				       const struct pci_device_id *id)
+{
+	char *DRIVER_NAME = "pch_phub";
+	int ret;
+	unsigned int rom_size;
+
+	pch_phub_major_no = (pch_phub_major_no < 0 || pch_phub_major_no > 254) ?
+				0 : pch_phub_major_no;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"\npch_phub_probe : pci_enable_device FAILED");
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+			"pci_enable_device returns %d\n", ret);
+
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"pch_phub_probe : pci_request_regions FAILED");
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+		"pci_request_regions returns %d\n", ret);
+
+	pch_phub_reg.pch_phub_base_address = \
+					(void __iomem *)pci_iomap(pdev, 1, 0);
+
+	if (pch_phub_reg.pch_phub_base_address == 0) {
+		dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap FAILED");
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : pci_iomap SUCCESS and value "
+		"in pch_phub_base_address variable is 0x%08x\n",
+		(unsigned int)pch_phub_reg.pch_phub_base_address);
+
+	pch_phub_reg.pch_phub_extrom_base_address =
+	    (void __iomem *)pci_map_rom(pdev, &rom_size);
+	if (pch_phub_reg.pch_phub_extrom_base_address == 0) {
+		dev_dbg(&pdev->dev, "pch_phub_probe : pci_map_rom FAILED");
+		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe : "
+		"pci_map_rom SUCCESS and value in "
+		"pch_phub_extrom_base_address variable is 0x%08x\n",
+		(unsigned int)pch_phub_reg.pch_phub_extrom_base_address);
+
+	if (pch_phub_major_no) {
+		pch_phub_dev_no = MKDEV(pch_phub_major_no, 0);
+		ret = register_chrdev_region(pch_phub_dev_no,
+					   PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(&pdev->dev, "pch_phub_probe : "
+				"register_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				(void *)pch_phub_reg.pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(&pdev->dev, "pch_phub_probe : "
+				"register_chrdev_region returns %d\n", ret);
+	} else {
+		ret = alloc_chrdev_region(&pch_phub_dev_no, 0,
+						PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(&pdev->dev, "pch_phub_probe : "
+					"alloc_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				    (void *)pch_phub_reg.pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(&pdev->dev, "pch_phub_probe : "
+			"alloc_chrdev_region returns %d\n", ret);
+	}
+
+	cdev_init(&pch_phub_dev, &pch_phub_fops);
+	dev_dbg(&pdev->dev,
+			"pch_phub_probe :  cdev_init invoked successfully\n");
+
+	pch_phub_dev.owner = THIS_MODULE;
+	pch_phub_dev.ops = &pch_phub_fops;
+
+	ret = cdev_add(&pch_phub_dev, pch_phub_dev_no, PCH_MINOR_NOS);
+	if (ret) {
+		dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add FAILED");
+		unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+		pci_unmap_rom(pdev,
+			(void *)pch_phub_reg.pch_phub_extrom_base_address);
+		pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(&pdev->dev, "pch_phub_probe :  cdev_add returns %d\n", ret);
+
+	/*set the clock config reg if CAN clock is 50Mhz */
+	dev_dbg(&pdev->dev, "pch_phub_probe : invoking "
+		"pch_phub_read_modify_write_reg "
+		"to set CLKCFG reg for CAN clk 50Mhz\n");
+	pch_phub_read_modify_write_reg((unsigned int)CLKCFG_REG_OFFSET,
+					  CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+
+	/* set the prefech value */
+	iowrite32(0x000ffffa, pch_phub_reg.pch_phub_base_address + 0x14);
+	/* set the interrupt delay value */
+	iowrite32(0x25, pch_phub_reg.pch_phub_base_address + 0x44);
+	return 0;
+
+err_probe:
+	dev_dbg(&pdev->dev, "pch_phub_probe returns %d\n", ret);
+	return ret;
+}
+
+/** pch_phub_remove - Implements the remove functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+
+	cdev_del(&pch_phub_dev);
+	dev_dbg(&pdev->dev,
+			"pch_phub_remove - cdev_del Invoked successfully\n");
+
+	unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"unregister_chrdev_region Invoked successfully\n");
+
+	pci_unmap_rom(pdev, (void *)pch_phub_reg.pch_phub_extrom_base_address);
+
+	pci_iounmap(pdev, (void *)pch_phub_reg.pch_phub_base_address);
+
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+			"pci_iounmap Invoked successfully\n");
+
+	pci_release_regions(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"pci_release_regions Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_remove - "
+		"pci_disable_device Invoked successfully\n");
+
+}
+
+#ifdef CONFIG_PM
+
+/** pch_phub_suspend - Implements the suspend functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ *  @state: Contains the reference of the pm_message_t structure
+ */
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int ret;
+
+	pch_phub_reg.pch_phub_suspended = true;/* For blocking further IOCTLs */
+
+	pch_phub_save_reg_conf(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+		"pch_phub_save_reg_conf Invoked successfully\n");
+
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+			" pch_phub_suspend -pci_save_state returns-%d\n", ret);
+		return ret;
+	}
+	dev_dbg(&pdev->dev,
+			"pch_phub_suspend - pci_save_state returns %d\n", ret);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_disable_device Invoked successfully\n");
+
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	dev_dbg(&pdev->dev, "pch_phub_suspend - "
+			"pci_set_power_state Invoked successfully   "
+			"return = %d\n", 0);
+
+	return 0;
+}
+
+/** pch_phub_resume - Implements the resume functionality of the module.
+ *  @pdev: Contains the reference of the pci_dev structure
+ */
+static int pch_phub_resume(struct pci_dev *pdev)
+{
+
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pci_set_power_state Invoked successfully\n");
+
+	pci_restore_state(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pci_restore_state Invoked successfully\n");
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(&pdev->dev,
+				"pch_phub_resume-pci_enable_device failed ");
+		return ret;
+	}
+
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+			"pci_enable_device returns -%d\n", ret);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pch_phub_restore_reg_conf(pdev);
+	dev_dbg(&pdev->dev, "pch_phub_resume - "
+		"pch_phub_restore_reg_conf Invoked successfully\n");
+
+	pch_phub_reg.pch_phub_suspended = false;
+
+	dev_dbg(&pdev->dev, "pch_phub_resume  returns- %d\n", 0);
+	return 0;
+}
+#endif /* CONFIG_PM */
+
+static struct pci_device_id pch_phub_pcidev_id[] = {
+
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+	{0,}
+};
+
+
+static struct pci_driver pch_phub_driver = {
+	.name = "pch_phub",
+	.id_table = pch_phub_pcidev_id,
+	.probe = pch_phub_probe,
+	.remove = __devexit_p(pch_phub_remove),
+#ifdef CONFIG_PM
+	.suspend = pch_phub_suspend,
+	.resume = pch_phub_resume
+#endif
+};
+
+/** pch_phub_pci_init - Implements the initialization functionality of
+ *  								 the module.
+ */
+static int __init pch_phub_pci_init(void)
+{
+	int ret;
+	ret = pci_register_driver(&pch_phub_driver);
+
+	return ret;
+}
+
+/** pch_phub_pci_exit - Implements the exit functionality of the module.
+ */
+static void __exit pch_phub_pci_exit(void)
+{
+	pci_unregister_driver(&pch_phub_driver);
+
+}
+
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);
+
+MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/char/pch_phub/pch_phub.h b/drivers/char/pch_phub/pch_phub.h
new file mode 100755
index 0000000..25d7c56
--- /dev/null
+++ b/drivers/char/pch_phub/pch_phub.h
@@ -0,0 +1,58 @@
+#ifndef __PCH_PHUB_H__
+#define __PCH_PHUB_H__
+/*!
+ * @file pch_phub.h
+ * @brief Provides all the interfaces pertaining to the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+#define PHUB_IOCTL_MAGIC 		(0xf7)
+
+/*Outlines the read mac address function signature. */
+#define IOCTL_PHUB_READ_MAC_ADDR (_IOR(PHUB_IOCTL_MAGIC, 6, __u8[6]))
+
+/*brief Outlines the write mac address function signature. */
+#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u8[6]))
+
+
+/* Registers address offset */
+#define PCH_PHUB_PHUB_ID_REG			0x0000
+#define PCH_PHUB_QUEUE_PRI_VAL_REG		0x0004
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG		0x0008
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG		0x000C
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG		0x0010
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG		0x0014
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG	0x0018
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0	0x0020
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1	0x0024
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2	0x0028
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3	0x002C
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	0x0040
+#define CLKCFG_REG_OFFSET           		0x500
+
+#define PCH_PHUB_OROM_SIZE 15360
+
+#endif
-- 
1.6.0.6

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
@ 2010-06-22  2:14 Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-22  2:14 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Arnd,

Sorry, for late patch releasing.

I have modified like below.
We will release today.

>
> On Thursday 17 June 2010, Masayuki Ohtak wrote:
> > +
> > +#define PCH_READ_REG(a) ioread32(pch_phub_reg.pch_phub_base_address + (a))
> > +
> > +#define PCH_WRITE_REG(a, b) iowrite32((a), pch_phub_reg.pch_phub_base_address +\
> > + (b))
>
> I'd recommend just getting rid of these abstractions. You only use
> them in one or two functions each, so you can just as well add a local
> variable there and do
>
> void __iomem *p = pch_phub_reg.pch_phub_base_address;
> foo = ioread32(p + foo_offset);
> bar = ioread32(p + bar_offset);
> ...
>
> Not really important, but this way it would be more conventional
> without having to write extra code.
Modified like above.


>
> > +/*--------------------------------------------
> > + global variables
> > +--------------------------------------------*/
> > +/**
> > + * struct pch_phub_reg_t - PHUB register structure
> > + * @phub_id_reg: PHUB_ID register val
> > + * @q_pri_val_reg: QUEUE_PRI_VAL register val
> > + * @rc_q_maxsize_reg: RC_QUEUE_MAXSIZE register val
> > + * @bri_q_maxsize_reg: BRI_QUEUE_MAXSIZE register val
> > + * @comp_resp_timeout_reg: COMP_RESP_TIMEOUT register val
> > + * @bus_slave_control_reg: BUS_SLAVE_CONTROL_REG register val
> > + * @deadlock_avoid_type_reg:  DEADLOCK_AVOID_TYPE register val
> > + * @intpin_reg_wpermit_reg0:  INTPIN_REG_WPERMIT register 0 val
> > + * @intpin_reg_wpermit_reg1:  INTPIN_REG_WPERMIT register 1 val
> > + * @intpin_reg_wpermit_reg2:  INTPIN_REG_WPERMIT register 2 val
> > + * @intpin_reg_wpermit_reg3:  INTPIN_REG_WPERMIT register 3 val
> > + * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val
> > + * @clkcfg_reg: CLK CFG register val
> > + * @pch_phub_base_address:  register base address
> > + * @pch_phub_extrom_base_address:  external rom base address
> > + * @pch_phub_suspended: PHUB status val
> > + */
> > +struct pch_phub_reg_t {
>
> It would be better to drop the _t postfix on the type name.
> By convention, we use this only for typedefs on simple data
> types like off_t but not for structures.
Deleted '_t' prefix

>
> > + __u32 phub_id_reg;
> > + __u32 q_pri_val_reg;
> > + __u32 rc_q_maxsize_reg;
>
> When I told you to change the ioctl arguments to use __u32 instead
> of u32, I was only referring to those parts that are in the user-visible
> section of the header file. While it does not hurt to use __u32 in
> the kernel, you should understand the distinction.
The following types are modified like below except user-visible secton '__u8 mac_addr[6].
__u32 -> unsigned int
__s32 -> int
__u8  -> unsigned char
__s8  -> char


>
> > +/** pch_phub_write - Implements the write functionality of the Packet Hub
> > + *  module.
> > + *  @file: Contains the reference of the file structure
> > + *  @buf: Usermode buffer pointer
> > + *  @size: Usermode buffer size
> > + *  @ppos: Contains the reference of the file structure
> > + */
> > +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> > + size_t size, loff_t *ppos)
> > +{
> > + static __u32 data;
>
> No need to make data static.
Deleted 'static'.

>
> > + __s32 ret_value;
> > + __u32 addr_offset = 0;
> > + loff_t pos = *ppos;
> > +
> > + if (pos < 0)
> > + return -EINVAL;
> > +
> > + for (addr_offset = 0; addr_offset < size; addr_offset++) {
> > + get_user(data, &buf[addr_offset]);
> > +
> > + ret_value = pch_phub_write_serial_rom(0x80 + addr_offset + pos,
> > + data);
> > + if (ret_value)
> > + return -EFAULT;
>
> You should return -EFAULT if the get_user() call fails, otherwise you have
> a possible security hole. If pch_phub_write_serial_rom fails, the correct
> return code would be -EIO.
Modified to care returned value of get_user.
Modified retunrn code of pch_phub_write_serial_rom to -EIO.

>
> > +/**
> > + * file_operations structure initialization
> > + */
> > +static const struct file_operations pch_phub_fops = {
> > + .owner = THIS_MODULE,
> > + .read = pch_phub_read,
> > + .write = pch_phub_write,
> > + .unlocked_ioctl = pch_phub_ioctl,
> > +};
>
> If would be good to add a line of
> .llseek = default_llseek,
> here. I have a patch to change the default llseek method to one
> that disallows seeking, so if you add this line, there is one
> less driver for me to patch.
Added a line of '.llseek = default_llseek'.

Thanks,
Ohtake

----- Original Message ----- 
From: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
To: "Arnd Bergmann" <arnd@arndb.de>
Cc: "Wang, Yong Y" <yong.y.wang@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "LKML" <linux-kernel@vger.kernel.org>; "Alan Cox" <alan@lxorguk.ukuu.org.uk>
Sent: Friday, June 18, 2010 8:49 AM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> Hi Arnd,
>
> I will modify for your comments by today or tomorrow.
>
> Thanks,
> Ohtake
>
> ----- Original Message ----- 
> From: "Arnd Bergmann" <arnd@arndb.de>
> To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
> Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML" <linux-kernel@vger.kernel.org>; "Andrew"
> <andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y"
> <yong.y.wang@intel.com>
> Sent: Thursday, June 17, 2010 8:59 PM
> Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
>
>
> > Looks almost good to me now. Some more details (only the -EFAULT return code
> > is a real issue, the other ones are cosmetic changes):
> >
> > On Thursday 17 June 2010, Masayuki Ohtak wrote:
> > > +
> > > +#define PCH_READ_REG(a) ioread32(pch_phub_reg.pch_phub_base_address + (a))
> > > +
> > > +#define PCH_WRITE_REG(a, b) iowrite32((a), pch_phub_reg.pch_phub_base_address +\
> > > + (b))
> >
> > I'd recommend just getting rid of these abstractions. You only use
> > them in one or two functions each, so you can just as well add a local
> > variable there and do
> >
> > void __iomem *p = pch_phub_reg.pch_phub_base_address;
> > foo = ioread32(p + foo_offset);
> > bar = ioread32(p + bar_offset);
> > ...
> >
> > Not really important, but this way it would be more conventional
> > without having to write extra code.
> >
> > > +/*--------------------------------------------
> > > + global variables
> > > +--------------------------------------------*/
> > > +/**
> > > + * struct pch_phub_reg_t - PHUB register structure
> > > + * @phub_id_reg: PHUB_ID register val
> > > + * @q_pri_val_reg: QUEUE_PRI_VAL register val
> > > + * @rc_q_maxsize_reg: RC_QUEUE_MAXSIZE register val
> > > + * @bri_q_maxsize_reg: BRI_QUEUE_MAXSIZE register val
> > > + * @comp_resp_timeout_reg: COMP_RESP_TIMEOUT register val
> > > + * @bus_slave_control_reg: BUS_SLAVE_CONTROL_REG register val
> > > + * @deadlock_avoid_type_reg:  DEADLOCK_AVOID_TYPE register val
> > > + * @intpin_reg_wpermit_reg0:  INTPIN_REG_WPERMIT register 0 val
> > > + * @intpin_reg_wpermit_reg1:  INTPIN_REG_WPERMIT register 1 val
> > > + * @intpin_reg_wpermit_reg2:  INTPIN_REG_WPERMIT register 2 val
> > > + * @intpin_reg_wpermit_reg3:  INTPIN_REG_WPERMIT register 3 val
> > > + * @int_reduce_control_reg: INT_REDUCE_CONTROL registers val
> > > + * @clkcfg_reg: CLK CFG register val
> > > + * @pch_phub_base_address:  register base address
> > > + * @pch_phub_extrom_base_address:  external rom base address
> > > + * @pch_phub_suspended: PHUB status val
> > > + */
> > > +struct pch_phub_reg_t {
> >
> > It would be better to drop the _t postfix on the type name.
> > By convention, we use this only for typedefs on simple data
> > types like off_t but not for structures.
> >
> > > + __u32 phub_id_reg;
> > > + __u32 q_pri_val_reg;
> > > + __u32 rc_q_maxsize_reg;
> >
> > When I told you to change the ioctl arguments to use __u32 instead
> > of u32, I was only referring to those parts that are in the user-visible
> > section of the header file. While it does not hurt to use __u32 in
> > the kernel, you should understand the distinction.
> >
> > > +/** pch_phub_write - Implements the write functionality of the Packet Hub
> > > + *  module.
> > > + *  @file: Contains the reference of the file structure
> > > + *  @buf: Usermode buffer pointer
> > > + *  @size: Usermode buffer size
> > > + *  @ppos: Contains the reference of the file structure
> > > + */
> > > +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> > > + size_t size, loff_t *ppos)
> > > +{
> > > + static __u32 data;
> >
> > No need to make data static.
> >
> > > + __s32 ret_value;
> > > + __u32 addr_offset = 0;
> > > + loff_t pos = *ppos;
> > > +
> > > + if (pos < 0)
> > > + return -EINVAL;
> > > +
> > > + for (addr_offset = 0; addr_offset < size; addr_offset++) {
> > > + get_user(data, &buf[addr_offset]);
> > > +
> > > + ret_value = pch_phub_write_serial_rom(0x80 + addr_offset + pos,
> > > + data);
> > > + if (ret_value)
> > > + return -EFAULT;
> >
> > You should return -EFAULT if the get_user() call fails, otherwise you have
> > a possible security hole. If pch_phub_write_serial_rom fails, the correct
> > return code would be -EIO.
> >
> > > +/**
> > > + * file_operations structure initialization
> > > + */
> > > +static const struct file_operations pch_phub_fops = {
> > > + .owner = THIS_MODULE,
> > > + .read = pch_phub_read,
> > > + .write = pch_phub_write,
> > > + .unlocked_ioctl = pch_phub_ioctl,
> > > +};
> >
> > If would be good to add a line of
> > .llseek = default_llseek,
> > here. I have a patch to change the default llseek method to one
> > that disallows seeking, so if you add this line, there is one
> > less driver for me to patch.
> >
> > Arnd
> >
>
>
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-16 10:50     ` Arnd Bergmann
@ 2010-06-17  0:17       ` Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-17  0:17 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Arnd,

Thank you.
I will try it.

Ohtake.

----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML" <linux-kernel@vger.kernel.org>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y"
<yong.y.wang@intel.com>
Sent: Wednesday, June 16, 2010 7:50 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Wednesday 16 June 2010, Masayuki Ohtake wrote:
> > > Especially if you want to be able to use tools like 'cat', 'hexdump'
> > > or 'dd' on the file descriptor, you need to implement support for
> > > short reads.
> > I don't know how to test(short read/write access).
> > Could you tell me how to do the above ?
>
> The easiest way is using dd, where you can specify the block
> size as well as input and output offsets.
>
> e.g.
> dd if=/dev/topcliffphub of=testfile bs=7
>
> Should be able to read the contents of the rom completely
> without error conditions, copying seven bytes at a time.
>
> dd if=inputfile of=/dev/topcliffphub bs=1 seek=1024 count=16
>
> would write 16 bytes from inputfile into the rom at position 1024.
>
> Arnd
>




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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-16  8:58   ` Masayuki Ohtake
@ 2010-06-16 10:50     ` Arnd Bergmann
  2010-06-17  0:17       ` Masayuki Ohtake
  0 siblings, 1 reply; 45+ messages in thread
From: Arnd Bergmann @ 2010-06-16 10:50 UTC (permalink / raw)
  To: Masayuki Ohtake; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

On Wednesday 16 June 2010, Masayuki Ohtake wrote:
> > Especially if you want to be able to use tools like 'cat', 'hexdump'
> > or 'dd' on the file descriptor, you need to implement support for
> > short reads.
> I don't know how to test(short read/write access).
> Could you tell me how to do the above ?

The easiest way is using dd, where you can specify the block
size as well as input and output offsets.

e.g.
dd if=/dev/topcliffphub of=testfile bs=7

Should be able to read the contents of the rom completely
without error conditions, copying seven bytes at a time.

dd if=inputfile of=/dev/topcliffphub bs=1 seek=1024 count=16

would write 16 bytes from inputfile into the rom at position 1024.

	Arnd

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-15 10:37 ` Arnd Bergmann
  2010-06-15 12:14   ` Masayuki Ohtake
@ 2010-06-16  8:58   ` Masayuki Ohtake
  2010-06-16 10:50     ` Arnd Bergmann
  1 sibling, 1 reply; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-16  8:58 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Arnd,

For user useful, I have decided to implement 'pos' processing to Phub driver.

I have a question.
> Especially if you want to be able to use tools like 'cat', 'hexdump'
> or 'dd' on the file descriptor, you need to implement support for
> short reads.
I don't know how to test(short read/write access).
Could you tell me how to do the above ?

Thanks,
Ohtake.

----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "Wang, Yong Y" <yong.y.wang@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "LKML" <linux-kernel@vger.kernel.org>; "Alan Cox" <alan@lxorguk.ukuu.org.uk>
Sent: Tuesday, June 15, 2010 7:37 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Tuesday 15 June 2010, Masayuki Ohtake wrote:
> > I have additional question.
> > > - When the user does an llseek or pread, the *pos argument is not zero,
> > >   so you should return data from the middle, but you still return data
> > >   from the beginning.
> >
> >
> > Must a driver read/write method support '*pos' parameter ?
> > We think PHUB doesn't have to support '*pos',
> > and ,we think, PHUB OROM R/W function supports only whole of ROM data R/W is enough.
> > Please give us your opinion.
>
> While you do not strictly need to support *pos to get the functionality
> you want, it should be easy enough to implement and it will make the
> read/write callbacks conform to the general semantics of file based
> I/O. Especially if you want to be able to use tools like 'cat', 'hexdump'
> or 'dd' on the file descriptor, you need to implement support for
> short reads. If you are unsure about how to do that correctly, I can
> help you some more. A good reference implementation is
> simple_transaction_read in fs/libfs.c, which simply returns some
> private memory.
>
> If there is a strict hardware limitation that prevents you from doing
> partial writes, you could expose that in the interface and return -EIO
> in case of invalid *pos or size arguements, but my impression was that
> the hardware can deal with bytewise access.
>
> Arnd
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-15 10:37 ` Arnd Bergmann
@ 2010-06-15 12:14   ` Masayuki Ohtake
  2010-06-16  8:58   ` Masayuki Ohtake
  1 sibling, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-15 12:14 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew, LKML, Alan Cox

Hi Arnd,

Thank you for your comments.
I will study your showed reference.

Thanks,
Ohtake

----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "Wang, Yong Y" <yong.y.wang@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "LKML" <linux-kernel@vger.kernel.org>; "Alan Cox" <alan@lxorguk.ukuu.org.uk>
Sent: Tuesday, June 15, 2010 7:37 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Tuesday 15 June 2010, Masayuki Ohtake wrote:
> > I have additional question.
> > > - When the user does an llseek or pread, the *pos argument is not zero,
> > >   so you should return data from the middle, but you still return data
> > >   from the beginning.
> >
> >
> > Must a driver read/write method support '*pos' parameter ?
> > We think PHUB doesn't have to support '*pos',
> > and ,we think, PHUB OROM R/W function supports only whole of ROM data R/W is enough.
> > Please give us your opinion.
>
> While you do not strictly need to support *pos to get the functionality
> you want, it should be easy enough to implement and it will make the
> read/write callbacks conform to the general semantics of file based
> I/O. Especially if you want to be able to use tools like 'cat', 'hexdump'
> or 'dd' on the file descriptor, you need to implement support for
> short reads. If you are unsure about how to do that correctly, I can
> help you some more. A good reference implementation is
> simple_transaction_read in fs/libfs.c, which simply returns some
> private memory.
>
> If there is a strict hardware limitation that prevents you from doing
> partial writes, you could expose that in the interface and return -EIO
> in case of invalid *pos or size arguements, but my impression was that
> the hardware can deal with bytewise access.
>
> Arnd
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-15  6:58 Masayuki Ohtake
@ 2010-06-15 10:37 ` Arnd Bergmann
  2010-06-15 12:14   ` Masayuki Ohtake
  2010-06-16  8:58   ` Masayuki Ohtake
  0 siblings, 2 replies; 45+ messages in thread
From: Arnd Bergmann @ 2010-06-15 10:37 UTC (permalink / raw)
  To: Masayuki Ohtake; +Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew, LKML, Alan Cox

On Tuesday 15 June 2010, Masayuki Ohtake wrote:
> I have additional question.
> > - When the user does an llseek or pread, the *pos argument is not zero,
> >   so you should return data from the middle, but you still return data
> >   from the beginning.
> 
> 
> Must a driver read/write method support '*pos' parameter ?
> We think PHUB doesn't have to support '*pos',
> and ,we think, PHUB OROM R/W function supports only whole of ROM data R/W is enough.
> Please give us your opinion.

While you do not strictly need to support *pos to get the functionality
you want, it should be easy enough to implement and it will make the
read/write callbacks conform to the general semantics of file based
I/O. Especially if you want to be able to use tools like 'cat', 'hexdump'
or 'dd' on the file descriptor, you need to implement support for
short reads. If you are unsure about how to do that correctly, I can
help you some more. A good reference implementation is
simple_transaction_read in fs/libfs.c, which simply returns some
private memory.

If there is a strict hardware limitation that prevents you from doing
partial writes, you could expose that in the interface and return -EIO
in case of invalid *pos or size arguements, but my impression was that
the hardware can deal with bytewise access.

	Arnd

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
@ 2010-06-15  6:58 Masayuki Ohtake
  2010-06-15 10:37 ` Arnd Bergmann
  0 siblings, 1 reply; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-15  6:58 UTC (permalink / raw)
  To: Arnd Bergmann, Masayuki Ohtake
  Cc: Wang, Yong Y, Wang, Qi, Intel OTC, Andrew, LKML, Alan Cox

Hi Arnd,

I have additional question.
> - When the user does an llseek or pread, the *pos argument is not zero,
>   so you should return data from the middle, but you still return data
>   from the beginning.


Must a driver read/write method support '*pos' parameter ?
We think PHUB doesn't have to support '*pos',
and ,we think, PHUB OROM R/W function supports only whole of ROM data R/W is enough.
Please give us your opinion.

Thanks.
Ohtake

----- Original Message ----- 
From: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
To: "Arnd Bergmann" <arnd@arndb.de>
Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML" <linux-kernel@vger.kernel.org>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y"
<yong.y.wang@intel.com>
Sent: Tuesday, June 15, 2010 3:25 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> Hi Arnd,
>
> >> +#to set CAN clock to 50Mhz
> >> +ifdef CONFIG_PCH_CAN_PCLK_50MHZ
> >> +EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
> >> +endif
>
> >This should not be necessary. Just use CONFIG_PCH_CAN_PCLK_50MHZ directly
> >in the code instead of the extra PCH_CAN_PCLK_50MHZ macro.
>
> I have a question. I show the above reason.
> In case CAN is integrated as MODULE, macro name is CONFIG_PCH_CAN_PCLK_50MHZ_MODULE.
> On the other hand, integrated as built-in, CONFIG_PCH_CAN_PCLK_50MHZ.
> To prevent PHUB source code from integrated as MODULE or BUILT-IN,
> we re-define macro name in Makefile.
>
> If use CONFIG_PCH_CAN_PCLK_50MHZ directly in the source code,
> in case buit-in, behavior is not correct.
> But in case module, behavior is not correct.
>
> Please give us your opinion
>
> Thanks,
> Ohtake.
> ----- Original Message ----- 
> From: "Arnd Bergmann" <arnd@arndb.de>
> To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
> Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML" <linux-kernel@vger.kernel.org>; "Andrew"
> <andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y"
> <yong.y.wang@intel.com>
> Sent: Monday, June 14, 2010 9:50 PM
> Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
>
>
> > On Monday 14 June 2010, Masayuki Ohtak wrote:
> > > Hi we have modified for your comments.
> > > Please Confirm below.
> >
> > Looks much better. A few more comments about the new code:
> >
> > > +#to set CAN clock to 50Mhz
> > > +ifdef CONFIG_PCH_CAN_PCLK_50MHZ
> > > +EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
> > > +endif
> >
> > This should not be necessary. Just use CONFIG_PCH_CAN_PCLK_50MHZ directly
> > in the code instead of the extra PCH_CAN_PCLK_50MHZ macro.
> > > +
> > > +DEFINE_MUTEX(pch_phub_ioctl_mutex);
> >
> > This should probable be 'static DEFINE_MUTEX', since the symbol does not
> > need to be visible in the entire kernel.
> >
> >
> > > +/*--------------------------------------------
> > > + internal function prototypes
> > > +--------------------------------------------*/
> > > +static __s32 __devinit pch_phub_probe(struct pci_dev *pdev, const
> > > +        struct pci_device_id *id);
> > > +static void __devexit pch_phub_remove(struct pci_dev *pdev);
> > > +static __s32 pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
> > > +static __s32 pch_phub_resume(struct pci_dev *pdev);
> > > +static __s32 pch_phub_open(struct inode *inode, struct file *file);
> > > +static __s32 pch_phub_release(struct inode *inode, struct file *file);
> > > +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> > > + unsigned long arg);
> > > +static ssize_t pch_phub_read(struct file *, char __user *, size_t, loff_t *);
> > > +static ssize_t pch_phub_write(struct file *, const char __user *,
> > > + size_t, loff_t *);
> >
> > My general recommendation would be to reorder all the function
> > definitions so that you don't need any of these forward declarations.
> > That is the order used in most parts of the kernel (so you start reading
> > at the bottom), and it makes it easier to understand the structure of
> > the code IMHO.
> >
> > > +/** pch_phub_open - Implements the Initializing and opening of the Packet Hub
> > > + module.
> > > + *  @inode: Contains the reference of the inode structure
> > > + *  @file: Contains the reference of the file structure
> > > + */
> > > +static __s32 pch_phub_open(struct inode *inode, struct file *file)
> > > +{
> > > + __s32 ret;
> > > +
> > > + spin_lock(&pch_phub_lock);
> > > + if (pch_phub_reg.pch_phub_opencount) {
> > > + ret = -EBUSY;
> > > + } else {
> > > + pch_phub_reg.pch_phub_opencount++;
> > > + ret = 0;
> > > + }
> > > + spin_unlock(&pch_phub_lock);
> > > +
> > > + return ret;
> > > +}
> >
> > As far as I can tell, there is no longer a reason to prevent multiple
> > openers. Besides, even if there is only a single user, you might still
> > have concurrency problems, so the lock does not help and you could remove
> > the open function entirely.
> >
> > > +/** pch_phub_read - Implements the read functionality of the Packet Hub module.
> > > + *  @file: Contains the reference of the file structure
> > > + *  @buf: Usermode buffer pointer
> > > + *  @size: Usermode buffer size
> > > + *  @pos: Contains the reference of the file structure
> > > + */
> > > +
> > > +static ssize_t pch_phub_read(struct file *file, char __user *buf, size_t size,
> > > + loff_t *pos)
> > > +{
> > > + __u32 rom_signature = 0;
> > > + __u8 rom_length;
> > > + __s32 ret_value;
> > > + __u32 tmp;
> > > + __u8 data;
> > > + __u32 addr_offset = 0;
> > > +
> > > + /*Get Rom signature*/
> > > + pch_phub_read_serial_rom(0x80, (__u8 *)&rom_signature);
> > > + pch_phub_read_serial_rom(0x81, (__u8 *)&tmp);
> > > + rom_signature |= (tmp & 0xff) << 8;
> > > + if (rom_signature == 0xAA55) {
> > > + pch_phub_read_serial_rom(0x82, &rom_length);
> > > + if (size > (rom_length * 512)+1)
> > > + return -ENOMEM;
> > > +
> > > + for (addr_offset = 0;
> > > + addr_offset <= ((__u32)rom_length * 512);
> > > + addr_offset++) {
> > > + pch_phub_read_serial_rom(0x80 + addr_offset, &data);
> > > + ret_value = copy_to_user((void *)&buf[addr_offset],
> > > + (void *)&data, 1);
> > > + if (ret_value)
> > > + return -EFAULT;
> > > + }
> > > + } else {
> > > + return -ENOEXEC;
> > > + }
> > > +
> > > + return rom_length * 512 + 1;
> > > +}
> >
> > This function has multiple problems:
> >
> > - If the size argument is less than rom_length*512, you access past the
> >   user-provided buffer.
> > - When the user does an llseek or pread, the *pos argument is not zero,
> >   so you should return data from the middle, but you still return data
> >   from the beginning.
> > - You don't update the *pos argument with the new position, so you cannot
> >   continue the read where the first call left.
> > - Instead of returning -ENOMEM, you should just the data you have (or
> >   0 for end-of-file).
> > - ENOEXEC does not seem appropriate either: The user can just check
> >   these buffer for the signature here, so you just as well return
> >   whatever you find in the ROM.
> >
> > > +
> > > +/** pch_phub_write - Implements the write functionality of the Packet Hub
> > > + *  module.
> > > + *  @file: Contains the reference of the file structure
> > > + *  @buf: Usermode buffer pointer
> > > + *  @size: Usermode buffer size
> > > + *  @pos: Contains the reference of the file structure
> > > + */
> > > +static ssize_t pch_phub_write(struct file *file, const char __user *buf,
> > > + size_t size, loff_t *pos)
> > > +{
> > > + static __u8 data[PCH_PHUB_OROM_SIZE];
> > > + __s32 ret_value;
> > > + __u32 addr_offset = 0;
> > > +
> > > + if (size > PCH_PHUB_OROM_SIZE)
> > > + size = PCH_PHUB_OROM_SIZE;
> > > +
> > > + ret_value = copy_from_user(data, buf, size);
> > > + if (ret_value)
> > > + return -EFAULT;
> > > +
> > > + for (addr_offset = 0; addr_offset < size; addr_offset++) {
> > > + ret_value = pch_phub_write_serial_rom(0x80 + addr_offset,
> > > + data[addr_offset]);
> > > + }
> > > +
> > > + return size;
> > > +}
> >
> > This has the same problems, plus a buffer overflow: You must never have an
> > array of multiple kilobytes on the stack (data[PCH_PHUB_OROM_SIZE]), because
> > the stack itself is only a few kilobytes in the kernel. Better use a loop
> > with copy_from_user like the read function does.
> >
> > > +/** pch_phub_release - Implements the release functionality of the Packet Hub
> > > + *  module.
> > > + *  @inode: Contains the reference of the inode structure
> > > + *  @file: Contains the reference of the file structure
> > > + */
> > > +static __s32 pch_phub_release(struct inode *inode, struct file *file)
> > > +{
> > > + spin_lock(&pch_phub_lock);
> > > +
> > > + if (pch_phub_reg.pch_phub_opencount > 0)
> > > + pch_phub_reg.pch_phub_opencount--;
> > > + spin_unlock(&pch_phub_lock);
> > > +
> > > + return 0;
> > > +}
> >
> > When you remove the open function, this one can go away as well.
> >
> > > +/** pch_phub_ioctl - Implements the various ioctl functionalities of the Packet
> > > + *  Hub module.
> > > + *  @inode: Contains the reference of the inode structure
> > > + *  @file: Contains the reference of the file structure
> > > + *  @cmd: Contains the command value
> > > + *  @arg: Contains the command argument value
> > > + */
> > > +
> > > +
> > > +static long pch_phub_ioctl(struct file *file, unsigned int cmd,
> > > + unsigned long arg)
> > > +{
> > > + __s32 ret_value = 0;
> > > + struct pch_phub_reqt __user *p_pch_phub_reqt;
> > > + __u32 data;
> > > + __u32 mac_addr[2];
> > > + __s32 ret;
> > > + __u32 i;
> > > + void __user *varg = (void __user *)arg;
> > > +
> > > + ret = mutex_trylock(&pch_phub_ioctl_mutex);
> > > + if (ret == 0)
> > > + goto return_ioctrl;/*Can't get mutex lock*/
> >
> > mutex_trylock is probably not what you want, it returns immediately
> > when there is another function in the kernel.
> > mutex_lock_interruptible seems more appropriate, it will block
> > until the mutex is free or the process gets sent a signal,
> > which you should handle by returning -ERESTARTSYS.
> >
> > In either case, you must not jump to return_ioctrl here, because
> > that will try to release the mutex that you do not hold here,
> > causing a hang the next time you enter the function.
> >
> > > + if (pch_phub_reg.pch_phub_suspended == true) {
> > > + ret_value = -EPERM;
> > > + goto return_ioctrl;
> > > + }
> > > +
> > > + p_pch_phub_reqt = (struct pch_phub_reqt *)varg;
> > > +
> > > + if (ret_value)
> > > + goto return_ioctrl;
> >
> > is always zero here.
> >
> > > + /* End of Access area check */
> > > +
> > > +
> > > + switch (cmd) {
> > > +
> > > + case IOCTL_PHUB_READ_MAC_ADDR:
> > > + mac_addr[0] = 0;
> > > + mac_addr[1] = 0;
> > > + for (i = 0; i < 4; i++) {
> > > + pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
> > > + mac_addr[0] |= data << i*8;
> > > + }
> > > + for (; i < 6; i++) {
> > > + pch_phub_read_gbe_mac_addr(i, (__u8 *)&data);
> > > + mac_addr[1] |= data << (i-4)*8;
> > > + }
> > > +
> > > + ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
> > > + (void *)mac_addr, sizeof(mac_addr));
> >
> > p_pch_phub_reqt->data has multiple problems:
> >
> > - You have the typecast to (void *), which is wrong and unneeded.
> > - The data structure has no point at all any more when you use only one
> >   field.
> >
> > Just make this
> >
> > u8 mac_addr[6];
> > for (i = 0; i < 4; i++)
> > pch_phub_read_gbe_mac_addr(i, &mac_addr[i]);
> > ret_value = copy_to_user(varg, mac_addr, sizeof(mac_addr));
> >
> > > +#define PHUB_IOCTL_MAGIC (0xf7)
> > > +
> > > +/*Outlines the read register function signature.  */
> > > +#define IOCTL_PHUB_READ_REG (_IOW(PHUB_IOCTL_MAGIC, 1, __u32))
> > > +
> > > +/*Outlines the write register function signature. */
> > > +#define IOCTL_PHUB_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 2, __u32))
> > > +
> > > +/*Outlines the read, modify and write register function signature. */
> > > +#define IOCTL_PHUB_READ_MODIFY_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 3,\
> > > + __u32))
> > > +
> > > +/*Outlines the read option rom function signature. */
> > > +#define IOCTL_PHUB_READ_OROM (_IOW(PHUB_IOCTL_MAGIC, 4, __u32))
> > > +
> > > +/*Outlines the write option rom function signature. */
> > > +#define IOCTL_PHUB_WRITE_OROM (_IOW(PHUB_IOCTL_MAGIC, 5, __u32))
> >
> > These should all get removed now.
> >
> > > +/*Outlines the read mac address function signature. */
> > > +#define IOCTL_PHUB_READ_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 6, __u32))
> > > +
> > > +/*brief Outlines the write mac address function signature. */
> > > +#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u32))
> >
> > IOCTL_PHUB_READ_MAC_ADDR needs _IOR instead of _IOW, and the type
> > is still wrong here. Your code currently has struct pch_phub_reqt
> > instead of __u32, and if you change the ioctl function as I explained
> > above, it should become
> >
> > #define IOCTL_PHUB_READ_MAC_ADDR (_IOR(PHUB_IOCTL_MAGIC, 6, __u8[6]))
> > #define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, __u8[6]))
> >
> > Arnd
> >
>
>



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

* RE: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-08  8:48   ` Masayuki Ohtake
  2010-06-08  9:29     ` Arnd Bergmann
@ 2010-06-09  0:14     ` Wang, Qi
  1 sibling, 0 replies; 45+ messages in thread
From: Wang, Qi @ 2010-06-09  0:14 UTC (permalink / raw)
  To: Masayuki Ohtake
  Cc: LKML, Khor, Andrew Chih Howe, Clark, Joel, Wang, Yong Y, Arnd Bergmann

Ohtake-san,

Let me explain what Arnd means.

Writing the all the registers with ioctl is discouraged. For this case, what you need is writing/updating or reading some registers, not all the registers of Topcliff. It's better that you implement as the following example.

For example, you want to update MAC register with 'aaaa'.
It's not a better way to pass the register of mac address and aaaa via the ioctl routine. It's better only pass the aaaa with the 'update mac address command' (update aaaa to mac register). Actually it's discouraged to pass the address information with ioctl routine, because it'll bring the security issue even if you check the address-range.

It's better to pass the command and relative argument to implement something, not 'the address', 'read/write register command' and 'the value to read/write'.

Any question, please let me know.

Best Regards,
Qi.

-----Original Message-----
From: Masayuki Ohtake [mailto:masa-korg@dsn.okisemi.com] 
Sent: Tuesday, June 08, 2010 4:49 PM
To: Arnd Bergmann
Cc: LKML; Khor, Andrew Chih Howe; Clark, Joel; Wang, Qi; Wang, Yong Y
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver

Hi Arnd

We are studying your indication.
> My feeling is that this ioctl interface is too
> low-level in general. You only export access to specific
> registers, not to functionality exposed by them.
> The best kernel interfaces are defined in a way that
> is independent of the underlying hardware and
> convert generic commands into device specific commands.

I have a question.
We don't know 'generic commands' concretely.
Let me know 'generic commands' in detail.

Thanks. Ohtake.

----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "LKML" <linux-kernel@vger.kernel.org>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Intel OTC"
<joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y" <yong.y.wang@intel.com>
Sent: Monday, June 07, 2010 10:37 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Friday 04 June 2010, Masayuki Ohtake wrote:
> > From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> >
> > This patch adds the Packet Hub driver for Topcliff.
> > Patch created against 2.6.33.1
> >
> > Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
>
> Most of the comments from my first review still apply to
> this version, please have another look at what I wrote
> back in april, see http://article.gmane.org/gmane.linux.network/158879
>
> Note also that patch submissions should be against the latest
> development kernel, in this case 2.6.35-rc2, not against stable
> kernel releases like 2.6.33.1.
>
> Arnd
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-08  8:48   ` Masayuki Ohtake
@ 2010-06-08  9:29     ` Arnd Bergmann
  2010-06-09  0:14     ` Wang, Qi
  1 sibling, 0 replies; 45+ messages in thread
From: Arnd Bergmann @ 2010-06-08  9:29 UTC (permalink / raw)
  To: Masayuki Ohtake; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

On Tuesday 08 June 2010, Masayuki Ohtake wrote:
> We are studying your indication.
> > My feeling is that this ioctl interface is too
> > low-level in general. You only export access to specific
> > registers, not to functionality exposed by them.
> > The best kernel interfaces are defined in a way that
> > is independent of the underlying hardware and
> > convert generic commands into device specific commands.
> 
> I have a question.
> We don't know 'generic commands' concretely.
> Let me know 'generic commands' in detail.

I have not seen the application using the driver, but
a better abstraction IMHO would be to take an abstraction
you have in your application and move it into the kernel.

I can be more specific if you tell me where to find the
source of the application. Generally speaking, you'd
transform a function like

/* the function that knows how to do 'this' */
int phub_do_this(int phub_fd, unsigned long arg)
{
	struct pch_phub_req req = {
		.addr_offset = SOME_ADDR_OFF,
	};
	ioctl(fd, IOCTL_PHUB_READ_REG, &req);

	if (req.data & SOME_BITS)
		return ERROR;

	req.addr_offset = ANOTHER_ADDR_OFF;
	req.data = arg | REALLY_DO_IT_BITMASK;

	ioctl(fd, IOCTL_PHUB_WRITE_REG, &req);

	return 0;
}

into another function that does the same thing but
without knowing anything about the registers:

/* the same function on the abstract interface */
int phub_do_this_new(int phub_fd, unsigned long arg)
{
	return ioctl(phub_fd, IOCTL_PHUB_DO_THIS, &arg);
}

	Arnd

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-07 13:37 ` Arnd Bergmann
  2010-06-08  0:15   ` Masayuki Ohtake
@ 2010-06-08  8:48   ` Masayuki Ohtake
  2010-06-08  9:29     ` Arnd Bergmann
  2010-06-09  0:14     ` Wang, Qi
  1 sibling, 2 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-08  8:48 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Arnd

We are studying your indication.
> My feeling is that this ioctl interface is too
> low-level in general. You only export access to specific
> registers, not to functionality exposed by them.
> The best kernel interfaces are defined in a way that
> is independent of the underlying hardware and
> convert generic commands into device specific commands.

I have a question.
We don't know 'generic commands' concretely.
Let me know 'generic commands' in detail.

Thanks. Ohtake.

----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "LKML" <linux-kernel@vger.kernel.org>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Intel OTC"
<joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y" <yong.y.wang@intel.com>
Sent: Monday, June 07, 2010 10:37 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Friday 04 June 2010, Masayuki Ohtake wrote:
> > From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> >
> > This patch adds the Packet Hub driver for Topcliff.
> > Patch created against 2.6.33.1
> >
> > Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
>
> Most of the comments from my first review still apply to
> this version, please have another look at what I wrote
> back in april, see http://article.gmane.org/gmane.linux.network/158879
>
> Note also that patch submissions should be against the latest
> development kernel, in this case 2.6.35-rc2, not against stable
> kernel releases like 2.6.33.1.
>
> Arnd
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-08  7:20 ` Yong Wang
@ 2010-06-08  8:09   ` Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-08  8:09 UTC (permalink / raw)
  To: Yong Wang; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Yong Wang

Thank you for your comment.

> Why is 50MHz so special, btw?
This code is work around for previous HW bug.
(CAN worked only 50MHz with previous HW)

Since the HW bug has been already fixed for the latest HW,
this code is unnecessary for the latest HW.

> Note that 'a' is supposed to be surrounded by brackets, too.
>
> #define PCH_WRITE_REG(a, b) iowrite32((a), pcb_phub_base_address + (b))
Thank you for your indication. We have updated.

Best Regards,
----- Original Message ----- 
From: "Yong Wang" <yong.y.wang@linux.intel.com>
To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
Cc: "Alan Cox" <alan@lxorguk.ukuu.org.uk>; "LKML" <linux-kernel@vger.kernel.org>; "Andrew"
<andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y"
<yong.y.wang@intel.com>
Sent: Tuesday, June 08, 2010 4:20 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Tue, Jun 08, 2010 at 02:00:55PM +0900, Masayuki Ohtak wrote:
> > Hi Alan
> >
> > We are now updating our Phub driver.
> >
> > I have a questions for your comment.
> >
> > (1)
> > >> +#ifdef PCH_CAN_PCLK_50MHZ
> > >> + /* save clk cfg register */
> > >> + g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
> > >> +#endif
> > >
> > > This makes it hard to build one kernel for everything
> > We couldn't understand your intention.
> > Does the above mean we must not use "#ifdef PCH_CAN_PCLK_50MHZ" in source code ?
> >
>
> I think what Alan means is that you will have to build two kernel images
> for two possible configurations of how your hardware is going to be used
> if you write code this way. One is the case when CAN clock runs at 50MHz
> and you will build a kernel image with PCH_CAN_PCLK_50MHZ defined. The
> other is when CAN clock runs at other speed and you need to build
> another kernel image with PCH_CAN_PCLK_50MHZ undefined. It would be much
> better if one kernel image could run on all configurations.
>
> Why is 50MHz so special, btw? Don't you need to save and restore the
> clock config register when CAN clock runs at other speed?
>
> >
> > >> +#define PCH_READ_REG(a) ioread32((pch_phub_base_address + a))
> >
> > >> +
> >
> > >> +#define PCH_WRITE_REG(a, b) iowrite32(a, (pch_phub_base_address + b))
> >
> > >
> >
> > > These on the other hand do - but not where they are now
> >
> > >
> >
> > > iowrite32((a), pcb_phub_base_address + (b))
> >
> > >
> >
> > > (so that if a or b are expressions they are evaluated first)
> >
> > Modify like below.
> >
> > #define PCH_READ_REG(a) ioread32(pch_phub_base_address + (a))
> >
> > #define PCH_WRITE_REG(a, b) iowrite32(a, pch_phub_base_address + (b))
> >
>
> Note that 'a' is supposed to be surrounded by brackets, too.
>
> #define PCH_WRITE_REG(a, b) iowrite32((a), pcb_phub_base_address + (b))
>
> Thanks
> -Yong
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-08  5:00 Masayuki Ohtak
  2010-06-08  5:46 ` Masayuki Ohtake
  2010-06-08  7:20 ` Yong Wang
@ 2010-06-08  8:04 ` Alan Cox
  2 siblings, 0 replies; 45+ messages in thread
From: Alan Cox @ 2010-06-08  8:04 UTC (permalink / raw)
  To: Masayuki Ohtak; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

> > This makes it hard to build one kernel for everything
> We couldn't understand your intention.
> Does the above mean we must not use "#ifdef PCH_CAN_PCLK_50MHZ"	in source code ?

The problem for people building kernels is this

- They want to have a single kernel for all the boxes of a single
  architecture
- They cannot do this if there are compile time settings that only work
  on some boards


Ideally this should be done automatically. If not then can it be a module
parameter instead ?

Alan

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-08  5:46 ` Masayuki Ohtake
@ 2010-06-08  8:01   ` Alan Cox
  0 siblings, 0 replies; 45+ messages in thread
From: Alan Cox @ 2010-06-08  8:01 UTC (permalink / raw)
  To: Masayuki Ohtake; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

On Tue, 8 Jun 2010 14:46:31 +0900
"Masayuki Ohtake" <masa-korg@dsn.okisemi.com> wrote:

> Hi Alan
> 
> > > Remember here ioctl isn't single threaded so you may want to double check
> >
> > > some of these
> >
> > The above copy_from_user is Copy global variable to local variable.
> > Thus, We think this code has re-entrant.
> The above is not true.
> Our ioctl routine is just used under single pthread.

What if someone else chooses to open it and run multiple threads through
it. What if the code changes. What about malicious attempts to confuse
the driver ?

The fact your own current userspace does not do this does not mean it can
be ignored.

Alan

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-08  5:00 Masayuki Ohtak
  2010-06-08  5:46 ` Masayuki Ohtake
@ 2010-06-08  7:20 ` Yong Wang
  2010-06-08  8:09   ` Masayuki Ohtake
  2010-06-08  8:04 ` Alan Cox
  2 siblings, 1 reply; 45+ messages in thread
From: Yong Wang @ 2010-06-08  7:20 UTC (permalink / raw)
  To: Masayuki Ohtak; +Cc: Alan Cox, LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

On Tue, Jun 08, 2010 at 02:00:55PM +0900, Masayuki Ohtak wrote:
> Hi Alan
> 
> We are now updating our Phub driver.
> 
> I have a questions for your comment.
> 
> (1)
> >> +#ifdef PCH_CAN_PCLK_50MHZ
> >> + /* save clk cfg register */
> >> + g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
> >> +#endif
> > 
> > This makes it hard to build one kernel for everything
> We couldn't understand your intention.
> Does the above mean we must not use "#ifdef PCH_CAN_PCLK_50MHZ"	in source code ?
> 

I think what Alan means is that you will have to build two kernel images
for two possible configurations of how your hardware is going to be used
if you write code this way. One is the case when CAN clock runs at 50MHz
and you will build a kernel image with PCH_CAN_PCLK_50MHZ defined. The
other is when CAN clock runs at other speed and you need to build
another kernel image with PCH_CAN_PCLK_50MHZ undefined. It would be much
better if one kernel image could run on all configurations.

Why is 50MHz so special, btw? Don't you need to save and restore the
clock config register when CAN clock runs at other speed?

> 
> >> +#define PCH_READ_REG(a) ioread32((pch_phub_base_address + a))
> 
> >> +
> 
> >> +#define PCH_WRITE_REG(a, b) iowrite32(a, (pch_phub_base_address + b))
> 
> > 
> 
> > These on the other hand do - but not where they are now
> 
> > 
> 
> > iowrite32((a), pcb_phub_base_address + (b))
> 
> > 
> 
> > (so that if a or b are expressions they are evaluated first)
> 
> Modify like below.
> 
> #define PCH_READ_REG(a) ioread32(pch_phub_base_address + (a))
> 
> #define PCH_WRITE_REG(a, b) iowrite32(a, pch_phub_base_address + (b))
> 

Note that 'a' is supposed to be surrounded by brackets, too.

#define PCH_WRITE_REG(a, b)	iowrite32((a), pcb_phub_base_address + (b))

Thanks
-Yong


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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-08  5:00 Masayuki Ohtak
@ 2010-06-08  5:46 ` Masayuki Ohtake
  2010-06-08  8:01   ` Alan Cox
  2010-06-08  7:20 ` Yong Wang
  2010-06-08  8:04 ` Alan Cox
  2 siblings, 1 reply; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-08  5:46 UTC (permalink / raw)
  To: Masayuki Ohtak, Alan Cox; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Alan

> > Remember here ioctl isn't single threaded so you may want to double check
>
> > some of these
>
> The above copy_from_user is Copy global variable to local variable.
> Thus, We think this code has re-entrant.
The above is not true.
Our ioctl routine is just used under single pthread.

> Hi Andrew
Sorry, I have not checked my email.

Thanks,

----- Original Message ----- 
From: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
To: "Alan Cox" <alan@lxorguk.ukuu.org.uk>
Cc: "LKML" <linux-kernel@vger.kernel.org>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Intel OTC"
<joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y" <yong.y.wang@intel.com>; "Masayuki Ohtak"
<masa-korg@dsn.okisemi.com>
Sent: Tuesday, June 08, 2010 2:00 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> Hi Alan
>
> We are now updating our Phub driver.
>
> I have a questions for your comment.
>
> (1)
> >> +#ifdef PCH_CAN_PCLK_50MHZ
> >> + /* save clk cfg register */
> >> + g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
> >> +#endif
> >
> > This makes it hard to build one kernel for everything
> We couldn't understand your intention.
> Does the above mean we must not use "#ifdef PCH_CAN_PCLK_50MHZ" in source code ?
>
>
> BTW, We show our modification policy the following email with inline.
> Please confirm it.
> If there is any mistake, please inform us.
>
>
> Thanks.
>
> Ohtake.
>
>
> ----- Original Message ----- 
>
> From: "Alan Cox" <alan@lxorguk.ukuu.org.uk>
>
> To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>
>
> Cc: "LKML" <linux-kernel@vger.kernel.org>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Intel OTC"
<joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y" <yong.y.wang@intel.com>
>
> Sent: Tuesday, June 08, 2010 12:05 AM
>
> Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
>
>
>
>
>
> >O> +/* Status Register offset */
>
> >> +#define PHUB_STATUS (0x00)
>
> >> +/* Control Register offset */
>
> >> +#define PHUB_CONTROL (0x04)
>
> >> +/* Time out value for Status Register */
>
> >> +#define PHUB_TIMEOUT (0x05)
>
> >> +/* Enabling for writing ROM */
>
> >> +#define PCH_PHUB_ROM_WRITE_ENABLE (0x01)
>
> >> +/* Disabling for writing ROM */
>
> >> +#define PCH_PHUB_ROM_WRITE_DISABLE (0x00)
>
> >> +/* ROM data area start address offset */
>
> >> +#define PCH_PHUB_ROM_START_ADDR (0x14)
>
> >> +/* MAX number of INT_REDUCE_CONTROL registers */
>
> >> +#define MAX_NUM_INT_REDUCE_CONTROL_REG (128)
>
> >> +
>
> >> +#define PCI_DEVICE_ID_PCH1_PHUB (0x8801)
>
> >> +
>
> >> +#define PCH_MINOR_NOS (1)
>
> >> +#define CLKCFG_CAN_50MHZ (0x12000000)
>
> >> +#define CLKCFG_CANCLK_MASK (0xFF000000)
>
> >
>
> > Style: constants don't need brackets - might also look more Linux like
>
> > tabbed out a bit
>
> The above brackets are deleted
>
>
>
> >
>
> >> +#define PCH_READ_REG(a) ioread32((pch_phub_base_address + a))
>
> >> +
>
> >> +#define PCH_WRITE_REG(a, b) iowrite32(a, (pch_phub_base_address + b))
>
> >
>
> > These on the other hand do - but not where they are now
>
> >
>
> > iowrite32((a), pcb_phub_base_address + (b))
>
> >
>
> > (so that if a or b are expressions they are evaluated first)
>
> Modify like below.
>
> #define PCH_READ_REG(a) ioread32(pch_phub_base_address + (a))
>
> #define PCH_WRITE_REG(a, b) iowrite32(a, pch_phub_base_address + (b))
>
>
>
> >
>
> >
>
> >> +struct pch_phub_reg {
>
> >> + u32 phub_id_reg; /* PHUB_ID register val */
>
> >> + u32 q_pri_val_reg; /* QUEUE_PRI_VAL register val */
>
> >> + u32 rc_q_maxsize_reg; /* RC_QUEUE_MAXSIZE register val */
>
> >> + u32 bri_q_maxsize_reg; /* BRI_QUEUE_MAXSIZE register val */
>
> >> + u32 comp_resp_timeout_reg; /* COMP_RESP_TIMEOUT register val */
>
> >> + u32 bus_slave_control_reg; /* BUS_SLAVE_CONTROL_REG register val */
>
> >> + u32 deadlock_avoid_type_reg; /* DEADLOCK_AVOID_TYPE register val */
>
> >> + u32 intpin_reg_wpermit_reg0; /* INTPIN_REG_WPERMIT register 0 val */
>
> >> + u32 intpin_reg_wpermit_reg1; /* INTPIN_REG_WPERMIT register 1 val */
>
> >> + u32 intpin_reg_wpermit_reg2; /* INTPIN_REG_WPERMIT register 2 val */
>
> >> + u32 intpin_reg_wpermit_reg3; /* INTPIN_REG_WPERMIT register 3 val */
>
> >> + /* INT_REDUCE_CONTROL registers val */
>
> >> + u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
>
> >> +#ifdef PCH_CAN_PCLK_50MHZ
>
> >> + u32 clkcfg_reg; /* CLK CFG register val */
>
> >> +#endif
>
> >> +} g_pch_phub_reg;
>
> >
>
> > Stylewise the kernel doesn't use the g_ convention that many Windows
>
> > people do, so lose the g_
>
> Delete prefix 'g_'.
>
>
>
>
>
> >
>
> >> +s32 pch_phub_opencount; /* check whether opened or not */
>
> >> +u32 pch_phub_base_address;
>
> >> +u32 pch_phub_extrom_base_address;
>
> >> +s32 pch_phub_suspended;
>
> >
>
> > Any reason these can't be in the struct ?
>
> Move the above 4 variables into 'struct pch_phub_reg_t'.
>
>
>
> >> +
>
> >> +struct device *dev_dbg;
>
> >
>
> > Not a good name for a global variable as it will clash with others
>
> Modify to phub_dev_dbg.
>
>
>
> >
>
> >> +DEFINE_SPINLOCK(pch_phub_lock); /* for spin lock */
>
> >
>
> > Can this be static or in the struct ?
>
> Modify lile below.
>
> static DEFINE_SPINLOCK(pch_phub_lock); /* for spin lock */
>
>
>
>
>
> >
>
> >> +
>
> >> +/**
>
> >> + * file_operations structure initialization
>
> >> + */
>
> >> +const struct file_operations pch_phub_fops = {
>
> >> + .owner = THIS_MODULE,
>
> >> + .open = pch_phub_open,
>
> >> + .release = pch_phub_release,
>
> >> + .ioctl = pch_phub_ioctl,
>
> >> +};
>
> >
>
> > static const ?
>
> >
>
> Modify to 'static const'.
>
>
>
>
>
> >> +/*--------------------------------------------
>
> >> + exported function prototypes
>
> >> +--------------------------------------------*/
>
> >
>
> > They start 'static' I don't think they are exportdd !
>
> Modify comment to 'Internal function prototypes'
>
>
>
> >
>
> >> +static int __devinit pch_phub_probe(struct pci_dev *pdev, const
>
> >> +        struct pci_device_id *id);
>
> >> +static void __devexit pch_phub_remove(struct pci_dev *pdev);
>
> >> +static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
>
> >> +static int pch_phub_resume(struct pci_dev *pdev);
>
> >
>
> >> +static struct pci_driver pch_phub_driver = {
>
> >> + .name = "pch_phub",
>
> >> + .id_table = pch_phub_pcidev_id,
>
> >> + .probe = pch_phub_probe,
>
> >> + .remove = __devexit_p(pch_phub_remove),
>
> >> +#ifdef CONFIG_PM
>
> >> + .suspend = pch_phub_suspend,
>
> >> + .resume = pch_phub_resume
>
> >> +#endif
>
> >> +};
>
> >> +
>
> >> +static int __init pch_phub_pci_init(void);
>
> >> +static void __exit pch_phub_pci_exit(void);
>
> >> +
>
> >> +MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
>
> >> +MODULE_LICENSE("GPL");
>
> >> +module_init(pch_phub_pci_init);
>
> >> +module_exit(pch_phub_pci_exit);
>
> >> +module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);
>
> >
>
> > If you migrated the module registration/PCI registration to the bottom of
>
> > the file you could avoid the forward declations and make the code easier
>
> > to follow ?
>
> Move the PCI registration code to the bottom of the file.
>
>
>
> >
>
> >> +void pch_phub_read_modify_write_reg(unsigned long reg_addr_offset,
>
> >> +        unsigned long data, unsigned long mask)
>
> >> +{
>
> >> + unsigned long reg_addr = pch_phub_base_address + reg_addr_offset;
>
> >> + iowrite32(((ioread32((void __iomem *)reg_addr) & ~mask)) | data,
>
> >> + (void __iomem *)reg_addr);
>
> >
>
> > When you have that many casts in a line it's perhaps a hint you have the
>
> > types wrong initially. At the very least reg_addr should be void __iomem,
>
> > and probably pch_phub_base_address should be
>
> >
>
> > It would probably make sense to pass a pointer to your struct pch_hub_reg
>
> > and use that to hold the base address. Then if you ever get a box with
>
> > two in some future design it won't be a disaster
>
> >
>
> >> +void pch_phub_save_reg_conf(void)
>
> >
>
> > Ditto
>
>  reg_addr/pch_phub_base_address  are defined as 'void __iomem',
>
>
>
> >
>
> >> +#ifdef PCH_CAN_PCLK_50MHZ
>
> >> + /* save clk cfg register */
>
> >> + g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
>
> >> +#endif
>
> >
>
> > This makes it hard to build one kernel for everything
>
> ???
>
>
>
> >
>
> >> + return;
>
> >> +}
>
> >
>
> >> +void pch_phub_restore_reg_conf(void)
>
> >> +{
>
> >> + u32 i = 0;
>
> >
>
> > Why = 0, if you do that here you may hide initialisation errors from
>
> > future changes ?
>
> Delete '=0'
>
>
>
>
>
> >
>
> >> +/** pch_phub_read_serial_rom - Implements the functionality of reading Serial
>
> >> + *  ROM.
>
> >> + *  @offset_address: Contains the Serial ROM address offset value
>
> >> + *  @data: Contains the Serial ROM value
>
> >> + */
>
> >> +int pch_phub_read_serial_rom(unsigned long offset_address, unsigned char *data)
>
> >> +{
>
> >> + unsigned long mem_addr = pch_phub_extrom_base_address + offset_address;
>
> >> +
>
> >> + dev_dbg(dev_dbg,
>
> >> + "pch_phub_read_serial_rom:mem_addr=0x%08x\n", (u32)mem_addr);
>
> >> + *data = ioread8((void __iomem *)mem_addr);
>
> >
>
> > Same comments about casts
>
> Please refer the above.(defined as 'void __iomem',)
>
>
>
> >
>
> >
>
> >
>
> >> +int pch_phub_ioctl(struct inode *inode, struct file *file,
>
> >> + unsigned int cmd, unsigned long arg)
>
> >> +{
>
> >> + int ret_value = 0;
>
> >> + struct pch_phub_reqt *p_pch_phub_reqt;
>
> >> + unsigned long addr_offset;
>
> >
>
> > This will change size on 32/64bit boxes makign your copy a bit
>
> > problematic
>
> Modify like belwo,
>
> u64 addr_offset;
>
>
>
>
>
> >
>
> >> + p_pch_phub_reqt = (struct pch_phub_reqt *)arg;
>
> >> + ret_value = copy_from_user((void *)&addr_offset,
>
> >> + (void *)&p_pch_phub_reqt->addr_offset,
>
> >> + sizeof(addr_offset));
>
> >> + if (ret_value) {
>
> >
>
> >> + /* End of Access area check */
>
> >
>
> > Remember here ioctl isn't single threaded so you may want to double check
>
> > some of these
>
> The above copy_from_user is Copy global variable to local variable.
> Thus, We think this code has re-entrant.
>
>
> >
>
> >> +struct pch_phub_reqt {
>
> >> + unsigned long addr_offset; /*specifies the register address
>
> >> + offset */
>
> >> + unsigned long data; /*specifies the data */
>
> >> + unsigned long mask; /*specifies the mask */
>
> >
>
> > If they may need to be long make them u64. That way 32 and 64bit systems
>
> > get the same ioctl structure and life is good.
>
> Modify type of addr_offset to u64
>
>
>
> >
>
> >> +};
>
> >> +
>
> >> +/* exported function prototypes */
>
> >> +int pch_phub_open(struct inode *inode, struct file *file);
>
> >> +int pch_phub_release(struct inode *inode, struct file *file);
>
> >> +int pch_phub_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
>
> >> +       unsigned long arg);
>
> >
>
> > You have various other functions that are not static - if they should be
>
> > then make them static
>
> Add static description for all of internal functions.
>
>
>
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
@ 2010-06-08  5:00 Masayuki Ohtak
  2010-06-08  5:46 ` Masayuki Ohtake
                   ` (2 more replies)
  0 siblings, 3 replies; 45+ messages in thread
From: Masayuki Ohtak @ 2010-06-08  5:00 UTC (permalink / raw)
  To: Alan Cox; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y, Masayuki Ohtak

Hi Alan

We are now updating our Phub driver.

I have a questions for your comment.

(1)
>> +#ifdef PCH_CAN_PCLK_50MHZ
>> + /* save clk cfg register */
>> + g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
>> +#endif
> 
> This makes it hard to build one kernel for everything
We couldn't understand your intention.
Does the above mean we must not use "#ifdef PCH_CAN_PCLK_50MHZ"	in source code ?


BTW, We show our modification policy the following email with inline.
Please confirm it.
If there is any mistake, please inform us.


Thanks.  

Ohtake.


----- Original Message ----- 

From: "Alan Cox" <alan@lxorguk.ukuu.org.uk>

To: "Masayuki Ohtak" <masa-korg@dsn.okisemi.com>

Cc: "LKML" <linux-kernel@vger.kernel.org>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Intel OTC" <joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y" <yong.y.wang@intel.com>

Sent: Tuesday, June 08, 2010 12:05 AM

Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver





>O> +/* Status Register offset */

>> +#define PHUB_STATUS (0x00)

>> +/* Control Register offset */

>> +#define PHUB_CONTROL (0x04)

>> +/* Time out value for Status Register */

>> +#define PHUB_TIMEOUT (0x05)

>> +/* Enabling for writing ROM */

>> +#define PCH_PHUB_ROM_WRITE_ENABLE (0x01)

>> +/* Disabling for writing ROM */

>> +#define PCH_PHUB_ROM_WRITE_DISABLE (0x00)

>> +/* ROM data area start address offset */

>> +#define PCH_PHUB_ROM_START_ADDR (0x14)

>> +/* MAX number of INT_REDUCE_CONTROL registers */

>> +#define MAX_NUM_INT_REDUCE_CONTROL_REG (128)

>> +

>> +#define PCI_DEVICE_ID_PCH1_PHUB (0x8801)

>> +

>> +#define PCH_MINOR_NOS (1)

>> +#define CLKCFG_CAN_50MHZ (0x12000000)

>> +#define CLKCFG_CANCLK_MASK (0xFF000000)

> 

> Style: constants don't need brackets - might also look more Linux like

> tabbed out a bit

The above brackets are deleted



> 

>> +#define PCH_READ_REG(a) ioread32((pch_phub_base_address + a))

>> +

>> +#define PCH_WRITE_REG(a, b) iowrite32(a, (pch_phub_base_address + b))

> 

> These on the other hand do - but not where they are now

> 

> iowrite32((a), pcb_phub_base_address + (b))

> 

> (so that if a or b are expressions they are evaluated first)

Modify like below.

#define PCH_READ_REG(a) ioread32(pch_phub_base_address + (a))

#define PCH_WRITE_REG(a, b) iowrite32(a, pch_phub_base_address + (b))



> 

> 

>> +struct pch_phub_reg {

>> + u32 phub_id_reg; /* PHUB_ID register val */

>> + u32 q_pri_val_reg; /* QUEUE_PRI_VAL register val */

>> + u32 rc_q_maxsize_reg; /* RC_QUEUE_MAXSIZE register val */

>> + u32 bri_q_maxsize_reg; /* BRI_QUEUE_MAXSIZE register val */

>> + u32 comp_resp_timeout_reg; /* COMP_RESP_TIMEOUT register val */

>> + u32 bus_slave_control_reg; /* BUS_SLAVE_CONTROL_REG register val */

>> + u32 deadlock_avoid_type_reg; /* DEADLOCK_AVOID_TYPE register val */

>> + u32 intpin_reg_wpermit_reg0; /* INTPIN_REG_WPERMIT register 0 val */

>> + u32 intpin_reg_wpermit_reg1; /* INTPIN_REG_WPERMIT register 1 val */

>> + u32 intpin_reg_wpermit_reg2; /* INTPIN_REG_WPERMIT register 2 val */

>> + u32 intpin_reg_wpermit_reg3; /* INTPIN_REG_WPERMIT register 3 val */

>> + /* INT_REDUCE_CONTROL registers val */

>> + u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];

>> +#ifdef PCH_CAN_PCLK_50MHZ

>> + u32 clkcfg_reg; /* CLK CFG register val */

>> +#endif

>> +} g_pch_phub_reg;

> 

> Stylewise the kernel doesn't use the g_ convention that many Windows

> people do, so lose the g_

Delete prefix 'g_'.





> 

>> +s32 pch_phub_opencount; /* check whether opened or not */

>> +u32 pch_phub_base_address;

>> +u32 pch_phub_extrom_base_address;

>> +s32 pch_phub_suspended;

> 

> Any reason these can't be in the struct ?

Move the above 4 variables into 'struct pch_phub_reg_t'.



>> +

>> +struct device *dev_dbg;

> 

> Not a good name for a global variable as it will clash with others 

Modify to phub_dev_dbg.



> 

>> +DEFINE_SPINLOCK(pch_phub_lock); /* for spin lock */

> 

> Can this be static or in the struct ?

Modify lile below.

static DEFINE_SPINLOCK(pch_phub_lock); /* for spin lock */





> 

>> +

>> +/**

>> + * file_operations structure initialization

>> + */

>> +const struct file_operations pch_phub_fops = {

>> + .owner = THIS_MODULE,

>> + .open = pch_phub_open,

>> + .release = pch_phub_release,

>> + .ioctl = pch_phub_ioctl,

>> +};

> 

> static const ?

> 

Modify to 'static const'.





>> +/*--------------------------------------------

>> + exported function prototypes

>> +--------------------------------------------*/

> 

> They start 'static' I don't think they are exportdd !

Modify comment to 'Internal function prototypes'



> 

>> +static int __devinit pch_phub_probe(struct pci_dev *pdev, const

>> +        struct pci_device_id *id);

>> +static void __devexit pch_phub_remove(struct pci_dev *pdev);

>> +static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);

>> +static int pch_phub_resume(struct pci_dev *pdev);

> 

>> +static struct pci_driver pch_phub_driver = {

>> + .name = "pch_phub",

>> + .id_table = pch_phub_pcidev_id,

>> + .probe = pch_phub_probe,

>> + .remove = __devexit_p(pch_phub_remove),

>> +#ifdef CONFIG_PM

>> + .suspend = pch_phub_suspend,

>> + .resume = pch_phub_resume

>> +#endif

>> +};

>> +

>> +static int __init pch_phub_pci_init(void);

>> +static void __exit pch_phub_pci_exit(void);

>> +

>> +MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");

>> +MODULE_LICENSE("GPL");

>> +module_init(pch_phub_pci_init);

>> +module_exit(pch_phub_pci_exit);

>> +module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);

> 

> If you migrated the module registration/PCI registration to the bottom of

> the file you could avoid the forward declations and make the code easier

> to follow ?

Move the PCI registration code to the bottom of the file.



> 

>> +void pch_phub_read_modify_write_reg(unsigned long reg_addr_offset,

>> +        unsigned long data, unsigned long mask)

>> +{

>> + unsigned long reg_addr = pch_phub_base_address + reg_addr_offset;

>> + iowrite32(((ioread32((void __iomem *)reg_addr) & ~mask)) | data,

>> + (void __iomem *)reg_addr);

> 

> When you have that many casts in a line it's perhaps a hint you have the

> types wrong initially. At the very least reg_addr should be void __iomem,

> and probably pch_phub_base_address should be 

> 

> It would probably make sense to pass a pointer to your struct pch_hub_reg

> and use that to hold the base address. Then if you ever get a box with

> two in some future design it won't be a disaster

> 

>> +void pch_phub_save_reg_conf(void)

> 

> Ditto 

 reg_addr/pch_phub_base_address  are defined as 'void __iomem',



> 

>> +#ifdef PCH_CAN_PCLK_50MHZ

>> + /* save clk cfg register */

>> + g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);

>> +#endif

> 

> This makes it hard to build one kernel for everything

???



> 

>> + return;

>> +}

> 

>> +void pch_phub_restore_reg_conf(void)

>> +{

>> + u32 i = 0;

> 

> Why = 0, if you do that here you may hide initialisation errors from

> future changes ?

Delete '=0'





> 

>> +/** pch_phub_read_serial_rom - Implements the functionality of reading Serial

>> + *  ROM.

>> + *  @offset_address: Contains the Serial ROM address offset value

>> + *  @data: Contains the Serial ROM value

>> + */

>> +int pch_phub_read_serial_rom(unsigned long offset_address, unsigned char *data)

>> +{

>> + unsigned long mem_addr = pch_phub_extrom_base_address + offset_address;

>> +

>> + dev_dbg(dev_dbg,

>> + "pch_phub_read_serial_rom:mem_addr=0x%08x\n", (u32)mem_addr);

>> + *data = ioread8((void __iomem *)mem_addr);

> 

> Same comments about casts

Please refer the above.(defined as 'void __iomem',)



> 

> 

> 

>> +int pch_phub_ioctl(struct inode *inode, struct file *file,

>> + unsigned int cmd, unsigned long arg)

>> +{

>> + int ret_value = 0;

>> + struct pch_phub_reqt *p_pch_phub_reqt;

>> + unsigned long addr_offset;

> 

> This will change size on 32/64bit boxes makign your copy a bit

> problematic 

Modify like belwo,

u64 addr_offset;





> 

>> + p_pch_phub_reqt = (struct pch_phub_reqt *)arg;

>> + ret_value = copy_from_user((void *)&addr_offset,

>> + (void *)&p_pch_phub_reqt->addr_offset,

>> + sizeof(addr_offset));

>> + if (ret_value) {

> 

>> + /* End of Access area check */

> 

> Remember here ioctl isn't single threaded so you may want to double check

> some of these

The above copy_from_user is Copy global variable to local variable.
Thus, We think this code has re-entrant.


> 

>> +struct pch_phub_reqt {

>> + unsigned long addr_offset; /*specifies the register address

>> + offset */

>> + unsigned long data; /*specifies the data */

>> + unsigned long mask; /*specifies the mask */

> 

> If they may need to be long make them u64. That way 32 and 64bit systems

> get the same ioctl structure and life is good.

Modify type of addr_offset to u64



> 

>> +};

>> +

>> +/* exported function prototypes */

>> +int pch_phub_open(struct inode *inode, struct file *file);

>> +int pch_phub_release(struct inode *inode, struct file *file);

>> +int pch_phub_ioctl(struct inode *inode, struct file *file, unsigned int cmd,

>> +       unsigned long arg);

> 

> You have various other functions that are not static - if they should be

> then make them static

Add static description for all of internal functions.





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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-07 13:37 ` Arnd Bergmann
@ 2010-06-08  0:15   ` Masayuki Ohtake
  2010-06-08  8:48   ` Masayuki Ohtake
  1 sibling, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-08  0:15 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Arnd,

Thank you for your comments.
We will integrate your comments to our PHUB as soon as possible.

Ohtake..

----- Original Message ----- 
From: "Arnd Bergmann" <arnd@arndb.de>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "LKML" <linux-kernel@vger.kernel.org>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Intel OTC"
<joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y" <yong.y.wang@intel.com>
Sent: Monday, June 07, 2010 10:37 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> On Friday 04 June 2010, Masayuki Ohtake wrote:
> > From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> >
> > This patch adds the Packet Hub driver for Topcliff.
> > Patch created against 2.6.33.1
> >
> > Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
>
> Most of the comments from my first review still apply to
> this version, please have another look at what I wrote
> back in april, see http://article.gmane.org/gmane.linux.network/158879
>
> Note also that patch submissions should be against the latest
> development kernel, in this case 2.6.35-rc2, not against stable
> kernel releases like 2.6.33.1.
>
> Arnd
>



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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-04 10:16 Masayuki Ohtake
  2010-06-04 12:00 ` Alan Cox
@ 2010-06-07 13:37 ` Arnd Bergmann
  2010-06-08  0:15   ` Masayuki Ohtake
  2010-06-08  8:48   ` Masayuki Ohtake
  1 sibling, 2 replies; 45+ messages in thread
From: Arnd Bergmann @ 2010-06-07 13:37 UTC (permalink / raw)
  To: Masayuki Ohtake; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

On Friday 04 June 2010, Masayuki Ohtake wrote:
> From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
> 
> This patch adds the Packet Hub driver for Topcliff.
> Patch created against 2.6.33.1
> 
> Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>

Most of the comments from my first review still apply to
this version, please have another look at what I wrote
back in april, see http://article.gmane.org/gmane.linux.network/158879

Note also that patch submissions should be against the latest
development kernel, in this case 2.6.35-rc2, not against stable
kernel releases like 2.6.33.1.

	Arnd

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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-04 12:00 ` Alan Cox
@ 2010-06-07  7:53   ` Masayuki Ohtake
  0 siblings, 0 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-07  7:53 UTC (permalink / raw)
  To: Alan Cox; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

Hi Alan

Thank you for your comment.
We are now modifying.
We will resubmit as soon as we can possible.

Thanks.
----- Original Message ----- 
From: "Alan Cox" <alan@lxorguk.ukuu.org.uk>
To: "Masayuki Ohtake" <masa-korg@dsn.okisemi.com>
Cc: "LKML" <linux-kernel@vger.kernel.org>; "Andrew" <andrew.chih.howe.khor@intel.com>; "Intel OTC"
<joel.clark@intel.com>; "Wang, Qi" <qi.wang@intel.com>; "Wang, Yong Y" <yong.y.wang@intel.com>
Sent: Friday, June 04, 2010 9:00 PM
Subject: Re: [PATCH] Topcliff PHUB: Generate PacketHub driver


> > +/*!
> > + * @ingroup PHUB_PCILayerAPI
> > + * @fn static void __exit pch_phub_pci_exit(void)
> > + * @brief Provides the functionality of exiting the module
> > + * */
>
> Can we please do something about all this stuff first so the code is
> easier to review by those not familiar with the kernel format.
>
> I sent a bit of code out last time that did most of the work
>
> Alan
>




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

* Re: [PATCH] Topcliff PHUB: Generate PacketHub driver
  2010-06-04 10:16 Masayuki Ohtake
@ 2010-06-04 12:00 ` Alan Cox
  2010-06-07  7:53   ` Masayuki Ohtake
  2010-06-07 13:37 ` Arnd Bergmann
  1 sibling, 1 reply; 45+ messages in thread
From: Alan Cox @ 2010-06-04 12:00 UTC (permalink / raw)
  To: Masayuki Ohtake; +Cc: LKML, Andrew, Intel OTC, Wang, Qi, Wang, Yong Y

> +/*!
> + * @ingroup	PHUB_PCILayerAPI
> + * @fn		static void __exit pch_phub_pci_exit(void)
> + * @brief	Provides the functionality of exiting the module
> + * */

Can we please do something about all this stuff first so the code is
easier to review by those not familiar with the kernel format.

I sent a bit of code out last time that did most of the work

Alan

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

* [PATCH] Topcliff PHUB: Generate PacketHub driver
@ 2010-06-04 10:16 Masayuki Ohtake
  2010-06-04 12:00 ` Alan Cox
  2010-06-07 13:37 ` Arnd Bergmann
  0 siblings, 2 replies; 45+ messages in thread
From: Masayuki Ohtake @ 2010-06-04 10:16 UTC (permalink / raw)
  To: LKML; +Cc: Andrew, Intel OTC, Wang, Qi, Wang, Yong Y, Masayuki Ohtake

From: Masayuki Ohtake <masa-korg@dsn.okisemi.com>

This patch adds the Packet Hub driver for Topcliff.
Patch created against 2.6.33.1

Signed-off-by: Masayuki Ohtake <masa-korg@dsn.okisemi.com>
---
 linux-2.6.33.1/drivers/char/Kconfig             |   20 +
 linux-2.6.33.1/drivers/char/Makefile            |    4 +
 linux-2.6.33.1/drivers/char/pch_phub/Makefile   |   11 +
 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c | 1500 +++++++++++++++++++++++
 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h |  182 +++
 5 files changed, 1717 insertions(+), 0 deletions(-)
 create mode 100644 linux-2.6.33.1/drivers/char/pch_phub/Makefile
 create mode 100644 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c
 create mode 100644 linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h

diff --git a/linux-2.6.33.1/drivers/char/Kconfig b/linux-2.6.33.1/drivers/char/Kconfig
index e023682..16a8334 100644
--- a/linux-2.6.33.1/drivers/char/Kconfig
+++ b/linux-2.6.33.1/drivers/char/Kconfig
@@ -4,6 +4,26 @@
 
 menu "Character devices"
 
+config PCH_IEEE1588
+	tristate "PCH IEEE1588"
+	depends on PCI
+	help
+	  If you say yes to this option, support will be included for the
+	  PCH IEEE1588 Host controller.
+
+config PCH_PHUB
+        tristate "PCH PHUB"
+        depends on PCI
+        help
+          If you say yes to this option, support will be included for the
+          PCH Packet Hub Host controller.
+
+config PCH_CAN_PCLK_50MHZ
+	bool "CAN PCLK 50MHz"
+	depends on PCH_PHUB
+        help
+          If you say yes to this option, clock is set to 50MHz.(For CAN control)
+
 config VT
 	bool "Virtual terminal" if EMBEDDED
 	depends on !S390
diff --git a/linux-2.6.33.1/drivers/char/Makefile b/linux-2.6.33.1/drivers/char/Makefile
index f957edf..dc092d0 100644
--- a/linux-2.6.33.1/drivers/char/Makefile
+++ b/linux-2.6.33.1/drivers/char/Makefile
@@ -111,6 +111,10 @@ obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
 obj-$(CONFIG_JS_RTC)		+= js-rtc.o
 js-rtc-y = rtc.o
 
+obj-$(CONFIG_PCH_IEEE1588)		+= pch_ieee1588/
+
+obj-$(CONFIG_PCH_PHUB)	+= pch_phub/
+
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c
 
diff --git a/linux-2.6.33.1/drivers/char/pch_phub/Makefile b/linux-2.6.33.1/drivers/char/pch_phub/Makefile
new file mode 100644
index 0000000..bfe2a2b
--- /dev/null
+++ b/linux-2.6.33.1/drivers/char/pch_phub/Makefile
@@ -0,0 +1,11 @@
+ifeq ($(CONFIG_PHUB_DEBUG),y)
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+obj-$(CONFIG_PCH_PHUB) += pch_phub_drv.o
+#to set CAN clock to 50Mhz
+ifdef CONFIG_PCH_CAN_PCLK_50MHZ
+EXTRA_CFLAGS +=-DPCH_CAN_PCLK_50MHZ
+endif
+
+pch_phub_drv-objs := pch_phub.o
diff --git a/linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c b/linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c
new file mode 100644
index 0000000..162653b
--- /dev/null
+++ b/linux-2.6.33.1/drivers/char/pch_phub/pch_phub.c
@@ -0,0 +1,1500 @@
+/*!
+ * @file pch_phub.c
+ * @brief Provides all the implementation of the interfaces pertaining to
+ *		the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+/* includes */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/string.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+
+#include "pch_phub.h"
+
+/*--------------------------------------------
+	macros
+--------------------------------------------*/
+/* Status Register offset */
+#define PHUB_STATUS (0x00)
+/* Control Register offset */
+#define PHUB_CONTROL (0x04)
+/* Time out value for Status Register */
+#define PHUB_TIMEOUT (0x05)
+/* Enabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_ENABLE (0x01)
+/* Disabling for writing ROM */
+#define PCH_PHUB_ROM_WRITE_DISABLE (0x00)
+/* ROM data area start address offset */
+#define PCH_PHUB_ROM_START_ADDR (0x14)
+/* MAX number of INT_REDUCE_CONTROL registers */
+#define MAX_NUM_INT_REDUCE_CONTROL_REG (128)
+
+/*!
+  @ingroup PHUB_PCILayer
+  @def PCI_DEVICE_ID_PCH1_PHUB
+  @brief Outlines the PCI Device ID.
+  */
+#define PCI_DEVICE_ID_PCH1_PHUB (0x8801)
+
+/*!
+  @ingroup	PHUB_PCILayer
+  @def		PCH_MINOR_NOS
+  @brief	Outlines the Packet Hub minor numbers limit.
+  */
+#define PCH_MINOR_NOS (1)
+
+/*values for configuring CLKCFG reg
+ * for CAN clock of 50Mhz*/
+
+/*!
+  @ingroup	PHUB_PCILayer
+  @def		CLKCFG_CAN_50MHZ
+  @brief	CLKCFG register setting for CAN clock of 50Mhz.
+  */
+#define CLKCFG_CAN_50MHZ (0x12000000)
+
+/*!
+  @ingroup	PHUB_PCILayer
+  @def		CLKCFG_CANCLK_MASK
+  @brief	Bit mask for bit fields in CLKCFG register
+		to set CAN clock to 50Mhz.
+  */
+#define CLKCFG_CANCLK_MASK (0xFF000000)
+
+#define MODULE_NAME "pch_phub"
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @def		PCH_READ_REG(a)
+  @remarks 	Implements the functionality of reading register.
+  @param	a [@ref IN] Contains the register offset address value
+  @retval	Contains the register value
+  */
+#define PCH_READ_REG(a)	ioread32((pch_phub_base_address + a))
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @def		PCH_WRITE_REG(a, b)
+  @remarks	Implements the functionality of writing register.
+  @param	a [@ref IN] Contains the writing value
+  @param	b [@ref IN] Contains the register offset address value
+  @retval	NONE
+  */
+#define PCH_WRITE_REG(a, b)	iowrite32(a, (pch_phub_base_address + b))
+
+/*--------------------------------------------
+	global variables
+--------------------------------------------*/
+struct pch_phub_reg {
+	u32 phub_id_reg;		/* PHUB_ID register val */
+	u32 q_pri_val_reg;		/* QUEUE_PRI_VAL register val */
+	u32 rc_q_maxsize_reg;	/* RC_QUEUE_MAXSIZE register val */
+	u32 bri_q_maxsize_reg;	/* BRI_QUEUE_MAXSIZE register val */
+	u32 comp_resp_timeout_reg;	/* COMP_RESP_TIMEOUT register val */
+	u32 bus_slave_control_reg;	/* BUS_SLAVE_CONTROL_REG register val */
+	u32 deadlock_avoid_type_reg; /* DEADLOCK_AVOID_TYPE register val */
+	u32 intpin_reg_wpermit_reg0; /* INTPIN_REG_WPERMIT register 0 val */
+	u32 intpin_reg_wpermit_reg1; /* INTPIN_REG_WPERMIT register 1 val */
+	u32 intpin_reg_wpermit_reg2; /* INTPIN_REG_WPERMIT register 2 val */
+	u32 intpin_reg_wpermit_reg3; /* INTPIN_REG_WPERMIT register 3 val */
+	/* INT_REDUCE_CONTROL registers val */
+	u32 int_reduce_control_reg[MAX_NUM_INT_REDUCE_CONTROL_REG];
+#ifdef PCH_CAN_PCLK_50MHZ
+	u32 clkcfg_reg;		/* CLK CFG register val */
+#endif
+} g_pch_phub_reg;
+
+s32 pch_phub_opencount;	/* check whether opened or not */
+u32 pch_phub_base_address;
+u32 pch_phub_extrom_base_address;
+s32 pch_phub_suspended;
+
+struct device *dev_dbg;
+
+DEFINE_SPINLOCK(pch_phub_lock);	/* for spin lock */
+
+/**
+ * file_operations structure initialization
+ */
+const struct file_operations pch_phub_fops = {
+	.owner = THIS_MODULE,
+	.open = pch_phub_open,
+	.release = pch_phub_release,
+	.ioctl = pch_phub_ioctl,
+};
+
+/* ToDo: major number allocation via module parameter */
+static dev_t pch_phub_dev_no;
+static int pch_phub_major_no;
+static struct cdev pch_phub_dev;
+
+
+/*--------------------------------------------
+	exported function prototypes
+--------------------------------------------*/
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static int __devinit pch_phub_probe(struct pci_dev* pch_pci_dev,
+					 const struct pci_device_id* pci_id)
+  @brief	Provides the functionality of probing the module
+  */
+static int __devinit pch_phub_probe(struct pci_dev *pdev, const
+				       struct pci_device_id *id);
+
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static void __devexit pch_phub_remove(
+				struct pci_dev * pch_pci_dev)
+  @brief	Provides the functionality of removing the module
+  */
+static void __devexit pch_phub_remove(struct pci_dev *pdev);
+
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static int pch_phub_suspend(struct pci_dev* pDev,
+						pm_message_t state)
+  @brief	Provides the functionality of suspending the module
+  */
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state);
+
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static int pch_phub_resume(struct pci_dev* pDev)
+  @brief	Provides the functionality of resuming the module
+  */
+static int pch_phub_resume(struct pci_dev *pdev);
+
+/*--------------------------------------------
+	structures
+--------------------------------------------*/
+/*!
+  @ingroup	PHUB_PCILayerFacilitators
+  @static	struct pci_device_id
+  @brief	It is a structure used for perserving information related to
+		the device id.
+  @note	The concerned details should be provided as a reference in
+		the pci driver structure.
+  */
+static struct pci_device_id pch_phub_pcidev_id[] = {
+
+	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
+	{0,}
+};
+
+/*!
+  @ingroup	PHUB_PCILayerFacilitators
+  @static	struct pch_phub_driver
+  @brief	It is a structure used for perserving information related to
+		the Packet Hub device and preserves function signatures to
+		manipulate the device.
+  @note	The structure contains the various interfaces aspects
+		provided to the pci layer.
+  @see
+  pch_phub_probe
+  pch_phub_suspend
+  pch_phub_resume
+  pch_phub_remove
+  */
+static struct pci_driver pch_phub_driver = {
+	.name = "pch_phub",
+	.id_table = pch_phub_pcidev_id,
+	.probe = pch_phub_probe,
+	.remove = __devexit_p(pch_phub_remove),
+#ifdef CONFIG_PM
+	.suspend = pch_phub_suspend,
+	.resume = pch_phub_resume
+#endif
+};
+
+/*!
+ * @ingroup	PHUB_PCILayerAPI
+ * @fn		static int __init pch_phub_pci_init(void)
+ * @brief	Provides the functionality of initializing the module
+ * */
+static int __init pch_phub_pci_init(void);
+/*!
+ * @ingroup	PHUB_PCILayerAPI
+ * @fn		static void __exit pch_phub_pci_exit(void)
+ * @brief	Provides the functionality of exiting the module
+ * */
+static void __exit pch_phub_pci_exit(void);
+
+MODULE_DESCRIPTION("PCH PACKET HUB PCI Driver");
+MODULE_LICENSE("GPL");
+module_init(pch_phub_pci_init);
+module_exit(pch_phub_pci_exit);
+module_param(pch_phub_major_no, int, S_IRUSR | S_IWUSR);
+
+
+/*--------------------------------------------
+	functions implementations
+--------------------------------------------*/
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		void pch_phub_read_modify_write_reg(
+				unsigned long reg_addr_offset,
+				unsigned long data, unsigned long mask)
+  @remarks	Implements the functionality of reading, modifying and writing
+								 register.
+  @param	reg_addr_offset [@ref IN] Contains the register offset address
+					     value
+  @param	data            [@ref IN] Contains the writing value
+  @param	mask            [@ref IN] Contains the mask value
+  @retval	NONE
+  @see
+  */
+void pch_phub_read_modify_write_reg(unsigned long reg_addr_offset,
+				       unsigned long data, unsigned long mask)
+{
+	unsigned long reg_addr = pch_phub_base_address + reg_addr_offset;
+	iowrite32(((ioread32(reg_addr) & ~mask)) | data, reg_addr);
+
+	return;
+}
+
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		void pch_phub_save_reg_conf(void)
+  @remarks	saves register configuration
+  @param	NONE
+  @retval	NONE
+  @see
+  pch_phub_suspend
+  */
+void pch_phub_save_reg_conf(void)
+{
+	u32 i = 0;
+
+	dev_dbg(dev_dbg, "pch_phub_save_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	g_pch_phub_reg.phub_id_reg = PCH_READ_REG(PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	g_pch_phub_reg.q_pri_val_reg = PCH_READ_REG(PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	g_pch_phub_reg.rc_q_maxsize_reg =
+	    PCH_READ_REG(PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	g_pch_phub_reg.bri_q_maxsize_reg =
+	    PCH_READ_REG(PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	g_pch_phub_reg.comp_resp_timeout_reg =
+	    PCH_READ_REG(PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	g_pch_phub_reg.bus_slave_control_reg =
+	    PCH_READ_REG(PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	g_pch_phub_reg.deadlock_avoid_type_reg =
+	    PCH_READ_REG(PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	g_pch_phub_reg.intpin_reg_wpermit_reg0 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	g_pch_phub_reg.intpin_reg_wpermit_reg1 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	g_pch_phub_reg.intpin_reg_wpermit_reg2 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	g_pch_phub_reg.intpin_reg_wpermit_reg3 =
+	    PCH_READ_REG(PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(dev_dbg, "pch_phub_save_reg_conf : "
+		"g_pch_phub_reg.phub_id_reg=%x, "
+		"g_pch_phub_reg.q_pri_val_reg=%x, "
+		"g_pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"g_pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"g_pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"g_pch_phub_reg.bus_slave_control_reg=%x, "
+		"g_pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		g_pch_phub_reg.phub_id_reg,
+		g_pch_phub_reg.q_pri_val_reg,
+		g_pch_phub_reg.rc_q_maxsize_reg,
+		g_pch_phub_reg.bri_q_maxsize_reg,
+		g_pch_phub_reg.comp_resp_timeout_reg,
+		g_pch_phub_reg.bus_slave_control_reg,
+		g_pch_phub_reg.deadlock_avoid_type_reg,
+		g_pch_phub_reg.intpin_reg_wpermit_reg0,
+		g_pch_phub_reg.intpin_reg_wpermit_reg1,
+		g_pch_phub_reg.intpin_reg_wpermit_reg2,
+		g_pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL registers */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		g_pch_phub_reg.int_reduce_control_reg[i] =
+		    PCH_READ_REG(
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(dev_dbg, "pch_phub_save_reg_conf : "
+			"g_pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, g_pch_phub_reg.int_reduce_control_reg[i]);
+	}
+#ifdef PCH_CAN_PCLK_50MHZ
+	/* save clk cfg register */
+	g_pch_phub_reg.clkcfg_reg = PCH_READ_REG(CLKCFG_REG_OFFSET);
+#endif
+	return;
+}
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		void pch_phub_restore_reg_conf(void)
+  @remarks	restore register configuration
+  @param	NONE
+  @retval	NONE
+  @see
+  pch_phub_resume
+  */
+
+void pch_phub_restore_reg_conf(void)
+{
+	u32 i = 0;
+
+	dev_dbg(dev_dbg, "pch_phub_restore_reg_conf ENTRY\n");
+	/* to store contents of PHUB_ID register */
+	PCH_WRITE_REG(g_pch_phub_reg.phub_id_reg, PCH_PHUB_PHUB_ID_REG);
+	/* to store contents of QUEUE_PRI_VAL register */
+	PCH_WRITE_REG(g_pch_phub_reg.q_pri_val_reg, PCH_PHUB_QUEUE_PRI_VAL_REG);
+	/* to store contents of RC_QUEUE_MAXSIZE register */
+	PCH_WRITE_REG(g_pch_phub_reg.rc_q_maxsize_reg,
+			PCH_PHUB_RC_QUEUE_MAXSIZE_REG);
+	/* to store contents of BRI_QUEUE_MAXSIZE register */
+	PCH_WRITE_REG(g_pch_phub_reg.bri_q_maxsize_reg,
+			PCH_PHUB_BRI_QUEUE_MAXSIZE_REG);
+	/* to store contents of COMP_RESP_TIMEOUT register */
+	PCH_WRITE_REG(g_pch_phub_reg.comp_resp_timeout_reg,
+			PCH_PHUB_COMP_RESP_TIMEOUT_REG);
+	/* to store contents of BUS_SLAVE_CONTROL_REG register */
+	PCH_WRITE_REG(g_pch_phub_reg.bus_slave_control_reg,
+			PCH_PHUB_BUS_SLAVE_CONTROL_REG);
+	/* to store contents of DEADLOCK_AVOID_TYPE register */
+	PCH_WRITE_REG(g_pch_phub_reg.deadlock_avoid_type_reg,
+			PCH_PHUB_DEADLOCK_AVOID_TYPE_REG);
+	/* to store contents of INTPIN_REG_WPERMIT register 0 */
+	PCH_WRITE_REG(g_pch_phub_reg.intpin_reg_wpermit_reg0,
+			PCH_PHUB_INTPIN_REG_WPERMIT_REG0);
+	/* to store contents of INTPIN_REG_WPERMIT register 1 */
+	PCH_WRITE_REG(g_pch_phub_reg.intpin_reg_wpermit_reg1,
+			PCH_PHUB_INTPIN_REG_WPERMIT_REG1);
+	/* to store contents of INTPIN_REG_WPERMIT register 2 */
+	PCH_WRITE_REG(g_pch_phub_reg.intpin_reg_wpermit_reg2,
+			PCH_PHUB_INTPIN_REG_WPERMIT_REG2);
+	/* to store contents of INTPIN_REG_WPERMIT register 3 */
+	PCH_WRITE_REG(g_pch_phub_reg.intpin_reg_wpermit_reg3,
+			PCH_PHUB_INTPIN_REG_WPERMIT_REG3);
+	dev_dbg(dev_dbg, "pch_phub_save_reg_conf : "
+		"g_pch_phub_reg.phub_id_reg=%x, "
+		"g_pch_phub_reg.q_pri_val_reg=%x, "
+		"g_pch_phub_reg.rc_q_maxsize_reg=%x, "
+		"g_pch_phub_reg.bri_q_maxsize_reg=%x, "
+		"g_pch_phub_reg.comp_resp_timeout_reg=%x, "
+		"g_pch_phub_reg.bus_slave_control_reg=%x, "
+		"g_pch_phub_reg.deadlock_avoid_type_reg=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg0=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg1=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg2=%x, "
+		"g_pch_phub_reg.intpin_reg_wpermit_reg3=%x\n",
+		g_pch_phub_reg.phub_id_reg,
+		g_pch_phub_reg.q_pri_val_reg,
+		g_pch_phub_reg.rc_q_maxsize_reg,
+		g_pch_phub_reg.bri_q_maxsize_reg,
+		g_pch_phub_reg.comp_resp_timeout_reg,
+		g_pch_phub_reg.bus_slave_control_reg,
+		g_pch_phub_reg.deadlock_avoid_type_reg,
+		g_pch_phub_reg.intpin_reg_wpermit_reg0,
+		g_pch_phub_reg.intpin_reg_wpermit_reg1,
+		g_pch_phub_reg.intpin_reg_wpermit_reg2,
+		g_pch_phub_reg.intpin_reg_wpermit_reg3);
+	/* to store contents of INT_REDUCE_CONTROL register */
+	for (i = 0; i < MAX_NUM_INT_REDUCE_CONTROL_REG; i++) {
+		PCH_WRITE_REG(g_pch_phub_reg.int_reduce_control_reg[i],
+			PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE + 4 * i);
+		dev_dbg(dev_dbg, "pch_phub_save_reg_conf : "
+			"g_pch_phub_reg.int_reduce_control_reg[%d]=%x\n",
+			i, g_pch_phub_reg.int_reduce_control_reg[i]);
+	}
+
+#ifdef PCH_CAN_PCLK_50MHZ
+	/*restore the clock config reg */
+	PCH_WRITE_REG(g_pch_phub_reg.clkcfg_reg, CLKCFG_REG_OFFSET);
+#endif
+
+	return;
+}
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		void pch_phub_read_serial_rom
+			(unsigned long offset_address, unsigned char *data)
+  @remarks	Implements the functionality of reading Serial ROM.
+  @param	unsigned long offset_address
+		[@ref IN] Contains the Serial ROM address offset value
+  @param	*data [@ref INOUT] Contains the Serial ROM value
+  @retval	returnvalue [@ref OUT] contains the result for the reading
+		Serial ROM attempt
+  @see
+  */
+int pch_phub_read_serial_rom(unsigned long offset_address, unsigned char *data)
+{
+	unsigned long mem_addr = pch_phub_extrom_base_address + offset_address;
+
+	dev_dbg(dev_dbg,
+		"pch_phub_read_serial_rom:mem_addr=0x%08x\n", mem_addr);
+	*data = ioread8(mem_addr);
+
+	return 0;
+}
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		void pch_phub_write_serial_rom(unsigned long offset_address,
+							 unsigned char data)
+  @remarks	Implements the functionality of writing Serial ROM.
+  @param	unsigned long offset_address
+		[@ref IN] Contains the Serial ROM address offset value
+  @param	data  [@ref IN] Contains the Serial ROM value
+  @retval	returnvalue [@ref OUT] contains the result for
+		the writing Serial ROM attempt
+  @see
+  */
+int pch_phub_write_serial_rom(unsigned long offset_address, unsigned char data)
+{
+	int retval = 0;
+	unsigned long mem_addr = pch_phub_extrom_base_address + offset_address;
+	int i = 0;
+	unsigned long word_data = 0;
+
+	dev_dbg(dev_dbg,
+		"pch_phub_write_serial_rom:mem_addr=0x%08x\n", mem_addr);
+	iowrite32(PCH_PHUB_ROM_WRITE_ENABLE,
+			pch_phub_extrom_base_address + PHUB_CONTROL);
+
+	word_data = ioread32(mem_addr & 0xFFFFFFFC);
+	dev_dbg(dev_dbg, "word_data=0x%08x  data=0x%02x\n",
+		 word_data, data);
+	switch (mem_addr % 4) {
+	case 0:
+		word_data &= 0xFFFFFF00;
+		iowrite32((word_data | (unsigned long)data),
+				(mem_addr & 0xFFFFFFFC));
+		break;
+	case 1:
+		word_data &= 0xFFFF00FF;
+		iowrite32((word_data | ((unsigned long)data << 8)),
+				(mem_addr & 0xFFFFFFFC));
+		break;
+	case 2:
+		word_data &= 0xFF00FFFF;
+		iowrite32((word_data | ((unsigned long)data << 16)),
+				(mem_addr & 0xFFFFFFFC));
+		break;
+	case 3:
+		word_data &= 0x00FFFFFF;
+		iowrite32((word_data | ((unsigned long)data << 24)),
+				(mem_addr & 0xFFFFFFFC));
+		break;
+	}
+	while (0x00 !=
+	       ioread8(pch_phub_extrom_base_address + PHUB_STATUS)) {
+		msleep(1);
+		if (PHUB_TIMEOUT == i) {
+			retval = -EPERM;
+			break;
+		}
+		i++;
+	}
+
+	iowrite32(PCH_PHUB_ROM_WRITE_DISABLE,
+			pch_phub_extrom_base_address + PHUB_CONTROL);
+
+	return retval;
+}
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		void pch_phub_read_serial_rom_val(unsigned long offset_address,
+							 unsigned char *data)
+  @remarks	Implements the functionality of reading Serial ROM value.
+  @param	unsigned long offset_address
+		[@ref IN] Contains the Serial ROM address offset value
+  @param	*data [@ref INOUT] Contains the Serial ROM value
+  @retval	returnvalue [@ref OUT] contains the result for
+		the reading Serial ROM attempt
+  @see
+  */
+int pch_phub_read_serial_rom_val(unsigned long offset_address,
+				    unsigned char *data)
+{
+	int retval = 0;
+	unsigned long mem_addr;
+
+	mem_addr = (offset_address / 4 * 8) + 3 -
+			(offset_address % 4) + PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_read_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		void pch_phub_write_serial_rom_val(unsigned long offset_address,
+							 unsigned char data)
+  @remarks	Implements the functionality of writing Serial ROM value.
+  @param	unsigned long offset_address
+		[@ref IN] Contains the Serial ROM address offset value
+  @param	data [@ref IN] Contains the Serial ROM value
+  @retval	returnvalue [@ref OUT] contains the result for
+		the writing Serial ROM attempt
+  @see
+  */
+int pch_phub_write_serial_rom_val(unsigned long offset_address,
+				     unsigned char data)
+{
+	int retval = 0;
+	unsigned long mem_addr;
+
+	mem_addr =
+	    (offset_address / 4 * 8) + 3 - (offset_address % 4) +
+	    PCH_PHUB_ROM_START_ADDR;
+	retval = pch_phub_write_serial_rom(mem_addr, data);
+
+	return retval;
+}
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		int pch_phub_gbe_serial_rom_conf(void)
+  @remarks	makes Serial ROM header format configuration
+		for Gigabit Ethernet MAC address
+  @param	NONE
+  @retval	returnvalue [@ref OUT] contains the result for
+		the writing Serial ROM attempt
+  @see
+  */
+int pch_phub_gbe_serial_rom_conf(void)
+{
+	int retval = 0;
+
+	retval |= pch_phub_write_serial_rom(0x0b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x0a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x09, 0x01);
+	retval |= pch_phub_write_serial_rom(0x08, 0x02);
+
+	retval |= pch_phub_write_serial_rom(0x0f, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0e, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0d, 0x00);
+	retval |= pch_phub_write_serial_rom(0x0c, 0x80);
+
+	retval |= pch_phub_write_serial_rom(0x13, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x12, 0x10);
+	retval |= pch_phub_write_serial_rom(0x11, 0x01);
+	retval |= pch_phub_write_serial_rom(0x10, 0x18);
+
+	retval |= pch_phub_write_serial_rom(0x1b, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x1a, 0x10);
+	retval |= pch_phub_write_serial_rom(0x19, 0x01);
+	retval |= pch_phub_write_serial_rom(0x18, 0x19);
+
+	retval |= pch_phub_write_serial_rom(0x23, 0xbc);
+	retval |= pch_phub_write_serial_rom(0x22, 0x10);
+	retval |= pch_phub_write_serial_rom(0x21, 0x01);
+	retval |= pch_phub_write_serial_rom(0x20, 0x3a);
+
+	retval |= pch_phub_write_serial_rom(0x27, 0x01);
+	retval |= pch_phub_write_serial_rom(0x26, 0x00);
+	retval |= pch_phub_write_serial_rom(0x25, 0x00);
+	retval |= pch_phub_write_serial_rom(0x24, 0x00);
+
+	return retval;
+}
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		int pch_phub_read_gbe_mac_addr(unsigned long offset_address,
+							 unsigned char *data)
+  @param	unsigned long offset_address
+		[@ref IN] Contains the Gigabit Ethernet MAC address offset value
+  @param	*data
+		[@ref INOUT] Contains the Gigabit Ethernet MAC address value
+  @retval	return value [@ref OUT] contains the result
+		for the reading Gigabit Ethernet MAC address attempt
+  @see
+  */
+int pch_phub_read_gbe_mac_addr(unsigned long offset_address,
+				  unsigned char *data)
+{
+	int retval = 0;
+
+	retval = pch_phub_read_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/*!
+  @ingroup	PHUB_HALLayerAPI
+  @fn		int pch_phub_write_gbe_mac_addr(unsigned long offset_address,
+							 unsigned char data)
+  @param	unsigned long offset_address
+		[@ref IN] Contains the Gigabit Ethernet MAC address offset value
+  @param	data [@ref IN] Contains the Gigabit Ethernet MAC address value
+  @retval	return value [@ref OUT] contains the result for the
+				 writing Gigabit Ethernet MAC address attempt
+  @see
+  */
+int pch_phub_write_gbe_mac_addr(unsigned long offset_address,
+				   unsigned char data)
+{
+	int retval = 0;
+
+	retval = pch_phub_gbe_serial_rom_conf();
+	retval |= pch_phub_write_serial_rom_val(offset_address, data);
+
+	return retval;
+}
+
+/*!
+  @ingroup	PHUB_InterfaceLayerAPI
+  @fn		int pch_phub_open( struct inode *inode,struct file *file)
+  @remarks	Implements the Initializing and opening of
+		the Packet Hub module.
+  @param	inode
+		[@ref INOUT] Contains the reference of the inode structure
+  @param	file
+		[@ref INOUT] Contains the reference of the file structure
+  @retval	returnvalue
+		[@ref OUT] contains the result for the concerned attempt.
+		The result would generally comprise of success code
+		or failure code. The failure code will indicate reason for
+  failure.
+  @see
+  EBUSY
+  */
+int pch_phub_open(struct inode *inode, struct file *file)
+{
+	int ret;
+
+	spin_lock(&pch_phub_lock);
+	dev_dbg(dev_dbg, "pch_phub_open : open count value = %d",
+		  pch_phub_opencount);
+	if (pch_phub_opencount) {
+		dev_dbg(dev_dbg, "pch_phub_open :  device already opened\n");
+		ret = -EBUSY;
+	} else {
+		pch_phub_opencount++;
+		ret = 0;
+	}
+	spin_unlock(&pch_phub_lock);
+
+	dev_dbg(dev_dbg, "pch_phub_open returns=%d\n", ret);
+	return ret;
+}
+
+/*!
+  @ingroup	PHUB_InterfaceLayerAPI
+  @fn		int pch_phub_release(struct inode *inode,struct file *file)
+  @remarks	Implements the release functionality of the Packet Hub module.
+  @param	inode
+		[@ref INOUT] Contains the reference of the inode structure
+  @param	file
+		[@ref INOUT] Contains the reference of the file structure
+  @retval	returnvalue
+		[@ref OUT] contains the result for the concerned attempt.
+		The result would generally comprise of success code or failure
+		code. The failure code will indicate reason for failure.
+  @see
+  SUCCESS
+  */
+int pch_phub_release(struct inode *inode, struct file *file)
+{
+	spin_lock(&pch_phub_lock);
+
+	if (pch_phub_opencount > 0)
+		pch_phub_opencount--;
+	spin_unlock(&pch_phub_lock);
+
+	dev_dbg(dev_dbg, "pch_phub_release : "
+		"pch_phub_opencount=%d  returning=%d\n",
+		pch_phub_opencount, 0);
+	return 0;
+}
+
+/*!
+  @ingroup	PHUB_InterfaceLayerAPI
+  @fn		int pch_phub_ioctl(struct inode * inode,struct file * file,
+					 unsigned int cmd,unsigned long arg)
+  @remarks	Implements the various ioctl functionalities of
+		the Packet Hub module.
+  @param	inode
+		[@ref INOUT] Contains the reference of the inode structure
+  @param	file
+		[@ref INOUT] Contains the reference of the file structure
+  @param	cmd 	[@ref IN] Contains the command value
+  @param	arg 	[@ref IN] Contains the command argument value
+  @retval	returnvalue
+		[@ref OUT] contains the result for the concerned attempt.
+		The result would generally comprise of success code or failure
+		code. The failure code will indicate reason for failure.
+  @see
+  EINVAL
+  EFAULT
+  */
+#if 0
+int pch_phub_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	int ret_value = 0;
+	struct pch_phub_reqt *p_pch_phub_reqt;
+	unsigned long addr_offset;
+	unsigned long data;
+	unsigned long mask;
+
+	do {
+		if (pch_phub_suspended == true) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"suspend initiated returning =%d\n",
+				-EPERM);
+			ret_value = -EPERM;
+			break;
+		}
+
+		p_pch_phub_reqt = (struct pch_phub_reqt *)arg;
+		ret_value =
+			copy_from_user((void *)&addr_offset,
+				(void *)&p_pch_phub_reqt->addr_offset,
+				sizeof(addr_offset));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_from_user fail returning =%d\n",
+				-EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		dev_dbg(dev_dbg, "pch_phub_ioctl : "
+			"copy_from_user returns =%d\n", ret_value);
+
+		/* Access area check */
+		switch (cmd) {
+		case IOCTL_PHUB_READ_REG:
+		case IOCTL_PHUB_WRITE_REG:
+		case IOCTL_PHUB_READ_MODIFY_WRITE_REG:
+			if (addr_offset >= 0x504)
+				ret_value = -EPERM;
+			break;
+		case IOCTL_PHUB_READ_OROM:
+		case IOCTL_PHUB_WRITE_OROM:
+		case IOCTL_PHUB_READ_MAC_ADDR:
+		case IOCTL_PHUB_WRITE_MAC_ADDR:
+			if (addr_offset >= 0x10000)
+				ret_value = -EPERM;
+			break;
+		}
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"access area is wrong returning =%d\n",
+				-EPERM);
+			break;
+		}
+		/* End of Access area check */
+
+		switch (cmd) {
+		case IOCTL_PHUB_READ_REG:
+			data = PCH_READ_REG(addr_offset);
+			dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+				"PCH_READ_REG successfully\n");
+
+			ret_value =
+			    copy_to_user((void *)&p_pch_phub_reqt->data,
+					 (void *)&data, sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_to_user fail returning =%d\n",
+					-EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			break;
+		case IOCTL_PHUB_WRITE_REG:
+			ret_value = copy_from_user((void *)&data,
+						(void *)&p_pch_phub_reqt->data,
+						sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_from_user fail returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			PCH_WRITE_REG(data, addr_offset);
+			dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+				"PCH_WRITE_REG successfully\n");
+			break;
+		case IOCTL_PHUB_READ_MODIFY_WRITE_REG:
+			ret_value = copy_from_user((void *)&data,
+						   (void *)&p_pch_phub_reqt->
+						   data, sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+						"copy_from_user fail "
+						"returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			ret_value = copy_from_user((void *)&mask,
+						   (void *)&p_pch_phub_reqt->
+						   mask, sizeof(mask));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			pch_phub_read_modify_write_reg(addr_offset, data, mask);
+			dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+				"pch_phub_read_modify_write_reg "
+				"successfully\n");
+			break;
+		case IOCTL_PHUB_READ_OROM:
+			ret_value = pch_phub_read_serial_rom(addr_offset,
+							(unsigned char *)&data);
+			if (ret_value) {
+				dev_dbg(dev_dbg,
+					"pch_phub_ioctl : Invoked "
+					"pch_phub_read_serial_rom "
+					"=%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			} else {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+					"pch_phub_read_serial_rom "
+					"successfully\n");
+			}
+			ret_value = copy_to_user((void *)&p_pch_phub_reqt->
+						 data, (void *)&data,
+						 sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_to_user fail returning "
+					"=%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			break;
+		case IOCTL_PHUB_WRITE_OROM:
+			ret_value =
+			    copy_from_user((void *)&data,
+					   (void *)&p_pch_phub_reqt->
+					   data, sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_from_user fail returning "
+					"=%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			ret_value =
+				pch_phub_write_serial_rom(addr_offset, data);
+			if (ret_value) {
+				dev_dbg(dev_dbg,
+					"pch_phub_ioctl : Invoked "
+					"pch_phub_write_serial_rom "
+					"=%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			} else {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+					"pch_phub_write_serial_rom "
+					"successfully\n");
+			}
+			break;
+		case IOCTL_PHUB_READ_MAC_ADDR:
+			pch_phub_read_gbe_mac_addr(addr_offset,
+					 (unsigned char *)&data);
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_read_gbe_mac_addr successfully\n");
+
+			ret_value =
+			    copy_to_user((void *)&p_pch_phub_reqt->data,
+					 (void *)&data, sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_to_user fail "
+					"returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			break;
+		case IOCTL_PHUB_WRITE_MAC_ADDR:
+			ret_value =
+			    copy_from_user((void *)&data,
+					   (void *)&p_pch_phub_reqt->data,
+					   sizeof(data));
+			if (ret_value) {
+				dev_dbg(dev_dbg, "pch_phub_ioctl : "
+					"copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+				ret_value = -EFAULT;
+				break;
+			}
+			pch_phub_write_gbe_mac_addr(addr_offset, data);
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+					"pch_phub_write_gbe_mac_addr "
+					"successfully\n");
+			break;
+		default:
+			dev_dbg(dev_dbg, "pch_write_ioctl invalid "
+				"command returning=%d\n", -EINVAL);
+			ret_value = -EINVAL;
+			break;
+		}
+		break;
+
+	} while (0);
+
+
+	dev_dbg(dev_dbg, "pch_write_ioctl returns=%d\n", ret_value);
+	return ret_value;
+}
+#endif
+int pch_phub_ioctl(struct inode *inode, struct file *file,
+			unsigned int cmd, unsigned long arg)
+{
+	int ret_value = 0;
+	struct pch_phub_reqt *p_pch_phub_reqt;
+	unsigned long addr_offset;
+	unsigned long data;
+	unsigned long mask;
+
+	if (pch_phub_suspended == true) {
+		dev_dbg(dev_dbg, "pch_phub_ioctl : "
+			"suspend initiated returning =%d\n", -EPERM);
+		ret_value = -EPERM;
+		goto return_ioctrl;
+	}
+
+	p_pch_phub_reqt = (struct pch_phub_reqt *)arg;
+	ret_value = copy_from_user((void *)&addr_offset,
+				(void *)&p_pch_phub_reqt->addr_offset,
+				sizeof(addr_offset));
+	if (ret_value) {
+		dev_dbg(dev_dbg, "pch_phub_ioctl : "
+			"copy_from_user fail returning =%d\n", -EFAULT);
+		ret_value = -EFAULT;
+		goto return_ioctrl;
+	}
+	dev_dbg(dev_dbg, "pch_phub_ioctl : "
+		"copy_from_user returns =%d\n", ret_value);
+
+	/* Access area check */
+	switch (cmd) {
+	case IOCTL_PHUB_READ_REG:
+	case IOCTL_PHUB_WRITE_REG:
+	case IOCTL_PHUB_READ_MODIFY_WRITE_REG:
+		if (addr_offset >= 0x504)
+			ret_value = -EPERM;
+		break;
+	case IOCTL_PHUB_READ_OROM:
+	case IOCTL_PHUB_WRITE_OROM:
+	case IOCTL_PHUB_READ_MAC_ADDR:
+	case IOCTL_PHUB_WRITE_MAC_ADDR:
+		if (addr_offset >= 0x10000)
+			ret_value = -EPERM;
+		break;
+	}
+	if (ret_value) {
+		dev_dbg(dev_dbg, "pch_phub_ioctl : "
+			"access area is wrong returning =%d\n", -EPERM);
+		goto return_ioctrl;
+	}
+	/* End of Access area check */
+
+	switch (cmd) {
+	case IOCTL_PHUB_READ_REG:
+		data = PCH_READ_REG(addr_offset);
+		dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+			"PCH_READ_REG successfully\n");
+
+		ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
+					 (void *)&data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_to_user fail returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		break;
+	case IOCTL_PHUB_WRITE_REG:
+		ret_value = copy_from_user((void *)&data,
+					(void *)&p_pch_phub_reqt->data,
+					sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_from_user fail returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		PCH_WRITE_REG(data, addr_offset);
+		dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+				"PCH_WRITE_REG successfully\n");
+		break;
+	case IOCTL_PHUB_READ_MODIFY_WRITE_REG:
+		ret_value = copy_from_user((void *)&data,
+			   (void *)&p_pch_phub_reqt->data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		ret_value = copy_from_user((void *)&mask,
+			   (void *)&p_pch_phub_reqt->mask, sizeof(mask));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		pch_phub_read_modify_write_reg(addr_offset, data, mask);
+		dev_dbg(dev_dbg, "pch_phub_ioctl  : Invoked "
+			"pch_phub_read_modify_write_reg successfully\n");
+		break;
+	case IOCTL_PHUB_READ_OROM:
+		ret_value = pch_phub_read_serial_rom(addr_offset,
+							(unsigned char *)&data);
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_read_serial_rom =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		} else {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_read_serial_rom successfully\n");
+		}
+		ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
+						(void *)&data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_to_user fail returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		break;
+	case IOCTL_PHUB_WRITE_OROM:
+		ret_value = copy_from_user((void *)&data,
+			   (void *)&p_pch_phub_reqt->data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : "
+				"copy_from_user fail returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		ret_value = pch_phub_write_serial_rom(addr_offset, data);
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_write_serial_rom =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		} else {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_write_serial_rom successfully\n");
+		}
+		break;
+	case IOCTL_PHUB_READ_MAC_ADDR:
+		pch_phub_read_gbe_mac_addr(addr_offset, (unsigned char *)&data);
+		dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_read_gbe_mac_addr successfully\n");
+
+		ret_value = copy_to_user((void *)&p_pch_phub_reqt->data,
+						 (void *)&data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : copy_to_user fail "
+					"returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		break;
+	case IOCTL_PHUB_WRITE_MAC_ADDR:
+		ret_value = copy_from_user((void *)&data,
+			   (void *)&p_pch_phub_reqt->data, sizeof(data));
+		if (ret_value) {
+			dev_dbg(dev_dbg, "pch_phub_ioctl : copy_from_user fail "
+					"returning =%d\n", -EFAULT);
+			ret_value = -EFAULT;
+			break;
+		}
+		pch_phub_write_gbe_mac_addr(addr_offset, data);
+		dev_dbg(dev_dbg, "pch_phub_ioctl : Invoked "
+				"pch_phub_write_gbe_mac_addr successfully\n");
+		break;
+	default:
+		dev_dbg(dev_dbg, "pch_write_ioctl invalid "
+				"command returning=%d\n", -EINVAL);
+		ret_value = -EINVAL;
+		break;
+	}
+return_ioctrl:
+	dev_dbg(dev_dbg, "pch_write_ioctl returns=%d\n", ret_value);
+	return ret_value;
+}
+
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static int __init pch_phub_pci_init(void)
+  @remarks	Implements the initialization functionality of the module.
+  @param	NONE
+  @retval	returnvalue
+		[@ref OUT] contains the result for the concerned attempt.
+		The result would generally comprise of success code or
+		failure code. The failure code will indicate reason for failure.
+  @see
+	  pch_phub_pci_exit
+  */
+static int __init pch_phub_pci_init(void)
+{
+	s32 ret;
+	ret = pci_register_driver(&pch_phub_driver);
+	dev_dbg(dev_dbg, "pch_phub_pci_init : "
+			"Invoked pci_register_driver successfully   "
+			"returns = %d\n", ret);
+	return ret;
+}
+
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static void __exit pch_phub_pci_exit(void)
+  @remarks	Implements the exit functionality of the module.
+  @param	NONE
+  @retval	returnvalue
+		[@ref OUT] contains the result for the concerned attempt.
+		The result would generally comprise of success code or failure
+		code. The failure code will indicate reason for failure.
+  @see
+	  pch_phub_pci_init
+  */
+static void __exit pch_phub_pci_exit(void)
+{
+	pci_unregister_driver(&pch_phub_driver);
+	dev_dbg(dev_dbg, "pch_phub_pci_exit : "
+			"Invoked pci_unregister_driver successfully\n");
+}
+
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static int __devinit pch_phub_probe(struct pci_dev* pdev,
+						 const struct pci_device_id* id)
+  @remarks	Implements the probe functionality of the module.
+  @param	pdev
+		[@ref INOUT] Contains the reference of the pci_dev structure
+  @param	id
+		[@ref INOUT] Contains the reference of
+		the pci_device_id structure
+  @retval	returnvalue
+		[@ref OUT] contains the result for the concerned attempt.
+		The result would generally comprise of success code or failure
+		code. The failure code will indicate reason for failure.
+  @see
+	  pch_phub_pci_init
+  */
+static int __devinit pch_phub_probe(struct pci_dev *pdev,
+				       const struct pci_device_id *id)
+{
+
+	char *DRIVER_NAME = "pch_phub";
+	int ret;
+	unsigned int rom_size;
+
+	dev_dbg = &pdev->dev;
+
+	pch_phub_major_no = (pch_phub_major_no < 0 || pch_phub_major_no > 254) ?
+				0 : pch_phub_major_no;
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(dev_dbg, "\npch_phub_probe : pci_enable_device FAILED");
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe : "
+			"pci_enable_device returns %d\n", ret);
+
+	ret = pci_request_regions(pdev, DRIVER_NAME);
+	if (ret) {
+		dev_dbg(dev_dbg, "pch_phub_probe : pci_request_regions FAILED");
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe : "
+		"pci_request_regions returns %d\n", ret);
+
+	pch_phub_base_address = (unsigned long)pci_iomap(pdev, 1, 0);
+
+	if (pch_phub_base_address == 0) {
+		dev_dbg(dev_dbg, "pch_phub_probe : pci_iomap FAILED");
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe : pci_iomap SUCCESS and value "
+		"in pch_phub_base_address variable is 0x%08x\n",
+		pch_phub_base_address);
+
+	pch_phub_extrom_base_address =
+	    (unsigned long)pci_map_rom(pdev, &rom_size);
+	if (pch_phub_extrom_base_address == 0) {
+		dev_dbg(dev_dbg, "pch_phub_probe : pci_map_rom FAILED");
+		pci_iounmap(pdev, (void *)pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		ret = -ENOMEM;
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe : "
+		"pci_map_rom SUCCESS and value in "
+		"pch_phub_extrom_base_address variable is 0x%08x\n",
+		pch_phub_extrom_base_address);
+
+	if (pch_phub_major_no) {
+		pch_phub_dev_no = MKDEV(pch_phub_major_no, 0);
+		ret = register_chrdev_region(pch_phub_dev_no,
+					   PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(dev_dbg, "pch_phub_probe : "
+				"register_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+					(void *)pch_phub_extrom_base_address);
+			pci_iounmap(pdev, (void *)pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(dev_dbg, "pch_phub_probe : "
+				"register_chrdev_region returns %d\n", ret);
+	} else {
+		ret = alloc_chrdev_region(&pch_phub_dev_no, 0,
+						PCH_MINOR_NOS, DRIVER_NAME);
+		if (ret) {
+			dev_dbg(dev_dbg, "pch_phub_probe : "
+					"alloc_chrdev_region FAILED");
+			pci_unmap_rom(pdev,
+				      (void *)pch_phub_extrom_base_address);
+			pci_iounmap(pdev,
+				    (void *)pch_phub_base_address);
+			pci_release_regions(pdev);
+			pci_disable_device(pdev);
+			goto err_probe;
+		}
+		dev_dbg(dev_dbg, "pch_phub_probe : "
+			"alloc_chrdev_region returns %d\n", ret);
+	}
+
+	cdev_init(&pch_phub_dev, &pch_phub_fops);
+	dev_dbg(dev_dbg, "pch_phub_probe :  cdev_init invoked successfully\n");
+
+	pch_phub_dev.owner = THIS_MODULE;
+	pch_phub_dev.ops = &pch_phub_fops;
+
+	ret = cdev_add(&pch_phub_dev, pch_phub_dev_no, PCH_MINOR_NOS);
+	if (ret) {
+		dev_dbg(dev_dbg, "pch_phub_probe :  cdev_add FAILED");
+		unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+		pci_unmap_rom(pdev, (void *)pch_phub_extrom_base_address);
+		pci_iounmap(pdev, (void *)pch_phub_base_address);
+		pci_release_regions(pdev);
+		pci_disable_device(pdev);
+		goto err_probe;
+	}
+	dev_dbg(dev_dbg, "pch_phub_probe :  cdev_add returns %d\n", ret);
+
+#ifdef PCH_CAN_PCLK_50MHZ
+	/*set the clock config reg if CAN clock is 50Mhz */
+	dev_dbg(dev_dbg, "pch_phub_probe : invoking "
+		"pch_phub_read_modify_write_reg "
+		"to set CLKCFG reg for CAN clk 50Mhz\n");
+	pch_phub_read_modify_write_reg(CLKCFG_REG_OFFSET,
+					  CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+#endif
+	/* set the prefech value */
+	PCH_WRITE_REG(0x000ffffa, 0x14);
+	/* set the interrupt delay value */
+	PCH_WRITE_REG(0x25, 0x44);
+	return 0;
+
+err_probe:
+	dev_dbg(dev_dbg, "pch_phub_probe returns %d\n", ret);
+	return ret;
+}
+
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static void __devexit pch_phub_remove(struct pci_dev * pdev)
+  @remarks	Implements the remove functionality of the module.
+  @param	pdev
+		[@ref INOUT] Contains the reference of the pci_dev structure
+  @retval	returnvalue
+		[@ref OUT] contains the result for the concerned attempt.
+		The result would generally comprise of success code or failure
+		code. The failure code will indicate reason for failure.
+  @see
+		pch_phub_pci_init
+  */
+static void __devexit pch_phub_remove(struct pci_dev *pdev)
+{
+
+	cdev_del(&pch_phub_dev);
+	dev_dbg(dev_dbg, "pch_phub_remove - cdev_del Invoked successfully\n");
+
+	unregister_chrdev_region(pch_phub_dev_no, PCH_MINOR_NOS);
+	dev_dbg(dev_dbg, "pch_phub_remove - "
+		"unregister_chrdev_region Invoked successfully\n");
+
+	pci_unmap_rom(pdev, (void *)pch_phub_extrom_base_address);
+
+	pci_iounmap(pdev, (void *)pch_phub_base_address);
+
+	dev_dbg(dev_dbg, "pch_phub_remove - "
+			"pci_iounmap Invoked successfully\n");
+
+	pci_release_regions(pdev);
+	dev_dbg(dev_dbg, "pch_phub_remove - "
+		"pci_release_regions Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(dev_dbg, "pch_phub_remove - "
+		"pci_disable_device Invoked successfully\n");
+
+}
+
+#ifdef CONFIG_PM
+
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static int pch_phub_suspend(struct pci_dev* pdev,
+							pm_message_t state)
+  @remarks	Implements the suspend functionality of the module.
+  @param	pdev
+		[@ref INOUT] Contains the reference of the pci_dev structure
+  @param	state	[@ref INOUT] Contains the reference of
+		the pm_message_t structure
+  @retval	returnvalue
+		[@ref OUT] contains the result for the concerned attempt.
+		The result would generally comprise of success code or failure
+		code. The failure code will indicate reason for failure.
+  @see
+		pch_phub_pci_init
+		pch_phub_resume
+  */
+static int pch_phub_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	int ret;
+
+	pch_phub_suspended = true;	/* For blocking further IOCTLs */
+
+	pch_phub_save_reg_conf();
+	dev_dbg(dev_dbg, "pch_phub_suspend - "
+		"pch_phub_save_reg_conf Invoked successfully\n");
+
+	ret = pci_save_state(pdev);
+	if (ret) {
+		dev_dbg(dev_dbg,
+			" pch_phub_suspend -pci_save_state returns-%d\n", ret);
+		return ret;
+	}
+	dev_dbg(dev_dbg, "pch_phub_suspend - pci_save_state returns %d\n", ret);
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(dev_dbg, "pch_phub_suspend - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pci_disable_device(pdev);
+	dev_dbg(dev_dbg, "pch_phub_suspend - "
+			"pci_disable_device Invoked successfully\n");
+
+	pci_set_power_state(pdev, pci_choose_state(pdev, state));
+	dev_dbg(dev_dbg, "pch_phub_suspend - "
+			"pci_set_power_state Invoked successfully   "
+			"return = %d\n", 0);
+
+	return 0;
+}
+
+/*!
+  @ingroup	PHUB_PCILayerAPI
+  @fn		static int pch_phub_resume(struct pci_dev* pdev)
+  @remarks	Implements the resume functionality of the module.
+  @param	pdev
+		[@ref INOUT] Contains the reference of the pci_dev structure
+  @retval	returnvalue
+		[@ref OUT] contains the result for the concerned attempt.
+		The result would generally comprise of success code or failure
+		code. The failure code will indicate reason for failure.
+  @see
+		pch_phub_pci_init
+		pch_phub_suspend
+  */
+static int pch_phub_resume(struct pci_dev *pdev)
+{
+
+	int ret;
+
+	pci_set_power_state(pdev, PCI_D0);
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+		"pci_set_power_state Invoked successfully\n");
+
+	pci_restore_state(pdev);
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+		"pci_restore_state Invoked successfully\n");
+
+	ret = pci_enable_device(pdev);
+	if (ret) {
+		dev_dbg(dev_dbg, "pch_phub_resume-pci_enable_device failed ");
+		return ret;
+	}
+
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+			"pci_enable_device returns -%d\n", ret);
+
+	pci_enable_wake(pdev, PCI_D3hot, 0);
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+			"pci_enable_wake Invoked successfully\n");
+
+	pch_phub_restore_reg_conf();
+	dev_dbg(dev_dbg, "pch_phub_resume - "
+		"pch_phub_restore_reg_conf Invoked successfully\n");
+
+	pch_phub_suspended = false;
+
+	dev_dbg(dev_dbg, "pch_phub_resume  returns- %d\n", 0);
+	return 0;
+}
+#endif /* CONFIG_PM */
diff --git a/linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h b/linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h
new file mode 100644
index 0000000..009ae1e
--- /dev/null
+++ b/linux-2.6.33.1/drivers/char/pch_phub/pch_phub.h
@@ -0,0 +1,182 @@
+#ifndef __PCH_PHUB_H__
+#define __PCH_PHUB_H__
+/*!
+ * @file pch_phub.h
+ * @brief Provides all the interfaces pertaining to the Packet Hub module.
+ * @version 1.0.0.0
+ * @section
+ * 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.
+ */
+
+/*
+ * History:
+ * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ *
+ * created:
+ *	OKI SEMICONDUCTOR 04/14/2010
+ * modified:
+ *
+ */
+
+/*! @defgroup PHUB */
+/*! @defgroup PHUB_Global  				Global
+  @ingroup PHUB */
+/*! @defgroup PHUB_GlobalGeneral			General
+  @ingroup PHUB_Global */
+/*! @defgroup PHUB_GlobalResultCodes			StatusCodes
+  @ingroup PHUB_Global */
+/*! @defgroup PHUB_InterfaceLayer			InterfaceLayer
+  @ingroup PHUB */
+/*! @defgroup PHUB_InterfaceLayerAPI  			Providers
+  @ingroup PHUB_InterfaceLayer
+  */
+/*! @defgroup PHUB_InterfaceLayerNotifyRoutines  	Notifiers
+  @ingroup PHUB_InterfaceLayer
+  */
+/*! @defgroup PHUB_PCILayer				PCILayer
+  @ingroup PHUB */
+/*! @defgroup PHUB_PCILayerAPI  			Providers
+  @ingroup PHUB_PCILayer
+  */
+/*! @defgroup PHUB_PCILayerFacilitators  		Facilitators
+  @ingroup PHUB_PCILayer
+  */
+/*! @defgroup PHUB_HALLayer				HALLayer
+  @ingroup PHUB */
+/*! @defgroup PHUB_HALLayerAPI  			Providers
+  @ingroup PHUB_HALLayer
+  */
+/*! @defgroup PHUB_HALLayerFacilitators  		Facilitators
+  @ingroup PHUB_HALLayer
+  */
+/*! @defgroup PHUB_Utilities				Utilities
+  @ingroup PHUB */
+/*! @defgroup PHUB_UtilitiesAPI  			Providers
+  @ingroup PHUB_Utilities
+  */
+
+/*! @ingroup PHUB_InterfaceLayer
+  @def PHUB_IOCTL_MAGIC
+  @brief Outlines the ioctl magic.
+  */
+#define PHUB_IOCTL_MAGIC 		(0xf7)
+
+/*! @ingroup PHUB_InterfaceLayer
+  @def IOCTL_PHUB_READ_REG
+  @brief Outlines the read register function signature.
+  */
+#define IOCTL_PHUB_READ_REG (_IOW(PHUB_IOCTL_MAGIC, 1, unsigned long))
+
+/*! @ingroup PHUB_InterfaceLayer
+  @def IOCTL_PHUB_WRITE_REG
+  @brief Outlines the write register function signature.
+  */
+#define IOCTL_PHUB_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 2, unsigned long))
+
+/*! @ingroup PHUB_InterfaceLayer
+  @def IOCTL_PHUB_READ_MODIFY_WRITE_REG
+  @brief Outlines the read, modify and write register function signature.
+  */
+#define IOCTL_PHUB_READ_MODIFY_WRITE_REG (_IOW(PHUB_IOCTL_MAGIC, 3,\
+								 unsigned long))
+
+/*! @ingroup PHUB_InterfaceLayer
+  @def IOCTL_PHUB_READ_OROM
+  @brief Outlines the read option rom function signature.
+  */
+#define IOCTL_PHUB_READ_OROM (_IOW(PHUB_IOCTL_MAGIC, 4, unsigned long))
+
+/*! @ingroup PHUB_InterfaceLayer
+  @def IOCTL_PHUB_WRITE_OROM
+  @brief Outlines the write option rom function signature.
+  */
+#define IOCTL_PHUB_WRITE_OROM (_IOW(PHUB_IOCTL_MAGIC, 5, unsigned long))
+
+/*! @ingroup PHUB_InterfaceLayer
+  @def IOCTL_PHUB_READ_MAC_ADDR
+  @brief Outlines the read mac address function signature.
+  */
+#define IOCTL_PHUB_READ_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 6, unsigned long))
+
+/*! @ingroup PHUB_InterfaceLayer
+  @def IOCTL_PHUB_WRITE_MAC_ADDR
+  @brief Outlines the write mac address function signature.
+  */
+#define IOCTL_PHUB_WRITE_MAC_ADDR (_IOW(PHUB_IOCTL_MAGIC, 7, unsigned long))
+
+
+/* Registers address offset */
+#define PCH_PHUB_PHUB_ID_REG			(0x0000)
+#define PCH_PHUB_QUEUE_PRI_VAL_REG			(0x0004)
+#define PCH_PHUB_RC_QUEUE_MAXSIZE_REG		(0x0008)
+#define PCH_PHUB_BRI_QUEUE_MAXSIZE_REG		(0x000C)
+#define PCH_PHUB_COMP_RESP_TIMEOUT_REG		(0x0010)
+#define PCH_PHUB_BUS_SLAVE_CONTROL_REG		(0x0014)
+#define PCH_PHUB_DEADLOCK_AVOID_TYPE_REG		(0x0018)
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG0		(0x0020)
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG1		(0x0024)
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG2		(0x0028)
+#define PCH_PHUB_INTPIN_REG_WPERMIT_REG3		(0x002C)
+#define PCH_PHUB_INT_REDUCE_CONTROL_REG_BASE	(0x0040)
+#define CLKCFG_REG_OFFSET           		(0x500)
+
+/*structures*/
+/*! @ingroup PHUB_InterfaceLayer
+  @struct pch_phub_reqt
+  @brief It is a structure used for perserving information related to the
+  Packet Hub request.
+  @note
+  The concerned details should be provided during the read register,
+   write register and read / modify / write register.
+  @see
+  pch_phub_ioctl
+  */
+struct pch_phub_reqt {
+	unsigned long addr_offset;	/*specifies the register address
+								 offset */
+	unsigned long data;	/*specifies the data */
+	unsigned long mask;	/*specifies the mask */
+};
+
+/* exported function prototypes */
+/*! @ingroup PHUB_InterfaceLayerAPI
+  @fn nt pch_phub_open( struct inode *inode,struct file *file )
+  @brief  Provides the functionality of initialization of the module
+  */
+int pch_phub_open(struct inode *inode, struct file *file);
+
+/*! @ingroup PHUB_InterfaceLayerAPI
+  @fn int pch_phub_release(struct inode *inode,struct file *file)
+  @brief  Provides the functionality of releasing the module
+  */
+int pch_phub_release(struct inode *inode, struct file *file);
+
+/*! @ingroup PHUB_InterfaceLayerAPI
+  @fn int pch_phub_ioctl(struct inode * inode,struct file * file,
+							 unsigned int cmd,
+  unsigned long arg)
+  @brief  Provides the functionality of invoking various functionalities of
+								 the Packet Hub.
+  */
+int pch_phub_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
+		      unsigned long arg);
+
+/**global variables*/
+extern u32 pch_phub_base_address;	/* base address */
+extern s32 pch_phub_suspended;		/* suspend status */
+
+extern s32 pch_phub_opencount;
+extern spinlock_t pch_phub_lock;
+extern const struct file_operations pch_phub_fops;
+#endif
-- 1.6.2.2 

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

end of thread, other threads:[~2010-07-01  4:09 UTC | newest]

Thread overview: 45+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-07 12:39 [PATCH] Topcliff PHUB: Generate PacketHub driver Masayuki Ohtak
2010-06-07 15:05 ` Alan Cox
2010-06-08  0:19   ` Masayuki Ohtake
2010-06-14 12:09 ` Masayuki Ohtak
2010-06-14 12:50   ` Arnd Bergmann
2010-06-14 23:56     ` Masayuki Ohtake
2010-06-15  6:25     ` Masayuki Ohtake
2010-06-15 10:42       ` Arnd Bergmann
2010-06-15 12:12         ` Masayuki Ohtake
2010-06-17  2:43   ` Masayuki Ohtak
2010-06-17 11:59     ` Arnd Bergmann
2010-06-17 23:49       ` Masayuki Ohtake
2010-06-18  8:08     ` Wang, Yong Y
2010-06-18 11:39       ` Masayuki Ohtake
  -- strict thread matches above, loose matches on Subject: below --
2010-06-22  5:33 Masayuki Ohtak
2010-06-22 10:33 ` Masayuki Ohtak
2010-06-22 22:12   ` Andrew Morton
2010-06-23  0:31     ` Masayuki Ohtake
2010-06-22 11:30 ` Arnd Bergmann
2010-06-22 13:52   ` Yong Wang
2010-06-29 23:31 ` Andy Isaacson
2010-06-30  5:58   ` Masayuki Ohtake
2010-06-30 18:28     ` Andy Isaacson
2010-07-01  4:08       ` Masayuki Ohtake
2010-06-22  2:14 Masayuki Ohtake
2010-06-15  6:58 Masayuki Ohtake
2010-06-15 10:37 ` Arnd Bergmann
2010-06-15 12:14   ` Masayuki Ohtake
2010-06-16  8:58   ` Masayuki Ohtake
2010-06-16 10:50     ` Arnd Bergmann
2010-06-17  0:17       ` Masayuki Ohtake
2010-06-08  5:00 Masayuki Ohtak
2010-06-08  5:46 ` Masayuki Ohtake
2010-06-08  8:01   ` Alan Cox
2010-06-08  7:20 ` Yong Wang
2010-06-08  8:09   ` Masayuki Ohtake
2010-06-08  8:04 ` Alan Cox
2010-06-04 10:16 Masayuki Ohtake
2010-06-04 12:00 ` Alan Cox
2010-06-07  7:53   ` Masayuki Ohtake
2010-06-07 13:37 ` Arnd Bergmann
2010-06-08  0:15   ` Masayuki Ohtake
2010-06-08  8:48   ` Masayuki Ohtake
2010-06-08  9:29     ` Arnd Bergmann
2010-06-09  0:14     ` Wang, Qi

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.