LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 1/2]: powerpc/cell spidernet bottom half
From: David Miller @ 2006-08-16 22:29 UTC (permalink / raw)
  To: arnd
  Cc: akpm, jeff, netdev, jklewis, linux-kernel, linuxppc-dev,
	Jens.Osterkamp
In-Reply-To: <200608170016.47072.arnd@arndb.de>

From: Arnd Bergmann <arnd@arndb.de>
Date: Thu, 17 Aug 2006 00:16:46 +0200

> Am Wednesday 16 August 2006 23:32 schrieb David Miller:
> > Can spidernet be told these kinds of parameters? =A0"N packets or
> > X usecs"?
> =

> It can not do exactly this but probably we can get close to it by

Oh, you can only control TX packet counts using bits in the TX ring
entries :(

Tigon3 can even be told to use different interrupt mitigation
parameters when the cpu is actively servicing an interrupt for
the chip.

Didn't you say spidernet's facilities were sophisticated? :)
This Tigon3 stuff is like 5+ year old technology.

^ permalink raw reply

* Re: [PATCH 1/2]: powerpc/cell spidernet bottom half
From: Arnd Bergmann @ 2006-08-16 22:16 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: akpm, jeff, netdev, jklewis, linux-kernel, Jens.Osterkamp,
	David Miller
In-Reply-To: <20060816.143203.11626235.davem@davemloft.net>

Am Wednesday 16 August 2006 23:32 schrieb David Miller:
> Can spidernet be told these kinds of parameters? =A0"N packets or
> X usecs"?

It can not do exactly this but probably we can get close to it by

1.) Setting a one-time interrupt to fire x*10=B5s after putting a
   packet into the TX queue.

and

2.a) Enabling end of TX queue interrupts whenever more than y frames
     have been queued for TX.

or

2.b) Marking frame number y in the TX to fire an interrupt when it
     has been transmitted, and move the mark whenever we clean up
     TX descriptors.

or

2.c) Marking frame number y to generate an interrupt, but counting
     y from the end of the queue, and update the mark whenever we
     add frames to the queue tail.

I'm not sure which version of 2. would give us the best approximation.

	Arnd <><

^ permalink raw reply

* Re: Linux hanging on Xilinx SystemACE
From: Jeff Angielski @ 2006-08-16 22:07 UTC (permalink / raw)
  To: Clint Thomas; +Cc: linuxppc-embedded
In-Reply-To: <3C02138692C13C4BB675FE7EA240952918DBED@bluefin.Soneticom.local>

On Wed, 2006-08-16 at 17:06 -0400, Clint Thomas wrote:

> Using the powerpc development tree of Linux 2.4, I am trying to boot
> my system from CompactFlash using Xilinx SystemACE. My compact flash
> card has two partitions, a 16MB FAT16 that holds the combination FPGA
> image / Linux Kernel ELF file, and an Ext2 partition that holds the
> root file system. The system starts the boot process, uncompresses the
> Linux kernel and begins loading drivers. Part way into this process,
> it conducts a partition check of the drive being reported to it by
> SystemACE, however, it hangs at that point. No kernel panic, no error
> message, it simply hangs. Here is the output at that point...
> 
> Partition check:
>  xsysacea:
>  
> what I am trying to find out is if this problem has been seen/fixed in
> the past? or did I format the CF card incorrectly?

Can u-boot see the partition formatted with ext2? 

Can you mount an NFS root filesystem and access the card normally?  Or
is it just when you use it as your rootfs?

How did you create you partitions and format the CF card?

And like somebody else mentioned, if you are really going to use this
for an embedded system, you are going to want to rethink your
partitioning scheme.

Maybe something like:

p1 fat12 - kernel and binary image
p2 ext2 - read only rootfs
p3 ext3 - non volatile, slow rate data rootfs
p4 tmpfs - volatile, high rate data rootfs


Jeff Angielski
The PTR Group

^ permalink raw reply

* Re: Linux hanging on Xilinx SystemACE
From: Keith J Outwater @ 2006-08-16 22:01 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <3C02138692C13C4BB675FE7EA240952918DBED@bluefin.Soneticom.local>

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

Clint,

> Using the powerpc development tree of Linux 2.4, I am trying to boot my 
system from CompactFlash using Xilinx SystemACE. My compact flash card has 
two partitions, a 16MB FAT16 that holds the combination FPGA image / Linux 
Kernel ELF file, and an Ext2 partition that holds the root file system. 
The system starts the boot process, uncompresses the Linux kernel and 
begins loading drivers. Part way into this process, it conducts a 
partition check of the drive being reported to it by SystemACE, however, 
it hangs at that point. No kernel panic, no error message, it simply 
hangs. Here is the output at that point...
> 
> Partition check:
>  xsysacea:
> 
> what I am trying to find out is if this problem has been seen/fixed in 
the past? or did I format the CF card incorrectly?
> 

I have a system that uses the SystemAce in a similar way.  I was also 
having lockups.  After a lot of digging, I found a patch by John Masters 
(e-mail unknown) to the MontaVista SystemAce driver in the 2.4 kernel that 
disables the use of interrupts and runs the SystemAce in a polled mode. 
Performance is not that great, but at least it does not crash with the 
patch.  As I recall, the reason that the unpatched driver crashed is that 
the SystemAce is issuing more than one interrupt upon completion of a 
sector read or write.  Apparently, the Xilinx ML300 board works fine 
without this patch while other eval boards like the Memec DS-BD-2VPxx 
crash without the patch.

This still may not be your problem, but the patch may help later on.

I've attached the patched file.  The file is from 
./drivers/block/xilinx_sysace/adapter.c in the 2.4.30 from MontaVista.

Keith

