Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 3870
b: refs/heads/master
c: fa0ebff
h: refs/heads/master
v: v3
  • Loading branch information
Richard Purdie authored and Russell King committed Jun 28, 2005
1 parent 13cb8b2 commit 3cca659
Show file tree
Hide file tree
Showing 91 changed files with 3,424 additions and 2,587 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: adb2705a89e8b41abcf29c0ed86f4ce93ab36734
refs/heads/master: fa0ebff62a8a25952a082641db0ed6b1cfc6c38c
96 changes: 3 additions & 93 deletions trunk/Documentation/DocBook/libata.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,6 @@ void (*port_disable) (struct ata_port *);
Called from ata_bus_probe() and ata_bus_reset() error paths,
as well as when unregistering from the SCSI module (rmmod, hot
unplug).
This function should do whatever needs to be done to take the
port out of use. In most cases, ata_port_disable() can be used
as this hook.
</para>
<para>
Called from ata_bus_probe() on a failed probe.
Called from ata_bus_reset() on a failed bus reset.
Called from ata_scsi_release().
</para>

</sect2>
Expand All @@ -106,13 +98,6 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
found. Typically used to apply device-specific fixups prior to
issue of SET FEATURES - XFER MODE, and prior to operation.
</para>
<para>
Called by ata_device_add() after ata_dev_identify() determines
a device is present.
</para>
<para>
This entry may be specified as NULL in ata_port_operations.
</para>

</sect2>

Expand Down Expand Up @@ -150,8 +135,6 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
registers / DMA buffers. ->tf_read() is called to read the
hardware registers / DMA buffers, to obtain the current set of
taskfile register values.
Most drivers for taskfile-based hardware (PIO or MMIO) use
ata_tf_load() and ata_tf_read() for these hooks.
</para>

</sect2>
Expand All @@ -164,8 +147,6 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
<para>
causes an ATA command, previously loaded with
->tf_load(), to be initiated in hardware.
Most drivers for taskfile-based hardware use ata_exec_command()
for this hook.
</para>

</sect2>
Expand All @@ -180,10 +161,6 @@ Allow low-level driver to filter ATA PACKET commands, returning a status
indicating whether or not it is OK to use DMA for the supplied PACKET
command.
</para>
<para>
This hook may be specified as NULL, in which case libata will
assume that atapi dma can be supported.
</para>

</sect2>

Expand All @@ -198,14 +175,6 @@ u8 (*check_err)(struct ata_port *ap);
Reads the Status/AltStatus/Error ATA shadow register from
hardware. On some hardware, reading the Status register has
the side effect of clearing the interrupt condition.
Most drivers for taskfile-based hardware use
ata_check_status() for this hook.
</para>
<para>
Note that because this is called from ata_device_add(), at
least a dummy function that clears device interrupts must be
provided for all drivers, even if the controller doesn't
actually have a taskfile status register.
</para>

</sect2>
Expand All @@ -219,13 +188,7 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
Issues the low-level hardware command(s) that causes one of N
hardware devices to be considered 'selected' (active and
available for use) on the ATA bus. This generally has no
meaning on FIS-based devices.
</para>
<para>
Most drivers for taskfile-based hardware use
ata_std_dev_select() for this hook. Controllers which do not
support second drives on a port (such as SATA contollers) will
use ata_noop_dev_select().
meaning on FIS-based devices.
</para>

</sect2>
Expand All @@ -241,8 +204,6 @@ void (*phy_reset) (struct ata_port *ap);
for device presence (PATA and SATA), typically a soft reset
(SRST) will be performed. Drivers typically use the helper
functions ata_bus_reset() or sata_phy_reset() for this hook.
Many SATA drivers use sata_phy_reset() or call it from within
their own phy_reset() functions.
</para>

</sect2>
Expand All @@ -266,25 +227,6 @@ PCI IDE DMA Status register.
These hooks are typically either no-ops, or simply not implemented, in
FIS-based drivers.
</para>
<para>
Most legacy IDE drivers use ata_bmdma_setup() for the bmdma_setup()
hook. ata_bmdma_setup() will write the pointer to the PRD table to
the IDE PRD Table Address register, enable DMA in the DMA Command
register, and call exec_command() to begin the transfer.
</para>
<para>
Most legacy IDE drivers use ata_bmdma_start() for the bmdma_start()
hook. ata_bmdma_start() will write the ATA_DMA_START flag to the DMA
Command register.
</para>
<para>
Many legacy IDE drivers use ata_bmdma_stop() for the bmdma_stop()
hook. ata_bmdma_stop() clears the ATA_DMA_START flag in the DMA
command register.
</para>
<para>
Many legacy IDE drivers use ata_bmdma_status() as the bmdma_status() hook.
</para>

