From a079c57bb891b164cba8a70517ed647d0891d697 Mon Sep 17 00:00:00 2001 From: Alessandro Rubini <rubini@gnudd.com> Date: Wed, 1 Aug 2012 21:57:55 +0200 Subject: [PATCH] fmc_operations: use a different reprogram --- doc/fmc-bus.in | 11 ++++++----- kernel/fmc-trivial.c | 25 ++++--------------------- kernel/include/linux/fmc.h | 2 +- kernel/spec-fmc.c | 29 +++++++++++++++++++++++++++-- kernel/wr-nic-core.c | 33 +++++++++++---------------------- 5 files changed, 49 insertions(+), 51 deletions(-) diff --git a/doc/fmc-bus.in b/doc/fmc-bus.in index e06666b..7ce826b 100644 --- a/doc/fmc-bus.in +++ b/doc/fmc-bus.in @@ -184,7 +184,7 @@ this document): struct fmc_operations { uint32_t (*readl)(struct fmc_device *fmc, int offset); void (*writel)(struct fmc_device *fmc, uint32_t value, int offset); - int (*reprogram)(struct fmc_device *fmc, void *data, int len); + int (*reprogram)(struct fmc_device *fmc, char *gateware); int (*irq_request)(struct fmc_device *fmc, irq_handler_t h, char *name, int flags); void (*irq_ack)(struct fmc_device *fmc); @@ -214,10 +214,11 @@ The individual methods perform the following tasks: The carrier enumerates FMC devices by loading a standard (or @i{golden} FPGA binary that allows EEPROM access. Each driver, then, - will need to reprogram the FPGA for its own use by calling this - function. If @i{reprogram} is called with NULL arguments, the - carrier will reprogram the golden binary -- which will happen - after @i{remove} time in any case. + will need to reprogram the FPGA by calling this + function. If the name argument is NULL, + the carrier will reprogram the golden binary. If the gateware name + has been overridden through module parameters (in a carrier-specific + way) the file loaded will match the parameters. @item irq_request @itemx irq_ack diff --git a/kernel/fmc-trivial.c b/kernel/fmc-trivial.c index ea5f5d5..7f6694e 100644 --- a/kernel/fmc-trivial.c +++ b/kernel/fmc-trivial.c @@ -2,7 +2,6 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/firmware.h> #include <linux/fmc.h> #include "spec.h" @@ -21,31 +20,15 @@ irqreturn_t t_handler(int irq, void *dev_id) int t_probe(struct fmc_device *fmc) { int ret; - struct device *dev = fmc->hwdev; ret = fmc->op->irq_request(fmc, t_handler, "fmc-trivial", 0); if (ret < 0) return ret; - if (t_filename) { - const struct firmware *fw; - - ret = request_firmware(&fw, t_filename, dev); - if (ret < 0) { - dev_warn(dev, "request firmware \"%s\": error %i\n", - t_filename, ret); - ret = 0; /* not fatal */ - } else { - ret = fmc->op->reprogram(fmc, (void *)fw->data, - fw->size); - } - if (ret <0) { - dev_err(dev, "write firmware \"%s\": error %i\n", - t_filename, ret); - ret = 0; /* not fatal, either (lazy me) */ - } - release_firmware(fw); - } + /* Reprogram, but only if specified in the arguments */ + ret = fmc->op->reprogram(fmc, ""); + if (ret < 0) + fmc->op->irq_free(fmc); return ret; } diff --git a/kernel/include/linux/fmc.h b/kernel/include/linux/fmc.h index 2c6109b..cd1863d 100644 --- a/kernel/include/linux/fmc.h +++ b/kernel/include/linux/fmc.h @@ -36,7 +36,7 @@ struct fmc_driver { struct fmc_operations { uint32_t (*readl)(struct fmc_device *fmc, int offset); void (*writel)(struct fmc_device *fmc, uint32_t value, int offset); - int (*reprogram)(struct fmc_device *fmc, void *data, int len); + int (*reprogram)(struct fmc_device *fmc, char *gateware); int (*irq_request)(struct fmc_device *fmc, irq_handler_t h, char *name, int flags); void (*irq_ack)(struct fmc_device *fmc); diff --git a/kernel/spec-fmc.c b/kernel/spec-fmc.c index 5f327fc..55ec26e 100644 --- a/kernel/spec-fmc.c +++ b/kernel/spec-fmc.c @@ -18,11 +18,36 @@ module_param_named(test_irq, spec_test_irq, int, 0444); /* The main role of this file is offering the fmc_operations for the spec */ -static int spec_reprogram(struct fmc_device *fmc, void *data, int len) +static int spec_reprogram(struct fmc_device *fmc, char *gw) { struct spec_dev *spec = fmc->carrier_data; + const struct firmware *fw; + struct device *dev = fmc->hwdev; + int ret; + + if (!gw) + return 0; + + if (!strlen(gw)) { + /* FIXME: use module parameters */ + return 0; + } - return spec_load_fpga(spec, data, len); /* spec-pci.c */ + ret = request_firmware(&fw, gw, dev); + if (ret < 0) { + dev_warn(dev, "request firmware \"%s\": error %i\n", gw, ret); + goto out; + } + ret = spec_load_fpga(spec, fw->data, fw->size); + if (ret <0) { + dev_err(dev, "write firmware \"%s\": error %i\n", gw, ret); + goto out; + } + + /* FIXME: load lm32 */ +out: + release_firmware(fw); + return ret; } static int spec_irq_request(struct fmc_device *fmc, irq_handler_t handler, diff --git a/kernel/wr-nic-core.c b/kernel/wr-nic-core.c index 06ac48b..98d0857 100644 --- a/kernel/wr-nic-core.c +++ b/kernel/wr-nic-core.c @@ -10,7 +10,6 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> -#include <linux/firmware.h> #include <linux/fmc.h> #include <linux/fmc-sdb.h> #include "wr-nic.h" @@ -32,7 +31,6 @@ int wrn_probe(struct fmc_device *fmc) { int ret = 0; struct device *dev = fmc->hwdev; - const struct firmware *fw; struct wrn_drvdata *dd; /* Driver data */ @@ -41,41 +39,34 @@ int wrn_probe(struct fmc_device *fmc) return -ENOMEM; fmc_set_drvdata(fmc, dd); - /* We first write a new binary within the spec */ - if (wrn_filename) { - - ret = request_firmware(&fw, wrn_filename, dev); - if (ret < 0) { - dev_warn(dev, "request firmware \"%s\": error %i\n", - wrn_filename, ret); - goto out; - } - ret = fmc->op->reprogram(fmc, (void *)fw->data, fw->size); - if (ret <0) { - dev_err(dev, "write firmware \"%s\": error %i\n", - wrn_filename, ret); - goto out_fw; - } + /* We first write a new binary (and lm32) within the spec */ + ret = fmc->op->reprogram(fmc, WRN_GATEWARE_DEFAULT_NAME); + if (ret <0) { + dev_err(dev, "write firmware \"%s\": error %i\n", + wrn_filename, ret); + goto out; } /* Verify that we have SDB at offset 0x63000 */ if (fmc_readl(fmc, 0x63000) != 0x5344422d) { dev_err(dev, "Can't find SDB magic\n"); ret = -ENODEV; - goto out_fw; + goto out; } dev_info(dev, "Gateware successfully loaded\n"); if ( (ret = fmc_scan_sdb_tree(fmc, 0x63000)) < 0) { dev_err(dev, "scan fmc failed %i\n", ret); - goto out_fw; + goto out; } fmc_show_sdb_tree(fmc); + /* FIXME: load lm32 */ + /* Register the gpio stuff, if we have kernel support */ ret = wrn_gpio_init(fmc); if (ret < 0) - goto out_fw; + goto out; /* The netword device */ ret = wrn_eth_init(fmc); @@ -94,8 +85,6 @@ out_nic: wrn_eth_exit(fmc); out_gpio: wrn_gpio_exit(fmc); -out_fw: - release_firmware(fw); out: return ret; } -- GitLab