[-- Attachment #2: adapter.c --]
[-- Type: application/octet-stream, Size: 25817 bytes --]

/*
 * adapter.c
 *
 * Xilinx System ACE Adapter component to interface System ACE to Linux
 *
 * Author: MontaVista Software, Inc.
 *         source@mvista.com
 *
 * History:
 * 22/09/2004 - Added xsa_use_interrupts.
 * Jon Masters <jcm@xxxxxxxxxxxxxx>.
 *
 * 2002 (c) MontaVista, Software, Inc.  This file is licensed under the terms
 * of the GNU General Public License version 2.  This program is licensed
 * "as is" without any warranty of any kind, whether express or implied.
 */

/*
 * Through System ACE, the processor can access the CompactFlash and the
 * JTAG chain.  In addition, the System ACE controls system reset and
 * which configuration will be loaded into the JTAG chain at that time.
 * This driver provides two different interfaces.  The first is handling
 * reset by tying into the system's reset code as well as providing a
 * /proc interface to read and write which configuration should be used
 * when the system is reset.  The second is to expose a block interface
 * to the CompactFlash.
 * 
 * This driver is a bit unusual in that it is composed of two logical
 * parts where one part is the OS independent code and the other part is
 * the OS dependent code.  Xilinx provides their drivers split in this
 * fashion.  This file represents the Linux OS dependent part known as
 * the Linux adapter.  The other files in this directory are the OS
 * independent files as provided by Xilinx with no changes made to them.
 * The names exported by those files begin with XSysAce_.  All functions
 * in this file that are called by Linux have names that begin with
 * xsysace_.  Any other functions are static helper functions.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/hdreg.h>
#include <linux/slab.h>
#include <linux/blkpg.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/uaccess.h>

#define NR_HD		1	/* System ACE only handles one CompactFlash */
#define PARTN_BITS	4	/* Only allow 15 partitions. */

/* Dynamically allocate a major number. */
static int xsa_major = 0;

#define MAJOR_NR	(xsa_major)
#define MAJOR_NAME	"xsysace"

#define DEVICE_NAME	"System ACE"
#define DEVICE_REQUEST	xsysace_do_request
#define DEVICE_NR(device) (MINOR(device) >> PARTN_BITS)

#include <linux/blk.h>
#include <linux/blkdev.h>
#include <xbasic_types.h>
#include "xsysace.h"

#undef  DEBUG
#ifdef  DEBUG
# define debugk(fmt,args...)    printk(fmt ,##args)
# define DEBUG_OPTARG(arg)  arg,
#else
# define debugk(fmt,args...)
# define DEBUG_OPTARG(arg)
#endif

/*
 * We have to disable interrupts on certain boards where writing causes an
 * additional unexpected hardware interrupt on sector write completion.
 */
static int xsa_use_interrupts = 0;

MODULE_AUTHOR("MontaVista Software, Inc. <source@mvista.com>");
MODULE_DESCRIPTION("Xilinx System ACE block driver");
MODULE_LICENSE("GPL");
MODULE_PARM(xsa_enable_interrupts, "i");

/*
 * We have to wait for a lock and for the CompactFlash to not be busy
 * via polling.  If dont_spin is non-zero, we will use schedule_timeout
 * in a loop to check for these conditions.  If dont_spin is zero, we
 * will tight loop without a schedule_timeout as long as need_resched is
 * false.  If need_resched is true, we'll fall back to using
 * schedule_timeout.  This could obviously be made run-time settable.
 */
static const int dont_spin = 0;

static u32 save_BaseAddress;	/* Saved physical base address */
#ifdef CONFIG_VIRTEX_II_PRO
static void (*old_restart)(char *cmd);	/* old ppc_md.restart */
#endif

static unsigned char heads;
static unsigned char sectors;
static unsigned short cylinders;

static int access_count = 0;
static char revalidating = 0;
static DECLARE_WAIT_QUEUE_HEAD(revalidate_wait);

/*
 * The following variables are used to keep track of what all has been
 * done to make error handling easier.
 */
static char reqirq = 0;		/* Has request_irq() been called? */
static char registered = 0;	/* Has devfs_register_blkdev() been called? */

/*
 * The underlying OS independent code needs space as well.  A pointer to
 * the following XSysAce structure will be passed to any XSysAce_
 * function that requires it.  However, we treat the data as an opaque
 * object in this file (meaning that we never reference any of the
 * fields inside of the structure).
 */
static XSysAce SysAce;

/* These tables are indexed by major and minor numbers. */
static int xsa_sizes[NR_HD << PARTN_BITS];	/* Size of the device, kb */
static int xsa_blocksizes[NR_HD << PARTN_BITS];	/* Block size, bytes */
static int xsa_hardsectsizes[NR_HD << PARTN_BITS];	/* Sector size, bytes */
static int xsa_maxsect[NR_HD << PARTN_BITS];	/* Max request size, sectors */
static struct hd_struct xsa_hd[NR_HD << PARTN_BITS];	/* Partition Table */

/*
 * In general, requests enter this driver through xsysace_do_request()
 * which then schedules the xsa_thread.  The xsa_thread sends the
 * request down to the Xilinx OS independent layer.  When the request
 * completes, EventHandler() will get called as a result of an
 * interrupt.  The following variables support this flow.
 */
static struct task_struct *xsa_task = NULL;	/* xsa_thread pointer */
static struct completion task_sync;	/* xsa_thread start/stop syncing */
static char task_shutdown = 0;	/* Set to non-zero when task should quit.  */

/*
 * req_fnc will be either NULL or a pointer to XSysAce_SectorRead or
 * XSysAce_SectorWrite.  It will be set to point to one of the XSysAce*
 * functions by xsysace_do_request and then xsa_thread will be scheduled.
 * The xsa_thread will then NULL req_fnc after it has copied the pointer.
 */
static XStatus(*req_fnc) (XSysAce * InstancePtr, u32 StartSector,
			  int NumSectors, u8 * BufferPtr);
/* xsa_thread waits on req_wait until xsysace_do_request does wake_up on it */
static DECLARE_WAIT_QUEUE_HEAD(req_wait);
/* req_active is a simple flag that says a request is being serviced. */
static char req_active = 0;
/* req_str will be used for errors and will be either "reading" or "writing" */
static char *req_str;


/* SAATODO: Xilinx is going to add this function.  Nuke when they do. */
unsigned int
XSysAce_GetCfgAddr(XSysAce * InstancePtr)
{
	u32 Status;

	XASSERT_NONVOID(InstancePtr != NULL);
	XASSERT_NONVOID(InstancePtr->IsReady == XCOMPONENT_IS_READY);

	Status = XSysAce_mGetControlReg(InstancePtr->BaseAddress);
	if (!(Status & XSA_CR_FORCECFGADDR_MASK))
		Status = XSysAce_mGetStatusReg(InstancePtr->BaseAddress);

	return (unsigned int) ((Status & XSA_SR_CFGADDR_MASK) >>
			       XSA_CR_CFGADDR_SHIFT);
}

/* SAATODO: Nuke the following line when Config stuff moved out. */
extern XSysAce_Config XSysAce_ConfigTable[];
/* SAATODO: This function will be moved into the Xilinx code. */
/*****************************************************************************/
/**
*
* Lookup the device configuration based on the sysace instance.  The table
* XSysAce_ConfigTable contains the configuration info for each device in the system.
*
* @param Instance is the index of the interface being looked up.
*
* @return
*
* A pointer to the configuration table entry corresponding to the given
* device ID, or NULL if no match is found.
*
* @note
*
* None.
*
******************************************************************************/
XSysAce_Config *
XSysAce_GetConfig(int Instance)
{
	if (Instance < 0 || Instance >= XPAR_XSYSACE_NUM_INSTANCES) {
		return NULL;
	}

	return &XSysAce_ConfigTable[Instance];
}

/*
 * The following block of code implements the reset handling.  The first
 * part implements /proc/xsysace/cfgaddr.  When read, it will yield a
 * number from 0 to 7 that represents which configuration will be used
 * next (the configuration address).  Writing a number to it will change
 * the configuration address.  After that is the function that is hooked
 * into the system's reset handler.
 */
#ifndef CONFIG_PROC_FS
#define proc_init() 0
#define proc_cleanup()
#else
#define CFGADDR_NAME "cfgaddr"

static struct proc_dir_entry *xsysace_dir = NULL;
static struct proc_dir_entry *cfgaddr_file = NULL;

static int
cfgaddr_read(char *page, char **start,
	     off_t off, int count, int *eof, void *data)
{
	unsigned int cfgaddr;

	/* Make sure we have room for a digit (0-7), a newline and a NULL */
	if (count < 3)
		return -EINVAL;

	MOD_INC_USE_COUNT;

	cfgaddr = XSysAce_GetCfgAddr(&SysAce);

	count = sprintf(page + off, "%d\n", cfgaddr);
	*eof = 1;

	MOD_DEC_USE_COUNT;

	return count;
}

static int
cfgaddr_write(struct file *file,
	      const char *buffer, unsigned long count, void *data)
{
	char val[2];

	if (count < 1 || count > 2)
		return -EINVAL;

	MOD_INC_USE_COUNT;

	if (copy_from_user(val, buffer, count)) {
		MOD_DEC_USE_COUNT;
		return -EFAULT;
	}

	if (val[0] < '0' || val[0] > '7' || (count == 2 && !(val[1] == '\n' ||
							     val[1] == '\0'))) {
		MOD_DEC_USE_COUNT;
		return -EINVAL;
	}
#endif

	XSysAce_SetCfgAddr(&SysAce, val[0] - '0');

	MOD_DEC_USE_COUNT;

	return count;
}

static int
proc_init(void)
{
	xsysace_dir = proc_mkdir(MAJOR_NAME, NULL);
	if (!xsysace_dir)
		return -ENOMEM;
	xsysace_dir->owner = THIS_MODULE;

	cfgaddr_file = create_proc_entry(CFGADDR_NAME, 0644, xsysace_dir);
	if (!cfgaddr_file) {
		remove_proc_entry(MAJOR_NAME, NULL);
		return -ENOMEM;
	}
	cfgaddr_file->read_proc = cfgaddr_read;
	cfgaddr_file->write_proc = cfgaddr_write;
	cfgaddr_file->owner = THIS_MODULE;
	return 0;
}

static void
proc_cleanup(void)
{
	if (cfgaddr_file)
		remove_proc_entry(CFGADDR_NAME, xsysace_dir);
	if (xsysace_dir)
		remove_proc_entry(MAJOR_NAME, NULL);
}

#ifdef CONFIG_VIRTEX_II_PRO
/*
 * The XSysAce_ResetCfg function causes the SystemACE to reset the
 * Xilinx chain that is attached to it. If I am a Virtex II Pro, then
 * presumably that includes me. Thus, The ResetCfg will ultimately
 * reset me, the processor, end of story.
 */
static void
xsysace_restart(char *cmd)
{
	printk(KERN_INFO "Using SystemACE to restart stystem ...\n");
	XSysAce_ResetCfg(&SysAce);

	/* Wait for reset. */
	for (;;) ;
}
#endif

/*
 * The code to handle the block device starts here.
 */

/*
 * This is just a small helper function to clean up a request that has
 * been given to the xsa_thread.
 */
static void
xsa_complete_request(int uptodate)
{
	unsigned long flags;

	XSysAce_Unlock(&SysAce);
	spin_lock_irqsave(&io_request_lock, flags);
	end_request(uptodate);
	req_active = 0;
	/* If there's something in the queue, */
	if (!QUEUE_EMPTY)
		xsysace_do_request(NULL);	/* handle it. */
	spin_unlock_irqrestore(&io_request_lock, flags);
}

/* Small helper function used inside polling loops. */
static inline void
xsa_short_delay(void)
{
	/* If someone else needs the CPU, go to sleep. */
	if (dont_spin || current->need_resched) {
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(HZ / 100);
	}
}

/* Simple function that hands an interrupt to the Xilinx code. */
static void
xsysace_interrupt(int irq, void *dev_id, struct pt_regs *regs)
{
	XSysAce_InterruptHandler(&SysAce);
}

/* Called by the Xilinx interrupt handler to give us an event. */
static void
EventHandler(void *CallbackRef, int Event)
{
	u32 ErrorMask;

	switch (Event) {
	case XSA_EVENT_DATA_DONE:
		xsa_complete_request(1);	/* The request succeeded. */
		break;

	case XSA_EVENT_ERROR:
		ErrorMask = XSysAce_GetErrors(&SysAce);

		/* Print out what went wrong. */
		if (ErrorMask & XSA_ER_CARD_RESET)
			printk(KERN_ERR "CompactFlash failed to reset\n");
		if (ErrorMask & XSA_ER_CARD_READY)
			printk(KERN_ERR "CompactFlash failed to ready\n");
		if (ErrorMask & XSA_ER_CARD_READ)
			printk(KERN_ERR "CompactFlash read command failed\n");
		if (ErrorMask & XSA_ER_CARD_WRITE)
			printk(KERN_ERR "CompactFlash write command failed\n");
		if (ErrorMask & XSA_ER_SECTOR_READY)
			printk(KERN_ERR
			       "CompactFlash sector failed to ready\n");
		if (ErrorMask & XSA_ER_BAD_BLOCK)
			printk(KERN_ERR "CompactFlash bad block detected\n");
		if (ErrorMask & XSA_ER_UNCORRECTABLE)
			printk(KERN_ERR "CompactFlash uncorrectable error\n");
		if (ErrorMask & XSA_ER_SECTOR_ID)
			printk(KERN_ERR "CompactFlash sector ID not found\n");
		if (ErrorMask & XSA_ER_ABORT)
			printk(KERN_ERR "CompactFlash command aborted\n");
		if (ErrorMask & XSA_ER_GENERAL)
			printk(KERN_ERR "CompactFlash general error\n");

		if (ErrorMask & XSA_ER_CFG_READ)
			printk(KERN_ERR
			       "JTAG controller couldn't read configuration from the CompactFlash\n");
		if (ErrorMask & XSA_ER_CFG_ADDR)
			printk(KERN_ERR
			       "Invalid address given to JTAG controller\n");
		if (ErrorMask & XSA_ER_CFG_FAIL)
			printk(KERN_ERR
			       "JTAG controller failed to configure a device\n");
		if (ErrorMask & XSA_ER_CFG_INSTR)
			printk(KERN_ERR
			       "Invalid instruction during JTAG configuration\n");
		if (ErrorMask & XSA_ER_CFG_INIT)
			printk(KERN_ERR "JTAG CFGINIT pin error\n");

		/* Check for errors that should reset the CompactFlash */
		if (ErrorMask & (XSA_ER_CARD_RESET |
				 XSA_ER_CARD_READY |
				 XSA_ER_CARD_READ |
				 XSA_ER_CARD_WRITE |
				 XSA_ER_SECTOR_READY |
				 XSA_ER_BAD_BLOCK |
				 XSA_ER_UNCORRECTABLE |
				 XSA_ER_SECTOR_ID | XSA_ER_ABORT |
				 XSA_ER_GENERAL)) {
			if (XSysAce_ResetCF(&SysAce) != XST_SUCCESS)
				printk(KERN_ERR
				       "Could not reset CompactFlash\n");
			xsa_complete_request(0); /* The request failed. */
		}
		break;
	case XSA_EVENT_CFG_DONE:
		printk(KERN_WARNING "XSA_EVENT_CFG_DONE not handled yet.\n");
		break;
	default:
		printk(KERN_ERR "%s: unrecognized event %d\n",
		       DEVICE_NAME, Event);
		break;
	}
}

/*
 * This task takes care of sending requests down to the Xilinx OS independent
 * code.  A task is necessary because there isn't an interrupt telling us
 * when the hardware is ready to accept another request, so we have to poll.
 */
static int
xsa_thread(void *arg)
{
	XStatus stat;
	unsigned long sector;

	struct task_struct *tsk = current;
	DECLARE_WAITQUEUE(wait, tsk);
	xsa_task = tsk;

	daemonize();
	reparent_to_init();
	strcpy(xsa_task->comm, MAJOR_NAME);
	xsa_task->tty = NULL;

	/* only want to receive SIGKILL */
	spin_lock_irq(&xsa_task->sigmask_lock);
	siginitsetinv(&xsa_task->blocked, sigmask(SIGKILL));
	recalc_sigpending(xsa_task);
	spin_unlock_irq(&xsa_task->sigmask_lock);

	complete(&task_sync);

	add_wait_queue(&req_wait, &wait);
	for (;;) {
		XStatus(*cur_req) (XSysAce * InstancePtr, u32 StartSector,
				   int NumSectors, u8 * BufferPtr);

		/* Block waiting for request */
		for (;;) {
			set_task_state(tsk, TASK_INTERRUPTIBLE);
			cur_req = req_fnc;
			if (cur_req != NULL) {
				req_fnc = NULL;
				break;	/* We've got a request. */
			}
			while (signal_pending(tsk)) {
				siginfo_t info;

				/* Only honor the signal if we're cleaning up */
				if (task_shutdown)
					goto exit;
				/*
				 * Someone else sent us a kill (probably
				 * the shutdown scripts "Sending all
				 * processes the KILL signal").  Just
				 * dequeue it and ignore it.
				 */
				spin_lock_irq(&current->sigmask_lock);
				(void)dequeue_signal(&current->blocked, &info);
				spin_unlock_irq(&current->sigmask_lock);
			}
			schedule();
		}
		set_task_state(tsk, TASK_RUNNING);

		/* We have a request. */
		sector = (CURRENT->sector +
			  xsa_hd[MINOR(CURRENT->rq_dev)].start_sect);

		while ((stat = XSysAce_Lock(&SysAce, 0)) == XST_DEVICE_BUSY)
			xsa_short_delay();
		if (stat != XST_SUCCESS) {
			printk(KERN_ERR "%s: Error %d when locking.\n",
			       DEVICE_NAME, stat);
			xsa_complete_request(0);	/* Request failed. */
		}

		while ((stat = cur_req(&SysAce, sector,
				       CURRENT->current_nr_sectors,
				       CURRENT->buffer)) == XST_DEVICE_BUSY)
			xsa_short_delay();
		/*
		 * If the stat is XST_SUCCESS, we have successfully
		 * gotten the request started on the hardware.  The
		 * completion (or error) interrupt will unlock the
		 * CompactFlash and complete the request, so we don't
		 * need to do anything except just loop around and wait
		 * for the next request.  If the status is not
		 * XST_SUCCESS, we need to finish the request with an
		 * error before waiting for the next request.
		 */
		if (stat != XST_SUCCESS) {
			printk(KERN_ERR "%s: Error %d when %s sector %lu.\n",
			       DEVICE_NAME, stat, req_str, sector);
			xsa_complete_request(0);	/* Request failed. */
		}

		if ((!xsa_use_interrupts) && (stat == XST_SUCCESS)) {
			debugk("RIQC: request complete.\n");
			xsa_complete_request(1);
		}
	}

      exit:
	remove_wait_queue(&req_wait, &wait);

	xsa_task = NULL;
	complete_and_exit(&task_sync, 0);
}

static void
xsysace_do_request(request_queue_t * q)
{
	/* We're already handling a request.  Don't accept another. */
	if (req_active)
		return;

	for (;;) {
		INIT_REQUEST;

		switch (CURRENT->cmd) {
		case READ:
			req_str = "reading";
			req_fnc = XSysAce_SectorRead;
			break;
		case WRITE:
			req_str = "writing";
			req_fnc = XSysAce_SectorWrite;
			break;
		default:
			printk(KERN_CRIT "%s: unknown request %d.\n",
			       DEVICE_NAME, CURRENT->cmd);
			end_request(0);	/* Bad request.  End it and onwards. */
			continue;	/* Go on to the next request. */
		}

		req_active = 1;
		wake_up(&req_wait);	/* Schedule task to take care of it */
		/*
		 * It is up to the task or interrupt handler to complete
		 * the request.  We return now so the io_request_lock
		 * will get cleared and requests can be queued.
		 */
		return;
	}
}

extern struct gendisk xsa_gendisk;

static int
xsa_revalidate(kdev_t kdev, int max_access)
{
	int target, max_p, start, i;
	long flags;

	target = DEVICE_NR(kdev);

	save_flags(flags);
	cli();
	if (revalidating || access_count > max_access) {
		restore_flags(flags);
		return -EBUSY;
	}
	revalidating = 1;
	restore_flags(flags);

	max_p = xsa_gendisk.max_p;
	start = target << PARTN_BITS;
	for (i = max_p - 1; i >= 0; i--) {
		int minor = start + i;
		invalidate_device(MKDEV(MAJOR_NR, minor), 1);
		xsa_gendisk.part[minor].start_sect = 0;
		xsa_gendisk.part[minor].nr_sects = 0;
	}

	grok_partitions(&xsa_gendisk, target, NR_HD << PARTN_BITS,
			(long) cylinders * (long) heads * (long) sectors);
	revalidating = 0;
	wake_up(&revalidate_wait);
	return 0;
}

/*
 * For right now, there isn't a way to tell the hardware to spin down
 * the drive.  For IBM Microdrives, which is what the ML300 ships with,
 * removing them without a spindown is probably not very good.  Thus, we
 * don't even want to have the System ACE driver handle removable media.
 * For now, placeholder code has been surrounded by ifdef XSA_REMOVABLE
 * (which is not defined) in a few places in this file.  Something that
 * is not handled in the placeholder code is identifying the new drive.
 */
#ifdef XSA_REMOVABLE
static int
xsysace_revalidate(kdev_t kdev)
{
	return xsa_revalidate(kdev, 0);
}

static int
xsysace_check_change(kdev_t kdev)
{
	/*
	 * If and when we do support removable media, we'll need to
	 * figure out how to tell if the media was changed.  For now,
	 * just always say that the media was changed, which is safe,
	 * but not optimal.
	 */
	return 1;
}
#endif

static int
xsysace_open(struct inode *inode, struct file *file)
{
	wait_event(revalidate_wait, !revalidating);
	access_count++;

	MOD_INC_USE_COUNT;
	return 0;
}

static int
xsysace_release(struct inode *inode, struct file *file)
{
	access_count--;

	MOD_DEC_USE_COUNT;
	return 0;
}

static int
xsysace_ioctl(struct inode *inode, struct file *file,
	      unsigned int cmd, unsigned long arg)
{
	if (!inode || !inode->i_rdev)
		return -EINVAL;

	switch (cmd) {
	case BLKGETSIZE:
		return put_user(xsa_hd[MINOR(inode->i_rdev)].nr_sects,
				(unsigned long *) arg);
	case BLKGETSIZE64:
		return put_user((u64) xsa_hd[MINOR(inode->i_rdev)].
				nr_sects, (u64 *) arg);
	case BLKRRPART:
		if (!capable(CAP_SYS_ADMIN))
			return -EACCES;

		return xsa_revalidate(inode->i_rdev, 1);

	case HDIO_GETGEO:
		{
			struct hd_geometry *loc, g;
			loc = (struct hd_geometry *) arg;
			if (!loc)
				return -EINVAL;
			g.heads = heads;
			g.sectors = sectors;
			g.cylinders = cylinders;
			g.start = xsa_hd[MINOR(inode->i_rdev)].start_sect;
			return copy_to_user(loc, &g, sizeof(g)) ? -EFAULT : 0;
		}
	default:
		/* Let the block layer handle all the others. */
		return blk_ioctl(inode->i_rdev, cmd, arg);
	}
}

static struct block_device_operations xsa_fops = {
	open:xsysace_open,
	release:xsysace_release,
	ioctl:xsysace_ioctl,
#ifdef XSA_REMOVABLE
	check_media_change:xsysace_check_change,
	revalidate:xsysace_revalidate
#endif
};

static struct gendisk xsa_gendisk = {	/* Generic Hard Disk */
	major_name:MAJOR_NAME,
	minor_shift:PARTN_BITS,
	max_p:NR_HD << PARTN_BITS,
	part:xsa_hd,
	sizes:xsa_sizes,
	fops:&xsa_fops
};

#define XSA_IRQ (31 - XPAR_INTC_0_SYSACE_0_VEC_ID)

static void
cleanup(void)
{
	XSysAce_Config *cfg;
	int i;

	/* Make sure everything is flushed. */
	for (i = 0; i < (NR_HD << PARTN_BITS); i++)
		fsync_dev(MKDEV(xsa_major, i));

	proc_cleanup();

	if (registered) {
		blk_cleanup_queue(BLK_DEFAULT_QUEUE(xsa_major));
		del_gendisk(&xsa_gendisk);
		if (devfs_unregister_blkdev(xsa_major, DEVICE_NAME) != 0) {
			printk(KERN_ERR "%s: unable to release major %d\n",
			       DEVICE_NAME, xsa_major);
		}
	}

	/* Tidy up a little. */
	read_ahead[xsa_major] = 0;
	blk_size[xsa_major] = NULL;
	blksize_size[xsa_major] = NULL;
	hardsect_size[xsa_major] = NULL;
	max_sectors[xsa_major] = NULL;

	if (xsa_task) {
		task_shutdown = 1;
		send_sig(SIGKILL, xsa_task, 1);
		wait_for_completion(&task_sync);
	}

	if (reqirq) {
		XSysAce_DisableInterrupt(&SysAce);
		disable_irq(XSA_IRQ);
		free_irq(XSA_IRQ, NULL);
	}

	cfg = XSysAce_GetConfig(0);
	iounmap((void *) cfg->BaseAddress);
	cfg->BaseAddress = save_BaseAddress;

#ifdef CONFIG_VIRTEX_II_PRO
	if (old_restart)
		ppc_md.restart = old_restart;
#endif
}

static int __init
xsysace_init(void)
{
	static const unsigned long remap_size
	    = XPAR_SYSACE_0_HIGHADDR - XPAR_SYSACE_0_BASEADDR + 1;
	XSysAce_Config *cfg;
	XSysAce_CFParameters ident;
	XStatus stat;
	long size;
	int i;

	/* Find the config for our device. */
	cfg = XSysAce_GetConfig(0);
	if (!cfg)
		return -ENODEV;

	/* Change the addresses to be virtual; save the old ones to restore. */
	save_BaseAddress = cfg->BaseAddress;
	cfg->BaseAddress = (u32) ioremap(save_BaseAddress, remap_size);

	/* Tell the Xilinx code to bring this interface up. */
	if (XSysAce_Initialize(&SysAce, cfg->DeviceId) != XST_SUCCESS) {
		printk(KERN_ERR "%s: Could not initialize device.\n",
		       DEVICE_NAME);
		cleanup();
		return -ENODEV;
	}

	if (xsa_use_interrupts) {
		i = request_irq(XSA_IRQ, xsysace_interrupt, 0, DEVICE_NAME, NULL);
		if (i) {
			printk(KERN_ERR "%s: Could not allocate interrupt %d.\n",
				DEVICE_NAME, XSA_IRQ);
			cleanup();
			return i;
		}
		reqirq = 1;
	}

	XSysAce_SetEventHandler(&SysAce, EventHandler, (void *) NULL);

	if (xsa_use_interrupts) {
		XSysAce_EnableInterrupt(&SysAce);
	} else {
		XSysAce_DisableInterrupt(&SysAce);
	}

	/* Time to identify the drive. */
	while (XSysAce_Lock(&SysAce, 0) == XST_DEVICE_BUSY)
		xsa_short_delay();
	while ((stat = XSysAce_IdentifyCF(&SysAce, &ident)) == XST_DEVICE_BUSY)
		xsa_short_delay();
	XSysAce_Unlock(&SysAce);
	if (stat != XST_SUCCESS) {
		printk(KERN_ERR "%s: Could not send identify command.\n",
		       DEVICE_NAME);
		cleanup();
		return -ENODEV;
	}

	/* Fill in what we learned. */
	heads = ident.NumHeads;
	sectors = ident.NumSectorsPerTrack;
	cylinders = ident.NumCylinders;
	size = (long) cylinders * (long) heads * (long) sectors;

	/* Start up our task. */
	init_completion(&task_sync);
	if ((i = kernel_thread(xsa_thread, 0, 0)) < 0) {
		cleanup();
		return i;
	}
	wait_for_completion(&task_sync);

	i = devfs_register_blkdev(xsa_major, DEVICE_NAME, &xsa_fops);
	if (i < 0) {
		printk(KERN_ERR "%s: Unable to register device\n", DEVICE_NAME);
		cleanup();
		return i;
	}
	if (xsa_major == 0)
		xsa_major = i;
	registered = 1;
	xsa_gendisk.major = xsa_major;

	blk_init_queue(BLK_DEFAULT_QUEUE(xsa_major), xsysace_do_request);

	read_ahead[xsa_major] = 8;	/* 8 sector (4kB) read-ahead */
	add_gendisk(&xsa_gendisk);

	/* Start with zero-sized partitions, and correctly sized unit */
	memset(xsa_sizes, 0, sizeof(xsa_sizes));
	xsa_sizes[0] = size / 2;	/* convert sectors to kilobytes */
	blk_size[xsa_major] = xsa_sizes;
	memset(xsa_hd, 0, sizeof(xsa_hd));
	xsa_hd[0].nr_sects = size;
	for (i = 0; i < (NR_HD << PARTN_BITS); i++) {
		xsa_blocksizes[i] = 1024;
		xsa_hardsectsizes[i] = 512;
		/* XSysAce_Sector{Read,Write} will allow up to 256 sectors.
		 *
		 * HOWEVER, the driver code will assert on an absolute sector
		 * count > 255 because to the driver, 0 means 256 sectors.
		 * Rather than fix this bug at a lower level by masking the
		 * sector transfer count with 0xff, I chose to simply limit
		 * the maximum number of sectors transferred to < 0xff - KJO
		 */
		xsa_maxsect[i] = 250;
	}
	blksize_size[xsa_major] = xsa_blocksizes;
	hardsect_size[xsa_major] = xsa_hardsectsizes;
	max_sectors[xsa_major] = xsa_maxsect;

	xsa_gendisk.nr_real = NR_HD;

	register_disk(&xsa_gendisk, MKDEV(xsa_major, 0),
		      NR_HD << PARTN_BITS, &xsa_fops, size);

	if (xsa_use_interrupts) {
		printk(KERN_INFO
			"%s at 0x%08X mapped to 0x%08X, irq=%d, %ldKB CF card\n",
			DEVICE_NAME, save_BaseAddress, cfg->BaseAddress, XSA_IRQ,
			size / 2);
	} else {
		printk(KERN_INFO
			"%s at 0x%08X mapped to 0x%08X, polled I/O, %ldKB CF card\n",
			DEVICE_NAME, save_BaseAddress, cfg->BaseAddress, size / 2);
	}

#ifdef CONFIG_VIRTEX_II_PRO
	/* Hook our reset function into system's restart code. */
	old_restart = ppc_md.restart;
	ppc_md.restart = xsysace_restart;
#endif

	if (proc_init())
		printk(KERN_WARNING "%s: Could not register /proc interface.\n",
		       DEVICE_NAME);

	return 0;
}

static void __exit
xsysace_exit(void)
{
	cleanup();
}

EXPORT_NO_SYMBOLS;

module_init(xsysace_init);
module_exit(xsysace_exit);

^ permalink raw reply

* Re: [PATCH 1/2]: powerpc/cell spidernet bottom half
From: Linas Vepstas @ 2006-08-16 21:58 UTC (permalink / raw)
  To: David Miller
  Cc: akpm, jeff, arnd, netdev, jklewis, linux-kernel, linuxppc-dev,
	Jens.Osterkamp
In-Reply-To: <20060816.134640.115912460.davem@davemloft.net>

On Wed, Aug 16, 2006 at 01:46:40PM -0700, David Miller wrote:
> From: Jeff Garzik <jeff@garzik.org>
> Date: Wed, 16 Aug 2006 16:34:31 -0400
> 
> > Linas Vepstas wrote:
> > > I was under the impression that NAPI was for the receive side only.
> > 
> > That depends on the driver implementation.
> 
> What Jeff is trying to say is that TX reclaim can occur in
> the NAPI poll routine, and in fact this is what the vast
> majority of NAPI drivers do.

I'll experiment with this.  When doing, say, an ftp, there are 
enough TCP ack packets coming back to have NAPI netdev->poll 
be called frequently enough? 

> implied.  In fact, I get the impression that spidernet is limited
> in some way and that's where all the strange approaches are coming
> from :)

