LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: Linuxppc-embedded Digest, Vol 35, Issue 33
From: Scott Wood @ 2007-07-16 16:09 UTC (permalink / raw)
  To: Siva Prasad; +Cc: sureshtang, linuxppc-embedded
In-Reply-To: <D83235F0F3C86D4D889D8B9A0DA8C6D78D7DE9@corpexc01.corp.networkrobots.com>

Siva Prasad wrote:
> It returns kernel virtual address. If you use this buffer space for DMA,
> please use appropriate flags. You may use __pa(address) or
> virt_to_phys() to convert virtual to physical.

No, you may not -- physical and DMA addresses are not always identical. 
  Use the DMA mapping API.

-Scott

^ permalink raw reply

* Re: How to add platform specific data to a of_device
From: Segher Boessenkool @ 2007-07-16 16:13 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1184489825.25235.4.camel@localhost.localdomain>

>> Hmm, as I stated above: Handling the SPI slave devices is done in  
>> the SPI
>> framework. But including this data into the dts sounds better than  
>> including
>> it into the BSP. Is there some documentation around how to  
>> describe such a
>> SPI bus with its devices in the dts?
>
> I don't think so, I doubt there's an SPI OF binding.

That's correct.


Segher

^ permalink raw reply

* Re: How to add platform specific data to a of_device
From: Segher Boessenkool @ 2007-07-16 16:16 UTC (permalink / raw)
  To: Robert Schwebel; +Cc: linuxppc-dev
In-Reply-To: <20070716065144.GH1678@pengutronix.de>

> Is there a reason why there is sooo much interaction of the
> platform code with the oftree?

Yes.  Since the decision has been made to require a device
tree for every platform, arch/powerpc is in the luxury
position that we can actually exploit the benefits of _having_
a tree for every platform.


Segher

^ permalink raw reply

* [patch 0/3] PS3 Storage Drivers for 2.6.23, take 5
From: Geert Uytterhoeven @ 2007-07-16 16:15 UTC (permalink / raw)
  To: Paul Mackerras, Jens Axboe, James E.J.  Bottomley,
	Alessandro Rubini
  Cc: linuxppc-dev, linux-kernel, linux-scsi

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1391 bytes --]

	Hi,

These are the remaining patches of the new PS3 storage drivers series:
  [1] ps3: Disk Storage Driver
  [2] ps3: BD/DVD/CD-ROM Storage Driver
  [3] ps3: FLASH ROM Storage Driver

They are based on:
  - the current Linux kernel source tree,
  - plus the PS3 patches already submitted by Geoff Levand on linuxppc-dev,
    which are in the for-2.6.23 branch of Paulus' tree,
  - plus the first 3 patches from the PS3 storage drivers series I submitted
    before, which are also in the for-2.6.23 branch of Paulus' tree.

The only changes compared to the previous submission are the kmap updates, as
requested by Jens Axboe and James E.J. Bottomley.

I didn't hear anything from the misc device maintainer (for the FLASH ROM
Storage Driver).

Paulus, please apply.  Thanks in advance!

With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium	
VAT BE 0413.825.160 · RPR Brussels	
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619

^ permalink raw reply

* [patch 1/3] ps3: Disk Storage Driver
From: Geert Uytterhoeven @ 2007-07-16 16:15 UTC (permalink / raw)
  To: Paul Mackerras, Jens Axboe, James E.J.  Bottomley,
	Alessandro Rubini
  Cc: linux-scsi, linux-kernel, linuxppc-dev, Jens Axboe,
	Geert Uytterhoeven
In-Reply-To: <20070716161539.075822000@pademelon.sonytel.be>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 18961 bytes --]

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

Add a Disk Storage Driver for the PS3:
  - Implemented as a block device driver with a dynamic major
  - Disk names (and partitions) are of the format ps3d%c(%u)
  - Uses software scatter-gather with a 64 KiB bounce buffer as the hypervisor
    doesn't support scatter-gather

CC: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Acked-by: Jens Axboe <jens.axboe@oracle.com>
---
v4:
  - Replace KM_USER0 by KM_IRQ0 (all kmap routines are either called from an
    interrupt handler or from .request_fn())
  - Add a call to flush_kernel_dcache_page() before kunmap in routines that
    write to buffers

v3:
  - Cleanup #includes
  - Kill PS3DISK_MAJOR, always use zero to obtain a dynamic major
  - Group LV1 API related stuff
  - Kill empty ps3disk_open
  - Reset ps3disk_priv(dev) to NULL during cleanup
  - Move call to put_disk() down
  - Pass the interrupt handler to ps3stor_setup(), so it doesn't have to be
    overridden later
  - Fold ps3disk_read_write_sectors() into ps3disk_submit_request_sg()
  - Identify the hard drive capacity and model name during probing

v2:
  - Don't use `default y' in Kconfig
  - Remove the thread for handling requests
  - Set up sysfs links between block device and PS3 system device:
      o /sys/block/ps3da/device -> ../../devices/ps3_system/sb_02
      o /sys/devices/ps3_system/sb_02/block:ps3da -> ../../../block/ps3da
  - Fix all FIXMEs
  - Implement proper barrier support
  - Call add_disk_randomness()
  - Add a test to verify we are running on a PS3
  - Fix error path in ps3disk_init()
  - Fix cleanup order in ps3disk_exit()

 arch/powerpc/platforms/ps3/Kconfig |   10 
 drivers/block/Makefile             |    1 
 drivers/block/ps3disk.c            |  624 +++++++++++++++++++++++++++++++++++++
 3 files changed, 635 insertions(+)

--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -102,4 +102,14 @@ config PS3_STORAGE
 	depends on PPC_PS3
 	tristate
 
+config PS3_DISK
+	tristate "PS3 Disk Storage Driver"
+	depends on PPC_PS3 && BLOCK
+	select PS3_STORAGE
+	help
+	  Include support for the PS3 Disk Storage.
+
+	  This support is required to access the PS3 hard disk.
+	  In general, all users will say Y or M.
+
 endmenu
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -28,3 +28,4 @@ obj-$(CONFIG_VIODASD)		+= viodasd.o
 obj-$(CONFIG_BLK_DEV_SX8)	+= sx8.o
 obj-$(CONFIG_BLK_DEV_UB)	+= ub.o
 
