[dahdi-commits] dahdi/linux.git branch "master" updated.

SVN commits to the DAHDI project dahdi-commits at lists.digium.com
Fri Jan 24 15:55:17 CST 2014


branch "master" has been updated
       via  3efa9d8cd1f65f1cf524a041cf68a87df44c1080 (commit)
      from  4cd09feb54c97148e8792a393396f3fc31744372 (commit)

Summary of changes:
 drivers/dahdi/wcaxx-base.c    |    2 +-
 drivers/dahdi/wcte13xp-base.c |   35 +++++++++++++--------
 drivers/dahdi/wcte43x-base.c  |    2 +-
 drivers/dahdi/wcxb.c          |   68 +++++++++++++++++++++++++++++++++--------
 drivers/dahdi/wcxb.h          |   10 +++++-
 5 files changed, 90 insertions(+), 27 deletions(-)


- Log -----------------------------------------------------------------
commit 3efa9d8cd1f65f1cf524a041cf68a87df44c1080
Author: Russ Meyerriecks <rmeyerriecks at digium.com>
Date:   Wed Dec 11 16:46:36 2013 -0600

    wcte13xp: wcxb: Add delayed reset firmware feature
    
    Allow certain older firmwares to delay the hard reset until a full power cycle.
    This way we can "preload" newer firmware images, without requiring the user to
    physically power off/on their machine.
    
    Signed-off-by: Russ Meyerriecks <rmeyerriecks at digium.com>
    Acked-by: Shaun Ruffell <sruffell at digium.com>

diff --git a/drivers/dahdi/wcaxx-base.c b/drivers/dahdi/wcaxx-base.c
index c17f1bc..d90f014 100644
--- a/drivers/dahdi/wcaxx-base.c
+++ b/drivers/dahdi/wcaxx-base.c
@@ -3909,7 +3909,7 @@ static int wcaxx_check_firmware(struct wcaxx *wc)
 	}
 
 	return wcxb_check_firmware(&wc->xb, firmware_version,
-				   filename, force_firmware);
+				   filename, force_firmware, WCXB_RESET_NOW);
 }
 
 static void wcaxx_check_sethook(struct wcaxx *wc, struct wcaxx_module *mod)
diff --git a/drivers/dahdi/wcte13xp-base.c b/drivers/dahdi/wcte13xp-base.c
index 726a63c..5c61309 100644
--- a/drivers/dahdi/wcte13xp-base.c
+++ b/drivers/dahdi/wcte13xp-base.c
@@ -2431,6 +2431,26 @@ error_exit:
 	return serial;
 }
 