Hmm. Or maybe I'm just getting old. Once upon a time, low watermarks
were considered the "best" way of doing anything; never occurred to me
it would be considered "strange".  Based on my probably obsolete idea
of what constitutes "slick hardware", I was actually impressed by what
the spidernet could do.

Aside from cleaning up the transmit ring in the receive poll loop,
what would be the not-so-strange way of doing things?

--linas

^ permalink raw reply

* Re: Linux hanging on Xilinx SystemACE
From: Grant Likely @ 2006-08-16 21:48 UTC (permalink / raw)
  To: Clint Thomas; +Cc: linuxppc-embedded
In-Reply-To: <3C02138692C13C4BB675FE7EA240952918DBED@bluefin.Soneticom.local>

On 8/16/06, Clint Thomas <cthomas@soneticom.com> wrote:
>
>
> Hey,
>
> Using the powerpc development tree of Linux 2.4, I am trying to boot my
> system from CompactFlash using Xilinx SystemACE. My compact flash card has
> two partitions, a 16MB FAT16 that holds the combination FPGA image / Linux
> Kernel ELF file, and an Ext2 partition that holds the root file system. The
> system starts the boot process, uncompresses the Linux kernel and begins
> loading drivers. Part way into this process, it conducts a partition check
> of the drive being reported to it by SystemACE, however, it hangs at that
> point. No kernel panic, no error message, it simply hangs. Here is the
> output at that point...
>
> Partition check:
>  xsysacea:
>
> what I am trying to find out is if this problem has been seen/fixed in the
> past? or did I format the CF card incorrectly?

