From patchwork Wed Mar 7 06:04:58 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyril Bur X-Patchwork-Id: 882416 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 3zx38W6hvTz9sfK for ; Wed, 7 Mar 2018 17:07:39 +1100 (AEDT) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=au1.ibm.com Received: from bilbo.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id 3zx38R236TzF1WW for ; Wed, 7 Mar 2018 17:07:35 +1100 (AEDT) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=au1.ibm.com X-Original-To: skiboot@lists.ozlabs.org Delivered-To: skiboot@lists.ozlabs.org Authentication-Results: lists.ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=au1.ibm.com (client-ip=148.163.158.5; helo=mx0a-001b2d01.pphosted.com; envelope-from=cyril.bur@au1.ibm.com; receiver=) Authentication-Results: lists.ozlabs.org; dmarc=none (p=none dis=none) header.from=au1.ibm.com Received: from mx0a-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3zx3684b46zF1VQ for ; Wed, 7 Mar 2018 17:05:36 +1100 (AEDT) Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w275xPFn108002 for ; Wed, 7 Mar 2018 01:05:34 -0500 Received: from e06smtp13.uk.ibm.com (e06smtp13.uk.ibm.com [195.75.94.109]) by mx0a-001b2d01.pphosted.com with ESMTP id 2gjabxrbn6-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Wed, 07 Mar 2018 01:05:33 -0500 Received: from localhost by e06smtp13.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 7 Mar 2018 06:05:31 -0000 Received: from b06cxnps4074.portsmouth.uk.ibm.com (9.149.109.196) by e06smtp13.uk.ibm.com (192.168.101.143) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Wed, 7 Mar 2018 06:05:29 -0000 Received: from d06av26.portsmouth.uk.ibm.com (d06av26.portsmouth.uk.ibm.com [9.149.105.62]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2765Swk58785954 for ; Wed, 7 Mar 2018 06:05:29 GMT Received: from d06av26.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6F339AE05A for ; Wed, 7 Mar 2018 05:56:05 +0000 (GMT) Received: from d06av26.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D4307AE051 for ; Wed, 7 Mar 2018 05:56:04 +0000 (GMT) Received: from ozlabs.au.ibm.com (unknown [9.192.253.14]) by d06av26.portsmouth.uk.ibm.com (Postfix) with ESMTP for ; Wed, 7 Mar 2018 05:56:04 +0000 (GMT) Received: from camb691.ozlabs.ibm.com (haven.au.ibm.com [9.192.254.114]) (using TLSv1.2 with cipher DHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by ozlabs.au.ibm.com (Postfix) with ESMTPSA id 01976A0230; Wed, 7 Mar 2018 17:05:27 +1100 (AEDT) From: Cyril Bur To: skiboot@lists.ozlabs.org Date: Wed, 7 Mar 2018 17:04:58 +1100 X-Mailer: git-send-email 2.16.2 In-Reply-To: <20180307060459.18338-1-cyril.bur@au1.ibm.com> References: <20180307060459.18338-1-cyril.bur@au1.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18030706-0012-0000-0000-000005B9C1FE X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18030706-0013-0000-0000-00001935DBFA Message-Id: <20180307060459.18338-5-cyril.bur@au1.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-03-07_02:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=1 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803070071 Subject: [Skiboot] [PATCH v2 4/5] libflash/blocklevel: Return region start from ecc_protected() X-BeenThere: skiboot@lists.ozlabs.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: Mailing list for skiboot development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: skiboot-bounces+incoming=patchwork.ozlabs.org@lists.ozlabs.org Sender: "Skiboot" Currently all ecc_protected() does is say if a region is ECC protected or not. Knowing a region is ECC protected is one thing but there isn't much that can be done afterwards if this is the only known fact. A lot more can be done if the caller is told where the ECC region begins. Knowing where the ECC region start it allows to caller to align its read/and writes. This allows for more flexibility calling read and write without knowing exactly how the backing store is organised. Signed-off-by: Cyril Bur --- libflash/blocklevel.c | 63 ++++++++++++++++++++++++++++++++++------- libflash/test/test-blocklevel.c | 22 +++++++------- 2 files changed, 63 insertions(+), 22 deletions(-) diff --git a/libflash/blocklevel.c b/libflash/blocklevel.c index eaab431a..fe24ebc2 100644 --- a/libflash/blocklevel.c +++ b/libflash/blocklevel.c @@ -22,6 +22,7 @@ #include #include +#include #include #include "blocklevel.h" @@ -34,7 +35,7 @@ * 0 - The region is not ECC protected * -1 - Partially protected */ -static int ecc_protected(struct blocklevel_device *bl, uint64_t pos, uint64_t len) +static int ecc_protected(struct blocklevel_device *bl, uint64_t pos, uint64_t len, uint64_t *start) { int i; @@ -44,8 +45,12 @@ static int ecc_protected(struct blocklevel_device *bl, uint64_t pos, uint64_t le for (i = 0; i < bl->ecc_prot.n_prot; i++) { /* Fits entirely within the range */ - if (bl->ecc_prot.prot[i].start <= pos && bl->ecc_prot.prot[i].start + bl->ecc_prot.prot[i].len >= pos + len) + if (bl->ecc_prot.prot[i].start <= pos && + bl->ecc_prot.prot[i].start + bl->ecc_prot.prot[i].len >= pos + len) { + if (start) + *start = bl->ecc_prot.prot[i].start; return 1; + } /* * Since we merge regions on inserting we can be sure that a @@ -53,8 +58,12 @@ static int ecc_protected(struct blocklevel_device *bl, uint64_t pos, uint64_t le * region */ if ((bl->ecc_prot.prot[i].start >= pos && bl->ecc_prot.prot[i].start < pos + len) || - (bl->ecc_prot.prot[i].start <= pos && bl->ecc_prot.prot[i].start + bl->ecc_prot.prot[i].len > pos)) + (bl->ecc_prot.prot[i].start <= pos && + bl->ecc_prot.prot[i].start + bl->ecc_prot.prot[i].len > pos)) { + if (start) + *start = bl->ecc_prot.prot[i].start; return -1; + } } return 0; } @@ -101,9 +110,9 @@ int blocklevel_raw_read(struct blocklevel_device *bl, uint64_t pos, void *buf, u int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint64_t len) { - int rc; + int rc, ecc_protection; struct ecc64 *buffer; - uint64_t ecc_len = ecc_buffer_size(len); + uint64_t ecc_start, ecc_len = ecc_buffer_size(len); FL_DBG("%s: 0x%" PRIx64 "\t%p\t0x%" PRIx64 "\n", __func__, pos, buf, len); if (!bl || !buf) { @@ -111,10 +120,25 @@ int blocklevel_read(struct blocklevel_device *bl, uint64_t pos, void *buf, uint6 return FLASH_ERR_PARM_ERROR; } - if (!ecc_protected(bl, pos, len)) + ecc_protection = ecc_protected(bl, pos, len, &ecc_start); + + FL_DBG("%s: 0x%" PRIx64 " for 0x%" PRIx64 " ecc=%s", + __func__, pos, len, ecc_protection ? + (ecc_protection == -1 ? "partial" : "yes") : "no"); + + if (!ecc_protection) return blocklevel_raw_read(bl, pos, buf, len); - FL_DBG("%s: region has ECC\n", __func__); + /* + * The region we're reading to has both ecc protection and not. + * Perhaps one day in the future blocklevel can cope with this. + */ + if (ecc_protection == -1) { + FL_ERR("%s: Can't cope with partial ecc\n", __func__); + errno = EINVAL; + return FLASH_ERR_PARM_ERROR; + } + buffer = malloc(ecc_len); if (!buffer) { errno = ENOMEM; @@ -161,9 +185,10 @@ int blocklevel_raw_write(struct blocklevel_device *bl, uint64_t pos, int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf, uint64_t len) { - int rc; + int rc, ecc_protection; struct ecc64 *buffer; uint64_t ecc_len = ecc_buffer_size(len); + uint64_t ecc_start; FL_DBG("%s: 0x%" PRIx64 "\t%p\t0x%" PRIx64 "\n", __func__, pos, buf, len); if (!bl || !buf) { @@ -171,10 +196,25 @@ int blocklevel_write(struct blocklevel_device *bl, uint64_t pos, const void *buf return FLASH_ERR_PARM_ERROR; } - if (!ecc_protected(bl, pos, len)) + ecc_protection = ecc_protected(bl, pos, len, &ecc_start); + + FL_DBG("%s: 0x%" PRIx64 " for 0x%" PRIx64 " ecc=%s", + __func__, pos, len, ecc_protection ? + (ecc_protection == -1 ? "partial" : "yes") : "no"); + + if (!ecc_protection) return blocklevel_raw_write(bl, pos, buf, len); - FL_DBG("%s: region has ECC\n", __func__); + /* + * The region we're writing to has both ecc protection and not. + * Perhaps one day in the future blocklevel can cope with this. + */ + if (ecc_protection == -1) { + FL_ERR("%s: Can't cope with partial ecc\n", __func__); + errno = EINVAL; + return FLASH_ERR_PARM_ERROR; + } + buffer = malloc(ecc_len); if (!buffer) { errno = ENOMEM; @@ -420,6 +460,7 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi uint32_t erase_size; const void *write_buf = buf; void *write_buf_start = NULL; + uint64_t ecc_start; void *erase_buf; int rc = 0; @@ -439,7 +480,7 @@ int blocklevel_smart_write(struct blocklevel_device *bl, uint64_t pos, const voi if (rc) return rc; - if (ecc_protected(bl, pos, len)) { + if (ecc_protected(bl, pos, len, &ecc_start)) { FL_DBG("%s: region has ECC\n", __func__); len = ecc_buffer_size(len); diff --git a/libflash/test/test-blocklevel.c b/libflash/test/test-blocklevel.c index 3787cd6d..3862784b 100644 --- a/libflash/test/test-blocklevel.c +++ b/libflash/test/test-blocklevel.c @@ -162,17 +162,17 @@ int main(void) return 1; } - if (ecc_protected(bl, 0, 1) != 1) { + if (ecc_protected(bl, 0, 1, NULL) != 1) { ERR("Invaid result for ecc_protected(0, 1)\n"); return 1; } - if (ecc_protected(bl, 0, 0x1000) != 1) { + if (ecc_protected(bl, 0, 0x1000, NULL) != 1) { ERR("Invalid result for ecc_protected(0, 0x1000)\n"); return 1; } - if (ecc_protected(bl, 0x100, 0x100) != 1) { + if (ecc_protected(bl, 0x100, 0x100, NULL) != 1) { ERR("Invalid result for ecc_protected(0x0100, 0x100)\n"); return 1; } @@ -190,33 +190,33 @@ int main(void) return 1; } - if (ecc_protected(bl, 0x1000, 0) != 1) { + if (ecc_protected(bl, 0x1000, 0, NULL) != 1) { ERR("Invalid result for ecc_protected(0x1000, 0)\n"); return 1; } - if (ecc_protected(bl, 0x1000, 0x1000) != -1) { + if (ecc_protected(bl, 0x1000, 0x1000, NULL) != -1) { ERR("Invalid result for ecc_protected(0x1000, 0x1000)\n"); return 1; } - if (ecc_protected(bl, 0x1000, 0x100) != 1) { + if (ecc_protected(bl, 0x1000, 0x100, NULL) != 1) { ERR("Invalid result for ecc_protected(0x1000, 0x100)\n"); return 1; } - if (ecc_protected(bl, 0x2000, 0) != 0) { + if (ecc_protected(bl, 0x2000, 0, NULL) != 0) { ERR("Invalid result for ecc_protected(0x2000, 0)\n"); return 1; } - if (ecc_protected(bl, 0x4000, 1) != 0) { + if (ecc_protected(bl, 0x4000, 1, NULL) != 0) { ERR("Invalid result for ecc_protected(0x4000, 1)\n"); return 1; } /* Check for asking for a region with mixed protection */ - if (ecc_protected(bl, 0x100, 0x2000) != -1) { + if (ecc_protected(bl, 0x100, 0x2000, NULL) != -1) { ERR("Invalid result for ecc_protected(0x100, 0x2000)\n"); return 1; } @@ -237,7 +237,7 @@ int main(void) return 1; } - if (ecc_protected(bl, 0x5120, 0x10) != 1) { + if (ecc_protected(bl, 0x5120, 0x10, NULL) != 1) { ERR("Invalid result for ecc_protected(0x5120, 0x10)\n"); return 1; } @@ -252,7 +252,7 @@ int main(void) return 1; } - if (ecc_protected(bl, 0x4920, 0x10) != 1) { + if (ecc_protected(bl, 0x4920, 0x10, NULL) != 1) { ERR("Invalid result for ecc_protected(0x4920, 0x10)\n"); return 1; }