Blame view

drivers/char/ps3flash.c 10.7 KB
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
  /*
   * PS3 FLASH ROM Storage Driver
   *
   * Copyright (C) 2007 Sony Computer Entertainment Inc.
   * Copyright 2007 Sony Corp.
   *
   * This program is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License as published
   * by the Free Software Foundation; version 2 of the License.
   *
   * This program is distributed in the hope that it will be useful, but
   * WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License along
   * with this program; if not, write to the Free Software Foundation, Inc.,
   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
   */
  
  #include <linux/fs.h>
  #include <linux/miscdevice.h>
  #include <linux/uaccess.h>
  
  #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...
36
37
38
  	u64 chunk_sectors;
  	int tag;		/* Start sector of buffer, -1 if invalid */
  	bool dirty;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
39
40
41
  };
  
  static struct ps3_storage_device *ps3flash_dev;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
42
  static int ps3flash_read_write_sectors(struct ps3_storage_device *dev,
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
43
  				       u64 start_sector, int write)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
44
  {
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
45
46
47
  	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...
48
49
  					     write);
  	if (res) {
4c33d2dc3   Stephen Rothwell   powerpc/ps3: Prin...
50
51
  		dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx
  ", __func__,
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
52
53
54
  			__LINE__, write ? "write" : "read", res);
  		return -EIO;
  	}
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
55
  	return 0;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
56
  }
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
57
  static int ps3flash_writeback(struct ps3_storage_device *dev)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
58
  {
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
59
60
  	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
  	int res;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
61

6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
62
63
  	if (!priv->dirty || priv->tag < 0)
  		return 0;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
64
  	res = ps3flash_read_write_sectors(dev, priv->tag, 1);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
65
66
  	if (res)
  		return res;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
67

6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
68
69
  	priv->dirty = false;
  	return 0;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
70
  }
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
71
  static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
72
  {
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
73
  	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
74
  	int res;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
75
  	if (start_sector == priv->tag)
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
76
77
78
79
80
81
82
  		return 0;
  
  	res = ps3flash_writeback(dev);
  	if (res)
  		return res;
  
  	priv->tag = -1;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
83
  	res = ps3flash_read_write_sectors(dev, start_sector, 0);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
84
85
  	if (res)
  		return res;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
86
  	priv->tag = start_sector;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
87
  	return 0;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
  }
  
  static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
  {
  	struct ps3_storage_device *dev = ps3flash_dev;
  	loff_t res;
  
  	mutex_lock(&file->f_mapping->host->i_mutex);
  	switch (origin) {
  	case 1:
  		offset += file->f_pos;
  		break;
  	case 2:
  		offset += dev->regions[dev->region_idx].size*dev->blk_size;
  		break;
  	}
  	if (offset < 0) {
  		res = -EINVAL;
  		goto out;
  	}
  
  	file->f_pos = offset;
  	res = file->f_pos;
  
  out:
  	mutex_unlock(&file->f_mapping->host->i_mutex);
  	return res;
  }
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
116
117
  static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
  			     size_t count, loff_t *pos)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
118
119
  {
  	struct ps3_storage_device *dev = ps3flash_dev;
559dc87f5   Geert Uytterhoeven   ps3flash: Use ps3...
120
  	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
121
  	u64 size, sector, offset;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
122
  	int res;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
123
  	size_t remaining, n;
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
124
  	const void *src;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
125
126
  
  	dev_dbg(&dev->sbd.core,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
127
128
129
  		"%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...
130
131
132
133
134
135
136
137
138
139
140
141
  
  	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 ...
142
  	sector = *pos / dev->bounce_size * priv->chunk_sectors;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
143
  	offset = *pos % dev->bounce_size;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
144
145
146
  
  	remaining = count;
  	do {
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
147
148
  		n = min_t(u64, remaining, dev->bounce_size - offset);
  		src = dev->bounce_buf + offset;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
149

f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
150
  		mutex_lock(&priv->mutex);
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
151
  		res = ps3flash_fetch(dev, sector);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
152
  		if (res)
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
153
  			goto fail;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
154

f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
155
  		dev_dbg(&dev->sbd.core,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
156
157
158
159
160
  			"%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...
161
  				res = -EFAULT;
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
162
163
164
165
166
167
168
  				goto fail;
  			}
  			userbuf += n;
  		}
  		if (kernelbuf) {
  			memcpy(kernelbuf, src, n);
  			kernelbuf += n;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
169
170
171
172
173
  		}
  
  		mutex_unlock(&priv->mutex);
  
  		*pos += n;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
174
  		remaining -= n;
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
175
  		sector += priv->chunk_sectors;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
176
177
178
179
180
181
  		offset = 0;
  	} while (remaining > 0);
  
  	return count;
  
  fail:
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
182
183
  	mutex_unlock(&priv->mutex);
  	return res;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
184
  }
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
185
186
  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...