Checking partitions is a user-space activity (fsck).  Remove it from
your init scripts.  Besides, unless your using a microdrive, your ext2
rootfs should be mounted read-only which greatly reduces the need for
fsck.  (because FLASH will wear out after too many writes)

Cheers,
g.
-- 
Grant Likely, B.Sc. P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195

^ permalink raw reply

* Re: [PATCH 1/2]: powerpc/cell spidernet bottom half
From: David Miller @ 2006-08-16 21:32 UTC (permalink / raw)
  To: arnd
  Cc: akpm, jeff, netdev, jklewis, linux-kernel, linuxppc-dev,
	Jens.Osterkamp
In-Reply-To: <200608162324.47235.arnd@arndb.de>

From: Arnd Bergmann <arnd@arndb.de>
Date: Wed, 16 Aug 2006 23:24:46 +0200

> We first had an interrupt per descriptor, then got rid of all TX
> interrupts and replaced them by timers to reduce the interrupt load,
> but reducing throughput in the case where user space sleeps on a full
> socket buffer.

The best schemes seem to be to interrupt mitigate using a combination
of time and number of TX entries pending to be purged.  This is what
most gigabit chips seem to offer.

On Tigon3, for example, we tell the chip to interrupt if either 53
frames or 150usecs have passed since the first TX packet has become
available for reclaim.

That bounds the latency as well as force the interrupt if a lot of TX
work becomes available.

Can spidernet be told these kinds of parameters?  "N packets or
X usecs"?

This is all controllable via ethtool btw (via ETHTOOL_{S,G}COALESCE),
so you can experiment if you want.

^ permalink raw reply

* Re: [PATCH 1/2]: powerpc/cell spidernet bottom half
From: Arnd Bergmann @ 2006-08-16 21:24 UTC (permalink / raw)
  To: David Miller
  Cc: akpm, jeff, netdev, jklewis, linux-kernel, linuxppc-dev,
	Jens.Osterkamp
In-Reply-To: <20060816.134640.115912460.davem@davemloft.net>

Am Wednesday 16 August 2006 22:46 schrieb David Miller:
> I'm not familiar with the spidernet TX side interrupt capabilities
> so I can't say whether that is something that can be directly
> implied. =A0In fact, I get the impression that spidernet is limited
> in some way and that's where all the strange approaches are coming
> from :)

Actually, the capabilities of the chip are quite powerful, it only
seems to be hard to make it go fast using any of them. That may
be the fault of strange locking rules and other bugs we had in
the driver before, so maybe you can recommend which one to use.

Cleaning up the TX queue only from ->poll() like all the others
sounds like the right approach to simplify the code.

The spider hardware offers at least these options:

=2D end of TX queue interrupt
=2D set a per-descriptor bit to fire an interrupt at a specific frame
=2D an interrupt for each frame (may be multiple descriptors)
=2D an interrupt for each descriptor
=2D timers implemented in the spidernet hardware

We first had an interrupt per descriptor, then got rid of all TX
interrupts and replaced them by timers to reduce the interrupt load,
but reducing throughput in the case where user space sleeps on a full
socket buffer.

The last patches that were suggested introduce marking a single descriptor
(not the last one, but somewhere near the end of the queue) so we fire
an interrupt just before the TX queue gets empty.

	Arnd <><

^ permalink raw reply

* Re: [PATCH 1/2]: powerpc/cell spidernet bottom half
From: David Miller @ 2006-08-16 20:46 UTC (permalink / raw)
  To: jeff
  Cc: akpm, arnd, netdev, jklewis, linux-kernel, linuxppc-dev,
	Jens.Osterkamp
In-Reply-To: <44E38157.4070805@garzik.org>

From: Jeff Garzik <jeff@garzik.org>
Date: Wed, 16 Aug 2006 16:34:31 -0400

> Linas Vepstas wrote:
> > I was under the impression that NAPI was for the receive side only.
> 
> That depends on the driver implementation.

What Jeff is trying to say is that TX reclaim can occur in
the NAPI poll routine, and in fact this is what the vast
majority of NAPI drivers do.

It also makes the locking simpler.

In practice, the best thing seems to be to put both RX and TX
work into ->poll() and have a very mild hw interrupt mitigation
setting programmed into the chip.

I'm not familiar with the spidernet TX side interrupt capabilities
so I can't say whether that is something that can be directly
implied.  In fact, I get the impression that spidernet is limited
in some way and that's where all the strange approaches are coming
from :)

^ permalink raw reply

* Linux hanging on Xilinx SystemACE
From: Clint Thomas @ 2006-08-16 21:06 UTC (permalink / raw)
  To: linuxppc-embedded

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

Hey,

Using the powerpc development tree of Linux 2.4, I am trying to boot my
system from CompactFlash using Xilinx SystemACE. My compact flash card
has two partitions, a 16MB FAT16 that holds the combination FPGA image /
Linux Kernel ELF file, and an Ext2 partition that holds the root file
system. The system starts the boot process, uncompresses the Linux
kernel and begins loading drivers. Part way into this process, it
conducts a partition check of the drive being reported to it by
SystemACE, however, it hangs at that point. No kernel panic, no error
message, it simply hangs. Here is the output at that point...

Partition check:
 xsysacea:
 
what I am trying to find out is if this problem has been seen/fixed in
the past? or did I format the CF card incorrectly?
 
Clinton Thomas
cthomas@soneticom.com
 

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

^ permalink raw reply

* RE: 8260  SMC1 and SMC2 serial port problems
From: Pelton, Dave @ 2006-08-16 20:46 UTC (permalink / raw)
  To: linuxppc-embedded; +Cc: Boris Shteinbock

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

Hi Boris,

I recently upgraded my kernel from 2.6.15 to 2.6.17 on a 8247 based
custom board (8247 has a CPM2 and is similar to the 8260).  I use SMC2
as a serial port, and I had a couple of problems when I started using
2.6.17.  I think initially I was seeing the same behaviour as you
(serial port only worked when it was defined as the console).

The "compat mode" message you are seeing is part of the new CPM UART
0.02 driver (refer to http://patchwork.ozlabs.org/linuxppc/patch?id=5149
and related patches).  If there are no UART platform devices added in
your board specific code, then you will see this message.  To make the
compat mode work properly with the new driver I made a couple of changes
(see attached cpm2_uart_noplatform.diff).  The changes are to
drivers/serial/cpm_uart/cpm_uart_core.c:

1) Added a call to pinfo->set_lineif in cpm_uart_request_port
This code is required to set up the port pins and BRG for the UART.
This was in the old version of the driver and I added it back.  As far
as I can tell, this chunk of code is what makes the serial port work
properly when it is not the console (in compat mode).  To make this
properly compatible with the platform stuff, this call should not be
made if the device has platform data, but I'm not exactly sure how to
add that check in a clean way.

2) Added a call to cpm_uart_init_portdesc in cpm_uart_console_init
This was another snippet that was in the previous version of the driver.
I don't recall exactly what behaviour this fixed, but I think it made
things better.  Again this may not work properly if the device has
platform data.


I did try defining a platform device for the UART in my board specific
file (similar to what is done in arch/ppc/platforms/mpc8272ads_setup.c),
but I ran into a couple of problems here too.  The main problem is that
arch/ppc/syslib/pq2_devices.c needs a small change to the naming of
things for the SMCs (see attached cpm2_smc_resource_rename.diff).  That
made things work better, but not 100%.  I decided to go back to compat
mode, because with the fixes outlined above it was working fine for me.


- Hope this helps,
  David Pelton


-----Original Message-----
Sent: Monday, August 14, 2006 6:26 PM
To: linuxppc-embedded@ozlabs.org
Subject: 8260 SMC1 and SMC2 serial port problems

Hi guys.

I am working on the Linux port on a custom 8260-based board.
During the port I've encountered a few problems with serial ports.

1. On the latest kernel 2.6.17 the cpm2 serial driver fails during the
bus scan and fails back to so called compat mode.
2. For whatever strange reason, the driver is unable to initialize
serial port, if the console on SMC is not selected.
3. I am unable to work with both SMC1 and SMC2 together. During driver
init, only one port actually gets an IRQ.
In another words, if I enable both SMC1 and SMC2 in the  kernel config. 
and put console on ttyCPM0, then SMC1 gets IRQ, but SMC2 doesn't. dmesg
actually prints IRQs for both ports, but looking into /proc/irq reveals,
that only one interrupt is assigned only for port that is used as a
console.

2) and 3) relate for both 2.6.17 and 2.6.16 kernel trees

Could someone, please, advise me, on possible solutions for those
problems ?

Thanks in advance,
Boris
_______________________________________________
Linuxppc-embedded mailing list
Linuxppc-embedded@ozlabs.org
https://ozlabs.org/mailman/listinfo/linuxppc-embedded

