Merge branch 'apei-release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb...
[pandora-kernel.git] / drivers / acpi / apei / erst.c
index d6cb0ff..2ca59dc 100644 (file)
@@ -642,7 +642,7 @@ static int __erst_write_to_storage(u64 offset)
        int rc;
 
        erst_exec_ctx_init(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_WRITE);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_WRITE);
        if (rc)
                return rc;
        apei_exec_ctx_set_input(&ctx, offset);
@@ -666,7 +666,7 @@ static int __erst_write_to_storage(u64 offset)
        if (rc)
                return rc;
        val = apei_exec_ctx_get_output(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_END);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_END);
        if (rc)
                return rc;
 
@@ -681,7 +681,7 @@ static int __erst_read_from_storage(u64 record_id, u64 offset)
        int rc;
 
        erst_exec_ctx_init(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_READ);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_READ);
        if (rc)
                return rc;
        apei_exec_ctx_set_input(&ctx, offset);
@@ -709,7 +709,7 @@ static int __erst_read_from_storage(u64 record_id, u64 offset)
        if (rc)
                return rc;
        val = apei_exec_ctx_get_output(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_END);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_END);
        if (rc)
                return rc;
 
@@ -724,7 +724,7 @@ static int __erst_clear_from_storage(u64 record_id)
        int rc;
 
        erst_exec_ctx_init(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_BEGIN_CLEAR);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_BEGIN_CLEAR);
        if (rc)
                return rc;
        apei_exec_ctx_set_input(&ctx, record_id);
@@ -748,7 +748,7 @@ static int __erst_clear_from_storage(u64 record_id)
        if (rc)
                return rc;
        val = apei_exec_ctx_get_output(&ctx);
-       rc = apei_exec_run(&ctx, ACPI_ERST_END);
+       rc = apei_exec_run_optional(&ctx, ACPI_ERST_END);
        if (rc)
                return rc;
 
@@ -929,16 +929,23 @@ static int erst_check_table(struct acpi_table_erst *erst_tab)
        return 0;
 }
 
-static size_t erst_reader(u64 *id, enum pstore_type_id *type,
-                      struct timespec *time);
-static u64 erst_writer(enum pstore_type_id type, size_t size);
+static int erst_open_pstore(struct pstore_info *psi);
+static int erst_close_pstore(struct pstore_info *psi);
+static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
+                          struct timespec *time, struct pstore_info *psi);
+static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+                      size_t size, struct pstore_info *psi);
+static int erst_clearer(enum pstore_type_id type, u64 id,
+                       struct pstore_info *psi);
 
 static struct pstore_info erst_info = {
        .owner          = THIS_MODULE,
        .name           = "erst",
+       .open           = erst_open_pstore,
+       .close          = erst_close_pstore,
        .read           = erst_reader,
        .write          = erst_writer,
-       .erase          = erst_clear
+       .erase          = erst_clearer
 };
 
 #define CPER_CREATOR_PSTORE                                            \
@@ -957,12 +964,32 @@ struct cper_pstore_record {
        char data[];
 } __packed;
 
-static size_t erst_reader(u64 *id, enum pstore_type_id *type,
-                      struct timespec *time)
+static int reader_pos;
+
+static int erst_open_pstore(struct pstore_info *psi)
 {
        int rc;
-       ssize_t len;
-       unsigned long flags;
+
+       if (erst_disable)
+               return -ENODEV;
+
+       rc = erst_get_record_id_begin(&reader_pos);
+
+       return rc;
+}
+
+static int erst_close_pstore(struct pstore_info *psi)
+{
+       erst_get_record_id_end();
+
+       return 0;
+}
+
+static ssize_t erst_reader(u64 *id, enum pstore_type_id *type,
+                          struct timespec *time, struct pstore_info *psi)
+{
+       int rc;
+       ssize_t len = 0;
        u64 record_id;
        struct cper_pstore_record *rcd = (struct cper_pstore_record *)
                                        (erst_info.buf - sizeof(*rcd));
@@ -970,24 +997,28 @@ static size_t erst_reader(u64 *id, enum pstore_type_id *type,
        if (erst_disable)
                return -ENODEV;
 
-       raw_spin_lock_irqsave(&erst_lock, flags);
 skip:
-       rc = __erst_get_next_record_id(&record_id);
-       if (rc) {
-               raw_spin_unlock_irqrestore(&erst_lock, flags);
-               return rc;
-       }
+       rc = erst_get_record_id_next(&reader_pos, &record_id);
+       if (rc)
+               goto out;
+
        /* no more record */
        if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-               raw_spin_unlock_irqrestore(&erst_lock, flags);
-               return 0;
+               rc = -1;
+               goto out;
        }
 
-       len = __erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
-                         erst_erange.size);
+       len = erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
+                       erst_info.bufsize);
+       /* The record may be cleared by others, try read next record */
+       if (len == -ENOENT)
+               goto skip;
+       else if (len < 0) {
+               rc = -1;
+               goto out;
+       }
        if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
                goto skip;
-       raw_spin_unlock_irqrestore(&erst_lock, flags);
 
        *id = record_id;
        if (uuid_le_cmp(rcd->sec_hdr.section_type,
@@ -1005,10 +1036,12 @@ skip:
                time->tv_sec = 0;
        time->tv_nsec = 0;
 
-       return len - sizeof(*rcd);
+out:
+       return (rc < 0) ? rc : (len - sizeof(*rcd));
 }
 
-static u64 erst_writer(enum pstore_type_id type, size_t size)
+static u64 erst_writer(enum pstore_type_id type, unsigned int part,
+                      size_t size, struct pstore_info *psi)
 {
        struct cper_pstore_record *rcd = (struct cper_pstore_record *)
                                        (erst_info.buf - sizeof(*rcd));
@@ -1051,6 +1084,12 @@ static u64 erst_writer(enum pstore_type_id type, size_t size)
        return rcd->hdr.record_id;
 }
 
+static int erst_clearer(enum pstore_type_id type, u64 id,
+                       struct pstore_info *psi)
+{
+       return erst_clear(id);
+}
+
 static int __init erst_init(void)
 {
        int rc = 0;