~ubuntu-branches/ubuntu/trusty/linux-armadaxp/trusty

« back to all changes in this revision

Viewing changes to fs/pstore/platform.c

  • Committer: Package Import Robot
  • Author(s): Michael Casadevall, Bryan Wu, Dann Frazier, Michael Casadeall
  • Date: 2012-03-10 15:00:54 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120310150054-flugb39zon8vvgwe
Tags: 3.2.0-1600.1
[ Bryan Wu ]
* UBUNTU: import debian/debian.env and debian.armadaxp

[ Dann Frazier ]
* ARM: Armada XP: remove trailing '/' in dirnames in mvRules.mk

[ Michael Casadeall ]
* tools: add some tools for Marvell Armada XP processor
* kernel: timer tick hacking from Marvell
* kernel: Sheeva Errata: add delay on Sheeva when powering down
* net: add Marvell NFP netfilter
* net: socket and skb modifications made by Marvell
* miscdevice: add minor IDs for some Marvell Armada drivers
* fs: introduce memory pool for splice()
* video: EDID detection updates from Marvell Armada XP patchset
* video: backlight: add Marvell Dove LCD backlight driver
* video: display: add THS8200 display driver
* video: framebuffer: add Marvell Dove and Armada XP processor onchip LCD controller driver
* usbtest: add Interrupt transfer testing by Marvell Armada XP code
* usb: ehci: add support for Marvell EHCI controler
* tty/serial: 8250: add support for Marvell Armada XP processor and DeviceTree work
* rtc: add support for Marvell Armada XP onchip RTC controller
* net: pppoe: add Marvell ethernet NFP hook in PPPoE networking driver
* mtd: nand: add support for Marvell Armada XP Nand Flash Controller
* mtd: maps: add Marvell Armada XP specific map driver
* mmc: add support for Marvell Armada XP MMC/SD host controller
* i2c: add support for Marvell Armada XP onchip i2c bus controller
* hwmon: add Kconfig option for Armada XP onchip thermal sensor driver
* dmaengine: add Net DMA support for splice and update Marvell XOR DMA engine driver
* ata: add support for Marvell Armada XP SATA controller and update some quirks
* ARM: add Marvell Armada XP machine to mach-types
* ARM: oprofile: add support for Marvell PJ4B core
* ARM: mm: more ARMv6 switches for Marvell Armada XP
* ARM: remove static declaration to allow compilation
* ARM: alignment access fault trick
* ARM: mm: skip some fault fixing when run on NONE SMP ARMv6 mode during early abort event
* ARM: mm: add Marvell Sheeva CPU Architecture for PJ4B
* ARM: introduce optimized copy operation for Marvell Armada XP
* ARM: SAUCE: hardware breakpoint trick for Marvell Armada XP
* ARM: big endian and little endian tricks for Marvell Armada XP
* ARM: SAUCE: Add Marvell Armada XP build rules to arch/arm/kernel/Makefile
* ARM: vfp: add special handling for Marvell Armada XP
* ARM: add support for Marvell U-Boot
* ARM: add mv_controller_num for ARM PCI drivers
* ARM: add support for local PMUs, general SMP tweaks and cache flushing
* ARM: add Marvell device identifies in glue-proc.h
* ARM: add IPC driver support for Marvell platforms
* ARM: add DMA mapping for Marvell platforms
* ARM: add Sheeva errata and PJ4B code for booting
* ARM: update Kconfig and Makefile to include Marvell Armada XP platforms
* ARM: Armada XP: import LSP from Marvell for Armada XP 3.2 kernel enablement

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <linux/module.h>
26
26
#include <linux/pstore.h>
27
27
#include <linux/string.h>
 
28
#include <linux/timer.h>
28
29
#include <linux/slab.h>
29
30
#include <linux/uaccess.h>
 
31
#include <linux/hardirq.h>
 
32
#include <linux/workqueue.h>
30
33
 
31
34
#include "internal.h"
32
35
 
33
36
/*
 
37
 * We defer making "oops" entries appear in pstore - see
 
38
 * whether the system is actually still running well enough
 
39
 * to let someone see the entry
 
40
 */
 
41
#define PSTORE_INTERVAL (60 * HZ)
 
42
 
 
43
static int pstore_new_entry;
 
44
 
 
45
static void pstore_timefunc(unsigned long);
 
