aboutsummaryrefslogtreecommitdiffstats
path: root/fs/pstore/ram.c
diff options
context:
space:
mode:
authorAnton Vorontsov <anton.vorontsov@linaro.org>2012-05-17 03:15:18 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-17 11:51:41 -0400
commit896fc1f0c4c6c19b270734f274be67cb0e8a24af (patch)
treedfdeccb50e7288365d1595a5e57ca21e5824abed /fs/pstore/ram.c
parentcddb8751c80348df75149f44fc3bf38d3dd1f3e6 (diff)
pstore/ram: Switch to persistent_ram routines
The patch switches pstore RAM backend to use persistent_ram routines, one step closer to the ECC support. Signed-off-by: Anton Vorontsov <anton.vorontsov@linaro.org> Acked-by: Marco Stornelli <marco.stornelli@gmail.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs/pstore/ram.c')
-rw-r--r--fs/pstore/ram.c106
1 files changed, 59 insertions, 47 deletions
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index e443c9c6914f..62b13eda4691 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -57,7 +57,7 @@ MODULE_PARM_DESC(dump_oops,
57 "set to 1 to dump oopses, 0 to only dump panics (default 1)"); 57 "set to 1 to dump oopses, 0 to only dump panics (default 1)");
58 58
59struct ramoops_context { 59struct ramoops_context {
60 void *virt_addr; 60 struct persistent_ram_zone **przs;
61 phys_addr_t phys_addr; 61 phys_addr_t phys_addr;
62 unsigned long size; 62 unsigned long size;
63 size_t record_size; 63 size_t record_size;
@@ -85,39 +85,56 @@ static ssize_t ramoops_pstore_read(u64 *id, enum pstore_type_id *type,
85 struct pstore_info *psi) 85 struct pstore_info *psi)
86{ 86{
87 ssize_t size; 87 ssize_t size;
88 char *rambuf;
89 struct ramoops_context *cxt = psi->data; 88 struct ramoops_context *cxt = psi->data;
89 struct persistent_ram_zone *prz;
90 90
91 if (cxt->read_count >= cxt->max_count) 91 if (cxt->read_count >= cxt->max_count)
92 return -EINVAL; 92 return -EINVAL;
93
93 *id = cxt->read_count++; 94 *id = cxt->read_count++;
95 prz = cxt->przs[*id];
96
94 /* Only supports dmesg output so far. */ 97 /* Only supports dmesg output so far. */
95 *type = PSTORE_TYPE_DMESG; 98 *type = PSTORE_TYPE_DMESG;
96 /* TODO(kees): Bogus time for the moment. */ 99 /* TODO(kees): Bogus time for the moment. */
97 time->tv_sec = 0; 100 time->tv_sec = 0;
98 time->tv_nsec = 0; 101 time->tv_nsec = 0;
99 102
100 rambuf = cxt->virt_addr + (*id * cxt->record_size); 103 size = persistent_ram_old_size(prz);
101 size = strnlen(rambuf, cxt->record_size);
102 *buf = kmalloc(size, GFP_KERNEL); 104 *buf = kmalloc(size, GFP_KERNEL);
103 if (*buf == NULL) 105 if (*buf == NULL)
104 return -ENOMEM; 106 return -ENOMEM;
105 memcpy(*buf, rambuf, size); 107 memcpy(*buf, persistent_ram_old(prz), size);
106 108
107 return size; 109 return size;
108} 110}
109 111
112static size_t ramoops_write_kmsg_hdr(struct persistent_ram_zone *prz)
113{
114 char *hdr;
115 struct timeval timestamp;
116 size_t len;
117
118 do_gettimeofday(&timestamp);
119 hdr = kasprintf(GFP_ATOMIC, RAMOOPS_KERNMSG_HDR "%lu.%lu\n",
120 (long)timestamp.tv_sec, (long)timestamp.tv_usec);
121 WARN_ON_ONCE(!hdr);
122 len = hdr ? strlen(hdr) : 0;
123 persistent_ram_write(prz, hdr, len);
124 kfree(hdr);
125
126 return len;
127}
128
110static int ramoops_pstore_write(enum pstore_type_id type, 129static int ramoops_pstore_write(enum pstore_type_id type,
111 enum kmsg_dump_reason reason, 130 enum kmsg_dump_reason reason,
112 u64 *id, 131 u64 *id,
113 unsigned int part, 132 unsigned int part,
114 size_t size, struct pstore_info *psi) 133 size_t size, struct pstore_info *psi)
115{ 134{
116 char *buf;
117 size_t res;
118 struct timeval timestamp;
119 struct ramoops_context *cxt = psi->data; 135 struct ramoops_context *cxt = psi->data;
120 size_t available = cxt->record_size; 136 struct persistent_ram_zone *prz = cxt->przs[cxt->count];
137 size_t hlen;
121 138
122 /* Currently ramoops is designed to only store dmesg dumps. */ 139 /* Currently ramoops is designed to only store dmesg dumps. */
123 if (type != PSTORE_TYPE_DMESG) 140 if (type != PSTORE_TYPE_DMESG)
@@ -142,22 +159,10 @@ static int ramoops_pstore_write(enum pstore_type_id type,
142 if (part != 1) 159 if (part != 1)
143 return -ENOSPC; 160 return -ENOSPC;
144 161
145 buf = cxt->virt_addr + (cxt->count * cxt->record_size); 162 hlen = ramoops_write_kmsg_hdr(prz);
146 163 if (size + hlen > prz->buffer_size)
147 res = sprintf(buf, "%s", RAMOOPS_KERNMSG_HDR); 164 size = prz->buffer_size - hlen;
148 buf += res; 165 persistent_ram_write(prz, cxt->pstore.buf, size);
149 available -= res;
150
151 do_gettimeofday(&timestamp);
152 res = sprintf(buf, "%lu.%lu\n", (long)timestamp.tv_sec, (long)timestamp.tv_usec);
153 buf += res;
154 available -= res;
155
156 if (size > available)
157 size = available;
158
159 memcpy(buf, cxt->pstore.buf, size);
160 memset(buf + size, '\0', available - size);
161 166
162 cxt->count = (cxt->count + 1) % cxt->max_count; 167 cxt->count = (cxt->count + 1) % cxt->max_count;
163 168
@@ -167,14 +172,12 @@ static int ramoops_pstore_write(enum pstore_type_id type,
167static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, 172static int ramoops_pstore_erase(enum pstore_type_id type, u64 id,
168 struct pstore_info *psi) 173 struct pstore_info *psi)
169{ 174{
170 char *buf;
171 struct ramoops_context *cxt = psi->data; 175 struct ramoops_context *cxt = psi->data;
172 176
173 if (id >= cxt->max_count) 177 if (id >= cxt->max_count)
174 return -EINVAL; 178 return -EINVAL;
175 179
176 buf = cxt->virt_addr + (id * cxt->record_size); 180 persistent_ram_free_old(cxt->przs[id]);
177 memset(buf, '\0', cxt->record_size);
178 181
179 return 0; 182 return 0;
180} 183}
@@ -192,9 +195,11 @@ static struct ramoops_context oops_cxt = {
192 195
193static int __init ramoops_probe(struct platform_device *pdev) 196static int __init ramoops_probe(struct platform_device *pdev)
194{ 197{
198 struct device *dev = &pdev->dev;
195 struct ramoops_platform_data *pdata = pdev->dev.platform_data; 199 struct ramoops_platform_data *pdata = pdev->dev.platform_data;
196 struct ramoops_context *cxt = &oops_cxt; 200 struct ramoops_context *cxt = &oops_cxt;
197 int err = -EINVAL; 201 int err = -EINVAL;
202 int i;
198 203
199 /* Only a single ramoops area allowed at a time, so fail extra 204 /* Only a single ramoops area allowed at a time, so fail extra
200 * probes. 205 * probes.
@@ -232,8 +237,28 @@ static int __init ramoops_probe(struct platform_device *pdev)
232 cxt->record_size = pdata->record_size; 237 cxt->record_size = pdata->record_size;
233 cxt->dump_oops = pdata->dump_oops; 238 cxt->dump_oops = pdata->dump_oops;
234 239
240 cxt->przs = kzalloc(sizeof(*cxt->przs) * cxt->max_count, GFP_KERNEL);
241 if (!cxt->przs) {
242 err = -ENOMEM;
243 dev_err(dev, "failed to initialize a prz array\n");
244 goto fail_out;
245 }
246
247 for (i = 0; i < cxt->max_count; i++) {
248 size_t sz = cxt->record_size;
249 phys_addr_t start = cxt->phys_addr + sz * i;
250
251 cxt->przs[i] = persistent_ram_new(start, sz, 0);
252 if (IS_ERR(cxt->przs[i])) {
253 err = PTR_ERR(cxt->przs[i]);
254 dev_err(dev, "failed to request mem region (0x%zx@0x%llx): %d\n",
255 sz, (unsigned long long)start, err);
256 goto fail_przs;
257 }
258 }
259
235 cxt->pstore.data = cxt; 260 cxt->pstore.data = cxt;
236 cxt->pstore.bufsize = cxt->record_size; 261 cxt->pstore.bufsize = cxt->przs[0]->buffer_size;
237 cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL); 262 cxt->pstore.buf = kmalloc(cxt->pstore.bufsize, GFP_KERNEL);
238 spin_lock_init(&cxt->pstore.buf_lock); 263 spin_lock_init(&cxt->pstore.buf_lock);
239 if (!cxt->pstore.buf) { 264 if (!cxt->pstore.buf) {
@@ -241,23 +266,10 @@ static int __init ramoops_probe(struct platform_device *pdev)
241 goto fail_clear; 266 goto fail_clear;
242 } 267 }
243 268
244 if (!request_mem_region(cxt->phys_addr, cxt->size, "ramoops")) {
245 pr_err("request mem region (0x%lx@0x%llx) failed\n",
246 cxt->size, (unsigned long long)cxt->phys_addr);
247 err = -EINVAL;
248 goto fail_buf;
249 }
250
251 cxt->virt_addr = ioremap(cxt->phys_addr, cxt->size);
252 if (!cxt->virt_addr) {
253 pr_err("ioremap failed\n");
254 goto fail_mem_region;
255 }
256
257 err = pstore_register(&cxt->pstore); 269 err = pstore_register(&cxt->pstore);
258 if (err) { 270 if (err) {
259 pr_err("registering with pstore failed\n"); 271 pr_err("registering with pstore failed\n");
260 goto fail_iounmap; 272 goto fail_buf;
261 } 273 }
262 274
263 /* 275 /*
@@ -275,15 +287,15 @@ static int __init ramoops_probe(struct platform_device *pdev)
275 287
276 return 0; 288 return 0;
277 289
278fail_iounmap:
279 iounmap(cxt->virt_addr);
280fail_mem_region:
281 release_mem_region(cxt->phys_addr, cxt->size);
282fail_buf: 290fail_buf:
283 kfree(cxt->pstore.buf); 291 kfree(cxt->pstore.buf);
284fail_clear: 292fail_clear:
285 cxt->pstore.bufsize = 0; 293 cxt->pstore.bufsize = 0;
286 cxt->max_count = 0; 294 cxt->max_count = 0;
295fail_przs:
296 for (i = 0; cxt->przs[i]; i++)
297 persistent_ram_free(cxt->przs[i]);
298 kfree(cxt->przs);
287fail_out: 299fail_out:
288 return err; 300 return err;
289} 301}