Blame view

drivers/char/ps3flash.c 10 KB
935912c53   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
2
3
4
5
6
  /*
   * PS3 FLASH ROM Storage Driver
   *
   * Copyright (C) 2007 Sony Computer Entertainment Inc.
   * Copyright 2007 Sony Corp.
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
7
8
9
10
   */
  
  #include <linux/fs.h>
  #include <linux/miscdevice.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
11
  #include <linux/slab.h>
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
12
  #include <linux/uaccess.h>
c22405c98   Paul Gortmaker   drivers/char: Add...
13
  #include <linux/module.h>
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
14
15
16
17
18
19
20
21
22
23
24
25
  
  #include <asm/lv1call.h>
  #include <asm/ps3stor.h>
  
  
  #define DEVICE_NAME		"ps3flash"
  
  #define FLASH_BLOCK_SIZE	(256*1024)
  
  
  struct ps3flash_private {
  	struct mutex mutex;	/* Bounce buffer mutex */
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
26
27
28
  	u64 chunk_sectors;
  	int tag;		/* Start sector of buffer, -1 if invalid */
  	bool dirty;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
29
30
31
  };
  
  static struct ps3_storage_device *ps3flash_dev;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
32
  static int ps3flash_read_write_sectors(struct ps3_storage_device *dev,
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
33
  				       u64 start_sector, int write)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
34
  {
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
35
36
37
  	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
  	u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar,
  					     start_sector, priv->chunk_sectors,
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
38
39
  					     write);
  	if (res) {
4c33d2dc3   Stephen Rothwell   powerpc/ps3: Prin...
40
41
  		dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx
  ", __func__,
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
42
43
44
  			__LINE__, write ? "write" : "read", res);
  		return -EIO;
  	}
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
45
  	return 0;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
46
  }
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
47
  static int ps3flash_writeback(struct ps3_storage_device *dev)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
48
  {
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
49
50
  	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
  	int res;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
51

6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
52
53
  	if (!priv->dirty || priv->tag < 0)
  		return 0;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
54
  	res = ps3flash_read_write_sectors(dev, priv->tag, 1);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
55
56
  	if (res)
  		return res;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
57

6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
58
59
  	priv->dirty = false;
  	return 0;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
60
  }
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
61
  static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
62
  {
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
63
  	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
64
  	int res;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
65
  	if (start_sector == priv->tag)
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
66
67
68
69
70
71
72
  		return 0;
  
  	res = ps3flash_writeback(dev);
  	if (res)
  		return res;
  
  	priv->tag = -1;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
73
  	res = ps3flash_read_write_sectors(dev, start_sector, 0);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
74
75
  	if (res)
  		return res;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
76
  	priv->tag = start_sector;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
77
  	return 0;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
78
79
80
81
82
  }
  
  static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
  {
  	struct ps3_storage_device *dev = ps3flash_dev;
ee3246524   Al Viro   ps3flash: switch ...
83
84
  	return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
  			dev->regions[dev->region_idx].size*dev->blk_size);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
85
  }
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
86
87
  static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
  			     size_t count, loff_t *pos)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