[-- Attachment #2: cpm2_smc_resource_rename.diff --]
[-- Type: application/octet-stream, Size: 901 bytes --]

Index: linux/arch/ppc/syslib/pq2_devices.c
===================================================================
--- linux/arch/ppc/syslib/pq2_devices.c	(revision 33743)
+++ linux/arch/ppc/syslib/pq2_devices.c	(working copy)
@@ -297,13 +297,13 @@
 		.num_resources	 = 3,
 		.resource = (struct resource[]) {
 			{
-				.name	= "smc_mem",
+				.name	= "regs",
 				.start	= 0x11A80,
 				.end	= 0x11A8F,
 				.flags	= IORESOURCE_MEM,
 			},
 			{
-				.name	= "smc_pram",
+				.name	= "pram",
 				.start	= 0x87fc,
 				.end	= 0x87fd,
 				.flags	= IORESOURCE_MEM,
@@ -321,13 +321,13 @@
 		.num_resources	 = 3,
 		.resource = (struct resource[]) {
 			{
-				.name	= "smc_mem",
+				.name	= "regs",
 				.start	= 0x11A90,
 				.end	= 0x11A9F,
 				.flags	= IORESOURCE_MEM,
 			},
 			{
-				.name	= "smc_pram",
+				.name	= "pram",
 				.start	= 0x88fc,
 				.end	= 0x88fd,
 				.flags	= IORESOURCE_MEM,

[-- Attachment #3: cpm2_uart_noplatform.diff --]
[-- Type: application/octet-stream, Size: 881 bytes --]

Index: linux/drivers/serial/cpm_uart/cpm_uart_core.c
===================================================================
--- linux/drivers/serial/cpm_uart/cpm_uart_core.c	(revision 33559)
+++ linux/drivers/serial/cpm_uart/cpm_uart_core.c	(working copy)
@@ -868,6 +869,14 @@
 	if (pinfo->flags & FLAG_CONSOLE)
 		return 0;
 
+	/*
+	 * Setup any port IO, connect any baud rate generators,
+	 * etc.	 This is expected to be handled by board
+	 * dependant code
+	 */
+	if (pinfo->set_lineif)		 
+		pinfo->set_lineif(pinfo);	 
+ 
 	if (IS_SMC(pinfo)) {
 		pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
 		pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
@@ -1238,7 +1243,10 @@
 
 int __init cpm_uart_console_init(void)
 {
-	register_console(&cpm_scc_uart_console);
+	int ret = cpm_uart_init_portdesc(); 	 
+
+	if (!ret)
+		register_console(&cpm_scc_uart_console);
 	return 0;
 }
 

^ permalink raw reply

* Re: [PATCH 1/2]:  powerpc/cell spidernet bottom half
From: Jeff Garzik @ 2006-08-16 20:34 UTC (permalink / raw)
  To: Linas Vepstas
  Cc: akpm, Arnd Bergmann, netdev, James K Lewis, linux-kernel,
	linuxppc-dev, Jens Osterkamp
In-Reply-To: <20060816203043.GJ20551@austin.ibm.com>

Linas Vepstas wrote:
> I was under the impression that NAPI was for the receive side only.

That depends on the driver implementation.

	Jeff

^ permalink raw reply

* Re: [PATCH 1/2]:  powerpc/cell spidernet bottom half
From: Linas Vepstas @ 2006-08-16 20:30 UTC (permalink / raw)
  To: Jeff Garzik
  Cc: akpm, Arnd Bergmann, netdev, James K Lewis, linux-kernel,
	linuxppc-dev, Jens Osterkamp
In-Reply-To: <44E34825.2020105@garzik.org>

On Wed, Aug 16, 2006 at 12:30:29PM -0400, Jeff Garzik wrote:
> Linas Vepstas wrote:
> >
> >The recent set of low-waterark patches for the spider result in a
> 
> Let's not reinvented NAPI, shall we...

?? 

I was under the impression that NAPI was for the receive side only.
This round of patches were for the transmit queue.

Let me describe the technical problem; perhaps there's some other
solution for it?  

The default socket size seems to be 128KB; (cat
/proc/sys/net/core/wmem_default) if a user application
writes more than 128 KB to a socket, the app is blocked by the 
kernel till there's room in the socket for more.  At gigabit speeds,
a network card can drain 128KB in about a millisecond, or about
four times a jiffy (assuming  HZ=250).  If the network card isn't
generaing interrupts, (and there are no other interrupts flying 
around) then the tcp stack only wakes up once a jiffy, and so 
the user app is scheduled only once a jiffy.  Thus, the max
bandwidth that the app can see is (HZ * wmem_default) bytes per 
second, or about 250 Mbits/sec for my system.  Disappointing 
for a gigabit adapter.

There's three ways out of this: 

(1) tell the sysadmin to 
    "echo 1234567 > /proc/sys/net/core/wmem_default" which 
    violates all the rules.

(2) Poll more frequently than once-a-jiffy. Arnd Bergmann and I 
    got this working, using hrtimers. It worked pretty well,
    but seemed like a hack to me.

(3) Generate transmit queue low-watermark interrupts, 
    which is an admitedly olde-fashioned but common
    engineering practice.  This round of patches implement 
    this.


--linas

^ permalink raw reply

* [PATCH] powerpc: Make RTAS console init generic
From: Michael Neuling @ 2006-08-16 19:42 UTC (permalink / raw)
  To: paulus; +Cc: linuxppc-dev, anton

The rtas console doesn't have to be Cell specific.  If we get both
rtas tokens, we should just enabled the console then and there.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
Updated Kconfig so we can enable it.  

 arch/powerpc/Kconfig                |    2 +-
 arch/powerpc/kernel/rtas.c          |    5 +++++
 arch/powerpc/platforms/cell/setup.c |    4 ----
 3 files changed, 6 insertions(+), 5 deletions(-)

Index: linux-2.6-ozlabs/arch/powerpc/Kconfig
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/Kconfig
+++ linux-2.6-ozlabs/arch/powerpc/Kconfig
@@ -426,7 +426,7 @@ config PPC_IBM_CELL_BLADE
 	select UDBG_RTAS_CONSOLE
 
 config UDBG_RTAS_CONSOLE
-	bool
+	bool "RTAS based debug console"
 	default n
 
 config XICS
Index: linux-2.6-ozlabs/arch/powerpc/kernel/rtas.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/kernel/rtas.c
+++ linux-2.6-ozlabs/arch/powerpc/kernel/rtas.c
@@ -910,6 +910,11 @@ int __init early_init_dt_scan_rtas(unsig
 	basep = of_get_flat_dt_prop(node, "get-term-char", NULL);
 	if (basep)
 		rtas_getchar_token = *basep;
+
+	if (rtas_putchar_token != RTAS_UNKNOWN_SERVICE &&
+	    rtas_getchar_token != RTAS_UNKNOWN_SERVICE)
+		udbg_init_rtas_console();
+
 #endif
 
 	/* break now */
Index: linux-2.6-ozlabs/arch/powerpc/platforms/cell/setup.c
===================================================================
--- linux-2.6-ozlabs.orig/arch/powerpc/platforms/cell/setup.c
+++ linux-2.6-ozlabs/arch/powerpc/platforms/cell/setup.c
@@ -150,10 +150,6 @@ static int __init cell_probe(void)
 	    !of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
 		return 0;
 
-#ifdef CONFIG_UDBG_RTAS_CONSOLE
-	udbg_init_rtas_console();
-#endif
-
 	hpte_init_native();
 
 	return 1;

^ permalink raw reply

* Re: [PATCH 7/7] ehea: Makefile & Kconfig
From: Michael Neuling @ 2006-08-16 19:27 UTC (permalink / raw)
  To: Jan-Bernd Themann
  Cc: Thomas Klein, Jan-Bernd Themann, netdev, linux-kernel,
	Thomas Klein, linux-ppc, Christoph Raisch, Marcus Eder
In-Reply-To: <44E0A580.9020507@de.ibm.com>

This patch is still being white space munged so it doesn't apply.  

The context is being shifted over 1 column.  All your other patches add
new files so there is no context and hence they apply.

Mikey

In message <44E0A580.9020507@de.ibm.com> you wrote:
> Signed-off-by: Jan-Bernd Themann <themann@de.ibm.com>
> 
> 
>   drivers/net/Kconfig  |    6 ++++++
>   drivers/net/Makefile |    1 +
>   2 files changed, 7 insertions(+)
> 
> 
> 
> diff -Nurp -X dontdiff linux-2.6.18-rc4/drivers/net/Kconfig patched_kernel/dr
ivers/net/Kconfig
> --- linux-2.6.18-rc4/drivers/net/Kconfig	2006-08-06 11:20:11.000000000 -
0700
> +++ patched_kernel/drivers/net/Kconfig	2006-08-08 03:00:49.526421944 -
0700
> @@ -2277,6 +2277,12 @@ config CHELSIO_T1
>             To compile this driver as a module, choose M here: the module
>             will be called cxgb.
> 
> +config EHEA
> +        tristate "eHEA Ethernet support"
> +        depends on IBMEBUS
> +        ---help---
> +          This driver supports the IBM pSeries ethernet adapter
> +
>   config IXGB
>   	tristate "Intel(R) PRO/10GbE support"
>   	depends on PCI
> diff -Nurp -X dontdiff linux-2.6.18-rc4/drivers/net/Makefile patched_kernel/d
rivers/net/Makefile
> --- linux-2.6.18-rc4/drivers/net/Makefile	2006-08-06 11:20:11.000000000 -
0700
> +++ patched_kernel/drivers/net/Makefile	2006-08-08 03:00:30.061451584 -
0700
> @@ -10,6 +10,7 @@ obj-$(CONFIG_E1000) += e1000/
>   obj-$(CONFIG_IBM_EMAC) += ibm_emac/
>   obj-$(CONFIG_IXGB) += ixgb/
>   obj-$(CONFIG_CHELSIO_T1) += chelsio/
> +obj-$(CONFIG_EHEA) += ehea/
>   obj-$(CONFIG_BONDING) += bonding/
>   obj-$(CONFIG_GIANFAR) += gianfar_driver.o
> 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

^ permalink raw reply

* Re: PowerPC paxtest results w/ gcc-4.1
From: Segher Boessenkool @ 2006-08-16 17:49 UTC (permalink / raw)
  To: Gabriel Paubert
  Cc: 'Albert Cahalan', linuxppc-dev, debian-powerpc,
	Paul Mackerras
In-Reply-To: <20060816105925.GB21865@iram.es>

> I never understood why PTE entries waste 4 bits (WIMG)
> for effectively very few valid combinations.

The only invalid combinations are WI=11 -- if you know of
a way to fit 12 combinations in fewer than 4 bits, let us
know :-)

Not all of those 12 are very useful, of course.


Segher

^ permalink raw reply

* Re: [PATCH 1/2]:  powerpc/cell spidernet bottom half
From: Jeff Garzik @ 2006-08-16 16:30 UTC (permalink / raw)
  To: Linas Vepstas
  Cc: akpm, Arnd Bergmann, netdev, James K Lewis, linux-kernel,
	linuxppc-dev, Jens Osterkamp
In-Reply-To: <20060816161856.GD20551@austin.ibm.com>

Linas Vepstas wrote:
> Please apply and forward upstream. This patch requires the previous
> sequence of 4 spidernet patches to be applied.
> 
> --linas
> 
> 
> The recent set of low-waterark patches for the spider result in a
> significant amount of computing being done in an interrupt context.
> This patch moves this to a "bottom half" aka work queue, so that
> the code runs in a normal kernel context. Curiously, this seems to 
> result in a performance boost of about 5% for large packets.
> 
> Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
> Cc: Utz Bacher <utz.bacher@de.ibm.com>
> Cc: Jens Osterkamp <Jens.Osterkamp@de.ibm.com>

Let's not reinvented NAPI, shall we...

	Jeff

^ permalink raw reply

* [PATCH 2/2]:  powerpc/cell spidernet refine locking
From: Linas Vepstas @ 2006-08-16 16:23 UTC (permalink / raw)
  To: netdev, linux-kernel, linuxppc-dev
  Cc: akpm, , Arnd Bergmann, jeff, Jens Osterkamp, James K Lewis, wq
In-Reply-To: <20060811170337.GH10638@austin.ibm.com>


Please apply and forward upstream. This patch requires the 
pervious set of four spidernet patches to be applied.

--linas

The transmit side of the spider ethernet driver currently
places locks around some very large chunks of code. This
results in a fair amount of lock contention is some cases. 
This patch makes the locks much more fine-grained, protecting
only the cirtical sections (the queue head and tail pointers,
and the queue low-watermark location).

This, with the previous patches, result in the following 
performance, using netperf, averaged over 5 minute runs:

pkt size    rate
========    ====
1500        804 Mbits/sec
 800        701 Mbits/sec
 600        600 Mbits/sec
 300        280 Mbits/sec
  60         60 Mbits/sec


Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: Utz Bacher <utz.bacher@de.ibm.com>
Cc: Jens Osterkamp <Jens.Osterkamp@de.ibm.com>

----
 drivers/net/spider_net.c |   77 ++++++++++++++++++++---------------------------
 drivers/net/spider_net.h |    2 -
 2 files changed, 35 insertions(+), 44 deletions(-)

Index: linux-2.6.18-rc3-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-rc3-mm2.orig/drivers/net/spider_net.c	2006-08-15 14:28:56.000000000 -0500
+++ linux-2.6.18-rc3-mm2/drivers/net/spider_net.c	2006-08-15 14:29:36.000000000 -0500
@@ -644,8 +644,9 @@ static int
 spider_net_prepare_tx_descr(struct spider_net_card *card,
 			    struct sk_buff *skb)
 {
-	struct spider_net_descr *descr = card->tx_chain.head;
+	struct spider_net_descr *descr;
 	dma_addr_t buf;
+	unsigned long flags;
 
 	buf = pci_map_single(card->pdev, skb->data, skb->len, PCI_DMA_TODEVICE);
 	if (buf == DMA_ERROR_CODE) {
@@ -655,6 +656,10 @@ spider_net_prepare_tx_descr(struct spide
 		return -ENOMEM;
 	}
 
+	spin_lock_irqsave(&card->tx_chain.lock, flags);
+	descr = card->tx_chain.head;
+	card->tx_chain.head = card->tx_chain.head->next;
+
 	descr->buf_addr = buf;
 	descr->buf_size = skb->len;
 	descr->next_descr_addr = 0;
@@ -663,6 +668,8 @@ spider_net_prepare_tx_descr(struct spide
 
 	descr->dmac_cmd_status =
 			SPIDER_NET_DESCR_CARDOWNED | SPIDER_NET_DMAC_NOCS;
+	spin_unlock_irqrestore(&card->tx_chain.lock, flags);
+
 	if (skb->protocol == htons(ETH_P_IP))
 		switch (skb->nh.iph->protocol) {
 		case IPPROTO_TCP:
@@ -673,37 +680,16 @@ spider_net_prepare_tx_descr(struct spide
 			break;
 		}
 
+	/* Chain the bus address, so that the DMA engine finds this descr. */
 	descr->prev->next_descr_addr = descr->bus_addr;
 
 	return 0;
 }
 
-/**
- * spider_net_release_tx_descr - processes a used tx descriptor
- * @card: card structure
- * @descr: descriptor to release
- *
- * releases a used tx descriptor (unmapping, freeing of skb)
- */
-static inline void
-spider_net_release_tx_descr(struct spider_net_card *card)
-{
-	struct spider_net_descr *descr = card->tx_chain.tail;
-	struct sk_buff *skb;
-
-	card->tx_chain.tail = card->tx_chain.tail->next;
-	descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
-
-	/* unmap the skb */
-	skb = descr->skb;
-	pci_unmap_single(card->pdev, descr->buf_addr, skb->len,
-			PCI_DMA_TODEVICE);
-	dev_kfree_skb_any(skb);
-}
-
 static void
 spider_net_set_low_watermark(struct spider_net_card *card)
 {
+	unsigned long flags;
 	int status;
 	int cnt=0;
 	int i;
@@ -727,11 +713,13 @@ spider_net_set_low_watermark(struct spid
 		descr = descr->next;
 
 	/* Set the new watermark, clear the old wtermark */
+	spin_lock_irqsave(&card->tx_chain.lock, flags);
 	descr->dmac_cmd_status |= SPIDER_NET_DESCR_TXDESFLG;
 	if (card->low_watermark && card->low_watermark != descr)
 		card->low_watermark->dmac_cmd_status =
 		     card->low_watermark->dmac_cmd_status & ~SPIDER_NET_DESCR_TXDESFLG;
 	card->low_watermark = descr;
+	spin_unlock_irqrestore(&card->tx_chain.lock, flags);
 }
 
 /**
@@ -750,22 +738,30 @@ static int
 spider_net_release_tx_chain(struct spider_net_card *card, int brutal)
 {
 	struct spider_net_descr_chain *chain = &card->tx_chain;
+	struct spider_net_descr *descr;
+	struct sk_buff *skb;
+	u32 buf_addr;
+	unsigned long flags;
 	int status;
 	int rc=0;
 
 	spider_net_read_reg(card, SPIDER_NET_GDTDMACCNTR);
 
 	while (chain->tail != chain->head) {
-		status = spider_net_get_descr_status(chain->tail);
+		spin_lock_irqsave(&chain->lock, flags);
+		descr = chain->tail;
+
+		status = spider_net_get_descr_status(descr);
 		switch (status) {
 		case SPIDER_NET_DESCR_COMPLETE:
 			card->netdev_stats.tx_packets++;
-			card->netdev_stats.tx_bytes += chain->tail->skb->len;
+			card->netdev_stats.tx_bytes += descr->skb->len;
 			break;
 
 		case SPIDER_NET_DESCR_CARDOWNED:
 			if (!brutal) {
 				rc = 1;
+				spin_unlock_irqrestore(&chain->lock, flags);
 				goto done;
 			}
 			/* fallthrough, if we release the descriptors
@@ -785,9 +781,19 @@ spider_net_release_tx_chain(struct spide
 		default:
 			card->netdev_stats.tx_dropped++;
 			rc = 1;
+			spin_unlock_irqrestore(&chain->lock, flags);
 			goto done;
 		}
-		spider_net_release_tx_descr(card);
+
+		chain->tail = chain->tail->next;
+		descr->dmac_cmd_status |= SPIDER_NET_DESCR_NOT_IN_USE;
+		skb = descr->skb;
+		buf_addr = descr->buf_addr;
+		spin_unlock_irqrestore(&chain->lock, flags);
+
+		/* unmap the skb */
+		pci_unmap_single(card->pdev, buf_addr, skb->len, PCI_DMA_TODEVICE);
+		dev_kfree_skb_any(skb);
 	}
 done:
 	if (rc == 1)
@@ -844,11 +850,8 @@ spider_net_xmit(struct sk_buff *skb, str
 	struct spider_net_card *card = netdev_priv(netdev);
 	struct spider_net_descr_chain *chain = &card->tx_chain;
 	struct spider_net_descr *descr = chain->head;
-	unsigned long flags;
 	int result;
: 
-	spin_lock_irqsave(&chain->lock, flags);
-
 	spider_net_release_tx_chain(card, 0);
 
 	if (chain->head->next == chain->tail->prev) {
@@ -869,12 +872,9 @@ spider_net_xmit(struct sk_buff *skb, str
 	}
 
 	result = NETDEV_TX_OK;
-
 	spider_net_kick_tx_dma(card);
-	card->tx_chain.head = card->tx_chain.head->next;
 
 out:
-	spin_unlock_irqrestore(&chain->lock, flags);
 	netif_wake_queue(netdev);
 	return result;
 }
@@ -891,17 +891,11 @@ out:
 static void
 spider_net_cleanup_tx_ring(struct spider_net_card *card)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->tx_chain.lock, flags);
-
 	if ((spider_net_release_tx_chain(card, 0) != 0) &&
 	    (card->netdev->flags & IFF_UP)) {
 		spider_net_kick_tx_dma(card);
 		netif_wake_queue(card->netdev);
 	}
-
-	spin_unlock_irqrestore(&card->tx_chain.lock, flags);
 }
 
 static void
@@ -1932,10 +1926,7 @@ spider_net_stop(struct net_device *netde
 	spider_net_disable_rxdmac(card);
 
 	/* release chains */
-	if (spin_trylock(&card->tx_chain.lock)) {
-		spider_net_release_tx_chain(card, 1);
-		spin_unlock(&card->tx_chain.lock);
-	}
+	spider_net_release_tx_chain(card, 1);
 
 	spider_net_free_chain(card, &card->tx_chain);
 	spider_net_free_chain(card, &card->rx_chain);
Index: linux-2.6.18-rc3-mm2/drivers/net/spider_net.h
===================================================================
--- linux-2.6.18-rc3-mm2.orig/drivers/net/spider_net.h	2006-08-15 14:28:56.000000000 -0500
+++ linux-2.6.18-rc3-mm2/drivers/net/spider_net.h	2006-08-15 14:29:36.000000000 -0500
@@ -24,7 +24,7 @@
 #ifndef _SPIDER_NET_H
 #define _SPIDER_NET_H
 
-#define VERSION "1.1 B"
+#define VERSION "1.1 C"
 
 #include "sungem_phy.h"
 

^ permalink raw reply

* [PATCH 1/2]:  powerpc/cell spidernet bottom half
From: Linas Vepstas @ 2006-08-16 16:18 UTC (permalink / raw)
  To: netdev, linux-kernel, linuxppc-dev
  Cc: akpm, Jens Osterkamp, James K Lewis, jeff, Arnd Bergmann
In-Reply-To: <20060811170337.GH10638@austin.ibm.com>


Please apply and forward upstream. This patch requires the previous
sequence of 4 spidernet patches to be applied.

--linas


The recent set of low-waterark patches for the spider result in a
significant amount of computing being done in an interrupt context.
This patch moves this to a "bottom half" aka work queue, so that
the code runs in a normal kernel context. Curiously, this seems to 
result in a performance boost of about 5% for large packets.

Signed-off-by: Linas Vepstas <linas@austin.ibm.com>
Cc: Utz Bacher <utz.bacher@de.ibm.com>
Cc: Jens Osterkamp <Jens.Osterkamp@de.ibm.com>

----
 drivers/net/spider_net.c |   21 +++++++++++++++------
 drivers/net/spider_net.h |    4 +++-
 2 files changed, 18 insertions(+), 7 deletions(-)

Index: linux-2.6.18-rc3-mm2/drivers/net/spider_net.c
===================================================================
--- linux-2.6.18-rc3-mm2.orig/drivers/net/spider_net.c	2006-08-15 14:25:50.000000000 -0500
+++ linux-2.6.18-rc3-mm2/drivers/net/spider_net.c	2006-08-15 14:28:56.000000000 -0500
@@ -883,9 +883,10 @@ out:
  * spider_net_cleanup_tx_ring - cleans up the TX ring
  * @card: card structure
  *
- * spider_net_cleanup_tx_ring is called by the tx_timer (as we don't use
- * interrupts to cleanup our TX ring) and returns sent packets to the stack
- * by freeing them
+ * spider_net_cleanup_tx_ring is called by either the tx_timer
+ * or from a work-queue scheduled by the tx-empty interrupt.
+ * This routine releases resources associted with transmitted
+ * packets, including updating the queue tail pointer.
  */
 static void
 spider_net_cleanup_tx_ring(struct spider_net_card *card)
@@ -895,12 +896,20 @@ spider_net_cleanup_tx_ring(struct spider
 	spin_lock_irqsave(&card->tx_chain.lock, flags);
 
 	if ((spider_net_release_tx_chain(card, 0) != 0) &&
-	    (card->netdev->flags & IFF_UP))
+	    (card->netdev->flags & IFF_UP)) {
 		spider_net_kick_tx_dma(card);
+		netif_wake_queue(card->netdev);
+	}
 
 	spin_unlock_irqrestore(&card->tx_chain.lock, flags);
 }
 
+static void
+spider_net_tx_cleanup_task(void * data)
+{
+	spider_net_cleanup_tx_ring((struct spider_net_card *) data);
+}
+
 /**
  * spider_net_do_ioctl - called for device ioctls
  * @netdev: interface device structure
@@ -1499,8 +1508,7 @@ spider_net_interrupt(int irq, void *ptr,
 		netif_rx_schedule(netdev);
 	}
 	if (status_reg & SPIDER_NET_TXINT ) {
-		spider_net_cleanup_tx_ring(card);
-		netif_wake_queue(netdev);
+		schedule_work(&card->tx_cleanup_task);
 	}
 
 	if (status_reg & SPIDER_NET_ERRINT )
@@ -2117,6 +2125,7 @@ spider_net_alloc_card(void)
 	card->netdev = netdev;
 	card->msg_enable = SPIDER_NET_DEFAULT_MSG;
 	INIT_WORK(&card->tx_timeout_task, spider_net_tx_timeout_task, netdev);
+	INIT_WORK(&card->tx_cleanup_task, spider_net_tx_cleanup_task, card);
 	init_waitqueue_head(&card->waitq);
 	atomic_set(&card->tx_timeout_task_counter, 0);
 
Index: linux-2.6.18-rc3-mm2/drivers/net/spider_net.h
===================================================================
--- linux-2.6.18-rc3-mm2.orig/drivers/net/spider_net.h	2006-08-15 14:25:50.000000000 -0500
+++ linux-2.6.18-rc3-mm2/drivers/net/spider_net.h	2006-08-15 14:28:56.000000000 -0500
@@ -24,7 +24,7 @@
 #ifndef _SPIDER_NET_H
 #define _SPIDER_NET_H
 
-#define VERSION "1.1 A"
+#define VERSION "1.1 B"
 
 #include "sungem_phy.h"
 
@@ -441,6 +441,8 @@ struct spider_net_card {
 	atomic_t tx_timeout_task_counter;
 	wait_queue_head_t waitq;
 
+	struct work_struct tx_cleanup_task;
+
 	/* for ethtool */
 	int msg_enable;
 

^ permalink raw reply

* [PATCH] powerpc: Instrument Hypervisor Calls
From: Mike Kravetz @ 2006-08-16 16:04 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev

Add instrumentation for hypervisor calls on pseries.  Call statistics
include number of calls, wall time and cpu cycles (if available) and
are made available via debugfs.  Instrumentation code is behind the
HCALL_STATS config option and has no impact if not enabled.

-- 
Signed-off-by: Mike Kravetz <kravetz@us.ibm.com>

diff -Naupr powerpc2/arch/powerpc/Kconfig.debug powerpc2.work/arch/powerpc/Kconfig.debug
--- powerpc2/arch/powerpc/Kconfig.debug	2006-08-14 18:00:45.000000000 +0000
+++ powerpc2.work/arch/powerpc/Kconfig.debug	2006-08-15 18:45:57.000000000 +0000
@@ -18,6 +18,20 @@ config DEBUG_STACK_USAGE
 
 	  This option will slow down process creation somewhat.
 
+config HCALL_STATS
+	bool "Hypervisor call instrumentation"
+	depends on PPC_PSERIES && DEBUG_FS
+	help
+	  Adds code to keep track of the number of hypervisor calls made and
+	  the amount of time spent in hypervisor callsr.  Wall time spent in
+	  each call is always calculated, and if available CPU cycles spent
+	  are also calculated.  A directory named hcall_inst is added at the
+	  root of the debugfs filesystem.  Within the hcall_inst directory
+	  are files that contain CPU specific call statistics.
+
+	  This option will add a small amount of overhead to all hypervisor
+	  calls.
+
 config DEBUGGER
 	bool "Enable debugger hooks"
 	depends on DEBUG_KERNEL
diff -Naupr powerpc2/arch/powerpc/kernel/asm-offsets.c powerpc2.work/arch/powerpc/kernel/asm-offsets.c
--- powerpc2/arch/powerpc/kernel/asm-offsets.c	2006-08-14 18:00:46.000000000 +0000
+++ powerpc2.work/arch/powerpc/kernel/asm-offsets.c	2006-08-14 22:22:49.000000000 +0000
@@ -136,6 +136,7 @@ int main(void)
 	DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time));
 	DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time));
 	DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr));
+	DEFINE(PACA_DATA_OFFSET, offsetof(struct paca_struct, data_offset));
 
 	DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0));
 	DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1));