46
static DEFINE_TIMER(pstore_timer, pstore_timefunc, 0, 0);
 
47
 
 
48
static void pstore_dowork(struct work_struct *);
 
49
static DECLARE_WORK(pstore_work, pstore_dowork);
 
50
 
 
51
/*
34
52
 * pstore_lock just protects "psinfo" during
35
53
 * calls to pstore_register()
36
54
 */
37
55
static DEFINE_SPINLOCK(pstore_lock);
38
56
static struct pstore_info *psinfo;
39
57
 
 
58
static char *backend;
 
59
 
40
60
/* How much of the console log to snapshot */
41
61
static unsigned long kmsg_bytes = 10240;
42
62
 
67
87
        unsigned long   size, total = 0;
68
88
        char            *dst, *why;
69
89
        u64             id;
70
 
        int             hsize, part = 1;
 
90
        int             hsize, ret;
 
91
        unsigned int    part = 1;
 
92
        unsigned long   flags = 0;
 
93
        int             is_locked = 0;
71
94
 
72
95
        if (reason < ARRAY_SIZE(reason_str))
73
96
                why = reason_str[reason];
74
97
        else
75
98
                why = "Unknown";
76
99
 
77
 
        mutex_lock(&psinfo->buf_mutex);
 
100
        if (in_nmi()) {
 
101
                is_locked = spin_trylock(&psinfo->buf_lock);
 
102
                if (!is_locked)
 
103
                        pr_err("pstore dump routine blocked in NMI, may corrupt error record\n");
 
104
        } else
 
105
                spin_lock_irqsave(&psinfo->buf_lock, flags);
78
106
        oopscount++;
79
107
        while (total < kmsg_bytes) {
80
108
                dst = psinfo->buf;
81
 
                hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part++);
 
109
                hsize = sprintf(dst, "%s#%d Part%d\n", why, oopscount, part);
82
110
                size = psinfo->bufsize - hsize;
83
111
                dst += hsize;
84
112
 
94
122
                memcpy(dst, s1 + s1_start, l1_cpy);
95
123
                memcpy(dst + l1_cpy, s2 + s2_start, l2_cpy);
96
124
 
97
 
                id = psinfo->write(PSTORE_TYPE_DMESG, hsize + l1_cpy + l2_cpy);
98
 
                if (reason == KMSG_DUMP_OOPS && pstore_is_mounted())
99
 
                        pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id,
100
 
                                      psinfo->buf, hsize + l1_cpy + l2_cpy,
101
 
                                      CURRENT_TIME, psinfo->erase);
 
125
                ret = psinfo->write(PSTORE_TYPE_DMESG, &id, part,
 
126
                                   hsize + l1_cpy + l2_cpy, psinfo);
 
127
                if (ret == 0 && reason == KMSG_DUMP_OOPS && pstore_is_mounted())
 
128
                        pstore_new_entry = 1;
102
129
                l1 -= l1_cpy;
103
130
                l2 -= l2_cpy;
104
131
                total += l1_cpy + l2_cpy;
 
132
                part++;
105
133
        }
106
 
        mutex_unlock(&psinfo->buf_mutex);
 
134
        if (in_nmi()) {
 
135
                if (is_locked)
 
136
                        spin_unlock(&psinfo->buf_lock);
 
137
        } else
 
138
                spin_unlock_irqrestore(&psinfo->buf_lock, flags);
107
139
}
108
140
 
109
141
static struct kmsg_dumper pstore_dumper = {
128
160
                spin_unlock(&pstore_lock);
129
161
                return -EBUSY;
130
162
        }
 
163
 
 
164
        if (backend && strcmp(backend, psi->name)) {
 
165
                spin_unlock(&pstore_lock);
 
166
                return -EINVAL;
 
167
        }
 
168
 
131
169
        psinfo = psi;
 
170
        mutex_init(&psinfo->read_mutex);
132
171
        spin_unlock(&pstore_lock);
133
172
 
134
173
        if (owner && !try_module_get(owner)) {
137
176
        }
138
177
 
139
178
        if (pstore_is_mounted())
140
 
                pstore_get_records();
 
179
                pstore_get_records(0);
141
180
 
142
181
        kmsg_dump_register(&pstore_dumper);
143
182
 
 
183
        pstore_timer.expires = jiffies + PSTORE_INTERVAL;
 