88
89
  {
  	struct ps3_storage_device *dev = ps3flash_dev;
559dc87f5   Geert Uytterhoeven   ps3flash: Use ps3...
90
  	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
91
  	u64 size, sector, offset;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
92
  	int res;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
93
  	size_t remaining, n;
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
94
  	const void *src;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
95
96
  
  	dev_dbg(&dev->sbd.core,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
97
98
99
  		"%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p
  ",
  		__func__, __LINE__, count, *pos, userbuf, kernelbuf);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
100
101
102
103
104
105
106
107
108
109
110
111
  
  	size = dev->regions[dev->region_idx].size*dev->blk_size;
  	if (*pos >= size || !count)
  		return 0;
  
  	if (*pos + count > size) {
  		dev_dbg(&dev->sbd.core,
  			"%s:%u Truncating count from %zu to %llu
  ", __func__,
  			__LINE__, count, size - *pos);
  		count = size - *pos;
  	}
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
112
  	sector = *pos / dev->bounce_size * priv->chunk_sectors;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
113
  	offset = *pos % dev->bounce_size;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
114
115
116
  
  	remaining = count;
  	do {
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
117
118
  		n = min_t(u64, remaining, dev->bounce_size - offset);
  		src = dev->bounce_buf + offset;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
119

f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
120
  		mutex_lock(&priv->mutex);
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
121
  		res = ps3flash_fetch(dev, sector);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
122
  		if (res)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
123
  			goto fail;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
124

f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
125
  		dev_dbg(&dev->sbd.core,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
126
127
128
129
130
  			"%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p
  ",
  			__func__, __LINE__, n, src, userbuf, kernelbuf);
  		if (userbuf) {
  			if (copy_to_user(userbuf, src, n)) {
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
131
  				res = -EFAULT;
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
132
133
134
135
136
137
138
  				goto fail;
  			}
  			userbuf += n;
  		}
  		if (kernelbuf) {
  			memcpy(kernelbuf, src, n);
  			kernelbuf += n;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
139
140
141
142
143
  		}
  
  		mutex_unlock(&priv->mutex);
  
  		*pos += n;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
144
  		remaining -= n;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
145
  		sector += priv->chunk_sectors;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
146
147
148
149
150
151
  		offset = 0;
  	} while (remaining > 0);
  
  	return count;
  
  fail:
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
152
153
  	mutex_unlock(&priv->mutex);
  	return res;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
154
  }
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
155
156
  static ssize_t ps3flash_write(const char __user *userbuf,
  			      const void *kernelbuf, size_t count, loff_t *pos)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
157
158
  {
  	struct ps3_storage_device *dev = ps3flash_dev;
559dc87f5   Geert Uytterhoeven   ps3flash: Use ps3...
159
  	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
160
161
  	u64 size, sector, offset;
  	int res = 0;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
162
  	size_t remaining, n;
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
163
  	void *dst;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
164
165
  
  	dev_dbg(&dev->sbd.core,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
166
167
168
  		"%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p
  ",
  		__func__, __LINE__, count, *pos, userbuf, kernelbuf);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
169
170
171
172
173
174
175
176
177
178
179
180
  
  	size = dev->regions[dev->region_idx].size*dev->blk_size;
  	if (*pos >= size || !count)
  		return 0;
  
  	if (*pos + count > size) {
  		dev_dbg(&dev->sbd.core,
  			"%s:%u Truncating count from %zu to %llu
  ", __func__,
  			__LINE__, count, size - *pos);
  		count = size - *pos;
  	}
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
181
  	sector = *pos / dev->bounce_size * priv->chunk_sectors;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
182
  	offset = *pos % dev->bounce_size;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
183
184
185
  
  	remaining = count;
  	do {
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
186
  		n = min_t(u64, remaining, dev->bounce_size - offset);
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
187
  		dst = dev->bounce_buf + offset;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
188

f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
189
  		mutex_lock(&priv->mutex);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
190
  		if (n != dev->bounce_size)
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
191
  			res = ps3flash_fetch(dev, sector);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
192
193
194
195
  		else if (sector != priv->tag)
  			res = ps3flash_writeback(dev);
  		if (res)
  			goto fail;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
196

f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
197
  		dev_dbg(&dev->sbd.core,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
198
199
200
201
202
203
204
205
206
207
208
209
210
  			"%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p
  ",
  			__func__, __LINE__, n, userbuf, kernelbuf, dst);
  		if (userbuf) {
  			if (copy_from_user(dst, userbuf, n)) {
  				res = -EFAULT;
  				goto fail;
  			}
  			userbuf += n;
  		}
  		if (kernelbuf) {
  			memcpy(dst, kernelbuf, n);
  			kernelbuf += n;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
211
  		}
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
212
213
  		priv->tag = sector;
  		priv->dirty = true;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
214
215
216
217
  
  		mutex_unlock(&priv->mutex);
  
  		*pos += n;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
218
  		remaining -= n;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
219
  		sector += priv->chunk_sectors;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
220
221
222
223
224
225
226
227
228
  		offset = 0;
  	} while (remaining > 0);
  
  	return count;
  
  fail:
  	mutex_unlock(&priv->mutex);
  	return res;
  }
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
  static ssize_t ps3flash_user_read(struct file *file, char __user *buf,
  				  size_t count, loff_t *pos)
  {
  	return ps3flash_read(buf, NULL, count, pos);
  }
  
  static ssize_t ps3flash_user_write(struct file *file, const char __user *buf,
  				   size_t count, loff_t *pos)
  {
  	return ps3flash_write(buf, NULL, count, pos);
  }
  
  static ssize_t ps3flash_kernel_read(void *buf, size_t count, loff_t pos)
  {
  	return ps3flash_read(NULL, buf, count, &pos);
  }
  
  static ssize_t ps3flash_kernel_write(const void *buf, size_t count,
  				     loff_t pos)
  {
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
249
250
251
252
253
254
255
256
257
258
259
260
261
  	ssize_t res;
  	int wb;
  
  	res = ps3flash_write(NULL, buf, count, &pos);
  	if (res < 0)
  		return res;
  
  	/* Make kernel writes synchronous */
  	wb = ps3flash_writeback(ps3flash_dev);
  	if (wb)
  		return wb;
  
  	return res;
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
262
  }
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
263
264
265
266
  static int ps3flash_flush(struct file *file, fl_owner_t id)
  {
  	return ps3flash_writeback(ps3flash_dev);
  }