@@ -160,6 +161,12 @@ int main(void)
 	/* Create extra stack space for SRR0 and SRR1 when calling prom/rtas. */
 	DEFINE(PROM_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
 	DEFINE(RTAS_FRAME_SIZE, STACK_FRAME_OVERHEAD + sizeof(struct pt_regs) + 16);
+
+	/* hcall statistics */
+	DEFINE(HCALL_STAT_SIZE, sizeof(struct hcall_stats));
+	DEFINE(HCALL_STAT_CALLS, offsetof(struct hcall_stats, num_calls));
+	DEFINE(HCALL_STAT_TB, offsetof(struct hcall_stats, tb_total));
+	DEFINE(HCALL_STAT_PURR, offsetof(struct hcall_stats, purr_total));
 #endif /* CONFIG_PPC64 */
 	DEFINE(GPR0, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[0]));
 	DEFINE(GPR1, STACK_FRAME_OVERHEAD+offsetof(struct pt_regs, gpr[1]));
diff -Naupr powerpc2/arch/powerpc/platforms/pseries/Makefile powerpc2.work/arch/powerpc/platforms/pseries/Makefile
--- powerpc2/arch/powerpc/platforms/pseries/Makefile	2006-08-14 18:00:55.000000000 +0000
+++ powerpc2.work/arch/powerpc/platforms/pseries/Makefile	2006-08-14 21:31:45.000000000 +0000
@@ -12,3 +12,4 @@ obj-$(CONFIG_EEH)	+= eeh.o eeh_cache.o e
 
 obj-$(CONFIG_HVC_CONSOLE)	+= hvconsole.o
 obj-$(CONFIG_HVCS)		+= hvcserver.o