+static int te13xp_check_firmware(struct t13x *wc)
+{
+	const char *filename;
+	enum wcxb_reset_option reset;
+
+	if (is_pcie(wc))
+		filename = TE133_FW_FILENAME;
+	else
+		filename = TE134_FW_FILENAME;
+
+	/* Specific firmware requires power cycle to properly reset */
+	if (0x6f0017 == wcxb_get_firmware_version(&wc->xb))
+		reset = WCXB_RESET_LATER;
+	else
+		reset = WCXB_RESET_NOW;
+
+	return wcxb_check_firmware(&wc->xb, TE13X_FW_VERSION, filename,
+			force_firmware, reset);
+}
+
 static int __devinit te13xp_init_one(struct pci_dev *pdev,
 		const struct pci_device_id *ent)
 {
@@ -2513,18 +2533,9 @@ static int __devinit te13xp_init_one(struct pci_dev *pdev,
 	if (res)
 		goto fail_exit;
 
-	/* Check for field updatable firmware */
-	if (is_pcie(wc)) {
-		res = wcxb_check_firmware(&wc->xb, TE13X_FW_VERSION,
-				TE133_FW_FILENAME, force_firmware);
-		if (res)
-			goto fail_exit;
-	} else {
-		res = wcxb_check_firmware(&wc->xb, TE13X_FW_VERSION,
-				TE134_FW_FILENAME, force_firmware);
-		if (res)
-			goto fail_exit;
-	}
+	res = te13xp_check_firmware(wc);
+	if (res)
+		goto fail_exit;
 
 	wc->ddev->hardware_id = t13x_read_serial(wc);
 	if (!wc->ddev->hardware_id) {
diff --git a/drivers/dahdi/wcte43x-base.c b/drivers/dahdi/wcte43x-base.c
index af7b787..a285fa2 100644
--- a/drivers/dahdi/wcte43x-base.c
+++ b/drivers/dahdi/wcte43x-base.c
@@ -3357,7 +3357,7 @@ static int __devinit t43x_init_one(struct pci_dev *pdev,
 
 	/* Check for field updatable firmware */
 	res = wcxb_check_firmware(&wc->xb, TE435_VERSION,
-			TE435_FW_FILENAME, force_firmware);
+			TE435_FW_FILENAME, force_firmware, WCXB_RESET_NOW);
 	if (res)
 		goto fail_exit;
 
diff --git a/drivers/dahdi/wcxb.c b/drivers/dahdi/wcxb.c
index 5ae5325..3373723 100644
--- a/drivers/dahdi/wcxb.c
+++ b/drivers/dahdi/wcxb.c
@@ -792,7 +792,7 @@ struct wcxb_firm_header {
 	__le32	version;
 } __packed;
 
-static u32 wcxb_get_firmware_version(struct wcxb *xb)
+u32 wcxb_get_firmware_version(struct wcxb *xb)
 {
 	u32 version = 0;
 
@@ -807,7 +807,8 @@ static u32 wcxb_get_firmware_version(struct wcxb *xb)
 }
 
 static int wcxb_update_firmware(struct wcxb *xb, const struct firmware *fw,
-				const char *filename)
+				const char *filename,
+				enum wcxb_reset_option reset)
 {
 	u32 tdm_control;
 	static const int APPLICATION_ADDRESS = 0x200000;
@@ -859,14 +860,20 @@ static int wcxb_update_firmware(struct wcxb *xb, const struct firmware *fw,
 			 APPLICATION_ADDRESS + META_BLOCK_OFFSET,
 			 &meta, sizeof(meta));
 
-	/* Reset fpga after loading firmware */
-	dev_info(&xb->pdev->dev, "Firmware load complete. Reseting device.\n");
-	tdm_control = ioread32be(xb->membase + TDM_CONTROL);
+	if (WCXB_RESET_NOW == reset) {
+		/* Reset fpga after loading firmware */
+		dev_info(&xb->pdev->dev,
+				"Firmware load complete. Reseting device.\n");
+		tdm_control = ioread32be(xb->membase + TDM_CONTROL);
 
-	wcxb_hard_reset(xb);
+		wcxb_hard_reset(xb);
 
-	iowrite32be(0, xb->membase + 0x04);
-	iowrite32be(tdm_control, xb->membase + TDM_CONTROL);
+		iowrite32be(0, xb->membase + 0x04);
+		iowrite32be(tdm_control, xb->membase + TDM_CONTROL);
+	} else {
+		dev_info(&xb->pdev->dev,
+			"Delaying reset. Firmware load requires a power cycle\n");
+	}
 
 	wcxb_spi_device_destroy(flash_spi_device);
 	wcxb_spi_master_destroy(flash_spi_master);
@@ -874,10 +881,16 @@ static int wcxb_update_firmware(struct wcxb *xb, const struct firmware *fw,
 }
 
 int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
-			const char *firmware_filename, bool force_firmware)
+			const char *firmware_filename, bool force_firmware,
+			enum wcxb_reset_option reset)
 {
 	const struct firmware *fw;
 	const struct wcxb_firm_header *header;
+	static const int APPLICATION_ADDRESS = 0x200000;
+	static const int META_BLOCK_OFFSET   = 0x170000;
+	struct wcxb_spi_master *flash_spi_master;
+	struct wcxb_spi_device *flash_spi_device;
+	struct wcxb_meta_block meta;
 	int res = 0;
 	u32 crc;
 	u32 version = 0;
@@ -896,6 +909,27 @@ int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
 		return 0;
 	}
 
+	/* Check meta firmware version for a not-booted application image */
+	flash_spi_master = wcxb_spi_master_create(&xb->pdev->dev,
+						  xb->membase + FLASH_SPI_BASE,
+						  false);
+	flash_spi_device = wcxb_spi_device_create(flash_spi_master, 0);
+	res = wcxb_flash_read(flash_spi_device,
+			APPLICATION_ADDRESS + META_BLOCK_OFFSET,
+			&meta, sizeof(meta));
+	if (res) {
+		dev_info(&xb->pdev->dev, "Unable to read flash\n");
+		return -EIO;
+	}
+
+	if ((meta.version == cpu_to_le32(expected_version))
+			&& !force_firmware) {
+		dev_info(&xb->pdev->dev,
+			"Detected previous firmware updated to current version %x, but not running. You likely need to power cycle your system.\n",
+			expected_version);
+		return 0;
+	}
+
 	if (force_firmware) {
 		dev_info(&xb->pdev->dev,
 			"force_firmware module parameter is set. Forcing firmware load, regardless of version\n");
@@ -938,12 +972,22 @@ int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
 	dev_info(&xb->pdev->dev, "Found %s (version: %x) Preparing for flash\n",
 				firmware_filename, header->version);
 
-	res = wcxb_update_firmware(xb, fw, firmware_filename);
+	res = wcxb_update_firmware(xb, fw, firmware_filename, reset);
 
 	version = wcxb_get_firmware_version(xb);
-	dev_info(&xb->pdev->dev, "Reset into firmware version: %x\n", version);
+	if (WCXB_RESET_NOW == reset) {
+		dev_info(&xb->pdev->dev,
+			"Reset into firmware version: %x\n", version);
+	} else {
+		dev_info(&xb->pdev->dev,
+			"Running firmware version: %x\n", version);
+		dev_info(&xb->pdev->dev,
+			"Loaded firmware version: %x (Will load after next power cycle)\n",
+			header->version);
+	}
 
-	if ((expected_version != version) && !force_firmware) {
+	if ((WCXB_RESET_NOW == reset) && (expected_version != version)
+			&& !force_firmware) {
 		/* On the off chance that the interface is in a state where it
 		 * cannot boot into the updated firmware image, power cycling
 		 * the card can recover. A simple "reset" of the computer is not
diff --git a/drivers/dahdi/wcxb.h b/drivers/dahdi/wcxb.h
index 268e6c2..af7828b 100644
--- a/drivers/dahdi/wcxb.h
+++ b/drivers/dahdi/wcxb.h
@@ -105,9 +105,17 @@ static inline void wcxb_disable_timing_header_driver(struct wcxb *xb)
 	xb->flags.drive_timing_cable = 0;
 }
 
+enum wcxb_reset_option {
+	WCXB_RESET_NOW,
+	WCXB_RESET_LATER
+};
+
+extern u32 wcxb_get_firmware_version(struct wcxb *xb);
 extern int wcxb_check_firmware(struct wcxb *xb, const u32 expected_version,
 			       const char *firmware_filename,
-			       bool force_firmware);
+			       bool force_firmware,
+			       enum wcxb_reset_option reset);
+
 extern void wcxb_stop_dma(struct wcxb *xb);
 extern void wcxb_disable_interrupts(struct wcxb *xb);
 

-----------------------------------------------------------------------


-- 
dahdi/linux.git



More information about the dahdi-commits mailing list