[ofa-general] [PATCH 2/10] nes: add support for external flash update utility

Glenn Grundstrom NetEffect glenn at lists.openfabrics.org
Thu Dec 20 12:24:20 PST 2007


Allows an external utility to read/write flash for
firmware upgrades.

Signed-off-by: Glenn Grundstrom <ggrundstrom at neteffect.com>

---

diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c
index a5e0bb5..1088330 100644
--- a/drivers/infiniband/hw/nes/nes.c
+++ b/drivers/infiniband/hw/nes/nes.c
@@ -780,6 +780,136 @@ static struct pci_driver nes_pci_driver = {
 	.remove = __devexit_p(nes_remove),
 };
 
+static ssize_t nes_show_ee_cmd(struct device_driver *ddp, char *buf)
+{
+	u32 eeprom_cmd;
+	struct nes_device *nesdev;
+
+	nesdev = list_entry(nes_dev_list.next, typeof(*nesdev), list);
+	eeprom_cmd = nes_read32(nesdev->regs + NES_EEPROM_COMMAND);
+
+	return snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_cmd);
+}
+
+static ssize_t nes_store_ee_cmd(struct device_driver *ddp,
+	const char *buf, size_t count)
+{
+	char *p = (char *)buf;
+	u32 val;
+	struct nes_device *nesdev;
+
+	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+		val = simple_strtoul(p, &p, 16);
+		nesdev = list_entry(nes_dev_list.next, typeof(*nesdev), list);
+		nes_write32(nesdev->regs + NES_EEPROM_COMMAND, val);
+	}
+	return strnlen(buf, count);
+}
+
+static ssize_t nes_show_ee_data(struct device_driver *ddp, char *buf)
+{
+	u32 eeprom_data;
+	struct nes_device *nesdev;
+
+	nesdev = list_entry(nes_dev_list.next, typeof(*nesdev), list);
+	eeprom_data = nes_read32(nesdev->regs + NES_EEPROM_DATA);
+
+	return  snprintf(buf, PAGE_SIZE, "0x%x\n", eeprom_data);
+}
+
+static ssize_t nes_store_ee_data(struct device_driver *ddp,
+	const char *buf, size_t count)
+{
+	char *p = (char *)buf;
+	u32 val;
+	struct nes_device *nesdev;
+
+	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+		val = simple_strtoul(p, &p, 16);
+		nesdev = list_entry(nes_dev_list.next, typeof(*nesdev), list);
+		nes_write32(nesdev->regs + NES_EEPROM_DATA, val);
+	}
+	return strnlen(buf, count);
+}
+
+static ssize_t nes_show_flash_cmd(struct device_driver *ddp, char *buf)
+{
+	u32 flash_cmd;
+	struct nes_device *nesdev;
+
+	nesdev = list_entry(nes_dev_list.next, typeof(*nesdev), list);
+	flash_cmd = nes_read32(nesdev->regs + NES_FLASH_COMMAND);
+
+	return  snprintf(buf, PAGE_SIZE, "0x%x\n", flash_cmd);
+}
+
+static ssize_t nes_store_flash_cmd(struct device_driver *ddp,
+	const char *buf, size_t count)
+{
+	char *p = (char *)buf;
+	u32 val;
+	struct nes_device *nesdev;
+
+	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+		val = simple_strtoul(p, &p, 16);
+		nesdev = list_entry(nes_dev_list.next, typeof(*nesdev), list);
+		nes_write32(nesdev->regs + NES_FLASH_COMMAND, val);
+	}
+	return strnlen(buf, count);
+}
+
+static ssize_t nes_show_flash_data(struct device_driver *ddp, char *buf)
+{
+	u32 flash_data;
+	struct nes_device *nesdev;
+
+	nesdev = list_entry(nes_dev_list.next, typeof(*nesdev), list);
+	flash_data = nes_read32(nesdev->regs + NES_FLASH_DATA);
+
+	return  snprintf(buf, PAGE_SIZE, "0x%x\n", flash_data);
+}
+
+static ssize_t nes_store_flash_data(struct device_driver *ddp,
+	const char *buf, size_t count)
+{
+	char *p = (char *)buf;
+	u32 val;
+	struct nes_device *nesdev;
+
+	if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') {
+		val = simple_strtoul(p, &p, 16);
+		nesdev = list_entry(nes_dev_list.next, typeof(*nesdev), list);
+		nes_write32(nesdev->regs + NES_FLASH_DATA, val);
+	}
+	return strnlen(buf, count);
+}
+
+DRIVER_ATTR(eeprom_cmd, S_IRUSR | S_IWUSR,
+	nes_show_ee_cmd, nes_store_ee_cmd);
+DRIVER_ATTR(eeprom_data, S_IRUSR | S_IWUSR,
+	nes_show_ee_data, nes_store_ee_data);
+DRIVER_ATTR(flash_cmd, S_IRUSR | S_IWUSR,
+	nes_show_flash_cmd, nes_store_flash_cmd);
+DRIVER_ATTR(flash_data, S_IRUSR | S_IWUSR,
+	nes_show_flash_data, nes_store_flash_data);
+
+int nes_create_driver_sysfs(struct pci_driver *drv)
+{
+	int error;
+	error  = driver_create_file(&drv->driver, &driver_attr_eeprom_cmd);
+	error |= driver_create_file(&drv->driver, &driver_attr_eeprom_data);
+	error |= driver_create_file(&drv->driver, &driver_attr_flash_cmd);
+	error |= driver_create_file(&drv->driver, &driver_attr_flash_data);
+	return error;
+}
+
+void nes_remove_driver_sysfs(struct pci_driver *drv)
+{
+	driver_remove_file(&drv->driver, &driver_attr_eeprom_cmd);
+	driver_remove_file(&drv->driver, &driver_attr_eeprom_data);
+	driver_remove_file(&drv->driver, &driver_attr_flash_cmd);
+	driver_remove_file(&drv->driver, &driver_attr_flash_data);
+}
 
 /**
  * nes_init_module - module initialization entry point
@@ -787,12 +917,20 @@ static struct pci_driver nes_pci_driver = {
 static int __init nes_init_module(void)
 {
 	int retval;
+	int retval1;
+
 	retval = nes_cm_start();
 	if (retval) {
 		printk(KERN_ERR PFX "Unable to start NetEffect iWARP CM.\n");
 		return retval;
 	}
-	return pci_register_driver(&nes_pci_driver);
+	retval = pci_register_driver(&nes_pci_driver);
+	if (retval >= 0) {
+		retval1 = nes_create_driver_sysfs(&nes_pci_driver);
+		if (retval1 < 0)
+			printk(KERN_ERR PFX "Unable to create NetEffect sys files.\n");
+	}
+	return retval;
 }
 
 
@@ -802,6 +940,8 @@ static int __init nes_init_module(void)
 static void __exit nes_exit_module(void)
 {
 	nes_cm_stop();
+	nes_remove_driver_sysfs(&nes_pci_driver);
+
 	pci_unregister_driver(&nes_pci_driver);
 }
 
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index 178f3d5..25cfda2 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -49,6 +49,8 @@ enum pci_regs {
 	NES_ONE_SHOT_CONTROL = 0x001C,
 	NES_EEPROM_COMMAND = 0x0020,
 	NES_EEPROM_DATA = 0x0024,
+	NES_FLASH_COMMAND = 0x0028,
+	NES_FLASH_DATA  = 0x002C,
 	NES_SOFTWARE_RESET = 0x0030,
 	NES_CQ_ACK = 0x0034,
 	NES_WQE_ALLOC = 0x0040,



More information about the general mailing list