187
188
  {
  	struct ps3_storage_device *dev = ps3flash_dev;
559dc87f5   Geert Uytterhoeven   ps3flash: Use ps3...
189
  	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
190
191
  	u64 size, sector, offset;
  	int res = 0;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
192
  	size_t remaining, n;
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
193
  	void *dst;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
194
195
  
  	dev_dbg(&dev->sbd.core,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
196
197
198
  		"%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...
199
200
201
202
203
204
205
206
207
208
209
210
  
  	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...
211
  	sector = *pos / dev->bounce_size * priv->chunk_sectors;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
212
  	offset = *pos % dev->bounce_size;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
213
214
215
  
  	remaining = count;
  	do {
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
216
  		n = min_t(u64, remaining, dev->bounce_size - offset);
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
217
  		dst = dev->bounce_buf + offset;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
218

f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
219
  		mutex_lock(&priv->mutex);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
220
  		if (n != dev->bounce_size)
42e27bfc4   Geert Uytterhoeven   ps3flash: Always ...
221
  			res = ps3flash_fetch(dev, sector);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
222
223
224
225
  		else if (sector != priv->tag)
  			res = ps3flash_writeback(dev);
  		if (res)
  			goto fail;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
226

f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
227
  		dev_dbg(&dev->sbd.core,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
228
229
230
231
232
233
234
235
236
237
238
239
240
  			"%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...
241
  		}
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
242
243
  		priv->tag = sector;
  		priv->dirty = true;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
244
245
246
247
  
  		mutex_unlock(&priv->mutex);
  
  		*pos += n;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
248
  		remaining -= n;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
249
  		sector += priv->chunk_sectors;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
250
251
252
253
254
255
256
257
258
  		offset = 0;
  	} while (remaining > 0);
  
  	return count;
  
  fail:
  	mutex_unlock(&priv->mutex);
  	return res;
  }
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
  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...
279
280
281
282
283
284
285
286
287
288
289
290
291
  	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...
292
  }
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
293
294
295
296
297
298
299
300
301
302
  static int ps3flash_flush(struct file *file, fl_owner_t id)
  {
  	return ps3flash_writeback(ps3flash_dev);
  }
  
  static int ps3flash_fsync(struct file *file, struct dentry *dentry,
  			  int datasync)
  {
  	return ps3flash_writeback(ps3flash_dev);
  }
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
303
304
305
306
307
308
309
310
311
312
313
  
  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...
314
315
  			"%s:%u: tag mismatch, got %llx, expected %llx
  ",
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
316
317
318
  			__func__, __LINE__, tag, dev->tag);
  
  	if (res) {
4c33d2dc3   Stephen Rothwell   powerpc/ps3: Prin...
319
320
  		dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx
  ",
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
321
322
323
324
325
326
327
  			__func__, __LINE__, res, status);
  	} else {
  		dev->lv1_status = status;
  		complete(&dev->done);
  	}
  	return IRQ_HANDLED;
  }
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
328
329
330
  static const struct file_operations ps3flash_fops = {
  	.owner	= THIS_MODULE,
  	.llseek	= ps3flash_llseek,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
331
332
  	.read	= ps3flash_user_read,
  	.write	= ps3flash_user_write,
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
333
334
  	.flush	= ps3flash_flush,
  	.fsync	= ps3flash_fsync,
a4e623fbc   Geert Uytterhoeven   ps3: Replace dire...
335
336
337
338
339
  };
  
  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...
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
  };
  
  static struct miscdevice ps3flash_misc = {
  	.minor	= MISC_DYNAMIC_MINOR,
  	.name	= DEVICE_NAME,
  	.fops	= &ps3flash_fops,
  };
  
  static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
  {
  	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...
390
  	ps3_system_bus_set_drvdata(&dev->sbd, priv);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
391
  	mutex_init(&priv->mutex);
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
392
  	priv->tag = -1;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
393
394
395
  
  	dev->bounce_size = ps3flash_bounce_buffer.size;
  	dev->bounce_buf = ps3flash_bounce_buffer.address;
6bd57f2e5   Geert Uytterhoeven   ps3flash: Cache t...
396
  	priv->chunk_sectors = dev->bounce_size / dev->blk_size;
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
  
  	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...
414
415
  
  	ps3_os_area_flash_register(&ps3flash_kernel_ops);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
416
417
418
419
420
421
  	return 0;
  
  fail_teardown:
  	ps3stor_teardown(dev);
  fail_free_priv:
  	kfree(priv);
559dc87f5   Geert Uytterhoeven   ps3flash: Use ps3...
422
  	ps3_system_bus_set_drvdata(&dev->sbd, NULL);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
423
424
425
426
427
428
429
430
  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...
431
  	ps3_os_area_flash_register(NULL);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
432
433
  	misc_deregister(&ps3flash_misc);
  	ps3stor_teardown(dev);
559dc87f5   Geert Uytterhoeven   ps3flash: Use ps3...
434
435
  	kfree(ps3_system_bus_get_drvdata(&dev->sbd));
  	ps3_system_bus_set_drvdata(&dev->sbd, NULL);
f96526354   Geert Uytterhoeven   ps3: FLASH ROM St...
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
  	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);