[Skiboot] [PATCH 07/10] fsi-master: Refactor the driver

Benjamin Herrenschmidt benh at kernel.crashing.org
Tue Jun 23 14:25:57 AEST 2015


Move the various base addresses etc... in a per-instance struct mfsi
which simplifies the code and will make it easier to add subsequent
error handling improvements.

Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
 hw/fsi-master.c | 240 ++++++++++++++++++++++++++++++++------------------------
 include/chip.h  |   4 +
 2 files changed, 141 insertions(+), 103 deletions(-)

diff --git a/hw/fsi-master.c b/hw/fsi-master.c
index b8e5d6b..f2efd01 100644
--- a/hw/fsi-master.c
+++ b/hw/fsi-master.c
@@ -64,64 +64,75 @@
 #define hMFSI_OPB_REG_BASE	0x03400
 #define MFSI_OPB_PORT_STRIDE	0x08000
 
-
+struct mfsi {
+	uint32_t chip_id;
+	uint32_t unit;
+	uint32_t xscom_base;
+	uint32_t port_base;
+	uint32_t reg_base;
+	uint32_t err_bits;
+};
+
+#define mfsi_log(__lev, __m, __fmt, ...) \
+	prlog(__lev, "MFSI %x:%x: " __fmt, __m->chip_id, __m->unit, ##__VA_ARGS__)
 /*
  * Use a global FSI lock for now. Beware of re-entrancy
  * if we ever add support for normal chip XSCOM via FSI, in
  * which case we'll probably have to consider either per chip
  * lock (which can have AB->BA deadlock issues) or a re-entrant
- * global lock
+ * global lock or something else. ...
  */
 static struct lock fsi_lock = LOCK_UNLOCKED;
-static uint32_t mfsi_valid_err;
 
 /*
  * OPB accessors
  */
 
-#define MFSI_OPB_MAX_TRIES	120
+/* We try up to 1.2ms for an OPB access */
+#define MFSI_OPB_MAX_TRIES	1200
 
-static int64_t mfsi_pib2opb_reset(uint32_t chip, uint32_t xscom_base)
+static int64_t mfsi_pib2opb_reset(struct mfsi *mfsi)
 {
 	uint64_t stat;
 	int64_t rc;
 
-	rc = xscom_write(chip, xscom_base + PIB2OPB_REG_RESET, (1ul << 63));
+	rc = xscom_write(mfsi->chip_id,
+			 mfsi->xscom_base + PIB2OPB_REG_RESET, (1ul << 63));
 	if (rc) {
-		prerror("MFSI: XSCOM error %lld resetting PIB2OPB\n", rc);
+		mfsi_log(PR_ERR, mfsi, "XSCOM error %lld resetting PIB2OPB\n", rc);
 		return rc;
 	}
-	rc = xscom_write(chip, xscom_base + PIB2OPB_REG_STAT, (1ul << 63));
+	rc = xscom_write(mfsi->chip_id,
+			 mfsi->xscom_base + PIB2OPB_REG_STAT, (1ul << 63));
 	if (rc) {
-		prerror("MFSI: XSCOM error %lld resetting status\n", rc);
+		mfsi_log(PR_ERR, mfsi, "XSCOM error %lld resetting status\n", rc);
 		return rc;
 	}
-	rc = xscom_read(chip, xscom_base + PIB2OPB_REG_STAT, &stat);
+	rc = xscom_read(mfsi->chip_id,
+			mfsi->xscom_base + PIB2OPB_REG_STAT, &stat);
 	if (rc) {
-		prerror("MFSI: XSCOM error %lld reading status\n", rc);
+		mfsi_log(PR_ERR, mfsi, "XSCOM error %lld reading status\n", rc);
 		return rc;
 	}
 	return 0;
 }
 
 
-static int64_t mfsi_handle_opb_error(uint32_t chip, uint32_t xscom_base,
-				     uint32_t stat, uint32_t err_bits)
+static int64_t mfsi_handle_opb_error(struct mfsi *mfsi, uint32_t stat)
 {
-	prerror("MFSI: Error status=0x%08x (raw=0x%08x) !\n",
-		stat & err_bits, stat);
+	mfsi_log(PR_ERR, mfsi, "MFSI: Error status=0x%08x (raw=0x%08x)\n",
+		 stat & mfsi->err_bits, stat);
 
 	/* For now, just reset the PIB2OPB on error. We should collect more
 	 * info and look at the remote errors in the target as well but that
 	 * will be for another day.
 	 */
-	mfsi_pib2opb_reset(chip, xscom_base);
+	mfsi_pib2opb_reset(mfsi);
 	
 	return OPAL_HARDWARE;
 }
 
-static int64_t mfsi_opb_poll(uint32_t chip, uint32_t xscom_base,
-			     uint32_t *read_data, uint32_t err_bits)
+static int64_t mfsi_opb_poll(struct mfsi *mfsi, uint32_t *read_data)
 {
 	unsigned long retries = MFSI_OPB_MAX_TRIES;
 	uint64_t sval;
@@ -131,13 +142,13 @@ static int64_t mfsi_opb_poll(uint32_t chip, uint32_t xscom_base,
 	/* We try again every 10us for a bit more than 1ms */
 	for (;;) {
 		/* Read OPB status register */
-		rc = xscom_read(chip, xscom_base + PIB2OPB_REG_STAT, &sval);
+		rc = xscom_read(mfsi->chip_id, mfsi->xscom_base + PIB2OPB_REG_STAT, &sval);
 		if (rc) {
 			/* Do something here ? */
-			prerror("MFSI: XSCOM error %lld read OPB STAT\n", rc);
+			mfsi_log(PR_ERR, mfsi, "XSCOM error %lld read OPB STAT\n", rc);
 			return rc;
 		}
-		prlog(PR_INSANE, "  STAT=0x%16llx...\n", sval);
+		mfsi_log(PR_INSANE, mfsi, "  STAT=0x%16llx...\n", sval);
 
 		stat = sval >> 32;
 
@@ -146,21 +157,22 @@ static int64_t mfsi_opb_poll(uint32_t chip, uint32_t xscom_base,
 			break;
 		if (retries-- == 0) {
 			/* XXX What should we do here ? reset it ? */
-			prerror("MFSI: OPB POLL timeout !\n");
+			mfsi_log(PR_ERR, mfsi, "OPB POLL timeout !\n");
 			return OPAL_HARDWARE;
 		}
-		time_wait_us(10);
+		time_wait_us(1);
 	}
 
 	/* Did we have an error ? */
-	if (stat & err_bits)
-		 return mfsi_handle_opb_error(chip, xscom_base, stat, err_bits);
+	if (stat & mfsi->err_bits)
+		return mfsi_handle_opb_error(mfsi, stat);
 
 	if (read_data) {
 		if (!(stat & OPB_STAT_READ_VALID)) {
-			prerror("MFSI: Read successful but no data !\n");
+			mfsi_log(PR_ERR, mfsi, "Read successful but no data !\n");
+
 			/* What do do here ? can it actually happen ? */
-			sval |= 0xffffffff;
+			sval = 0xffffffff;
 		}
 		*read_data = sval & 0xffffffff;
 	}
@@ -168,135 +180,142 @@ static int64_t mfsi_opb_poll(uint32_t chip, uint32_t xscom_base,
 	return OPAL_SUCCESS;
 }
 
-static int64_t mfsi_opb_read(uint32_t chip, uint32_t xscom_base,
-			     uint32_t addr, uint32_t *data,
-			     uint32_t err_bits)
+static int64_t mfsi_opb_read(struct mfsi *mfsi, uint32_t opb_addr, uint32_t *data)
 {
 	uint64_t opb_cmd = OPB_CMD_READ | OPB_CMD_32BIT;
 	int64_t rc;
 
-	if (addr > 0x00ffffff)
+	if (opb_addr > 0x00ffffff)
 		return OPAL_PARAMETER;
 
-	opb_cmd |= addr;
+	opb_cmd |= opb_addr;
 	opb_cmd <<= 32;
 
-	prlog(PR_INSANE, "MFSI_OPB_READ: Writing 0x%16llx to XSCOM %x\n",
-	      opb_cmd, xscom_base);
+	mfsi_log(PR_INSANE, mfsi, "MFSI_OPB_READ: Writing 0x%16llx to XSCOM %x\n",
+		 opb_cmd, mfsi->xscom_base);
 
-	rc = xscom_write(chip, xscom_base + PIB2OPB_REG_CMD, opb_cmd);
+	rc = xscom_write(mfsi->chip_id, mfsi->xscom_base + PIB2OPB_REG_CMD, opb_cmd);
 	if (rc) {
-		prerror("MFSI: XSCOM error %lld writing OPB CMD\n", rc);
+		mfsi_log(PR_ERR, mfsi, "XSCOM error %lld writing OPB CMD\n", rc);
 		return rc;
 	}
-	return mfsi_opb_poll(chip, xscom_base, data, err_bits);
+	return mfsi_opb_poll(mfsi, data);
 }
 
-static int64_t mfsi_opb_write(uint32_t chip, uint32_t xscom_base,
-			      uint32_t addr, uint32_t data,
-			      uint32_t err_bits)
+static int64_t mfsi_opb_write(struct mfsi *mfsi, uint32_t opb_addr, uint32_t data)
 {
 	uint64_t opb_cmd = OPB_CMD_WRITE | OPB_CMD_32BIT;
 	int64_t rc;
 
-	if (addr > 0x00ffffff)
+	if (opb_addr > 0x00ffffff)
 		return OPAL_PARAMETER;
 
-	opb_cmd |= addr;
+	opb_cmd |= opb_addr;
 	opb_cmd <<= 32;
 	opb_cmd |= data;
 
-	prlog(PR_INSANE, "MFSI_OPB_WRITE: Writing 0x%16llx to XSCOM %x\n",
-	    opb_cmd, xscom_base);
+	mfsi_log(PR_INSANE, mfsi, "MFSI_OPB_WRITE: Writing 0x%16llx to XSCOM %x\n",
+		 opb_cmd, mfsi->xscom_base);
 
-	rc = xscom_write(chip, xscom_base + PIB2OPB_REG_CMD, opb_cmd);
+	rc = xscom_write(mfsi->chip_id, mfsi->xscom_base + PIB2OPB_REG_CMD, opb_cmd);
 	if (rc) {
-		prerror("MFSI: XSCOM error %lld writing OPB CMD\n", rc);
+		mfsi_log(PR_ERR, mfsi, "XSCOM error %lld writing OPB CMD\n", rc);
 		return rc;
 	}
-	return mfsi_opb_poll(chip, xscom_base, NULL, err_bits);
+	return mfsi_opb_poll(mfsi, NULL);
 }
 
-static int64_t mfsi_get_addrs(uint32_t mfsi, uint32_t port,
-			      uint32_t *xscom_base, uint32_t *port_base,
-			      uint32_t *reg_base, uint32_t *err_bits)
+static struct mfsi *mfsi_get(uint32_t chip_id, uint32_t unit)
 {
-	if (port > 7)
-		return OPAL_PARAMETER;
-
-	/* We hard code everything for now */
-	switch(mfsi) {
-	case MFSI_cMFSI0:
-		*xscom_base = PIB2OPB_MFSI0_ADDR;
-		*port_base = cMFSI_OPB_PORT_BASE + port * MFSI_OPB_PORT_STRIDE;
-		*reg_base = cMFSI_OPB_REG_BASE;
-		*err_bits = OPB_STAT_ERR_BASE | OPB_STAT_ERR_CMFSI;
-		break;
-	case MFSI_cMFSI1:
-		*xscom_base = PIB2OPB_MFSI1_ADDR;
-		*port_base = cMFSI_OPB_PORT_BASE + port * MFSI_OPB_PORT_STRIDE;
-		*reg_base = cMFSI_OPB_REG_BASE;
-		*err_bits = OPB_STAT_ERR_BASE | OPB_STAT_ERR_CMFSI;
-		break;
-	case MFSI_hMFSI0:
-		*xscom_base = PIB2OPB_MFSI0_ADDR;
-		*port_base = hMFSI_OPB_PORT_BASE + port * MFSI_OPB_PORT_STRIDE;
-		*reg_base = hMFSI_OPB_REG_BASE;
-		*err_bits = OPB_STAT_ERR_BASE | OPB_STAT_ERR_HMFSI;
-		break;
-	default:
-		return OPAL_PARAMETER;
-	}
-	*err_bits = *err_bits & mfsi_valid_err;
-
-	return OPAL_SUCCESS;
+	struct proc_chip *chip = get_chip(chip_id);
+	struct mfsi *mfsi;
+
+	if (!chip || unit > MFSI_hMFSI0)
+		return NULL;
+	mfsi = &chip->fsi_masters[unit];
+	if (mfsi->xscom_base == 0)
+		return NULL;
+	return mfsi;
 }
 
-int64_t mfsi_read(uint32_t chip, uint32_t mfsi, uint32_t port,
+int64_t mfsi_read(uint32_t chip, uint32_t unit, uint32_t port,
 		  uint32_t fsi_addr, uint32_t *data)
 {
+	struct mfsi *mfsi = mfsi_get(chip, unit);
+	uint32_t port_addr;
 	int64_t rc;
-	uint32_t xscom, port_addr, reg, err_bits;
 
-	rc = mfsi_get_addrs(mfsi, port, &xscom, &port_addr, &reg, &err_bits);
-	if (rc)
-		return rc;
+	if (!mfsi)
+		return OPAL_PARAMETER;
+
 	lock(&fsi_lock);
-	rc = mfsi_opb_read(chip, xscom, port_addr + fsi_addr, data, err_bits);
-	/* XXX Handle FSI level errors here, maybe reset port */
+
+	/* Calculate port address */
+	port_addr = mfsi->port_base + port * MFSI_OPB_PORT_STRIDE;
+	port_addr += fsi_addr;
+
+	/* Perform OPB access */
+	rc = mfsi_opb_read(mfsi, port_addr, data);
+
+	/* XXX Handle FSI level errors here */
+
 	unlock(&fsi_lock);
 
 	return rc;
 }
 
-int64_t mfsi_write(uint32_t chip, uint32_t mfsi, uint32_t port,
+int64_t mfsi_write(uint32_t chip, uint32_t unit, uint32_t port,
 		   uint32_t fsi_addr, uint32_t data)
 {
+	struct mfsi *mfsi = mfsi_get(chip, unit);
+	uint32_t port_addr;
 	int64_t rc;
-	uint32_t xscom, port_addr, reg, err_bits;
 
-	rc = mfsi_get_addrs(mfsi, port, &xscom, &port_addr, &reg, &err_bits);
-	if (rc)
-		return rc;
 	lock(&fsi_lock);
-	rc = mfsi_opb_write(chip, xscom, port_addr + fsi_addr, data, err_bits);
-	/* XXX Handle FSI level errors here, maybe reset port */
+
+	/* Calculate port address */
+	port_addr = mfsi->port_base + port * MFSI_OPB_PORT_STRIDE;
+	port_addr += fsi_addr;
+
+	/* Perform OPB access */
+	rc = mfsi_opb_write(mfsi, port_addr, data);
+
+	/* XXX Handle FSI level errors here */
+
 	unlock(&fsi_lock);
 
 	return rc;
 }
 
-void mfsi_init(void)
+static void mfsi_add(struct proc_chip *chip, struct mfsi *mfsi, uint32_t unit)
 {
-	struct proc_chip *chip;
-
-	/* For now assume all chips are the same DD... might need
-	 * fixing.
-	 */
-	chip = next_chip(NULL);
-	assert(chip);
-	mfsi_valid_err = OPB_STAT_ERR_BASE | OPB_STAT_ERR_CMFSI | OPB_STAT_ERR_HMFSI;
+	mfsi->chip_id = chip->id;
+	mfsi->unit = unit;
 
+	/* We hard code everything for now */
+	switch(unit) {
+	case MFSI_cMFSI0:
+		mfsi->xscom_base = PIB2OPB_MFSI0_ADDR;
+		mfsi->port_base = cMFSI_OPB_PORT_BASE;
+		mfsi->reg_base = cMFSI_OPB_REG_BASE;
+		mfsi->err_bits = OPB_STAT_ERR_BASE | OPB_STAT_ERR_CMFSI;
+		break;
+	case MFSI_cMFSI1:
+		mfsi->xscom_base = PIB2OPB_MFSI1_ADDR;
+		mfsi->port_base = cMFSI_OPB_PORT_BASE;
+		mfsi->reg_base = cMFSI_OPB_REG_BASE;
+		mfsi->err_bits = OPB_STAT_ERR_BASE | OPB_STAT_ERR_CMFSI;
+		break;
+	case MFSI_hMFSI0:
+		mfsi->xscom_base = PIB2OPB_MFSI0_ADDR;
+		mfsi->port_base = hMFSI_OPB_PORT_BASE;
+		mfsi->reg_base = hMFSI_OPB_REG_BASE;
+		mfsi->err_bits = OPB_STAT_ERR_BASE | OPB_STAT_ERR_HMFSI;
+		break;
+	default:
+		/* ??? */
+		return;
+	}
 
 	/* Hardware Bug HW222712 on Murano DD1.0 causes the
 	 * any_error bit to be un-clearable so we just
@@ -310,6 +329,21 @@ void mfsi_init(void)
 
 	/* 16: cMFSI any-master-error */
 	/* 24: hMFSI any-master-error */
-	mfsi_valid_err &= 0xFFFF7F7F;
+	mfsi->err_bits &= 0xFFFF7F7F;
+
+	mfsi_log(PR_INFO, mfsi, "Initialized\n");
+}
+
+void mfsi_init(void)
+{
+	struct proc_chip *chip;
+
+	for_each_chip(chip) {
+		chip->fsi_masters = zalloc(sizeof(struct mfsi) * 3);
+		mfsi_add(chip, &chip->fsi_masters[MFSI_cMFSI0], MFSI_cMFSI0);
+		mfsi_add(chip, &chip->fsi_masters[MFSI_hMFSI0], MFSI_hMFSI0);
+		mfsi_add(chip, &chip->fsi_masters[MFSI_cMFSI1], MFSI_cMFSI1);
+
+	}
 }
 
diff --git a/include/chip.h b/include/chip.h
index 9cecace..470ba64 100644
--- a/include/chip.h
+++ b/include/chip.h
@@ -79,6 +79,7 @@
 
 struct dt_node;
 struct centaur_chip;
+struct mfsi;
 
 /* Chip type */
 enum proc_chip_type {
@@ -161,6 +162,9 @@ struct proc_chip {
 
 	/* Used by hw/psi.c */
 	struct psi		*psi;
+
+	/* Used by hw/fsi-master.c */
+	struct mfsi		*fsi_masters;
 };
 
 extern uint32_t pir_to_chip_id(uint32_t pir);
-- 
2.1.4



More information about the Skiboot mailing list