+obj-$(CONFIG_PS3_DISK)		+= ps3disk.o
--- /dev/null
+++ b/drivers/block/ps3disk.c
@@ -0,0 +1,624 @@
+/*
+ * PS3 Disk 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/ata.h>
+#include <linux/blkdev.h>
+
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+#include <asm/firmware.h>
+
+
+#define DEVICE_NAME		"ps3disk"
+
+#define BOUNCE_SIZE		(64*1024)
+
+#define PS3DISK_MAX_DISKS	16
+#define PS3DISK_MINORS		16
+
+#define KERNEL_SECTOR_SIZE	512
+
+
+#define PS3DISK_NAME		"ps3d%c"
+
+
+struct ps3disk_private {
+	spinlock_t lock;		/* Request queue spinlock */
+	struct request_queue *queue;
+	struct gendisk *gendisk;
+	unsigned int blocking_factor;
+	struct request *req;
+	u64 raw_capacity;
+	unsigned char model[ATA_ID_PROD_LEN+1];
+};
+#define ps3disk_priv(dev)	((dev)->sbd.core.driver_data)
+
+
+#define LV1_STORAGE_SEND_ATA_COMMAND	(2)
+#define LV1_STORAGE_ATA_HDDOUT		(0x23)
+
+struct lv1_ata_cmnd_block {
+	u16	features;
+	u16	sector_count;
+	u16	LBA_low;
+	u16	LBA_mid;
+	u16	LBA_high;
+	u8	device;
+	u8	command;
+	u32	is_ext;
+	u32	proto;
+	u32	in_out;
+	u32	size;
+	u64	buffer;
+	u32	arglen;
+};
+
+enum lv1_ata_proto {
+	NON_DATA_PROTO     = 0,
+	PIO_DATA_IN_PROTO  = 1,
+	PIO_DATA_OUT_PROTO = 2,
+	DMA_PROTO = 3
+};
+
+enum lv1_ata_in_out {
+	DIR_WRITE = 0,			/* memory -> device */
+	DIR_READ = 1			/* device -> memory */
+};
+
+static int ps3disk_major;
+
+
+static struct block_device_operations ps3disk_fops = {
+	.owner		= THIS_MODULE,
+};
+
+
+static void ps3disk_scatter_gather(struct ps3_storage_device *dev,
+				   struct request *req, int gather)
+{
+	unsigned int sectors = 0, offset = 0;
+	struct bio *bio;
+	sector_t sector;
+	struct bio_vec *bvec;
+	unsigned int i = 0, j;
+	size_t size;
+	void *buf;
+
+	rq_for_each_bio(bio, req) {
+		sector = bio->bi_sector;
+		dev_dbg(&dev->sbd.core,
+			"%s:%u: bio %u: %u segs %u sectors from %lu\n",
+			__func__, __LINE__, i, bio_segments(bio),
+			bio_sectors(bio), sector);
+		bio_for_each_segment(bvec, bio, j) {
+			size = bio_cur_sectors(bio)*KERNEL_SECTOR_SIZE;
+			buf = __bio_kmap_atomic(bio, j, KM_IRQ0);
+			if (gather)
+				memcpy(dev->bounce_buf+offset, buf, size);
+			else
+				memcpy(buf, dev->bounce_buf+offset, size);
+			offset += size;
+			flush_kernel_dcache_page(bio_iovec_idx(bio, j)->bv_page);
+			__bio_kunmap_atomic(bio, KM_IRQ0);
+		}
+		sectors += bio_sectors(bio);
+		i++;
+	}
+}
+
+static int ps3disk_submit_request_sg(struct ps3_storage_device *dev,
+				     struct request *req)
+{
+	struct ps3disk_private *priv = ps3disk_priv(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;
+
+#ifdef DEBUG
+	unsigned int n = 0;
+	struct bio *bio;
+	rq_for_each_bio(bio, req)
+		n++;
+	dev_dbg(&dev->sbd.core,
+		"%s:%u: %s req has %u bios for %lu sectors %lu hard sectors\n",
+		__func__, __LINE__, op, n, req->nr_sectors,
+		req->hard_nr_sectors);
+#endif
+
+	start_sector = req->sector*priv->blocking_factor;
+	sectors = req->nr_sectors*priv->blocking_factor;
+	dev_dbg(&dev->sbd.core, "%s:%u: %s %lu sectors starting at %lu\n",
+		__func__, __LINE__, op, sectors, start_sector);
+
+	if (write) {
+		ps3disk_scatter_gather(dev, req, 1);
+
+		res = lv1_storage_write(dev->sbd.dev_id, region_id,
+					start_sector, sectors, 0,
+					dev->bounce_lpar, &dev->tag);
+	} else {
+		res = lv1_storage_read(dev->sbd.dev_id, region_id,
+				       start_sector, sectors, 0,
+				       dev->bounce_lpar, &dev->tag);
+	}
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__,
+			__LINE__, op, res);
+		end_request(req, 0);
+		return 0;
+	}
+
+	priv->req = req;
+	return 1;
+}
+
+static int ps3disk_submit_flush_request(struct ps3_storage_device *dev,
+					struct request *req)
+{
+	struct ps3disk_private *priv = ps3disk_priv(dev);
+	u64 res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: flush request\n", __func__, __LINE__);
+
+	res = lv1_storage_send_device_command(dev->sbd.dev_id,
+					      LV1_STORAGE_ATA_HDDOUT, 0, 0, 0,
+					      0, &dev->tag);
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%lx\n",
+			__func__, __LINE__, res);
+		end_request(req, 0);
+		return 0;
+	}
+
+	priv->req = req;
+	return 1;
+}
+
+static void ps3disk_do_request(struct ps3_storage_device *dev,
+			       request_queue_t *q)
+{
+	struct request *req;
+
+	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
+
+	while ((req = elv_next_request(q))) {
+		if (blk_fs_request(req)) {
+			if (ps3disk_submit_request_sg(dev, req))
+				break;
+		} else if (req->cmd_type == REQ_TYPE_FLUSH) {
+			if (ps3disk_submit_flush_request(dev, req))
+				break;
+		} else {
+			blk_dump_rq_flags(req, DEVICE_NAME " bad request");
+			end_request(req, 0);
+			continue;
+		}
+	}
+}
+
+static void ps3disk_request(request_queue_t *q)
+{
+	struct ps3_storage_device *dev = q->queuedata;
+	struct ps3disk_private *priv = ps3disk_priv(dev);
+
+	if (priv->req) {
+		dev_dbg(&dev->sbd.core, "%s:%u busy\n", __func__, __LINE__);
+		return;
+	}
+
+	ps3disk_do_request(dev, q);
+}
+
+static irqreturn_t ps3disk_interrupt(int irq, void *data)
+{
+	struct ps3_storage_device *dev = data;
+	struct ps3disk_private *priv;
+	struct request *req;
+	int res, read, uptodate;
+	u64 tag, status;
+	unsigned long num_sectors;
+	const char *op;
+
+	res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
+
+	if (tag != dev->tag)
+		dev_err(&dev->sbd.core,
+			"%s:%u: tag mismatch, got %lx, expected %lx\n",
+			__func__, __LINE__, tag, dev->tag);
+
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n",
+			__func__, __LINE__, res, status);
+		return IRQ_HANDLED;
+	}
+
+	priv = ps3disk_priv(dev);
+	req = priv->req;
+	if (!req) {
+		dev_dbg(&dev->sbd.core,
+			"%s:%u non-block layer request completed\n", __func__,
+			__LINE__);
+		dev->lv1_status = status;
+		complete(&dev->done);
+		return IRQ_HANDLED;
+	}
+
+	if (req->cmd_type == REQ_TYPE_FLUSH) {
+		read = 0;
+		num_sectors = req->hard_cur_sectors;
+		op = "flush";
+	} else {
+		read = !rq_data_dir(req);
+		num_sectors = req->nr_sectors;
+		op = read ? "read" : "write";
+	}
+	if (status) {
+		dev_dbg(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+			__LINE__, op, status);
+		uptodate = 0;
+	} else {
+		dev_dbg(&dev->sbd.core, "%s:%u: %s completed\n", __func__,
+			__LINE__, op);
+		uptodate = 1;
+		if (read)
+			ps3disk_scatter_gather(dev, req, 0);
+	}
+
+	spin_lock(&priv->lock);
+	if (!end_that_request_first(req, uptodate, num_sectors)) {
+		add_disk_randomness(req->rq_disk);
+		blkdev_dequeue_request(req);
+		end_that_request_last(req, uptodate);
+	}
+	priv->req = NULL;
+	ps3disk_do_request(dev, priv->queue);
+	spin_unlock(&priv->lock);
+
+	return IRQ_HANDLED;
+}
+
+static int ps3disk_sync_cache(struct ps3_storage_device *dev)
+{
+	u64 res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: sync cache\n", __func__, __LINE__);
+
+	res = ps3stor_send_command(dev, LV1_STORAGE_ATA_HDDOUT, 0, 0, 0, 0);
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%lx\n",
+			__func__, __LINE__, res);
+		return -EIO;
+	}
+	return 0;
+}
+
+
+/* ATA helpers copied from drivers/ata/libata-core.c */
+
+static void swap_buf_le16(u16 *buf, unsigned int buf_words)
+{
+#ifdef __BIG_ENDIAN
+	unsigned int i;
+
+	for (i = 0; i < buf_words; i++)
+		buf[i] = le16_to_cpu(buf[i]);
+#endif /* __BIG_ENDIAN */
+}
+
+static u64 ata_id_n_sectors(const u16 *id)
+{
+	if (ata_id_has_lba(id)) {
+		if (ata_id_has_lba48(id))
+			return ata_id_u64(id, 100);
+		else
+			return ata_id_u32(id, 60);
+	} else {
+		if (ata_id_current_chs_valid(id))
+			return ata_id_u32(id, 57);
+		else
+			return id[1] * id[3] * id[6];
+	}
+}
+
+static void ata_id_string(const u16 *id, unsigned char *s, unsigned int ofs,
+			  unsigned int len)
+{
+	unsigned int c;
+
+	while (len > 0) {
+		c = id[ofs] >> 8;
+		*s = c;
+		s++;
+
+		c = id[ofs] & 0xff;
+		*s = c;
+		s++;
+
+		ofs++;
+		len -= 2;
+	}
+}
+
+static void ata_id_c_string(const u16 *id, unsigned char *s, unsigned int ofs,
+			    unsigned int len)
+{
+	unsigned char *p;
+
+	WARN_ON(!(len & 1));
+
+	ata_id_string(id, s, ofs, len - 1);
+
+	p = s + strnlen(s, len - 1);
+	while (p > s && p[-1] == ' ')
+		p--;
+	*p = '\0';
+}
+
+static int ps3disk_identify(struct ps3_storage_device *dev)
+{
+	struct ps3disk_private *priv = ps3disk_priv(dev);
+	struct lv1_ata_cmnd_block ata_cmnd;
+	u16 *id = dev->bounce_buf;
+	u64 res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: identify disk\n", __func__, __LINE__);
+
+	memset(&ata_cmnd, 0, sizeof(struct lv1_ata_cmnd_block));
+	ata_cmnd.command = ATA_CMD_ID_ATA;
+	ata_cmnd.sector_count = 1;
+	ata_cmnd.size = ata_cmnd.arglen = ATA_ID_WORDS * 2;
+	ata_cmnd.buffer = dev->bounce_lpar;
+	ata_cmnd.proto = PIO_DATA_IN_PROTO;
+	ata_cmnd.in_out = DIR_READ;
+
+	res = ps3stor_send_command(dev, LV1_STORAGE_SEND_ATA_COMMAND,
+				   ps3_mm_phys_to_lpar(__pa(&ata_cmnd)),
+				   sizeof(ata_cmnd), ata_cmnd.buffer,
+				   ata_cmnd.arglen);
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: identify disk failed 0x%lx\n",
+			__func__, __LINE__, res);
+		return -EIO;
+	}
+
+	swap_buf_le16(id, ATA_ID_WORDS);
+
+	/* All we're interested in are raw capacity and model name */
+	priv->raw_capacity = ata_id_n_sectors(id);
+	ata_id_c_string(id, priv->model, ATA_ID_PROD, sizeof(priv->model));
+	return 0;
+}
+
+static void ps3disk_prepare_flush(request_queue_t *q, struct request *req)
+{
+	struct ps3_storage_device *dev = q->queuedata;
+
+	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
+
+	memset(req->cmd, 0, sizeof(req->cmd));
+	req->cmd_type = REQ_TYPE_FLUSH;
+}
+
+static int ps3disk_issue_flush(request_queue_t *q, struct gendisk *gendisk,
+			       sector_t *sector)
+{
+	struct ps3_storage_device *dev = q->queuedata;
+	struct request *req;
+	int res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__);
+
+	req = blk_get_request(q, WRITE, __GFP_WAIT);
+	ps3disk_prepare_flush(q, req);
+	res = blk_execute_rq(q, gendisk, req, 0);
+	if (res)
+		dev_err(&dev->sbd.core, "%s:%u: flush request failed %d\n",
+			__func__, __LINE__, res);
+	blk_put_request(req);
+	return res;
+}
+
+
+static unsigned long ps3disk_mask;
+
+static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev)
+{
+	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
+	struct ps3disk_private *priv;
+	int error;
+	unsigned int devidx;
+	struct request_queue *queue;
+	struct gendisk *gendisk;
+
+	if (dev->blk_size < KERNEL_SECTOR_SIZE) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: cannot handle block size %lu\n", __func__,
+			__LINE__, dev->blk_size);
+		return -EINVAL;
+	}
+
+	BUILD_BUG_ON(PS3DISK_MAX_DISKS > BITS_PER_LONG);
+	devidx = find_first_zero_bit(&ps3disk_mask, PS3DISK_MAX_DISKS);
+	if (devidx >= PS3DISK_MAX_DISKS) {
+		dev_err(&dev->sbd.core, "%s:%u: Too many disks\n", __func__,
+			__LINE__);
+		return -ENOSPC;
+	}
+	__set_bit(devidx, &ps3disk_mask);
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		error = -ENOMEM;
+		goto fail;
+	}
+
+	ps3disk_priv(dev) = priv;
+	spin_lock_init(&priv->lock);
+
+	dev->bounce_size = BOUNCE_SIZE;
+	dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
+	if (!dev->bounce_buf) {
+		error = -ENOMEM;
+		goto fail_free_priv;
+	}
+
+	error = ps3stor_setup(dev, ps3disk_interrupt);
+	if (error)
+		goto fail_free_bounce;
+
+	ps3disk_identify(dev);
+
+	queue = blk_init_queue(ps3disk_request, &priv->lock);
+	if (!queue) {
+		dev_err(&dev->sbd.core, "%s:%u: blk_init_queue failed\n",
+			__func__, __LINE__);
+		error = -ENOMEM;
+		goto fail_teardown;
+	}
+
+	priv->queue = queue;
+	queue->queuedata = dev;
+
+	blk_queue_bounce_limit(queue, BLK_BOUNCE_HIGH);
+
+	blk_queue_max_sectors(queue, dev->bounce_size/KERNEL_SECTOR_SIZE);
+	blk_queue_segment_boundary(queue, -1UL);
+	blk_queue_dma_alignment(queue, dev->blk_size-1);
+	blk_queue_hardsect_size(queue, dev->blk_size);
+
+	blk_queue_issue_flush_fn(queue, ps3disk_issue_flush);
+	blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH,
+			  ps3disk_prepare_flush);
+
+	blk_queue_max_phys_segments(queue, -1);
+	blk_queue_max_hw_segments(queue, -1);
+	blk_queue_max_segment_size(queue, dev->bounce_size);
+
+	gendisk = alloc_disk(PS3DISK_MINORS);
+	if (!gendisk) {
+		dev_err(&dev->sbd.core, "%s:%u: alloc_disk failed\n", __func__,
+			__LINE__);
+		error = -ENOMEM;
+		goto fail_cleanup_queue;
+	}
+
+	priv->gendisk = gendisk;
+	gendisk->major = ps3disk_major;
+	gendisk->first_minor = devidx * PS3DISK_MINORS;
+	gendisk->fops = &ps3disk_fops;
+	gendisk->queue = queue;
+	gendisk->private_data = dev;
+	gendisk->driverfs_dev = &dev->sbd.core;
+	snprintf(gendisk->disk_name, sizeof(gendisk->disk_name), PS3DISK_NAME,
+		 devidx+'a');
+	priv->blocking_factor = dev->blk_size/KERNEL_SECTOR_SIZE;
+	set_capacity(gendisk,
+		     dev->regions[dev->region_idx].size*priv->blocking_factor);
+
+	dev_info(&dev->sbd.core,
+		 "%s is a %s (%lu MiB total, %lu MiB for OtherOS)\n",
+		 gendisk->disk_name, priv->model, priv->raw_capacity >> 11,
+		 get_capacity(gendisk) >> 11);
+
+	add_disk(gendisk);
+	return 0;
+
+fail_cleanup_queue:
+	blk_cleanup_queue(queue);
+fail_teardown:
+	ps3stor_teardown(dev);
+fail_free_bounce:
+	kfree(dev->bounce_buf);
+fail_free_priv:
+	kfree(priv);
+	ps3disk_priv(dev) = NULL;
+fail:
+	__clear_bit(devidx, &ps3disk_mask);
+	return error;
+}
+
+static int ps3disk_remove(struct ps3_system_bus_device *_dev)
+{
+	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
+	struct ps3disk_private *priv = ps3disk_priv(dev);
+
+	__clear_bit(priv->gendisk->first_minor / PS3DISK_MINORS,
+		    &ps3disk_mask);
+	del_gendisk(priv->gendisk);
+	blk_cleanup_queue(priv->queue);
+	put_disk(priv->gendisk);
+	dev_notice(&dev->sbd.core, "Synchronizing disk cache\n");
+	ps3disk_sync_cache(dev);
+	ps3stor_teardown(dev);
+	kfree(dev->bounce_buf);
+	kfree(priv);
+	ps3disk_priv(dev) = NULL;
+	return 0;
+}
+
+static struct ps3_system_bus_driver ps3disk = {
+	.match_id	= PS3_MATCH_ID_STOR_DISK,
+	.core.name	= DEVICE_NAME,
+	.core.owner	= THIS_MODULE,
+	.probe		= ps3disk_probe,
+	.remove		= ps3disk_remove,
+	.shutdown	= ps3disk_remove,
+};
+
+
+static int __init ps3disk_init(void)
+{
+	int error;
+
+	if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+		return -ENODEV;
+
+	error = register_blkdev(0, DEVICE_NAME);
+	if (error <= 0) {
+		printk(KERN_ERR "%s:%u: register_blkdev failed %d\n", __func__,
+		       __LINE__, error);
+		return error;
+	}
+	ps3disk_major = error;
+
+	pr_info("%s:%u: registered block device major %d\n", __func__,
+		__LINE__, ps3disk_major);
+
+	error = ps3_system_bus_driver_register(&ps3disk);
+	if (error)
+		unregister_blkdev(ps3disk_major, DEVICE_NAME);
+
+	return error;
+}
+
+static void __exit ps3disk_exit(void)
+{
+	ps3_system_bus_driver_unregister(&ps3disk);
+	unregister_blkdev(ps3disk_major, DEVICE_NAME);
+}
+
+module_init(ps3disk_init);
+module_exit(ps3disk_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PS3 Disk Storage Driver");
+MODULE_AUTHOR("Sony Corporation");
+MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_DISK);

-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium	
VAT BE 0413.825.160 · RPR Brussels	
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619

^ permalink raw reply

* [patch 3/3] ps3: FLASH ROM Storage Driver
From: Geert Uytterhoeven @ 2007-07-16 16:15 UTC (permalink / raw)
  To: Paul Mackerras, Jens Axboe, James E.J.  Bottomley,
	Alessandro Rubini
  Cc: Geert Uytterhoeven, linuxppc-dev, linux-kernel, linux-scsi
In-Reply-To: <20070716161539.075822000@pademelon.sonytel.be>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 14401 bytes --]

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

Add a FLASH ROM Storage Driver for the PS3:
  - Implemented as a misc character device driver
  - Uses a fixed 256 KiB buffer allocated from boot memory as the hypervisor
    requires the writing of aligned 256 KiB blocks

CC: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
v3:
  - Cleanup #includes
  - Allow to disable ps3flash (and the preallocated 256 KiB buffer) using
    `ps3flash=off'
  - Move selection of write/read strings to error path
  - Rename and move ps3stor_interrupt() to ps3flash_interrupt()
  - Pass the interrupt handler to ps3stor_setup()
  - Reset ps3flash_priv(dev) to NULL during cleanup

v2:
  - Don't use `default y' in Kconfig
  - #include <linux/uaccess.h> instead of <asm/uaccess.h>
  - Set up sysfs links between misc character device and PS3 system device:
      o /sys/class/misc/ps3flash/device -> ../../../devices/ps3_system/sb_01
      o /sys/devices/ps3_system/sb_01/misc:ps3flash -> ../../../class/misc/ps3flash

 arch/powerpc/platforms/ps3/Kconfig |   15 +
 drivers/char/Makefile              |    2 
 drivers/char/ps3flash.c            |  429 +++++++++++++++++++++++++++++++++++++
 3 files changed, 446 insertions(+)

--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -123,4 +123,19 @@ config PS3_ROM
 	  In general, all users will say Y or M.
 	  Also make sure to say Y or M to "SCSI CDROM support" later.
 
