diff options
author | Anton Vorontsov <anton.vorontsov@linaro.org> | 2012-05-17 03:15:18 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-05-17 11:51:41 -0400 |
commit | 896fc1f0c4c6c19b270734f274be67cb0e8a24af (patch) | |
tree | dfdeccb50e7288365d1595a5e57ca21e5824abed /fs/pstore/ram.c | |
parent | cddb8751c80348df75149f44fc3bf38d3dd1f3e6 (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.c | 106 |
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 | ||
59 | struct ramoops_context { | 59 | struct 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 | ||
112 | static 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(×tamp); | ||
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 | |||
110 | static int ramoops_pstore_write(enum pstore_type_id type, | 129 | static 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(×tamp); | ||
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, | |||
167 | static int ramoops_pstore_erase(enum pstore_type_id type, u64 id, | 172 | static 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 | ||
193 | static int __init ramoops_probe(struct platform_device *pdev) | 196 | static 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 | ||
278 | fail_iounmap: | ||
279 | iounmap(cxt->virt_addr); | ||
280 | fail_mem_region: | ||
281 | release_mem_region(cxt->phys_addr, cxt->size); | ||
282 | fail_buf: | 290 | fail_buf: |
283 | kfree(cxt->pstore.buf); | 291 | kfree(cxt->pstore.buf); |
284 | fail_clear: | 292 | fail_clear: |
285 | cxt->pstore.bufsize = 0; | 293 | cxt->pstore.bufsize = 0; |
286 | cxt->max_count = 0; | 294 | cxt->max_count = 0; |
295 | fail_przs: | ||
296 | for (i = 0; cxt->przs[i]; i++) | ||
297 | persistent_ram_free(cxt->przs[i]); | ||
298 | kfree(cxt->przs); | ||
287 | fail_out: | 299 | fail_out: |
288 | return err; | 300 | return err; |
289 | } | 301 | } |