From patchwork Sat Jun 24 19:17:12 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Neuling X-Patchwork-Id: 780383 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [103.22.144.68]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3ww4s10XTwz9s8H for ; Sun, 25 Jun 2017 05:20:05 +1000 (AEST) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3ww4s06g14zDr2g for ; Sun, 25 Jun 2017 05:20:04 +1000 (AEST) X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Received: from ozlabs.org (ozlabs.org [IPv6:2401:3900:2:1::2]) (using TLSv1.2 with cipher ADH-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3ww4p92fM6zDr20 for ; Sun, 25 Jun 2017 05:17:37 +1000 (AEST) Received: from localhost.localdomain (localhost [127.0.0.1]) by ozlabs.org (Postfix) with ESMTP id 3ww4p861vSz9s9Y; Sun, 25 Jun 2017 05:17:36 +1000 (AEST) Received: by localhost.localdomain (Postfix, from userid 1000) id 51C8CEEE109; Sun, 25 Jun 2017 05:17:35 +1000 (AEST) From: Michael Neuling To: stewart@linux.vnet.ibm.com Date: Sat, 24 Jun 2017 14:17:12 -0500 Message-Id: <20170624191728.14793-8-mikey@neuling.org> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170624191728.14793-1-mikey@neuling.org> References: <20170624191728.14793-1-mikey@neuling.org> Subject: [Skiboot] [PATCH v2 07/23] phb4: Mask out write-1-to-clear registers in RC cfg X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: skiboot@lists.ozlabs.org, Michael Neuling MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" From: Russell Currey The root complex config space only supports 4-byte accesses. Thus, when the client requests a smaller size write, we do a read-modify-write to the register. However, some register have bits defined as "write 1 to clear". If we do a RMW cycles on such a register and such bits are 1 in the part that the client doesn't intend to modify, we will accidentally write back those 1's and clear the corresponding bit. This avoids it by masking out those magic bits from the "old" value read from the register. Signed-off-by: Russell Currey Signed-off-by: Michael Neuling --- hw/phb4.c | 44 +++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/hw/phb4.c b/hw/phb4.c index 3ee618e3a8..7e8ba3b07c 100644 --- a/hw/phb4.c +++ b/hw/phb4.c @@ -264,20 +264,54 @@ static int64_t phb4_rc_write(struct phb4 *p, uint32_t offset, uint8_t sz, uint32_t val) { uint32_t reg = offset & ~3; - uint32_t old, mask, shift; + uint32_t old, mask, shift, oldold; int64_t rc; if (reg > PHB_RC_CONFIG_SIZE) return OPAL_SUCCESS; - /* If size isn't 4-bytes, do a RMW cycle - * - * XXX TODO: Filter out registers that do write-1-to-clear !!! - */ + /* If size isn't 4-bytes, do a RMW cycle */ if (sz < 4) { rc = phb4_rc_read(p, reg, 4, &old); if (rc != OPAL_SUCCESS) return rc; + + /* + * Since we have to Read-Modify-Write here, we need to filter + * out registers that have write-1-to-clear bits to prevent + * clearing stuff we shouldn't be. So for any register this + * applies to, mask out those bits. + */ + oldold = old; + switch(reg) { + case 0x1C: /* Secondary status */ + old &= 0x00ffffff; /* mask out 24-31 */ + break; + case 0x50: /* EC - Device status */ + old &= 0xfff0ffff; /* mask out 16-19 */ + break; + case 0x58: /* EC - Link status */ + old &= 0x3fffffff; /* mask out 30-31 */ + break; + case 0x78: /* EC - Link status 2 */ + old &= 0xf000ffff; /* mask out 16-27 */ + break; + /* These registers *only* have write-1-to-clear bits */ + case 0x104: /* AER - Uncorr. error status */ + case 0x110: /* AER - Corr. error status */ + case 0x130: /* AER - Root error status */ + case 0x180: /* P16 - status */ + case 0x184: /* P16 - LDPM status */ + case 0x188: /* P16 - FRDPM status */ + case 0x18C: /* P16 - SRDPM status */ + old &= 0x00000000; + break; + } + + if (old != oldold) + PHBDBG(p, "Rewrote %x to %x for reg %x for W1C\n", + oldold, old, reg); + if (sz == 1) { shift = (offset & 3) << 3; mask = 0xff << shift;