</sect2>

Expand All @@ -308,10 +250,6 @@ int (*qc_issue) (struct ata_queued_cmd *qc);
helper function ata_qc_issue_prot() for taskfile protocol-based
dispatch. More advanced drivers implement their own ->qc_issue.
</para>
<para>
ata_qc_issue_prot() calls ->tf_load(), ->bmdma_setup(), and
->bmdma_start() as necessary to initiate a transfer.
</para>

</sect2>

Expand Down Expand Up @@ -341,21 +279,6 @@ void (*irq_clear) (struct ata_port *);
before the interrupt handler is registered, to be sure hardware
is quiet.
</para>
<para>
The second argument, dev_instance, should be cast to a pointer
to struct ata_host_set.
</para>
<para>
Most legacy IDE drivers use ata_interrupt() for the
irq_handler hook, which scans all ports in the host_set,
determines which queued command was active (if any), and calls
ata_host_intr(ap,qc).
</para>
<para>
Most legacy IDE drivers use ata_bmdma_irq_clear() for the
irq_clear() hook, which simply clears the interrupt and error
flags in the DMA status register.
</para>

</sect2>

Expand All @@ -369,7 +292,6 @@ void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
<para>
Read and write standard SATA phy registers. Currently only used
if ->phy_reset hook called the sata_phy_reset() helper function.
sc_reg is one of SCR_STATUS, SCR_CONTROL, SCR_ERROR, or SCR_ACTIVE.
</para>

</sect2>
Expand All @@ -385,29 +307,17 @@ void (*host_stop) (struct ata_host_set *host_set);
->port_start() is called just after the data structures for each
port are initialized. Typically this is used to alloc per-port
DMA buffers / tables / rings, enable DMA engines, and similar
tasks. Some drivers also use this entry point as a chance to
allocate driver-private memory for ap->private_data.
</para>
<para>
Many drivers use ata_port_start() as this hook or call
it from their own port_start() hooks. ata_port_start()
allocates space for a legacy IDE PRD table and returns.
tasks.
</para>
<para>
->port_stop() is called after ->host_stop(). It's sole function
is to release DMA/memory resources, now that they are no longer
actively being used. Many drivers also free driver-private
data from port at this time.
</para>
<para>
Many drivers use ata_port_stop() as this hook, which frees the
PRD table.
actively being used.
</para>
<para>
->host_stop() is called after all ->port_stop() calls
have completed. The hook must finalize hardware shutdown, release DMA
and other resources, etc.
This hook may be specified as NULL, in which case it is not called.
</para>

</sect2>
Expand Down
4 changes: 0 additions & 4 deletions trunk/Documentation/kernel-parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1030,10 +1030,6 @@ running once the system is up.
irqmask=0xMMMM [IA-32] Set a bit mask of IRQs allowed to be assigned
automatically to PCI devices. You can make the kernel
exclude IRQs of your ISA cards this way.
pirqaddr=0xAAAAA [IA-32] Specify the physical address
of the PIRQ table (normally generated
by the BIOS) if it is outside the
F0000h-100000h range.
lastbus=N [IA-32] Scan all buses till bus #N. Can be useful
if the kernel is unable to find your secondary buses
and you want to tell it explicitly which ones they are.
Expand Down
2 changes: 1 addition & 1 deletion trunk/arch/arm/oprofile/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ DRIVER_OBJS = $(addprefix ../../../drivers/oprofile/, \
oprofilefs.o oprofile_stats.o \
timer_int.o )

oprofile-y := $(DRIVER_OBJS) init.o
oprofile-y := $(DRIVER_OBJS) init.o backtrace.o
oprofile-$(CONFIG_CPU_XSCALE) += common.o op_model_xscale.o

144 changes: 144 additions & 0 deletions trunk/arch/arm/oprofile/backtrace.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Arm specific backtracing code for oprofile
*
* Copyright 2005 Openedhand Ltd.
*
* Author: Richard Purdie <rpurdie@openedhand.com>
*
* Based on i386 oprofile backtrace code by John Levon, David Smith
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/