+config PS3_FLASH
+	tristate "PS3 FLASH ROM Storage Driver"
+	depends on PPC_PS3
+	select PS3_STORAGE
+	help
+	  Include support for the PS3 FLASH ROM Storage.
+
+	  This support is required to access the PS3 FLASH ROM, which
+	  contains the boot loader and some boot options.
+	  In general, all users will say Y or M.
+
+	  As this driver needs a fixed buffer of 256 KiB of memory, it can
+	  be disabled on the kernel command line using "ps3flash=off", to
+	  not allocate this fixed buffer.
+
 endmenu
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -104,6 +104,8 @@ obj-$(CONFIG_IPMI_HANDLER)	+= ipmi/
 obj-$(CONFIG_HANGCHECK_TIMER)	+= hangcheck-timer.o
 obj-$(CONFIG_TCG_TPM)		+= tpm/
 
+obj-$(CONFIG_PS3_FLASH)		+= ps3flash.o
+
 # Files generated that shall be removed upon make clean
 clean-files := consolemap_deftbl.c defkeymap.c
 
--- /dev/null
+++ b/drivers/char/ps3flash.c
@@ -0,0 +1,429 @@
+/*
+ * 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 */
+};
+#define ps3flash_priv(dev)	((dev)->sbd.core.driver_data)
+
+static struct ps3_storage_device *ps3flash_dev;
+
+static ssize_t ps3flash_read_write_sectors(struct ps3_storage_device *dev,
+					   u64 lpar, u64 start_sector,
+					   u64 sectors, int write)
+{
+	u64 res = ps3stor_read_write_sectors(dev, lpar, start_sector, sectors,
+					     write);
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: %s failed 0x%lx\n", __func__,
+			__LINE__, write ? "write" : "read", res);
+		return -EIO;
+	}
+	return sectors;
+}
+
+static ssize_t ps3flash_read_sectors(struct ps3_storage_device *dev,
+				     u64 start_sector, u64 sectors,
+				     unsigned int sector_offset)
+{
+	u64 max_sectors, lpar;
+
+	max_sectors = dev->bounce_size / dev->blk_size;
+	if (sectors > max_sectors) {
+		dev_dbg(&dev->sbd.core, "%s:%u Limiting sectors to %lu\n",
+			__func__, __LINE__, max_sectors);
+		sectors = max_sectors;
+	}
+
+	lpar = dev->bounce_lpar + sector_offset * dev->blk_size;
+	return ps3flash_read_write_sectors(dev, lpar, start_sector, sectors,
+					   0);
+}
+
+static ssize_t ps3flash_write_chunk(struct ps3_storage_device *dev,
+				    u64 start_sector)
+{
+       u64 sectors = dev->bounce_size / dev->blk_size;
+       return ps3flash_read_write_sectors(dev, dev->bounce_lpar, start_sector,
+					  sectors, 1);
+}
+
+static loff_t ps3flash_llseek(struct file *file, loff_t offset, int origin)
+{
+	struct ps3_storage_device *dev = ps3flash_dev;
+	u64 size = dev->regions[dev->region_idx].size*dev->blk_size;
+
+	switch (origin) {
+	case 1:
+		offset += file->f_pos;
+		break;
+	case 2:
+		offset += size;
+		break;
+	}
+	if (offset < 0)
+		return -EINVAL;
+
+	file->f_pos = offset;
+	return file->f_pos;
+}
+
+static ssize_t ps3flash_read(struct file *file, char __user *buf, size_t count,
+			     loff_t *pos)
+{
+	struct ps3_storage_device *dev = ps3flash_dev;
+	struct ps3flash_private *priv = ps3flash_priv(dev);
+	u64 size, start_sector, end_sector, offset;
+	ssize_t sectors_read;
+	size_t remaining, n;
+
+	dev_dbg(&dev->sbd.core,
+		"%s:%u: Reading %zu bytes at position %lld to user 0x%p\n",
+		__func__, __LINE__, count, *pos, buf);
+
+	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\n", __func__,
+			__LINE__, count, size - *pos);
+		count = size - *pos;
+	}
+
+	start_sector = do_div_llr(*pos, dev->blk_size, &offset);
+	end_sector = DIV_ROUND_UP(*pos+count, dev->blk_size);
+
+	remaining = count;
+	do {
+		mutex_lock(&priv->mutex);
+
+		sectors_read = ps3flash_read_sectors(dev, start_sector,
+						     end_sector-start_sector,
+						     0);
+		if (sectors_read < 0) {
+			mutex_unlock(&priv->mutex);
+			return sectors_read;
+		}
+
+		n = min(remaining, sectors_read*dev->blk_size-offset);
+		dev_dbg(&dev->sbd.core,
+			"%s:%u: copy %lu bytes from 0x%p to user 0x%p\n",
+			__func__, __LINE__, n, dev->bounce_buf+offset, buf);
+		if (copy_to_user(buf, dev->bounce_buf+offset, n)) {
+			mutex_unlock(&priv->mutex);
+			return -EFAULT;
+		}
+
+		mutex_unlock(&priv->mutex);
+
+		*pos += n;
+		buf += n;
+		remaining -= n;
+		start_sector += sectors_read;
+		offset = 0;
+	} while (remaining > 0);
+
+	return count;
+}
+
+static ssize_t ps3flash_write(struct file *file, const char __user *buf,
+			      size_t count, loff_t *pos)
+{
+	struct ps3_storage_device *dev = ps3flash_dev;
+	struct ps3flash_private *priv = ps3flash_priv(dev);
+	u64 size, chunk_sectors, start_write_sector, end_write_sector,
+	    end_read_sector, start_read_sector, head, tail, offset;
+	ssize_t res;
+	size_t remaining, n;
+	unsigned int sec_off;
+
+	dev_dbg(&dev->sbd.core,
+		"%s:%u: Writing %zu bytes at position %lld from user 0x%p\n",
+		__func__, __LINE__, count, *pos, buf);
+
+	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\n", __func__,
+			__LINE__, count, size - *pos);
+		count = size - *pos;
+	}
+
+	chunk_sectors = dev->bounce_size / dev->blk_size;
+
+	start_write_sector = do_div_llr(*pos, dev->bounce_size, &offset) *
+			     chunk_sectors;
+	end_write_sector = DIV_ROUND_UP(*pos+count, dev->bounce_size) *
+			   chunk_sectors;
+
+	end_read_sector = DIV_ROUND_UP(*pos, dev->blk_size);
+	start_read_sector = (*pos+count) / dev->blk_size;
+
+	/*
+	 * As we have to write in 256 KiB chunks, while we can read in blk_size
+	 * (usually 512 bytes) chunks, we perform the following steps:
+	 *   1. Read from start_write_sector to end_read_sector ("head")
+	 *   2. Read from start_read_sector to end_write_sector ("tail")
+	 *   3. Copy data to buffer
+	 *   4. Write from start_write_sector to end_write_sector
+	 * All of this is complicated by using only one 256 KiB bounce buffer.
+	 */
+
+	head = end_read_sector-start_write_sector;
+	tail = end_write_sector-start_read_sector;
+
+	remaining = count;
+	do {
+		mutex_lock(&priv->mutex);
+
+		if (end_read_sector >= start_read_sector) {
+			/* Merge head and tail */
+			dev_dbg(&dev->sbd.core,
+				"Merged head and tail: %lu sectors at %lu\n",
+				chunk_sectors, start_write_sector);
+			res = ps3flash_read_sectors(dev, start_write_sector,
+						    chunk_sectors, 0);
+			if (res < 0)
+				goto fail;
+		} else {
+			if (head) {
+				/* Read head */
+				dev_dbg(&dev->sbd.core,
+					"head: %lu sectors at %lu\n", head,
+					start_write_sector);
+				res = ps3flash_read_sectors(dev,
+							    start_write_sector,
+							    head, 0);
+				if (res < 0)
+					goto fail;
+			}
+			if (start_read_sector <
+			    start_write_sector+chunk_sectors) {
+				/* Read tail */
+				dev_dbg(&dev->sbd.core,
+					"tail: %lu sectors at %lu\n", tail,
+					start_read_sector);
+				sec_off = start_read_sector-start_write_sector;
+				res = ps3flash_read_sectors(dev,
+							    start_read_sector,
+							    tail, sec_off);
+				if (res < 0)
+					goto fail;
+			}
+		}
+
+		n = min(remaining, dev->bounce_size-offset);
+		dev_dbg(&dev->sbd.core,
+			"%s:%u: copy %lu bytes from user 0x%p to 0x%p\n",
+			__func__, __LINE__, n, buf, dev->bounce_buf+offset);
+		if (copy_from_user(dev->bounce_buf+offset, buf, n)) {
+			res = -EFAULT;
+			goto fail;
+		}
+
+		res = ps3flash_write_chunk(dev, start_write_sector);
+		if (res < 0)
+			goto fail;
+
+		mutex_unlock(&priv->mutex);
+
+		*pos += n;
+		buf += n;
+		remaining -= n;
+		start_write_sector += chunk_sectors;
+		head = 0;
+		offset = 0;
+	} while (remaining > 0);
+
+	return count;
+
+fail:
+	mutex_unlock(&priv->mutex);
+	return res;
+}
+
+
+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,
+			"%s:%u: tag mismatch, got %lx, expected %lx\n",
+			__func__, __LINE__, tag, dev->tag);
+
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n",
+			__func__, __LINE__, res, status);
+	} else {
+		dev->lv1_status = status;
+		complete(&dev->done);
+	}
+	return IRQ_HANDLED;
+}
+
+
+static const struct file_operations ps3flash_fops = {
+	.owner	= THIS_MODULE,
+	.llseek	= ps3flash_llseek,
+	.read	= ps3flash_read,
+	.write	= ps3flash_write,
+};
+
+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\n", __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\n", __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\n");
+		return -EBUSY;
+	}
+
+	ps3flash_dev = dev;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		error = -ENOMEM;
+		goto fail;
+	}
+
+	ps3flash_priv(dev) = priv;
+	mutex_init(&priv->mutex);
+
+	dev->bounce_size = ps3flash_bounce_buffer.size;
+	dev->bounce_buf = ps3flash_bounce_buffer.address;
+
+	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\n",
+			__func__, __LINE__, error);
+		goto fail_teardown;
+	}
+
+	dev_info(&dev->sbd.core, "%s:%u: registered misc device %d\n",
+		 __func__, __LINE__, ps3flash_misc.minor);
+	return 0;
+
+fail_teardown:
+	ps3stor_teardown(dev);
+fail_free_priv:
+	kfree(priv);
+	ps3flash_priv(dev) = NULL;
+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);
+
+	misc_deregister(&ps3flash_misc);
+	ps3stor_teardown(dev);
+	kfree(ps3flash_priv(dev));
+	ps3flash_priv(dev) = NULL;
+	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);

-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium	
VAT BE 0413.825.160 · RPR Brussels	
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619

^ permalink raw reply

* [patch 2/3] ps3: BD/DVD/CD-ROM Storage Driver
From: Geert Uytterhoeven @ 2007-07-16 16:15 UTC (permalink / raw)
  To: Paul Mackerras, Jens Axboe, James E.J.  Bottomley,
	Alessandro Rubini
  Cc: Geert Uytterhoeven, linuxppc-dev, linux-kernel, linux-scsi
In-Reply-To: <20070716161539.075822000@pademelon.sonytel.be>

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 17923 bytes --]

From: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

Add a BD/DVD/CD-ROM Storage Driver for the PS3:
  - Implemented as a SCSI device driver
  - Uses software scatter-gather with a 64 KiB bounce buffer as the hypervisor
    doesn't support scatter-gather

CC: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
---
v4:
  - Replace KM_USER0 by KM_IRQ0 (all kmap routines are either called from an
    interrupt handler or from .queuecommand())
  - Add a call to flush_kernel_dcache_page() before kunmap in routines that
    write to buffers

v3:
  - Replace dependency on BLK_DEV_SR by SCSI
  - Use `BD/DVD/CD-ROM' instead of `ROM' in driver descriptions
  - Inform the user to enable "SCSI CDROM support"
  - Cleanup #includes
  - Group LV1 API related stuff
  - Rename ps3rom_private.cmd to ps3rom_private.curr_cmd
  - Use shost_priv() (from scsi-misc)
  - Set scsi_device.use_10_for_rw and remove support for {READ,WRITE}_6
  - Explain why we prefer to use lv1_storage_{read,write}()
  - Pass the interrupt handler to ps3stor_setup(), so it doesn't have to be
    overridden later
  - Reset ps3rom_priv(dev) to NULL during cleanup

v2:
  - Don't use `default y' in Kconfig
  - Add missing #include <linux/highmem.h>
  - Remove ps3rom_private.scsi_done, use scsi_cmnd.scsi_done instead
  - Use scsi_device.host.hostdata
  - Remove empty ps3rom_slave_{alloc,destroy}()
  - Kill superfluous test for command in progress
  - Move scsi_host_put() last in cleanup sequence
  - Remove scsi_command(), use scsi_print_command() for debugging
  - scsi_cmnd.use_sg is always > 0 these days
  - Allocate struct ps3rom_private using scsi_host_alloc()
  - Remove the thread for handling requests
  - Remove unused position parameter enum
  - Remove unused NA_PROTO and DIR_NA
  - Derive buffer length, data direction, and transfer protocol from the
    struct scsi_command, instead of using a big switch() statement
  - Kill superfluous spinlock
  - Remove manual request sense, as modern hypervisors always do auto sense
  - Pass all SCSI commands to the hypervisor as ATAPI commands, except for
    READ_*/WRITE_*
  - Don't print errors for SCSI commands that are not allowed for an Other OS
    by the hypervisor
  - Remove superfluous tests for data directions in
    {fill_from,fetch_to}_dev_buffer()
  - Handle errors in {fill_from,fetch_to}_dev_buffer()
  - Reorder routines
  - Manually inline ps3rom_send_atapi_command()
  - Fix all FIXMEs

 arch/powerpc/platforms/ps3/Kconfig |   11 
 drivers/scsi/Makefile              |    1 
 drivers/scsi/ps3rom.c              |  538 +++++++++++++++++++++++++++++++++++++
 3 files changed, 550 insertions(+)