02c24a821   Josef Bacik   fs: push i_mutex ...
267
  static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync)
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
268
  {
496ad9aa8   Al Viro   new helper: file_...
269
  	struct inode *inode = file_inode(file);
02c24a821   Josef Bacik   fs: push i_mutex ...
270
  	int err;
5955102c9   Al Viro   wrappers for ->i_...
271
  	inode_lock(inode);
02c24a821   Josef Bacik   fs: push i_mutex ...
272
  	err = ps3flash_writeback(ps3flash_dev);
5955102c9   Al Viro   wrappers for ->i_...
273
  	inode_unlock(inode);
02c24a821   Josef Bacik   fs: push i_mutex ...
274
  	return err;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
275
  }
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
276
277
278
279
280
281
282
283
284
285
286
  
  static irqreturn_t ps3flash_interrupt(int irq, void *data)
  {
  	struct ps3_storage_device *dev = data;
  	int res;
  	u64 tag, status;
  
  	res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
  
  	if (tag != dev->tag)
  		dev_err(&dev->sbd.core,
4c33d2dc3   Stephen Rothwell   powerpc/ps3: Prin...
287
288
  			"%s:%u: tag mismatch, got %llx, expected %llx
  ",
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
289
290
291
  			__func__, __LINE__, tag, dev->tag);
  
  	if (res) {
4c33d2dc3   Stephen Rothwell   powerpc/ps3: Prin...
292
293
  		dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx
  ",
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
294
295
296
297
298
299
300
  			__func__, __LINE__, res, status);
  	} else {
  		dev->lv1_status = status;
  		complete(&dev->done);
  	}
  	return IRQ_HANDLED;
  }
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
301
302
303
  static const struct file_operations ps3flash_fops = {
  	.owner	= THIS_MODULE,
  	.llseek	= ps3flash_llseek,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
304
305
  	.read	= ps3flash_user_read,
  	.write	= ps3flash_user_write,
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
306
307
  	.flush	= ps3flash_flush,
  	.fsync	= ps3flash_fsync,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
308
309
310
311
312
  };
  
  static const struct ps3_os_area_flash_ops ps3flash_kernel_ops = {
  	.read	= ps3flash_kernel_read,
  	.write	= ps3flash_kernel_write,
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
313
314
315
316
317
318
319
  };
  
  static struct miscdevice ps3flash_misc = {
  	.minor	= MISC_DYNAMIC_MINOR,
  	.name	= DEVICE_NAME,
  	.fops	= &ps3flash_fops,
  };