+obj-$(CONFIG_HCALL_STATS)	+= hvCall_inst.o
diff -Naupr powerpc2/arch/powerpc/platforms/pseries/hvCall.S powerpc2.work/arch/powerpc/platforms/pseries/hvCall.S
--- powerpc2/arch/powerpc/platforms/pseries/hvCall.S	2006-08-14 18:00:55.000000000 +0000
+++ powerpc2.work/arch/powerpc/platforms/pseries/hvCall.S	2006-08-15 19:06:10.000000000 +0000
@@ -10,9 +10,67 @@
 #include <asm/hvcall.h>
 #include <asm/processor.h>
 #include <asm/ppc_asm.h>
+#include <asm/asm-offsets.h>
 	
 #define STK_PARM(i)     (48 + ((i)-3)*8)
 
+#ifdef CONFIG_HCALL_STATS
+/*
+ * precall must preserve all registers.  use unused STK_PARM()
+ * areas to save snapshots and opcode.
+ */
+#define HCALL_INST_PRECALL					\
+	std	r3,STK_PARM(r3)(r1);	/* save opcode */	\
+	mftb	r3;			/* get timebase and */	\
+	std     r3,STK_PARM(r5)(r1);	/* save for later */	\
+BEGIN_FTR_SECTION;						\
+	mfspr	r3,SPRN_PURR;		/* get PURR and */	\
+	std	r3,STK_PARM(r6)(r1);	/* save for later */	\
+END_FTR_SECTION_IFSET(CPU_FTR_PURR);				\
+	ld	r3,STK_PARM(r3)(r1);	/* opcode back in r3 */
+	
+/*
+ * postcall is performed immediately before function return which
+ * allows liberal use of volital registers.
+ */
+#define HCALL_INST_POSTCALL					\
+	/* get time and PURR snapshots after hcall */		\
+	mftb	r7;			/* timebase after */	\
+BEGIN_FTR_SECTION;						\
+	mfspr	r8,SPRN_PURR;		/* PURR after */	\
+	ld	r6,STK_PARM(r6)(r1);	/* PURR before */	\
+	subf	r6,r6,r8;		/* delta */		\
+END_FTR_SECTION_IFSET(CPU_FTR_PURR);				\
+								\
+	ld	r5,STK_PARM(r5)(r1);	/* timebase before */	\
+	subf	r5,r5,r7;		/* time delta */	\
+								\
+	/* calculate address of stat structure */		\
+	ld	r4,STK_PARM(r3)(r1);	/* use opcode as */	\
+	rldicl	r4,r4,62,2;		/* index into array */	\
+	mulli	r4,r4,HCALL_STAT_SIZE;				\
+	LOAD_REG_ADDR(r7, per_cpu__hcall_stats);		\
+	add	r4,r4,r7;					\
+	ld	r7,PACA_DATA_OFFSET(r13); /* per cpu offset */	\
+	add	r4,r4,r7;					\
+								\
+	/* update stats	*/					\
+	ld	r7,HCALL_STAT_CALLS(r4); /* count */		\
+	addi	r7,r7,1;					\
+	std	r7,HCALL_STAT_CALLS(r4);			\
+	ld      r7,HCALL_STAT_TB(r4);	/* timebase */		\
+	add	r7,r7,r5;					\
+	std	r7,HCALL_STAT_TB(r4);				\
+BEGIN_FTR_SECTION;						\
+	ld	r7,HCALL_STAT_PURR(r4);	/* PURR */		\
+	add	r7,r7,r6;					\
+	std	r7,HCALL_STAT_PURR(r4);				\
+END_FTR_SECTION_IFSET(CPU_FTR_PURR);
+#else
+#define HCALL_INST_PRECALL
+#define HCALL_INST_POSTCALL
+#endif
+
 	.text
 
 _GLOBAL(plpar_hcall_norets)
@@ -21,8 +79,12 @@ _GLOBAL(plpar_hcall_norets)
 	mfcr	r0
 	stw	r0,8(r1)
 
+	HCALL_INST_PRECALL
+
 	HVSC				/* invoke the hypervisor */
 
+	HCALL_INST_POSTCALL
+
 	lwz	r0,8(r1)
 	mtcrf	0xff,r0
 	blr				/* return r3 = status */
@@ -33,6 +95,8 @@ _GLOBAL(plpar_hcall)
 	mfcr	r0
 	stw	r0,8(r1)
 
+	HCALL_INST_PRECALL
+
 	std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
 
 	mr	r4,r5
@@ -50,6 +114,8 @@ _GLOBAL(plpar_hcall)
 	std	r6, 16(r12)
 	std	r7, 24(r12)
 
+	HCALL_INST_POSTCALL
+
 	lwz	r0,8(r1)
 	mtcrf	0xff,r0
 
@@ -61,6 +127,8 @@ _GLOBAL(plpar_hcall9)
 	mfcr	r0
 	stw	r0,8(r1)
 
+	HCALL_INST_PRECALL
+
 	std     r4,STK_PARM(r4)(r1)     /* Save ret buffer */
 
 	mr	r4,r5
@@ -86,6 +154,8 @@ _GLOBAL(plpar_hcall9)
 	std	r11,56(r12)
 	std	r12,64(r12)
 
+	HCALL_INST_POSTCALL
+
 	lwz	r0,8(r1)
 	mtcrf	0xff,r0
 
