[ofa-general] [PATCH] net/mlx4: modify sw reset

Eli Cohen eli at dev.mellanox.co.il
Wed Apr 25 07:41:39 PDT 2007


Modify SW reset to acquire the HW semaphore before hitting reset. This is
recommended to prevent SW reset of the device while the flash is being
programmed.
Avoid delay after reset - this is not required. Instead, wait until the 
vendor ID is read.

Signed-off-by: Eli Cohen <eli at mellanox.co.il>

---

Index: connectx_kernel/drivers/net/mlx4/reset.c
===================================================================
--- connectx_kernel.orig/drivers/net/mlx4/reset.c	2007-04-25 12:04:23.000000000 +0300
+++ connectx_kernel/drivers/net/mlx4/reset.c	2007-04-25 18:52:16.000000000 +0300
@@ -42,13 +42,18 @@
 {
 	int i;
 	int err = 0;
-	u32 *hca_header = NULL;
+	u32 *hca_header = NULL, sem = 1;
 	int pcie_cap;
+	unsigned long end;
 
-	u16 devctl;
+	u16 devctl, v;
 	u16 linkctl;
+	void __iomem *reset;
 
-#define MLX4_RESET_OFFSET 0xf0010
+#define MLX4_RESET_BASE   0xf0000
+#define MLX4_RESET_SIZE   0x400
+#define MLX4_SEM_OFFSET   0x3fc
+#define MLX4_RESET_OFFSET 0x10
 #define MLX4_RESET_VALUE  swab32(1)
 
 	/*
@@ -80,51 +85,51 @@
 		}
 	}
 
-	/* actually hit reset */
-	{
-		void __iomem *reset = ioremap(pci_resource_start(dev->pdev, 0) +
-					      MLX4_RESET_OFFSET, 4);
-
-		if (!reset) {
-			err = -ENOMEM;
-			mlx4_err(dev, "Couldn't map HCA reset register, "
-				  "aborting.\n");
-			goto out;
-		}
+	reset = ioremap(pci_resource_start(dev->pdev, 0) + MLX4_RESET_BASE, MLX4_RESET_SIZE);
+	if (!reset) {
+		err = -ENOMEM;
+		mlx4_err(dev, "Couldn't map HCA reset register, aborting.\n");
+		goto out;
+	}
 
-		writel(MLX4_RESET_VALUE, reset);
-		iounmap(reset);
+	/* grab the semaphore */
+	end = jiffies + 10 * HZ;
+	while (time_before(jiffies, end)) {
+		sem = readl(reset + MLX4_SEM_OFFSET);
+		if (!sem)
+			break;
+
+		set_current_state(TASK_RUNNING);
+		schedule();
 	}
 
-	/* Docs say to wait one second before accessing device */
-	msleep(1000);
+	if (sem) {
+		mlx4_err(dev, "failed to obtain semaphore, aborting\n");
+		err = -EAGAIN;
+		iounmap(reset);
+		goto out;
+	}
+	/* actually hit reset - hw sem is released after reset */
+	writel(MLX4_RESET_VALUE, reset + MLX4_RESET_OFFSET);
+	iounmap(reset);
 
 	/* Now wait for PCI device to start responding again */
-	{
-		u32 v;
-		int c = 0;
-
-		for (c = 0; c < 100; ++c) {
-			if (pci_read_config_dword(dev->pdev, 0, &v)) {
-				err = -ENODEV;
-				mlx4_err(dev, "Couldn't access HCA after reset, "
-					  "aborting.\n");
-				goto out;
-			}
-
-			if (v != 0xffffffff)
-				goto good;
+	end = jiffies + 2 * HZ;
+	while (time_before(jiffies, end)) {
+		if (!pci_read_config_word(dev->pdev, 0, &v) &&
+		    (v == PCI_VENDOR_ID_MELLANOX))
+				break;
 
-			msleep(100);
-		}
+		set_current_state(TASK_RUNNING);
+		schedule();
+	}
 
+	if (pci_read_config_word(dev->pdev, 0, &v) || v != PCI_VENDOR_ID_MELLANOX) {
+		mlx4_err(dev, "Couldn't read vendor ID after reset, aborting.\n");
 		err = -ENODEV;
-		mlx4_err(dev, "PCI device did not come back after reset, "
-			  "aborting.\n");
 		goto out;
 	}
 
-good:
 	/* Now restore the PCI headers */
 	if (pcie_cap) {
 		devctl = hca_header[(pcie_cap + PCI_EXP_DEVCTL) / 4];





More information about the general mailing list