184
        add_timer(&pstore_timer);
 
185
 
144
186
        return 0;
145
187
}
146
188
EXPORT_SYMBOL_GPL(pstore_register);
147
189
 
148
190
/*
149
 
 * Read all the records from the persistent store. Create and
150
 
 * file files in our filesystem.
 
191
 * Read all the records from the persistent store. Create
 
192
 * files in our filesystem.  Don't warn about -EEXIST errors
 
193
 * when we are re-scanning the backing store looking to add new
 
194
 * error records.
151
195
 */
152
 
void pstore_get_records(void)
 
196
void pstore_get_records(int quiet)
153
197
{
154
198
        struct pstore_info *psi = psinfo;
 
199
        char                    *buf = NULL;
155
200
        ssize_t                 size;
156
201
        u64                     id;
157
202
        enum pstore_type_id     type;
161
206
        if (!psi)
162
207
                return;
163
208
 
164
 
        mutex_lock(&psinfo->buf_mutex);
 
209
        mutex_lock(&psi->read_mutex);
165
210
        rc = psi->open(psi);
166
211
        if (rc)
167
212
                goto out;
168
213
 
169
 
        while ((size = psi->read(&id, &type, &time)) > 0) {
170
 
                if (pstore_mkfile(type, psi->name, id, psi->buf, (size_t)size,
171
 
                                  time, psi->erase))
 
214
        while ((size = psi->read(&id, &type, &time, &buf, psi)) > 0) {
 
215
                rc = pstore_mkfile(type, psi->name, id, buf, (size_t)size,
 
216
                                  time, psi);
 
217
                kfree(buf);
 
218
                buf = NULL;
 
219
                if (rc && (rc != -EEXIST || !quiet))
172
220
                        failed++;
173
221
        }
174
222
        psi->close(psi);
175
223
out:
176
 
        mutex_unlock(&psinfo->buf_mutex);
 
224
        mutex_unlock(&psi->read_mutex);
177
225
 
178
226
        if (failed)
179
227
                printk(KERN_WARNING "pstore: failed to load %d record(s) from '%s'\n",
180
228
                       failed, psi->name);
181
229
}
182
230
 
 
231
static void pstore_dowork(struct work_struct *work)
 
232
{
 
233
        pstore_get_records(1);
 
234
}
 
235
 
 
236
static void pstore_timefunc(unsigned long dummy)
 
237
{
 
238
        if (pstore_new_entry) {
 
239
                pstore_new_entry = 0;
 
240
                schedule_work(&pstore_work);
 
241
        }
 
242
 
 
243
        mod_timer(&pstore_timer, jiffies + PSTORE_INTERVAL);
 
244
}
 
245
 
183
246
/*
184
247
 * Call platform driver to write a record to the
185
248
 * persistent store.
186
249
 */
187
250
int pstore_write(enum pstore_type_id type, char *buf, size_t size)
188
251
{
189
 
        u64     id;
 
252
        u64             id;
 
253
        int             ret;
 
254
        unsigned long   flags;
190
255
 
191
256
        if (!psinfo)
192
257
                return -ENODEV;
194
259
        if (size > psinfo->bufsize)
195
260
                return -EFBIG;
196
261
 
197
 
        mutex_lock(&psinfo->buf_mutex);
 
262
        spin_lock_irqsave(&psinfo->buf_lock, flags);
198
263
        memcpy(psinfo->buf, buf, size);
199
 
        id = psinfo->write(type, size);
200
 
        if (pstore_is_mounted())
 
264
        ret = psinfo->write(type, &id, 0, size, psinfo);
 
265
        if (ret == 0 && pstore_is_mounted())
201
266
                pstore_mkfile(PSTORE_TYPE_DMESG, psinfo->name, id, psinfo->buf,
202
 
                              size, CURRENT_TIME, psinfo->erase);
203
 
        mutex_unlock(&psinfo->buf_mutex);
 
267
                              size, CURRENT_TIME, psinfo);
 
268
        spin_unlock_irqrestore(&psinfo->buf_lock, flags);
204
269
 
205
270
        return 0;
206
271
}
207
272
EXPORT_SYMBOL_GPL(pstore_write);
 
273
 
 
274
module_param(backend, charp, 0444);
 
275
MODULE_PARM_DESC(backend, "Pstore backend to use");