aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorFrederic Barrat <fbarrat@linux.ibm.com>2019-03-12 21:35:15 +0100
committerStewart Smith <stewart@linux.ibm.com>2019-03-13 21:55:18 -0500
commit998911498597f3a057d73f7c78c075d830d22731 (patch)
tree3a3e9ff0c0ceebba5d6325541010bb2fc815737a /hw
parentd75436f0d3d0f4b8ecdb28fb2f08dd34d2119c24 (diff)
downloadskiboot-998911498597f3a057d73f7c78c075d830d22731.zip
skiboot-998911498597f3a057d73f7c78c075d830d22731.tar.gz
skiboot-998911498597f3a057d73f7c78c075d830d22731.tar.bz2
npu2-opencapi: Fix adapter reset when using 2 adapters
If two opencapi adapters are on the same obus, we may try to train the two links in parallel at boot time, when all the PCI links are being trained. Both links use the same i2c controller to handle the reset signal, so some care is needed to make sure resetting one doesn't interfere with the reset of the other. We need to keep track of the current state of the i2c controller (and use locking). This went mostly unnoticed as you need to have 2 opencapi cards on the same socket and links tended to train anyway because of the retries. Signed-off-by: Frederic Barrat <fbarrat@linux.ibm.com> Reviewed-by: Andrew Donnellan <andrew.donnellan@au1.ibm.com> Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'hw')
-rw-r--r--hw/npu2-common.c3
-rw-r--r--hw/npu2-opencapi.c34
2 files changed, 30 insertions, 7 deletions
diff --git a/hw/npu2-common.c b/hw/npu2-common.c
index ec69953..3d0b636 100644
--- a/hw/npu2-common.c
+++ b/hw/npu2-common.c
@@ -182,6 +182,9 @@ static struct npu2 *setup_npu(struct dt_node *dn)
npu->xscom_base = dt_get_address(dn, 0, NULL);
npu->phb_index = dt_prop_get_u32(dn, "ibm,phb-index");
+ init_lock(&npu->i2c_lock);
+ npu->i2c_pin_mode = ~0; // input mode by default
+ npu->i2c_pin_wr_state = ~0; // reset is active low
if (platform.ocapi) {
/* Find I2C port for handling device presence/reset */
snprintf(port_name, sizeof(port_name), "p8_%08x_e%dp%d",
diff --git a/hw/npu2-opencapi.c b/hw/npu2-opencapi.c
index e4e3ae6..b2740f3 100644
--- a/hw/npu2-opencapi.c
+++ b/hw/npu2-opencapi.c
@@ -848,10 +848,9 @@ static void otl_enabletx(uint32_t gcid, uint32_t scom_base,
/* TODO: Abort if credits are zero */
}
-static void assert_adapter_reset(struct npu2_dev *dev)
+static uint8_t get_reset_pin(struct npu2_dev *dev)
{
- uint8_t pin, data;
- int rc;
+ uint8_t pin;
switch (dev->brick_index) {
case 2:
@@ -869,14 +868,25 @@ static void assert_adapter_reset(struct npu2_dev *dev)
default:
assert(false);
}
+ return pin;
+}
+
+static void assert_adapter_reset(struct npu2_dev *dev)
+{
+ uint8_t pin, data;
+ int rc;
+ pin = get_reset_pin(dev);
/*
* set the i2c reset pin in output mode
*
* On the 9554 device, register 3 is the configuration
* register and a pin is in output mode if its value is 0
*/
- data = ~pin;
+ lock(&dev->npu->i2c_lock);
+ dev->npu->i2c_pin_mode &= ~pin;
+ data = dev->npu->i2c_pin_mode;
+
rc = i2c_request_send(dev->npu->i2c_port_id_ocapi,
platform.ocapi->i2c_reset_addr, SMBUS_WRITE,
0x3, 1,
@@ -885,16 +895,20 @@ static void assert_adapter_reset(struct npu2_dev *dev)
goto err;
/* register 1 controls the signal, reset is active low */
- data = ~pin;
+ dev->npu->i2c_pin_wr_state &= ~pin;
+ data = dev->npu->i2c_pin_wr_state;
+
rc = i2c_request_send(dev->npu->i2c_port_id_ocapi,
platform.ocapi->i2c_reset_addr, SMBUS_WRITE,
0x1, 1,
&data, sizeof(data), 120);
if (rc)
goto err;
+ unlock(&dev->npu->i2c_lock);
return;
err:
+ unlock(&dev->npu->i2c_lock);
/**
* @fwts-label OCAPIDeviceResetFailed
* @fwts-advice There was an error attempting to send
@@ -905,14 +919,20 @@ err:
static void deassert_adapter_reset(struct npu2_dev *dev)
{
- uint8_t data;
+ uint8_t pin, data;
int rc;
- data = 0xFF;
+ pin = get_reset_pin(dev);
+
+ lock(&dev->npu->i2c_lock);
+ dev->npu->i2c_pin_wr_state |= pin;
+ data = dev->npu->i2c_pin_wr_state;
+
rc = i2c_request_send(dev->npu->i2c_port_id_ocapi,
platform.ocapi->i2c_reset_addr, SMBUS_WRITE,
0x1, 1,
&data, sizeof(data), 120);
+ unlock(&dev->npu->i2c_lock);
if (rc) {
/**
* @fwts-label OCAPIDeviceResetFailed