diff -Naupr powerpc2/arch/powerpc/platforms/pseries/hvCall_inst.c powerpc2.work/arch/powerpc/platforms/pseries/hvCall_inst.c
--- powerpc2/arch/powerpc/platforms/pseries/hvCall_inst.c	1970-01-01 00:00:00.000000000 +0000
+++ powerpc2.work/arch/powerpc/platforms/pseries/hvCall_inst.c	2006-08-15 21:41:17.000000000 +0000
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2006 Mike Kravetz IBM Corporation
+ *
+ * Hypervisor Call Instrumentation
+ *
+ * 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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/percpu.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/cpumask.h>
+#include <asm/hvcall.h>
+#include <asm/firmware.h>
+#include <asm/cputable.h>
+
+DEFINE_PER_CPU(struct hcall_stats[MAX_HCALL_OPCODES+1], hcall_stats);
+
+/*
+ * Routines for displaying the statistics in debugfs
+ */
+static void *hc_start(struct seq_file *m, loff_t *pos)
+{
+	if ((int)*pos < (MAX_HCALL_OPCODES + 1))
+		return (void *)(unsigned long)(*pos + 1);
+
+	return NULL;
+}
+
+static void *hc_next(struct seq_file *m, void *p, loff_t * pos)
+{
+	++*pos;
+
+	return hc_start(m, pos);
+}
+
+static void hc_stop(struct seq_file *m, void *p)
+{
+}
+
+static int hc_show(struct seq_file *m, void *p)
+{
+	unsigned long h_num = (unsigned long)p;
+	struct hcall_stats *hs = (struct hcall_stats *)m->private;
+
+	if (hs[h_num].num_calls) {
+		if (cpu_has_feature(CPU_FTR_PURR))
+			seq_printf(m, "%lu %lu %lu %lu\n", h_num<<2,
+				   hs[h_num].num_calls,
+				   hs[h_num].tb_total,
+				   hs[h_num].purr_total);
+		else
+			seq_printf(m, "%lu %lu %lu\n", h_num<<2,
+				   hs[h_num].num_calls,
+				   hs[h_num].tb_total);
+	}
+
+	return 0;
+}
+
+static struct seq_operations hcall_inst_seq_ops = {
+        .start = hc_start,
+        .next  = hc_next,
+        .stop  = hc_stop,
+        .show  = hc_show
+};
+
+static int hcall_inst_seq_open(struct inode *inode, struct file *file)
+{
+	int rc;
+	struct seq_file *seq;
+
+	rc = seq_open(file, &hcall_inst_seq_ops);
+	seq = file->private_data;
+	seq->private = file->f_dentry->d_inode->u.generic_ip;
+
+	return rc;
+}
+
+static struct file_operations hcall_inst_seq_fops = {
+	.open = hcall_inst_seq_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+#define	HCALL_ROOT_DIR		"hcall_inst"
+#define CPU_NAME_BUF_SIZE	32
+
+static int __init hcall_inst_init(void)
+{
+	struct dentry *hcall_root;
+	struct dentry *hcall_file;
+	char cpu_name_buf[CPU_NAME_BUF_SIZE];
+	int cpu;
+
+	if (!firmware_has_feature(FW_FEATURE_LPAR))
+		return 0;
+
+	hcall_root = debugfs_create_dir(HCALL_ROOT_DIR, NULL);
+	if (!hcall_root)
+		return -ENOMEM;
+
+	for_each_possible_cpu(cpu) {
+		snprintf(cpu_name_buf, CPU_NAME_BUF_SIZE, "cpu%d", cpu);
+		hcall_file = debugfs_create_file(cpu_name_buf, S_IRUGO,
+						 hcall_root,
+						 per_cpu(hcall_stats, cpu),
+						 &hcall_inst_seq_fops);
+		if (!hcall_file)
+			return -ENOMEM;
+	}
+
+	return 0;
+}
+__initcall(hcall_inst_init);
diff -Naupr powerpc2/include/asm-powerpc/hvcall.h powerpc2.work/include/asm-powerpc/hvcall.h
--- powerpc2/include/asm-powerpc/hvcall.h	2006-08-14 18:05:16.000000000 +0000
+++ powerpc2.work/include/asm-powerpc/hvcall.h	2006-08-14 21:31:45.000000000 +0000
@@ -246,6 +246,15 @@ long plpar_hcall(unsigned long opcode, u
 #define PLPAR_HCALL9_BUFSIZE 9
 long plpar_hcall9(unsigned long opcode, unsigned long *retbuf, ...);
 
+/* For hcall instrumentation.  One structure per-hcall, per-CPU */
+struct hcall_stats {
+	unsigned long	num_calls;	/* number of calls (on this CPU) */
+	unsigned long	tb_total;	/* total wall time (mftb) of calls. */
+	unsigned long	purr_total;	/* total cpu time (PURR) of calls. */
+};
+void update_hcall_stats(unsigned long opcode, unsigned long tb_delta,
+			unsigned long purr_delta);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_HVCALL_H */

^ permalink raw reply

* Re: CPM2 UARTs: Won't work under low (<= 1200BD) baudrates?
From: Dan Malek @ 2006-08-16 15:42 UTC (permalink / raw)
  To: David Tao; +Cc: linuxppc-embedded
In-Reply-To: <20060815195203.37918.qmail@web32106.mail.mud.yahoo.com>


On Aug 15, 2006, at 3:52 PM, David Tao wrote:

> Under 2400 baud or above the UARTs work fine, but once the baudrate  
> set to 1200 or below, there is NO data can be sent out or received  
> even programed to do so.

It doesn't look like we check the baud rate and
add the preceding divide-by-16 clock for the
low baud rates like we did on the original CPM.
You can add this, test it, and submit a patch if
you like :-)

Thanks.

	-- Dan

^ permalink raw reply

* Re: [PATCH] powerpc: Make RTAS console init generic
From: Michael Neuling @ 2006-08-16 15:22 UTC (permalink / raw)
  To: michael; +Cc: linuxppc-dev, paulus, anton
In-Reply-To: <1155705695.12715.7.camel@localhost.localdomain>

In message <1155705695.12715.7.camel@localhost.localdomain> you wrote:
> 
> --=-PNKyW5KJv4630LcmkXVt
> Content-Type: text/plain
> Content-Transfer-Encoding: quoted-printable
> 
> On Tue, 2006-08-15 at 23:00 -0500, Michael Neuling wrote:
> > The RTAS console doesn't have to be Cell specific.  If we have both
> > the put and get char RTAS functions, init the rtas console.
> >=20
> > Index: linux-2.6-ozlabs/arch/powerpc/kernel/rtas.c
> > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> > --- linux-2.6-ozlabs.orig/arch/powerpc/kernel/rtas.c
> > +++ linux-2.6-ozlabs/arch/powerpc/kernel/rtas.c
> > @@ -910,6 +910,11 @@ int __init early_init_dt_scan_rtas(unsig
> >  	basep =3D of_get_flat_dt_prop(node, "get-term-char", NULL);
> >  	if (basep)
> >  		rtas_getchar_token =3D *basep;
> > +
> > +	if (rtas_putchar_token !=3D RTAS_UNKNOWN_SERVICE &&
> > +	    rtas_getchar_token !=3D RTAS_UNKNOWN_SERVICE)
> > +		udbg_init_rtas_console();
> > +
> >  #endif
> > =20
> >  	/* break now */
> > Index: linux-2.6-ozlabs/arch/powerpc/platforms/cell/setup.c
> > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
> > --- linux-2.6-ozlabs.orig/arch/powerpc/platforms/cell/setup.c
> > +++ linux-2.6-ozlabs/arch/powerpc/platforms/cell/setup.c
> > @@ -150,10 +150,6 @@ static int __init cell_probe(void)
> >  	    !of_flat_dt_is_compatible(root, "IBM,CPBW-1.0"))
> >  		return 0;
> > =20
> > -#ifdef CONFIG_UDBG_RTAS_CONSOLE
> > -	udbg_init_rtas_console();
> > -#endif
> > -
> 
> I'd like to see it still guarded by UDBG_RTAS_CONSOLE, otherwise there's
> no way to select a different type of early console on a machine which
> has those tokens in the device tree.

Agreed but that section in rtas.c is already guarded by
UDBG_RTAS_CONSOLE.  After applying the patch, it looks like: 

#ifdef CONFIG_UDBG_RTAS_CONSOLE
	basep = of_get_flat_dt_prop(node, "put-term-char", NULL);
	if (basep)
		rtas_putchar_token = *basep;

	basep = of_get_flat_dt_prop(node, "get-term-char", NULL);
	if (basep)
		rtas_getchar_token = *basep;

	if (rtas_putchar_token != RTAS_UNKNOWN_SERVICE &&
	    rtas_getchar_token != RTAS_UNKNOWN_SERVICE)
		udbg_init_rtas_console();

#endif

Mikey

^ permalink raw reply

* Re: 2.6.18-rc3->rc4 hugetlbfs regression
From: Adam Litke @ 2006-08-16 15:00 UTC (permalink / raw)
  To: Dave Hansen
  Cc: Suzuki Kp, PPC External List, Linux Kernel Mailing List, linux-mm,
	Yao Fei Zhu, lge, Nishanth Aravamudan
In-Reply-To: <1155655344.12700.45.camel@localhost.localdomain>

On Tue, 2006-08-15 at 08:22 -0700, Dave Hansen wrote:
> kernel BUG in cache_free_debugcheck at mm/slab.c:2748!

Alright, this one is only triggered when slab debugging is enabled.  The slabs
are assumed to be aligned on a HUGEPTE_TABLE_SIZE boundary.  The free path
makes use of this assumption and uses the lowest nibble to pass around an index
into an array of kmem_cache pointers.  With slab debugging turned on, the slab
is still aligned, but the "working" object pointer is not.  This would break
the assumption above that a full nibble is available for the PGF_CACHENUM_MASK.

The following patch reduces PGF_CACHENUM_MASK to cover only the two least
significant bits, which is enough to cover the current number of 4 pgtable
cache types.  Then use this constant to mask out the appropriate part of the
huge pte pointer.

Signed-off-by: Adam Litke <agl@us.ibm.com>
---
 arch/powerpc/mm/hugetlbpage.c |    2 +-
 include/asm-powerpc/pgalloc.h |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
diff -upN reference/arch/powerpc/mm/hugetlbpage.c current/arch/powerpc/mm/hugetlbpage.c
--- reference/arch/powerpc/mm/hugetlbpage.c
+++ current/arch/powerpc/mm/hugetlbpage.c
@@ -153,7 +153,7 @@ static void free_hugepte_range(struct mm
 	hpdp->pd = 0;
 	tlb->need_flush = 1;
 	pgtable_free_tlb(tlb, pgtable_free_cache(hugepte, HUGEPTE_CACHE_NUM,
-						 HUGEPTE_TABLE_SIZE-1));
+						 PGF_CACHENUM_MASK));
 }
 
 #ifdef CONFIG_PPC_64K_PAGES
diff -upN reference/include/asm-powerpc/pgalloc.h current/include/asm-powerpc/pgalloc.h
--- reference/include/asm-powerpc/pgalloc.h
+++ current/include/asm-powerpc/pgalloc.h
@@ -117,7 +117,7 @@ static inline void pte_free(struct page 
 	pte_free_kernel(page_address(ptepage));
 }
 
-#define PGF_CACHENUM_MASK	0xf
+#define PGF_CACHENUM_MASK	0x3
 
 typedef struct pgtable_free {
 	unsigned long val;


-- 
Adam Litke - (agl at us.ibm.com)
IBM Linux Technology Center

^ permalink raw reply

* Re: PowerPC paxtest results w/ gcc-4.1
From: Albert Cahalan @ 2006-08-16 14:43 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: debian-powerpc, linuxppc-dev
In-Reply-To: <17634.64640.709200.871907@cargo.ozlabs.ibm.com>

On 8/16/06, Paul Mackerras <paulus@samba.org> wrote:
> Gabriel Paubert writes:

> > BTW, there is one way to make pages non executable: mark
> > them as guarded, but it will have a significant cost in
> > terms of performance.
>
> Indeed.  I guess we could do that as a config option for machines that
> really want maximum security at the expense of performance, but I
> don't think all users would want that.

On the other hand, if you want to squeeze some performance
out of the chip, turn off coherency. (probably not for SMP)

I've done it before, with a non-Linux OS. It does help.

Other tricks are to map userspace via BATs and, on the 7410
at least, to map half or all of the outermost cache memory as
a special block of high-speed memory.

^ permalink raw reply

* Re: Problems dynamically linking busybox with ppc libs.
From: Ben Warren @ 2006-08-16 14:13 UTC (permalink / raw)
  To: Keith Redfern; +Cc: linuxppc-embedded
In-Reply-To: <367F3B3911959C4DA9991C00166F620C1DE208@EUDUCEX2.europe.ad.flextronics.com>

Keith,

On Wed, 2006-08-16 at 10:53 +0200, Keith Redfern wrote:
> I am trying to dynamically link busybox with the correct libraries but
> run into problems with directory paths and CC/LD flags.
> 
> I am using the toolchain supplied with ELDK and my target board is
> ppc_8xx based. The busybox version that I am using is 1.1.3.
> 
<snip>
> 
> Is this the correct place to make modifications?
> 
> Has anyone already figured the changes required to get this to work
> with ELDK toolchain?
> 
> Any insight would be useful.
> 
>  
> 
> ...…Keith

I have busybox 1.2 building under ELDK 4.0, and didn't mess at all with
the Make system, and am building for a ppc_6xx- target.  I realize this
isn't quite your setup, but is pretty close.

As long as you have the tools listed in your PATH (in my
case /opt/tools/eldk4.0/usr/bin:/opt/tools/eldk4.0/bin), you should be
able to build fine using 'make menuconfig'.  Just go to 'Busybox
Settings->Build Options' and select 'Do you want to build BusyBox with a
Cross Compiler?', in your case entering 'ppc_8xx-' or whatever the
prefix is for your CPU.

regards,
Ben

^ 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