#include <linux/oprofile.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <asm/ptrace.h>
#include <asm/uaccess.h>


/*
* The registers we're interested in are at the end of the variable
* length saved register structure. The fp points at the end of this
* structure so the address of this struct is:
* (struct frame_tail *)(xxx->fp)-1
*/
struct frame_tail {
struct frame_tail *fp;
unsigned long sp;
unsigned long lr;
} __attribute__((packed));


#ifdef CONFIG_FRAME_POINTER
static struct frame_tail* kernel_backtrace(struct frame_tail *tail)
{
oprofile_add_trace(tail->lr);

/* frame pointers should strictly progress back up the stack
* (towards higher addresses) */
if (tail >= tail->fp)
return NULL;

return tail->fp-1;
}
#endif

static struct frame_tail* user_backtrace(struct frame_tail *tail)
{
struct frame_tail buftail;

/* hardware pte might not be valid due to dirty/accessed bit emulation
* so we use copy_from_user and benefit from exception fixups */
if (copy_from_user(&buftail, tail, sizeof(struct frame_tail)))
return NULL;

oprofile_add_trace(buftail.lr);

/* frame pointers should strictly progress back up the stack
* (towards higher addresses) */
if (tail >= buftail.fp)
return NULL;

return buftail.fp-1;
}

/* Compare two addresses and see if they're on the same page */
#define CMP_ADDR_EQUAL(x,y,offset) ((((unsigned long) x) >> PAGE_SHIFT) \
== ((((unsigned long) y) + offset) >> PAGE_SHIFT))

/* check that the page(s) containing the frame tail are present */
static int pages_present(struct frame_tail *tail)
{
struct mm_struct * mm = current->mm;

if (!check_user_page_readable(mm, (unsigned long)tail))
return 0;

if (CMP_ADDR_EQUAL(tail, tail, 8))
return 1;

if (!check_user_page_readable(mm, ((unsigned long)tail) + 8))
return 0;

return 1;
}

/*
* | | /\ Higher addresses
* | |
* --------------- stack base (address of current_thread_info)
* | thread info |
* . .
* | stack |
* --------------- saved regs->ARM_fp value if valid (frame_tail address)
* . .
* --------------- struct pt_regs stored on stack (struct pt_regs *)
* | |
* . .
* | |
* --------------- %esp
* | |
* | | \/ Lower addresses
*
* Thus, &pt_regs <-> stack base restricts the valid(ish) fp values
*/
static int valid_kernel_stack(struct frame_tail *tail, struct pt_regs *regs)
{
unsigned long tailaddr = (unsigned long)tail;
unsigned long stack = (unsigned long)regs;
unsigned long stack_base = (stack & ~(THREAD_SIZE - 1)) + THREAD_SIZE;

return (tailaddr > stack) && (tailaddr < stack_base);
}

void arm_backtrace(struct pt_regs const *regs, unsigned int depth)
{
struct frame_tail *tail;
unsigned long last_address = 0;

tail = ((struct frame_tail *) regs->ARM_fp) - 1;

if (!user_mode(regs)) {

#ifdef CONFIG_FRAME_POINTER
while (depth-- && tail && valid_kernel_stack(tail, regs)) {
tail = kernel_backtrace(tail);
}
#endif
return;
}

while (depth-- && tail && !((unsigned long) tail & 3)) {
if ((!CMP_ADDR_EQUAL(last_address, tail, 0)
|| !CMP_ADDR_EQUAL(last_address, tail, 8))
&& !pages_present(tail))
return;
last_address = (unsigned long) tail;
tail = user_backtrace(tail);
}
}

2 changes: 2 additions & 0 deletions trunk/arch/arm/oprofile/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
ret = pmu_init(ops, &op_xscale_spec);
#endif

ops->backtrace = arm_backtrace;

return ret;
}

Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/arm/oprofile/op_arm_model.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ struct op_arm_model_spec {
extern struct op_arm_model_spec op_xscale_spec;
#endif

extern void arm_backtrace(struct pt_regs * const regs, unsigned int depth);

extern int __init pmu_init(struct oprofile_operations *ops, struct op_arm_model_spec *spec);
extern void pmu_exit(void);
#endif /* OP_ARM_MODEL_H */
Loading

0 comments on commit 3cca659

Please sign in to comment.