[ewg] [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 ewg
mailing list