[PATCH 10/15] ps3stor_lib: Add support for multiple regions

Andre Heider a.heider at gmail.com
Tue Aug 2 06:03:01 EST 2011


Users (ps3disk, ps3flash and ps3rom) retain the old behavior. That is:
they still only provide access to the first accessible region.

Signed-off-by: Andre Heider <a.heider at gmail.com>
---
 arch/powerpc/include/asm/ps3stor.h |    4 ++--
 drivers/block/ps3disk.c            |   15 +++++++++++++--
 drivers/char/ps3flash.c            |   23 +++++++++++++++++------
 drivers/ps3/ps3stor_lib.c          |   25 ++++++++++++-------------
 drivers/scsi/ps3rom.c              |   11 +++++++----
 5 files changed, 51 insertions(+), 27 deletions(-)

diff --git a/arch/powerpc/include/asm/ps3stor.h b/arch/powerpc/include/asm/ps3stor.h
index d51e53c..9871c05 100644
--- a/arch/powerpc/include/asm/ps3stor.h
+++ b/arch/powerpc/include/asm/ps3stor.h
@@ -51,7 +51,6 @@ struct ps3_storage_device {
 
 	unsigned int num_regions;
 	unsigned long accessible_regions;
-	unsigned int region_idx;		/* first accessible region */
 	struct ps3_storage_region regions[0];	/* Must be last */
 };
 
@@ -63,7 +62,8 @@ static inline struct ps3_storage_device *to_ps3_storage_device(struct device *de
 extern int ps3stor_setup(struct ps3_storage_device *dev,
 			 irq_handler_t handler);
 extern void ps3stor_teardown(struct ps3_storage_device *dev);
-extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+extern u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev,
+				      unsigned int region_idx, u64 lpar,
 				      u64 start_sector, u64 sectors,
 				      int write);
 extern u64 ps3stor_send_command(struct ps3_storage_device *dev, u64 cmd,
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c
index 8e1ce2e..96e00ff 100644
--- a/drivers/block/ps3disk.c
+++ b/drivers/block/ps3disk.c
@@ -42,6 +42,7 @@ struct ps3disk_private {
 	spinlock_t lock;		/* Request queue spinlock */
 	struct request_queue *queue;
 	struct gendisk *gendisk;
+	unsigned int region_idx;	/* first accessible region */
 	unsigned int blocking_factor;
 	struct request *req;
 	u64 raw_capacity;
@@ -125,7 +126,7 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
 	int write = rq_data_dir(req), res;
 	const char *op = write ? "write" : "read";
 	u64 start_sector, sectors;
-	unsigned int region_id = dev->regions[dev->region_idx].id;
+	unsigned int region_id = dev->regions[priv->region_idx].id;
 
 #ifdef DEBUG
 	unsigned int n = 0;
@@ -408,6 +409,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
 	unsigned int devidx;
 	struct request_queue *queue;
 	struct gendisk *gendisk;
+	unsigned int region_idx;
 
 	if (dev->blk_size < 512) {
 		dev_err(&dev->sbd.core,
@@ -482,6 +484,14 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
 	}
 
 	priv->gendisk = gendisk;
+
+	/* find first accessible region */
+	for (region_idx = 0; region_idx < dev->num_regions; region_idx++)
+		if (test_bit(region_idx, &dev->accessible_regions)) {
+			priv->region_idx = region_idx;
+			break;
+		}
+
 	gendisk->major = ps3disk_major;
 	gendisk->first_minor = devidx * PS3DISK_MINORS;
 	gendisk->fops = &ps3disk_fops;
@@ -492,7 +502,8 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
 		 devidx+'a');
 	priv->blocking_factor = dev->blk_size >> 9;
 	set_capacity(gendisk,
-		     dev->regions[dev->region_idx].size*priv->blocking_factor);
+		     dev->regions[priv->region_idx].size *
+				 priv->blocking_factor);
 
 	dev_info(&dev->sbd.core,
 		 "%s is a %s (%llu MiB total, %lu MiB for OtherOS)\n",
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c
index b1e8659..47b1dc7 100644
--- a/drivers/char/ps3flash.c
+++ b/drivers/char/ps3flash.c
@@ -36,6 +36,7 @@
 struct ps3flash_private {
 	struct mutex mutex;	/* Bounce buffer mutex */
 	u64 chunk_sectors;
+	unsigned int region_idx;	/* first accessible region */
 	int tag;		/* Start sector of buffer, -1 if invalid */
 	bool dirty;
 };
@@ -46,7 +47,8 @@ static int ps3flash_read_write_sectors(struct ps3_storage_device *dev,
 				       u64 start_sector, int write)
 {
 	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
-	u64 res = ps3stor_read_write_sectors(dev, dev->bounce_lpar,
+	u64 res = ps3stor_read_write_sectors(dev, priv->region_idx,
+					     dev->bounce_lpar,
 					     start_sector, priv->chunk_sectors,
 					     write);
 	if (res) {
@@ -98,6 +100,7 @@ static int ps3flash_fetch(struct ps3_storage_device *dev, u64 start_sector)
 static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
 {
 	struct ps3_storage_device *dev = ps3flash_dev;
+	struct ps3flash_private *priv = ps3_system_bus_get_drvdata(&dev->sbd);
 	loff_t res;
 
 	mutex_lock(&file->f_mapping->host->i_mutex);
@@ -106,7 +109,7 @@ static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
 		offset += file->f_pos;
 		break;
 	case 2:
-		offset += dev->regions[dev->region_idx].size*dev->blk_size;
+		offset += dev->regions[priv->region_idx].size*dev->blk_size;
 		break;
 	}
 	if (offset < 0) {
@@ -136,7 +139,7 @@ static ssize_t ps3flash_read(char __user *userbuf, void *kernelbuf,
 		"%s:%u: Reading %zu bytes at position %lld to U0x%p/K0x%p\n",
 		__func__, __LINE__, count, *pos, userbuf, kernelbuf);
 
-	size = dev->regions[dev->region_idx].size*dev->blk_size;
+	size = dev->regions[priv->region_idx].size*dev->blk_size;
 	if (*pos >= size || !count)
 		return 0;
 
@@ -205,7 +208,7 @@ static ssize_t ps3flash_write(const char __user *userbuf,
 		"%s:%u: Writing %zu bytes at position %lld from U0x%p/K0x%p\n",
 		__func__, __LINE__, count, *pos, userbuf, kernelbuf);
 
-	size = dev->regions[dev->region_idx].size*dev->blk_size;
+	size = dev->regions[priv->region_idx].size*dev->blk_size;
 	if (*pos >= size || !count)
 		return 0;
 
@@ -359,6 +362,7 @@ 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 int region_idx;
 	unsigned long tmp;
 
 	/* use static buffer, kmalloc cannot allocate 256 KiB */
@@ -391,14 +395,21 @@ static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev)
 	if (error)
 		goto fail_free_priv;
 
-	tmp = dev->regions[dev->region_idx].start*dev->blk_size;
+	/* find first accessible region */
+	for (region_idx = 0; region_idx < dev->num_regions; region_idx++)
+		if (test_bit(region_idx, &dev->accessible_regions)) {
+			priv->region_idx = region_idx;
+			break;
+		}
+
+	tmp = dev->regions[priv->region_idx].start*dev->blk_size;
 	if (tmp % FLASH_BLOCK_SIZE) {
 		dev_err(&dev->sbd.core,
 			"%s:%u region start %lu is not aligned\n", __func__,
 			__LINE__, tmp);
 		return -EINVAL;
 	}
-	tmp = dev->regions[dev->region_idx].size*dev->blk_size;
+	tmp = dev->regions[priv->region_idx].size*dev->blk_size;
 	if (tmp % FLASH_BLOCK_SIZE) {
 		dev_err(&dev->sbd.core,
 			"%s:%u region size %lu is not aligned\n", __func__,
diff --git a/drivers/ps3/ps3stor_lib.c b/drivers/ps3/ps3stor_lib.c
index af0afa1..5bbc023 100644
--- a/drivers/ps3/ps3stor_lib.c
+++ b/drivers/ps3/ps3stor_lib.c
@@ -101,9 +101,8 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)
 			"%s:%u: checking accessibility of region %u\n",
 			__func__, __LINE__, i);
 
-		dev->region_idx = i;
-		res = ps3stor_read_write_sectors(dev, dev->bounce_lpar, 0, 1,
-						 0);
+		res = ps3stor_read_write_sectors(dev, i, dev->bounce_lpar,
+						 0, 1, 0);
 		if (res) {
 			dev_dbg(&dev->sbd.core, "%s:%u: read failed, "
 				"region %u is not accessible\n", __func__,
@@ -117,6 +116,11 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)
 
 		/* We can access at least one region */
 		error = 0;
+
+		dev_info(&dev->sbd.core,
+			 "Accessible region found: #%u start %llu size %llu\n",
+			 i, dev->regions[i].start, dev->regions[i].size);
+
 	}
 	if (error)
 		return error;
@@ -124,15 +128,8 @@ static int ps3stor_probe_access(struct ps3_storage_device *dev)
 	n = hweight_long(dev->accessible_regions);
 	if (n > 1)
 		dev_info(&dev->sbd.core,
-			 "%s:%u: %lu accessible regions found. Only the first "
-			 "one will be used\n",
+			 "%s:%u: %lu accessible regions found\n",
 			 __func__, __LINE__, n);
-	dev->region_idx = __ffs(dev->accessible_regions);
-	dev_info(&dev->sbd.core,
-		 "First accessible region has index %u start %llu size %llu\n",
-		 dev->region_idx, dev->regions[dev->region_idx].start,
-		 dev->regions[dev->region_idx].size);
-
 	return 0;
 }
 
@@ -264,6 +261,7 @@ EXPORT_SYMBOL_GPL(ps3stor_teardown);
 /**
  *	ps3stor_read_write_sectors - read/write from/to a storage device
  *	@dev: Pointer to a struct ps3_storage_device
+ *	@region_idx: Index of the region to access
  *	@lpar: HV logical partition address
  *	@start_sector: First sector to read/write
  *	@sectors: Number of sectors to read/write
@@ -272,10 +270,11 @@ EXPORT_SYMBOL_GPL(ps3stor_teardown);
  *	Returns 0 for success, -1 in case of failure to submit the command, or
  *	an LV1 status value in case of other errors
  */
-u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev, u64 lpar,
+u64 ps3stor_read_write_sectors(struct ps3_storage_device *dev,
+			       unsigned int region_idx, u64 lpar,
 			       u64 start_sector, u64 sectors, int write)
 {
-	unsigned int region_id = dev->regions[dev->region_idx].id;
+	unsigned int region_id = dev->regions[region_idx].id;
 	const char *op = write ? "write" : "read";
 	int res;
 
diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c
index cd178b9..68db03c 100644
--- a/drivers/scsi/ps3rom.c
+++ b/drivers/scsi/ps3rom.c
@@ -39,6 +39,7 @@
 
 #define PS3ROM_MAX_SECTORS		(BOUNCE_SIZE >> 9)
 
+#define PS3ROM_REGION_IDX		0
 
 struct ps3rom_private {
 	struct ps3_storage_device *dev;
@@ -177,8 +178,9 @@ static int ps3rom_read_request(struct ps3_storage_device *dev,
 		__func__, __LINE__, sectors, start_sector);
 
 	res = lv1_storage_read(dev->sbd.dev_id,
-			       dev->regions[dev->region_idx].id, start_sector,
-			       sectors, 0, dev->bounce_lpar, &dev->tag);
+			       dev->regions[PS3ROM_REGION_IDX].id,
+			       start_sector, sectors, 0,
+			       dev->bounce_lpar, &dev->tag);
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__,
 			__LINE__, res);
@@ -200,8 +202,9 @@ static int ps3rom_write_request(struct ps3_storage_device *dev,
 	scsi_sg_copy_to_buffer(cmd, dev->bounce_buf, dev->bounce_size);
 
 	res = lv1_storage_write(dev->sbd.dev_id,
-				dev->regions[dev->region_idx].id, start_sector,
-				sectors, 0, dev->bounce_lpar, &dev->tag);
+				dev->regions[PS3ROM_REGION_IDX].id,
+				start_sector, sectors, 0,
+				dev->bounce_lpar, &dev->tag);
 	if (res) {
 		dev_err(&dev->sbd.core, "%s:%u: write failed %d\n", __func__,
 			__LINE__, res);
-- 
1.7.5.4



More information about the Linuxppc-dev mailing list