summaryrefslogtreecommitdiffstats
path: root/external
diff options
context:
space:
mode:
authorJoel Stanley <joel@jms.id.au>2015-03-04 17:11:30 +1030
committerJeremy Kerr <jk@ozlabs.org>2015-03-04 22:57:43 +1100
commit5ae13c25766b0025ffab99b9f8622182af2d4b36 (patch)
tree9600cea74c9c55dcd01234bec65561b9de4688d4 /external
parentdddd88034e069ba2c1fe540f1a701d94cd01710e (diff)
downloadtalos-skiboot-5ae13c25766b0025ffab99b9f8622182af2d4b36.tar.gz
talos-skiboot-5ae13c25766b0025ffab99b9f8622182af2d4b36.zip
external/opal-prd: Allow partial ops with PNOR API
The PNOR operations will now return the number of bytes successfully written, which may be less than the number of bytes requested, similar to read(2) and write(2). The hostboot interface is updated with this information. The signature does not change. Signed-off-by: Joel Stanley <joel@jms.id.au> Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Diffstat (limited to 'external')
-rw-r--r--external/opal-prd/hostboot-interface.h4
-rw-r--r--external/opal-prd/pnor.c32
2 files changed, 26 insertions, 10 deletions
diff --git a/external/opal-prd/hostboot-interface.h b/external/opal-prd/hostboot-interface.h
index 1088178d..a518f504 100644
--- a/external/opal-prd/hostboot-interface.h
+++ b/external/opal-prd/hostboot-interface.h
@@ -170,7 +170,7 @@ struct host_interfaces {
* @param[in] i_offset: offset within the partition
* @param[out] o_data: pointer to the data read
* @param[in] i_sizeBytes: size of data to read
- * @retval rc - non-zero on error
+ * @retval rc - number of bytes read, or non-zero on error
* @platform OpenPOWER
*/
int (*pnor_read) ( uint32_t i_proc, const char* i_partitionName,
@@ -183,7 +183,7 @@ struct host_interfaces {
* @param[in] i_offset: offset withing the partition
* @param[in] i_data: pointer to the data to write
* @param[in] i_sizeBytes: size of data to write
- * @retval rc - non-zero on error
+ * @retval rc - number of bytes written, or non-zero on error
* @platform OpenPOWER
*/
int (*pnor_write) ( uint32_t i_proc, const char* i_partitionName,
diff --git a/external/opal-prd/pnor.c b/external/opal-prd/pnor.c
index e5609fe4..e40d2924 100644
--- a/external/opal-prd/pnor.c
+++ b/external/opal-prd/pnor.c
@@ -240,11 +240,16 @@ out:
return rc;
}
+/* Similar to read(2), this performs partial operations where the number of
+ * bytes read/written may be less than size.
+ *
+ * Returns number of bytes written, or a negative value on failure. */
int pnor_operation(struct pnor *pnor, const char *name, uint64_t offset,
- void *data, size_t size, enum pnor_op op)
+ void *data, size_t requested_size, enum pnor_op op)
{
int rc, fd;
uint32_t pstart, psize, idx;
+ int size;
if (!pnor->ffsh) {
warnx("PNOR: ffs not initialised");
@@ -263,9 +268,23 @@ int pnor_operation(struct pnor *pnor, const char *name, uint64_t offset,
return -ENOENT;
}
- if (size > psize || offset > psize || size + offset > psize) {
- warnx("PNOR: offset (%ld) or size (%ld) out of bounds (%d)",
- offset, size, psize);
+ if (offset > psize) {
+ warnx("PNOR: offset (%ld) out of bounds (%d)", offset, psize);
+ return -ERANGE;
+ }
+
+ /* Large requests are trimmed */
+ if (requested_size > psize)
+ size = psize;
+ else
+ size = requested_size;
+
+ if (size + offset > psize)
+ size = psize - offset;
+
+ if (size < 0) {
+ warnx("PNOR: size (%zd) and offset (%ld) out of bounds (%d)",
+ requested_size, offset, psize);
return -ERANGE;
}
@@ -297,11 +316,8 @@ int pnor_operation(struct pnor *pnor, const char *name, uint64_t offset,
if (rc < 0)
warn("PNOR: MTD operation failed");
else if (rc != size)
- warnx("PNOR: mtd operation returned %d, expected %zd",
+ warnx("PNOR: mtd operation returned %d, expected %d",
rc, size);
- else
- rc = 0;
-
out:
close(fd);
OpenPOWER on IntegriCloud