--- a/arch/powerpc/platforms/ps3/Kconfig
+++ b/arch/powerpc/platforms/ps3/Kconfig
@@ -112,4 +112,15 @@ config PS3_DISK
 	  This support is required to access the PS3 hard disk.
 	  In general, all users will say Y or M.
 
+config PS3_ROM
+	tristate "PS3 BD/DVD/CD-ROM Storage Driver"
+	depends on PPC_PS3 && SCSI
+	select PS3_STORAGE
+	help
+	  Include support for the PS3 ROM Storage.
+
+	  This support is required to access the PS3 BD/DVD/CD-ROM drive.
+	  In general, all users will say Y or M.
+	  Also make sure to say Y or M to "SCSI CDROM support" later.
+
 endmenu
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -132,6 +132,7 @@ obj-$(CONFIG_SCSI_IBMVSCSI)	+= ibmvscsi/
 obj-$(CONFIG_SCSI_IBMVSCSIS)	+= ibmvscsi/
 obj-$(CONFIG_SCSI_HPTIOP)	+= hptiop.o
 obj-$(CONFIG_SCSI_STEX)		+= stex.o
+obj-$(CONFIG_PS3_ROM)		+= ps3rom.o
 
 obj-$(CONFIG_ARM)		+= arm/
 
--- /dev/null
+++ b/drivers/scsi/ps3rom.c
@@ -0,0 +1,538 @@
+/*
+ * PS3 BD/DVD/CD-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/cdrom.h>
+#include <linux/highmem.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_dbg.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+
+#include <asm/lv1call.h>
+#include <asm/ps3stor.h>
+
+
+#define DEVICE_NAME			"ps3rom"
+
+#define BOUNCE_SIZE			(64*1024)
+
+#define PS3ROM_MAX_SECTORS		(BOUNCE_SIZE / CD_FRAMESIZE)
+
+
+struct ps3rom_private {
+	struct ps3_storage_device *dev;
+	struct scsi_cmnd *curr_cmd;
+};
+#define ps3rom_priv(dev)	((dev)->sbd.core.driver_data)
+
+
+#define LV1_STORAGE_SEND_ATAPI_COMMAND	(1)
+
+struct lv1_atapi_cmnd_block {
+	u8	pkt[32];	/* packet command block           */
+	u32	pktlen;		/* should be 12 for ATAPI 8020    */
+	u32	blocks;
+	u32	block_size;
+	u32	proto;		/* transfer mode                  */
+	u32	in_out;		/* transfer direction             */
+	u64	buffer;		/* parameter except command block */
+	u32	arglen;		/* length above                   */
+};
+
+enum lv1_atapi_proto {
+	NON_DATA_PROTO     = 0,
+	PIO_DATA_IN_PROTO  = 1,
+	PIO_DATA_OUT_PROTO = 2,
+	DMA_PROTO = 3
+};
+
+enum lv1_atapi_in_out {
+	DIR_WRITE = 0,		/* memory -> device */
+	DIR_READ = 1		/* device -> memory */
+};
+
+
+static int ps3rom_slave_configure(struct scsi_device *scsi_dev)
+{
+	struct ps3rom_private *priv = shost_priv(scsi_dev->host);
+	struct ps3_storage_device *dev = priv->dev;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %u, channel %u\n", __func__,
+		__LINE__, scsi_dev->id, scsi_dev->lun, scsi_dev->channel);
+
+	/*
+	 * ATAPI SFF8020 devices use MODE_SENSE_10,
+	 * so we can prohibit MODE_SENSE_6
+	 */
+	scsi_dev->use_10_for_ms = 1;
+
+	/* we don't support {READ,WRITE}_6 */
+	scsi_dev->use_10_for_rw = 1;
+
+	return 0;
+}
+
+/*
+ * copy data from device into scatter/gather buffer
+ */
+static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf)
+{
+	int k, req_len, act_len, len, active;
+	void *kaddr;
+	struct scatterlist *sgpnt;
+	unsigned int buflen;
+
+	buflen = cmd->request_bufflen;
+	if (!buflen)
+		return 0;
+
+	if (!cmd->request_buffer)
+		return -1;
+
+	sgpnt = cmd->request_buffer;
+	active = 1;
+	for (k = 0, req_len = 0, act_len = 0; k < cmd->use_sg; ++k, ++sgpnt) {
+		if (active) {
+			kaddr = kmap_atomic(sgpnt->page, KM_IRQ0);
+			if (!kaddr)
+				return -1;
+			len = sgpnt->length;
+			if ((req_len + len) > buflen) {
+				active = 0;
+				len = buflen - req_len;
+			}
+			memcpy(kaddr + sgpnt->offset, buf + req_len, len);
+			flush_kernel_dcache_page(sgpnt->page);
+			kunmap_atomic(kaddr, KM_IRQ0);
+			act_len += len;
+		}
+		req_len += sgpnt->length;
+	}
+	cmd->resid = req_len - act_len;
+	return 0;
+}
+
+/*
+ * copy data from scatter/gather into device's buffer
+ */
+static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf)
+{
+	int k, req_len, len, fin;
+	void *kaddr;
+	struct scatterlist *sgpnt;
+	unsigned int buflen;
+
+	buflen = cmd->request_bufflen;
+	if (!buflen)
+		return 0;
+
+	if (!cmd->request_buffer)
+		return -1;
+
+	sgpnt = cmd->request_buffer;
+	for (k = 0, req_len = 0, fin = 0; k < cmd->use_sg; ++k, ++sgpnt) {
+		kaddr = kmap_atomic(sgpnt->page, KM_IRQ0);
+		if (!kaddr)
+			return -1;
+		len = sgpnt->length;
+		if ((req_len + len) > buflen) {
+			len = buflen - req_len;
+			fin = 1;
+		}
+		memcpy(buf + req_len, kaddr + sgpnt->offset, len);
+		kunmap_atomic(kaddr, KM_IRQ0);
+		if (fin)
+			return req_len + len;
+		req_len += sgpnt->length;
+	}
+	return req_len;
+}
+
+static int ps3rom_atapi_request(struct ps3_storage_device *dev,
+				struct scsi_cmnd *cmd)
+{
+	struct lv1_atapi_cmnd_block atapi_cmnd;
+	unsigned char opcode = cmd->cmnd[0];
+	int res;
+	u64 lpar;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: send ATAPI command 0x%02x\n", __func__,
+		__LINE__, opcode);
+
+	memset(&atapi_cmnd, 0, sizeof(struct lv1_atapi_cmnd_block));
+	memcpy(&atapi_cmnd.pkt, cmd->cmnd, 12);
+	atapi_cmnd.pktlen = 12;
+	atapi_cmnd.block_size = 1; /* transfer size is block_size * blocks */
+	atapi_cmnd.blocks = atapi_cmnd.arglen = cmd->request_bufflen;
+	atapi_cmnd.buffer = dev->bounce_lpar;
+
+	switch (cmd->sc_data_direction) {
+	case DMA_FROM_DEVICE:
+		if (cmd->request_bufflen >= CD_FRAMESIZE)
+			atapi_cmnd.proto = DMA_PROTO;
+		else
+			atapi_cmnd.proto = PIO_DATA_IN_PROTO;
+		atapi_cmnd.in_out = DIR_READ;
+		break;
+
+	case DMA_TO_DEVICE:
+		if (cmd->request_bufflen >= CD_FRAMESIZE)
+			atapi_cmnd.proto = DMA_PROTO;
+		else
+			atapi_cmnd.proto = PIO_DATA_OUT_PROTO;
+		atapi_cmnd.in_out = DIR_WRITE;
+		res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
+		if (res < 0)
+			return DID_ERROR << 16;
+		break;
+
+	default:
+		atapi_cmnd.proto = NON_DATA_PROTO;
+		break;
+	}
+
+	lpar = ps3_mm_phys_to_lpar(__pa(&atapi_cmnd));
+	res = lv1_storage_send_device_command(dev->sbd.dev_id,
+					      LV1_STORAGE_SEND_ATAPI_COMMAND,
+					      lpar, sizeof(atapi_cmnd),
+					      atapi_cmnd.buffer,
+					      atapi_cmnd.arglen, &dev->tag);
+	if (res == LV1_DENIED_BY_POLICY) {
+		dev_dbg(&dev->sbd.core,
+			"%s:%u: ATAPI command 0x%02x denied by policy\n",
+			__func__, __LINE__, opcode);
+		return DID_ERROR << 16;
+	}
+
+	if (res) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: ATAPI command 0x%02x failed %d\n", __func__,
+			__LINE__, opcode, res);
+		return DID_ERROR << 16;
+	}
+
+	return 0;
+}
+
+static inline unsigned int srb10_lba(const struct scsi_cmnd *cmd)
+{
+	return cmd->cmnd[2] << 24 | cmd->cmnd[3] << 16 | cmd->cmnd[4] << 8 |
+	       cmd->cmnd[5];
+}
+
+static inline unsigned int srb10_len(const struct scsi_cmnd *cmd)
+{
+	return cmd->cmnd[7] << 8 | cmd->cmnd[8];
+}
+
+static int ps3rom_read_request(struct ps3_storage_device *dev,
+			       struct scsi_cmnd *cmd, u32 start_sector,
+			       u32 sectors)
+{
+	int res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: read %u sectors starting at %u\n",
+		__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);
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: read failed %d\n", __func__,
+			__LINE__, res);
+		return DID_ERROR << 16;
+	}
+
+	return 0;
+}
+
+static int ps3rom_write_request(struct ps3_storage_device *dev,
+				struct scsi_cmnd *cmd, u32 start_sector,
+				u32 sectors)
+{
+	int res;
+
+	dev_dbg(&dev->sbd.core, "%s:%u: write %u sectors starting at %u\n",
+		__func__, __LINE__, sectors, start_sector);
+
+	res = fetch_to_dev_buffer(cmd, dev->bounce_buf);
+	if (res < 0)
+		return DID_ERROR << 16;
+
+	res = lv1_storage_write(dev->sbd.dev_id,
+				dev->regions[dev->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);
+		return DID_ERROR << 16;
+	}
+
+	return 0;
+}
+
+static int ps3rom_queuecommand(struct scsi_cmnd *cmd,
+			       void (*done)(struct scsi_cmnd *))
+{
+	struct ps3rom_private *priv = shost_priv(cmd->device->host);
+	struct ps3_storage_device *dev = priv->dev;
+	unsigned char opcode;
+	int res;
+
+#ifdef DEBUG
+	scsi_print_command(cmd);
+#endif
+
+	priv->curr_cmd = cmd;
+	cmd->scsi_done = done;
+
+	opcode = cmd->cmnd[0];
+	/*
+	 * While we can submit READ/WRITE SCSI commands as ATAPI commands,
+	 * it's recommended for various reasons (performance, error handling,
+	 * ...) to use lv1_storage_{read,write}() instead
+	 */
+	switch (opcode) {
+	case READ_10:
+		res = ps3rom_read_request(dev, cmd, srb10_lba(cmd),
+					  srb10_len(cmd));
+		break;
+
+	case WRITE_10:
+		res = ps3rom_write_request(dev, cmd, srb10_lba(cmd),
+					   srb10_len(cmd));
+		break;
+
+	default:
+		res = ps3rom_atapi_request(dev, cmd);
+		break;
+	}
+
+	if (res) {
+		memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
+		cmd->result = res;
+		cmd->sense_buffer[0] = 0x70;
+		cmd->sense_buffer[2] = ILLEGAL_REQUEST;
+		priv->curr_cmd = NULL;
+		cmd->scsi_done(cmd);
+	}
+
+	return 0;
+}
+
+static int decode_lv1_status(u64 status, unsigned char *sense_key,
+			     unsigned char *asc, unsigned char *ascq)
+{
+	if (((status >> 24) & 0xff) != SAM_STAT_CHECK_CONDITION)
+		return -1;
+
+	*sense_key = (status >> 16) & 0xff;
+	*asc       = (status >>  8) & 0xff;
+	*ascq      =  status        & 0xff;
+	return 0;
+}
+
+static irqreturn_t ps3rom_interrupt(int irq, void *data)
+{
+	struct ps3_storage_device *dev = data;
+	struct Scsi_Host *host;
+	struct ps3rom_private *priv;
+	struct scsi_cmnd *cmd;
+	int res;
+	u64 tag, status;
+	unsigned char sense_key, asc, ascq;
+
+	res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status);
+	/*
+	 * status = -1 may mean that ATAPI transport completed OK, but
+	 * ATAPI command itself resulted CHECK CONDITION
+	 * so, upper layer should issue REQUEST_SENSE to check the sense data
+	 */
+
+	if (tag != dev->tag)
+		dev_err(&dev->sbd.core,
+			"%s:%u: tag mismatch, got %lx, expected %lx\n",
+			__func__, __LINE__, tag, dev->tag);
+
+	if (res) {
+		dev_err(&dev->sbd.core, "%s:%u: res=%d status=0x%lx\n",
+			__func__, __LINE__, res, status);
+		return IRQ_HANDLED;
+	}
+
+	host = ps3rom_priv(dev);
+	priv = shost_priv(host);
+	cmd = priv->curr_cmd;
+
+	if (!status) {
+		/* OK, completed */
+		if (cmd->sc_data_direction == DMA_FROM_DEVICE) {
+			res = fill_from_dev_buffer(cmd, dev->bounce_buf);
+			if (res) {
+				cmd->result = DID_ERROR << 16;
+				goto done;
+			}
+		}
+		cmd->result = DID_OK << 16;
+		goto done;
+	}
+
+	if (cmd->cmnd[0] == REQUEST_SENSE) {
+		/* SCSI spec says request sense should never get error */
+		dev_err(&dev->sbd.core, "%s:%u: end error without autosense\n",
+			__func__, __LINE__);
+		cmd->result = DID_ERROR << 16 | SAM_STAT_CHECK_CONDITION;
+		goto done;
+	}
+
+	if (decode_lv1_status(status, &sense_key, &asc, &ascq)) {
+		cmd->result = DID_ERROR << 16;
+		goto done;
+	}
+
+	cmd->sense_buffer[0]  = 0x70;
+	cmd->sense_buffer[2]  = sense_key;
+	cmd->sense_buffer[7]  = 16 - 6;
+	cmd->sense_buffer[12] = asc;
+	cmd->sense_buffer[13] = ascq;
+	cmd->result = SAM_STAT_CHECK_CONDITION;
+
+done:
+	priv->curr_cmd = NULL;
+	cmd->scsi_done(cmd);
+	return IRQ_HANDLED;
+}
+
+static struct scsi_host_template ps3rom_host_template = {
+	.name =			DEVICE_NAME,
+	.slave_configure =	ps3rom_slave_configure,
+	.queuecommand =		ps3rom_queuecommand,
+	.can_queue =		1,
+	.this_id =		7,
+	.sg_tablesize =		SG_ALL,
+	.cmd_per_lun =		1,
+	.emulated =             1,		/* only sg driver uses this */
+	.max_sectors =		PS3ROM_MAX_SECTORS,
+	.use_clustering =	ENABLE_CLUSTERING,
+	.module =		THIS_MODULE,
+};
+
+
+static int __devinit ps3rom_probe(struct ps3_system_bus_device *_dev)
+{
+	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
+	int error;
+	struct Scsi_Host *host;
+	struct ps3rom_private *priv;
+
+	if (dev->blk_size != CD_FRAMESIZE) {
+		dev_err(&dev->sbd.core,
+			"%s:%u: cannot handle block size %lu\n", __func__,
+			__LINE__, dev->blk_size);
+		return -EINVAL;
+	}
+
+	dev->bounce_size = BOUNCE_SIZE;
+	dev->bounce_buf = kmalloc(BOUNCE_SIZE, GFP_DMA);
+	if (!dev->bounce_buf)
+		return -ENOMEM;
+
+	error = ps3stor_setup(dev, ps3rom_interrupt);
+	if (error)
+		goto fail_free_bounce;
+
+	host = scsi_host_alloc(&ps3rom_host_template,
+			       sizeof(struct ps3rom_private));
+	if (!host) {
+		dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed\n",
+			__func__, __LINE__);
+		goto fail_teardown;
+	}
+
+	priv = shost_priv(host);
+	ps3rom_priv(dev) = host;
+	priv->dev = dev;
+
+	/* One device/LUN per SCSI bus */
+	host->max_id = 1;
+	host->max_lun = 1;
+
+	error = scsi_add_host(host, &dev->sbd.core);
+	if (error) {
+		dev_err(&dev->sbd.core, "%s:%u: scsi_host_alloc failed %d\n",
+			__func__, __LINE__, error);
+		error = -ENODEV;
+		goto fail_host_put;
+	}
+
+	scsi_scan_host(host);
+	return 0;
+
+fail_host_put:
+	scsi_host_put(host);
+	ps3rom_priv(dev) = NULL;
+fail_teardown:
+	ps3stor_teardown(dev);
+fail_free_bounce:
+	kfree(dev->bounce_buf);
+	return error;
+}
+
+static int ps3rom_remove(struct ps3_system_bus_device *_dev)
+{
+	struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core);
+	struct Scsi_Host *host = ps3rom_priv(dev);
+
+	scsi_remove_host(host);
+	ps3stor_teardown(dev);
+	scsi_host_put(host);
+	ps3rom_priv(dev) = NULL;
+	kfree(dev->bounce_buf);
+	return 0;
+}
+
+static struct ps3_system_bus_driver ps3rom = {
+	.match_id	= PS3_MATCH_ID_STOR_ROM,
+	.core.name	= DEVICE_NAME,
+	.core.owner	= THIS_MODULE,
+	.probe		= ps3rom_probe,
+	.remove		= ps3rom_remove
+};
+
+
+static int __init ps3rom_init(void)
+{
+	return ps3_system_bus_driver_register(&ps3rom);
+}
+
+static void __exit ps3rom_exit(void)
+{
+	ps3_system_bus_driver_unregister(&ps3rom);
+}
+
+module_init(ps3rom_init);
+module_exit(ps3rom_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("PS3 BD/DVD/CD-ROM Storage Driver");
+MODULE_AUTHOR("Sony Corporation");
+MODULE_ALIAS(PS3_MODULE_ALIAS_STOR_ROM);

-- 
With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium	
VAT BE 0413.825.160 · RPR Brussels	
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619

^ permalink raw reply

* RE: XSysAce driver cant mount DOS part
From: Robertson, Joseph M. @ 2007-07-16 16:19 UTC (permalink / raw)
  To: urwithsudheer; +Cc: linuxppc-embedded
In-Reply-To: <469AFD4B.3090704@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 9982 bytes --]