2223cbec3   Bill Pemberton   char: remove use ...
320
  static int ps3flash_probe(struct ps3_system_bus_device *_dev)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
  {
  	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
  	struct ps3flash_private *priv;
  	int error;
  	unsigned long tmp;
  
  	tmp = dev->regions[dev->region_idx].start*dev->blk_size;
  	if (tmp % FLASH_BLOCK_SIZE) {
  		dev_err(&dev->sbd.core,
  			"%s:%u region start %lu is not aligned
  ", __func__,
  			__LINE__, tmp);
  		return -EINVAL;
  	}
  	tmp = dev->regions[dev->region_idx].size*dev->blk_size;
  	if (tmp % FLASH_BLOCK_SIZE) {
  		dev_err(&dev->sbd.core,
  			"%s:%u region size %lu is not aligned
  ", __func__,
  			__LINE__, tmp);
  		return -EINVAL;
  	}
  
  	/* use static buffer, kmalloc cannot allocate 256 KiB */
  	if (!ps3flash_bounce_buffer.address)
  		return -ENODEV;
  
  	if (ps3flash_dev) {
  		dev_err(&dev->sbd.core,
  			"Only one FLASH device is supported
  ");
  		return -EBUSY;
  	}
  
  	ps3flash_dev = dev;
  
  	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  	if (!priv) {
  		error = -ENOMEM;
  		goto fail;
  	}
559dc87f5   Geert Uytterhoeven   ps3flash: Use ps3...
362
  	ps3_system_bus_set_drvdata(&dev->sbd, priv);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
363
  	mutex_init(&priv->mutex);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
364
  	priv->tag = -1;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
365
366
367
  
  	dev->bounce_size = ps3flash_bounce_buffer.size;
  	dev->bounce_buf = ps3flash_bounce_buffer.address;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
368
  	priv->chunk_sectors = dev->bounce_size / dev->blk_size;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
  
  	error = ps3stor_setup(dev, ps3flash_interrupt);
  	if (error)
  		goto fail_free_priv;
  
  	ps3flash_misc.parent = &dev->sbd.core;
  	error = misc_register(&ps3flash_misc);
  	if (error) {
  		dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d
  ",
  			__func__, __LINE__, error);
  		goto fail_teardown;
  	}
  
  	dev_info(&dev->sbd.core, "%s:%u: registered misc device %d
  ",
  		 __func__, __LINE__, ps3flash_misc.minor);
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
386
387
  
  	ps3_os_area_flash_register(&ps3flash_kernel_ops);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
388
389
390
391
392
393
  	return 0;
  
  fail_teardown:
  	ps3stor_teardown(dev);
  fail_free_priv:
  	kfree(priv);
559dc87f5   Geert Uytterhoeven   ps3flash: Use ps3...
394
  	ps3_system_bus_set_drvdata(&dev->sbd, NULL);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
395
396
397
398
399
400
401
402
  fail:
  	ps3flash_dev = NULL;
  	return error;
  }
  
  static int ps3flash_remove(struct ps3_system_bus_device *_dev)
  {
  	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
403
  	ps3_os_area_flash_register(NULL);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
404
405
  	misc_deregister(&ps3flash_misc);
  	ps3stor_teardown(dev);
559dc87f5   Geert Uytterhoeven   ps3flash: Use ps3...
406
407
  	kfree(ps3_system_bus_get_drvdata(&dev->sbd));
  	ps3_system_bus_set_drvdata(&dev->sbd, NULL);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
  	ps3flash_dev = NULL;
  	return 0;
  }
  
  
  static struct ps3_system_bus_driver ps3flash = {
  	.match_id	= PS3_MATCH_ID_STOR_FLASH,
  	.core.name	= DEVICE_NAME,
  	.core.owner	= THIS_MODULE,
  	.probe		= ps3flash_probe,
  	.remove		= ps3flash_remove,
  	.shutdown	= ps3flash_remove,
  };
  
  
  static int __init ps3flash_init(void)
  {
  	return ps3_system_bus_driver_register(&ps3flash);
  }
  
  static void __exit ps3flash_exit(void)
  {
  	ps3_system_bus_driver_unregister(&ps3flash);
  }
  
  module_init(ps3flash_init);
  module_exit(ps3flash_exit);
  
  MODULE_LICENSE("GPL");
  MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver");
  MODULE_AUTHOR("Sony Corporation");
  MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH);