VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   33 Branches   57 Tags
935912c538f15 (Thomas Gleixner    2019-05-27 08:55:12 +0200   1) // SPDX-License-Identifier: GPL-2.0-only
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700   2) /*
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700   3)  * PS3 FLASH ROM Storage Driver
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700   4)  *
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700   5)  * Copyright (C) 2007 Sony Computer Entertainment Inc.
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700   6)  * Copyright 2007 Sony Corp.
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700   7)  */
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700   8) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700   9) #include <linux/fs.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  10) #include <linux/miscdevice.h>
5a0e3ad6af866 (Tejun Heo          2010-03-24 17:04:11 +0900  11) #include <linux/slab.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  12) #include <linux/uaccess.h>
c22405c98d3ff (Paul Gortmaker     2011-07-03 13:35:48 -0400  13) #include <linux/module.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  14) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  15) #include <asm/lv1call.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  16) #include <asm/ps3stor.h>
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  17) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  18) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  19) #define DEVICE_NAME		"ps3flash"
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  20) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  21) #define FLASH_BLOCK_SIZE	(256*1024)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  22) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  23) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  24) struct ps3flash_private {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  25) 	struct mutex mutex;	/* Bounce buffer mutex */
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  26) 	u64 chunk_sectors;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  27) 	int tag;		/* Start sector of buffer, -1 if invalid */
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  28) 	bool dirty;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  29) };
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  30) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  31) static struct ps3_storage_device *ps3flash_dev;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  32) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  33) static int ps3flash_read_write_sectors(struct ps3_storage_device *dev,
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  34) 				       u64 start_sector, int write)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  35) {
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  36) 	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  37) 	u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar,
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  38) 					     start_sector, priv->chunk_sectors,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  39) 					     write);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  40) 	if (res) {
4c33d2dc34f50 (Stephen Rothwell   2009-01-13 20:06:02 +0000  41) 		dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%llx\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  42) 			__LINE__, write ? "write" : "read", res);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  43) 		return -EIO;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  44) 	}
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  45) 	return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  46) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  47) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  48) static int ps3flash_writeback(struct ps3_storage_device *dev)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  49) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  50) 	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  51) 	int res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  52) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  53) 	if (!priv->dirty || priv->tag < 0)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  54) 		return 0;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  55) 
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  56) 	res = ps3flash_read_write_sectors(dev, priv->tag, 1);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  57) 	if (res)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  58) 		return res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  59) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  60) 	priv->dirty = false;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  61) 	return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  62) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  63) 
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  64) static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  65) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  66) 	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  67) 	int res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  68) 
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  69) 	if (start_sector == priv->tag)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  70) 		return 0;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  71) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  72) 	res = ps3flash_writeback(dev);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  73) 	if (res)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  74) 		return res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  75) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  76) 	priv->tag = -1;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  77) 
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  78) 	res = ps3flash_read_write_sectors(dev, start_sector, 0);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  79) 	if (res)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  80) 		return res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  81) 
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  82) 	priv->tag = start_sector;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  83) 	return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  84) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  85) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  86) static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  87) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  88) 	struct ps3_storage_device *dev = ps3flash_dev;
ee32465249bee (Al Viro            2013-06-17 10:05:35 +0400  89) 	return generic_file_llseek_size(file, offset, origin, MAX_LFS_FILESIZE,
ee32465249bee (Al Viro            2013-06-17 10:05:35 +0400  90) 			dev->regions[dev->region_idx].size*dev->blk_size);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  91) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  92) 
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000  93) static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000  94) 			     size_t count, loff_t *pos)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  95) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700  96) 	struct ps3_storage_device *dev = ps3flash_dev;
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000  97) 	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000  98) 	u64 size, sector, offset;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000  99) 	int res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 100) 	size_t remaining, n;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 101) 	const void *src;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 102) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 103) 	dev_dbg(&dev->sbd.core,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 104) 		"%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n",
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 105) 		__func__, __LINE__, count, *pos, userbuf, kernelbuf);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 106) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 107) 	size = dev->regions[dev->region_idx].size*dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 108) 	if (*pos >= size || !count)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 109) 		return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 110) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 111) 	if (*pos + count > size) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 112) 		dev_dbg(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 113) 			"%s:%u Truncating count from %zu to %llu\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 114) 			__LINE__, count, size - *pos);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 115) 		count = size - *pos;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 116) 	}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 117) 
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 118) 	sector = *pos / dev->bounce_size * priv->chunk_sectors;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 119) 	offset = *pos % dev->bounce_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 120) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 121) 	remaining = count;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 122) 	do {
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 123) 		n = min_t(u64, remaining, dev->bounce_size - offset);
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 124) 		src = dev->bounce_buf + offset;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 125) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 126) 		mutex_lock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 127) 
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 128) 		res = ps3flash_fetch(dev, sector);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 129) 		if (res)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 130) 			goto fail;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 131) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 132) 		dev_dbg(&dev->sbd.core,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 133) 			"%s:%u: copy %lu bytes from 0x%p to U0x%p/K0x%p\n",
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 134) 			__func__, __LINE__, n, src, userbuf, kernelbuf);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 135) 		if (userbuf) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 136) 			if (copy_to_user(userbuf, src, n)) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 137) 				res = -EFAULT;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 138) 				goto fail;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 139) 			}
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 140) 			userbuf += n;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 141) 		}
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 142) 		if (kernelbuf) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 143) 			memcpy(kernelbuf, src, n);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 144) 			kernelbuf += n;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 145) 		}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 146) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 147) 		mutex_unlock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 148) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 149) 		*pos += n;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 150) 		remaining -= n;
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 151) 		sector += priv->chunk_sectors;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 152) 		offset = 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 153) 	} while (remaining > 0);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 154) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 155) 	return count;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 156) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 157) fail:
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 158) 	mutex_unlock(&priv->mutex);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 159) 	return res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 160) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 161) 
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 162) static ssize_t ps3flash_write(const char __user *userbuf,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 163) 			      const void *kernelbuf, size_t count, loff_t *pos)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 164) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 165) 	struct ps3_storage_device *dev = ps3flash_dev;
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 166) 	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 167) 	u64 size, sector, offset;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 168) 	int res = 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 169) 	size_t remaining, n;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 170) 	void *dst;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 171) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 172) 	dev_dbg(&dev->sbd.core,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 173) 		"%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n",
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 174) 		__func__, __LINE__, count, *pos, userbuf, kernelbuf);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 175) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 176) 	size = dev->regions[dev->region_idx].size*dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 177) 	if (*pos >= size || !count)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 178) 		return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 179) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 180) 	if (*pos + count > size) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 181) 		dev_dbg(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 182) 			"%s:%u Truncating count from %zu to %llu\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 183) 			__LINE__, count, size - *pos);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 184) 		count = size - *pos;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 185) 	}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 186) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 187) 	sector = *pos / dev->bounce_size * priv->chunk_sectors;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 188) 	offset = *pos % dev->bounce_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 189) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 190) 	remaining = count;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 191) 	do {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 192) 		n = min_t(u64, remaining, dev->bounce_size - offset);
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 193) 		dst = dev->bounce_buf + offset;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 194) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 195) 		mutex_lock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 196) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 197) 		if (n != dev->bounce_size)
42e27bfc4bfa4 (Geert Uytterhoeven 2009-06-10 04:39:08 +0000 198) 			res = ps3flash_fetch(dev, sector);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 199) 		else if (sector != priv->tag)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 200) 			res = ps3flash_writeback(dev);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 201) 		if (res)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 202) 			goto fail;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 203) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 204) 		dev_dbg(&dev->sbd.core,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 205) 			"%s:%u: copy %lu bytes from U0x%p/K0x%p to 0x%p\n",
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 206) 			__func__, __LINE__, n, userbuf, kernelbuf, dst);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 207) 		if (userbuf) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 208) 			if (copy_from_user(dst, userbuf, n)) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 209) 				res = -EFAULT;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 210) 				goto fail;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 211) 			}
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 212) 			userbuf += n;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 213) 		}
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 214) 		if (kernelbuf) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 215) 			memcpy(dst, kernelbuf, n);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 216) 			kernelbuf += n;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 217) 		}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 218) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 219) 		priv->tag = sector;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 220) 		priv->dirty = true;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 221) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 222) 		mutex_unlock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 223) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 224) 		*pos += n;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 225) 		remaining -= n;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 226) 		sector += priv->chunk_sectors;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 227) 		offset = 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 228) 	} while (remaining > 0);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 229) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 230) 	return count;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 231) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 232) fail:
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 233) 	mutex_unlock(&priv->mutex);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 234) 	return res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 235) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 236) 
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 237) static ssize_t ps3flash_user_read(struct file *file, char __user *buf,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 238) 				  size_t count, loff_t *pos)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 239) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 240) 	return ps3flash_read(buf, NULL, count, pos);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 241) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 242) 
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 243) static ssize_t ps3flash_user_write(struct file *file, const char __user *buf,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 244) 				   size_t count, loff_t *pos)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 245) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 246) 	return ps3flash_write(buf, NULL, count, pos);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 247) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 248) 
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 249) static ssize_t ps3flash_kernel_read(void *buf, size_t count, loff_t pos)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 250) {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 251) 	return ps3flash_read(NULL, buf, count, &pos);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 252) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 253) 
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 254) static ssize_t ps3flash_kernel_write(const void *buf, size_t count,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 255) 				     loff_t pos)
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 256) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 257) 	ssize_t res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 258) 	int wb;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 259) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 260) 	res = ps3flash_write(NULL, buf, count, &pos);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 261) 	if (res < 0)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 262) 		return res;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 263) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 264) 	/* Make kernel writes synchronous */
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 265) 	wb = ps3flash_writeback(ps3flash_dev);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 266) 	if (wb)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 267) 		return wb;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 268) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 269) 	return res;
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 270) }
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 271) 
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 272) static int ps3flash_flush(struct file *file, fl_owner_t id)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 273) {
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 274) 	return ps3flash_writeback(ps3flash_dev);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 275) }
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 276) 
02c24a82187d5 (Josef Bacik        2011-07-16 20:44:56 -0400 277) static int ps3flash_fsync(struct file *file, loff_t start, loff_t end, int datasync)
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 278) {
496ad9aa8ef44 (Al Viro            2013-01-23 17:07:38 -0500 279) 	struct inode *inode = file_inode(file);
02c24a82187d5 (Josef Bacik        2011-07-16 20:44:56 -0400 280) 	int err;
5955102c9984f (Al Viro            2016-01-22 15:40:57 -0500 281) 	inode_lock(inode);
02c24a82187d5 (Josef Bacik        2011-07-16 20:44:56 -0400 282) 	err = ps3flash_writeback(ps3flash_dev);
5955102c9984f (Al Viro            2016-01-22 15:40:57 -0500 283) 	inode_unlock(inode);
02c24a82187d5 (Josef Bacik        2011-07-16 20:44:56 -0400 284) 	return err;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 285) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 286) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 287) static irqreturn_t ps3flash_interrupt(int irq, void *data)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 288) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 289) 	struct ps3_storage_device *dev = data;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 290) 	int res;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 291) 	u64 tag, status;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 292) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 293) 	res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 294) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 295) 	if (tag != dev->tag)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 296) 		dev_err(&dev->sbd.core,
4c33d2dc34f50 (Stephen Rothwell   2009-01-13 20:06:02 +0000 297) 			"%s:%u: tag mismatch, got %llx, expected %llx\n",
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 298) 			__func__, __LINE__, tag, dev->tag);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 299) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 300) 	if (res) {
4c33d2dc34f50 (Stephen Rothwell   2009-01-13 20:06:02 +0000 301) 		dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%llx\n",
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 302) 			__func__, __LINE__, res, status);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 303) 	} else {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 304) 		dev->lv1_status = status;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 305) 		complete(&dev->done);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 306) 	}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 307) 	return IRQ_HANDLED;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 308) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 309) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 310) static const struct file_operations ps3flash_fops = {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 311) 	.owner	= THIS_MODULE,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 312) 	.llseek	= ps3flash_llseek,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 313) 	.read	= ps3flash_user_read,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 314) 	.write	= ps3flash_user_write,
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 315) 	.flush	= ps3flash_flush,
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 316) 	.fsync	= ps3flash_fsync,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 317) };
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 318) 
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 319) static const struct ps3_os_area_flash_ops ps3flash_kernel_ops = {
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 320) 	.read	= ps3flash_kernel_read,
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 321) 	.write	= ps3flash_kernel_write,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 322) };
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 323) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 324) static struct miscdevice ps3flash_misc = {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 325) 	.minor	= MISC_DYNAMIC_MINOR,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 326) 	.name	= DEVICE_NAME,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 327) 	.fops	= &ps3flash_fops,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 328) };
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 329) 
2223cbec33ef3 (Bill Pemberton     2012-11-19 13:22:51 -0500 330) static int ps3flash_probe(struct ps3_system_bus_device *_dev)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 331) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 332) 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 333) 	struct ps3flash_private *priv;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 334) 	int error;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 335) 	unsigned long tmp;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 336) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 337) 	tmp = dev->regions[dev->region_idx].start*dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 338) 	if (tmp % FLASH_BLOCK_SIZE) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 339) 		dev_err(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 340) 			"%s:%u region start %lu is not aligned\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 341) 			__LINE__, tmp);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 342) 		return -EINVAL;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 343) 	}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 344) 	tmp = dev->regions[dev->region_idx].size*dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 345) 	if (tmp % FLASH_BLOCK_SIZE) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 346) 		dev_err(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 347) 			"%s:%u region size %lu is not aligned\n", __func__,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 348) 			__LINE__, tmp);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 349) 		return -EINVAL;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 350) 	}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 351) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 352) 	/* use static buffer, kmalloc cannot allocate 256 KiB */
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 353) 	if (!ps3flash_bounce_buffer.address)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 354) 		return -ENODEV;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 355) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 356) 	if (ps3flash_dev) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 357) 		dev_err(&dev->sbd.core,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 358) 			"Only one FLASH device is supported\n");
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 359) 		return -EBUSY;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 360) 	}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 361) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 362) 	ps3flash_dev = dev;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 363) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 364) 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 365) 	if (!priv) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 366) 		error = -ENOMEM;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 367) 		goto fail;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 368) 	}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 369) 
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 370) 	ps3_system_bus_set_drvdata(&dev->sbd, priv);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 371) 	mutex_init(&priv->mutex);
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 372) 	priv->tag = -1;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 373) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 374) 	dev->bounce_size = ps3flash_bounce_buffer.size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 375) 	dev->bounce_buf = ps3flash_bounce_buffer.address;
6bd57f2e5db40 (Geert Uytterhoeven 2009-06-10 04:39:07 +0000 376) 	priv->chunk_sectors = dev->bounce_size / dev->blk_size;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 377) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 378) 	error = ps3stor_setup(dev, ps3flash_interrupt);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 379) 	if (error)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 380) 		goto fail_free_priv;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 381) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 382) 	ps3flash_misc.parent = &dev->sbd.core;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 383) 	error = misc_register(&ps3flash_misc);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 384) 	if (error) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 385) 		dev_err(&dev->sbd.core, "%s:%u: misc_register failed %d\n",
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 386) 			__func__, __LINE__, error);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 387) 		goto fail_teardown;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 388) 	}
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 389) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 390) 	dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 391) 		 __func__, __LINE__, ps3flash_misc.minor);
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 392) 
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 393) 	ps3_os_area_flash_register(&ps3flash_kernel_ops);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 394) 	return 0;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 395) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 396) fail_teardown:
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 397) 	ps3stor_teardown(dev);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 398) fail_free_priv:
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 399) 	kfree(priv);
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 400) 	ps3_system_bus_set_drvdata(&dev->sbd, NULL);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 401) fail:
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 402) 	ps3flash_dev = NULL;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 403) 	return error;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 404) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 405) 
6d247e4d26496 (Uwe Kleine-König   2020-11-26 17:59:50 +0100 406) static void ps3flash_remove(struct ps3_system_bus_device *_dev)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 407) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 408) 	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 409) 
a4e623fbc9b20 (Geert Uytterhoeven 2009-06-10 04:39:06 +0000 410) 	ps3_os_area_flash_register(NULL);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 411) 	misc_deregister(&ps3flash_misc);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 412) 	ps3stor_teardown(dev);
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 413) 	kfree(ps3_system_bus_get_drvdata(&dev->sbd));
559dc87f50d06 (Geert Uytterhoeven 2009-06-10 04:38:55 +0000 414) 	ps3_system_bus_set_drvdata(&dev->sbd, NULL);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 415) 	ps3flash_dev = NULL;
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 416) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 417) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 418) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 419) static struct ps3_system_bus_driver ps3flash = {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 420) 	.match_id	= PS3_MATCH_ID_STOR_FLASH,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 421) 	.core.name	= DEVICE_NAME,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 422) 	.core.owner	= THIS_MODULE,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 423) 	.probe		= ps3flash_probe,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 424) 	.remove		= ps3flash_remove,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 425) 	.shutdown	= ps3flash_remove,
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 426) };
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 427) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 428) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 429) static int __init ps3flash_init(void)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 430) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 431) 	return ps3_system_bus_driver_register(&ps3flash);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 432) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 433) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 434) static void __exit ps3flash_exit(void)
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 435) {
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 436) 	ps3_system_bus_driver_unregister(&ps3flash);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 437) }
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 438) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 439) module_init(ps3flash_init);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 440) module_exit(ps3flash_exit);
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 441) 
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 442) MODULE_LICENSE("GPL");
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 443) MODULE_DESCRIPTION("PS3 FLASH ROM Storage Driver");
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 444) MODULE_AUTHOR("Sony Corporation");
f96526354bb08 (Geert Uytterhoeven 2007-07-21 04:37:48 -0700 445) MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_FLASH);