Hi,

Thanks for your insight into the older code. 
I tried your fix and came up with this.
I have run e2fsck and the cf card comes up clean with that.

heres a boot sequence:

Initializing Cryptographic API
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x40421003 (irq = 4) is a 16550A
serial8250.0: ttyS1 at MMIO 0x40401003 (irq = 5) is a 16550A
RAMDISK driver initialized: 16 RAM disks of 65536K size 1024 blocksize
XSysAce driver  v0771.
IDENTIFY: heads: 16, nsec: 63, cyls: 1011, size= 1019088
REGISTERED: major no.= 125 capacity= 1019088
 xsa: xsa1 xsa2 xsa3
Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
mice: PS/2 mouse device common for all mice
TCP bic registered
NET: Registered protocol family 1
VFS: Mounted root (ext2 filesystem) readonly.
Freeing unused kernel memory: 100k init
EXT2-fs error (device xsa2): ext2_check_page: bad entry in directory #32689: unaligned directory entry - offset=1024, inode=1713398885, rec_len=29295, name_len=109
Warning: unable to open an initial console.
init has generated signal 11 but has no handler for it
Kernel panic - not syncing: Attempted to kill init!


The only thing I notice is that the disk capacity is wrong, its a 512Mb, not a 1Gb as shown.

Any thoughts about what to look into next?

Thanks a lot.


Joe Robertson
Joseph.Robertson@sanmina-sci.com



-----Original Message-----
From: urwithsudheer [mailto:urwithsudheer@gmail.com]
Sent: Mon 7/16/2007 12:08 AM
To: Robertson, Joseph M.
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: XSysAce driver cant mount DOS part
 
Hi Joe Robertson,

Thanks for the link.

In the xsa_thread function, can u try changing the hardcoded coded value 
"2" to "xsa_cur_req->current_nr_sectors " 


The actual code in the given link.

for(i = xsa_cur_req->current_nr_sectors; i > 0; i-=2){
+			xsa_device.req_done = 1;
+			while ((stat = cur_req(&SysAce, sector,
+					2,
+					buffer)) == XST_DEVICE_BUSY)
+				xsa_short_delay();


Try changing it to ...

for(i = xsa_cur_req->current_nr_sectors; i > 0; 
i-=xsa_cur_req->current_nr_sectors ){ xsa_device.req_done = 1;
while ((stat = cur_req(&SysAce, sector,
                                     xsa_cur_req->current_nr_sectors ,
                                    buffer)) == XST_DEVICE_BUSY)
                xsa_short_delay();



Due to the hardcoded value, it gave problem while mounting but no issue 
with fdisk. It mounts well but generated a kernel BUG. Tried changing 
the value to '1' from '2' , fdisk crashed but mount is working well. So 
removed the hardcode value and then placed the dynamic variable 
xsa_cur_req->current_nr_sectors which is chosen by kernel. And now fdisk 
and mount both are working fine.


Pl let me know the results in your setup.

Thanks
Sudheer


Robertson, Joseph M. wrote:
>
> Hi,
>
> Yes, I got it from here.
> http://www.cs.york.ac.uk/rtslab/demos/amos/xupv2pro/patches/linuxppc-2.6.17.1-sysace-1.2.patch
>
> The 'official' one, yes?
>
> Thanks,
>
> Joe Robertson
> Joseph.Robertson@sanmina-sci.com
>
>
>
> -----Original Message-----
> From: urwithsudheer [mailto:urwithsudheer@gmail.com]
> Sent: Fri 7/13/2007 4:25 AM
> To: Robertson, Joseph M.
> Cc: linuxppc-embedded@ozlabs.org
> Subject: Re: XSysAce driver cant mount DOS part
>
> Hi
>
> Robertson, Joseph M. wrote:
> >
> > Hi all,
> >
> > I've been workig with this for a while but have made no progress.
> > Today I got the latest XSysAce patch for kernel 2.6.17.1 and applied
> > it to get clean code.
> > I inherited the previous code from another developer.
> >
> Can you send the link to xsysace driver source code from where you 
> obtained.
>
>
> Thanks
> Sudheer
>
>
> >
> > My problem is that mounting the DOS partition always fails in a short
> > time with a kernel oops.
> >
> > ECAU-9999:# Oops: kernel access of bad area, sig: 11
> > [#1]                     
> > 
> PREEMPT                                                                       
> > NIP: C00701C8 LR: C0070C18 CTR:
> > 00000000                                      
> > REGS: c0391dd0 TRAP: 0300   Not tainted 
> > (2.6.17.1)                           
> > MSR: 00021030 <ME,IR,DR>  CR: 22028082  XER:
> > 0000000B                         
> > DAR: 00000000, DSISR:
> > 00800000                                                
> > TASK = c0373030[4] 'events/0' THREAD:
> > c0390000                                
> > GPR00: 00000080 C0391E80 C0373030 C02CAC00 C0E03000 C0E03154 00000000
> > C02CAC00
> > GPR08: 00200200 00000000 00100100 00000000 00051A4B FFFFDE60 03BD4900
> > 007FFF3B
> > GPR16: 00400000 00000001 FFFFFFFF 03BCDC58 00000000 007FFF00 00000002
> > C0280000
> > GPR24: C0363A10 0000000B 00000000 00000000 00000000 C02CAC00 C035ED20
> > C0E03000
> > NIP [C00701C8]
> > free_block+0x8c/0x138                                          
> > LR [C0070C18]
> > drain_array+0xb8/0x124                                          
> > Call Trace:                                 
> >
> > The setup:
> > My own build system.
> > Kernel 2.6.17.1 with lots of xilinx stuff, eth, i2c, xsysace. 
> > Crosscompiled for PPC405.
> > Latest, clean XSysAce code.  mods:  major hardcoded to = 125.  Polled
> > mode.
> > CF:  3 partitions,
> > 1:  DOS FAT16
> > 2:  Ext2  main
> > 3:  Ext2  rescue
> >
> > This build boots up fine, mounts a ext2 as root fine.  I can also
> > mount the rescue partition with no problems.
> >
> > Does anyone have any pointers of where I should look for problems?
> >
> > My next step is to go and set it up for interrupt service and see if
> > that changes anything.
> >
> > Thanks,
> >
> > Joe Robertson
> > Joseph.Robertson@sanmina-sci.com
> >
> >
> > CONFIDENTIALITY
> > This e-mail message and any attachments thereto, is intended only for
> > use by the addressee(s) named herein and may contain legally
> > privileged and/or confidential information. If you are not the
> > intended recipient of this e-mail message, you are hereby notified
> > that any dissemination, distribution or copying of this e-mail
> > message, and any attachments thereto, is strictly prohibited. If you
> > have received this e-mail message in error, please immediately notify
> > the sender and permanently delete the original and any copies of this
> > email and any prints thereof.
> > ABSENT AN EXPRESS STATEMENT TO THE CONTRARY HEREINABOVE, THIS E-MAIL
> > IS NOT INTENDED AS A SUBSTITUTE FOR A WRITING. Notwithstanding the
> > Uniform Electronic Transactions Act or the applicability of any other
> > law of similar substance and effect, absent an express statement to
> > the contrary hereinabove, this e-mail message its contents, and any
> > attachments hereto are not intended to represent an offer or
> > acceptance to enter into a contract and are not otherwise intended to
> > bind the sender, Sanmina-SCI Corporation (or any of its subsidiaries),
> > or any other person or entity.
> > ------------------------------------------------------------------------
> >
> > _______________________________________________
> > Linuxppc-embedded mailing list
> > Linuxppc-embedded@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>
>
> CONFIDENTIALITY
> This e-mail message and any attachments thereto, is intended only for 
> use by the addressee(s) named herein and may contain legally 
> privileged and/or confidential information. If you are not the 
> intended recipient of this e-mail message, you are hereby notified 
> that any dissemination, distribution or copying of this e-mail 
> message, and any attachments thereto, is strictly prohibited. If you 
> have received this e-mail message in error, please immediately notify 
> the sender and permanently delete the original and any copies of this 
> email and any prints thereof.
> ABSENT AN EXPRESS STATEMENT TO THE CONTRARY HEREINABOVE, THIS E-MAIL 
> IS NOT INTENDED AS A SUBSTITUTE FOR A WRITING. Notwithstanding the 
> Uniform Electronic Transactions Act or the applicability of any other 
> law of similar substance and effect, absent an express statement to 
> the contrary hereinabove, this e-mail message its contents, and any 
> attachments hereto are not intended to represent an offer or 
> acceptance to enter into a contract and are not otherwise intended to 
> bind the sender, Sanmina-SCI Corporation (or any of its subsidiaries), 
> or any other person or entity.



CONFIDENTIALITY
This e-mail message and any attachments thereto, is intended only for use by the addressee(s) named herein and may contain legally privileged and/or confidential information. If you are not the intended recipient of this e-mail message, you are hereby notified that any dissemination, distribution or copying of this e-mail message, and any attachments thereto, is strictly prohibited.  If you have received this e-mail message in error, please immediately notify the sender and permanently delete the original and any copies of this email and any prints thereof.
ABSENT AN EXPRESS STATEMENT TO THE CONTRARY HEREINABOVE, THIS E-MAIL IS NOT INTENDED AS A SUBSTITUTE FOR A WRITING.  Notwithstanding the Uniform Electronic Transactions Act or the applicability of any other law of similar substance and effect, absent an express statement to the contrary hereinabove, this e-mail message its contents, and any attachments hereto are not intended to represent an offer or acceptance to enter into a contract and are not otherwise intended to bind the sender, Sanmina-SCI Corporation (or any of its subsidiaries), or any other person or entity.

[-- Attachment #2: Type: text/html, Size: 15511 bytes --]

^ permalink raw reply

* Re: Gdbserver syscall clobber
From: Daniel Jacobowitz @ 2007-07-16 15:53 UTC (permalink / raw)
  To: Bill Gatliff; +Cc: gdb, linuxppc-embedded
In-Reply-To: <469B922D.3050701@billgatliff.com>

On Mon, Jul 16, 2007 at 10:43:41AM -0500, Bill Gatliff wrote:
> recv(4, 0x7ffffd60, 1, 0)               = ? ERESTARTSYS (To be restarted)
> --- SIGIO (I/O possible) @ 0 (0) ---
> syscall_4294966784(0xa, 0x7ffffd34, 0x1, 0, 0x1008a3c7, 0x1008b5a3, 0x1008b5a4, 

That's -512, a.k.a. the errno value used by syscall restarting.  I'd
say your glibc does not obey the restartable syscall convention used
by your kernel, and when it tries to restart the syscall the errno
value is not being replaced by the syscall number.  Check the assembly
for recv.

-- 
Daniel Jacobowitz
CodeSourcery

^ permalink raw reply

* Re: How to add platform specific data to a of_device
From: Segher Boessenkool @ 2007-07-16 16:28 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1184569752.25235.46.camel@localhost.localdomain>

> As I wrote a couple of times already, it's a perfectly acceptable
> approach to have "constructors" (what you call oftree-interpreter)  
> that
> generate platform devices from the OF tree.

Yes, lots of the "glue" code could be made into some
helper library.  Also, while that glue code might be
perceived as being "a lot of stuff", it isn't really,
and it is quite simple anyway; it's just a layer that
sits there to translate for the impedance mismatch of
the device tree on one hand, and the kernel interfaces
on the other.  Because we do have such a layer, interface
changes aren't a big deal; and since the device tree
interface is a way flexible, mostly text-based associative
array tree thing, we have none of the problems that
binary firmware interfaces on other platforms have.  Oh,
and the Open Firmware device tree works perfectly fine
across different architectures, too.

>> and they often contain redundant information (like names of oftree
>> nodes, which change more often than some people's panties).
>
> Well, they aren't supposed to :-) The problem at this point is more  
> due
> to the fact that for things that haven't been specified by official OF
> bindings, people are going all over trying to define their own and
> sometimes conflicting bindings and then changing them.

This is most of the "endless debate", too.


Segher

^ permalink raw reply

* [PATCH] cell: CONFIG_SPE_BASE is a typo (was: Re: possible dead CONFIG-related content under arch/powerpc)
From: Geert Uytterhoeven @ 2007-07-16 16:35 UTC (permalink / raw)
  To: Arnd Bergmann; +Cc: Linux PPC Mailing List, Robert P. J. Day
In-Reply-To: <1184591114.17330.1.camel@concordia.ozlabs.ibm.com>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1528 bytes --]

The config symbol for SPE support is called CONFIG_SPU_BASE, not
CONFIG_SPE_BASE.

Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>

diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 4f2f453..0b25d42 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -609,7 +609,7 @@ static void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
 	mm->context.sllp = SLB_VSID_USER | mmu_psize_defs[MMU_PAGE_4K].sllp;
 #endif /* CONFIG_PPC_MM_SLICES */
 
-#ifdef CONFIG_SPE_BASE
+#ifdef CONFIG_SPU_BASE
 	spu_flush_all_slbs(mm);
 #endif
 }
@@ -744,7 +744,7 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
 			       "to 4kB pages because of "
 			       "non-cacheable mapping\n");
 			psize = mmu_vmalloc_psize = MMU_PAGE_4K;
-#ifdef CONFIG_SPE_BASE
+#ifdef CONFIG_SPU_BASE
 			spu_flush_all_slbs(mm);
 #endif
 		}

With kind regards,
 
Geert Uytterhoeven
Software Architect

Sony Network and Software Technology Center Europe
The Corporate Village · Da Vincilaan 7-D1 · B-1935 Zaventem · Belgium
 
Phone:    +32 (0)2 700 8453	
Fax:      +32 (0)2 700 8622	
E-mail:   Geert.Uytterhoeven@sonycom.com	
Internet: http://www.sony-europe.com/
 	
Sony Network and Software Technology Center Europe	
A division of Sony Service Centre (Europe) N.V.	
Registered office: Technologielaan 7 · B-1840 Londerzeel · Belgium	
VAT BE 0413.825.160 · RPR Brussels	
Fortis Bank Zaventem · Swift GEBABEBB08A · IBAN BE39001382358619

^ permalink raw reply related

* Re: How to add platform specific data to a of_device
From: Segher Boessenkool @ 2007-07-16 16:47 UTC (permalink / raw)
  To: Robert Schwebel; +Cc: linuxppc-dev
In-Reply-To: <20070716071936.GK1678@pengutronix.de>

>> Well, they aren't supposed to :-) The problem at this point is  
>> more due
>> to the fact that for things that haven't been specified by  
>> official OF
>> bindings, people are going all over trying to define their own and
>> sometimes conflicting bindings and then changing them.
>
> I think it is a fundamental thing: the "we just have to wait long
> enough, until oftree definitions have settled" proposal just isn't
> right.

The big problem here is that lots of people got the _basic_
stuff wrong.  I feel that this is getting much better the
last few months though :-)

> It may be right for big irons, being well defined.

OF is being successfully used on many many more systems
than just "big iron"; and many of those do have really weird
quirks.  arch/powerpc also deals with many systems that don't
get their device trees quite right (*cough* powermac *cough*)
and that is doable just fine.  The quirks should be separated
more from the normal code though, in the Linux OF layer.

> But for the
> embedded processors, too less people are working on it, plus we  
> have too
> much things which could be defined.

For embedded, too often the whole bloody thing is dropped
onto the "bigger Linux community" after it has been developed
in-house for many many months.  And usually, lots of core
things are very wrong.  This is a problem with "embedded"
in general, nothing new for OF.

> Speaking of the MPC5200, look at how
> often device tree names change, e.g. for mpc5200 vs. mpc52xx vs.
> whatever. As long as things change, you have to keep the three  
> locations
> in sync manually, and that's bad.

No, you *do not* have to keep them in synch, that's part of
the beauty of the device tree definition.  Sure, you have to
make sure the consumer is at least as new as the producer,
unless people took pains to try to create wrong-way-around
compatibility.  Nothing new there.


Segher

^ permalink raw reply

* Re: [patch] use __attribute__ in asm-powerpc
From: Mike Frysinger @ 2007-07-16 16:51 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: linuxppc-dev, paulus, linux-kernel
In-Reply-To: <Pine.LNX.4.62.0707161117150.1072@pademelon.sonytel.be>

[-- Attachment #1: Type: text/plain, Size: 1257 bytes --]

On Monday 16 July 2007, Geert Uytterhoeven wrote:
> On Sat, 14 Jul 2007, Mike Frysinger wrote:
> > Pretty much everyone uses "__attribute__" or "attribute", no one
> > uses "__attribute".  This patch tweaks the three places in asm-powerpc
> > where this comes up.  While only asm-powerpc/types.h is interesting (for
> > userspace), I did asm-powerpc/processor.h as well for consistency.
> >
> > Signed-off-by: Mike Frysinger <vapier@gentoo.org>
> > ---
> > diff --git a/include/asm-powerpc/processor.h
> > b/include/asm-powerpc/processor.h index d947b16..2ce6ea6 100644
> > --- a/include/asm-powerpc/processor.h
> > +++ b/include/asm-powerpc/processor.h
> > @@ -153,9 +153,9 @@ struct thread_struct {
> >  	unsigned long	dabr;		/* Data address breakpoint register */
> >  #ifdef CONFIG_ALTIVEC
> >  	/* Complete AltiVec register set */
> > -	vector128	vr[32] __attribute((aligned(16)));
> > +	vector128	vr[32] __attribute__((aligned(16)));
>
> If the code is not exported to userspace (and thus not subject to different
> compilers), I think the preferred form is plain `attribute'.

i never said asm-powerpc/processor.h was exported to userspace ... i did say 
that i changed the file to be consistent with all other files.
-mike

[-- Attachment #2: This is a digitally signed message part. --]
[-- Type: application/pgp-signature, Size: 827 bytes --]

^ permalink raw reply

* Re: [PATCH 2/2]  Add PCI/PCI Express node for 8544DS board]
From: Segher Boessenkool @ 2007-07-16 17:12 UTC (permalink / raw)
  To: Zang Roy-r61911; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <1184321144.30789.45.camel@localhost.localdomain>

It looks real good now :-)

One tiny comment...

> +		pci@a000 {
> +			compatible = "fsl,mpc8548-pcie";

I would name the node pcie@a000 instead; generic names
aren't for machine consumption anyway, and most humans
want to know which buses are plain PCI vs. PCI-X vs.
PCI Express.

This could be changed with a follow-up patch of course.


Segher

^ permalink raw reply

* Re: [PATCH 04/10] IB/ehca: use common error code mapping instead of specific ones
From: Roland Dreier @ 2007-07-16 17:14 UTC (permalink / raw)
  To: Joachim Fenkes
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher
In-Reply-To: <200707121749.03556.fenkes@de.ibm.com>

 > @@ -161,8 +161,11 @@ static inline int ehca2ib_return_code(u64 ehca_rc)

applied, but as a further cleanup it seems that ehca2ib_return_code()
should be moved into a .c file and moved out of line -- I think it
would probably shrink the compiled code quite a bit, and as far as I
can see it is never used in the data path where the function call
overhead would matter at all.

^ permalink raw reply

* Re: [PATCH] crash in 2.6.22-git2 sysctl_set_parent()
From: Linas Vepstas @ 2007-07-16 17:22 UTC (permalink / raw)
  To: Eric W. Biederman; +Cc: linuxppc-dev, linux-kernel, netdev
In-Reply-To: <m13azreqtr.fsf@ebiederm.dsl.xmission.com>

On Fri, Jul 13, 2007 at 07:06:56PM -0600, Eric W. Biederman wrote:
> >  			.data		= &ipv4_devconf.loop,
> >  			.maxlen		= sizeof(int),
> >  			.mode		= 0644,
> > +			.child	= 0x0,
> >  			.proc_handler	= &proc_dointvec,
> >  		},
> Where did this entry above in devinet_sysctl come from?

My bad.
I habitually apply the "send-to-self" patch, since some of the 
network testing that I do is easiest if I load up the all of the 
adapters in the same box. (If you're not familiar with this patch ... 
its great, and I wish it was integratedd into mainline. It allows
one to drive network traffic through the physical devices, even
if they are in the same box.  Without it, the network stack is
too clever, and won't allow you to do this.)

> > +		{
> > +			.ctl_name	= 0,
> > +			.procname	= 0,
> > +		},
> I probably would have just done:
> +		{},

Yes, in retrospect, this would have been the simplest solution.

> What added the additional entry to devinet_root_dir?  I don't see that
> in Linus' tree?
> 
> The result may be fine but if it isn't named in a per network device
> manner we are adding duplicate entries to the root /proc/sys directory
> which is wrong.
> 
> Actually come to think of it I am concerned that someone added a
> settable entry into /proc/sys/ it should at least be in /proc/sys/net/
> where it won't conflict with other uses of that directory.  Especially
> as things like network devices have user controlled names.

Sigh. Silly me. Haste makes waste.

--linas

^ permalink raw reply

* RE: [PATCH] Fix Tsi108 ethernet driver performance
From: Alexandre Bounine @ 2007-07-16 17:25 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev
In-Reply-To: <4697E160.9000009@freescale.com>

I agree that 20 ms is not the best option. But, as you mentioned as
well, shorter period may bring more wasted CPU cycles.
Using this approach to interrupt moderation I see performance
improvement using frame flow that generates about one interrupt per
frame. Below are CPU usage numbers reported by top for the current and
patched versions of the Tsi108_eth driver.=20=20=20=20=20=20=20

Current version:
Cpu(s):  0.0% us, 0.3% sy, 0.0% ni, 14.6% id, 0.0% wa, 14.6% hi, 70.4%
si

Patched version:
Cpu(s):  0.0% us, 0.0% sy, 0.0% ni, 35.2% id, 1.2% wa, 2.4% hi, 61.2% si

- Alex.


-----Original Message-----
From: Scott Wood [mailto:scottwood@freescale.com]=20
Sent: Friday, July 13, 2007 4:33 PM
To: Scott Wood
Cc: Alexandre Bounine; linuxppc-dev@ozlabs.org
Subject: Re: [PATCH] Fix Tsi108 ethernet driver performance

Scott Wood wrote:
> Wouldn't this cause latencies of up to a second in responding to=20
> received packets?  I'd think that would be considered excessive.
>=20
> And shouldn't NAPI be reducing the RX interrupt load anyway?

Sorry, I missed that you reduced the interval to 20 ms.  Still, a bit on

the high side, and a source of wasted CPU cycles when the network isn't=20
heavily loaded.  How much of a difference in CPU usage did you see with=20
this patch?

-Scott

---=0D
=0D
Important Notice: This message is intended for the use of the individual to=
 whom it is addressed and may contain information which is privileged, conf=
idential and/or exempt from disclosure under applicable law. If the reader =
of this message is not the intended recipient, or is not the employee or ag=
ent responsible for delivering the message to the intended recipient, you a=
re hereby notified that any dissemination, distribution, or copying of this=
 communication is strictly prohibited. If you have received this communicat=
ion in error, please notify the sender immediately by telephone or return e=
-mail and delete the original message from your systems. Thank you. =0D

^ permalink raw reply

* Re: [PATCH] crash in 2.6.22-git2 sysctl_set_parent()
From: Linas Vepstas @ 2007-07-16 17:25 UTC (permalink / raw)
  To: David Miller; +Cc: linuxppc-dev, netdev, ebiederm, linux-kernel
In-Reply-To: <20070713.154702.17863636.davem@davemloft.net>

On Fri, Jul 13, 2007 at 03:47:02PM -0700, David Miller wrote:
> From: linas@austin.ibm.com (Linas Vepstas)
> Date: Fri, 13 Jul 2007 15:05:15 -0500
> 
> > 
> > This is a patch (& bug report) for a crash in sysctl_set_parent() 
> > in 2.6.22-git2. 
> > 
> > Problem: 2.6.22-git2 crashes with a stack trace 
> > 
> > Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
> 
> Thanks for tracking this down, I'll apply your patch.

NAK. As I just explained in another email, this bug
was introduced by the "send-to-self" patch I habitually
apply -- so habitually, that I forgot I was not working 
with a "clean" tree. So it goes ... 

--linas

^ permalink raw reply

* [PATCH] Fix Tsi108 ethernet driver performance
From: Alexandre Bounine @ 2007-07-16 17:36 UTC (permalink / raw)
  To: jgarzik, netdev; +Cc: linuxppc-dev

From: Alexandre Bounine <alexandreb@tundra.com>

This patch improves performance of the Tsi108 Ethernet driver by
changing interrupt handling for frame receive path. It reduces number of
interrupts generated for received frames and therefore lowers CPU
utilization by the device driver.
=20=20=20
Signed-off-by: Alexandre Bounine <alexandreb@tundra.com>

---

diff -Nurp linux-2.6.22-hpc2/drivers/net/tsi108_eth.c
linux-2.6.22-tun/drivers/net/tsi108_eth.c
--- linux-2.6.22-hpc2/drivers/net/tsi108_eth.c	2007-07-08
19:32:17.000000000 -0400
+++ linux-2.6.22-tun/drivers/net/tsi108_eth.c	2007-07-12
16:55:50.000000000 -0400
@@ -58,6 +58,7 @@
 #define MII_READ_DELAY 10000	/* max link wait time in msec */
=20
 #define TSI108_RXRING_LEN     256
+#define TSI108_RX_INT_FREQ    32
=20
 /* NOTE: The driver currently does not support receiving packets
  * larger than the buffer size, so don't decrease this (unless you
@@ -69,8 +70,10 @@
=20
 #define TSI108_TX_INT_FREQ    64
=20
-/* Check the phy status every half a second. */
-#define CHECK_PHY_INTERVAL (HZ/2)
+/* Timer interval to check the RX queue status */
+#define CHECK_RX_INTERVAL	(HZ/50)
+/* Timer interval to check the PHY status */
+#define CHECK_PHY_INTERVAL	(CHECK_RX_INTERVAL * 10)
=20
 static int tsi108_init_one(struct platform_device *pdev);
 static int tsi108_ether_remove(struct platform_device *pdev);
@@ -104,6 +107,7 @@ struct tsi108_prv_data {
 	unsigned int txfree;
=20
 	unsigned int phy_ok;		/* The PHY is currently powered
on. */
+	unsigned int phy_chk_count;
=20
 	/* PHY status (duplex is 1 for half, 2 for full,
 	 * so that the default 0 indicates that neither has
@@ -823,7 +827,10 @@ static int tsi108_refill_rx(struct net_d
 		 */
=20
 		data->rxring[rx].blen =3D TSI108_RX_SKB_SIZE;
-		data->rxring[rx].misc =3D TSI108_RX_OWN | TSI108_RX_INT;
+		if (rx % TSI108_RX_INT_FREQ)
+			data->rxring[rx].misc =3D TSI108_RX_OWN;
+		else
+			data->rxring[rx].misc =3D TSI108_RX_OWN |
TSI108_RX_INT;
=20
 		data->rxhead =3D (data->rxhead + 1) % TSI108_RXRING_LEN;
 		data->rxfree++;
@@ -973,24 +980,22 @@ static void tsi108_rx_int(struct net_dev
 	}
 }
=20
-/* If the RX ring has run out of memory, try periodically
- * to allocate some more, as otherwise poll would never
- * get called (apart from the initial end-of-queue condition).
- *
- * This is called once per second (by default) from the thread.
+/* tsi108_check_rxring() is used to periodically check if the RX ring
has
+ * pending frames that have not been reported by RX interrupt (due to
interrupt
+ * moderation). It is called with CHECK_RX_INTERVAL timer interval.
  */
=20
 static void tsi108_check_rxring(struct net_device *dev)
 {
 	struct tsi108_prv_data *data =3D netdev_priv(dev);
+	unsigned int rx =3D data->rxtail;
=20
-	/* A poll is scheduled, as opposed to caling tsi108_refill_rx
-	 * directly, so as to keep the receive path single-threaded
-	 * (and thus not needing a lock).
-	 */
-
-	if (netif_running(dev) && data->rxfree < TSI108_RXRING_LEN / 4)
+	/* Schedule a poll (if required) */
+	if (netif_running(dev) &&
+	    0 =3D=3D (data->rxring[rx].misc & TSI108_RX_OWN)) {
+		data->rxpending =3D 1;
 		tsi108_rx_int(dev);
+	}
 }
=20
 static void tsi108_tx_int(struct net_device *dev)
@@ -1295,6 +1300,7 @@ static void tsi108_init_phy(struct net_d
=20
 	printk(KERN_DEBUG "PHY_STAT reg contains %08x\n", phyval);
 	data->phy_ok =3D 1;
+	data->phy_chk_count =3D 0;
 	data->init_media =3D 1;
 	spin_unlock_irqrestore(&phy_lock, flags);
 }
@@ -1664,9 +1670,12 @@ static void tsi108_timed_checker(unsigne
 	struct net_device *dev =3D (struct net_device *)dev_ptr;
 	struct tsi108_prv_data *data =3D netdev_priv(dev);
=20
-	tsi108_check_phy(dev);
+	/* We assume that RX queue is checked more often than PHY status
*/
+	if (data->phy_chk_count++ =3D=3D 0)
+		tsi108_check_phy(dev);
 	tsi108_check_rxring(dev);
-	mod_timer(&data->timer, jiffies + CHECK_PHY_INTERVAL);
+	data->phy_chk_count %=3D (CHECK_PHY_INTERVAL/CHECK_RX_INTERVAL);
+	mod_timer(&data->timer, jiffies + CHECK_RX_INTERVAL);
 }
=20
 static int tsi108_ether_init(void)



---=0D
=0D
Important Notice: This message is intended for the use of the individual to=
 whom it is addressed and may contain information which is privileged, conf=
idential and/or exempt from disclosure under applicable law. If the reader =
of this message is not the intended recipient, or is not the employee or ag=
ent responsible for delivering the message to the intended recipient, you a=
re hereby notified that any dissemination, distribution, or copying of this=
 communication is strictly prohibited. If you have received this communicat=
ion in error, please notify the sender immediately by telephone or return e=
-mail and delete the original message from your systems. Thank you. =0D

^ permalink raw reply

* Re: [PATCH 10/10] IB/ehca: Support large page MRs
From: Roland Dreier @ 2007-07-16 17:37 UTC (permalink / raw)
  To: Joachim Fenkes
  Cc: LKML, LinuxPPC-Dev, Christoph Raisch, OF-General, Stefan Roscher
In-Reply-To: <200707121754.20293.fenkes@de.ibm.com>

 > Add support for MR pages larger than 4K on eHCA2. This reduces firmware
 > memory consumption. If enabled via the mr_largepage module parameter, the MR
 > page size will be determined based on the MR length and the hardware
 > capabilities - if the MR is >= 16M, 16M pages are used, for example.

Why the module parameter?  Is there any reason a user would want to
turn this off?  Or conversely, why is it off by default?

Also this patch seems to depend heavily on the multiple EQ patch,
which I am holding off on now.  So you may want to rebase to my
current tree, which has all the ehca patches except the EQ one.

 >  static ssize_t ehca_show_nr_eqs(struct device *dev,
 >  				struct device_attribute *attr,
 >  				char *buf)
 >  {
 >  	return sprintf(buf, "%d\n", ehca_nr_eqs);
 >  }
 > -
 >  static DEVICE_ATTR(nr_eqs, S_IRUGO, ehca_show_nr_eqs, NULL);

Although trivial, this chunk doesn't really belong in this patch --
just fix it up in the multiple EQ patch (which I haven't merged yet).

 - R.

^ permalink raw reply

* RE: XSysAce driver cant mount DOS part
From: Robertson, Joseph M. @ 2007-07-16 17:51 UTC (permalink / raw)
  To: urwithsudheer; +Cc: linuxppc-embedded
In-Reply-To: <939D37AEB47F1F49B88FAB6599B6023501A17215@hsv1dafpew02.das.gov.sanm.corp>

[-- Attachment #1: Type: text/plain, Size: 11701 bytes --]

I am sorry, I found a mistake on my part.

I fixed the code 'exactly' as you stated and I believe it is now working.
You are now in my credits page!

Extensive testing will now occur.

Thank you very much.


Joe Robertson
x8259
Joseph.Robertson@sanmina-sci.com



-----Original Message-----
From: linuxppc-embedded-bounces+joseph.robertson=sanmina-sci.com@ozlabs.org on behalf of Robertson, Joseph M.
Sent: Mon 7/16/2007 11:19 AM
To: urwithsudheer
Cc: linuxppc-embedded@ozlabs.org
Subject: RE: XSysAce driver cant mount DOS part
 
Hi,

Thanks for your insight into the older code. 
I tried your fix and came up with this.
I have run e2fsck and the cf card comes up clean with that.

heres a boot sequence:

Initializing Cryptographic API
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing disabled
serial8250.0: ttyS0 at MMIO 0x40421003 (irq = 4) is a 16550A
serial8250.0: ttyS1 at MMIO 0x40401003 (irq = 5) is a 16550A
RAMDISK driver initialized: 16 RAM disks of 65536K size 1024 blocksize
XSysAce driver  v0771.
IDENTIFY: heads: 16, nsec: 63, cyls: 1011, size= 1019088
REGISTERED: major no.= 125 capacity= 1019088
 xsa: xsa1 xsa2 xsa3
Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
mice: PS/2 mouse device common for all mice
TCP bic registered
NET: Registered protocol family 1
VFS: Mounted root (ext2 filesystem) readonly.
Freeing unused kernel memory: 100k init
EXT2-fs error (device xsa2): ext2_check_page: bad entry in directory #32689: unaligned directory entry - offset=1024, inode=1713398885, rec_len=29295, name_len=109
Warning: unable to open an initial console.
init has generated signal 11 but has no handler for it
Kernel panic - not syncing: Attempted to kill init!


The only thing I notice is that the disk capacity is wrong, its a 512Mb, not a 1Gb as shown.

Any thoughts about what to look into next?

Thanks a lot.


Joe Robertson
Joseph.Robertson@sanmina-sci.com



-----Original Message-----
From: urwithsudheer [mailto:urwithsudheer@gmail.com]
Sent: Mon 7/16/2007 12:08 AM
To: Robertson, Joseph M.
Cc: linuxppc-embedded@ozlabs.org
Subject: Re: XSysAce driver cant mount DOS part
 
Hi Joe Robertson,

Thanks for the link.

In the xsa_thread function, can u try changing the hardcoded coded value 
"2" to "xsa_cur_req->current_nr_sectors " 


The actual code in the given link.

for(i = xsa_cur_req->current_nr_sectors; i > 0; i-=2){
+			xsa_device.req_done = 1;
+			while ((stat = cur_req(&SysAce, sector,
+					2,
+					buffer)) == XST_DEVICE_BUSY)
+				xsa_short_delay();


Try changing it to ...

for(i = xsa_cur_req->current_nr_sectors; i > 0; 
i-=xsa_cur_req->current_nr_sectors ){ xsa_device.req_done = 1;
while ((stat = cur_req(&SysAce, sector,
                                     xsa_cur_req->current_nr_sectors ,
                                    buffer)) == XST_DEVICE_BUSY)
                xsa_short_delay();



Due to the hardcoded value, it gave problem while mounting but no issue 
with fdisk. It mounts well but generated a kernel BUG. Tried changing 
the value to '1' from '2' , fdisk crashed but mount is working well. So 
removed the hardcode value and then placed the dynamic variable 
xsa_cur_req->current_nr_sectors which is chosen by kernel. And now fdisk 
and mount both are working fine.


Pl let me know the results in your setup.

Thanks
Sudheer


Robertson, Joseph M. wrote:
>
> Hi,
>
> Yes, I got it from here.
> http://www.cs.york.ac.uk/rtslab/demos/amos/xupv2pro/patches/linuxppc-2.6.17.1-sysace-1.2.patch
>
> The 'official' one, yes?
>
> Thanks,
>
> Joe Robertson
> Joseph.Robertson@sanmina-sci.com
>
>
>
> -----Original Message-----
> From: urwithsudheer [mailto:urwithsudheer@gmail.com]
> Sent: Fri 7/13/2007 4:25 AM
> To: Robertson, Joseph M.
> Cc: linuxppc-embedded@ozlabs.org
> Subject: Re: XSysAce driver cant mount DOS part
>
> Hi
>
> Robertson, Joseph M. wrote:
> >
> > Hi all,
> >
> > I've been workig with this for a while but have made no progress.
> > Today I got the latest XSysAce patch for kernel 2.6.17.1 and applied
> > it to get clean code.
> > I inherited the previous code from another developer.
> >
> Can you send the link to xsysace driver source code from where you 
> obtained.
>
>
> Thanks
> Sudheer
>
>
> >
> > My problem is that mounting the DOS partition always fails in a short
> > time with a kernel oops.
> >
> > ECAU-9999:# Oops: kernel access of bad area, sig: 11
> > [#1]                     
> > 
> PREEMPT                                                                       
> > NIP: C00701C8 LR: C0070C18 CTR:
> > 00000000                                      
> > REGS: c0391dd0 TRAP: 0300   Not tainted 
> > (2.6.17.1)                           
> > MSR: 00021030 <ME,IR,DR>  CR: 22028082  XER:
> > 0000000B                         
> > DAR: 00000000, DSISR:
> > 00800000                                                
> > TASK = c0373030[4] 'events/0' THREAD:
> > c0390000                                
> > GPR00: 00000080 C0391E80 C0373030 C02CAC00 C0E03000 C0E03154 00000000
> > C02CAC00
> > GPR08: 00200200 00000000 00100100 00000000 00051A4B FFFFDE60 03BD4900
> > 007FFF3B
> > GPR16: 00400000 00000001 FFFFFFFF 03BCDC58 00000000 007FFF00 00000002
> > C0280000
> > GPR24: C0363A10 0000000B 00000000 00000000 00000000 C02CAC00 C035ED20
> > C0E03000
> > NIP [C00701C8]
> > free_block+0x8c/0x138                                          
> > LR [C0070C18]
> > drain_array+0xb8/0x124                                          
> > Call Trace:                                 
> >
> > The setup:
> > My own build system.
> > Kernel 2.6.17.1 with lots of xilinx stuff, eth, i2c, xsysace. 
> > Crosscompiled for PPC405.
> > Latest, clean XSysAce code.  mods:  major hardcoded to = 125.  Polled
> > mode.
> > CF:  3 partitions,
> > 1:  DOS FAT16
> > 2:  Ext2  main
> > 3:  Ext2  rescue
> >
> > This build boots up fine, mounts a ext2 as root fine.  I can also
> > mount the rescue partition with no problems.
> >
> > Does anyone have any pointers of where I should look for problems?
> >
> > My next step is to go and set it up for interrupt service and see if
> > that changes anything.
> >
> > Thanks,
> >
> > Joe Robertson
> > Joseph.Robertson@sanmina-sci.com
> >
> >
> > CONFIDENTIALITY
> > This e-mail message and any attachments thereto, is intended only for
> > use by the addressee(s) named herein and may contain legally
> > privileged and/or confidential information. If you are not the
> > intended recipient of this e-mail message, you are hereby notified
> > that any dissemination, distribution or copying of this e-mail
> > message, and any attachments thereto, is strictly prohibited. If you
> > have received this e-mail message in error, please immediately notify
> > the sender and permanently delete the original and any copies of this
> > email and any prints thereof.
> > ABSENT AN EXPRESS STATEMENT TO THE CONTRARY HEREINABOVE, THIS E-MAIL
> > IS NOT INTENDED AS A SUBSTITUTE FOR A WRITING. Notwithstanding the
> > Uniform Electronic Transactions Act or the applicability of any other
> > law of similar substance and effect, absent an express statement to
> > the contrary hereinabove, this e-mail message its contents, and any
> > attachments hereto are not intended to represent an offer or
> > acceptance to enter into a contract and are not otherwise intended to
> > bind the sender, Sanmina-SCI Corporation (or any of its subsidiaries),
> > or any other person or entity.
> > ------------------------------------------------------------------------
> >
> > _______________________________________________
> > Linuxppc-embedded mailing list
> > Linuxppc-embedded@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-embedded
>
>
>
> CONFIDENTIALITY
> This e-mail message and any attachments thereto, is intended only for 
> use by the addressee(s) named herein and may contain legally 
> privileged and/or confidential information. If you are not the 
> intended recipient of this e-mail message, you are hereby notified 
> that any dissemination, distribution or copying of this e-mail 
> message, and any attachments thereto, is strictly prohibited. If you 
> have received this e-mail message in error, please immediately notify 
> the sender and permanently delete the original and any copies of this 
> email and any prints thereof.
> ABSENT AN EXPRESS STATEMENT TO THE CONTRARY HEREINABOVE, THIS E-MAIL 
> IS NOT INTENDED AS A SUBSTITUTE FOR A WRITING. Notwithstanding the 
> Uniform Electronic Transactions Act or the applicability of any other 
> law of similar substance and effect, absent an express statement to 
> the contrary hereinabove, this e-mail message its contents, and any 
> attachments hereto are not intended to represent an offer or 
> acceptance to enter into a contract and are not otherwise intended to 
> bind the sender, Sanmina-SCI Corporation (or any of its subsidiaries), 
> or any other person or entity.



CONFIDENTIALITY
This e-mail message and any attachments thereto, is intended only for use by the addressee(s) named herein and may contain legally privileged and/or confidential information. If you are not the intended recipient of this e-mail message, you are hereby notified that any dissemination, distribution or copying of this e-mail message, and any attachments thereto, is strictly prohibited.  If you have received this e-mail message in error, please immediately notify the sender and permanently delete the original and any copies of this email and any prints thereof.
ABSENT AN EXPRESS STATEMENT TO THE CONTRARY HEREINABOVE, THIS E-MAIL IS NOT INTENDED AS A SUBSTITUTE FOR A WRITING.  Notwithstanding the Uniform Electronic Transactions Act or the applicability of any other law of similar substance and effect, absent an express statement to the contrary hereinabove, this e-mail message its contents, and any attachments hereto are not intended to represent an offer or acceptance to enter into a contract and are not otherwise intended to bind the sender, Sanmina-SCI Corporation (or any of its subsidiaries), or any other person or entity.



CONFIDENTIALITY
This e-mail message and any attachments thereto, is intended only for use by the addressee(s) named herein and may contain legally privileged and/or confidential information. If you are not the intended recipient of this e-mail message, you are hereby notified that any dissemination, distribution or copying of this e-mail message, and any attachments thereto, is strictly prohibited.  If you have received this e-mail message in error, please immediately notify the sender and permanently delete the original and any copies of this email and any prints thereof.
ABSENT AN EXPRESS STATEMENT TO THE CONTRARY HEREINABOVE, THIS E-MAIL IS NOT INTENDED AS A SUBSTITUTE FOR A WRITING.  Notwithstanding the Uniform Electronic Transactions Act or the applicability of any other law of similar substance and effect, absent an express statement to the contrary hereinabove, this e-mail message its contents, and any attachments hereto are not intended to represent an offer or acceptance to enter into a contract and are not otherwise intended to bind the sender, Sanmina-SCI Corporation (or any of its subsidiaries), or any other person or entity.

[-- Attachment #2: Type: text/html, Size: 17355 bytes --]

^ permalink raw reply

* [PATCH 0/3] 82xx: Add the support for Wind River SBC PowerQUICCII
From: Mark Zhan @ 2007-07-16  9:01 UTC (permalink / raw)
  To: paulus, linuxppc-dev

These 3 patches add the powerpc support of Wind River SBC PowerQUICCII.

1) Currently, some mpc82xx platform hooks in mpc82xx_ads.c are actually not specific to ads board. So the 1st patch 
makes them be shared by different 82xx boards.

2) The 2nd patch make 'cpm_uart_of_init' be able to parse SMC uart in DTS

3) The 3rd patch is the platform codes, defconfig and dts for Wind River SBC PowerQUICCII 82xx board.

Any comment is welcome.

Thanks
Mark Zhan

^ permalink raw reply

* Re: [PATCH] Update mpc7448hpc2 device tree to be compatible for tsi109 chip
From: Segher Boessenkool @ 2007-07-16 18:51 UTC (permalink / raw)
  To: Zang Roy-r61911; +Cc: linuxppc-dev list, Paul Mackerras
In-Reply-To: <1184299081.30789.9.camel@localhost.localdomain>

> Update mpc7448hpc2 device tree to be compatible for tsi109 chip.
>
> Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>

Looks good, thanks!


Segher

^ permalink raw reply

* Re: boottime kernel relocation, what I missed?
From: Becky Bruce @ 2007-07-16 19:10 UTC (permalink / raw)
  To: meerkat; +Cc: linuxppc-embedded
In-Reply-To: <11588451.post@talk.nabble.com>


On Jul 13, 2007, at 5:07 PM, meerkat wrote:

>
> Figure that out, the bootstrap actually mapped the first 16M from  
> C000000 to
> the physicall address,
> so calling a c routine, as long as it is in the first 16M, is OK
>

I think you're still not understanding the fact that "bl" is a  
*relative* branch - the branch target in the instruction encoding is  
just an offset from the current address, not an effective address.   
The bl should work correctly whether the code is actually running at  
the link address reported by nm (0xcxxxxxxx in this case), or if it  
has been loaded and executed elsewhere.

Refer to the 32-bit Programming Environments Manual for PowerPC, or  
in the EREF (if you're using a BookE part - e500/e200) for more  
details.  If you're just learning PowerPC assembler, you should  
really give this book a good thourough read.

>
> meerkat wrote:
>>
>> Good day all,
>>
>> For the first time I begin working on PPC, and on low level, and  
>> right
>> start from boot sequence, one issue puzzled me.
>>
>> After bootstrap code (zImage) uncompressed the kernel vmLinux to  
>> physical
>> memory (say from addr 0),
>> it jumps to the kernel entry point, _start, using physically address.

If you read the book specified above, you will see that branch  
instructions always specify an effective address, not a physical  
address.  You can disable translation or map the address so EA=PA,  
but that's a different issue.

-Becky

^ permalink raw reply

* Help needed interpreting weird kOops
From: Simon Vallet @ 2007-07-16 18:56 UTC (permalink / raw)
  To: linuxppc-dev

Hi,

still working on mapping a Mach-O driver to ELF, I'm seeing a weird
kOops when insmod'ing the driver :

Jul 16 20:16:07 tertius kernel: Oops: Unrecoverable FP Unavailable Exception, sig: 6 [#1]
Jul 16 20:16:07 tertius kernel: PREEMPT 
Jul 16 20:16:07 tertius kernel: Modules linked in: unicorn_pci_atm(P)
Jul 16 20:16:07 tertius kernel: NIP: F661CD6C LR: F661CD5C CTR: 000000D0
Jul 16 20:16:07 tertius kernel: REGS: ee86db70 TRAP: 0801   Tainted: P       (2.6.20-rc3-sjv1-gc6b33cc4-dirty)
Jul 16 20:16:07 tertius kernel: MSR: 00009032 <EE,ME,IR,DR>  CR: 24004288  XER: 00000000
Jul 16 20:16:07 tertius kernel: TASK = effcd790[1397] 'insmod' THREAD: ee86c000
Jul 16 20:16:07 tertius kernel: GPR00: F661CD5C EE86DC20 EFFCD790 00000008 F66885B0 00000104 EE9D3D60 EE9D269C 
Jul 16 20:16:07 tertius kernel: GPR08: EE9D23B4 F6684B38 000000D0 EE86C000 F664D9CC 
Jul 16 20:16:07 tertius kernel: NIP [F661CD6C] _ZN19InterruptDispatcher5resetEv+0x3c/0xb4 [unicorn_pci_atm]
Jul 16 20:16:07 tertius kernel: LR [F661CD5C] _ZN19InterruptDispatcher5resetEv+0x2c/0xb4 [unicorn_pci_atm]
Jul 16 20:16:07 tertius kernel: Call Trace:
Jul 16 20:16:07 tertius kernel: [EE86DC20] [F661CD5C] _ZN19InterruptDispatcher5resetEv+0x2c/0xb4 [unicorn_pci_atm] (unreliable)
Jul 16 20:16:07 tertius kernel: [EE86DC70] [10019678] 0x10019678
Jul 16 20:16:07 tertius kernel: [EE86DCC0] [F66C0000] fineGainConversionTable.728+0x664/0xfffc2294 [unicorn_pci_atm]
Jul 16 20:16:07 tertius kernel: [EE86DD30] [F6623444] _ZN17ModemSubsystemItfC1EmPtm+0x44/0xd8 [unicorn_pci_atm]
Jul 16 20:16:07 tertius kernel: [EE86DD90] [F65EEDA8] AMSW_Modem_SW_Init+0x110/0x1f8 [unicorn_pci_atm]
Jul 16 20:16:07 tertius kernel: [EE86DE00] [C002B16C] printk+0x50/0x60
Jul 16 20:16:07 tertius kernel: [EE86DE40] [F105252C] unicorn_pci_init+0x52c/0xb08 [unicorn_pci_atm]
Jul 16 20:16:07 tertius kernel: [EE86DE90] [C004E340] sys_init_module+0x16c/0x1610
Jul 16 20:16:07 tertius kernel: [EE86DF40] [C00112B0] ret_from_syscall+0x0/0x38
Jul 16 20:16:07 tertius kernel: --- Exception: c01 at 0xff6cfc8
Jul 16 20:16:07 tertius kernel:     LR = 0x10000e54
Jul 16 20:16:07 tertius kernel: Instruction dump:
Jul 16 20:16:07 tertius kernel: 9421ffb0 7c7f1b78 3c60f669 38630948 48000089 7fe3fb78 48000071 4800005d 
Jul 16 20:16:07 tertius kernel: 394000d0 3d20f668 7d4903a6 39294b38 <c8090000> 39600000 38000004 917f0008

Having learned more PPC assembly than I probably wished, I checked
 the code until _ZN17ModemSubsystemItfC1EmPtm+0x44, which disassembles 
to this (arg addresses are relative to the beginning of .text/0xf65c4000):

0xf6623440: 48 00 00 89     bl      0x5f4c8    [ branch island, un-optimized from JBSR ]
0xf6623444: 80 61 00 38     l       r3,56(r1)
[...]

[ this is the branch island ]
0xf66234c8: 3d 80 f6 64     liu     r12,0xf664
0xf66234cc: 61 8c e1 54     oril    r12,r12,0xe154
0xf66234d0: 7d 89 03 a6     mtctr   r12

mtctr branches to a memory-allocation function which does seem to behave
correctly (it is called multiple times before that). But somehow from
this point everything seems corrupted: the stack trace seems to show a 
jump into the .data section (fineGainConversionTable), which could be explained
by a bad relocation, but I didn't see any obvious problems on this side.

So I have to assume that the stack is somehow corrupted, but I can't explain
how this happens, at least in this portion of code. Any hint ?


Simon

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox