$(call cmd,db2pdf)
-main_idx = Documentation/DocBook/index.html
+index = index.html
+main_idx = Documentation/DocBook/$(index)
build_main_index = rm -rf $(main_idx) && \
echo '<h1>Linux Kernel HTML Documentation</h1>' >> $(main_idx) && \
echo '<h2>Kernel Version: $(KERNELVERSION)</h2>' >> $(main_idx) && \
$(patsubst %.xml, %.pdf, $(DOCBOOKS)) \
$(patsubst %.xml, %.html, $(DOCBOOKS)) \
$(patsubst %.xml, %.9, $(DOCBOOKS)) \
- $(C-procfs-example)
+ $(C-procfs-example) $(index)
clean-dirs := $(patsubst %.xml,%,$(DOCBOOKS)) man
BKL mmap_sem PageLocked(page)
open: no yes
close: no yes
-fault: no yes
-page_mkwrite: no yes no
+fault: no yes can return with page locked
+page_mkwrite: no yes can return with page locked
access: no yes
- ->page_mkwrite() is called when a previously read-only page is
-about to become writeable. The file system is responsible for
-protecting against truncate races. Once appropriate action has been
-taking to lock out truncate, the page range should be verified to be
-within i_size. The page mapping should also be checked that it is not
-NULL.
+ ->fault() is called when a previously not present pte is about
+to be faulted in. The filesystem must find and return the page associated
+with the passed in "pgoff" in the vm_fault structure. If it is possible that
+the page may be truncated and/or invalidated, then the filesystem must lock
+the page, then ensure it is not already truncated (the page lock will block
+subsequent truncate), and then return with VM_FAULT_LOCKED, and the page
+locked. The VM will unlock the page.
+
+ ->page_mkwrite() is called when a previously read-only pte is
+about to become writeable. The filesystem again must ensure that there are
+no truncate/invalidate races, and then return with the page locked. If
+the page has been truncated, the filesystem should not look up a new page
+like the ->fault() handler, but simply return with VM_FAULT_NOPAGE, which
+will cause the VM to retry the fault.
->access() is called when get_user_pages() fails in
acces_process_vm(), typically used to debug a process through
--- /dev/null
+BCM5974 Driver (bcm5974)
+------------------------
+ Copyright (C) 2008-2009 Henrik Rydberg <rydberg@euromail.se>
+
+The USB initialization and package decoding was made by Scott Shawcroft as
+part of the touchd user-space driver project:
+ Copyright (C) 2008 Scott Shawcroft (scott.shawcroft@gmail.com)
+
+The BCM5974 driver is based on the appletouch driver:
+ Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ Copyright (C) 2005 Johannes Berg (johannes@sipsolutions.net)
+ Copyright (C) 2005 Stelian Pop (stelian@popies.net)
+ Copyright (C) 2005 Frank Arnold (frank@scirocco-5v-turbo.de)
+ Copyright (C) 2005 Peter Osterlund (petero2@telia.com)
+ Copyright (C) 2005 Michael Hanselmann (linux-kernel@hansmi.ch)
+ Copyright (C) 2006 Nicolas Boichat (nicolas@boichat.ch)
+
+This driver adds support for the multi-touch trackpad on the new Apple
+Macbook Air and Macbook Pro laptops. It replaces the appletouch driver on
+those computers, and integrates well with the synaptics driver of the Xorg
+system.
+
+Known to work on Macbook Air, Macbook Pro Penryn and the new unibody
+Macbook 5 and Macbook Pro 5.
+
+Usage
+-----
+
+The driver loads automatically for the supported usb device ids, and
+becomes available both as an event device (/dev/input/event*) and as a
+mouse via the mousedev driver (/dev/input/mice).
+
+USB Race
+--------
+
+The Apple multi-touch trackpads report both mouse and keyboard events via
+different interfaces of the same usb device. This creates a race condition
+with the HID driver, which, if not told otherwise, will find the standard
+HID mouse and keyboard, and claim the whole device. To remedy, the usb
+product id must be listed in the mouse_ignore list of the hid driver.
+
+Debug output
+------------
+
+To ease the development for new hardware version, verbose packet output can
+be switched on with the debug kernel module parameter. The range [1-9]
+yields different levels of verbosity. Example (as root):
+
+echo -n 9 > /sys/module/bcm5974/parameters/debug
+
+tail -f /var/log/debug
+
+echo -n 0 > /sys/module/bcm5974/parameters/debug
+
+Trivia
+------
+
+The driver was developed at the ubuntu forums in June 2008 [1], and now has
+a more permanent home at bitmath.org [2].
+
+Links
+-----
+
+[1] http://ubuntuforums.org/showthread.php?t=840040
+[2] http://http://bitmath.org/code/
--- /dev/null
+Multi-touch (MT) Protocol
+-------------------------
+ Copyright (C) 2009 Henrik Rydberg <rydberg@euromail.se>
+
+
+Introduction
+------------
+
+In order to utilize the full power of the new multi-touch devices, a way to
+report detailed finger data to user space is needed. This document
+describes the multi-touch (MT) protocol which allows kernel drivers to
+report details for an arbitrary number of fingers.
+
+
+Usage
+-----
+
+Anonymous finger details are sent sequentially as separate packets of ABS
+events. Only the ABS_MT events are recognized as part of a finger
+packet. The end of a packet is marked by calling the input_mt_sync()
+function, which generates a SYN_MT_REPORT event. The end of multi-touch
+transfer is marked by calling the usual input_sync() function.
+
+A set of ABS_MT events with the desired properties is defined. The events
+are divided into categories, to allow for partial implementation. The
+minimum set consists of ABS_MT_TOUCH_MAJOR, ABS_MT_POSITION_X and
+ABS_MT_POSITION_Y, which allows for multiple fingers to be tracked. If the
+device supports it, the ABS_MT_WIDTH_MAJOR may be used to provide the size
+of the approaching finger. Anisotropy and direction may be specified with
+ABS_MT_TOUCH_MINOR, ABS_MT_WIDTH_MINOR and ABS_MT_ORIENTATION. Devices with
+more granular information may specify general shapes as blobs, i.e., as a
+sequence of rectangular shapes grouped together by an
+ABS_MT_BLOB_ID. Finally, the ABS_MT_TOOL_TYPE may be used to specify
+whether the touching tool is a finger or a pen or something else.
+
+
+Event Semantics
+---------------
+
+The word "contact" is used to describe a tool which is in direct contact
+with the surface. A finger, a pen or a rubber all classify as contacts.
+
+ABS_MT_TOUCH_MAJOR
+
+The length of the major axis of the contact. The length should be given in
+surface units. If the surface has an X times Y resolution, the largest
+possible value of ABS_MT_TOUCH_MAJOR is sqrt(X^2 + Y^2), the diagonal.
+
+ABS_MT_TOUCH_MINOR
+
+The length, in surface units, of the minor axis of the contact. If the
+contact is circular, this event can be omitted.
+
+ABS_MT_WIDTH_MAJOR
+
+The length, in surface units, of the major axis of the approaching
+tool. This should be understood as the size of the tool itself. The
+orientation of the contact and the approaching tool are assumed to be the
+same.
+
+ABS_MT_WIDTH_MINOR
+
+The length, in surface units, of the minor axis of the approaching
+tool. Omit if circular.
+
+The above four values can be used to derive additional information about
+the contact. The ratio ABS_MT_TOUCH_MAJOR / ABS_MT_WIDTH_MAJOR approximates
+the notion of pressure. The fingers of the hand and the palm all have
+different characteristic widths [1].
+
+ABS_MT_ORIENTATION
+
+The orientation of the ellipse. The value should describe half a revolution
+clockwise around the touch center. The scale of the value is arbitrary, but
+zero should be returned for an ellipse aligned along the Y axis of the
+surface. As an example, an index finger placed straight onto the axis could
+return zero orientation, something negative when twisted to the left, and
+something positive when twisted to the right. This value can be omitted if
+the touching object is circular, or if the information is not available in
+the kernel driver.
+
+ABS_MT_POSITION_X
+
+The surface X coordinate of the center of the touching ellipse.
+
+ABS_MT_POSITION_Y
+
+The surface Y coordinate of the center of the touching ellipse.
+
+ABS_MT_TOOL_TYPE
+
+The type of approaching tool. A lot of kernel drivers cannot distinguish
+between different tool types, such as a finger or a pen. In such cases, the
+event should be omitted. The protocol currently supports MT_TOOL_FINGER and
+MT_TOOL_PEN [2].
+
+ABS_MT_BLOB_ID
+
+The BLOB_ID groups several packets together into one arbitrarily shaped
+contact. This is a low-level anonymous grouping, and should not be confused
+with the high-level contactID, explained below. Most kernel drivers will
+not have this capability, and can safely omit the event.
+
+
+Finger Tracking
+---------------
+
+The kernel driver should generate an arbitrary enumeration of the set of
+anonymous contacts currently on the surface. The order in which the packets
+appear in the event stream is not important.
+
+The process of finger tracking, i.e., to assign a unique contactID to each
+initiated contact on the surface, is left to user space; preferably the
+multi-touch X driver [3]. In that driver, the contactID stays the same and
+unique until the contact vanishes (when the finger leaves the surface). The
+problem of assigning a set of anonymous fingers to a set of identified
+fingers is a euclidian bipartite matching problem at each event update, and
+relies on a sufficiently rapid update rate.
+
+Notes
+-----
+
+In order to stay compatible with existing applications, the data
+reported in a finger packet must not be recognized as single-touch
+events. In addition, all finger data must bypass input filtering,
+since subsequent events of the same type refer to different fingers.
+
+The first kernel driver to utilize the MT protocol is the bcm5974 driver,
+where examples can be found.
+
+[1] With the extension ABS_MT_APPROACH_X and ABS_MT_APPROACH_Y, the
+difference between the contact position and the approaching tool position
+could be used to derive tilt.
+[2] The list can of course be extended.
+[3] The multi-touch X driver is currently in the prototyping stage. At the
+time of writing (April 2009), the MT protocol is not yet merged, and the
+prototype implements finger matching, basic mouse support and two-finger
+scrolling. The project aims at improving the quality of current multi-touch
+functionality available in the synaptics X driver, and in addition
+implement more advanced gestures.
Inside a struct description, you can use the "private:" and "public:"
comment tags. Structure fields that are inside a "private:" area
-are not listed in the generated output documentation.
+are not listed in the generated output documentation. The "private:"
+and "public:" tags must begin immediately following a "/*" comment
+marker. They may optionally include comments between the ":" and the
+ending "*/" marker.
Example:
struct my_struct {
int a;
int b;
-/* private: */
+/* private: internal use only */
int c;
};
usbcore.blinkenlights=1
+Hyphens (dashes) and underscores are equivalent in parameter names, so
+ log_buf_len=1M print-fatal-signals=1
+can also be entered as
+ log-buf-len=1M print_fatal_signals=1
+
+
This document may not be entirely up to date and comprehensive. The command
"modinfo -p ${modulename}" shows a current list of all parameters of a loadable
module. Loadable modules, after being loaded into the running kernel, also
not play well with APC CPU idle - disable it if you have
APC and your system crashes randomly.
- apic= [APIC,i386] Advanced Programmable Interrupt Controller
+ apic= [APIC,X86-32] Advanced Programmable Interrupt Controller
Change the output verbosity whilst booting
Format: { quiet (default) | verbose | debug }
Change the amount of debugging information output
to discrete, to make X server driver able to add WB
entry later. This parameter enables that.
- enable_timer_pin_1 [i386,x86-64]
+ enable_timer_pin_1 [X86]
Enable PIN 1 of APIC timer
Can be useful to work around chipset bugs
(in particular on some ATI chipsets).
hashdist= [KNL,NUMA] Large hashes allocated during boot
are distributed across NUMA nodes. Defaults on
- for IA-64, off otherwise.
+ for 64bit NUMA, off otherwise.
Format: 0 | 1 (for off | on)
hcl= [IA-64] SGI's Hardware Graph compatibility layer
The bit position indicates STATE, STATE-read, for each of the states listed
above, and the character displayed in each indicates:
- '.' acquired while irqs disabled
- '+' acquired in irq context
- '-' acquired with irqs enabled
+ '.' acquired while irqs disabled and not in irq context
+ '-' acquired in irq context
+ '+' acquired with irqs enabled
'?' acquired in irq context with irqs enabled.
Unused mutexes cannot be part of the cause of an error.
If dirty_bytes is written, dirty_ratio becomes a function of its value
(dirty_bytes / the amount of dirtyable system memory).
+Note: the minimum value allowed for dirty_bytes is two pages (in bytes); any
+value lower than this limit will be ignored and the old configuration will be
+retained.
+
==============================================================
dirty_expire_centisecs
S: Maintained
LINUX FOR POWERPC EMBEDDED MPC5XXX
-P: Sylvain Munaut
-M: tnt@246tNt.com
P: Grant Likely
M: grant.likely@secretlab.ca
L: linuxppc-dev@ozlabs.org
+T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
LINUX FOR POWERPC EMBEDDED PPC4XX
M: grant.likely@secretlab.ca
W: http://wiki.secretlab.ca/index.php/Linux_on_Xilinx_Virtex
L: linuxppc-dev@ozlabs.org
+T: git git://git.secretlab.ca/git/linux-2.6.git
S: Maintained
LINUX FOR POWERPC EMBEDDED PPC8XX
M: joel.becker@oracle.com
L: ocfs2-devel@oss.oracle.com (moderated for non-subscribers)
W: http://oss.oracle.com/projects/ocfs2/
-T: git git://git.kernel.org/pub/scm/linux/kernel/git/mfasheh/ocfs2.git
+T: git git://git.kernel.org/pub/scm/linux/kernel/git/jlbec/ocfs2.git
S: Supported
F: Documentation/filesystems/ocfs2.txt
F: Documentation/filesystems/dlmfs.txt
L: cbe-oss-dev@ozlabs.org
S: Maintained
+PTRACE SUPPORT
+P: Roland McGrath
+M: roland@redhat.com
+P: Oleg Nesterov
+M: oleg@redhat.com
+L: linux-kernel@vger.kernel.org
+S: Maintained
+F: include/asm-generic/syscall.h
+F: include/linux/ptrace.h
+F: include/linux/regset.h
+F: include/linux/tracehook.h
+F: kernel/ptrace.c
+
PVRUSB2 VIDEO4LINUX DRIVER
P: Mike Isely
M: isely@pobox.com
RDC R-321X SoC
P: Florian Fainelli
-M: florian.fainelli@telecomint.eu
+M: florian@openwrt.org
L: linux-kernel@vger.kernel.org
S: Maintained
RDC R6040 FAST ETHERNET DRIVER
P: Florian Fainelli
-M: florian.fainelli@telecomint.eu
+M: florian@openwrt.org
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/r6040.c
@echo ' dir/ - Build all files in dir and below'
@echo ' dir/file.[ois] - Build specified target only'
@echo ' dir/file.ko - Build module including final link'
- @echo ' prepare - Set up for building external modules'
+ @echo ' modules_prepare - Set up for building external modules'
@echo ' tags/TAGS - Generate tags file for editors'
@echo ' cscope - Generate cscope index'
@echo ' kernelrelease - Output the release version string'
$(Q)$(MAKE) $(clean)=$(patsubst _clean_%,%,$@)
clean: rm-dirs := $(MODVERDIR)
-clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers
+clean: rm-files := $(KBUILD_EXTMOD)/Module.symvers \
+ $(KBUILD_EXTMOD)/Module.markers \
+ $(KBUILD_EXTMOD)/modules.order
clean: $(clean-dirs)
$(call cmd,rmdirs)
$(call cmd,rmfiles)
__asm__ __volatile__("mb": : :"memory")
#ifdef CONFIG_SMP
+#define __ASM_SMP_MB "\tmb\n"
#define smp_mb() mb()
#define smp_rmb() rmb()
#define smp_wmb() wmb()
#define smp_read_barrier_depends() read_barrier_depends()
#else
+#define __ASM_SMP_MB
#define smp_mb() barrier()
#define smp_rmb() barrier()
#define smp_wmb() barrier()
-#ifndef _ASM_FUTEX_H
-#define _ASM_FUTEX_H
+#ifndef _ASM_ALPHA_FUTEX_H
+#define _ASM_ALPHA_FUTEX_H
-#include <asm-generic/futex.h>
+#ifdef __KERNEL__
-#endif
+#include <linux/futex.h>
+#include <linux/uaccess.h>
+#include <asm/errno.h>
+#include <asm/barrier.h>
+
+#define __futex_atomic_op(insn, ret, oldval, uaddr, oparg) \
+ __asm__ __volatile__( \
+ __ASM_SMP_MB \
+ "1: ldl_l %0,0(%2)\n" \
+ insn \
+ "2: stl_c %1,0(%2)\n" \
+ " beq %1,4f\n" \
+ " mov $31,%1\n" \
+ "3: .subsection 2\n" \
+ "4: br 1b\n" \
+ " .previous\n" \
+ " .section __ex_table,\"a\"\n" \
+ " .long 1b-.\n" \
+ " lda $31,3b-1b(%1)\n" \
+ " .long 2b-.\n" \
+ " lda $31,3b-2b(%1)\n" \
+ " .previous\n" \
+ : "=&r" (oldval), "=&r"(ret) \
+ : "r" (uaddr), "r"(oparg) \
+ : "memory")
+
+static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+{
+ int op = (encoded_op >> 28) & 7;
+ int cmp = (encoded_op >> 24) & 15;
+ int oparg = (encoded_op << 8) >> 20;
+ int cmparg = (encoded_op << 20) >> 20;
+ int oldval = 0, ret;
+ if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
+ oparg = 1 << oparg;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ pagefault_disable();
+
+ switch (op) {
+ case FUTEX_OP_SET:
+ __futex_atomic_op("mov %3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ADD:
+ __futex_atomic_op("addl %0,%3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_OR:
+ __futex_atomic_op("or %0,%3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_ANDN:
+ __futex_atomic_op("andnot %0,%3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ case FUTEX_OP_XOR:
+ __futex_atomic_op("xor %0,%3,%1\n", ret, oldval, uaddr, oparg);
+ break;
+ default:
+ ret = -ENOSYS;
+ }
+
+ pagefault_enable();
+
+ if (!ret) {
+ switch (cmp) {
+ case FUTEX_OP_CMP_EQ: ret = (oldval == cmparg); break;
+ case FUTEX_OP_CMP_NE: ret = (oldval != cmparg); break;
+ case FUTEX_OP_CMP_LT: ret = (oldval < cmparg); break;
+ case FUTEX_OP_CMP_GE: ret = (oldval >= cmparg); break;
+ case FUTEX_OP_CMP_LE: ret = (oldval <= cmparg); break;
+ case FUTEX_OP_CMP_GT: ret = (oldval > cmparg); break;
+ default: ret = -ENOSYS;
+ }
+ }
+ return ret;
+}
+
+static inline int
+futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+{
+ int prev, cmp;
+
+ if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+ return -EFAULT;
+
+ __asm__ __volatile__ (
+ __ASM_SMP_MB
+ "1: ldl_l %0,0(%2)\n"
+ " cmpeq %0,%3,%1\n"
+ " beq %1,3f\n"
+ " mov %4,%1\n"
+ "2: stl_c %1,0(%2)\n"
+ " beq %1,4f\n"
+ "3: .subsection 2\n"
+ "4: br 1b\n"
+ " .previous\n"
+ " .section __ex_table,\"a\"\n"
+ " .long 1b-.\n"
+ " lda $31,3b-1b(%0)\n"
+ " .long 2b-.\n"
+ " lda $31,3b-2b(%0)\n"
+ " .previous\n"
+ : "=&r"(prev), "=&r"(cmp)
+ : "r"(uaddr), "r"((long)oldval), "r"(newval)
+ : "memory");
+
+ return prev;
+}
+
+#endif /* __KERNEL__ */
+#endif /* _ASM_ALPHA_FUTEX_H */
(pc) + (_fixup)->fixup.bits.nextinsn; \
})
+#define ARCH_HAS_SORT_EXTABLE
+#define ARCH_HAS_SEARCH_EXTABLE
#endif /* __ALPHA_UACCESS_H */
obj-y := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
irq_alpha.o signal.o setup.o ptrace.o time.o \
- alpha_ksyms.o systbls.o err_common.o io.o binfmt_loader.o
+ alpha_ksyms.o systbls.o err_common.o io.o
obj-$(CONFIG_VGA_HOSE) += console.o
obj-$(CONFIG_SMP) += smp.o
# Misc support
obj-$(CONFIG_ALPHA_SRM) += srmcons.o
+ifdef CONFIG_BINFMT_AOUT
+obj-y += binfmt_loader.o
+endif
+
# Core logic support
obj-$(CONFIG_ALPHA_APECS) += core_apecs.o
obj-$(CONFIG_ALPHA_CIA) += core_cia.o
static int __init init_loader_binfmt(void)
{
- return register_binfmt(&loader_format);
+ return insert_binfmt(&loader_format);
}
arch_initcall(init_loader_binfmt);
}
void
-ev6_machine_check(u64 vector, u64 la_ptr)
+ev6_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
}
void
-ev7_machine_check(u64 vector, u64 la_ptr)
+ev7_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
char *saved_err_prefix = err_print_prefix;
switch(header->type) {
case EL_TYPE__PAL__LOGOUT_FRAME:
- printk("%s*** MCHK occurred on LPID %ld (RBOX %llx)\n",
+ printk("%s*** MCHK occurred on LPID %lld (RBOX %llx)\n",
err_print_prefix,
packet->by_type.logout.whami,
packet->by_type.logout.rbox_whami);
ev7_collect_logout_frame_subpackets(struct el_subpacket *,
struct ev7_lf_subpackets *);
extern void ev7_register_error_handlers(void);
-extern void ev7_machine_check(u64, u64);
+extern void ev7_machine_check(unsigned long, unsigned long);
/*
* err_ev6.c
*/
extern void ev6_register_error_handlers(void);
extern int ev6_process_logout_frame(struct el_common *, int);
-extern void ev6_machine_check(u64, u64);
+extern void ev6_machine_check(unsigned long, unsigned long);
/*
* err_marvel.c
*/
-extern void marvel_machine_check(u64, u64);
+extern void marvel_machine_check(unsigned long, unsigned long);
extern void marvel_register_error_handlers(void);
/*
* err_titan.c
*/
extern int titan_process_logout_frame(struct el_common *, int);
-extern void titan_machine_check(u64, u64);
+extern void titan_machine_check(unsigned long, unsigned long);
extern void titan_register_error_handlers(void);
extern int privateer_process_logout_frame(struct el_common *, int);
-extern void privateer_machine_check(u64, u64);
+extern void privateer_machine_check(unsigned long, unsigned long);
}
void
-marvel_machine_check(u64 vector, u64 la_ptr)
+marvel_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_subpacket *el_ptr = (struct el_subpacket *)la_ptr;
int (*process_frame)(struct ev7_lf_subpackets *, int) = NULL;
}
void
-titan_machine_check(u64 vector, u64 la_ptr)
+titan_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
struct el_TITAN_sysdata_mcheck *tmchk =
}
void
-privateer_machine_check(u64 vector, u64 la_ptr)
+privateer_machine_check(unsigned long vector, unsigned long la_ptr)
{
struct el_common *mchk_header = (struct el_common *)la_ptr;
struct el_TITAN_sysdata_mcheck *tmchk =
extern struct pci_ops irongate_pci_ops;
extern int irongate_pci_clr_err(void);
extern void irongate_init_arch(void);
-extern void irongate_machine_check(u64, u64);
#define irongate_pci_tbi ((void *)0)
/* core_lca.c */
extern struct pci_ops marvel_pci_ops;
extern void marvel_init_arch(void);
extern void marvel_kill_arch(int);
-extern void marvel_machine_check(u64, u64);
+extern void marvel_machine_check(unsigned long, unsigned long);
extern void marvel_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern int marvel_pa_to_nid(unsigned long);
extern int marvel_cpuid_to_nid(int);
extern struct pci_ops titan_pci_ops;
extern void titan_init_arch(void);
extern void titan_kill_arch(int);
-extern void titan_machine_check(u64, u64);
+extern void titan_machine_check(unsigned long, unsigned long);
extern void titan_pci_tbi(struct pci_controller *, dma_addr_t, dma_addr_t);
extern struct _alpha_agp_info *titan_agp_info(void);
*/
#include <linux/module.h>
+#include <linux/sort.h>
#include <asm/uaccess.h>
+static inline unsigned long ex_to_addr(const struct exception_table_entry *x)
+{
+ return (unsigned long)&x->insn + x->insn;
+}
+
+static void swap_ex(void *a, void *b, int size)
+{
+ struct exception_table_entry *ex_a = a, *ex_b = b;
+ unsigned long addr_a = ex_to_addr(ex_a), addr_b = ex_to_addr(ex_b);
+ unsigned int t = ex_a->fixup.unit;
+
+ ex_a->fixup.unit = ex_b->fixup.unit;
+ ex_b->fixup.unit = t;
+ ex_a->insn = (int)(addr_b - (unsigned long)&ex_a->insn);
+ ex_b->insn = (int)(addr_a - (unsigned long)&ex_b->insn);
+}
+
+/*
+ * The exception table needs to be sorted so that the binary
+ * search that we use to find entries in it works properly.
+ * This is used both for the kernel exception table and for
+ * the exception tables of modules that get loaded.
+ */
+static int cmp_ex(const void *a, const void *b)
+{
+ const struct exception_table_entry *x = a, *y = b;
+
+ /* avoid overflow */
+ if (ex_to_addr(x) > ex_to_addr(y))
+ return 1;
+ if (ex_to_addr(x) < ex_to_addr(y))
+ return -1;
+ return 0;
+}
+
void sort_extable(struct exception_table_entry *start,
struct exception_table_entry *finish)
{
+ sort(start, finish - start, sizeof(struct exception_table_entry),
+ cmp_ex, swap_ex);
}
const struct exception_table_entry *
unsigned long mid_value;
mid = (last - first) / 2 + first;
- mid_value = (unsigned long)&mid->insn + mid->insn;
+ mid_value = ex_to_addr(mid);
if (mid_value == value)
return mid;
else if (mid_value < value)
select ARCH_MTD_XIP
select GENERIC_GPIO
select ARCH_REQUIRE_GPIOLIB
+ select HAVE_CLK
help
Support for Freescale MXC/iMX-based family of processors
select HAVE_CLK
select COMMON_CLKDEV
select ARCH_REQUIRE_GPIOLIB
- select HAVE_CLK
- select COMMON_CLKDEV
select GENERIC_TIME
select GENERIC_CLOCKEVENTS
select TICK_ONESHOT
select ARCH_REQUIRE_GPIOLIB
select HAVE_CLK
select ZONE_DMA
+ select HAVE_IDE
+ select COMMON_CLKDEV
help
Support for TI's DaVinci platform.
source "arch/arm/Kconfig-nommu"
endif
+config ARM_ERRATA_411920
+ bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
+ depends on CPU_V6 && !SMP
+ help
+ Invalidation of the Instruction Cache operation can
+ fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
+ It does not affect the MPCore. This option enables the ARM Ltd.
+ recommended workaround.
+
+config ARM_ERRATA_430973
+ bool "ARM errata: Stale prediction on replaced interworking branch"
+ depends on CPU_V7
+ help
+ This option enables the workaround for the 430973 Cortex-A8
+ (r1p0..r1p2) erratum. If a code sequence containing an ARM/Thumb
+ interworking branch is replaced with another code sequence at the
+ same virtual address, whether due to self-modifying code or virtual
+ to physical address re-mapping, Cortex-A8 does not recover from the
+ stale interworking branch prediction. This results in Cortex-A8
+ executing the new code sequence in the incorrect ARM or Thumb state.
+ The workaround enables the BTB/BTAC operations by setting ACTLR.IBE
+ and also flushes the branch target cache at every context switch.
+ Note that setting specific bits in the ACTLR register may not be
+ available in non-secure mode.
+
+config ARM_ERRATA_458693
+ bool "ARM errata: Processor deadlock when a false hazard is created"
+ depends on CPU_V7
+ help
+ This option enables the workaround for the 458693 Cortex-A8 (r2p0)
+ erratum. For very specific sequences of memory operations, it is
+ possible for a hazard condition intended for a cache line to instead
+ be incorrectly associated with a different cache line. This false
+ hazard might then cause a processor deadlock. The workaround enables
+ the L1 caching of the NEON accesses and disables the PLD instruction
+ in the ACTLR register. Note that setting specific bits in the ACTLR
+ register may not be available in non-secure mode.
+
+config ARM_ERRATA_460075
+ bool "ARM errata: Data written to the L2 cache can be overwritten with stale data"
+ depends on CPU_V7
+ help
+ This option enables the workaround for the 460075 Cortex-A8 (r2p0)
+ erratum. Any asynchronous access to the L2 cache may encounter a
+ situation in which recent store transactions to the L2 cache are lost
+ and overwritten with stale memory contents from external memory. The
+ workaround disables the write-allocate mode for the L2 cache via the
+ ACTLR register. Note that setting specific bits in the ACTLR register
+ may not be available in non-secure mode.
+
endmenu
source "arch/arm/common/Kconfig"
If in doubt, say N.
-config CPU_FREQ_PXA
- bool
- depends on CPU_FREQ && ARCH_PXA && PXA25x
- default y
- select CPU_FREQ_DEFAULT_GOV_USERSPACE
-
endif
source "drivers/cpuidle/Kconfig"
--- /dev/null
+#
+# Automatically generated make config: don't edit
+# Linux kernel version: 2.6.30-rc2
+# Wed Apr 15 08:16:53 2009
+#
+CONFIG_ARM=y
+CONFIG_SYS_SUPPORTS_APM_EMULATION=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_GENERIC_TIME=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_MMU=y
+# CONFIG_NO_IOPORT is not set
+CONFIG_GENERIC_HARDIRQS=y
+CONFIG_STACKTRACE_SUPPORT=y
+CONFIG_HAVE_LATENCYTOP_SUPPORT=y
+CONFIG_LOCKDEP_SUPPORT=y
+CONFIG_TRACE_IRQFLAGS_SUPPORT=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_GENERIC_IRQ_PROBE=y
+CONFIG_RWSEM_GENERIC_SPINLOCK=y
+# CONFIG_ARCH_HAS_ILOG2_U32 is not set
+# CONFIG_ARCH_HAS_ILOG2_U64 is not set
+CONFIG_GENERIC_HWEIGHT=y
+CONFIG_GENERIC_CALIBRATE_DELAY=y
+CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
+CONFIG_VECTORS_BASE=0xffff0000
+CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
+
+#
+# General setup
+#
+CONFIG_EXPERIMENTAL=y
+CONFIG_BROKEN_ON_SMP=y
+CONFIG_LOCK_KERNEL=y
+CONFIG_INIT_ENV_ARG_LIMIT=32
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+# CONFIG_SWAP is not set
+CONFIG_SYSVIPC=y
+CONFIG_SYSVIPC_SYSCTL=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_POSIX_MQUEUE_SYSCTL=y
+# CONFIG_BSD_PROCESS_ACCT is not set
+# CONFIG_TASKSTATS is not set
+# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_GROUP_SCHED=y
+CONFIG_FAIR_GROUP_SCHED=y
+# CONFIG_RT_GROUP_SCHED is not set
+CONFIG_USER_SCHED=y
+# CONFIG_CGROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
+CONFIG_SYSFS_DEPRECATED=y
+CONFIG_SYSFS_DEPRECATED_V2=y
+# CONFIG_RELAY is not set
+# CONFIG_NAMESPACES is not set
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_RD_GZIP=y
+# CONFIG_RD_BZIP2 is not set
+# CONFIG_RD_LZMA is not set
+CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
+CONFIG_EMBEDDED=y
+CONFIG_UID16=y
+CONFIG_SYSCTL_SYSCALL=y
+CONFIG_KALLSYMS=y
+# CONFIG_KALLSYMS_ALL is not set
+# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
+CONFIG_HOTPLUG=y
+CONFIG_PRINTK=y
+CONFIG_BUG=y
+CONFIG_ELF_CORE=y
+CONFIG_BASE_FULL=y
+CONFIG_FUTEX=y
+CONFIG_EPOLL=y
+CONFIG_SIGNALFD=y
+CONFIG_TIMERFD=y
+CONFIG_EVENTFD=y
+CONFIG_SHMEM=y
+CONFIG_AIO=y
+CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
+# CONFIG_SLAB is not set
+CONFIG_SLUB=y
+# CONFIG_SLOB is not set
+# CONFIG_PROFILING is not set
+# CONFIG_MARKERS is not set
+CONFIG_HAVE_OPROFILE=y
+# CONFIG_KPROBES is not set
+CONFIG_HAVE_KPROBES=y
+CONFIG_HAVE_KRETPROBES=y
+CONFIG_HAVE_CLK=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
+CONFIG_SLABINFO=y
+CONFIG_RT_MUTEXES=y
+CONFIG_BASE_SMALL=0
+CONFIG_MODULES=y
+# CONFIG_MODULE_FORCE_LOAD is not set
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+CONFIG_MODVERSIONS=y
+# CONFIG_MODULE_SRCVERSION_ALL is not set
+CONFIG_BLOCK=y
+# CONFIG_LBD is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
+
+#
+# IO Schedulers
+#
+CONFIG_IOSCHED_NOOP=y
+CONFIG_IOSCHED_AS=y
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_DEFAULT_AS=y
+# CONFIG_DEFAULT_DEADLINE is not set
+# CONFIG_DEFAULT_CFQ is not set
+# CONFIG_DEFAULT_NOOP is not set
+CONFIG_DEFAULT_IOSCHED="anticipatory"
+# CONFIG_FREEZER is not set
+
+#
+# System Type
+#
+# CONFIG_ARCH_AAEC2000 is not set
+# CONFIG_ARCH_INTEGRATOR is not set
+# CONFIG_ARCH_REALVIEW is not set
+# CONFIG_ARCH_VERSATILE is not set
+# CONFIG_ARCH_AT91 is not set
+# CONFIG_ARCH_CLPS711X is not set
+# CONFIG_ARCH_EBSA110 is not set
+# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
+# CONFIG_ARCH_FOOTBRIDGE is not set
+# CONFIG_ARCH_NETX is not set
+# CONFIG_ARCH_H720X is not set
+# CONFIG_ARCH_IMX is not set
+# CONFIG_ARCH_IOP13XX is not set
+# CONFIG_ARCH_IOP32X is not set
+# CONFIG_ARCH_IOP33X is not set
+# CONFIG_ARCH_IXP23XX is not set
+# CONFIG_ARCH_IXP2000 is not set
+# CONFIG_ARCH_IXP4XX is not set
+# CONFIG_ARCH_L7200 is not set
+# CONFIG_ARCH_KIRKWOOD is not set
+# CONFIG_ARCH_KS8695 is not set
+# CONFIG_ARCH_NS9XXX is not set
+# CONFIG_ARCH_LOKI is not set
+# CONFIG_ARCH_MV78XX0 is not set
+# CONFIG_ARCH_MXC is not set
+# CONFIG_ARCH_ORION5X is not set
+# CONFIG_ARCH_PNX4008 is not set
+# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
+# CONFIG_ARCH_RPC is not set
+# CONFIG_ARCH_SA1100 is not set
+# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
+# CONFIG_ARCH_SHARK is not set
+# CONFIG_ARCH_LH7A40X is not set
+CONFIG_ARCH_DAVINCI=y
+# CONFIG_ARCH_OMAP is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
+
+#
+# TI DaVinci Implementations
+#
+
+#
+# DaVinci Core Type
+#
+CONFIG_ARCH_DAVINCI_DM644x=y
+
+#
+# DaVinci Board Type
+#
+CONFIG_MACH_DAVINCI_EVM=y
+CONFIG_DAVINCI_MUX=y
+CONFIG_DAVINCI_MUX_DEBUG=y
+CONFIG_DAVINCI_MUX_WARNINGS=y
+CONFIG_DAVINCI_RESET_CLOCKS=y
+
+#
+# Processor Type
+#
+CONFIG_CPU_32=y
+CONFIG_CPU_ARM926T=y
+CONFIG_CPU_32v5=y
+CONFIG_CPU_ABRT_EV5TJ=y
+CONFIG_CPU_PABRT_NOIFAR=y
+CONFIG_CPU_CACHE_VIVT=y
+CONFIG_CPU_COPY_V4WB=y
+CONFIG_CPU_TLB_V4WBI=y
+CONFIG_CPU_CP15=y
+CONFIG_CPU_CP15_MMU=y
+
+#
+# Processor Features
+#
+CONFIG_ARM_THUMB=y
+# CONFIG_CPU_ICACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_DISABLE is not set
+# CONFIG_CPU_DCACHE_WRITETHROUGH is not set
+# CONFIG_CPU_CACHE_ROUND_ROBIN is not set
+# CONFIG_OUTER_CACHE is not set
+CONFIG_COMMON_CLKDEV=y
+
+#
+# Bus support
+#
+# CONFIG_PCI_SYSCALL is not set
+# CONFIG_ARCH_SUPPORTS_MSI is not set
+# CONFIG_PCCARD is not set
+
+#
+# Kernel Features
+#
+CONFIG_TICK_ONESHOT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
+CONFIG_PREEMPT=y
+CONFIG_HZ=100
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
+CONFIG_SELECT_MEMORY_MODEL=y
+CONFIG_FLATMEM_MANUAL=y
+# CONFIG_DISCONTIGMEM_MANUAL is not set
+# CONFIG_SPARSEMEM_MANUAL is not set
+CONFIG_FLATMEM=y
+CONFIG_FLAT_NODE_MEM_MAP=y
+CONFIG_PAGEFLAGS_EXTENDED=y
+CONFIG_SPLIT_PTLOCK_CPUS=4096
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=1
+CONFIG_BOUNCE=y
+CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
+CONFIG_LEDS=y
+# CONFIG_LEDS_CPU is not set
+CONFIG_ALIGNMENT_TRAP=y
+
+#
+# Boot options
+#
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE=""
+# CONFIG_XIP_KERNEL is not set
+# CONFIG_KEXEC is not set
+
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
+#
+# Floating point emulation
+#
+
+#
+# At least one emulation must be selected
+#
+# CONFIG_VFP is not set
+
+#
+# Userspace binary formats
+#
+CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
+# CONFIG_BINFMT_AOUT is not set
+# CONFIG_BINFMT_MISC is not set
+
+#
+# Power management options
+#
+# CONFIG_PM is not set
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_NET=y
+
+#
+# Networking options
+#
+CONFIG_PACKET=y
+# CONFIG_PACKET_MMAP is not set
+CONFIG_UNIX=y
+CONFIG_XFRM=y
+# CONFIG_XFRM_USER is not set
+# CONFIG_XFRM_SUB_POLICY is not set
+# CONFIG_XFRM_MIGRATE is not set
+# CONFIG_XFRM_STATISTICS is not set
+# CONFIG_NET_KEY is not set
+CONFIG_INET=y
+# CONFIG_IP_MULTICAST is not set
+# CONFIG_IP_ADVANCED_ROUTER is not set
+CONFIG_IP_FIB_HASH=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_NET_IPIP is not set
+# CONFIG_NET_IPGRE is not set
+# CONFIG_ARPD is not set
+# CONFIG_SYN_COOKIES is not set
+# CONFIG_INET_AH is not set
+# CONFIG_INET_ESP is not set
+# CONFIG_INET_IPCOMP is not set
+# CONFIG_INET_XFRM_TUNNEL is not set
+CONFIG_INET_TUNNEL=m
+CONFIG_INET_XFRM_MODE_TRANSPORT=y
+CONFIG_INET_XFRM_MODE_TUNNEL=y
+CONFIG_INET_XFRM_MODE_BEET=y
+# CONFIG_INET_LRO is not set
+CONFIG_INET_DIAG=y
+CONFIG_INET_TCP_DIAG=y
+# CONFIG_TCP_CONG_ADVANCED is not set
+CONFIG_TCP_CONG_CUBIC=y
+CONFIG_DEFAULT_TCP_CONG="cubic"
+# CONFIG_TCP_MD5SIG is not set
+CONFIG_IPV6=m
+# CONFIG_IPV6_PRIVACY is not set
+# CONFIG_IPV6_ROUTER_PREF is not set
+# CONFIG_IPV6_OPTIMISTIC_DAD is not set
+# CONFIG_INET6_AH is not set
+# CONFIG_INET6_ESP is not set
+# CONFIG_INET6_IPCOMP is not set
+# CONFIG_IPV6_MIP6 is not set
+# CONFIG_INET6_XFRM_TUNNEL is not set
+# CONFIG_INET6_TUNNEL is not set
+CONFIG_INET6_XFRM_MODE_TRANSPORT=m
+CONFIG_INET6_XFRM_MODE_TUNNEL=m
+CONFIG_INET6_XFRM_MODE_BEET=m
+# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
+CONFIG_IPV6_SIT=m
+CONFIG_IPV6_NDISC_NODETYPE=y
+# CONFIG_IPV6_TUNNEL is not set
+# CONFIG_IPV6_MULTIPLE_TABLES is not set
+# CONFIG_IPV6_MROUTE is not set
+# CONFIG_NETWORK_SECMARK is not set
+CONFIG_NETFILTER=y
+# CONFIG_NETFILTER_DEBUG is not set
+CONFIG_NETFILTER_ADVANCED=y
+
+#
+# Core Netfilter Configuration
+#
+# CONFIG_NETFILTER_NETLINK_QUEUE is not set
+# CONFIG_NETFILTER_NETLINK_LOG is not set
+# CONFIG_NF_CONNTRACK is not set
+# CONFIG_NETFILTER_XTABLES is not set
+# CONFIG_IP_VS is not set
+
+#
+# IP: Netfilter Configuration
+#
+# CONFIG_NF_DEFRAG_IPV4 is not set
+# CONFIG_IP_NF_QUEUE is not set
+# CONFIG_IP_NF_IPTABLES is not set
+# CONFIG_IP_NF_ARPTABLES is not set
+
+#
+# IPv6: Netfilter Configuration
+#
+# CONFIG_IP6_NF_QUEUE is not set
+# CONFIG_IP6_NF_IPTABLES is not set
+# CONFIG_IP_DCCP is not set
+# CONFIG_IP_SCTP is not set
+# CONFIG_TIPC is not set
+# CONFIG_ATM is not set
+# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
+# CONFIG_VLAN_8021Q is not set
+# CONFIG_DECNET is not set
+# CONFIG_LLC2 is not set
+# CONFIG_IPX is not set
+# CONFIG_ATALK is not set
+# CONFIG_X25 is not set
+# CONFIG_LAPB is not set
+# CONFIG_ECONET is not set
+# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
+# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
+
+#
+# Network testing
+#
+# CONFIG_NET_PKTGEN is not set
+# CONFIG_HAMRADIO is not set
+# CONFIG_CAN is not set
+# CONFIG_IRDA is not set
+# CONFIG_BT is not set
+# CONFIG_AF_RXRPC is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
+# CONFIG_RFKILL is not set
+# CONFIG_NET_9P is not set
+
+#
+# Device Drivers
+#
+
+#
+# Generic Driver Options
+#
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_STANDALONE=y
+CONFIG_PREVENT_FIRMWARE_BUILD=y
+# CONFIG_FW_LOADER is not set
+# CONFIG_DEBUG_DRIVER is not set
+# CONFIG_DEBUG_DEVRES is not set
+# CONFIG_SYS_HYPERVISOR is not set
+# CONFIG_CONNECTOR is not set
+CONFIG_MTD=m
+# CONFIG_MTD_DEBUG is not set
+# CONFIG_MTD_CONCAT is not set
+CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
+# CONFIG_MTD_REDBOOT_PARTS is not set
+# CONFIG_MTD_AFS_PARTS is not set
+# CONFIG_MTD_AR7_PARTS is not set
+
+#
+# User Modules And Translation Layers
+#
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+CONFIG_MTD_BLOCK=m
+# CONFIG_MTD_BLOCK_RO is not set
+# CONFIG_FTL is not set
+# CONFIG_NFTL is not set
+# CONFIG_INFTL is not set
+# CONFIG_RFD_FTL is not set
+# CONFIG_SSFDC is not set
+# CONFIG_MTD_OOPS is not set
+
+#
+# RAM/ROM/Flash chip drivers
+#
+CONFIG_MTD_CFI=m
+# CONFIG_MTD_JEDECPROBE is not set
+CONFIG_MTD_GEN_PROBE=m
+# CONFIG_MTD_CFI_ADV_OPTIONS is not set
+CONFIG_MTD_MAP_BANK_WIDTH_1=y
+CONFIG_MTD_MAP_BANK_WIDTH_2=y
+CONFIG_MTD_MAP_BANK_WIDTH_4=y
+# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
+# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
+CONFIG_MTD_CFI_I1=y
+CONFIG_MTD_CFI_I2=y
+# CONFIG_MTD_CFI_I4 is not set
+# CONFIG_MTD_CFI_I8 is not set
+# CONFIG_MTD_CFI_INTELEXT is not set
+CONFIG_MTD_CFI_AMDSTD=m
+# CONFIG_MTD_CFI_STAA is not set
+CONFIG_MTD_CFI_UTIL=m
+# CONFIG_MTD_RAM is not set
+# CONFIG_MTD_ROM is not set
+# CONFIG_MTD_ABSENT is not set
+
+#
+# Mapping drivers for chip access
+#
+# CONFIG_MTD_COMPLEX_MAPPINGS is not set
+CONFIG_MTD_PHYSMAP=m
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
+# CONFIG_MTD_ARM_INTEGRATOR is not set
+# CONFIG_MTD_PLATRAM is not set
+
+#
+# Self-contained MTD device drivers
+#
+# CONFIG_MTD_SLRAM is not set
+# CONFIG_MTD_PHRAM is not set
+# CONFIG_MTD_MTDRAM is not set
+# CONFIG_MTD_BLOCK2MTD is not set
+
+#
+# Disk-On-Chip Device Drivers
+#
+# CONFIG_MTD_DOC2000 is not set
+# CONFIG_MTD_DOC2001 is not set
+# CONFIG_MTD_DOC2001PLUS is not set
+CONFIG_MTD_NAND=m
+# CONFIG_MTD_NAND_VERIFY_WRITE is not set
+# CONFIG_MTD_NAND_ECC_SMC is not set
+# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
+CONFIG_MTD_NAND_IDS=m
+# CONFIG_MTD_NAND_DISKONCHIP is not set
+# CONFIG_MTD_NAND_NANDSIM is not set
+# CONFIG_MTD_NAND_PLATFORM is not set
+# CONFIG_MTD_ALAUDA is not set
+CONFIG_MTD_NAND_DAVINCI=m
+# CONFIG_MTD_ONENAND is not set
+
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
+#
+# UBI - Unsorted block images
+#
+# CONFIG_MTD_UBI is not set
+# CONFIG_PARPORT is not set
+CONFIG_BLK_DEV=y
+# CONFIG_BLK_DEV_COW_COMMON is not set
+CONFIG_BLK_DEV_LOOP=m
+# CONFIG_BLK_DEV_CRYPTOLOOP is not set
+# CONFIG_BLK_DEV_NBD is not set
+# CONFIG_BLK_DEV_UB is not set
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_COUNT=1
+CONFIG_BLK_DEV_RAM_SIZE=32768
+# CONFIG_BLK_DEV_XIP is not set
+# CONFIG_CDROM_PKTCDVD is not set
+# CONFIG_ATA_OVER_ETH is not set
+CONFIG_MISC_DEVICES=y
+# CONFIG_ICS932S401 is not set
+# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+CONFIG_EEPROM_AT24=y
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
+CONFIG_HAVE_IDE=y
+CONFIG_IDE=m
+
+#
+# Please see Documentation/ide/ide.txt for help/info on IDE drives
+#
+CONFIG_IDE_XFER_MODE=y
+CONFIG_IDE_TIMINGS=y
+# CONFIG_BLK_DEV_IDE_SATA is not set
+CONFIG_IDE_GD=m
+CONFIG_IDE_GD_ATA=y
+# CONFIG_IDE_GD_ATAPI is not set
+# CONFIG_BLK_DEV_IDECD is not set
+# CONFIG_BLK_DEV_IDETAPE is not set
+# CONFIG_IDE_TASK_IOCTL is not set
+CONFIG_IDE_PROC_FS=y
+
+#
+# IDE chipset support/bugfixes
+#
+# CONFIG_BLK_DEV_PLATFORM is not set
+CONFIG_BLK_DEV_IDEDMA_SFF=y
+CONFIG_BLK_DEV_PALMCHIP_BK3710=m
+CONFIG_BLK_DEV_IDEDMA=y
+
+#
+# SCSI device support
+#
+# CONFIG_RAID_ATTRS is not set
+CONFIG_SCSI=m
+CONFIG_SCSI_DMA=y
+# CONFIG_SCSI_TGT is not set
+# CONFIG_SCSI_NETLINK is not set
+CONFIG_SCSI_PROC_FS=y
+
+#
+# SCSI support type (disk, tape, CD-ROM)
+#
+CONFIG_BLK_DEV_SD=m
+# CONFIG_CHR_DEV_ST is not set
+# CONFIG_CHR_DEV_OSST is not set
+# CONFIG_BLK_DEV_SR is not set
+# CONFIG_CHR_DEV_SG is not set
+# CONFIG_CHR_DEV_SCH is not set
+
+#
+# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+#
+# CONFIG_SCSI_MULTI_LUN is not set
+# CONFIG_SCSI_CONSTANTS is not set
+# CONFIG_SCSI_LOGGING is not set
+# CONFIG_SCSI_SCAN_ASYNC is not set
+CONFIG_SCSI_WAIT_SCAN=m
+
+#
+# SCSI Transports
+#
+# CONFIG_SCSI_SPI_ATTRS is not set
+# CONFIG_SCSI_FC_ATTRS is not set
+# CONFIG_SCSI_ISCSI_ATTRS is not set
+# CONFIG_SCSI_SAS_LIBSAS is not set
+# CONFIG_SCSI_SRP_ATTRS is not set
+CONFIG_SCSI_LOWLEVEL=y
+# CONFIG_ISCSI_TCP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_SCSI_DEBUG is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
+# CONFIG_ATA is not set
+# CONFIG_MD is not set
+CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
+# CONFIG_DUMMY is not set
+# CONFIG_BONDING is not set
+# CONFIG_MACVLAN is not set
+# CONFIG_EQUALIZER is not set
+CONFIG_TUN=m
+# CONFIG_VETH is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+# CONFIG_MARVELL_PHY is not set
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+CONFIG_LXT_PHY=y
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+CONFIG_LSI_ET1011C_PHY=y
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+# CONFIG_AX88796 is not set
+# CONFIG_SMC91X is not set
+# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
+# CONFIG_IBM_NEW_EMAC_ZMII is not set
+# CONFIG_IBM_NEW_EMAC_RGMII is not set
+# CONFIG_IBM_NEW_EMAC_TAH is not set
+# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
+# CONFIG_B44 is not set
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+
+#
+# Wireless LAN
+#
+# CONFIG_WLAN_PRE80211 is not set
+# CONFIG_WLAN_80211 is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
+
+#
+# USB Network Adapters
+#
+# CONFIG_USB_CATC is not set
+# CONFIG_USB_KAWETH is not set
+# CONFIG_USB_PEGASUS is not set
+# CONFIG_USB_RTL8150 is not set
+# CONFIG_USB_USBNET is not set
+# CONFIG_WAN is not set
+CONFIG_PPP=m
+# CONFIG_PPP_MULTILINK is not set
+# CONFIG_PPP_FILTER is not set
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+# CONFIG_PPP_BSDCOMP is not set
+# CONFIG_PPP_MPPE is not set
+# CONFIG_PPPOE is not set
+# CONFIG_PPPOL2TP is not set
+# CONFIG_SLIP is not set
+CONFIG_SLHC=m
+CONFIG_NETCONSOLE=y
+# CONFIG_NETCONSOLE_DYNAMIC is not set
+CONFIG_NETPOLL=y
+CONFIG_NETPOLL_TRAP=y
+CONFIG_NET_POLL_CONTROLLER=y
+# CONFIG_ISDN is not set
+
+#
+# Input device support
+#
+CONFIG_INPUT=y
+# CONFIG_INPUT_FF_MEMLESS is not set
+# CONFIG_INPUT_POLLDEV is not set
+
+#
+# Userland interfaces
+#
+CONFIG_INPUT_MOUSEDEV=m
+CONFIG_INPUT_MOUSEDEV_PSAUX=y
+CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024
+CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768
+# CONFIG_INPUT_JOYDEV is not set
+CONFIG_INPUT_EVDEV=m
+CONFIG_INPUT_EVBUG=m
+
+#
+# Input Device Drivers
+#
+CONFIG_INPUT_KEYBOARD=y
+CONFIG_KEYBOARD_ATKBD=m
+# CONFIG_KEYBOARD_SUNKBD is not set
+# CONFIG_KEYBOARD_LKKBD is not set
+CONFIG_KEYBOARD_XTKBD=m
+# CONFIG_KEYBOARD_NEWTON is not set
+# CONFIG_KEYBOARD_STOWAWAY is not set
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_INPUT_JOYSTICK is not set
+# CONFIG_INPUT_TABLET is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+# CONFIG_TOUCHSCREEN_AD7879_I2C is not set
+# CONFIG_TOUCHSCREEN_AD7879 is not set
+# CONFIG_TOUCHSCREEN_FUJITSU is not set
+# CONFIG_TOUCHSCREEN_GUNZE is not set
+# CONFIG_TOUCHSCREEN_ELO is not set
+# CONFIG_TOUCHSCREEN_WACOM_W8001 is not set
+# CONFIG_TOUCHSCREEN_MTOUCH is not set
+# CONFIG_TOUCHSCREEN_INEXIO is not set
+# CONFIG_TOUCHSCREEN_MK712 is not set
+# CONFIG_TOUCHSCREEN_PENMOUNT is not set
+# CONFIG_TOUCHSCREEN_TOUCHRIGHT is not set
+# CONFIG_TOUCHSCREEN_TOUCHWIN is not set
+# CONFIG_TOUCHSCREEN_USB_COMPOSITE is not set
+# CONFIG_TOUCHSCREEN_TOUCHIT213 is not set
+# CONFIG_TOUCHSCREEN_TSC2007 is not set
+# CONFIG_INPUT_MISC is not set
+
+#
+# Hardware I/O ports
+#
+CONFIG_SERIO=y
+CONFIG_SERIO_SERPORT=y
+CONFIG_SERIO_LIBPS2=y
+# CONFIG_SERIO_RAW is not set
+# CONFIG_GAMEPORT is not set
+
+#
+# Character devices
+#
+CONFIG_VT=y
+CONFIG_CONSOLE_TRANSLATIONS=y
+# CONFIG_VT_CONSOLE is not set
+CONFIG_HW_CONSOLE=y
+# CONFIG_VT_HW_CONSOLE_BINDING is not set
+CONFIG_DEVKMEM=y
+# CONFIG_SERIAL_NONSTANDARD is not set
+
+#
+# Serial drivers
+#
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=3
+CONFIG_SERIAL_8250_RUNTIME_UARTS=3
+# CONFIG_SERIAL_8250_EXTENDED is not set
+
+#
+# Non-8250 serial port support
+#
+CONFIG_SERIAL_CORE=y
+CONFIG_SERIAL_CORE_CONSOLE=y
+CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
+CONFIG_LEGACY_PTYS=y
+CONFIG_LEGACY_PTY_COUNT=256
+# CONFIG_IPMI_HANDLER is not set
+CONFIG_HW_RANDOM=m
+# CONFIG_HW_RANDOM_TIMERIOMEM is not set
+# CONFIG_R3964 is not set
+# CONFIG_RAW_DRIVER is not set
+# CONFIG_TCG_TPM is not set
+CONFIG_I2C=y
+CONFIG_I2C_BOARDINFO=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
+
+#
+# I2C Hardware Bus support
+#
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+CONFIG_I2C_DAVINCI=y
+# CONFIG_I2C_GPIO is not set
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
+# CONFIG_I2C_PCA_PLATFORM is not set
+# CONFIG_I2C_STUB is not set
+
+#
+# Miscellaneous I2C Chip support
+#
+# CONFIG_DS1682 is not set
+# CONFIG_SENSORS_PCA9539 is not set
+# CONFIG_SENSORS_MAX6875 is not set
+# CONFIG_SENSORS_TSL2550 is not set
+# CONFIG_I2C_DEBUG_CORE is not set
+# CONFIG_I2C_DEBUG_ALGO is not set
+# CONFIG_I2C_DEBUG_BUS is not set
+# CONFIG_I2C_DEBUG_CHIP is not set
+# CONFIG_SPI is not set
+CONFIG_ARCH_REQUIRE_GPIOLIB=y
+CONFIG_GPIOLIB=y
+# CONFIG_DEBUG_GPIO is not set
+# CONFIG_GPIO_SYSFS is not set
+
+#
+# Memory mapped GPIO expanders:
+#
+
+#
+# I2C GPIO expanders:
+#
+# CONFIG_GPIO_MAX732X is not set
+# CONFIG_GPIO_PCA953X is not set
+CONFIG_GPIO_PCF857X=m
+
+#
+# PCI GPIO expanders:
+#
+
+#
+# SPI GPIO expanders:
+#
+# CONFIG_W1 is not set
+# CONFIG_POWER_SUPPLY is not set
+CONFIG_HWMON=y
+# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
+# CONFIG_SENSORS_AD7418 is not set
+# CONFIG_SENSORS_ADM1021 is not set
+# CONFIG_SENSORS_ADM1025 is not set
+# CONFIG_SENSORS_ADM1026 is not set
+# CONFIG_SENSORS_ADM1029 is not set
+# CONFIG_SENSORS_ADM1031 is not set
+# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
+# CONFIG_SENSORS_ADT7470 is not set
+# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
+# CONFIG_SENSORS_ATXP1 is not set
+# CONFIG_SENSORS_DS1621 is not set
+# CONFIG_SENSORS_F71805F is not set
+# CONFIG_SENSORS_F71882FG is not set
+# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
+# CONFIG_SENSORS_GL518SM is not set
+# CONFIG_SENSORS_GL520SM is not set
+# CONFIG_SENSORS_IT87 is not set
+# CONFIG_SENSORS_LM63 is not set
+# CONFIG_SENSORS_LM75 is not set
+# CONFIG_SENSORS_LM77 is not set
+# CONFIG_SENSORS_LM78 is not set
+# CONFIG_SENSORS_LM80 is not set
+# CONFIG_SENSORS_LM83 is not set
+# CONFIG_SENSORS_LM85 is not set
+# CONFIG_SENSORS_LM87 is not set
+# CONFIG_SENSORS_LM90 is not set
+# CONFIG_SENSORS_LM92 is not set
+# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
+# CONFIG_SENSORS_MAX1619 is not set
+# CONFIG_SENSORS_MAX6650 is not set
+# CONFIG_SENSORS_PC87360 is not set
+# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
+# CONFIG_SENSORS_DME1737 is not set
+# CONFIG_SENSORS_SMSC47M1 is not set
+# CONFIG_SENSORS_SMSC47M192 is not set
+# CONFIG_SENSORS_SMSC47B397 is not set
+# CONFIG_SENSORS_ADS7828 is not set
+# CONFIG_SENSORS_THMC50 is not set
+# CONFIG_SENSORS_VT1211 is not set
+# CONFIG_SENSORS_W83781D is not set
+# CONFIG_SENSORS_W83791D is not set
+# CONFIG_SENSORS_W83792D is not set
+# CONFIG_SENSORS_W83793 is not set
+# CONFIG_SENSORS_W83L785TS is not set
+# CONFIG_SENSORS_W83L786NG is not set
+# CONFIG_SENSORS_W83627HF is not set
+# CONFIG_SENSORS_W83627EHF is not set
+# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
+CONFIG_WATCHDOG=y
+# CONFIG_WATCHDOG_NOWAYOUT is not set
+
+#
+# Watchdog Device Drivers
+#
+# CONFIG_SOFT_WATCHDOG is not set
+CONFIG_DAVINCI_WATCHDOG=m
+
+#
+# USB-based Watchdog Cards
+#
+# CONFIG_USBPCWATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
+
+#
+# Sonics Silicon Backplane
+#
+# CONFIG_SSB is not set
+
+#
+# Multifunction device drivers
+#
+# CONFIG_MFD_CORE is not set
+# CONFIG_MFD_SM501 is not set
+# CONFIG_MFD_ASIC3 is not set
+# CONFIG_HTC_EGPIO is not set
+# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TPS65010 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_MFD_T7L66XB is not set
+# CONFIG_MFD_TC6387XB is not set
+# CONFIG_MFD_TC6393XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
+
+#
+# Multimedia devices
+#
+
+#
+# Multimedia core support
+#
+CONFIG_VIDEO_DEV=y
+CONFIG_VIDEO_V4L2_COMMON=y
+CONFIG_VIDEO_ALLOW_V4L1=y
+CONFIG_VIDEO_V4L1_COMPAT=y
+# CONFIG_DVB_CORE is not set
+CONFIG_VIDEO_MEDIA=y
+
+#
+# Multimedia drivers
+#
+# CONFIG_MEDIA_ATTACH is not set
+CONFIG_MEDIA_TUNER=y
+# CONFIG_MEDIA_TUNER_CUSTOMISE is not set
+CONFIG_MEDIA_TUNER_SIMPLE=y
+CONFIG_MEDIA_TUNER_TDA8290=y
+CONFIG_MEDIA_TUNER_TDA9887=y
+CONFIG_MEDIA_TUNER_TEA5761=y
+CONFIG_MEDIA_TUNER_TEA5767=y
+CONFIG_MEDIA_TUNER_MT20XX=y
+CONFIG_MEDIA_TUNER_XC2028=y
+CONFIG_MEDIA_TUNER_XC5000=y
+CONFIG_MEDIA_TUNER_MC44S803=y
+CONFIG_VIDEO_V4L2=y
+CONFIG_VIDEO_V4L1=y
+CONFIG_VIDEO_CAPTURE_DRIVERS=y
+# CONFIG_VIDEO_ADV_DEBUG is not set
+# CONFIG_VIDEO_FIXED_MINOR_RANGES is not set
+CONFIG_VIDEO_HELPER_CHIPS_AUTO=y
+# CONFIG_VIDEO_VIVI is not set
+# CONFIG_VIDEO_CPIA is not set
+# CONFIG_VIDEO_CPIA2 is not set
+# CONFIG_VIDEO_SAA5246A is not set
+# CONFIG_VIDEO_SAA5249 is not set
+# CONFIG_SOC_CAMERA is not set
+# CONFIG_V4L_USB_DRIVERS is not set
+# CONFIG_RADIO_ADAPTERS is not set
+CONFIG_DAB=y
+# CONFIG_USB_DABUSB is not set
+
+#
+# Graphics support
+#
+# CONFIG_VGASTATE is not set
+CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
+CONFIG_FIRMWARE_EDID=y
+# CONFIG_FB_DDC is not set
+# CONFIG_FB_BOOT_VESA_SUPPORT is not set
+# CONFIG_FB_CFB_FILLRECT is not set
+# CONFIG_FB_CFB_COPYAREA is not set
+# CONFIG_FB_CFB_IMAGEBLIT is not set
+# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set
+# CONFIG_FB_SYS_FILLRECT is not set
+# CONFIG_FB_SYS_COPYAREA is not set
+# CONFIG_FB_SYS_IMAGEBLIT is not set
+# CONFIG_FB_FOREIGN_ENDIAN is not set
+# CONFIG_FB_SYS_FOPS is not set
+# CONFIG_FB_SVGALIB is not set
+# CONFIG_FB_MACMODES is not set
+# CONFIG_FB_BACKLIGHT is not set
+# CONFIG_FB_MODE_HELPERS is not set
+# CONFIG_FB_TILEBLITTING is not set
+
+#
+# Frame buffer hardware drivers
+#
+# CONFIG_FB_S1D13XXX is not set
+# CONFIG_FB_VIRTUAL is not set
+# CONFIG_FB_METRONOME is not set
+# CONFIG_FB_MB862XX is not set
+# CONFIG_FB_BROADSHEET is not set
+# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
+
+#
+# Display device support
+#
+# CONFIG_DISPLAY_SUPPORT is not set
+
+#
+# Console display driver support
+#
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_DUMMY_CONSOLE=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set
+# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set
+# CONFIG_FONTS is not set
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+CONFIG_LOGO=y
+CONFIG_LOGO_LINUX_MONO=y
+CONFIG_LOGO_LINUX_VGA16=y
+CONFIG_LOGO_LINUX_CLUT224=y
+CONFIG_SOUND=m
+# CONFIG_SOUND_OSS_CORE is not set
+CONFIG_SND=m
+CONFIG_SND_TIMER=m
+CONFIG_SND_PCM=m
+CONFIG_SND_JACK=y
+# CONFIG_SND_SEQUENCER is not set
+# CONFIG_SND_MIXER_OSS is not set
+# CONFIG_SND_PCM_OSS is not set
+# CONFIG_SND_HRTIMER is not set
+# CONFIG_SND_DYNAMIC_MINORS is not set
+CONFIG_SND_SUPPORT_OLD_API=y
+CONFIG_SND_VERBOSE_PROCFS=y
+# CONFIG_SND_VERBOSE_PRINTK is not set
+# CONFIG_SND_DEBUG is not set
+CONFIG_SND_DRIVERS=y
+# CONFIG_SND_DUMMY is not set
+# CONFIG_SND_MTPAV is not set
+# CONFIG_SND_SERIAL_U16550 is not set
+# CONFIG_SND_MPU401 is not set
+CONFIG_SND_ARM=y
+CONFIG_SND_USB=y
+# CONFIG_SND_USB_AUDIO is not set
+# CONFIG_SND_USB_CAIAQ is not set
+CONFIG_SND_SOC=m
+# CONFIG_SND_DAVINCI_SOC is not set
+CONFIG_SND_SOC_I2C_AND_SPI=m
+# CONFIG_SND_SOC_ALL_CODECS is not set
+# CONFIG_SOUND_PRIME is not set
+CONFIG_HID_SUPPORT=y
+CONFIG_HID=m
+# CONFIG_HID_DEBUG is not set
+# CONFIG_HIDRAW is not set
+
+#
+# USB Input Devices
+#
+CONFIG_USB_HID=m
+# CONFIG_HID_PID is not set
+# CONFIG_USB_HIDDEV is not set
+
+#
+# USB HID Boot Protocol drivers
+#
+# CONFIG_USB_KBD is not set
+# CONFIG_USB_MOUSE is not set
+
+#
+# Special HID drivers
+#
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+# CONFIG_DRAGONRISE_FF is not set
+CONFIG_HID_EZKEY=m
+# CONFIG_HID_KYE is not set
+CONFIG_HID_GYRATION=m
+# CONFIG_HID_KENSINGTON is not set
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+# CONFIG_HID_NTRIG is not set
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+# CONFIG_USB_ARCH_HAS_OHCI is not set
+# CONFIG_USB_ARCH_HAS_EHCI is not set
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+# CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set
+
+#
+# Miscellaneous USB options
+#
+CONFIG_USB_DEVICEFS=y
+CONFIG_USB_DEVICE_CLASS=y
+# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_OTG is not set
+# CONFIG_USB_OTG_WHITELIST is not set
+# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+CONFIG_USB_MON=m
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
+
+#
+# USB Host Controller Drivers
+#
+# CONFIG_USB_C67X00_HCD is not set
+# CONFIG_USB_OXU210HP_HCD is not set
+# CONFIG_USB_ISP116X_HCD is not set
+# CONFIG_USB_ISP1760_HCD is not set
+# CONFIG_USB_SL811_HCD is not set
+# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
+CONFIG_USB_MUSB_HDRC=m
+CONFIG_USB_MUSB_SOC=y
+
+#
+# DaVinci 35x and 644x USB support
+#
+# CONFIG_USB_MUSB_HOST is not set
+CONFIG_USB_MUSB_PERIPHERAL=y
+# CONFIG_USB_MUSB_OTG is not set
+CONFIG_USB_GADGET_MUSB_HDRC=y
+CONFIG_MUSB_PIO_ONLY=y
+# CONFIG_USB_MUSB_DEBUG is not set
+
+#
+# USB Device Class drivers
+#
+# CONFIG_USB_ACM is not set
+# CONFIG_USB_PRINTER is not set
+# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
+
+#
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
+#
+
+#
+# also be needed; see USB_STORAGE Help for more info
+#
+CONFIG_USB_STORAGE=m
+# CONFIG_USB_STORAGE_DEBUG is not set
+# CONFIG_USB_STORAGE_DATAFAB is not set
+# CONFIG_USB_STORAGE_FREECOM is not set
+# CONFIG_USB_STORAGE_ISD200 is not set
+# CONFIG_USB_STORAGE_USBAT is not set
+# CONFIG_USB_STORAGE_SDDR09 is not set
+# CONFIG_USB_STORAGE_SDDR55 is not set
+# CONFIG_USB_STORAGE_JUMPSHOT is not set
+# CONFIG_USB_STORAGE_ALAUDA is not set
+# CONFIG_USB_STORAGE_ONETOUCH is not set
+# CONFIG_USB_STORAGE_KARMA is not set
+# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
+# CONFIG_USB_LIBUSUAL is not set
+
+#
+# USB Imaging devices
+#
+# CONFIG_USB_MDC800 is not set
+# CONFIG_USB_MICROTEK is not set
+
+#
+# USB port drivers
+#
+# CONFIG_USB_SERIAL is not set
+
+#
+# USB Miscellaneous drivers
+#
+# CONFIG_USB_EMI62 is not set
+# CONFIG_USB_EMI26 is not set
+# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
+# CONFIG_USB_RIO500 is not set
+# CONFIG_USB_LEGOTOWER is not set
+# CONFIG_USB_LCD is not set
+# CONFIG_USB_BERRY_CHARGE is not set
+# CONFIG_USB_LED is not set
+# CONFIG_USB_CYPRESS_CY7C63 is not set
+# CONFIG_USB_CYTHERM is not set
+# CONFIG_USB_IDMOUSE is not set
+# CONFIG_USB_FTDI_ELAN is not set
+# CONFIG_USB_APPLEDISPLAY is not set
+# CONFIG_USB_LD is not set
+# CONFIG_USB_TRANCEVIBRATOR is not set
+# CONFIG_USB_IOWARRIOR is not set
+CONFIG_USB_TEST=m
+# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
+CONFIG_USB_GADGET=m
+# CONFIG_USB_GADGET_DEBUG is not set
+CONFIG_USB_GADGET_DEBUG_FILES=y
+CONFIG_USB_GADGET_DEBUG_FS=y
+CONFIG_USB_GADGET_VBUS_DRAW=2
+CONFIG_USB_GADGET_SELECTED=y
+# CONFIG_USB_GADGET_AT91 is not set
+# CONFIG_USB_GADGET_ATMEL_USBA is not set
+# CONFIG_USB_GADGET_FSL_USB2 is not set
+# CONFIG_USB_GADGET_LH7A40X is not set
+# CONFIG_USB_GADGET_OMAP is not set
+# CONFIG_USB_GADGET_PXA25X is not set
+# CONFIG_USB_GADGET_PXA27X is not set
+# CONFIG_USB_GADGET_S3C2410 is not set
+# CONFIG_USB_GADGET_IMX is not set
+# CONFIG_USB_GADGET_M66592 is not set
+# CONFIG_USB_GADGET_AMD5536UDC is not set
+# CONFIG_USB_GADGET_FSL_QE is not set
+# CONFIG_USB_GADGET_CI13XXX is not set
+# CONFIG_USB_GADGET_NET2280 is not set
+# CONFIG_USB_GADGET_GOKU is not set
+# CONFIG_USB_GADGET_DUMMY_HCD is not set
+CONFIG_USB_GADGET_DUALSPEED=y
+CONFIG_USB_ZERO=m
+CONFIG_USB_ETH=m
+CONFIG_USB_ETH_RNDIS=y
+CONFIG_USB_GADGETFS=m
+CONFIG_USB_FILE_STORAGE=m
+# CONFIG_USB_FILE_STORAGE_TEST is not set
+CONFIG_USB_G_SERIAL=m
+# CONFIG_USB_MIDI_GADGET is not set
+CONFIG_USB_G_PRINTER=m
+CONFIG_USB_CDC_COMPOSITE=m
+
+#
+# OTG and related infrastructure
+#
+CONFIG_USB_OTG_UTILS=y
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+CONFIG_MMC=m
+# CONFIG_MMC_DEBUG is not set
+# CONFIG_MMC_UNSAFE_RESUME is not set
+
+#
+# MMC/SD/SDIO Card Drivers
+#
+CONFIG_MMC_BLOCK=m
+# CONFIG_MMC_BLOCK_BOUNCE is not set
+# CONFIG_SDIO_UART is not set
+# CONFIG_MMC_TEST is not set
+
+#
+# MMC/SD/SDIO Host Controller Drivers
+#
+# CONFIG_MMC_SDHCI is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=m
+
+#
+# LED drivers
+#
+# CONFIG_LEDS_PCA9532 is not set
+CONFIG_LEDS_GPIO=m
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
+
+#
+# LED Triggers
+#
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=m
+# CONFIG_LEDS_TRIGGER_IDE_DISK is not set
+CONFIG_LEDS_TRIGGER_HEARTBEAT=m
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
+# CONFIG_LEDS_TRIGGER_GPIO is not set
+# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
+CONFIG_RTC_LIB=y
+CONFIG_RTC_CLASS=m
+
+#
+# RTC interfaces
+#
+CONFIG_RTC_INTF_SYSFS=y
+CONFIG_RTC_INTF_PROC=y
+CONFIG_RTC_INTF_DEV=y
+# CONFIG_RTC_INTF_DEV_UIE_EMUL is not set
+# CONFIG_RTC_DRV_TEST is not set
+
+#
+# I2C RTC drivers
+#
+# CONFIG_RTC_DRV_DS1307 is not set
+# CONFIG_RTC_DRV_DS1374 is not set
+# CONFIG_RTC_DRV_DS1672 is not set
+# CONFIG_RTC_DRV_MAX6900 is not set
+# CONFIG_RTC_DRV_RS5C372 is not set
+# CONFIG_RTC_DRV_ISL1208 is not set
+# CONFIG_RTC_DRV_X1205 is not set
+# CONFIG_RTC_DRV_PCF8563 is not set
+# CONFIG_RTC_DRV_PCF8583 is not set
+# CONFIG_RTC_DRV_M41T80 is not set
+# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
+
+#
+# SPI RTC drivers
+#
+
+#
+# Platform RTC drivers
+#
+# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
+# CONFIG_RTC_DRV_DS1511 is not set
+# CONFIG_RTC_DRV_DS1553 is not set
+# CONFIG_RTC_DRV_DS1742 is not set
+# CONFIG_RTC_DRV_STK17TA8 is not set
+# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
+# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
+# CONFIG_RTC_DRV_V3020 is not set
+
+#
+# on-CPU RTC drivers
+#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
+# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
+
+#
+# File systems
+#
+CONFIG_EXT2_FS=y
+# CONFIG_EXT2_FS_XATTR is not set
+# CONFIG_EXT2_FS_XIP is not set
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_XATTR=y
+# CONFIG_EXT3_FS_POSIX_ACL is not set
+# CONFIG_EXT3_FS_SECURITY is not set
+# CONFIG_EXT4_FS is not set
+CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_FS_MBCACHE=y
+# CONFIG_REISERFS_FS is not set
+# CONFIG_JFS_FS is not set
+# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
+CONFIG_XFS_FS=m
+# CONFIG_XFS_QUOTA is not set
+# CONFIG_XFS_POSIX_ACL is not set
+# CONFIG_XFS_RT is not set
+# CONFIG_XFS_DEBUG is not set
+# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
+CONFIG_DNOTIFY=y
+CONFIG_INOTIFY=y
+CONFIG_INOTIFY_USER=y
+# CONFIG_QUOTA is not set
+# CONFIG_AUTOFS_FS is not set
+CONFIG_AUTOFS4_FS=m
+# CONFIG_FUSE_FS is not set
+
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
+#
+# CD-ROM/DVD Filesystems
+#
+# CONFIG_ISO9660_FS is not set
+# CONFIG_UDF_FS is not set
+
+#
+# DOS/FAT/NT Filesystems
+#
+CONFIG_FAT_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_FAT_DEFAULT_CODEPAGE=437
+CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1"
+# CONFIG_NTFS_FS is not set
+
+#
+# Pseudo filesystems
+#
+CONFIG_PROC_FS=y
+CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+# CONFIG_TMPFS_POSIX_ACL is not set
+# CONFIG_HUGETLB_PAGE is not set
+# CONFIG_CONFIGFS_FS is not set
+CONFIG_MISC_FILESYSTEMS=y
+# CONFIG_ADFS_FS is not set
+# CONFIG_AFFS_FS is not set
+# CONFIG_HFS_FS is not set
+# CONFIG_HFSPLUS_FS is not set
+# CONFIG_BEFS_FS is not set
+# CONFIG_BFS_FS is not set
+# CONFIG_EFS_FS is not set
+CONFIG_JFFS2_FS=m
+CONFIG_JFFS2_FS_DEBUG=0
+CONFIG_JFFS2_FS_WRITEBUFFER=y
+# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
+# CONFIG_JFFS2_SUMMARY is not set
+# CONFIG_JFFS2_FS_XATTR is not set
+# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
+CONFIG_JFFS2_ZLIB=y
+# CONFIG_JFFS2_LZO is not set
+CONFIG_JFFS2_RTIME=y
+# CONFIG_JFFS2_RUBIN is not set
+CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
+# CONFIG_VXFS_FS is not set
+CONFIG_MINIX_FS=m
+# CONFIG_OMFS_FS is not set
+# CONFIG_HPFS_FS is not set
+# CONFIG_QNX4FS_FS is not set
+# CONFIG_ROMFS_FS is not set
+# CONFIG_SYSV_FS is not set
+# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+# CONFIG_NFS_V3_ACL is not set
+# CONFIG_NFS_V4 is not set
+CONFIG_ROOT_NFS=y
+CONFIG_NFSD=m
+CONFIG_NFSD_V3=y
+# CONFIG_NFSD_V3_ACL is not set
+# CONFIG_NFSD_V4 is not set
+CONFIG_LOCKD=y
+CONFIG_LOCKD_V4=y
+CONFIG_EXPORTFS=m
+CONFIG_NFS_COMMON=y
+CONFIG_SUNRPC=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+# CONFIG_RPCSEC_GSS_SPKM3 is not set
+CONFIG_SMB_FS=m
+# CONFIG_SMB_NLS_DEFAULT is not set
+# CONFIG_CIFS is not set
+# CONFIG_NCP_FS is not set
+# CONFIG_CODA_FS is not set
+# CONFIG_AFS_FS is not set
+
+#
+# Partition Types
+#
+CONFIG_PARTITION_ADVANCED=y
+# CONFIG_ACORN_PARTITION is not set
+# CONFIG_OSF_PARTITION is not set
+# CONFIG_AMIGA_PARTITION is not set
+# CONFIG_ATARI_PARTITION is not set
+# CONFIG_MAC_PARTITION is not set
+CONFIG_MSDOS_PARTITION=y
+# CONFIG_BSD_DISKLABEL is not set
+# CONFIG_MINIX_SUBPARTITION is not set
+# CONFIG_SOLARIS_X86_PARTITION is not set
+# CONFIG_UNIXWARE_DISKLABEL is not set
+# CONFIG_LDM_PARTITION is not set
+# CONFIG_SGI_PARTITION is not set
+# CONFIG_ULTRIX_PARTITION is not set
+# CONFIG_SUN_PARTITION is not set
+# CONFIG_KARMA_PARTITION is not set
+# CONFIG_EFI_PARTITION is not set
+# CONFIG_SYSV68_PARTITION is not set
+CONFIG_NLS=y
+CONFIG_NLS_DEFAULT="iso8859-1"
+CONFIG_NLS_CODEPAGE_437=y
+# CONFIG_NLS_CODEPAGE_737 is not set
+# CONFIG_NLS_CODEPAGE_775 is not set
+# CONFIG_NLS_CODEPAGE_850 is not set
+# CONFIG_NLS_CODEPAGE_852 is not set
+# CONFIG_NLS_CODEPAGE_855 is not set
+# CONFIG_NLS_CODEPAGE_857 is not set
+# CONFIG_NLS_CODEPAGE_860 is not set
+# CONFIG_NLS_CODEPAGE_861 is not set
+# CONFIG_NLS_CODEPAGE_862 is not set
+# CONFIG_NLS_CODEPAGE_863 is not set
+# CONFIG_NLS_CODEPAGE_864 is not set
+# CONFIG_NLS_CODEPAGE_865 is not set
+# CONFIG_NLS_CODEPAGE_866 is not set
+# CONFIG_NLS_CODEPAGE_869 is not set
+# CONFIG_NLS_CODEPAGE_936 is not set
+# CONFIG_NLS_CODEPAGE_950 is not set
+# CONFIG_NLS_CODEPAGE_932 is not set
+# CONFIG_NLS_CODEPAGE_949 is not set
+# CONFIG_NLS_CODEPAGE_874 is not set
+# CONFIG_NLS_ISO8859_8 is not set
+# CONFIG_NLS_CODEPAGE_1250 is not set
+# CONFIG_NLS_CODEPAGE_1251 is not set
+CONFIG_NLS_ASCII=m
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_NLS_ISO8859_2 is not set
+# CONFIG_NLS_ISO8859_3 is not set
+# CONFIG_NLS_ISO8859_4 is not set
+# CONFIG_NLS_ISO8859_5 is not set
+# CONFIG_NLS_ISO8859_6 is not set
+# CONFIG_NLS_ISO8859_7 is not set
+# CONFIG_NLS_ISO8859_9 is not set
+# CONFIG_NLS_ISO8859_13 is not set
+# CONFIG_NLS_ISO8859_14 is not set
+# CONFIG_NLS_ISO8859_15 is not set
+# CONFIG_NLS_KOI8_R is not set
+# CONFIG_NLS_KOI8_U is not set
+CONFIG_NLS_UTF8=m
+# CONFIG_DLM is not set
+
+#
+# Kernel hacking
+#
+# CONFIG_PRINTK_TIME is not set
+CONFIG_ENABLE_WARN_DEPRECATED=y
+CONFIG_ENABLE_MUST_CHECK=y
+CONFIG_FRAME_WARN=1024
+# CONFIG_MAGIC_SYSRQ is not set
+# CONFIG_UNUSED_SYMBOLS is not set
+CONFIG_DEBUG_FS=y
+# CONFIG_HEADERS_CHECK is not set
+CONFIG_DEBUG_KERNEL=y
+# CONFIG_DEBUG_SHIRQ is not set
+CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
+CONFIG_SCHED_DEBUG=y
+# CONFIG_SCHEDSTATS is not set
+CONFIG_TIMER_STATS=y
+# CONFIG_DEBUG_OBJECTS is not set
+# CONFIG_SLUB_DEBUG_ON is not set
+# CONFIG_SLUB_STATS is not set
+CONFIG_DEBUG_PREEMPT=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+# CONFIG_RT_MUTEX_TESTER is not set
+# CONFIG_DEBUG_SPINLOCK is not set
+CONFIG_DEBUG_MUTEXES=y
+# CONFIG_DEBUG_LOCK_ALLOC is not set
+# CONFIG_PROVE_LOCKING is not set
+# CONFIG_LOCK_STAT is not set
+# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
+# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+# CONFIG_DEBUG_KOBJECT is not set
+CONFIG_DEBUG_BUGVERBOSE=y
+# CONFIG_DEBUG_INFO is not set
+# CONFIG_DEBUG_VM is not set
+# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
+# CONFIG_DEBUG_LIST is not set
+# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
+# CONFIG_BOOT_PRINTK_DELAY is not set
+# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
+# CONFIG_FAULT_INJECTION is not set
+# CONFIG_LATENCYTOP is not set
+# CONFIG_SYSCTL_SYSCALL_CHECK is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_DYNAMIC_DEBUG is not set
+# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+# CONFIG_DEBUG_STACK_USAGE is not set
+# CONFIG_DEBUG_LL is not set
+
+#
+# Security options
+#
+# CONFIG_KEYS is not set
+# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
+# CONFIG_SECURITY_FILE_CAPABILITIES is not set
+CONFIG_CRYPTO=y
+
+#
+# Crypto core or helper
+#
+# CONFIG_CRYPTO_FIPS is not set
+# CONFIG_CRYPTO_MANAGER is not set
+# CONFIG_CRYPTO_MANAGER2 is not set
+# CONFIG_CRYPTO_GF128MUL is not set
+# CONFIG_CRYPTO_NULL is not set
+# CONFIG_CRYPTO_CRYPTD is not set
+# CONFIG_CRYPTO_AUTHENC is not set
+# CONFIG_CRYPTO_TEST is not set
+
+#
+# Authenticated Encryption with Associated Data
+#
+# CONFIG_CRYPTO_CCM is not set
+# CONFIG_CRYPTO_GCM is not set
+# CONFIG_CRYPTO_SEQIV is not set
+
+#
+# Block modes
+#
+# CONFIG_CRYPTO_CBC is not set
+# CONFIG_CRYPTO_CTR is not set
+# CONFIG_CRYPTO_CTS is not set
+# CONFIG_CRYPTO_ECB is not set
+# CONFIG_CRYPTO_LRW is not set
+# CONFIG_CRYPTO_PCBC is not set
+# CONFIG_CRYPTO_XTS is not set
+
+#
+# Hash modes
+#
+# CONFIG_CRYPTO_HMAC is not set
+# CONFIG_CRYPTO_XCBC is not set
+
+#
+# Digest
+#
+# CONFIG_CRYPTO_CRC32C is not set
+# CONFIG_CRYPTO_MD4 is not set
+# CONFIG_CRYPTO_MD5 is not set
+# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
+# CONFIG_CRYPTO_SHA1 is not set
+# CONFIG_CRYPTO_SHA256 is not set
+# CONFIG_CRYPTO_SHA512 is not set
+# CONFIG_CRYPTO_TGR192 is not set
+# CONFIG_CRYPTO_WP512 is not set
+
+#
+# Ciphers
+#
+# CONFIG_CRYPTO_AES is not set
+# CONFIG_CRYPTO_ANUBIS is not set
+# CONFIG_CRYPTO_ARC4 is not set
+# CONFIG_CRYPTO_BLOWFISH is not set
+# CONFIG_CRYPTO_CAMELLIA is not set
+# CONFIG_CRYPTO_CAST5 is not set
+# CONFIG_CRYPTO_CAST6 is not set
+# CONFIG_CRYPTO_DES is not set
+# CONFIG_CRYPTO_FCRYPT is not set
+# CONFIG_CRYPTO_KHAZAD is not set
+# CONFIG_CRYPTO_SALSA20 is not set
+# CONFIG_CRYPTO_SEED is not set
+# CONFIG_CRYPTO_SERPENT is not set
+# CONFIG_CRYPTO_TEA is not set
+# CONFIG_CRYPTO_TWOFISH is not set
+
+#
+# Compression
+#
+# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
+# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
+# CONFIG_BINARY_PRINTF is not set
+
+#
+# Library routines
+#
+CONFIG_BITREVERSE=y
+CONFIG_GENERIC_FIND_LAST_BIT=y
+CONFIG_CRC_CCITT=m
+# CONFIG_CRC16 is not set
+CONFIG_CRC_T10DIF=m
+# CONFIG_CRC_ITU_T is not set
+CONFIG_CRC32=y
+# CONFIG_CRC7 is not set
+# CONFIG_LIBCRC32C is not set
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZLIB_DEFLATE=m
+CONFIG_DECOMPRESS_GZIP=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.29-rc5
-# Tue Mar 3 21:45:57 2009
+# Linux kernel version: 2.6.30-rc4
+# Mon May 4 11:58:57 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
# CONFIG_EMBEDDED is not set
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
# CONFIG_KALLSYMS_ALL is not set
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_VM_EVENT_COUNTERS=y
CONFIG_PCI_QUIRKS=y
CONFIG_SLUB_DEBUG=y
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_KRETPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_SLABINFO=y
CONFIG_RT_MUTEXES=y
# CONFIG_MODULE_SRCVERSION_ALL is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_ORION5X is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
#
CONFIG_ARCH_FLATMEM_HAS_HOLES=y
# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_ALIGNMENT_TRAP=y
#
#
# Networking options
#
-CONFIG_COMPAT_NET_DEV_OPS=y
CONFIG_PACKET=y
CONFIG_PACKET_MMAP=y
CONFIG_UNIX=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
+CONFIG_INET_LRO=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
# CONFIG_DCB is not set
#
CONFIG_NET_PKTGEN=m
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-# CONFIG_PHONET is not set
CONFIG_WIRELESS=y
CONFIG_CFG80211=y
# CONFIG_CFG80211_REG_DEBUG is not set
-# CONFIG_NL80211 is not set
CONFIG_WIRELESS_OLD_REGULATORY=y
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
CONFIG_LIB80211=y
+# CONFIG_LIB80211_DEBUG is not set
CONFIG_MAC80211=y
#
# LPDDR flash memory drivers
#
# CONFIG_MTD_LPDDR is not set
-# CONFIG_MTD_QINFO_PROBE is not set
#
# UBI - Unsorted block images
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
# CONFIG_ENC28J60 is not set
+# CONFIG_ETHOC is not set
# CONFIG_SMC911X is not set
# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
# CONFIG_JME is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
CONFIG_LIBERTAS=y
# CONFIG_LIBERTAS_USB is not set
CONFIG_LIBERTAS_SDIO=y
+# CONFIG_LIBERTAS_SPI is not set
# CONFIG_LIBERTAS_DEBUG is not set
# CONFIG_LIBERTAS_THINFIRM is not set
-# CONFIG_HERMES is not set
# CONFIG_ATMEL is not set
+# CONFIG_AT76C50X_USB is not set
# CONFIG_PRISM54 is not set
# CONFIG_USB_ZD1201 is not set
# CONFIG_USB_NET_RNDIS_WLAN is not set
# CONFIG_RTL8187 is not set
# CONFIG_ADM8211 is not set
# CONFIG_MAC80211_HWSIM is not set
+# CONFIG_MWL8K is not set
# CONFIG_P54_COMMON is not set
# CONFIG_ATH5K is not set
# CONFIG_ATH9K is not set
+# CONFIG_AR9170_USB is not set
# CONFIG_IPW2100 is not set
# CONFIG_IPW2200 is not set
-# CONFIG_IWLCORE is not set
-# CONFIG_IWLWIFI_LEDS is not set
-# CONFIG_IWLAGN is not set
-# CONFIG_IWL3945 is not set
+# CONFIG_IWLWIFI is not set
# CONFIG_HOSTAP is not set
# CONFIG_B43 is not set
# CONFIG_B43LEGACY is not set
# CONFIG_ZD1211RW is not set
# CONFIG_RT2X00 is not set
+# CONFIG_HERMES is not set
#
# Enable WiMAX (Networking options) to see the WiMAX drivers
#
# Non-8250 serial port support
#
+# CONFIG_SERIAL_MAX3100 is not set
CONFIG_SERIAL_CORE=y
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
#
# Special HID drivers
#
-CONFIG_HID_COMPAT=y
CONFIG_HID_A4TECH=y
CONFIG_HID_APPLE=y
CONFIG_HID_BELKIN=y
CONFIG_HID_CHERRY=y
CONFIG_HID_CHICONY=y
CONFIG_HID_CYPRESS=y
+# CONFIG_DRAGONRISE_FF is not set
CONFIG_HID_EZKEY=y
+CONFIG_HID_KYE=y
CONFIG_HID_GYRATION=y
+CONFIG_HID_KENSINGTON=y
CONFIG_HID_LOGITECH=y
# CONFIG_LOGITECH_FF is not set
# CONFIG_LOGIRUMBLEPAD2_FF is not set
# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# OTG and related infrastructure
#
# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
# CONFIG_UWB is not set
CONFIG_MMC=y
# CONFIG_MMC_DEBUG is not set
#
# CONFIG_LEDS_PCA9532 is not set
CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_DAC124S085 is not set
+# CONFIG_LEDS_BD2802 is not set
#
# LED Triggers
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
# DMA Clients
#
# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
# CONFIG_DMATEST is not set
+# CONFIG_AUXDISPLAY is not set
# CONFIG_REGULATOR is not set
# CONFIG_UIO is not set
# CONFIG_STAGING is not set
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
# CONFIG_EXT4_FS is not set
CONFIG_JBD=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
#
# CD-ROM/DVD Filesystems
#
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_REGISTER_V4 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
# CONFIG_SCHED_DEBUG is not set
# CONFIG_SCHEDSTATS is not set
# CONFIG_TIMER_STATS is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
CONFIG_NOP_TRACER=y
CONFIG_HAVE_FUNCTION_TRACER=y
CONFIG_RING_BUFFER=y
CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
#
# Tracers
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
# CONFIG_BOOT_TRACER is not set
# CONFIG_TRACE_BRANCH_PROFILING is not set
# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
# CONFIG_FTRACE_STARTUP_TEST is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_PCOMP=y
CONFIG_CRYPTO_MANAGER=y
CONFIG_CRYPTO_MANAGER2=y
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=y
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
#
# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
CONFIG_LIBCRC32C=y
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.26-rc5
-# Fri Jun 13 02:57:32 2008
+# Linux kernel version: 2.6.30-rc4
+# Mon May 4 14:22:12 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
-# CONFIG_GENERIC_GPIO is not set
+CONFIG_GENERIC_GPIO=y
CONFIG_GENERIC_TIME=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_MMU=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
+CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
CONFIG_KRETPROBES=y
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_DMA_ATTRS is not set
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_SLOW_WORK is not set
+CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-# CONFIG_KMOD is not set
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_BLK_DEV_INTEGRITY is not set
#
# IO Schedulers
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# System Type
# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_CO285 is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
# CONFIG_ARCH_ORION5X is not set
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_DAVINCI is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM7X00A is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
#
# Marvell MV78xx0 Implementations
#
CONFIG_MACH_DB78X00_BP=y
CONFIG_MACH_RD78X00_MASA=y
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
CONFIG_PLAT_ORION=y
#
# CONFIG_CPU_DCACHE_DISABLE is not set
CONFIG_OUTER_CACHE=y
CONFIG_CACHE_FEROCEON_L2=y
+# CONFIG_CACHE_FEROCEON_L2_WRITETHROUGH is not set
#
# Bus support
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
#
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PREEMPT=y
CONFIG_HZ=100
CONFIG_AEABI=y
CONFIG_OABI_COMPAT=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+CONFIG_HIGHMEM=y
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
CONFIG_BOUNCE=y
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_ALIGNMENT_TRAP=y
#
# CONFIG_XIP_KERNEL is not set
# CONFIG_KEXEC is not set
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
#
# Floating point emulation
#
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# CONFIG_PM is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
-
-#
-# Networking
-#
CONFIG_NET=y
#
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
+CONFIG_INET_LRO=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
#
CONFIG_NET_PKTGEN=m
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-CONFIG_WIRELESS_EXT=y
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIRELESS is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
CONFIG_STANDALONE=y
CONFIG_PREVENT_FIRMWARE_BUILD=y
CONFIG_FW_LOADER=y
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_EXTRA_FIRMWARE=""
# CONFIG_DEBUG_DRIVER is not set
# CONFIG_DEBUG_DEVRES is not set
# CONFIG_SYS_HYPERVISOR is not set
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_IMPA7 is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
CONFIG_MTD_NAND_VERIFY_WRITE=y
# CONFIG_MTD_NAND_ECC_SMC is not set
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_CAFE is not set
CONFIG_MTD_NAND_ORION=y
# CONFIG_MTD_ONENAND is not set
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
#
# UBI - Unsorted block images
#
# CONFIG_ATA_OVER_ETH is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
+# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_NSP32 is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
+# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
#
# IEEE 1394 (FireWire) support
#
+
+#
+# Enable only one of the two stacks, unless you know what you are doing
+#
# CONFIG_FIREWIRE is not set
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
-# CONFIG_NETDEVICES_MULTIQUEUE is not set
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000 is not set
# CONFIG_E1000E is not set
-# CONFIG_E1000E_ENABLED is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
CONFIG_MV643XX_ETH=y
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
+# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
#
# USB Network Adapters
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_RAW_DRIVER is not set
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_HELPER_AUTO=y
#
# I2C Hardware Bus support
#
+
+#
+# PC SMBus host controller drivers
+#
# CONFIG_I2C_ALI1535 is not set
# CONFIG_I2C_ALI1563 is not set
# CONFIG_I2C_ALI15X3 is not set
# CONFIG_I2C_AMD756 is not set
# CONFIG_I2C_AMD8111 is not set
# CONFIG_I2C_I801 is not set
-# CONFIG_I2C_I810 is not set
+# CONFIG_I2C_ISCH is not set
# CONFIG_I2C_PIIX4 is not set
# CONFIG_I2C_NFORCE2 is not set
-# CONFIG_I2C_OCORES is not set
-# CONFIG_I2C_PARPORT_LIGHT is not set
-# CONFIG_I2C_PROSAVAGE is not set
-# CONFIG_I2C_SAVAGE4 is not set
-# CONFIG_I2C_SIMTEC is not set
# CONFIG_I2C_SIS5595 is not set
# CONFIG_I2C_SIS630 is not set
# CONFIG_I2C_SIS96X is not set
-# CONFIG_I2C_TAOS_EVM is not set
-# CONFIG_I2C_STUB is not set
-# CONFIG_I2C_TINY_USB is not set
# CONFIG_I2C_VIA is not set
# CONFIG_I2C_VIAPRO is not set
+
+#
+# I2C system bus drivers (mostly embedded / system-on-chip)
+#
+# CONFIG_I2C_GPIO is not set
+CONFIG_I2C_MV64XXX=y
+# CONFIG_I2C_OCORES is not set
+# CONFIG_I2C_SIMTEC is not set
+
+#
+# External I2C/SMBus adapter drivers
+#
+# CONFIG_I2C_PARPORT_LIGHT is not set
+# CONFIG_I2C_TAOS_EVM is not set
+# CONFIG_I2C_TINY_USB is not set
+
+#
+# Graphics adapter I2C/DDC channel drivers
+#
# CONFIG_I2C_VOODOO3 is not set
+
+#
+# Other I2C/SMBus bus drivers
+#
# CONFIG_I2C_PCA_PLATFORM is not set
-CONFIG_I2C_MV64XXX=y
+# CONFIG_I2C_STUB is not set
#
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
-# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_PCA9539 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_POWER_SUPPLY is not set
CONFIG_HWMON=y
# CONFIG_HWMON_VID is not set
+# CONFIG_SENSORS_AD7414 is not set
# CONFIG_SENSORS_AD7418 is not set
# CONFIG_SENSORS_ADM1021 is not set
# CONFIG_SENSORS_ADM1025 is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# Multifunction device drivers
#
+# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
-# CONFIG_MFD_ASIC3 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
+# CONFIG_MFD_TMIO is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
# Display device support
#
# CONFIG_DISPLAY_SUPPORT is not set
-
-#
-# Sound
-#
# CONFIG_SOUND is not set
CONFIG_HID_SUPPORT=y
CONFIG_HID=y
# USB Input Devices
#
CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
+# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=y
# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
# CONFIG_USB_STORAGE_ISD200 is not set
-CONFIG_USB_STORAGE_DPCM=y
# CONFIG_USB_STORAGE_USBAT is not set
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
#
# CONFIG_USB_MDC800 is not set
# CONFIG_USB_MICROTEK is not set
-# CONFIG_USB_MON is not set
#
# USB port drivers
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
-# CONFIG_USB_AUERSWALD is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
#
# LED drivers
#
+# CONFIG_LEDS_PCA9532 is not set
+# CONFIG_LEDS_GPIO is not set
+# CONFIG_LEDS_LP5521 is not set
+# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
#
# LED Triggers
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
CONFIG_RTC_DRV_M41T80=y
# CONFIG_RTC_DRV_M41T80_WDT is not set
# CONFIG_RTC_DRV_S35390A is not set
+# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
# CONFIG_RTC_DRV_M48T86 is not set
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# on-CPU RTC drivers
#
+# CONFIG_DMADEVICES is not set
+# CONFIG_AUXDISPLAY is not set
+# CONFIG_REGULATOR is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
#
# CD-ROM/DVD Filesystems
#
#
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
+# CONFIG_OMFS_FS is not set
# CONFIG_HPFS_FS is not set
# CONFIG_QNX4FS_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
# CONFIG_NFS_V3_ACL is not set
# CONFIG_NFS_V4 is not set
-# CONFIG_NFSD is not set
CONFIG_ROOT_NFS=y
+# CONFIG_NFSD is not set
CONFIG_LOCKD=y
CONFIG_LOCKD_V4=y
CONFIG_NFS_COMMON=y
CONFIG_SUNRPC=y
-# CONFIG_SUNRPC_BIND34 is not set
# CONFIG_RPCSEC_GSS_KRB5 is not set
# CONFIG_RPCSEC_GSS_SPKM3 is not set
# CONFIG_SMB_FS is not set
CONFIG_FRAME_WARN=1024
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
+# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
+CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
CONFIG_SCHEDSTATS=y
# CONFIG_TIMER_STATS is not set
# CONFIG_LOCK_STAT is not set
# CONFIG_DEBUG_SPINLOCK_SLEEP is not set
# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set
+CONFIG_STACKTRACE=y
# CONFIG_DEBUG_KOBJECT is not set
+# CONFIG_DEBUG_HIGHMEM is not set
# CONFIG_DEBUG_BUGVERBOSE is not set
CONFIG_DEBUG_INFO=y
# CONFIG_DEBUG_VM is not set
# CONFIG_DEBUG_WRITECOUNT is not set
+# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
-CONFIG_FRAME_POINTER=y
+# CONFIG_DEBUG_NOTIFIERS is not set
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_KPROBES_SANITY_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
# CONFIG_LATENCYTOP is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
+# CONFIG_IRQSOFF_TRACER is not set
+# CONFIG_PREEMPT_TRACER is not set
+# CONFIG_SCHED_TRACER is not set
+# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
+CONFIG_HAVE_ARCH_KGDB=y
+# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_STACK_USAGE is not set
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=m
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
# CONFIG_CRYPTO_MD4 is not set
# CONFIG_CRYPTO_MD5 is not set
# CONFIG_CRYPTO_MICHAEL_MIC is not set
+# CONFIG_CRYPTO_RMD128 is not set
+# CONFIG_CRYPTO_RMD160 is not set
+# CONFIG_CRYPTO_RMD256 is not set
+# CONFIG_CRYPTO_RMD320 is not set
# CONFIG_CRYPTO_SHA1 is not set
# CONFIG_CRYPTO_SHA256 is not set
# CONFIG_CRYPTO_SHA512 is not set
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=m
+# CONFIG_CRC_T10DIF is not set
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
# CONFIG_CRC7 is not set
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
+++ /dev/null
-#
-# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc5
-# Fri Oct 24 11:41:22 2008
-#
-CONFIG_ARM=y
-CONFIG_SYS_SUPPORTS_APM_EMULATION=y
-CONFIG_GENERIC_GPIO=y
-CONFIG_GENERIC_TIME=y
-CONFIG_GENERIC_CLOCKEVENTS=y
-CONFIG_MMU=y
-# CONFIG_NO_IOPORT is not set
-CONFIG_GENERIC_HARDIRQS=y
-CONFIG_STACKTRACE_SUPPORT=y
-CONFIG_HAVE_LATENCYTOP_SUPPORT=y
-CONFIG_LOCKDEP_SUPPORT=y
-CONFIG_TRACE_IRQFLAGS_SUPPORT=y
-CONFIG_HARDIRQS_SW_RESEND=y
-CONFIG_GENERIC_IRQ_PROBE=y
-CONFIG_RWSEM_GENERIC_SPINLOCK=y
-# CONFIG_ARCH_HAS_ILOG2_U32 is not set
-# CONFIG_ARCH_HAS_ILOG2_U64 is not set
-CONFIG_GENERIC_HWEIGHT=y
-CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
-CONFIG_ARCH_MTD_XIP=y
-CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
-CONFIG_VECTORS_BASE=0xffff0000
-CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
-
-#
-# General setup
-#
-CONFIG_EXPERIMENTAL=y
-CONFIG_BROKEN_ON_SMP=y
-CONFIG_LOCK_KERNEL=y
-CONFIG_INIT_ENV_ARG_LIMIT=32
-CONFIG_LOCALVERSION=""
-CONFIG_LOCALVERSION_AUTO=y
-CONFIG_SWAP=y
-CONFIG_SYSVIPC=y
-CONFIG_SYSVIPC_SYSCTL=y
-# CONFIG_POSIX_MQUEUE is not set
-# CONFIG_BSD_PROCESS_ACCT is not set
-# CONFIG_TASKSTATS is not set
-# CONFIG_AUDIT is not set
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
-CONFIG_GROUP_SCHED=y
-CONFIG_FAIR_GROUP_SCHED=y
-# CONFIG_RT_GROUP_SCHED is not set
-CONFIG_USER_SCHED=y
-# CONFIG_CGROUP_SCHED is not set
-CONFIG_SYSFS_DEPRECATED=y
-CONFIG_SYSFS_DEPRECATED_V2=y
-# CONFIG_RELAY is not set
-# CONFIG_NAMESPACES is not set
-# CONFIG_BLK_DEV_INITRD is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
-CONFIG_SYSCTL=y
-CONFIG_EMBEDDED=y
-CONFIG_UID16=y
-CONFIG_SYSCTL_SYSCALL=y
-CONFIG_KALLSYMS=y
-# CONFIG_KALLSYMS_EXTRA_PASS is not set
-CONFIG_HOTPLUG=y
-CONFIG_PRINTK=y
-CONFIG_BUG=y
-CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
-CONFIG_BASE_FULL=y
-CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
-CONFIG_EPOLL=y
-CONFIG_SIGNALFD=y
-CONFIG_TIMERFD=y
-CONFIG_EVENTFD=y
-CONFIG_SHMEM=y
-CONFIG_VM_EVENT_COUNTERS=y
-CONFIG_SLAB=y
-# CONFIG_SLUB is not set
-# CONFIG_SLOB is not set
-# CONFIG_PROFILING is not set
-# CONFIG_MARKERS is not set
-CONFIG_HAVE_OPROFILE=y
-# CONFIG_KPROBES is not set
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_HAVE_IOREMAP_PROT is not set
-CONFIG_HAVE_KPROBES=y
-CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
-CONFIG_HAVE_GENERIC_DMA_COHERENT=y
-CONFIG_SLABINFO=y
-CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
-CONFIG_BASE_SMALL=0
-CONFIG_MODULES=y
-# CONFIG_MODULE_FORCE_LOAD is not set
-CONFIG_MODULE_UNLOAD=y
-CONFIG_MODULE_FORCE_UNLOAD=y
-CONFIG_MODVERSIONS=y
-# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
-CONFIG_BLOCK=y
-# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_BLK_DEV_INTEGRITY is not set
-
-#
-# IO Schedulers
-#
-CONFIG_IOSCHED_NOOP=y
-CONFIG_IOSCHED_AS=y
-CONFIG_IOSCHED_DEADLINE=y
-CONFIG_IOSCHED_CFQ=y
-# CONFIG_DEFAULT_AS is not set
-# CONFIG_DEFAULT_DEADLINE is not set
-CONFIG_DEFAULT_CFQ=y
-# CONFIG_DEFAULT_NOOP is not set
-CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
-
-#
-# System Type
-#
-# CONFIG_ARCH_AAEC2000 is not set
-# CONFIG_ARCH_INTEGRATOR is not set
-# CONFIG_ARCH_REALVIEW is not set
-# CONFIG_ARCH_VERSATILE is not set
-# CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
-# CONFIG_ARCH_CLPS711X is not set
-# CONFIG_ARCH_EBSA110 is not set
-# CONFIG_ARCH_EP93XX is not set
-# CONFIG_ARCH_FOOTBRIDGE is not set
-# CONFIG_ARCH_NETX is not set
-# CONFIG_ARCH_H720X is not set
-# CONFIG_ARCH_IMX is not set
-# CONFIG_ARCH_IOP13XX is not set
-# CONFIG_ARCH_IOP32X is not set
-# CONFIG_ARCH_IOP33X is not set
-# CONFIG_ARCH_IXP23XX is not set
-# CONFIG_ARCH_IXP2000 is not set
-# CONFIG_ARCH_IXP4XX is not set
-# CONFIG_ARCH_L7200 is not set
-# CONFIG_ARCH_KIRKWOOD is not set
-# CONFIG_ARCH_KS8695 is not set
-# CONFIG_ARCH_NS9XXX is not set
-# CONFIG_ARCH_LOKI is not set
-# CONFIG_ARCH_MV78XX0 is not set
-CONFIG_ARCH_MXC=y
-# CONFIG_ARCH_ORION5X is not set
-# CONFIG_ARCH_PNX4008 is not set
-# CONFIG_ARCH_PXA is not set
-# CONFIG_ARCH_RPC is not set
-# CONFIG_ARCH_SA1100 is not set
-# CONFIG_ARCH_S3C2410 is not set
-# CONFIG_ARCH_SHARK is not set
-# CONFIG_ARCH_LH7A40X is not set
-# CONFIG_ARCH_DAVINCI is not set
-# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM7X00A is not set
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
-
-#
-# Freescale MXC Implementations
-#
-# CONFIG_ARCH_MX2 is not set
-CONFIG_ARCH_MX3=y
-
-#
-# MX3 Options
-#
-# CONFIG_MACH_MX31ADS is not set
-# CONFIG_MACH_PCM037 is not set
-# CONFIG_MACH_MX31LITE is not set
-CONFIG_MACH_MX31MOBOARD=y
-# CONFIG_MXC_IRQ_PRIOR is not set
-
-#
-# Processor Type
-#
-CONFIG_CPU_32=y
-CONFIG_CPU_V6=y
-# CONFIG_CPU_32v6K is not set
-CONFIG_CPU_32v6=y
-CONFIG_CPU_ABRT_EV6=y
-CONFIG_CPU_PABRT_NOIFAR=y
-CONFIG_CPU_CACHE_V6=y
-CONFIG_CPU_CACHE_VIPT=y
-CONFIG_CPU_COPY_V6=y
-CONFIG_CPU_TLB_V6=y
-CONFIG_CPU_HAS_ASID=y
-CONFIG_CPU_CP15=y
-CONFIG_CPU_CP15_MMU=y
-
-#
-# Processor Features
-#
-CONFIG_ARM_THUMB=y
-# CONFIG_CPU_ICACHE_DISABLE is not set
-# CONFIG_CPU_DCACHE_DISABLE is not set
-# CONFIG_CPU_BPREDICT_DISABLE is not set
-# CONFIG_OUTER_CACHE is not set
-
-#
-# Bus support
-#
-# CONFIG_PCI_SYSCALL is not set
-# CONFIG_ARCH_SUPPORTS_MSI is not set
-# CONFIG_PCCARD is not set
-
-#
-# Kernel Features
-#
-CONFIG_TICK_ONESHOT=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
-CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
-CONFIG_PREEMPT=y
-CONFIG_HZ=100
-CONFIG_AEABI=y
-# CONFIG_OABI_COMPAT is not set
-CONFIG_ARCH_FLATMEM_HAS_HOLES=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
-CONFIG_SELECT_MEMORY_MODEL=y
-CONFIG_FLATMEM_MANUAL=y
-# CONFIG_DISCONTIGMEM_MANUAL is not set
-# CONFIG_SPARSEMEM_MANUAL is not set
-CONFIG_FLATMEM=y
-CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
-CONFIG_PAGEFLAGS_EXTENDED=y
-CONFIG_SPLIT_PTLOCK_CPUS=4
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
-CONFIG_VIRT_TO_BUS=y
-CONFIG_ALIGNMENT_TRAP=y
-
-#
-# Boot options
-#
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="noinitrd console=ttymxc0,115200 root=/dev/mtdblock2 rw ip=off"
-# CONFIG_XIP_KERNEL is not set
-# CONFIG_KEXEC is not set
-
-#
-# Floating point emulation
-#
-
-#
-# At least one emulation must be selected
-#
-CONFIG_VFP=y
-
-#
-# Userspace binary formats
-#
-CONFIG_BINFMT_ELF=y
-# CONFIG_BINFMT_AOUT is not set
-# CONFIG_BINFMT_MISC is not set
-
-#
-# Power management options
-#
-# CONFIG_PM is not set
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-CONFIG_NET=y
-
-#
-# Networking options
-#
-CONFIG_PACKET=y
-# CONFIG_PACKET_MMAP is not set
-CONFIG_UNIX=y
-# CONFIG_NET_KEY is not set
-CONFIG_INET=y
-# CONFIG_IP_MULTICAST is not set
-# CONFIG_IP_ADVANCED_ROUTER is not set
-CONFIG_IP_FIB_HASH=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-# CONFIG_IP_PNP_BOOTP is not set
-# CONFIG_IP_PNP_RARP is not set
-# CONFIG_NET_IPIP is not set
-# CONFIG_NET_IPGRE is not set
-# CONFIG_ARPD is not set
-# CONFIG_SYN_COOKIES is not set
-# CONFIG_INET_AH is not set
-# CONFIG_INET_ESP is not set
-# CONFIG_INET_IPCOMP is not set
-# CONFIG_INET_XFRM_TUNNEL is not set
-# CONFIG_INET_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
-# CONFIG_INET_XFRM_MODE_TUNNEL is not set
-# CONFIG_INET_XFRM_MODE_BEET is not set
-# CONFIG_INET_LRO is not set
-# CONFIG_INET_DIAG is not set
-# CONFIG_TCP_CONG_ADVANCED is not set
-CONFIG_TCP_CONG_CUBIC=y
-CONFIG_DEFAULT_TCP_CONG="cubic"
-# CONFIG_TCP_MD5SIG is not set
-# CONFIG_IPV6 is not set
-# CONFIG_NETWORK_SECMARK is not set
-# CONFIG_NETFILTER is not set
-# CONFIG_IP_DCCP is not set
-# CONFIG_IP_SCTP is not set
-# CONFIG_TIPC is not set
-# CONFIG_ATM is not set
-# CONFIG_BRIDGE is not set
-# CONFIG_VLAN_8021Q is not set
-# CONFIG_DECNET is not set
-# CONFIG_LLC2 is not set
-# CONFIG_IPX is not set
-# CONFIG_ATALK is not set
-# CONFIG_X25 is not set
-# CONFIG_LAPB is not set
-# CONFIG_ECONET is not set
-# CONFIG_WAN_ROUTER is not set
-# CONFIG_NET_SCHED is not set
-
-#
-# Network testing
-#
-# CONFIG_NET_PKTGEN is not set
-# CONFIG_HAMRADIO is not set
-# CONFIG_CAN is not set
-# CONFIG_IRDA is not set
-# CONFIG_BT is not set
-# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
-# CONFIG_CFG80211 is not set
-# CONFIG_WIRELESS_EXT is not set
-# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
-# CONFIG_RFKILL is not set
-# CONFIG_NET_9P is not set
-
-#
-# Device Drivers
-#
-
-#
-# Generic Driver Options
-#
-CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
-CONFIG_STANDALONE=y
-CONFIG_PREVENT_FIRMWARE_BUILD=y
-CONFIG_FW_LOADER=m
-CONFIG_FIRMWARE_IN_KERNEL=y
-CONFIG_EXTRA_FIRMWARE=""
-# CONFIG_SYS_HYPERVISOR is not set
-# CONFIG_CONNECTOR is not set
-CONFIG_MTD=y
-# CONFIG_MTD_DEBUG is not set
-# CONFIG_MTD_CONCAT is not set
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_REDBOOT_PARTS=y
-CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-1
-# CONFIG_MTD_REDBOOT_PARTS_UNALLOCATED is not set
-CONFIG_MTD_REDBOOT_PARTS_READONLY=y
-# CONFIG_MTD_CMDLINE_PARTS is not set
-# CONFIG_MTD_AFS_PARTS is not set
-# CONFIG_MTD_AR7_PARTS is not set
-
-#
-# User Modules And Translation Layers
-#
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLKDEVS=y
-CONFIG_MTD_BLOCK=y
-# CONFIG_FTL is not set
-# CONFIG_NFTL is not set
-# CONFIG_INFTL is not set
-# CONFIG_RFD_FTL is not set
-# CONFIG_SSFDC is not set
-# CONFIG_MTD_OOPS is not set
-
-#
-# RAM/ROM/Flash chip drivers
-#
-CONFIG_MTD_CFI=y
-# CONFIG_MTD_JEDECPROBE is not set
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_NOSWAP=y
-# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set
-# CONFIG_MTD_CFI_LE_BYTE_SWAP is not set
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set
-# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set
-CONFIG_MTD_CFI_I1=y
-# CONFIG_MTD_CFI_I2 is not set
-# CONFIG_MTD_CFI_I4 is not set
-# CONFIG_MTD_CFI_I8 is not set
-# CONFIG_MTD_OTP is not set
-# CONFIG_MTD_CFI_INTELEXT is not set
-CONFIG_MTD_CFI_AMDSTD=y
-# CONFIG_MTD_CFI_STAA is not set
-CONFIG_MTD_CFI_UTIL=y
-# CONFIG_MTD_RAM is not set
-# CONFIG_MTD_ROM is not set
-# CONFIG_MTD_ABSENT is not set
-# CONFIG_MTD_XIP is not set
-
-#
-# Mapping drivers for chip access
-#
-# CONFIG_MTD_COMPLEX_MAPPINGS is not set
-CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=2
-# CONFIG_MTD_ARM_INTEGRATOR is not set
-# CONFIG_MTD_PLATRAM is not set
-
-#
-# Self-contained MTD device drivers
-#
-# CONFIG_MTD_SLRAM is not set
-# CONFIG_MTD_PHRAM is not set
-# CONFIG_MTD_MTDRAM is not set
-# CONFIG_MTD_BLOCK2MTD is not set
-
-#
-# Disk-On-Chip Device Drivers
-#
-# CONFIG_MTD_DOC2000 is not set
-# CONFIG_MTD_DOC2001 is not set
-# CONFIG_MTD_DOC2001PLUS is not set
-# CONFIG_MTD_NAND is not set
-# CONFIG_MTD_ONENAND is not set
-
-#
-# UBI - Unsorted block images
-#
-# CONFIG_MTD_UBI is not set
-# CONFIG_PARPORT is not set
-# CONFIG_BLK_DEV is not set
-# CONFIG_MISC_DEVICES is not set
-CONFIG_HAVE_IDE=y
-# CONFIG_IDE is not set
-
-#
-# SCSI device support
-#
-# CONFIG_RAID_ATTRS is not set
-# CONFIG_SCSI is not set
-# CONFIG_SCSI_DMA is not set
-# CONFIG_SCSI_NETLINK is not set
-# CONFIG_ATA is not set
-# CONFIG_MD is not set
-CONFIG_NETDEVICES=y
-# CONFIG_DUMMY is not set
-# CONFIG_BONDING is not set
-# CONFIG_MACVLAN is not set
-# CONFIG_EQUALIZER is not set
-# CONFIG_TUN is not set
-# CONFIG_VETH is not set
-# CONFIG_PHYLIB is not set
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-# CONFIG_AX88796 is not set
-CONFIG_SMC91X=y
-# CONFIG_DM9000 is not set
-# CONFIG_IBM_NEW_EMAC_ZMII is not set
-# CONFIG_IBM_NEW_EMAC_RGMII is not set
-# CONFIG_IBM_NEW_EMAC_TAH is not set
-# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
-# CONFIG_B44 is not set
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-
-#
-# Wireless LAN
-#
-# CONFIG_WLAN_PRE80211 is not set
-# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
-# CONFIG_WAN is not set
-# CONFIG_PPP is not set
-# CONFIG_SLIP is not set
-# CONFIG_NETCONSOLE is not set
-# CONFIG_NETPOLL is not set
-# CONFIG_NET_POLL_CONTROLLER is not set
-# CONFIG_ISDN is not set
-
-#
-# Input device support
-#
-# CONFIG_INPUT is not set
-
-#
-# Hardware I/O ports
-#
-# CONFIG_SERIO is not set
-# CONFIG_GAMEPORT is not set
-
-#
-# Character devices
-#
-# CONFIG_VT is not set
-CONFIG_DEVKMEM=y
-# CONFIG_SERIAL_NONSTANDARD is not set
-
-#
-# Serial drivers
-#
-# CONFIG_SERIAL_8250 is not set
-
-#
-# Non-8250 serial port support
-#
-CONFIG_SERIAL_IMX=y
-CONFIG_SERIAL_IMX_CONSOLE=y
-CONFIG_SERIAL_CORE=y
-CONFIG_SERIAL_CORE_CONSOLE=y
-CONFIG_UNIX98_PTYS=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_IPMI_HANDLER is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
-# CONFIG_R3964 is not set
-# CONFIG_RAW_DRIVER is not set
-# CONFIG_TCG_TPM is not set
-# CONFIG_I2C is not set
-# CONFIG_SPI is not set
-CONFIG_ARCH_REQUIRE_GPIOLIB=y
-CONFIG_GPIOLIB=y
-# CONFIG_GPIO_SYSFS is not set
-
-#
-# I2C GPIO expanders:
-#
-
-#
-# PCI GPIO expanders:
-#
-
-#
-# SPI GPIO expanders:
-#
-# CONFIG_W1 is not set
-# CONFIG_POWER_SUPPLY is not set
-# CONFIG_HWMON is not set
-# CONFIG_WATCHDOG is not set
-
-#
-# Sonics Silicon Backplane
-#
-CONFIG_SSB_POSSIBLE=y
-# CONFIG_SSB is not set
-
-#
-# Multifunction device drivers
-#
-# CONFIG_MFD_CORE is not set
-# CONFIG_MFD_SM501 is not set
-# CONFIG_HTC_EGPIO is not set
-# CONFIG_HTC_PASIC3 is not set
-# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_T7L66XB is not set
-# CONFIG_MFD_TC6387XB is not set
-# CONFIG_MFD_TC6393XB is not set
-
-#
-# Multimedia devices
-#
-
-#
-# Multimedia core support
-#
-# CONFIG_VIDEO_DEV is not set
-# CONFIG_DVB_CORE is not set
-# CONFIG_VIDEO_MEDIA is not set
-
-#
-# Multimedia drivers
-#
-# CONFIG_DAB is not set
-
-#
-# Graphics support
-#
-# CONFIG_VGASTATE is not set
-# CONFIG_VIDEO_OUTPUT_CONTROL is not set
-# CONFIG_FB is not set
-# CONFIG_BACKLIGHT_LCD_SUPPORT is not set
-
-#
-# Display device support
-#
-# CONFIG_DISPLAY_SUPPORT is not set
-# CONFIG_SOUND is not set
-# CONFIG_USB_SUPPORT is not set
-# CONFIG_MMC is not set
-# CONFIG_NEW_LEDS is not set
-CONFIG_RTC_LIB=y
-# CONFIG_RTC_CLASS is not set
-# CONFIG_DMADEVICES is not set
-
-#
-# Voltage and Current regulators
-#
-# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
-# CONFIG_UIO is not set
-
-#
-# File systems
-#
-# CONFIG_EXT2_FS is not set
-# CONFIG_EXT3_FS is not set
-# CONFIG_EXT4DEV_FS is not set
-# CONFIG_REISERFS_FS is not set
-# CONFIG_JFS_FS is not set
-# CONFIG_FS_POSIX_ACL is not set
-# CONFIG_XFS_FS is not set
-# CONFIG_OCFS2_FS is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
-CONFIG_INOTIFY_USER=y
-# CONFIG_QUOTA is not set
-# CONFIG_AUTOFS_FS is not set
-# CONFIG_AUTOFS4_FS is not set
-# CONFIG_FUSE_FS is not set
-
-#
-# CD-ROM/DVD Filesystems
-#
-# CONFIG_ISO9660_FS is not set
-# CONFIG_UDF_FS is not set
-
-#
-# DOS/FAT/NT Filesystems
-#
-# CONFIG_MSDOS_FS is not set
-# CONFIG_VFAT_FS is not set
-# CONFIG_NTFS_FS is not set
-
-#
-# Pseudo filesystems
-#
-CONFIG_PROC_FS=y
-CONFIG_PROC_SYSCTL=y
-CONFIG_SYSFS=y
-CONFIG_TMPFS=y
-# CONFIG_TMPFS_POSIX_ACL is not set
-# CONFIG_HUGETLB_PAGE is not set
-# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
-# CONFIG_ADFS_FS is not set
-# CONFIG_AFFS_FS is not set
-# CONFIG_HFS_FS is not set
-# CONFIG_HFSPLUS_FS is not set
-# CONFIG_BEFS_FS is not set
-# CONFIG_BFS_FS is not set
-# CONFIG_EFS_FS is not set
-CONFIG_JFFS2_FS=y
-CONFIG_JFFS2_FS_DEBUG=0
-CONFIG_JFFS2_FS_WRITEBUFFER=y
-# CONFIG_JFFS2_FS_WBUF_VERIFY is not set
-# CONFIG_JFFS2_SUMMARY is not set
-# CONFIG_JFFS2_FS_XATTR is not set
-# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set
-CONFIG_JFFS2_ZLIB=y
-# CONFIG_JFFS2_LZO is not set
-CONFIG_JFFS2_RTIME=y
-# CONFIG_JFFS2_RUBIN is not set
-# CONFIG_CRAMFS is not set
-# CONFIG_VXFS_FS is not set
-# CONFIG_MINIX_FS is not set
-# CONFIG_OMFS_FS is not set
-# CONFIG_HPFS_FS is not set
-# CONFIG_QNX4FS_FS is not set
-# CONFIG_ROMFS_FS is not set
-# CONFIG_SYSV_FS is not set
-# CONFIG_UFS_FS is not set
-CONFIG_NETWORK_FILESYSTEMS=y
-CONFIG_NFS_FS=y
-# CONFIG_NFS_V3 is not set
-# CONFIG_NFS_V4 is not set
-CONFIG_ROOT_NFS=y
-# CONFIG_NFSD is not set
-CONFIG_LOCKD=y
-CONFIG_NFS_COMMON=y
-CONFIG_SUNRPC=y
-# CONFIG_RPCSEC_GSS_KRB5 is not set
-# CONFIG_RPCSEC_GSS_SPKM3 is not set
-# CONFIG_SMB_FS is not set
-# CONFIG_CIFS is not set
-# CONFIG_NCP_FS is not set
-# CONFIG_CODA_FS is not set
-# CONFIG_AFS_FS is not set
-
-#
-# Partition Types
-#
-# CONFIG_PARTITION_ADVANCED is not set
-CONFIG_MSDOS_PARTITION=y
-# CONFIG_NLS is not set
-# CONFIG_DLM is not set
-
-#
-# Kernel hacking
-#
-# CONFIG_PRINTK_TIME is not set
-# CONFIG_ENABLE_WARN_DEPRECATED is not set
-# CONFIG_ENABLE_MUST_CHECK is not set
-CONFIG_FRAME_WARN=1024
-# CONFIG_MAGIC_SYSRQ is not set
-# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
-# CONFIG_HEADERS_CHECK is not set
-# CONFIG_DEBUG_KERNEL is not set
-# CONFIG_DEBUG_BUGVERBOSE is not set
-# CONFIG_DEBUG_MEMORY_INIT is not set
-CONFIG_FRAME_POINTER=y
-# CONFIG_LATENCYTOP is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
-# CONFIG_IRQSOFF_TRACER is not set
-# CONFIG_PREEMPT_TRACER is not set
-# CONFIG_SCHED_TRACER is not set
-# CONFIG_CONTEXT_SWITCH_TRACER is not set
-# CONFIG_SAMPLES is not set
-CONFIG_HAVE_ARCH_KGDB=y
-# CONFIG_DEBUG_USER is not set
-
-#
-# Security options
-#
-# CONFIG_KEYS is not set
-# CONFIG_SECURITY is not set
-# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-# CONFIG_CRYPTO is not set
-
-#
-# Library routines
-#
-CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
-# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
-# CONFIG_CRC_T10DIF is not set
-# CONFIG_CRC_ITU_T is not set
-CONFIG_CRC32=y
-# CONFIG_CRC7 is not set
-# CONFIG_LIBCRC32C is not set
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_DMA=y
#
CONFIG_CPU_32=y
CONFIG_CPU_V6=y
-CONFIG_CPU_32v6K=y
+# CONFIG_CPU_32v6K is not set
CONFIG_CPU_32v6=y
CONFIG_CPU_ABRT_EV6=y
CONFIG_CPU_PABRT_NOIFAR=y
#
# Automatically generated make config: don't edit
-# Linux kernel version: 2.6.27-rc4
-# Fri Aug 22 12:38:51 2008
+# Linux kernel version: 2.6.30-rc4
+# Mon May 4 14:07:25 2009
#
CONFIG_ARM=y
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
CONFIG_GENERIC_HWEIGHT=y
CONFIG_GENERIC_CALIBRATE_DELAY=y
-CONFIG_ARCH_SUPPORTS_AOUT=y
-CONFIG_ZONE_DMA=y
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
CONFIG_VECTORS_BASE=0xffff0000
CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config"
# CONFIG_BSD_PROCESS_ACCT is not set
# CONFIG_TASKSTATS is not set
# CONFIG_AUDIT is not set
+
+#
+# RCU Subsystem
+#
+CONFIG_CLASSIC_RCU=y
+# CONFIG_TREE_RCU is not set
+# CONFIG_PREEMPT_RCU is not set
+# CONFIG_TREE_RCU_TRACE is not set
+# CONFIG_PREEMPT_RCU_TRACE is not set
# CONFIG_IKCONFIG is not set
CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CGROUPS is not set
# CONFIG_GROUP_SCHED is not set
+# CONFIG_CGROUPS is not set
CONFIG_SYSFS_DEPRECATED=y
CONFIG_SYSFS_DEPRECATED_V2=y
# CONFIG_RELAY is not set
# CONFIG_BLK_DEV_INITRD is not set
CONFIG_CC_OPTIMIZE_FOR_SIZE=y
CONFIG_SYSCTL=y
+CONFIG_ANON_INODES=y
CONFIG_EMBEDDED=y
CONFIG_UID16=y
CONFIG_SYSCTL_SYSCALL=y
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
# CONFIG_KALLSYMS_EXTRA_PASS is not set
+# CONFIG_STRIP_ASM_SYMS is not set
CONFIG_HOTPLUG=y
CONFIG_PRINTK=y
CONFIG_BUG=y
CONFIG_ELF_CORE=y
-CONFIG_COMPAT_BRK=y
CONFIG_BASE_FULL=y
CONFIG_FUTEX=y
-CONFIG_ANON_INODES=y
CONFIG_EPOLL=y
CONFIG_SIGNALFD=y
CONFIG_TIMERFD=y
CONFIG_EVENTFD=y
CONFIG_SHMEM=y
+CONFIG_AIO=y
CONFIG_VM_EVENT_COUNTERS=y
+CONFIG_PCI_QUIRKS=y
# CONFIG_SLUB_DEBUG is not set
+CONFIG_COMPAT_BRK=y
# CONFIG_SLAB is not set
CONFIG_SLUB=y
# CONFIG_SLOB is not set
CONFIG_PROFILING=y
+CONFIG_TRACEPOINTS=y
# CONFIG_MARKERS is not set
CONFIG_OPROFILE=y
CONFIG_HAVE_OPROFILE=y
CONFIG_KPROBES=y
-# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set
CONFIG_KRETPROBES=y
-# CONFIG_HAVE_IOREMAP_PROT is not set
CONFIG_HAVE_KPROBES=y
CONFIG_HAVE_KRETPROBES=y
-# CONFIG_HAVE_ARCH_TRACEHOOK is not set
-# CONFIG_HAVE_DMA_ATTRS is not set
-# CONFIG_USE_GENERIC_SMP_HELPERS is not set
-# CONFIG_HAVE_CLK is not set
-CONFIG_PROC_PAGE_MONITOR=y
+# CONFIG_SLOW_WORK is not set
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
CONFIG_RT_MUTEXES=y
-# CONFIG_TINY_SHMEM is not set
CONFIG_BASE_SMALL=0
CONFIG_MODULES=y
# CONFIG_MODULE_FORCE_LOAD is not set
# CONFIG_MODULE_FORCE_UNLOAD is not set
# CONFIG_MODVERSIONS is not set
# CONFIG_MODULE_SRCVERSION_ALL is not set
-CONFIG_KMOD=y
CONFIG_BLOCK=y
# CONFIG_LBD is not set
-# CONFIG_BLK_DEV_IO_TRACE is not set
-# CONFIG_LSF is not set
# CONFIG_BLK_DEV_BSG is not set
# CONFIG_BLK_DEV_INTEGRITY is not set
CONFIG_DEFAULT_CFQ=y
# CONFIG_DEFAULT_NOOP is not set
CONFIG_DEFAULT_IOSCHED="cfq"
-CONFIG_CLASSIC_RCU=y
+# CONFIG_FREEZER is not set
#
# System Type
# CONFIG_ARCH_REALVIEW is not set
# CONFIG_ARCH_VERSATILE is not set
# CONFIG_ARCH_AT91 is not set
-# CONFIG_ARCH_CLPS7500 is not set
# CONFIG_ARCH_CLPS711X is not set
# CONFIG_ARCH_EBSA110 is not set
# CONFIG_ARCH_EP93XX is not set
+# CONFIG_ARCH_GEMINI is not set
# CONFIG_ARCH_FOOTBRIDGE is not set
# CONFIG_ARCH_NETX is not set
# CONFIG_ARCH_H720X is not set
CONFIG_ARCH_ORION5X=y
# CONFIG_ARCH_PNX4008 is not set
# CONFIG_ARCH_PXA is not set
+# CONFIG_ARCH_MMP is not set
# CONFIG_ARCH_RPC is not set
# CONFIG_ARCH_SA1100 is not set
# CONFIG_ARCH_S3C2410 is not set
+# CONFIG_ARCH_S3C64XX is not set
# CONFIG_ARCH_SHARK is not set
# CONFIG_ARCH_LH7A40X is not set
# CONFIG_ARCH_DAVINCI is not set
# CONFIG_ARCH_OMAP is not set
-# CONFIG_ARCH_MSM7X00A is not set
+# CONFIG_ARCH_MSM is not set
+# CONFIG_ARCH_W90X900 is not set
#
# Orion Implementations
CONFIG_MACH_KUROBOX_PRO=y
CONFIG_MACH_DNS323=y
CONFIG_MACH_TS209=y
+CONFIG_MACH_TERASTATION_PRO2=y
CONFIG_MACH_LINKSTATION_PRO=y
CONFIG_MACH_LINKSTATION_MINI=y
CONFIG_MACH_TS409=y
CONFIG_MACH_RD88F5181L_GE=y
CONFIG_MACH_RD88F5181L_FXO=y
CONFIG_MACH_RD88F6183AP_GE=y
-
-#
-# Boot options
-#
-
-#
-# Power management
-#
CONFIG_PLAT_ORION=y
#
# CONFIG_ARCH_SUPPORTS_MSI is not set
CONFIG_PCI_LEGACY=y
# CONFIG_PCI_DEBUG is not set
+# CONFIG_PCI_STUB is not set
+# CONFIG_PCI_IOV is not set
# CONFIG_PCCARD is not set
#
CONFIG_NO_HZ=y
CONFIG_HIGH_RES_TIMERS=y
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
+CONFIG_VMSPLIT_3G=y
+# CONFIG_VMSPLIT_2G is not set
+# CONFIG_VMSPLIT_1G is not set
+CONFIG_PAGE_OFFSET=0xC0000000
CONFIG_PREEMPT=y
CONFIG_HZ=100
CONFIG_AEABI=y
CONFIG_OABI_COMPAT=y
-# CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set
+CONFIG_ARCH_FLATMEM_HAS_HOLES=y
+# CONFIG_ARCH_SPARSEMEM_DEFAULT is not set
+# CONFIG_ARCH_SELECT_MEMORY_MODEL is not set
+# CONFIG_HIGHMEM is not set
CONFIG_SELECT_MEMORY_MODEL=y
CONFIG_FLATMEM_MANUAL=y
# CONFIG_DISCONTIGMEM_MANUAL is not set
# CONFIG_SPARSEMEM_MANUAL is not set
CONFIG_FLATMEM=y
CONFIG_FLAT_NODE_MEM_MAP=y
-# CONFIG_SPARSEMEM_STATIC is not set
-# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set
CONFIG_PAGEFLAGS_EXTENDED=y
CONFIG_SPLIT_PTLOCK_CPUS=4096
-# CONFIG_RESOURCES_64BIT is not set
-CONFIG_ZONE_DMA_FLAG=1
-CONFIG_BOUNCE=y
+# CONFIG_PHYS_ADDR_T_64BIT is not set
+CONFIG_ZONE_DMA_FLAG=0
CONFIG_VIRT_TO_BUS=y
+CONFIG_UNEVICTABLE_LRU=y
+CONFIG_HAVE_MLOCK=y
+CONFIG_HAVE_MLOCKED_PAGE_BIT=y
CONFIG_LEDS=y
CONFIG_LEDS_CPU=y
CONFIG_ALIGNMENT_TRAP=y
# CONFIG_XIP_KERNEL is not set
# CONFIG_KEXEC is not set
+#
+# CPU Power Management
+#
+# CONFIG_CPU_IDLE is not set
+
#
# Floating point emulation
#
# Userspace binary formats
#
CONFIG_BINFMT_ELF=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_HAVE_AOUT=y
# CONFIG_BINFMT_AOUT is not set
# CONFIG_BINFMT_MISC is not set
#
# Power management options
#
-# CONFIG_PM is not set
+CONFIG_PM=y
+# CONFIG_PM_DEBUG is not set
+# CONFIG_SUSPEND is not set
+# CONFIG_APM_EMULATION is not set
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_NET=y
CONFIG_INET_XFRM_MODE_TRANSPORT=y
CONFIG_INET_XFRM_MODE_TUNNEL=y
CONFIG_INET_XFRM_MODE_BEET=y
-# CONFIG_INET_LRO is not set
+CONFIG_INET_LRO=y
CONFIG_INET_DIAG=y
CONFIG_INET_TCP_DIAG=y
# CONFIG_TCP_CONG_ADVANCED is not set
# CONFIG_TIPC is not set
# CONFIG_ATM is not set
# CONFIG_BRIDGE is not set
+CONFIG_NET_DSA=y
+CONFIG_NET_DSA_TAG_DSA=y
+CONFIG_NET_DSA_TAG_EDSA=y
+# CONFIG_NET_DSA_TAG_TRAILER is not set
+CONFIG_NET_DSA_MV88E6XXX=y
+# CONFIG_NET_DSA_MV88E6060 is not set
+CONFIG_NET_DSA_MV88E6XXX_NEED_PPU=y
+CONFIG_NET_DSA_MV88E6131=y
+CONFIG_NET_DSA_MV88E6123_61_65=y
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
# CONFIG_LAPB is not set
# CONFIG_ECONET is not set
# CONFIG_WAN_ROUTER is not set
+# CONFIG_PHONET is not set
# CONFIG_NET_SCHED is not set
+# CONFIG_DCB is not set
#
# Network testing
#
CONFIG_NET_PKTGEN=m
# CONFIG_NET_TCPPROBE is not set
+# CONFIG_NET_DROP_MONITOR is not set
# CONFIG_HAMRADIO is not set
# CONFIG_CAN is not set
# CONFIG_IRDA is not set
# CONFIG_BT is not set
# CONFIG_AF_RXRPC is not set
-
-#
-# Wireless
-#
+CONFIG_WIRELESS=y
# CONFIG_CFG80211 is not set
+# CONFIG_WIRELESS_OLD_REGULATORY is not set
CONFIG_WIRELESS_EXT=y
CONFIG_WIRELESS_EXT_SYSFS=y
+# CONFIG_LIB80211 is not set
# CONFIG_MAC80211 is not set
-# CONFIG_IEEE80211 is not set
+# CONFIG_WIMAX is not set
# CONFIG_RFKILL is not set
# CONFIG_NET_9P is not set
# CONFIG_MTD_DEBUG is not set
# CONFIG_MTD_CONCAT is not set
CONFIG_MTD_PARTITIONS=y
+# CONFIG_MTD_TESTS is not set
# CONFIG_MTD_REDBOOT_PARTS is not set
CONFIG_MTD_CMDLINE_PARTS=y
# CONFIG_MTD_AFS_PARTS is not set
#
# CONFIG_MTD_COMPLEX_MAPPINGS is not set
CONFIG_MTD_PHYSMAP=y
-CONFIG_MTD_PHYSMAP_START=0x0
-CONFIG_MTD_PHYSMAP_LEN=0x0
-CONFIG_MTD_PHYSMAP_BANKWIDTH=0
+# CONFIG_MTD_PHYSMAP_COMPAT is not set
# CONFIG_MTD_ARM_INTEGRATOR is not set
# CONFIG_MTD_IMPA7 is not set
# CONFIG_MTD_INTEL_VR_NOR is not set
CONFIG_MTD_NAND_VERIFY_WRITE=y
# CONFIG_MTD_NAND_ECC_SMC is not set
# CONFIG_MTD_NAND_MUSEUM_IDS is not set
+# CONFIG_MTD_NAND_GPIO is not set
CONFIG_MTD_NAND_IDS=y
# CONFIG_MTD_NAND_DISKONCHIP is not set
# CONFIG_MTD_NAND_CAFE is not set
CONFIG_MTD_NAND_ORION=y
# CONFIG_MTD_ONENAND is not set
+#
+# LPDDR flash memory drivers
+#
+# CONFIG_MTD_LPDDR is not set
+
#
# UBI - Unsorted block images
#
# CONFIG_ATA_OVER_ETH is not set
CONFIG_MISC_DEVICES=y
# CONFIG_PHANTOM is not set
-# CONFIG_EEPROM_93CX6 is not set
# CONFIG_SGI_IOC4 is not set
# CONFIG_TIFM_CORE is not set
+# CONFIG_ICS932S401 is not set
# CONFIG_ENCLOSURE_SERVICES is not set
# CONFIG_HP_ILO is not set
+# CONFIG_ISL29003 is not set
+# CONFIG_C2PORT is not set
+
+#
+# EEPROM support
+#
+# CONFIG_EEPROM_AT24 is not set
+# CONFIG_EEPROM_LEGACY is not set
+# CONFIG_EEPROM_93CX6 is not set
CONFIG_HAVE_IDE=y
# CONFIG_IDE is not set
# CONFIG_MEGARAID_NEWGEN is not set
# CONFIG_MEGARAID_LEGACY is not set
# CONFIG_MEGARAID_SAS is not set
+# CONFIG_SCSI_MPT2SAS is not set
# CONFIG_SCSI_HPTIOP is not set
+# CONFIG_LIBFC is not set
+# CONFIG_LIBFCOE is not set
+# CONFIG_FCOE is not set
# CONFIG_SCSI_DMX3191D is not set
# CONFIG_SCSI_FUTURE_DOMAIN is not set
# CONFIG_SCSI_IPS is not set
# CONFIG_SCSI_DEBUG is not set
# CONFIG_SCSI_SRP is not set
# CONFIG_SCSI_DH is not set
+# CONFIG_SCSI_OSD_INITIATOR is not set
CONFIG_ATA=y
# CONFIG_ATA_NONSTANDARD is not set
CONFIG_SATA_PMP=y
# CONFIG_IEEE1394 is not set
# CONFIG_I2O is not set
CONFIG_NETDEVICES=y
+CONFIG_COMPAT_NET_DEV_OPS=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_ARCNET is not set
-# CONFIG_PHYLIB is not set
+CONFIG_PHYLIB=y
+
+#
+# MII PHY device drivers
+#
+CONFIG_MARVELL_PHY=y
+# CONFIG_DAVICOM_PHY is not set
+# CONFIG_QSEMI_PHY is not set
+# CONFIG_LXT_PHY is not set
+# CONFIG_CICADA_PHY is not set
+# CONFIG_VITESSE_PHY is not set
+# CONFIG_SMSC_PHY is not set
+# CONFIG_BROADCOM_PHY is not set
+# CONFIG_ICPLUS_PHY is not set
+# CONFIG_REALTEK_PHY is not set
+# CONFIG_NATIONAL_PHY is not set
+# CONFIG_STE10XP is not set
+# CONFIG_LSI_ET1011C_PHY is not set
+# CONFIG_FIXED_PHY is not set
+# CONFIG_MDIO_BITBANG is not set
CONFIG_NET_ETHERNET=y
CONFIG_MII=y
# CONFIG_AX88796 is not set
# CONFIG_NET_VENDOR_3COM is not set
# CONFIG_SMC91X is not set
# CONFIG_DM9000 is not set
+# CONFIG_ETHOC is not set
+# CONFIG_SMC911X is not set
+# CONFIG_SMSC911X is not set
+# CONFIG_DNET is not set
# CONFIG_NET_TULIP is not set
# CONFIG_HP100 is not set
# CONFIG_IBM_NEW_EMAC_ZMII is not set
# CONFIG_IBM_NEW_EMAC_RGMII is not set
# CONFIG_IBM_NEW_EMAC_TAH is not set
# CONFIG_IBM_NEW_EMAC_EMAC4 is not set
+# CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set
+# CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set
+# CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set
CONFIG_NET_PCI=y
# CONFIG_PCNET32 is not set
# CONFIG_AMD8111_ETH is not set
# CONFIG_ADAPTEC_STARFIRE is not set
# CONFIG_B44 is not set
# CONFIG_FORCEDETH is not set
-# CONFIG_EEPRO100 is not set
# CONFIG_E100 is not set
# CONFIG_FEALNX is not set
# CONFIG_NATSEMI is not set
# CONFIG_R6040 is not set
# CONFIG_SIS900 is not set
# CONFIG_EPIC100 is not set
+# CONFIG_SMSC9420 is not set
# CONFIG_SUNDANCE is not set
# CONFIG_TLAN is not set
# CONFIG_VIA_RHINE is not set
# CONFIG_SC92031 is not set
+# CONFIG_ATL2 is not set
CONFIG_NETDEV_1000=y
# CONFIG_ACENIC is not set
# CONFIG_DL2K is not set
# CONFIG_E1000E is not set
# CONFIG_IP1000 is not set
# CONFIG_IGB is not set
+# CONFIG_IGBVF is not set
# CONFIG_NS83820 is not set
# CONFIG_HAMACHI is not set
# CONFIG_YELLOWFIN is not set
# CONFIG_QLA3XXX is not set
# CONFIG_ATL1 is not set
# CONFIG_ATL1E is not set
+# CONFIG_ATL1C is not set
+# CONFIG_JME is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_TR is not set
#
# CONFIG_WLAN_PRE80211 is not set
# CONFIG_WLAN_80211 is not set
-# CONFIG_IWLWIFI_LEDS is not set
+
+#
+# Enable WiMAX (Networking options) to see the WiMAX drivers
+#
#
# USB Network Adapters
CONFIG_SERIAL_CORE_CONSOLE=y
# CONFIG_SERIAL_JSM is not set
CONFIG_UNIX98_PTYS=y
+# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set
CONFIG_LEGACY_PTYS=y
CONFIG_LEGACY_PTY_COUNT=16
# CONFIG_IPMI_HANDLER is not set
# CONFIG_HW_RANDOM is not set
-# CONFIG_NVRAM is not set
# CONFIG_R3964 is not set
# CONFIG_APPLICOM is not set
# CONFIG_RAW_DRIVER is not set
# Miscellaneous I2C Chip support
#
# CONFIG_DS1682 is not set
-# CONFIG_EEPROM_AT24 is not set
-# CONFIG_EEPROM_LEGACY is not set
# CONFIG_SENSORS_PCF8574 is not set
# CONFIG_PCF8575 is not set
# CONFIG_SENSORS_PCA9539 is not set
-# CONFIG_SENSORS_PCF8591 is not set
# CONFIG_SENSORS_MAX6875 is not set
# CONFIG_SENSORS_TSL2550 is not set
# CONFIG_I2C_DEBUG_CORE is not set
# CONFIG_SENSORS_ADM1029 is not set
# CONFIG_SENSORS_ADM1031 is not set
# CONFIG_SENSORS_ADM9240 is not set
+# CONFIG_SENSORS_ADT7462 is not set
# CONFIG_SENSORS_ADT7470 is not set
# CONFIG_SENSORS_ADT7473 is not set
+# CONFIG_SENSORS_ADT7475 is not set
# CONFIG_SENSORS_ATXP1 is not set
# CONFIG_SENSORS_DS1621 is not set
# CONFIG_SENSORS_I5K_AMB is not set
# CONFIG_SENSORS_F71805F is not set
# CONFIG_SENSORS_F71882FG is not set
# CONFIG_SENSORS_F75375S is not set
+# CONFIG_SENSORS_G760A is not set
# CONFIG_SENSORS_GL518SM is not set
# CONFIG_SENSORS_GL520SM is not set
# CONFIG_SENSORS_IT87 is not set
# CONFIG_SENSORS_LM90 is not set
# CONFIG_SENSORS_LM92 is not set
# CONFIG_SENSORS_LM93 is not set
+# CONFIG_SENSORS_LTC4215 is not set
+# CONFIG_SENSORS_LTC4245 is not set
+# CONFIG_SENSORS_LM95241 is not set
# CONFIG_SENSORS_MAX1619 is not set
# CONFIG_SENSORS_MAX6650 is not set
# CONFIG_SENSORS_PC87360 is not set
# CONFIG_SENSORS_PC87427 is not set
+# CONFIG_SENSORS_PCF8591 is not set
+# CONFIG_SENSORS_SHT15 is not set
# CONFIG_SENSORS_SIS5595 is not set
# CONFIG_SENSORS_DME1737 is not set
# CONFIG_SENSORS_SMSC47M1 is not set
# CONFIG_SENSORS_W83627HF is not set
# CONFIG_SENSORS_W83627EHF is not set
# CONFIG_HWMON_DEBUG_CHIP is not set
+# CONFIG_THERMAL is not set
+# CONFIG_THERMAL_HWMON is not set
# CONFIG_WATCHDOG is not set
+CONFIG_SSB_POSSIBLE=y
#
# Sonics Silicon Backplane
#
-CONFIG_SSB_POSSIBLE=y
# CONFIG_SSB is not set
#
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
+# CONFIG_TWL4030_CORE is not set
# CONFIG_MFD_TMIO is not set
-# CONFIG_MFD_T7L66XB is not set
-# CONFIG_MFD_TC6387XB is not set
+# CONFIG_PMIC_DA903X is not set
+# CONFIG_MFD_WM8400 is not set
+# CONFIG_MFD_WM8350_I2C is not set
+# CONFIG_MFD_PCF50633 is not set
#
# Multimedia devices
# USB Input Devices
#
CONFIG_USB_HID=y
-# CONFIG_USB_HIDINPUT_POWERBOOK is not set
-# CONFIG_HID_FF is not set
+# CONFIG_HID_PID is not set
# CONFIG_USB_HIDDEV is not set
+
+#
+# Special HID drivers
+#
+# CONFIG_HID_A4TECH is not set
+# CONFIG_HID_APPLE is not set
+# CONFIG_HID_BELKIN is not set
+# CONFIG_HID_CHERRY is not set
+# CONFIG_HID_CHICONY is not set
+# CONFIG_HID_CYPRESS is not set
+# CONFIG_DRAGONRISE_FF is not set
+# CONFIG_HID_EZKEY is not set
+# CONFIG_HID_KYE is not set
+# CONFIG_HID_GYRATION is not set
+# CONFIG_HID_KENSINGTON is not set
+# CONFIG_HID_LOGITECH is not set
+# CONFIG_HID_MICROSOFT is not set
+# CONFIG_HID_MONTEREY is not set
+# CONFIG_HID_NTRIG is not set
+# CONFIG_HID_PANTHERLORD is not set
+# CONFIG_HID_PETALYNX is not set
+# CONFIG_HID_SAMSUNG is not set
+# CONFIG_HID_SONY is not set
+# CONFIG_HID_SUNPLUS is not set
+# CONFIG_GREENASIA_FF is not set
+# CONFIG_HID_TOPSEED is not set
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
CONFIG_USB_SUPPORT=y
CONFIG_USB_ARCH_HAS_HCD=y
CONFIG_USB_ARCH_HAS_OHCI=y
CONFIG_USB_DEVICEFS=y
CONFIG_USB_DEVICE_CLASS=y
# CONFIG_USB_DYNAMIC_MINORS is not set
+# CONFIG_USB_SUSPEND is not set
# CONFIG_USB_OTG is not set
# CONFIG_USB_OTG_WHITELIST is not set
# CONFIG_USB_OTG_BLACKLIST_HUB is not set
# CONFIG_USB_MON is not set
+# CONFIG_USB_WUSB is not set
+# CONFIG_USB_WUSB_CBAF is not set
#
# USB Host Controller Drivers
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_EHCI_ROOT_HUB_TT=y
CONFIG_USB_EHCI_TT_NEWSCHED=y
+# CONFIG_USB_OXU210HP_HCD is not set
# CONFIG_USB_ISP116X_HCD is not set
# CONFIG_USB_ISP1760_HCD is not set
# CONFIG_USB_OHCI_HCD is not set
# CONFIG_USB_UHCI_HCD is not set
# CONFIG_USB_SL811_HCD is not set
# CONFIG_USB_R8A66597_HCD is not set
+# CONFIG_USB_WHCI_HCD is not set
+# CONFIG_USB_HWA_HCD is not set
#
# USB Device Class drivers
# CONFIG_USB_ACM is not set
CONFIG_USB_PRINTER=y
# CONFIG_USB_WDM is not set
+# CONFIG_USB_TMC is not set
#
-# NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support'
+# NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may
#
#
-# may also be needed; see USB_STORAGE Help for more information
+# also be needed; see USB_STORAGE Help for more info
#
CONFIG_USB_STORAGE=y
# CONFIG_USB_STORAGE_DEBUG is not set
CONFIG_USB_STORAGE_DATAFAB=y
CONFIG_USB_STORAGE_FREECOM=y
# CONFIG_USB_STORAGE_ISD200 is not set
-CONFIG_USB_STORAGE_DPCM=y
# CONFIG_USB_STORAGE_USBAT is not set
CONFIG_USB_STORAGE_SDDR09=y
CONFIG_USB_STORAGE_SDDR55=y
# CONFIG_USB_STORAGE_ALAUDA is not set
# CONFIG_USB_STORAGE_ONETOUCH is not set
# CONFIG_USB_STORAGE_KARMA is not set
-# CONFIG_USB_STORAGE_SIERRA is not set
# CONFIG_USB_STORAGE_CYPRESS_ATACB is not set
# CONFIG_USB_LIBUSUAL is not set
# CONFIG_USB_EMI62 is not set
# CONFIG_USB_EMI26 is not set
# CONFIG_USB_ADUTUX is not set
+# CONFIG_USB_SEVSEG is not set
# CONFIG_USB_RIO500 is not set
# CONFIG_USB_LEGOTOWER is not set
# CONFIG_USB_LCD is not set
# CONFIG_USB_LED is not set
# CONFIG_USB_CYPRESS_CY7C63 is not set
# CONFIG_USB_CYTHERM is not set
-# CONFIG_USB_PHIDGET is not set
# CONFIG_USB_IDMOUSE is not set
# CONFIG_USB_FTDI_ELAN is not set
# CONFIG_USB_APPLEDISPLAY is not set
# CONFIG_USB_IOWARRIOR is not set
# CONFIG_USB_TEST is not set
# CONFIG_USB_ISIGHTFW is not set
+# CONFIG_USB_VST is not set
# CONFIG_USB_GADGET is not set
+
+#
+# OTG and related infrastructure
+#
+# CONFIG_USB_GPIO_VBUS is not set
+# CONFIG_NOP_USB_XCEIV is not set
+# CONFIG_UWB is not set
# CONFIG_MMC is not set
+# CONFIG_MEMSTICK is not set
+# CONFIG_ACCESSIBILITY is not set
CONFIG_NEW_LEDS=y
CONFIG_LEDS_CLASS=y
#
# CONFIG_LEDS_PCA9532 is not set
CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_GPIO_PLATFORM=y
+# CONFIG_LEDS_LP5521 is not set
# CONFIG_LEDS_PCA955X is not set
+# CONFIG_LEDS_BD2802 is not set
#
# LED Triggers
CONFIG_LEDS_TRIGGERS=y
CONFIG_LEDS_TRIGGER_TIMER=y
CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set
CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+
+#
+# iptables trigger is under Netfilter config (LED target)
+#
CONFIG_RTC_LIB=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_HCTOSYS=y
# CONFIG_RTC_DRV_M41T80_WDT is not set
CONFIG_RTC_DRV_S35390A=y
# CONFIG_RTC_DRV_FM3130 is not set
+# CONFIG_RTC_DRV_RX8581 is not set
#
# SPI RTC drivers
# Platform RTC drivers
#
# CONFIG_RTC_DRV_CMOS is not set
+# CONFIG_RTC_DRV_DS1286 is not set
# CONFIG_RTC_DRV_DS1511 is not set
# CONFIG_RTC_DRV_DS1553 is not set
# CONFIG_RTC_DRV_DS1742 is not set
# CONFIG_RTC_DRV_STK17TA8 is not set
CONFIG_RTC_DRV_M48T86=y
+# CONFIG_RTC_DRV_M48T35 is not set
# CONFIG_RTC_DRV_M48T59 is not set
+# CONFIG_RTC_DRV_BQ4802 is not set
# CONFIG_RTC_DRV_V3020 is not set
#
# DMA Clients
#
# CONFIG_NET_DMA is not set
+# CONFIG_ASYNC_TX_DMA is not set
# CONFIG_DMATEST is not set
-
-#
-# Voltage and Current regulators
-#
+# CONFIG_AUXDISPLAY is not set
# CONFIG_REGULATOR is not set
-# CONFIG_REGULATOR_FIXED_VOLTAGE is not set
-# CONFIG_REGULATOR_VIRTUAL_CONSUMER is not set
-# CONFIG_REGULATOR_BQ24022 is not set
# CONFIG_UIO is not set
+# CONFIG_STAGING is not set
#
# File systems
# CONFIG_EXT2_FS_XATTR is not set
# CONFIG_EXT2_FS_XIP is not set
CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
# CONFIG_EXT3_FS_XATTR is not set
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+# CONFIG_EXT4DEV_COMPAT is not set
+CONFIG_EXT4_FS_XATTR=y
+# CONFIG_EXT4_FS_POSIX_ACL is not set
+# CONFIG_EXT4_FS_SECURITY is not set
CONFIG_JBD=y
+# CONFIG_JBD_DEBUG is not set
+CONFIG_JBD2=m
+# CONFIG_JBD2_DEBUG is not set
+CONFIG_FS_MBCACHE=m
# CONFIG_REISERFS_FS is not set
# CONFIG_JFS_FS is not set
# CONFIG_FS_POSIX_ACL is not set
+CONFIG_FILE_LOCKING=y
# CONFIG_XFS_FS is not set
# CONFIG_OCFS2_FS is not set
+# CONFIG_BTRFS_FS is not set
CONFIG_DNOTIFY=y
CONFIG_INOTIFY=y
CONFIG_INOTIFY_USER=y
# CONFIG_AUTOFS4_FS is not set
# CONFIG_FUSE_FS is not set
+#
+# Caches
+#
+# CONFIG_FSCACHE is not set
+
#
# CD-ROM/DVD Filesystems
#
#
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
+CONFIG_PROC_PAGE_MONITOR=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
# CONFIG_TMPFS_POSIX_ACL is not set
# CONFIG_HUGETLB_PAGE is not set
# CONFIG_CONFIGFS_FS is not set
-
-#
-# Miscellaneous filesystems
-#
+CONFIG_MISC_FILESYSTEMS=y
# CONFIG_ADFS_FS is not set
# CONFIG_AFFS_FS is not set
# CONFIG_HFS_FS is not set
CONFIG_JFFS2_RTIME=y
# CONFIG_JFFS2_RUBIN is not set
CONFIG_CRAMFS=y
+# CONFIG_SQUASHFS is not set
# CONFIG_VXFS_FS is not set
# CONFIG_MINIX_FS is not set
# CONFIG_OMFS_FS is not set
# CONFIG_ROMFS_FS is not set
# CONFIG_SYSV_FS is not set
# CONFIG_UFS_FS is not set
+# CONFIG_NILFS2_FS is not set
CONFIG_NETWORK_FILESYSTEMS=y
CONFIG_NFS_FS=y
CONFIG_NFS_V3=y
CONFIG_FRAME_WARN=1024
CONFIG_MAGIC_SYSRQ=y
# CONFIG_UNUSED_SYMBOLS is not set
-# CONFIG_DEBUG_FS is not set
+CONFIG_DEBUG_FS=y
# CONFIG_HEADERS_CHECK is not set
CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_SHIRQ is not set
CONFIG_DETECT_SOFTLOCKUP=y
# CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set
CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set
+CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0
CONFIG_SCHED_DEBUG=y
CONFIG_SCHEDSTATS=y
# CONFIG_TIMER_STATS is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DEBUG_LIST is not set
# CONFIG_DEBUG_SG is not set
+# CONFIG_DEBUG_NOTIFIERS is not set
CONFIG_FRAME_POINTER=y
# CONFIG_BOOT_PRINTK_DELAY is not set
# CONFIG_RCU_TORTURE_TEST is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
# CONFIG_KPROBES_SANITY_TEST is not set
# CONFIG_BACKTRACE_SELF_TEST is not set
+# CONFIG_DEBUG_BLOCK_EXT_DEVT is not set
# CONFIG_LKDTM is not set
# CONFIG_FAULT_INJECTION is not set
CONFIG_LATENCYTOP=y
CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_HAVE_FTRACE=y
-CONFIG_HAVE_DYNAMIC_FTRACE=y
-# CONFIG_FTRACE is not set
+# CONFIG_PAGE_POISONING is not set
+CONFIG_NOP_TRACER=y
+CONFIG_HAVE_FUNCTION_TRACER=y
+CONFIG_RING_BUFFER=y
+CONFIG_TRACING=y
+CONFIG_TRACING_SUPPORT=y
+
+#
+# Tracers
+#
+# CONFIG_FUNCTION_TRACER is not set
# CONFIG_IRQSOFF_TRACER is not set
# CONFIG_PREEMPT_TRACER is not set
# CONFIG_SCHED_TRACER is not set
# CONFIG_CONTEXT_SWITCH_TRACER is not set
+# CONFIG_EVENT_TRACER is not set
+# CONFIG_BOOT_TRACER is not set
+# CONFIG_TRACE_BRANCH_PROFILING is not set
+# CONFIG_STACK_TRACER is not set
+# CONFIG_KMEMTRACE is not set
+# CONFIG_WORKQUEUE_TRACER is not set
+# CONFIG_BLK_DEV_IO_TRACE is not set
+# CONFIG_FTRACE_STARTUP_TEST is not set
+# CONFIG_DYNAMIC_DEBUG is not set
# CONFIG_SAMPLES is not set
CONFIG_HAVE_ARCH_KGDB=y
# CONFIG_KGDB is not set
+CONFIG_ARM_UNWIND=y
CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y
# CONFIG_DEBUG_STACK_USAGE is not set
#
# CONFIG_KEYS is not set
# CONFIG_SECURITY is not set
+# CONFIG_SECURITYFS is not set
# CONFIG_SECURITY_FILE_CAPABILITIES is not set
-CONFIG_ASYNC_CORE=y
CONFIG_CRYPTO=y
#
# Crypto core or helper
#
+# CONFIG_CRYPTO_FIPS is not set
CONFIG_CRYPTO_ALGAPI=m
+CONFIG_CRYPTO_ALGAPI2=m
+CONFIG_CRYPTO_AEAD2=m
CONFIG_CRYPTO_BLKCIPHER=m
+CONFIG_CRYPTO_BLKCIPHER2=m
+CONFIG_CRYPTO_HASH2=m
+CONFIG_CRYPTO_RNG2=m
+CONFIG_CRYPTO_PCOMP=m
CONFIG_CRYPTO_MANAGER=m
+CONFIG_CRYPTO_MANAGER2=m
# CONFIG_CRYPTO_GF128MUL is not set
# CONFIG_CRYPTO_NULL is not set
+CONFIG_CRYPTO_WORKQUEUE=m
# CONFIG_CRYPTO_CRYPTD is not set
# CONFIG_CRYPTO_AUTHENC is not set
# CONFIG_CRYPTO_TEST is not set
# Compression
#
# CONFIG_CRYPTO_DEFLATE is not set
+# CONFIG_CRYPTO_ZLIB is not set
# CONFIG_CRYPTO_LZO is not set
+
+#
+# Random Number Generation
+#
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
CONFIG_CRYPTO_HW=y
# CONFIG_CRYPTO_DEV_HIFN_795X is not set
+CONFIG_BINARY_PRINTF=y
#
# Library routines
#
CONFIG_BITREVERSE=y
-# CONFIG_GENERIC_FIND_FIRST_BIT is not set
-# CONFIG_GENERIC_FIND_NEXT_BIT is not set
+CONFIG_GENERIC_FIND_LAST_BIT=y
# CONFIG_CRC_CCITT is not set
-# CONFIG_CRC16 is not set
+CONFIG_CRC16=m
CONFIG_CRC_T10DIF=y
CONFIG_CRC_ITU_T=m
CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
-CONFIG_PLIST=y
CONFIG_HAS_IOMEM=y
CONFIG_HAS_IOPORT=y
CONFIG_HAS_DMA=y
+CONFIG_NLATTR=y
CONFIG_CPU_FREQ_GOV_USERSPACE=m
CONFIG_CPU_FREQ_GOV_ONDEMAND=m
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m
-CONFIG_CPU_FREQ_PXA=y
#
# Floating point emulation
#define EF_ARM_HASENTRY 0x00000002 /* All */
#define EF_ARM_RELEXEC 0x00000001 /* All */
-#define R_ARM_NONE 0
-#define R_ARM_PC24 1
-#define R_ARM_ABS32 2
-#define R_ARM_CALL 28
-#define R_ARM_JUMP24 29
-#define R_ARM_V4BX 40
-#define R_ARM_PREL31 42
+#define R_ARM_NONE 0
+#define R_ARM_PC24 1
+#define R_ARM_ABS32 2
+#define R_ARM_CALL 28
+#define R_ARM_JUMP24 29
+#define R_ARM_V4BX 40
+#define R_ARM_PREL31 42
+#define R_ARM_MOVW_ABS_NC 43
+#define R_ARM_MOVT_ABS 44
/*
* These are used to set parameters in the core dumps.
*(u32 *)loc = offset & 0x7fffffff;
break;
+ case R_ARM_MOVW_ABS_NC:
+ case R_ARM_MOVT_ABS:
+ offset = *(u32 *)loc;
+ offset = ((offset & 0xf0000) >> 4) | (offset & 0xfff);
+ offset = (offset ^ 0x8000) - 0x8000;
+
+ offset += sym->st_value;
+ if (ELF32_R_TYPE(rel->r_info) == R_ARM_MOVT_ABS)
+ offset >>= 16;
+
+ *(u32 *)loc &= 0xfff0f000;
+ *(u32 *)loc |= ((offset & 0xf000) << 4) |
+ (offset & 0x0fff);
+ break;
+
default:
printk(KERN_ERR "%s: unknown relocation: %u\n",
module->name, ELF32_R_TYPE(rel->r_info));
comment "DaVinci Core Type"
-config ARCH_DAVINCI644x
- default y
+config ARCH_DAVINCI_DM644x
bool "DaVinci 644x based system"
comment "DaVinci Board Type"
config MACH_DAVINCI_EVM
- bool "TI DaVinci EVM"
+ bool "TI DM644x EVM"
default y
- depends on ARCH_DAVINCI644x
+ depends on ARCH_DAVINCI_DM644x
help
Configure this option to specify the whether the board used
- for development is a DaVinci EVM
+ for development is a DM644x EVM
+
+
+config DAVINCI_MUX
+ bool "DAVINCI multiplexing support"
+ depends on ARCH_DAVINCI
+ default y
+ help
+ Pin multiplexing support for DAVINCI boards. If your bootloader
+ sets the multiplexing correctly, say N. Otherwise, or if unsure,
+ say Y.
+
+config DAVINCI_MUX_DEBUG
+ bool "Multiplexing debug output"
+ depends on DAVINCI_MUX
+ help
+ Makes the multiplexing functions print out a lot of debug info.
+ This is useful if you want to find out the correct values of the
+ multiplexing registers.
+
+config DAVINCI_MUX_WARNINGS
+ bool "Warn about pins the bootloader didn't set up"
+ depends on DAVINCI_MUX
+ help
+ Choose Y here to warn whenever driver initialization logic needs
+ to change the pin multiplexing setup. When there are no warnings
+ printed, it's safe to deselect DAVINCI_MUX for your product.
+
+config DAVINCI_RESET_CLOCKS
+ bool "Reset unused clocks during boot"
+ depends on ARCH_DAVINCI
+ help
+ Say Y if you want to reset unused clocks during boot.
+ This option saves power, but assumes all drivers are
+ using the clock framework. Broken drivers that do not
+ yet use clock framework may not work with this option.
+ If you are booting from another operating system, you
+ probably do not want this option enabled until your
+ device drivers work properly.
endmenu
# Common objects
obj-y := time.o irq.o clock.o serial.o io.o id.o psc.o \
- gpio.o mux.o devices.o usb.o
+ gpio.o devices.o dma.o usb.o
+
+obj-$(CONFIG_DAVINCI_MUX) += mux.o
+
+# Chip specific
+obj-$(CONFIG_ARCH_DAVINCI_DM644x) += dm644x.o
# Board specific
-obj-$(CONFIG_MACH_DAVINCI_EVM) += board-evm.o
+obj-$(CONFIG_MACH_DAVINCI_EVM) += board-dm644x-evm.o
--- /dev/null
+/*
+ * TI DaVinci EVM board support
+ *
+ * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (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.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/memory.h>
+#include <linux/etherdevice.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c/pcf857x.h>
+#include <linux/i2c/at24.h>
+
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+#include <linux/phy.h>
+#include <linux/clk.h>
+
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <mach/dm644x.h>
+#include <mach/common.h>
+#include <mach/i2c.h>
+#include <mach/serial.h>
+#include <mach/mux.h>
+#include <mach/psc.h>
+#include <mach/nand.h>
+
+#define DM644X_EVM_PHY_MASK (0x2)
+#define DM644X_EVM_MDIO_FREQUENCY (2200000) /* PHY bus frequency */
+
+#define DAVINCI_CFC_ATA_BASE 0x01C66000
+
+#define DAVINCI_ASYNC_EMIF_CONTROL_BASE 0x01e00000
+#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE 0x02000000
+#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE 0x04000000
+#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE 0x06000000
+#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE 0x08000000
+
+#define LXT971_PHY_ID (0x001378e2)
+#define LXT971_PHY_MASK (0xfffffff0)
+
+static struct mtd_partition davinci_evm_norflash_partitions[] = {
+ /* bootloader (UBL, U-Boot, etc) in first 5 sectors */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = 5 * SZ_64K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* bootloader params in the next 1 sectors */
+ {
+ .name = "params",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_64K,
+ .mask_flags = 0,
+ },
+ /* kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_2M,
+ .mask_flags = 0
+ },
+ /* file system */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0
+ }
+};
+
+static struct physmap_flash_data davinci_evm_norflash_data = {
+ .width = 2,
+ .parts = davinci_evm_norflash_partitions,
+ .nr_parts = ARRAY_SIZE(davinci_evm_norflash_partitions),
+};
+
+/* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF
+ * limits addresses to 16M, so using addresses past 16M will wrap */
+static struct resource davinci_evm_norflash_resource = {
+ .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
+ .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device davinci_evm_norflash_device = {
+ .name = "physmap-flash",
+ .id = 0,
+ .dev = {
+ .platform_data = &davinci_evm_norflash_data,
+ },
+ .num_resources = 1,
+ .resource = &davinci_evm_norflash_resource,
+};
+
+/* DM644x EVM includes a 64 MByte small-page NAND flash (16K blocks).
+ * It may used instead of the (default) NOR chip to boot, using TI's
+ * tools to install the secondary boot loader (UBL) and U-Boot.
+ */
+struct mtd_partition davinci_evm_nandflash_partition[] = {
+ /* Bootloader layout depends on whose u-boot is installed, but we
+ * can hide all the details.
+ * - block 0 for u-boot environment ... in mainline u-boot
+ * - block 1 for UBL (plus up to four backup copies in blocks 2..5)
+ * - blocks 6...? for u-boot
+ * - blocks 16..23 for u-boot environment ... in TI's u-boot
+ */
+ {
+ .name = "bootloader",
+ .offset = 0,
+ .size = SZ_256K + SZ_128K,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ /* Kernel */
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND,
+ .size = SZ_4M,
+ .mask_flags = 0,
+ },
+ /* File system (older GIT kernels started this on the 5MB mark) */
+ {
+ .name = "filesystem",
+ .offset = MTDPART_OFS_APPEND,
+ .size = MTDPART_SIZ_FULL,
+ .mask_flags = 0,
+ }
+ /* A few blocks at end hold a flash BBT ... created by TI's CCS
+ * using flashwriter_nand.out, but ignored by TI's versions of
+ * Linux and u-boot. We boot faster by using them.
+ */
+};
+
+static struct davinci_nand_pdata davinci_evm_nandflash_data = {
+ .parts = davinci_evm_nandflash_partition,
+ .nr_parts = ARRAY_SIZE(davinci_evm_nandflash_partition),
+ .ecc_mode = NAND_ECC_HW,
+ .options = NAND_USE_FLASH_BBT,
+};
+
+static struct resource davinci_evm_nandflash_resource[] = {
+ {
+ .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
+ .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .start = DAVINCI_ASYNC_EMIF_CONTROL_BASE,
+ .end = DAVINCI_ASYNC_EMIF_CONTROL_BASE + SZ_4K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+};
+
+static struct platform_device davinci_evm_nandflash_device = {
+ .name = "davinci_nand",
+ .id = 0,
+ .dev = {
+ .platform_data = &davinci_evm_nandflash_data,
+ },
+ .num_resources = ARRAY_SIZE(davinci_evm_nandflash_resource),
+ .resource = davinci_evm_nandflash_resource,
+};
+
+static u64 davinci_fb_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device davinci_fb_device = {
+ .name = "davincifb",
+ .id = -1,
+ .dev = {
+ .dma_mask = &davinci_fb_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+ .num_resources = 0,
+};
+
+static struct platform_device rtc_dev = {
+ .name = "rtc_davinci_evm",
+ .id = -1,
+};
+
+static struct resource ide_resources[] = {
+ {
+ .start = DAVINCI_CFC_ATA_BASE,
+ .end = DAVINCI_CFC_ATA_BASE + 0x7ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_IDE,
+ .end = IRQ_IDE,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static u64 ide_dma_mask = DMA_BIT_MASK(32);
+
+static struct platform_device ide_dev = {
+ .name = "palm_bk3710",
+ .id = -1,
+ .resource = ide_resources,
+ .num_resources = ARRAY_SIZE(ide_resources),
+ .dev = {
+ .dma_mask = &ide_dma_mask,
+ .coherent_dma_mask = DMA_BIT_MASK(32),
+ },
+};
+
+/*----------------------------------------------------------------------*/
+
+/*
+ * I2C GPIO expanders
+ */
+
+#define PCF_Uxx_BASE(x) (DAVINCI_N_GPIO + ((x) * 8))
+
+
+/* U2 -- LEDs */
+
+static struct gpio_led evm_leds[] = {
+ { .name = "DS8", .active_low = 1,
+ .default_trigger = "heartbeat", },
+ { .name = "DS7", .active_low = 1, },
+ { .name = "DS6", .active_low = 1, },
+ { .name = "DS5", .active_low = 1, },
+ { .name = "DS4", .active_low = 1, },
+ { .name = "DS3", .active_low = 1, },
+ { .name = "DS2", .active_low = 1,
+ .default_trigger = "mmc0", },
+ { .name = "DS1", .active_low = 1,
+ .default_trigger = "ide-disk", },
+};
+
+static const struct gpio_led_platform_data evm_led_data = {
+ .num_leds = ARRAY_SIZE(evm_leds),
+ .leds = evm_leds,
+};
+
+static struct platform_device *evm_led_dev;
+
+static int
+evm_led_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
+{
+ struct gpio_led *leds = evm_leds;
+ int status;
+
+ while (ngpio--) {
+ leds->gpio = gpio++;
+ leds++;
+ }
+
+ /* what an extremely annoying way to be forced to handle
+ * device unregistration ...
+ */
+ evm_led_dev = platform_device_alloc("leds-gpio", 0);
+ platform_device_add_data(evm_led_dev,
+ &evm_led_data, sizeof evm_led_data);
+
+ evm_led_dev->dev.parent = &client->dev;
+ status = platform_device_add(evm_led_dev);
+ if (status < 0) {
+ platform_device_put(evm_led_dev);
+ evm_led_dev = NULL;
+ }
+ return status;
+}
+
+static int
+evm_led_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
+{
+ if (evm_led_dev) {
+ platform_device_unregister(evm_led_dev);
+ evm_led_dev = NULL;
+ }
+ return 0;
+}
+
+static struct pcf857x_platform_data pcf_data_u2 = {
+ .gpio_base = PCF_Uxx_BASE(0),
+ .setup = evm_led_setup,
+ .teardown = evm_led_teardown,
+};
+
+
+/* U18 - A/V clock generator and user switch */
+
+static int sw_gpio;
+
+static ssize_t
+sw_show(struct device *d, struct device_attribute *a, char *buf)
+{
+ char *s = gpio_get_value_cansleep(sw_gpio) ? "on\n" : "off\n";
+
+ strcpy(buf, s);
+ return strlen(s);
+}
+
+static DEVICE_ATTR(user_sw, S_IRUGO, sw_show, NULL);
+
+static int
+evm_u18_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
+{
+ int status;
+
+ /* export dip switch option */
+ sw_gpio = gpio + 7;
+ status = gpio_request(sw_gpio, "user_sw");
+ if (status == 0)
+ status = gpio_direction_input(sw_gpio);
+ if (status == 0)
+ status = device_create_file(&client->dev, &dev_attr_user_sw);
+ else
+ gpio_free(sw_gpio);
+ if (status != 0)
+ sw_gpio = -EINVAL;
+
+ /* audio PLL: 48 kHz (vs 44.1 or 32), single rate (vs double) */
+ gpio_request(gpio + 3, "pll_fs2");
+ gpio_direction_output(gpio + 3, 0);
+
+ gpio_request(gpio + 2, "pll_fs1");
+ gpio_direction_output(gpio + 2, 0);
+
+ gpio_request(gpio + 1, "pll_sr");
+ gpio_direction_output(gpio + 1, 0);
+
+ return 0;
+}
+
+static int
+evm_u18_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
+{
+ gpio_free(gpio + 1);
+ gpio_free(gpio + 2);
+ gpio_free(gpio + 3);
+
+ if (sw_gpio > 0) {
+ device_remove_file(&client->dev, &dev_attr_user_sw);
+ gpio_free(sw_gpio);
+ }
+ return 0;
+}
+
+static struct pcf857x_platform_data pcf_data_u18 = {
+ .gpio_base = PCF_Uxx_BASE(1),
+ .n_latch = (1 << 3) | (1 << 2) | (1 << 1),
+ .setup = evm_u18_setup,
+ .teardown = evm_u18_teardown,
+};
+
+
+/* U35 - various I/O signals used to manage USB, CF, ATA, etc */
+
+static int
+evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
+{
+ /* p0 = nDRV_VBUS (initial: don't supply it) */
+ gpio_request(gpio + 0, "nDRV_VBUS");
+ gpio_direction_output(gpio + 0, 1);
+
+ /* p1 = VDDIMX_EN */
+ gpio_request(gpio + 1, "VDDIMX_EN");
+ gpio_direction_output(gpio + 1, 1);
+
+ /* p2 = VLYNQ_EN */
+ gpio_request(gpio + 2, "VLYNQ_EN");
+ gpio_direction_output(gpio + 2, 1);
+
+ /* p3 = n3V3_CF_RESET (initial: stay in reset) */
+ gpio_request(gpio + 3, "nCF_RESET");
+ gpio_direction_output(gpio + 3, 0);
+
+ /* (p4 unused) */
+
+ /* p5 = 1V8_WLAN_RESET (initial: stay in reset) */
+ gpio_request(gpio + 5, "WLAN_RESET");
+ gpio_direction_output(gpio + 5, 1);
+
+ /* p6 = nATA_SEL (initial: select) */
+ gpio_request(gpio + 6, "nATA_SEL");
+ gpio_direction_output(gpio + 6, 0);
+
+ /* p7 = nCF_SEL (initial: deselect) */
+ gpio_request(gpio + 7, "nCF_SEL");
+ gpio_direction_output(gpio + 7, 1);
+
+ /* irlml6401 switches over 1A, in under 8 msec;
+ * now it can be managed by nDRV_VBUS ...
+ */
+ setup_usb(500, 8);
+
+ return 0;
+}
+
+static int
+evm_u35_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
+{
+ gpio_free(gpio + 7);
+ gpio_free(gpio + 6);
+ gpio_free(gpio + 5);
+ gpio_free(gpio + 3);
+ gpio_free(gpio + 2);
+ gpio_free(gpio + 1);
+ gpio_free(gpio + 0);
+ return 0;
+}
+
+static struct pcf857x_platform_data pcf_data_u35 = {
+ .gpio_base = PCF_Uxx_BASE(2),
+ .setup = evm_u35_setup,
+ .teardown = evm_u35_teardown,
+};
+
+/*----------------------------------------------------------------------*/
+
+/* Most of this EEPROM is unused, but U-Boot uses some data:
+ * - 0x7f00, 6 bytes Ethernet Address
+ * - 0x0039, 1 byte NTSC vs PAL (bit 0x80 == PAL)
+ * - ... newer boards may have more
+ */
+static struct memory_accessor *at24_mem_acc;
+
+static void at24_setup(struct memory_accessor *mem_acc, void *context)
+{
+ DECLARE_MAC_BUF(mac_str);
+ char mac_addr[6];
+
+ at24_mem_acc = mem_acc;
+
+ /* Read MAC addr from EEPROM */
+ if (at24_mem_acc->read(at24_mem_acc, mac_addr, 0x7f00, 6) == 6) {
+ printk(KERN_INFO "Read MAC addr from EEPROM: %s\n",
+ print_mac(mac_str, mac_addr));
+ }
+}
+
+static struct at24_platform_data eeprom_info = {
+ .byte_len = (256*1024) / 8,
+ .page_size = 64,
+ .flags = AT24_FLAG_ADDR16,
+ .setup = at24_setup,
+};
+
+int dm6446evm_eeprom_read(void *buf, off_t off, size_t count)
+{
+ if (at24_mem_acc)
+ return at24_mem_acc->read(at24_mem_acc, buf, off, count);
+ return -ENODEV;
+}
+EXPORT_SYMBOL(dm6446evm_eeprom_read);
+
+int dm6446evm_eeprom_write(void *buf, off_t off, size_t count)
+{
+ if (at24_mem_acc)
+ return at24_mem_acc->write(at24_mem_acc, buf, off, count);
+ return -ENODEV;
+}
+EXPORT_SYMBOL(dm6446evm_eeprom_write);
+
+/*
+ * MSP430 supports RTC, card detection, input from IR remote, and
+ * a bit more. It triggers interrupts on GPIO(7) from pressing
+ * buttons on the IR remote, and for card detect switches.
+ */
+static struct i2c_client *dm6446evm_msp;
+
+static int dm6446evm_msp_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ dm6446evm_msp = client;
+ return 0;
+}
+
+static int dm6446evm_msp_remove(struct i2c_client *client)
+{
+ dm6446evm_msp = NULL;
+ return 0;
+}
+
+static const struct i2c_device_id dm6446evm_msp_ids[] = {
+ { "dm6446evm_msp", 0, },
+ { /* end of list */ },
+};
+
+static struct i2c_driver dm6446evm_msp_driver = {
+ .driver.name = "dm6446evm_msp",
+ .id_table = dm6446evm_msp_ids,
+ .probe = dm6446evm_msp_probe,
+ .remove = dm6446evm_msp_remove,
+};
+
+static int dm6444evm_msp430_get_pins(void)
+{
+ static const char txbuf[2] = { 2, 4, };
+ char buf[4];
+ struct i2c_msg msg[2] = {
+ {
+ .addr = dm6446evm_msp->addr,
+ .flags = 0,
+ .len = 2,
+ .buf = (void __force *)txbuf,
+ },
+ {
+ .addr = dm6446evm_msp->addr,
+ .flags = I2C_M_RD,
+ .len = 4,
+ .buf = buf,
+ },
+ };
+ int status;
+
+ if (!dm6446evm_msp)
+ return -ENXIO;
+
+ /* Command 4 == get input state, returns port 2 and port3 data
+ * S Addr W [A] len=2 [A] cmd=4 [A]
+ * RS Addr R [A] [len=4] A [cmd=4] A [port2] A [port3] N P
+ */
+ status = i2c_transfer(dm6446evm_msp->adapter, msg, 2);
+ if (status < 0)
+ return status;
+
+ dev_dbg(&dm6446evm_msp->dev,
+ "PINS: %02x %02x %02x %02x\n",
+ buf[0], buf[1], buf[2], buf[3]);
+
+ return (buf[3] << 8) | buf[2];
+}
+
+static struct i2c_board_info __initdata i2c_info[] = {
+ {
+ I2C_BOARD_INFO("dm6446evm_msp", 0x23),
+ },
+ {
+ I2C_BOARD_INFO("pcf8574", 0x38),
+ .platform_data = &pcf_data_u2,
+ },
+ {
+ I2C_BOARD_INFO("pcf8574", 0x39),
+ .platform_data = &pcf_data_u18,
+ },
+ {
+ I2C_BOARD_INFO("pcf8574", 0x3a),
+ .platform_data = &pcf_data_u35,
+ },
+ {
+ I2C_BOARD_INFO("24c256", 0x50),
+ .platform_data = &eeprom_info,
+ },
+ /* ALSO:
+ * - tvl320aic33 audio codec (0x1b)
+ * - tvp5146 video decoder (0x5d)
+ */
+};
+
+/* The msp430 uses a slow bitbanged I2C implementation (ergo 20 KHz),
+ * which requires 100 usec of idle bus after i2c writes sent to it.
+ */
+static struct davinci_i2c_platform_data i2c_pdata = {
+ .bus_freq = 20 /* kHz */,
+ .bus_delay = 100 /* usec */,
+};
+
+static void __init evm_init_i2c(void)
+{
+ davinci_init_i2c(&i2c_pdata);
+ i2c_add_driver(&dm6446evm_msp_driver);
+ i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
+}
+
+static struct platform_device *davinci_evm_devices[] __initdata = {
+ &davinci_fb_device,
+ &rtc_dev,
+};
+
+static struct davinci_uart_config uart_config __initdata = {
+ .enabled_uarts = (1 << 0),
+};
+
+static void __init
+davinci_evm_map_io(void)
+{
+ davinci_map_common_io();
+ dm644x_init();
+}
+
+static int davinci_phy_fixup(struct phy_device *phydev)
+{
+ unsigned int control;
+ /* CRITICAL: Fix for increasing PHY signal drive strength for
+ * TX lockup issue. On DaVinci EVM, the Intel LXT971 PHY
+ * signal strength was low causing TX to fail randomly. The
+ * fix is to Set bit 11 (Increased MII drive strength) of PHY
+ * register 26 (Digital Config register) on this phy. */
+ control = phy_read(phydev, 26);
+ phy_write(phydev, 26, (control | 0x800));
+ return 0;
+}
+
+#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
+ defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
+#define HAS_ATA 1
+#else
+#define HAS_ATA 0
+#endif
+
+#if defined(CONFIG_MTD_PHYSMAP) || \
+ defined(CONFIG_MTD_PHYSMAP_MODULE)
+#define HAS_NOR 1
+#else
+#define HAS_NOR 0
+#endif
+
+#if defined(CONFIG_MTD_NAND_DAVINCI) || \
+ defined(CONFIG_MTD_NAND_DAVINCI_MODULE)
+#define HAS_NAND 1
+#else
+#define HAS_NAND 0
+#endif
+
+static __init void davinci_evm_init(void)
+{
+ struct clk *aemif_clk;
+
+ aemif_clk = clk_get(NULL, "aemif");
+ clk_enable(aemif_clk);
+
+ if (HAS_ATA) {
+ if (HAS_NAND || HAS_NOR)
+ pr_warning("WARNING: both IDE and Flash are "
+ "enabled, but they share AEMIF pins.\n"
+ "\tDisable IDE for NAND/NOR support.\n");
+ davinci_cfg_reg(DM644X_HPIEN_DISABLE);
+ davinci_cfg_reg(DM644X_ATAEN);
+ davinci_cfg_reg(DM644X_HDIREN);
+ platform_device_register(&ide_dev);
+ } else if (HAS_NAND || HAS_NOR) {
+ davinci_cfg_reg(DM644X_HPIEN_DISABLE);
+ davinci_cfg_reg(DM644X_ATAEN_DISABLE);
+
+ /* only one device will be jumpered and detected */
+ if (HAS_NAND) {
+ platform_device_register(&davinci_evm_nandflash_device);
+ evm_leds[7].default_trigger = "nand-disk";
+ if (HAS_NOR)
+ pr_warning("WARNING: both NAND and NOR flash "
+ "are enabled; disable one of them.\n");
+ } else if (HAS_NOR)
+ platform_device_register(&davinci_evm_norflash_device);
+ }
+
+ platform_add_devices(davinci_evm_devices,
+ ARRAY_SIZE(davinci_evm_devices));
+ evm_init_i2c();
+
+ davinci_serial_init(&uart_config);
+
+ /* Register the fixup for PHY on DaVinci */
+ phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
+ davinci_phy_fixup);
+
+}
+
+static __init void davinci_evm_irq_init(void)
+{
+ davinci_irq_init();
+}
+
+MACHINE_START(DAVINCI_EVM, "DaVinci DM644x EVM")
+ /* Maintainer: MontaVista Software <source@mvista.com> */
+ .phys_io = IO_PHYS,
+ .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
+ .boot_params = (DAVINCI_DDR_BASE + 0x100),
+ .map_io = davinci_evm_map_io,
+ .init_irq = davinci_evm_irq_init,
+ .timer = &davinci_timer,
+ .init_machine = davinci_evm_init,
+MACHINE_END
+++ /dev/null
-/*
- * TI DaVinci EVM board support
- *
- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
- *
- * 2007 (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.
- */
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/dma-mapping.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/leds.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c/pcf857x.h>
-#include <linux/i2c/at24.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/physmap.h>
-#include <linux/io.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/flash.h>
-
-#include <mach/hardware.h>
-#include <mach/common.h>
-#include <mach/i2c.h>
-
-/* other misc. init functions */
-void __init davinci_psc_init(void);
-void __init davinci_irq_init(void);
-void __init davinci_map_common_io(void);
-void __init davinci_init_common_hw(void);
-
-#if defined(CONFIG_MTD_PHYSMAP) || \
- defined(CONFIG_MTD_PHYSMAP_MODULE)
-
-static struct mtd_partition davinci_evm_norflash_partitions[] = {
- /* bootloader (U-Boot, etc) in first 4 sectors */
- {
- .name = "bootloader",
- .offset = 0,
- .size = 4 * SZ_64K,
- .mask_flags = MTD_WRITEABLE, /* force read-only */
- },
- /* bootloader params in the next 1 sectors */
- {
- .name = "params",
- .offset = MTDPART_OFS_APPEND,
- .size = SZ_64K,
- .mask_flags = 0,
- },
- /* kernel */
- {
- .name = "kernel",
- .offset = MTDPART_OFS_APPEND,
- .size = SZ_2M,
- .mask_flags = 0
- },
- /* file system */
- {
- .name = "filesystem",
- .offset = MTDPART_OFS_APPEND,
- .size = MTDPART_SIZ_FULL,
- .mask_flags = 0
- }
-};
-
-static struct physmap_flash_data davinci_evm_norflash_data = {
- .width = 2,
- .parts = davinci_evm_norflash_partitions,
- .nr_parts = ARRAY_SIZE(davinci_evm_norflash_partitions),
-};
-
-/* NOTE: CFI probe will correctly detect flash part as 32M, but EMIF
- * limits addresses to 16M, so using addresses past 16M will wrap */
-static struct resource davinci_evm_norflash_resource = {
- .start = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE,
- .end = DAVINCI_ASYNC_EMIF_DATA_CE0_BASE + SZ_16M - 1,
- .flags = IORESOURCE_MEM,
-};
-
-static struct platform_device davinci_evm_norflash_device = {
- .name = "physmap-flash",
- .id = 0,
- .dev = {
- .platform_data = &davinci_evm_norflash_data,
- },
- .num_resources = 1,
- .resource = &davinci_evm_norflash_resource,
-};
-
-#endif
-
-#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
- defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
-
-static struct resource ide_resources[] = {
- {
- .start = DAVINCI_CFC_ATA_BASE,
- .end = DAVINCI_CFC_ATA_BASE + 0x7ff,
- .flags = IORESOURCE_MEM,
- },
- {
- .start = IRQ_IDE,
- .end = IRQ_IDE,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static u64 ide_dma_mask = DMA_BIT_MASK(32);
-
-static struct platform_device ide_dev = {
- .name = "palm_bk3710",
- .id = -1,
- .resource = ide_resources,
- .num_resources = ARRAY_SIZE(ide_resources),
- .dev = {
- .dma_mask = &ide_dma_mask,
- .coherent_dma_mask = DMA_BIT_MASK(32),
- },
-};
-
-#endif
-
-/*----------------------------------------------------------------------*/
-
-/*
- * I2C GPIO expanders
- */
-
-#define PCF_Uxx_BASE(x) (DAVINCI_N_GPIO + ((x) * 8))
-
-
-/* U2 -- LEDs */
-
-static struct gpio_led evm_leds[] = {
- { .name = "DS8", .active_low = 1,
- .default_trigger = "heartbeat", },
- { .name = "DS7", .active_low = 1, },
- { .name = "DS6", .active_low = 1, },
- { .name = "DS5", .active_low = 1, },
- { .name = "DS4", .active_low = 1, },
- { .name = "DS3", .active_low = 1, },
- { .name = "DS2", .active_low = 1,
- .default_trigger = "mmc0", },
- { .name = "DS1", .active_low = 1,
- .default_trigger = "ide-disk", },
-};
-
-static const struct gpio_led_platform_data evm_led_data = {
- .num_leds = ARRAY_SIZE(evm_leds),
- .leds = evm_leds,
-};
-
-static struct platform_device *evm_led_dev;
-
-static int
-evm_led_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
-{
- struct gpio_led *leds = evm_leds;
- int status;
-
- while (ngpio--) {
- leds->gpio = gpio++;
- leds++;
- }
-
- /* what an extremely annoying way to be forced to handle
- * device unregistration ...
- */
- evm_led_dev = platform_device_alloc("leds-gpio", 0);
- platform_device_add_data(evm_led_dev,
- &evm_led_data, sizeof evm_led_data);
-
- evm_led_dev->dev.parent = &client->dev;
- status = platform_device_add(evm_led_dev);
- if (status < 0) {
- platform_device_put(evm_led_dev);
- evm_led_dev = NULL;
- }
- return status;
-}
-
-static int
-evm_led_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
-{
- if (evm_led_dev) {
- platform_device_unregister(evm_led_dev);
- evm_led_dev = NULL;
- }
- return 0;
-}
-
-static struct pcf857x_platform_data pcf_data_u2 = {
- .gpio_base = PCF_Uxx_BASE(0),
- .setup = evm_led_setup,
- .teardown = evm_led_teardown,
-};
-
-
-/* U18 - A/V clock generator and user switch */
-
-static int sw_gpio;
-
-static ssize_t
-sw_show(struct device *d, struct device_attribute *a, char *buf)
-{
- char *s = gpio_get_value_cansleep(sw_gpio) ? "on\n" : "off\n";
-
- strcpy(buf, s);
- return strlen(s);
-}
-
-static DEVICE_ATTR(user_sw, S_IRUGO, sw_show, NULL);
-
-static int
-evm_u18_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
-{
- int status;
-
- /* export dip switch option */
- sw_gpio = gpio + 7;
- status = gpio_request(sw_gpio, "user_sw");
- if (status == 0)
- status = gpio_direction_input(sw_gpio);
- if (status == 0)
- status = device_create_file(&client->dev, &dev_attr_user_sw);
- else
- gpio_free(sw_gpio);
- if (status != 0)
- sw_gpio = -EINVAL;
-
- /* audio PLL: 48 kHz (vs 44.1 or 32), single rate (vs double) */
- gpio_request(gpio + 3, "pll_fs2");
- gpio_direction_output(gpio + 3, 0);
-
- gpio_request(gpio + 2, "pll_fs1");
- gpio_direction_output(gpio + 2, 0);
-
- gpio_request(gpio + 1, "pll_sr");
- gpio_direction_output(gpio + 1, 0);
-
- return 0;
-}
-
-static int
-evm_u18_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
-{
- gpio_free(gpio + 1);
- gpio_free(gpio + 2);
- gpio_free(gpio + 3);
-
- if (sw_gpio > 0) {
- device_remove_file(&client->dev, &dev_attr_user_sw);
- gpio_free(sw_gpio);
- }
- return 0;
-}
-
-static struct pcf857x_platform_data pcf_data_u18 = {
- .gpio_base = PCF_Uxx_BASE(1),
- .n_latch = (1 << 3) | (1 << 2) | (1 << 1),
- .setup = evm_u18_setup,
- .teardown = evm_u18_teardown,
-};
-
-
-/* U35 - various I/O signals used to manage USB, CF, ATA, etc */
-
-static int
-evm_u35_setup(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
-{
- /* p0 = nDRV_VBUS (initial: don't supply it) */
- gpio_request(gpio + 0, "nDRV_VBUS");
- gpio_direction_output(gpio + 0, 1);
-
- /* p1 = VDDIMX_EN */
- gpio_request(gpio + 1, "VDDIMX_EN");
- gpio_direction_output(gpio + 1, 1);
-
- /* p2 = VLYNQ_EN */
- gpio_request(gpio + 2, "VLYNQ_EN");
- gpio_direction_output(gpio + 2, 1);
-
- /* p3 = n3V3_CF_RESET (initial: stay in reset) */
- gpio_request(gpio + 3, "nCF_RESET");
- gpio_direction_output(gpio + 3, 0);
-
- /* (p4 unused) */
-
- /* p5 = 1V8_WLAN_RESET (initial: stay in reset) */
- gpio_request(gpio + 5, "WLAN_RESET");
- gpio_direction_output(gpio + 5, 1);
-
- /* p6 = nATA_SEL (initial: select) */
- gpio_request(gpio + 6, "nATA_SEL");
- gpio_direction_output(gpio + 6, 0);
-
- /* p7 = nCF_SEL (initial: deselect) */
- gpio_request(gpio + 7, "nCF_SEL");
- gpio_direction_output(gpio + 7, 1);
-
- /* irlml6401 sustains over 3A, switches 5V in under 8 msec */
- setup_usb(500, 8);
-
- return 0;
-}
-
-static int
-evm_u35_teardown(struct i2c_client *client, int gpio, unsigned ngpio, void *c)
-{
- gpio_free(gpio + 7);
- gpio_free(gpio + 6);
- gpio_free(gpio + 5);
- gpio_free(gpio + 3);
- gpio_free(gpio + 2);
- gpio_free(gpio + 1);
- gpio_free(gpio + 0);
- return 0;
-}
-
-static struct pcf857x_platform_data pcf_data_u35 = {
- .gpio_base = PCF_Uxx_BASE(2),
- .setup = evm_u35_setup,
- .teardown = evm_u35_teardown,
-};
-
-/*----------------------------------------------------------------------*/
-
-/* Most of this EEPROM is unused, but U-Boot uses some data:
- * - 0x7f00, 6 bytes Ethernet Address
- * - 0x0039, 1 byte NTSC vs PAL (bit 0x80 == PAL)
- * - ... newer boards may have more
- */
-static struct at24_platform_data eeprom_info = {
- .byte_len = (256*1024) / 8,
- .page_size = 64,
- .flags = AT24_FLAG_ADDR16,
-};
-
-static struct i2c_board_info __initdata i2c_info[] = {
- {
- I2C_BOARD_INFO("pcf8574", 0x38),
- .platform_data = &pcf_data_u2,
- },
- {
- I2C_BOARD_INFO("pcf8574", 0x39),
- .platform_data = &pcf_data_u18,
- },
- {
- I2C_BOARD_INFO("pcf8574", 0x3a),
- .platform_data = &pcf_data_u35,
- },
- {
- I2C_BOARD_INFO("24c256", 0x50),
- .platform_data = &eeprom_info,
- },
- /* ALSO:
- * - tvl320aic33 audio codec (0x1b)
- * - msp430 microcontroller (0x23)
- * - tvp5146 video decoder (0x5d)
- */
-};
-
-/* The msp430 uses a slow bitbanged I2C implementation (ergo 20 KHz),
- * which requires 100 usec of idle bus after i2c writes sent to it.
- */
-static struct davinci_i2c_platform_data i2c_pdata = {
- .bus_freq = 20 /* kHz */,
- .bus_delay = 100 /* usec */,
-};
-
-static void __init evm_init_i2c(void)
-{
- davinci_init_i2c(&i2c_pdata);
- i2c_register_board_info(1, i2c_info, ARRAY_SIZE(i2c_info));
-}
-
-static struct platform_device *davinci_evm_devices[] __initdata = {
-#if defined(CONFIG_MTD_PHYSMAP) || \
- defined(CONFIG_MTD_PHYSMAP_MODULE)
- &davinci_evm_norflash_device,
-#endif
-#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
- defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
- &ide_dev,
-#endif
-};
-
-static void __init
-davinci_evm_map_io(void)
-{
- davinci_map_common_io();
-}
-
-static __init void davinci_evm_init(void)
-{
- davinci_psc_init();
-
-#if defined(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
- defined(CONFIG_BLK_DEV_PALMCHIP_BK3710_MODULE)
-#if defined(CONFIG_MTD_PHYSMAP) || \
- defined(CONFIG_MTD_PHYSMAP_MODULE)
- printk(KERN_WARNING "WARNING: both IDE and NOR flash are enabled, "
- "but share pins.\n\t Disable IDE for NOR support.\n");
-#endif
-#endif
-
- platform_add_devices(davinci_evm_devices,
- ARRAY_SIZE(davinci_evm_devices));
- evm_init_i2c();
-}
-
-static __init void davinci_evm_irq_init(void)
-{
- davinci_init_common_hw();
- davinci_irq_init();
-}
-
-MACHINE_START(DAVINCI_EVM, "DaVinci EVM")
- /* Maintainer: MontaVista Software <source@mvista.com> */
- .phys_io = IO_PHYS,
- .io_pg_offst = (__IO_ADDRESS(IO_PHYS) >> 18) & 0xfffc,
- .boot_params = (DAVINCI_DDR_BASE + 0x100),
- .map_io = davinci_evm_map_io,
- .init_irq = davinci_evm_irq_init,
- .timer = &davinci_timer,
- .init_machine = davinci_evm_init,
-MACHINE_END
/*
- * TI DaVinci clock config file
+ * Clock and PLL control for DaVinci devices
*
- * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2006-2007 Texas Instruments.
+ * Copyright (C) 2008-2009 Deep Root Systems, LLC
*
* 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
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
+#include <linux/clk.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <mach/hardware.h>
#include <mach/psc.h>
+#include <mach/cputype.h>
#include "clock.h"
-/* PLL/Reset register offsets */
-#define PLLM 0x110
-
static LIST_HEAD(clocks);
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clockfw_lock);
-static unsigned int commonrate;
-static unsigned int armrate;
-static unsigned int fixedrate = 27000000; /* 27 MHZ */
-
-extern void davinci_psc_config(unsigned int domain, unsigned int id, char enable);
-
-/*
- * Returns a clock. Note that we first try to use device id on the bus
- * and clock name. If this fails, we try to use clock name only.
- */
-struct clk *clk_get(struct device *dev, const char *id)
+static unsigned psc_domain(struct clk *clk)
{
- struct clk *p, *clk = ERR_PTR(-ENOENT);
- int idno;
-
- if (dev == NULL || dev->bus != &platform_bus_type)
- idno = -1;
- else
- idno = to_platform_device(dev)->id;
-
- mutex_lock(&clocks_mutex);
-
- list_for_each_entry(p, &clocks, node) {
- if (p->id == idno &&
- strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
- clk = p;
- goto found;
- }
- }
-
- list_for_each_entry(p, &clocks, node) {
- if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
- clk = p;
- break;
- }
- }
-
-found:
- mutex_unlock(&clocks_mutex);
-
- return clk;
+ return (clk->flags & PSC_DSP)
+ ? DAVINCI_GPSC_DSPDOMAIN
+ : DAVINCI_GPSC_ARMDOMAIN;
}
-EXPORT_SYMBOL(clk_get);
-void clk_put(struct clk *clk)
+static void __clk_enable(struct clk *clk)
{
- if (clk && !IS_ERR(clk))
- module_put(clk->owner);
-}
-EXPORT_SYMBOL(clk_put);
-
-static int __clk_enable(struct clk *clk)
-{
- if (clk->flags & ALWAYS_ENABLED)
- return 0;
-
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 1);
- return 0;
+ if (clk->parent)
+ __clk_enable(clk->parent);
+ if (clk->usecount++ == 0 && (clk->flags & CLK_PSC))
+ davinci_psc_config(psc_domain(clk), clk->lpsc, 1);
}
static void __clk_disable(struct clk *clk)
{
- if (clk->usecount)
+ if (WARN_ON(clk->usecount == 0))
return;
-
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, clk->lpsc, 0);
+ if (--clk->usecount == 0 && !(clk->flags & CLK_PLL))
+ davinci_psc_config(psc_domain(clk), clk->lpsc, 0);
+ if (clk->parent)
+ __clk_disable(clk->parent);
}
int clk_enable(struct clk *clk)
{
unsigned long flags;
- int ret = 0;
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- if (clk->usecount++ == 0) {
- spin_lock_irqsave(&clockfw_lock, flags);
- ret = __clk_enable(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
- }
+ spin_lock_irqsave(&clockfw_lock, flags);
+ __clk_enable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
- return ret;
+ return 0;
}
EXPORT_SYMBOL(clk_enable);
if (clk == NULL || IS_ERR(clk))
return;
- if (clk->usecount > 0 && !(--clk->usecount)) {
- spin_lock_irqsave(&clockfw_lock, flags);
- __clk_disable(clk);
- spin_unlock_irqrestore(&clockfw_lock, flags);
- }
+ spin_lock_irqsave(&clockfw_lock, flags);
+ __clk_disable(clk);
+ spin_unlock_irqrestore(&clockfw_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- return *(clk->rate);
+ return clk->rate;
}
EXPORT_SYMBOL(clk_get_rate);
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
- return *(clk->rate);
+ return clk->rate;
}
EXPORT_SYMBOL(clk_round_rate);
if (clk == NULL || IS_ERR(clk))
return -EINVAL;
+ if (WARN(clk->parent && !clk->parent->rate,
+ "CLK: %s parent %s has no rate!\n",
+ clk->name, clk->parent->name))
+ return -EINVAL;
+
mutex_lock(&clocks_mutex);
- list_add(&clk->node, &clocks);
+ list_add_tail(&clk->node, &clocks);
mutex_unlock(&clocks_mutex);
+ /* If rate is already set, use it */
+ if (clk->rate)
+ return 0;
+
+ /* Otherwise, default to parent rate */
+ if (clk->parent)
+ clk->rate = clk->parent->rate;
+
return 0;
}
EXPORT_SYMBOL(clk_register);
}
EXPORT_SYMBOL(clk_unregister);
-static struct clk davinci_clks[] = {
- {
- .name = "ARMCLK",
- .rate = &armrate,
- .lpsc = -1,
- .flags = ALWAYS_ENABLED,
- },
- {
- .name = "UART",
- .rate = &fixedrate,
- .lpsc = DAVINCI_LPSC_UART0,
- },
- {
- .name = "EMACCLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
- },
- {
- .name = "I2CCLK",
- .rate = &fixedrate,
- .lpsc = DAVINCI_LPSC_I2C,
- },
- {
- .name = "IDECLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_ATA,
- },
- {
- .name = "McBSPCLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_McBSP,
- },
- {
- .name = "MMCSDCLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_MMC_SD,
- },
- {
- .name = "SPICLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_SPI,
- },
- {
- .name = "gpio",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_GPIO,
- },
- {
- .name = "usb",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_USB,
- },
- {
- .name = "AEMIFCLK",
- .rate = &commonrate,
- .lpsc = DAVINCI_LPSC_AEMIF,
- .usecount = 1,
+#ifdef CONFIG_DAVINCI_RESET_CLOCKS
+/*
+ * Disable any unused clocks left on by the bootloader
+ */
+static int __init clk_disable_unused(void)
+{
+ struct clk *ck;
+
+ spin_lock_irq(&clockfw_lock);
+ list_for_each_entry(ck, &clocks, node) {
+ if (ck->usecount > 0)
+ continue;
+ if (!(ck->flags & CLK_PSC))
+ continue;
+
+ /* ignore if in Disabled or SwRstDisable states */
+ if (!davinci_psc_is_clk_active(ck->lpsc))
+ continue;
+
+ pr_info("Clocks: disable unused %s\n", ck->name);
+ davinci_psc_config(psc_domain(ck), ck->lpsc, 0);
}
-};
+ spin_unlock_irq(&clockfw_lock);
+
+ return 0;
+}
+late_initcall(clk_disable_unused);
+#endif
-int __init davinci_clk_init(void)
+static void clk_sysclk_recalc(struct clk *clk)
{
- struct clk *clkp;
- int count = 0;
- u32 pll_mult;
-
- pll_mult = davinci_readl(DAVINCI_PLL_CNTRL0_BASE + PLLM);
- commonrate = ((pll_mult + 1) * 27000000) / 6;
- armrate = ((pll_mult + 1) * 27000000) / 2;
-
- for (clkp = davinci_clks; count < ARRAY_SIZE(davinci_clks);
- count++, clkp++) {
- clk_register(clkp);
-
- /* Turn on clocks that have been enabled in the
- * table above */
- if (clkp->usecount)
- clk_enable(clkp);
+ u32 v, plldiv;
+ struct pll_data *pll;
+
+ /* If this is the PLL base clock, no more calculations needed */
+ if (clk->pll_data)
+ return;
+
+ if (WARN_ON(!clk->parent))
+ return;
+
+ clk->rate = clk->parent->rate;
+
+ /* Otherwise, the parent must be a PLL */
+ if (WARN_ON(!clk->parent->pll_data))
+ return;
+
+ pll = clk->parent->pll_data;
+
+ /* If pre-PLL, source clock is before the multiplier and divider(s) */
+ if (clk->flags & PRE_PLL)
+ clk->rate = pll->input_rate;
+
+ if (!clk->div_reg)
+ return;
+
+ v = __raw_readl(pll->base + clk->div_reg);
+ if (v & PLLDIV_EN) {
+ plldiv = (v & PLLDIV_RATIO_MASK) + 1;
+ if (plldiv)
+ clk->rate /= plldiv;
+ }
+}
+
+static void __init clk_pll_init(struct clk *clk)
+{
+ u32 ctrl, mult = 1, prediv = 1, postdiv = 1;
+ u8 bypass;
+ struct pll_data *pll = clk->pll_data;
+
+ pll->base = IO_ADDRESS(pll->phys_base);
+ ctrl = __raw_readl(pll->base + PLLCTL);
+ clk->rate = pll->input_rate = clk->parent->rate;
+
+ if (ctrl & PLLCTL_PLLEN) {
+ bypass = 0;
+ mult = __raw_readl(pll->base + PLLM);
+ mult = (mult & PLLM_PLLM_MASK) + 1;
+ } else
+ bypass = 1;
+
+ if (pll->flags & PLL_HAS_PREDIV) {
+ prediv = __raw_readl(pll->base + PREDIV);
+ if (prediv & PLLDIV_EN)
+ prediv = (prediv & PLLDIV_RATIO_MASK) + 1;
+ else
+ prediv = 1;
+ }
+
+ /* pre-divider is fixed, but (some?) chips won't report that */
+ if (cpu_is_davinci_dm355() && pll->num == 1)
+ prediv = 8;
+
+ if (pll->flags & PLL_HAS_POSTDIV) {
+ postdiv = __raw_readl(pll->base + POSTDIV);
+ if (postdiv & PLLDIV_EN)
+ postdiv = (postdiv & PLLDIV_RATIO_MASK) + 1;
+ else
+ postdiv = 1;
+ }
+
+ if (!bypass) {
+ clk->rate /= prediv;
+ clk->rate *= mult;
+ clk->rate /= postdiv;
+ }
+
+ pr_debug("PLL%d: input = %lu MHz [ ",
+ pll->num, clk->parent->rate / 1000000);
+ if (bypass)
+ pr_debug("bypass ");
+ if (prediv > 1)
+ pr_debug("/ %d ", prediv);
+ if (mult > 1)
+ pr_debug("* %d ", mult);
+ if (postdiv > 1)
+ pr_debug("/ %d ", postdiv);
+ pr_debug("] --> %lu MHz output.\n", clk->rate / 1000000);
+}
+
+int __init davinci_clk_init(struct davinci_clk *clocks)
+ {
+ struct davinci_clk *c;
+ struct clk *clk;
+
+ for (c = clocks; c->lk.clk; c++) {
+ clk = c->lk.clk;
+
+ if (clk->pll_data)
+ clk_pll_init(clk);
+
+ /* Calculate rates for PLL-derived clocks */
+ else if (clk->flags & CLK_PLL)
+ clk_sysclk_recalc(clk);
+
+ if (clk->lpsc)
+ clk->flags |= CLK_PSC;
+
+ clkdev_add(&c->lk);
+ clk_register(clk);
+
+ /* Turn on clocks that Linux doesn't otherwise manage */
+ if (clk->flags & ALWAYS_ENABLED)
+ clk_enable(clk);
}
return 0;
{
}
-static int davinci_ck_show(struct seq_file *m, void *v)
+#define CLKNAME_MAX 10 /* longest clock name */
+#define NEST_DELTA 2
+#define NEST_MAX 4
+
+static void
+dump_clock(struct seq_file *s, unsigned nest, struct clk *parent)
{
- struct clk *cp;
+ char *state;
+ char buf[CLKNAME_MAX + NEST_DELTA * NEST_MAX];
+ struct clk *clk;
+ unsigned i;
+
+ if (parent->flags & CLK_PLL)
+ state = "pll";
+ else if (parent->flags & CLK_PSC)
+ state = "psc";
+ else
+ state = "";
+
+ /* <nest spaces> name <pad to end> */
+ memset(buf, ' ', sizeof(buf) - 1);
+ buf[sizeof(buf) - 1] = 0;
+ i = strlen(parent->name);
+ memcpy(buf + nest, parent->name,
+ min(i, (unsigned)(sizeof(buf) - 1 - nest)));
+
+ seq_printf(s, "%s users=%2d %-3s %9ld Hz\n",
+ buf, parent->usecount, state, clk_get_rate(parent));
+ /* REVISIT show device associations too */
+
+ /* cost is now small, but not linear... */
+ list_for_each_entry(clk, &clocks, node) {
+ if (clk->parent == parent)
+ dump_clock(s, nest + NEST_DELTA, clk);
+ }
+}
- list_for_each_entry(cp, &clocks, node)
- seq_printf(m,"%s %d %d\n", cp->name, *(cp->rate), cp->usecount);
+static int davinci_ck_show(struct seq_file *m, void *v)
+{
+ /* Show clock tree; we know the main oscillator is first.
+ * We trust nonzero usecounts equate to PSC enables...
+ */
+ mutex_lock(&clocks_mutex);
+ if (!list_empty(&clocks))
+ dump_clock(m, 0, list_first_entry(&clocks, struct clk, node));
+ mutex_unlock(&clocks_mutex);
return 0;
}
}
__initcall(davinci_ck_proc_init);
-#endif /* CONFIG_DEBUG_PROC_FS */
+#endif /* CONFIG_DEBUG_PROC_FS */
/*
* TI DaVinci clock definitions
*
- * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2006-2007 Texas Instruments.
+ * Copyright (C) 2008-2009 Deep Root Systems, LLC
*
* 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
#ifndef __ARCH_ARM_DAVINCI_CLOCK_H
#define __ARCH_ARM_DAVINCI_CLOCK_H
+#include <linux/list.h>
+#include <asm/clkdev.h>
+
+#define DAVINCI_PLL1_BASE 0x01c40800
+#define DAVINCI_PLL2_BASE 0x01c40c00
+#define MAX_PLL 2
+
+/* PLL/Reset register offsets */
+#define PLLCTL 0x100
+#define PLLCTL_PLLEN BIT(0)
+#define PLLCTL_CLKMODE BIT(8)
+
+#define PLLM 0x110
+#define PLLM_PLLM_MASK 0xff
+
+#define PREDIV 0x114
+#define PLLDIV1 0x118
+#define PLLDIV2 0x11c
+#define PLLDIV3 0x120
+#define POSTDIV 0x128
+#define BPDIV 0x12c
+#define PLLCMD 0x138
+#define PLLSTAT 0x13c
+#define PLLALNCTL 0x140
+#define PLLDCHANGE 0x144
+#define PLLCKEN 0x148
+#define PLLCKSTAT 0x14c
+#define PLLSYSTAT 0x150
+#define PLLDIV4 0x160
+#define PLLDIV5 0x164
+#define PLLDIV6 0x168
+#define PLLDIV7 0x16c
+#define PLLDIV8 0x170
+#define PLLDIV9 0x174
+#define PLLDIV_EN BIT(15)
+#define PLLDIV_RATIO_MASK 0x1f
+
+struct pll_data {
+ u32 phys_base;
+ void __iomem *base;
+ u32 num;
+ u32 flags;
+ u32 input_rate;
+};
+#define PLL_HAS_PREDIV 0x01
+#define PLL_HAS_POSTDIV 0x02
+
struct clk {
struct list_head node;
struct module *owner;
const char *name;
- unsigned int *rate;
- int id;
- __s8 usecount;
- __u8 flags;
- __u8 lpsc;
+ unsigned long rate;
+ u8 usecount;
+ u8 flags;
+ u8 lpsc;
+ struct clk *parent;
+ struct pll_data *pll_data;
+ u32 div_reg;
};
/* Clock flags */
-#define RATE_CKCTL 1
-#define RATE_FIXED 2
-#define RATE_PROPAGATES 4
-#define VIRTUAL_CLOCK 8
-#define ALWAYS_ENABLED 16
-#define ENABLE_REG_32BIT 32
+#define ALWAYS_ENABLED BIT(1)
+#define CLK_PSC BIT(2)
+#define PSC_DSP BIT(3) /* PSC uses DSP domain, not ARM */
+#define CLK_PLL BIT(4) /* PLL-derived clock */
+#define PRE_PLL BIT(5) /* source is before PLL mult/div */
+
+struct davinci_clk {
+ struct clk_lookup lk;
+};
+
+#define CLK(dev, con, ck) \
+ { \
+ .lk = { \
+ .dev_id = dev, \
+ .con_id = con, \
+ .clk = ck, \
+ }, \
+ }
+int davinci_clk_init(struct davinci_clk *clocks);
#endif
#include <mach/hardware.h>
#include <mach/i2c.h>
#include <mach/irqs.h>
+#include <mach/cputype.h>
+#include <mach/mux.h>
+
+#define DAVINCI_I2C_BASE 0x01C21000
static struct resource i2c_resources[] = {
{
void __init davinci_init_i2c(struct davinci_i2c_platform_data *pdata)
{
+ if (cpu_is_davinci_dm644x())
+ davinci_cfg_reg(DM644X_I2C);
+
davinci_i2c_device.dev.platform_data = pdata;
(void) platform_device_register(&davinci_i2c_device);
}
--- /dev/null
+/*
+ * TI DaVinci DM644x chip specific setup
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. 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.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+
+#include <mach/dm644x.h>
+#include <mach/clock.h>
+#include <mach/cputype.h>
+#include <mach/edma.h>
+#include <mach/irqs.h>
+#include <mach/psc.h>
+#include <mach/mux.h>
+
+#include "clock.h"
+#include "mux.h"
+
+/*
+ * Device specific clocks
+ */
+#define DM644X_REF_FREQ 27000000
+
+static struct pll_data pll1_data = {
+ .num = 1,
+ .phys_base = DAVINCI_PLL1_BASE,
+};
+
+static struct pll_data pll2_data = {
+ .num = 2,
+ .phys_base = DAVINCI_PLL2_BASE,
+};
+
+static struct clk ref_clk = {
+ .name = "ref_clk",
+ .rate = DM644X_REF_FREQ,
+};
+
+static struct clk pll1_clk = {
+ .name = "pll1",
+ .parent = &ref_clk,
+ .pll_data = &pll1_data,
+ .flags = CLK_PLL,
+};
+
+static struct clk pll1_sysclk1 = {
+ .name = "pll1_sysclk1",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV1,
+};
+
+static struct clk pll1_sysclk2 = {
+ .name = "pll1_sysclk2",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV2,
+};
+
+static struct clk pll1_sysclk3 = {
+ .name = "pll1_sysclk3",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV3,
+};
+
+static struct clk pll1_sysclk5 = {
+ .name = "pll1_sysclk5",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV5,
+};
+
+static struct clk pll1_aux_clk = {
+ .name = "pll1_aux_clk",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL | PRE_PLL,
+};
+
+static struct clk pll1_sysclkbp = {
+ .name = "pll1_sysclkbp",
+ .parent = &pll1_clk,
+ .flags = CLK_PLL | PRE_PLL,
+ .div_reg = BPDIV
+};
+
+static struct clk pll2_clk = {
+ .name = "pll2",
+ .parent = &ref_clk,
+ .pll_data = &pll2_data,
+ .flags = CLK_PLL,
+};
+
+static struct clk pll2_sysclk1 = {
+ .name = "pll2_sysclk1",
+ .parent = &pll2_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV1,
+};
+
+static struct clk pll2_sysclk2 = {
+ .name = "pll2_sysclk2",
+ .parent = &pll2_clk,
+ .flags = CLK_PLL,
+ .div_reg = PLLDIV2,
+};
+
+static struct clk pll2_sysclkbp = {
+ .name = "pll2_sysclkbp",
+ .parent = &pll2_clk,
+ .flags = CLK_PLL | PRE_PLL,
+ .div_reg = BPDIV
+};
+
+static struct clk dsp_clk = {
+ .name = "dsp",
+ .parent = &pll1_sysclk1,
+ .lpsc = DAVINCI_LPSC_GEM,
+ .flags = PSC_DSP,
+ .usecount = 1, /* REVISIT how to disable? */
+};
+
+static struct clk arm_clk = {
+ .name = "arm",
+ .parent = &pll1_sysclk2,
+ .lpsc = DAVINCI_LPSC_ARM,
+ .flags = ALWAYS_ENABLED,
+};
+
+static struct clk vicp_clk = {
+ .name = "vicp",
+ .parent = &pll1_sysclk2,
+ .lpsc = DAVINCI_LPSC_IMCOP,
+ .flags = PSC_DSP,
+ .usecount = 1, /* REVISIT how to disable? */
+};
+
+static struct clk vpss_master_clk = {
+ .name = "vpss_master",
+ .parent = &pll1_sysclk3,
+ .lpsc = DAVINCI_LPSC_VPSSMSTR,
+ .flags = CLK_PSC,
+};
+
+static struct clk vpss_slave_clk = {
+ .name = "vpss_slave",
+ .parent = &pll1_sysclk3,
+ .lpsc = DAVINCI_LPSC_VPSSSLV,
+};
+
+static struct clk uart0_clk = {
+ .name = "uart0",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_UART0,
+};
+
+static struct clk uart1_clk = {
+ .name = "uart1",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_UART1,
+};
+
+static struct clk uart2_clk = {
+ .name = "uart2",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_UART2,
+};
+
+static struct clk emac_clk = {
+ .name = "emac",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_EMAC_WRAPPER,
+};
+
+static struct clk i2c_clk = {
+ .name = "i2c",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_I2C,
+};
+
+static struct clk ide_clk = {
+ .name = "ide",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_ATA,
+};
+
+static struct clk asp_clk = {
+ .name = "asp0",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_McBSP,
+};
+
+static struct clk mmcsd_clk = {
+ .name = "mmcsd",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_MMC_SD,
+};
+
+static struct clk spi_clk = {
+ .name = "spi",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_SPI,
+};
+
+static struct clk gpio_clk = {
+ .name = "gpio",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_GPIO,
+};
+
+static struct clk usb_clk = {
+ .name = "usb",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_USB,
+};
+
+static struct clk vlynq_clk = {
+ .name = "vlynq",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_VLYNQ,
+};
+
+static struct clk aemif_clk = {
+ .name = "aemif",
+ .parent = &pll1_sysclk5,
+ .lpsc = DAVINCI_LPSC_AEMIF,
+};
+
+static struct clk pwm0_clk = {
+ .name = "pwm0",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_PWM0,
+};
+
+static struct clk pwm1_clk = {
+ .name = "pwm1",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_PWM1,
+};
+
+static struct clk pwm2_clk = {
+ .name = "pwm2",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_PWM2,
+};
+
+static struct clk timer0_clk = {
+ .name = "timer0",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_TIMER0,
+};
+
+static struct clk timer1_clk = {
+ .name = "timer1",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_TIMER1,
+};
+
+static struct clk timer2_clk = {
+ .name = "timer2",
+ .parent = &pll1_aux_clk,
+ .lpsc = DAVINCI_LPSC_TIMER2,
+ .usecount = 1, /* REVISIT: why cant' this be disabled? */
+};
+
+struct davinci_clk dm644x_clks[] = {
+ CLK(NULL, "ref", &ref_clk),
+ CLK(NULL, "pll1", &pll1_clk),
+ CLK(NULL, "pll1_sysclk1", &pll1_sysclk1),
+ CLK(NULL, "pll1_sysclk2", &pll1_sysclk2),
+ CLK(NULL, "pll1_sysclk3", &pll1_sysclk3),
+ CLK(NULL, "pll1_sysclk5", &pll1_sysclk5),
+ CLK(NULL, "pll1_aux", &pll1_aux_clk),
+ CLK(NULL, "pll1_sysclkbp", &pll1_sysclkbp),
+ CLK(NULL, "pll2", &pll2_clk),
+ CLK(NULL, "pll2_sysclk1", &pll2_sysclk1),
+ CLK(NULL, "pll2_sysclk2", &pll2_sysclk2),
+ CLK(NULL, "pll2_sysclkbp", &pll2_sysclkbp),
+ CLK(NULL, "dsp", &dsp_clk),
+ CLK(NULL, "arm", &arm_clk),
+ CLK(NULL, "vicp", &vicp_clk),
+ CLK(NULL, "vpss_master", &vpss_master_clk),
+ CLK(NULL, "vpss_slave", &vpss_slave_clk),
+ CLK(NULL, "arm", &arm_clk),
+ CLK(NULL, "uart0", &uart0_clk),
+ CLK(NULL, "uart1", &uart1_clk),
+ CLK(NULL, "uart2", &uart2_clk),
+ CLK("davinci_emac.1", NULL, &emac_clk),
+ CLK("i2c_davinci.1", NULL, &i2c_clk),
+ CLK("palm_bk3710", NULL, &ide_clk),
+ CLK("soc-audio.0", NULL, &asp_clk),
+ CLK("davinci_mmc.0", NULL, &mmcsd_clk),
+ CLK(NULL, "spi", &spi_clk),
+ CLK(NULL, "gpio", &gpio_clk),
+ CLK(NULL, "usb", &usb_clk),
+ CLK(NULL, "vlynq", &vlynq_clk),
+ CLK(NULL, "aemif", &aemif_clk),
+ CLK(NULL, "pwm0", &pwm0_clk),
+ CLK(NULL, "pwm1", &pwm1_clk),
+ CLK(NULL, "pwm2", &pwm2_clk),
+ CLK(NULL, "timer0", &timer0_clk),
+ CLK(NULL, "timer1", &timer1_clk),
+ CLK("watchdog", NULL, &timer2_clk),
+ CLK(NULL, NULL, NULL),
+};
+
+#if defined(CONFIG_TI_DAVINCI_EMAC) || defined(CONFIG_TI_DAVINCI_EMAC_MODULE)
+
+static struct resource dm644x_emac_resources[] = {
+ {
+ .start = DM644X_EMAC_BASE,
+ .end = DM644X_EMAC_BASE + 0x47ff,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_EMACINT,
+ .end = IRQ_EMACINT,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device dm644x_emac_device = {
+ .name = "davinci_emac",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(dm644x_emac_resources),
+ .resource = dm644x_emac_resources,
+};
+
+#endif
+
+/*
+ * Device specific mux setup
+ *
+ * soc description mux mode mode mux dbg
+ * reg offset mask mode
+ */
+static const struct mux_config dm644x_pins[] = {
+MUX_CFG(DM644X, HDIREN, 0, 16, 1, 1, true)
+MUX_CFG(DM644X, ATAEN, 0, 17, 1, 1, true)
+MUX_CFG(DM644X, ATAEN_DISABLE, 0, 17, 1, 0, true)
+
+MUX_CFG(DM644X, HPIEN_DISABLE, 0, 29, 1, 0, true)
+
+MUX_CFG(DM644X, AEAW, 0, 0, 31, 31, true)
+
+MUX_CFG(DM644X, MSTK, 1, 9, 1, 0, false)
+
+MUX_CFG(DM644X, I2C, 1, 7, 1, 1, false)
+
+MUX_CFG(DM644X, MCBSP, 1, 10, 1, 1, false)
+
+MUX_CFG(DM644X, UART1, 1, 1, 1, 1, true)
+MUX_CFG(DM644X, UART2, 1, 2, 1, 1, true)
+
+MUX_CFG(DM644X, PWM0, 1, 4, 1, 1, false)
+
+MUX_CFG(DM644X, PWM1, 1, 5, 1, 1, false)
+
+MUX_CFG(DM644X, PWM2, 1, 6, 1, 1, false)
+
+MUX_CFG(DM644X, VLYNQEN, 0, 15, 1, 1, false)
+MUX_CFG(DM644X, VLSCREN, 0, 14, 1, 1, false)
+MUX_CFG(DM644X, VLYNQWD, 0, 12, 3, 3, false)
+
+MUX_CFG(DM644X, EMACEN, 0, 31, 1, 1, true)
+
+MUX_CFG(DM644X, GPIO3V, 0, 31, 1, 0, true)
+
+MUX_CFG(DM644X, GPIO0, 0, 24, 1, 0, true)
+MUX_CFG(DM644X, GPIO3, 0, 25, 1, 0, false)
+MUX_CFG(DM644X, GPIO43_44, 1, 7, 1, 0, false)
+MUX_CFG(DM644X, GPIO46_47, 0, 22, 1, 0, true)
+
+MUX_CFG(DM644X, RGB666, 0, 22, 1, 1, true)
+
+MUX_CFG(DM644X, LOEEN, 0, 24, 1, 1, true)
+MUX_CFG(DM644X, LFLDEN, 0, 25, 1, 1, false)
+};
+
+
+/*----------------------------------------------------------------------*/
+
+static const s8 dma_chan_dm644x_no_event[] = {
+ 0, 1, 12, 13, 14,
+ 15, 25, 30, 31, 45,
+ 46, 47, 55, 56, 57,
+ 58, 59, 60, 61, 62,
+ 63,
+ -1
+};
+
+static struct edma_soc_info dm644x_edma_info = {
+ .n_channel = 64,
+ .n_region = 4,
+ .n_slot = 128,
+ .n_tc = 2,
+ .noevent = dma_chan_dm644x_no_event,
+};
+
+static struct resource edma_resources[] = {
+ {
+ .name = "edma_cc",
+ .start = 0x01c00000,
+ .end = 0x01c00000 + SZ_64K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "edma_tc0",
+ .start = 0x01c10000,
+ .end = 0x01c10000 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .name = "edma_tc1",
+ .start = 0x01c10400,
+ .end = 0x01c10400 + SZ_1K - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ {
+ .start = IRQ_CCINT0,
+ .flags = IORESOURCE_IRQ,
+ },
+ {
+ .start = IRQ_CCERRINT,
+ .flags = IORESOURCE_IRQ,
+ },
+ /* not using TC*_ERR */
+};
+
+static struct platform_device dm644x_edma_device = {
+ .name = "edma",
+ .id = -1,
+ .dev.platform_data = &dm644x_edma_info,
+ .num_resources = ARRAY_SIZE(edma_resources),
+ .resource = edma_resources,
+};
+
+/*----------------------------------------------------------------------*/
+void __init dm644x_init(void)
+{
+ davinci_clk_init(dm644x_clks);
+ davinci_mux_register(dm644x_pins, ARRAY_SIZE(dm644x_pins));
+}
+
+static int __init dm644x_init_devices(void)
+{
+ if (!cpu_is_davinci_dm644x())
+ return 0;
+
+ platform_device_register(&dm644x_edma_device);
+ return 0;
+}
+postcore_initcall(dm644x_init_devices);
--- /dev/null
+/*
+ * EDMA3 support for DaVinci
+ *
+ * Copyright (C) 2006-2009 Texas Instruments.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/compiler.h>
+#include <linux/io.h>
+
+#include <mach/cputype.h>
+#include <mach/memory.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/edma.h>
+#include <mach/mux.h>
+
+
+/* Offsets matching "struct edmacc_param" */
+#define PARM_OPT 0x00
+#define PARM_SRC 0x04
+#define PARM_A_B_CNT 0x08
+#define PARM_DST 0x0c
+#define PARM_SRC_DST_BIDX 0x10
+#define PARM_LINK_BCNTRLD 0x14
+#define PARM_SRC_DST_CIDX 0x18
+#define PARM_CCNT 0x1c
+
+#define PARM_SIZE 0x20
+
+/* Offsets for EDMA CC global channel registers and their shadows */
+#define SH_ER 0x00 /* 64 bits */
+#define SH_ECR 0x08 /* 64 bits */
+#define SH_ESR 0x10 /* 64 bits */
+#define SH_CER 0x18 /* 64 bits */
+#define SH_EER 0x20 /* 64 bits */
+#define SH_EECR 0x28 /* 64 bits */
+#define SH_EESR 0x30 /* 64 bits */
+#define SH_SER 0x38 /* 64 bits */
+#define SH_SECR 0x40 /* 64 bits */
+#define SH_IER 0x50 /* 64 bits */
+#define SH_IECR 0x58 /* 64 bits */
+#define SH_IESR 0x60 /* 64 bits */
+#define SH_IPR 0x68 /* 64 bits */
+#define SH_ICR 0x70 /* 64 bits */
+#define SH_IEVAL 0x78
+#define SH_QER 0x80
+#define SH_QEER 0x84
+#define SH_QEECR 0x88
+#define SH_QEESR 0x8c
+#define SH_QSER 0x90
+#define SH_QSECR 0x94
+#define SH_SIZE 0x200
+
+/* Offsets for EDMA CC global registers */
+#define EDMA_REV 0x0000
+#define EDMA_CCCFG 0x0004
+#define EDMA_QCHMAP 0x0200 /* 8 registers */
+#define EDMA_DMAQNUM 0x0240 /* 8 registers (4 on OMAP-L1xx) */
+#define EDMA_QDMAQNUM 0x0260
+#define EDMA_QUETCMAP 0x0280
+#define EDMA_QUEPRI 0x0284
+#define EDMA_EMR 0x0300 /* 64 bits */
+#define EDMA_EMCR 0x0308 /* 64 bits */
+#define EDMA_QEMR 0x0310
+#define EDMA_QEMCR 0x0314
+#define EDMA_CCERR 0x0318
+#define EDMA_CCERRCLR 0x031c
+#define EDMA_EEVAL 0x0320
+#define EDMA_DRAE 0x0340 /* 4 x 64 bits*/
+#define EDMA_QRAE 0x0380 /* 4 registers */
+#define EDMA_QUEEVTENTRY 0x0400 /* 2 x 16 registers */
+#define EDMA_QSTAT 0x0600 /* 2 registers */
+#define EDMA_QWMTHRA 0x0620
+#define EDMA_QWMTHRB 0x0624
+#define EDMA_CCSTAT 0x0640
+
+#define EDMA_M 0x1000 /* global channel registers */
+#define EDMA_ECR 0x1008
+#define EDMA_ECRH 0x100C
+#define EDMA_SHADOW0 0x2000 /* 4 regions shadowing global channels */
+#define EDMA_PARM 0x4000 /* 128 param entries */
+
+#define DAVINCI_DMA_3PCC_BASE 0x01C00000
+
+#define PARM_OFFSET(param_no) (EDMA_PARM + ((param_no) << 5))
+
+#define EDMA_MAX_DMACH 64
+#define EDMA_MAX_PARAMENTRY 512
+#define EDMA_MAX_EVQUE 2 /* FIXME too small */
+
+
+/*****************************************************************************/
+
+static void __iomem *edmacc_regs_base;
+
+static inline unsigned int edma_read(int offset)
+{
+ return (unsigned int)__raw_readl(edmacc_regs_base + offset);
+}
+
+static inline void edma_write(int offset, int val)
+{
+ __raw_writel(val, edmacc_regs_base + offset);
+}
+static inline void edma_modify(int offset, unsigned and, unsigned or)
+{
+ unsigned val = edma_read(offset);
+ val &= and;
+ val |= or;
+ edma_write(offset, val);
+}
+static inline void edma_and(int offset, unsigned and)
+{
+ unsigned val = edma_read(offset);
+ val &= and;
+ edma_write(offset, val);
+}
+static inline void edma_or(int offset, unsigned or)
+{
+ unsigned val = edma_read(offset);
+ val |= or;
+ edma_write(offset, val);
+}
+static inline unsigned int edma_read_array(int offset, int i)
+{
+ return edma_read(offset + (i << 2));
+}
+static inline void edma_write_array(int offset, int i, unsigned val)
+{
+ edma_write(offset + (i << 2), val);
+}
+static inline void edma_modify_array(int offset, int i,
+ unsigned and, unsigned or)
+{
+ edma_modify(offset + (i << 2), and, or);
+}
+static inline void edma_or_array(int offset, int i, unsigned or)
+{
+ edma_or(offset + (i << 2), or);
+}
+static inline void edma_or_array2(int offset, int i, int j, unsigned or)
+{
+ edma_or(offset + ((i*2 + j) << 2), or);
+}
+static inline void edma_write_array2(int offset, int i, int j, unsigned val)
+{
+ edma_write(offset + ((i*2 + j) << 2), val);
+}
+static inline unsigned int edma_shadow0_read(int offset)
+{
+ return edma_read(EDMA_SHADOW0 + offset);
+}
+static inline unsigned int edma_shadow0_read_array(int offset, int i)
+{
+ return edma_read(EDMA_SHADOW0 + offset + (i << 2));
+}
+static inline void edma_shadow0_write(int offset, unsigned val)
+{
+ edma_write(EDMA_SHADOW0 + offset, val);
+}
+static inline void edma_shadow0_write_array(int offset, int i, unsigned val)
+{
+ edma_write(EDMA_SHADOW0 + offset + (i << 2), val);
+}
+static inline unsigned int edma_parm_read(int offset, int param_no)
+{
+ return edma_read(EDMA_PARM + offset + (param_no << 5));
+}
+static inline void edma_parm_write(int offset, int param_no, unsigned val)
+{
+ edma_write(EDMA_PARM + offset + (param_no << 5), val);
+}
+static inline void edma_parm_modify(int offset, int param_no,
+ unsigned and, unsigned or)
+{
+ edma_modify(EDMA_PARM + offset + (param_no << 5), and, or);
+}
+static inline void edma_parm_and(int offset, int param_no, unsigned and)
+{
+ edma_and(EDMA_PARM + offset + (param_no << 5), and);
+}
+static inline void edma_parm_or(int offset, int param_no, unsigned or)
+{
+ edma_or(EDMA_PARM + offset + (param_no << 5), or);
+}
+
+/*****************************************************************************/
+
+/* actual number of DMA channels and slots on this silicon */
+static unsigned num_channels;
+static unsigned num_slots;
+
+static struct dma_interrupt_data {
+ void (*callback)(unsigned channel, unsigned short ch_status,
+ void *data);
+ void *data;
+} intr_data[EDMA_MAX_DMACH];
+
+/* The edma_inuse bit for each PaRAM slot is clear unless the
+ * channel is in use ... by ARM or DSP, for QDMA, or whatever.
+ */
+static DECLARE_BITMAP(edma_inuse, EDMA_MAX_PARAMENTRY);
+
+/* The edma_noevent bit for each channel is clear unless
+ * it doesn't trigger DMA events on this platform. It uses a
+ * bit of SOC-specific initialization code.
+ */
+static DECLARE_BITMAP(edma_noevent, EDMA_MAX_DMACH);
+
+/* dummy param set used to (re)initialize parameter RAM slots */
+static const struct edmacc_param dummy_paramset = {
+ .link_bcntrld = 0xffff,
+ .ccnt = 1,
+};
+
+static const int __initconst
+queue_tc_mapping[EDMA_MAX_EVQUE + 1][2] = {
+/* {event queue no, TC no} */
+ {0, 0},
+ {1, 1},
+ {-1, -1}
+};
+
+static const int __initconst
+queue_priority_mapping[EDMA_MAX_EVQUE + 1][2] = {
+ /* {event queue no, Priority} */
+ {0, 3},
+ {1, 7},
+ {-1, -1}
+};
+
+/*****************************************************************************/
+
+static void map_dmach_queue(unsigned ch_no, enum dma_event_q queue_no)
+{
+ int bit = (ch_no & 0x7) * 4;
+
+ /* default to low priority queue */
+ if (queue_no == EVENTQ_DEFAULT)
+ queue_no = EVENTQ_1;
+
+ queue_no &= 7;
+ edma_modify_array(EDMA_DMAQNUM, (ch_no >> 3),
+ ~(0x7 << bit), queue_no << bit);
+}
+
+static void __init map_queue_tc(int queue_no, int tc_no)
+{
+ int bit = queue_no * 4;
+ edma_modify(EDMA_QUETCMAP, ~(0x7 << bit), ((tc_no & 0x7) << bit));
+}
+
+static void __init assign_priority_to_queue(int queue_no, int priority)
+{
+ int bit = queue_no * 4;
+ edma_modify(EDMA_QUEPRI, ~(0x7 << bit), ((priority & 0x7) << bit));
+}
+
+static inline void
+setup_dma_interrupt(unsigned lch,
+ void (*callback)(unsigned channel, u16 ch_status, void *data),
+ void *data)
+{
+ if (!callback) {
+ edma_shadow0_write_array(SH_IECR, lch >> 5,
+ (1 << (lch & 0x1f)));
+ }
+
+ intr_data[lch].callback = callback;
+ intr_data[lch].data = data;
+
+ if (callback) {
+ edma_shadow0_write_array(SH_ICR, lch >> 5,
+ (1 << (lch & 0x1f)));
+ edma_shadow0_write_array(SH_IESR, lch >> 5,
+ (1 << (lch & 0x1f)));
+ }
+}
+
+/******************************************************************************
+ *
+ * DMA interrupt handler
+ *
+ *****************************************************************************/
+static irqreturn_t dma_irq_handler(int irq, void *data)
+{
+ int i;
+ unsigned int cnt = 0;
+
+ dev_dbg(data, "dma_irq_handler\n");
+
+ if ((edma_shadow0_read_array(SH_IPR, 0) == 0)
+ && (edma_shadow0_read_array(SH_IPR, 1) == 0))
+ return IRQ_NONE;
+
+ while (1) {
+ int j;
+ if (edma_shadow0_read_array(SH_IPR, 0))
+ j = 0;
+ else if (edma_shadow0_read_array(SH_IPR, 1))
+ j = 1;
+ else
+ break;
+ dev_dbg(data, "IPR%d %08x\n", j,
+ edma_shadow0_read_array(SH_IPR, j));
+ for (i = 0; i < 32; i++) {
+ int k = (j << 5) + i;
+ if (edma_shadow0_read_array(SH_IPR, j) & (1 << i)) {
+ /* Clear the corresponding IPR bits */
+ edma_shadow0_write_array(SH_ICR, j, (1 << i));
+ if (intr_data[k].callback) {
+ intr_data[k].callback(k, DMA_COMPLETE,
+ intr_data[k].data);
+ }
+ }
+ }
+ cnt++;
+ if (cnt > 10)
+ break;
+ }
+ edma_shadow0_write(SH_IEVAL, 1);
+ return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ *
+ * DMA error interrupt handler
+ *
+ *****************************************************************************/
+static irqreturn_t dma_ccerr_handler(int irq, void *data)
+{
+ int i;
+ unsigned int cnt = 0;
+
+ dev_dbg(data, "dma_ccerr_handler\n");
+
+ if ((edma_read_array(EDMA_EMR, 0) == 0) &&
+ (edma_read_array(EDMA_EMR, 1) == 0) &&
+ (edma_read(EDMA_QEMR) == 0) && (edma_read(EDMA_CCERR) == 0))
+ return IRQ_NONE;
+
+ while (1) {
+ int j = -1;
+ if (edma_read_array(EDMA_EMR, 0))
+ j = 0;
+ else if (edma_read_array(EDMA_EMR, 1))
+ j = 1;
+ if (j >= 0) {
+ dev_dbg(data, "EMR%d %08x\n", j,
+ edma_read_array(EDMA_EMR, j));
+ for (i = 0; i < 32; i++) {
+ int k = (j << 5) + i;
+ if (edma_read_array(EDMA_EMR, j) & (1 << i)) {
+ /* Clear the corresponding EMR bits */
+ edma_write_array(EDMA_EMCR, j, 1 << i);
+ /* Clear any SER */
+ edma_shadow0_write_array(SH_SECR, j,
+ (1 << i));
+ if (intr_data[k].callback) {
+ intr_data[k].callback(k,
+ DMA_CC_ERROR,
+ intr_data
+ [k].data);
+ }
+ }
+ }
+ } else if (edma_read(EDMA_QEMR)) {
+ dev_dbg(data, "QEMR %02x\n",
+ edma_read(EDMA_QEMR));
+ for (i = 0; i < 8; i++) {
+ if (edma_read(EDMA_QEMR) & (1 << i)) {
+ /* Clear the corresponding IPR bits */
+ edma_write(EDMA_QEMCR, 1 << i);
+ edma_shadow0_write(SH_QSECR, (1 << i));
+
+ /* NOTE: not reported!! */
+ }
+ }
+ } else if (edma_read(EDMA_CCERR)) {
+ dev_dbg(data, "CCERR %08x\n",
+ edma_read(EDMA_CCERR));
+ /* FIXME: CCERR.BIT(16) ignored! much better
+ * to just write CCERRCLR with CCERR value...
+ */
+ for (i = 0; i < 8; i++) {
+ if (edma_read(EDMA_CCERR) & (1 << i)) {
+ /* Clear the corresponding IPR bits */
+ edma_write(EDMA_CCERRCLR, 1 << i);
+
+ /* NOTE: not reported!! */
+ }
+ }
+ }
+ if ((edma_read_array(EDMA_EMR, 0) == 0)
+ && (edma_read_array(EDMA_EMR, 1) == 0)
+ && (edma_read(EDMA_QEMR) == 0)
+ && (edma_read(EDMA_CCERR) == 0)) {
+ break;
+ }
+ cnt++;
+ if (cnt > 10)
+ break;
+ }
+ edma_write(EDMA_EEVAL, 1);
+ return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ *
+ * Transfer controller error interrupt handlers
+ *
+ *****************************************************************************/
+
+#define tc_errs_handled false /* disabled as long as they're NOPs */
+
+static irqreturn_t dma_tc0err_handler(int irq, void *data)
+{
+ dev_dbg(data, "dma_tc0err_handler\n");
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t dma_tc1err_handler(int irq, void *data)
+{
+ dev_dbg(data, "dma_tc1err_handler\n");
+ return IRQ_HANDLED;
+}
+
+/*-----------------------------------------------------------------------*/
+
+/* Resource alloc/free: dma channels, parameter RAM slots */
+
+/**
+ * edma_alloc_channel - allocate DMA channel and paired parameter RAM
+ * @channel: specific channel to allocate; negative for "any unmapped channel"
+ * @callback: optional; to be issued on DMA completion or errors
+ * @data: passed to callback
+ * @eventq_no: an EVENTQ_* constant, used to choose which Transfer
+ * Controller (TC) executes requests using this channel. Use
+ * EVENTQ_DEFAULT unless you really need a high priority queue.
+ *
+ * This allocates a DMA channel and its associated parameter RAM slot.
+ * The parameter RAM is initialized to hold a dummy transfer.
+ *
+ * Normal use is to pass a specific channel number as @channel, to make
+ * use of hardware events mapped to that channel. When the channel will
+ * be used only for software triggering or event chaining, channels not
+ * mapped to hardware events (or mapped to unused events) are preferable.
+ *
+ * DMA transfers start from a channel using edma_start(), or by
+ * chaining. When the transfer described in that channel's parameter RAM
+ * slot completes, that slot's data may be reloaded through a link.
+ *
+ * DMA errors are only reported to the @callback associated with the
+ * channel driving that transfer, but transfer completion callbacks can
+ * be sent to another channel under control of the TCC field in
+ * the option word of the transfer's parameter RAM set. Drivers must not
+ * use DMA transfer completion callbacks for channels they did not allocate.
+ * (The same applies to TCC codes used in transfer chaining.)
+ *
+ * Returns the number of the channel, else negative errno.
+ */
+int edma_alloc_channel(int channel,
+ void (*callback)(unsigned channel, u16 ch_status, void *data),
+ void *data,
+ enum dma_event_q eventq_no)
+{
+ if (channel < 0) {
+ channel = 0;
+ for (;;) {
+ channel = find_next_bit(edma_noevent,
+ num_channels, channel);
+ if (channel == num_channels)
+ return -ENOMEM;
+ if (!test_and_set_bit(channel, edma_inuse))
+ break;
+ channel++;
+ }
+ } else if (channel >= num_channels) {
+ return -EINVAL;
+ } else if (test_and_set_bit(channel, edma_inuse)) {
+ return -EBUSY;
+ }
+
+ /* ensure access through shadow region 0 */
+ edma_or_array2(EDMA_DRAE, 0, channel >> 5, 1 << (channel & 0x1f));
+
+ /* ensure no events are pending */
+ edma_stop(channel);
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(channel),
+ &dummy_paramset, PARM_SIZE);
+
+ if (callback)
+ setup_dma_interrupt(channel, callback, data);
+
+ map_dmach_queue(channel, eventq_no);
+
+ return channel;
+}
+EXPORT_SYMBOL(edma_alloc_channel);
+
+
+/**
+ * edma_free_channel - deallocate DMA channel
+ * @channel: dma channel returned from edma_alloc_channel()
+ *
+ * This deallocates the DMA channel and associated parameter RAM slot
+ * allocated by edma_alloc_channel().
+ *
+ * Callers are responsible for ensuring the channel is inactive, and
+ * will not be reactivated by linking, chaining, or software calls to
+ * edma_start().
+ */
+void edma_free_channel(unsigned channel)
+{
+ if (channel >= num_channels)
+ return;
+
+ setup_dma_interrupt(channel, NULL, NULL);
+ /* REVISIT should probably take out of shadow region 0 */
+
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(channel),
+ &dummy_paramset, PARM_SIZE);
+ clear_bit(channel, edma_inuse);
+}
+EXPORT_SYMBOL(edma_free_channel);
+
+/**
+ * edma_alloc_slot - allocate DMA parameter RAM
+ * @slot: specific slot to allocate; negative for "any unused slot"
+ *
+ * This allocates a parameter RAM slot, initializing it to hold a
+ * dummy transfer. Slots allocated using this routine have not been
+ * mapped to a hardware DMA channel, and will normally be used by
+ * linking to them from a slot associated with a DMA channel.
+ *
+ * Normal use is to pass EDMA_SLOT_ANY as the @slot, but specific
+ * slots may be allocated on behalf of DSP firmware.
+ *
+ * Returns the number of the slot, else negative errno.
+ */
+int edma_alloc_slot(int slot)
+{
+ if (slot < 0) {
+ slot = num_channels;
+ for (;;) {
+ slot = find_next_zero_bit(edma_inuse,
+ num_slots, slot);
+ if (slot == num_slots)
+ return -ENOMEM;
+ if (!test_and_set_bit(slot, edma_inuse))
+ break;
+ }
+ } else if (slot < num_channels || slot >= num_slots) {
+ return -EINVAL;
+ } else if (test_and_set_bit(slot, edma_inuse)) {
+ return -EBUSY;
+ }
+
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot),
+ &dummy_paramset, PARM_SIZE);
+
+ return slot;
+}
+EXPORT_SYMBOL(edma_alloc_slot);
+
+/**
+ * edma_free_slot - deallocate DMA parameter RAM
+ * @slot: parameter RAM slot returned from edma_alloc_slot()
+ *
+ * This deallocates the parameter RAM slot allocated by edma_alloc_slot().
+ * Callers are responsible for ensuring the slot is inactive, and will
+ * not be activated.
+ */
+void edma_free_slot(unsigned slot)
+{
+ if (slot < num_channels || slot >= num_slots)
+ return;
+
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot),
+ &dummy_paramset, PARM_SIZE);
+ clear_bit(slot, edma_inuse);
+}
+EXPORT_SYMBOL(edma_free_slot);
+
+/*-----------------------------------------------------------------------*/
+
+/* Parameter RAM operations (i) -- read/write partial slots */
+
+/**
+ * edma_set_src - set initial DMA source address in parameter RAM slot
+ * @slot: parameter RAM slot being configured
+ * @src_port: physical address of source (memory, controller FIFO, etc)
+ * @addressMode: INCR, except in very rare cases
+ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+ *
+ * Note that the source address is modified during the DMA transfer
+ * according to edma_set_src_index().
+ */
+void edma_set_src(unsigned slot, dma_addr_t src_port,
+ enum address_mode mode, enum fifo_width width)
+{
+ if (slot < num_slots) {
+ unsigned int i = edma_parm_read(PARM_OPT, slot);
+
+ if (mode) {
+ /* set SAM and program FWID */
+ i = (i & ~(EDMA_FWID)) | (SAM | ((width & 0x7) << 8));
+ } else {
+ /* clear SAM */
+ i &= ~SAM;
+ }
+ edma_parm_write(PARM_OPT, slot, i);
+
+ /* set the source port address
+ in source register of param structure */
+ edma_parm_write(PARM_SRC, slot, src_port);
+ }
+}
+EXPORT_SYMBOL(edma_set_src);
+
+/**
+ * edma_set_dest - set initial DMA destination address in parameter RAM slot
+ * @slot: parameter RAM slot being configured
+ * @dest_port: physical address of destination (memory, controller FIFO, etc)
+ * @addressMode: INCR, except in very rare cases
+ * @fifoWidth: ignored unless @addressMode is FIFO, else specifies the
+ * width to use when addressing the fifo (e.g. W8BIT, W32BIT)
+ *
+ * Note that the destination address is modified during the DMA transfer
+ * according to edma_set_dest_index().
+ */
+void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+ enum address_mode mode, enum fifo_width width)
+{
+ if (slot < num_slots) {
+ unsigned int i = edma_parm_read(PARM_OPT, slot);
+
+ if (mode) {
+ /* set DAM and program FWID */
+ i = (i & ~(EDMA_FWID)) | (DAM | ((width & 0x7) << 8));
+ } else {
+ /* clear DAM */
+ i &= ~DAM;
+ }
+ edma_parm_write(PARM_OPT, slot, i);
+ /* set the destination port address
+ in dest register of param structure */
+ edma_parm_write(PARM_DST, slot, dest_port);
+ }
+}
+EXPORT_SYMBOL(edma_set_dest);
+
+/**
+ * edma_get_position - returns the current transfer points
+ * @slot: parameter RAM slot being examined
+ * @src: pointer to source port position
+ * @dst: pointer to destination port position
+ *
+ * Returns current source and destination addresses for a particular
+ * parameter RAM slot. Its channel should not be active when this is called.
+ */
+void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst)
+{
+ struct edmacc_param temp;
+
+ edma_read_slot(slot, &temp);
+ if (src != NULL)
+ *src = temp.src;
+ if (dst != NULL)
+ *dst = temp.dst;
+}
+EXPORT_SYMBOL(edma_get_position);
+
+/**
+ * edma_set_src_index - configure DMA source address indexing
+ * @slot: parameter RAM slot being configured
+ * @src_bidx: byte offset between source arrays in a frame
+ * @src_cidx: byte offset between source frames in a block
+ *
+ * Offsets are specified to support either contiguous or discontiguous
+ * memory transfers, or repeated access to a hardware register, as needed.
+ * When accessing hardware registers, both offsets are normally zero.
+ */
+void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx)
+{
+ if (slot < num_slots) {
+ edma_parm_modify(PARM_SRC_DST_BIDX, slot,
+ 0xffff0000, src_bidx);
+ edma_parm_modify(PARM_SRC_DST_CIDX, slot,
+ 0xffff0000, src_cidx);
+ }
+}
+EXPORT_SYMBOL(edma_set_src_index);
+
+/**
+ * edma_set_dest_index - configure DMA destination address indexing
+ * @slot: parameter RAM slot being configured
+ * @dest_bidx: byte offset between destination arrays in a frame
+ * @dest_cidx: byte offset between destination frames in a block
+ *
+ * Offsets are specified to support either contiguous or discontiguous
+ * memory transfers, or repeated access to a hardware register, as needed.
+ * When accessing hardware registers, both offsets are normally zero.
+ */
+void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx)
+{
+ if (slot < num_slots) {
+ edma_parm_modify(PARM_SRC_DST_BIDX, slot,
+ 0x0000ffff, dest_bidx << 16);
+ edma_parm_modify(PARM_SRC_DST_CIDX, slot,
+ 0x0000ffff, dest_cidx << 16);
+ }
+}
+EXPORT_SYMBOL(edma_set_dest_index);
+
+/**
+ * edma_set_transfer_params - configure DMA transfer parameters
+ * @slot: parameter RAM slot being configured
+ * @acnt: how many bytes per array (at least one)
+ * @bcnt: how many arrays per frame (at least one)
+ * @ccnt: how many frames per block (at least one)
+ * @bcnt_rld: used only for A-Synchronized transfers; this specifies
+ * the value to reload into bcnt when it decrements to zero
+ * @sync_mode: ASYNC or ABSYNC
+ *
+ * See the EDMA3 documentation to understand how to configure and link
+ * transfers using the fields in PaRAM slots. If you are not doing it
+ * all at once with edma_write_slot(), you will use this routine
+ * plus two calls each for source and destination, setting the initial
+ * address and saying how to index that address.
+ *
+ * An example of an A-Synchronized transfer is a serial link using a
+ * single word shift register. In that case, @acnt would be equal to
+ * that word size; the serial controller issues a DMA synchronization
+ * event to transfer each word, and memory access by the DMA transfer
+ * controller will be word-at-a-time.
+ *
+ * An example of an AB-Synchronized transfer is a device using a FIFO.
+ * In that case, @acnt equals the FIFO width and @bcnt equals its depth.
+ * The controller with the FIFO issues DMA synchronization events when
+ * the FIFO threshold is reached, and the DMA transfer controller will
+ * transfer one frame to (or from) the FIFO. It will probably use
+ * efficient burst modes to access memory.
+ */
+void edma_set_transfer_params(unsigned slot,
+ u16 acnt, u16 bcnt, u16 ccnt,
+ u16 bcnt_rld, enum sync_dimension sync_mode)
+{
+ if (slot < num_slots) {
+ edma_parm_modify(PARM_LINK_BCNTRLD, slot,
+ 0x0000ffff, bcnt_rld << 16);
+ if (sync_mode == ASYNC)
+ edma_parm_and(PARM_OPT, slot, ~SYNCDIM);
+ else
+ edma_parm_or(PARM_OPT, slot, SYNCDIM);
+ /* Set the acount, bcount, ccount registers */
+ edma_parm_write(PARM_A_B_CNT, slot, (bcnt << 16) | acnt);
+ edma_parm_write(PARM_CCNT, slot, ccnt);
+ }
+}
+EXPORT_SYMBOL(edma_set_transfer_params);
+
+/**
+ * edma_link - link one parameter RAM slot to another
+ * @from: parameter RAM slot originating the link
+ * @to: parameter RAM slot which is the link target
+ *
+ * The originating slot should not be part of any active DMA transfer.
+ */
+void edma_link(unsigned from, unsigned to)
+{
+ if (from >= num_slots)
+ return;
+ if (to >= num_slots)
+ return;
+ edma_parm_modify(PARM_LINK_BCNTRLD, from, 0xffff0000, PARM_OFFSET(to));
+}
+EXPORT_SYMBOL(edma_link);
+
+/**
+ * edma_unlink - cut link from one parameter RAM slot
+ * @from: parameter RAM slot originating the link
+ *
+ * The originating slot should not be part of any active DMA transfer.
+ * Its link is set to 0xffff.
+ */
+void edma_unlink(unsigned from)
+{
+ if (from >= num_slots)
+ return;
+ edma_parm_or(PARM_LINK_BCNTRLD, from, 0xffff);
+}
+EXPORT_SYMBOL(edma_unlink);
+
+/*-----------------------------------------------------------------------*/
+
+/* Parameter RAM operations (ii) -- read/write whole parameter sets */
+
+/**
+ * edma_write_slot - write parameter RAM data for slot
+ * @slot: number of parameter RAM slot being modified
+ * @param: data to be written into parameter RAM slot
+ *
+ * Use this to assign all parameters of a transfer at once. This
+ * allows more efficient setup of transfers than issuing multiple
+ * calls to set up those parameters in small pieces, and provides
+ * complete control over all transfer options.
+ */
+void edma_write_slot(unsigned slot, const struct edmacc_param *param)
+{
+ if (slot >= num_slots)
+ return;
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(slot), param, PARM_SIZE);
+}
+EXPORT_SYMBOL(edma_write_slot);
+
+/**
+ * edma_read_slot - read parameter RAM data from slot
+ * @slot: number of parameter RAM slot being copied
+ * @param: where to store copy of parameter RAM data
+ *
+ * Use this to read data from a parameter RAM slot, perhaps to
+ * save them as a template for later reuse.
+ */
+void edma_read_slot(unsigned slot, struct edmacc_param *param)
+{
+ if (slot >= num_slots)
+ return;
+ memcpy_fromio(param, edmacc_regs_base + PARM_OFFSET(slot), PARM_SIZE);
+}
+EXPORT_SYMBOL(edma_read_slot);
+
+/*-----------------------------------------------------------------------*/
+
+/* Various EDMA channel control operations */
+
+/**
+ * edma_pause - pause dma on a channel
+ * @channel: on which edma_start() has been called
+ *
+ * This temporarily disables EDMA hardware events on the specified channel,
+ * preventing them from triggering new transfers on its behalf
+ */
+void edma_pause(unsigned channel)
+{
+ if (channel < num_channels) {
+ unsigned int mask = (1 << (channel & 0x1f));
+
+ edma_shadow0_write_array(SH_EECR, channel >> 5, mask);
+ }
+}
+EXPORT_SYMBOL(edma_pause);
+
+/**
+ * edma_resume - resumes dma on a paused channel
+ * @channel: on which edma_pause() has been called
+ *
+ * This re-enables EDMA hardware events on the specified channel.
+ */
+void edma_resume(unsigned channel)
+{
+ if (channel < num_channels) {
+ unsigned int mask = (1 << (channel & 0x1f));
+
+ edma_shadow0_write_array(SH_EESR, channel >> 5, mask);
+ }
+}
+EXPORT_SYMBOL(edma_resume);
+
+/**
+ * edma_start - start dma on a channel
+ * @channel: channel being activated
+ *
+ * Channels with event associations will be triggered by their hardware
+ * events, and channels without such associations will be triggered by
+ * software. (At this writing there is no interface for using software
+ * triggers except with channels that don't support hardware triggers.)
+ *
+ * Returns zero on success, else negative errno.
+ */
+int edma_start(unsigned channel)
+{
+ if (channel < num_channels) {
+ int j = channel >> 5;
+ unsigned int mask = (1 << (channel & 0x1f));
+
+ /* EDMA channels without event association */
+ if (test_bit(channel, edma_noevent)) {
+ pr_debug("EDMA: ESR%d %08x\n", j,
+ edma_shadow0_read_array(SH_ESR, j));
+ edma_shadow0_write_array(SH_ESR, j, mask);
+ return 0;
+ }
+
+ /* EDMA channel with event association */
+ pr_debug("EDMA: ER%d %08x\n", j,
+ edma_shadow0_read_array(SH_ER, j));
+ /* Clear any pending error */
+ edma_write_array(EDMA_EMCR, j, mask);
+ /* Clear any SER */
+ edma_shadow0_write_array(SH_SECR, j, mask);
+ edma_shadow0_write_array(SH_EESR, j, mask);
+ pr_debug("EDMA: EER%d %08x\n", j,
+ edma_shadow0_read_array(SH_EER, j));
+ return 0;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL(edma_start);
+
+/**
+ * edma_stop - stops dma on the channel passed
+ * @channel: channel being deactivated
+ *
+ * When @lch is a channel, any active transfer is paused and
+ * all pending hardware events are cleared. The current transfer
+ * may not be resumed, and the channel's Parameter RAM should be
+ * reinitialized before being reused.
+ */
+void edma_stop(unsigned channel)
+{
+ if (channel < num_channels) {
+ int j = channel >> 5;
+ unsigned int mask = (1 << (channel & 0x1f));
+
+ edma_shadow0_write_array(SH_EECR, j, mask);
+ edma_shadow0_write_array(SH_ECR, j, mask);
+ edma_shadow0_write_array(SH_SECR, j, mask);
+ edma_write_array(EDMA_EMCR, j, mask);
+
+ pr_debug("EDMA: EER%d %08x\n", j,
+ edma_shadow0_read_array(SH_EER, j));
+
+ /* REVISIT: consider guarding against inappropriate event
+ * chaining by overwriting with dummy_paramset.
+ */
+ }
+}
+EXPORT_SYMBOL(edma_stop);
+
+/******************************************************************************
+ *
+ * It cleans ParamEntry qand bring back EDMA to initial state if media has
+ * been removed before EDMA has finished.It is usedful for removable media.
+ * Arguments:
+ * ch_no - channel no
+ *
+ * Return: zero on success, or corresponding error no on failure
+ *
+ * FIXME this should not be needed ... edma_stop() should suffice.
+ *
+ *****************************************************************************/
+
+void edma_clean_channel(unsigned channel)
+{
+ if (channel < num_channels) {
+ int j = (channel >> 5);
+ unsigned int mask = 1 << (channel & 0x1f);
+
+ pr_debug("EDMA: EMR%d %08x\n", j,
+ edma_read_array(EDMA_EMR, j));
+ edma_shadow0_write_array(SH_ECR, j, mask);
+ /* Clear the corresponding EMR bits */
+ edma_write_array(EDMA_EMCR, j, mask);
+ /* Clear any SER */
+ edma_shadow0_write_array(SH_SECR, j, mask);
+ edma_write(EDMA_CCERRCLR, (1 << 16) | 0x3);
+ }
+}
+EXPORT_SYMBOL(edma_clean_channel);
+
+/*
+ * edma_clear_event - clear an outstanding event on the DMA channel
+ * Arguments:
+ * channel - channel number
+ */
+void edma_clear_event(unsigned channel)
+{
+ if (channel >= num_channels)
+ return;
+ if (channel < 32)
+ edma_write(EDMA_ECR, 1 << channel);
+ else
+ edma_write(EDMA_ECRH, 1 << (channel - 32));
+}
+EXPORT_SYMBOL(edma_clear_event);
+
+/*-----------------------------------------------------------------------*/
+
+static int __init edma_probe(struct platform_device *pdev)
+{
+ struct edma_soc_info *info = pdev->dev.platform_data;
+ int i;
+ int status;
+ const s8 *noevent;
+ int irq = 0, err_irq = 0;
+ struct resource *r;
+ resource_size_t len;
+
+ if (!info)
+ return -ENODEV;
+
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "edma_cc");
+ if (!r)
+ return -ENODEV;
+
+ len = r->end - r->start + 1;
+
+ r = request_mem_region(r->start, len, r->name);
+ if (!r)
+ return -EBUSY;
+
+ edmacc_regs_base = ioremap(r->start, len);
+ if (!edmacc_regs_base) {
+ status = -EBUSY;
+ goto fail1;
+ }
+
+ num_channels = min_t(unsigned, info->n_channel, EDMA_MAX_DMACH);
+ num_slots = min_t(unsigned, info->n_slot, EDMA_MAX_PARAMENTRY);
+
+ dev_dbg(&pdev->dev, "DMA REG BASE ADDR=%p\n", edmacc_regs_base);
+
+ for (i = 0; i < num_slots; i++)
+ memcpy_toio(edmacc_regs_base + PARM_OFFSET(i),
+ &dummy_paramset, PARM_SIZE);
+
+ noevent = info->noevent;
+ if (noevent) {
+ while (*noevent != -1)
+ set_bit(*noevent++, edma_noevent);
+ }
+
+ irq = platform_get_irq(pdev, 0);
+ status = request_irq(irq, dma_irq_handler, 0, "edma", &pdev->dev);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+ irq, status);
+ goto fail;
+ }
+
+ err_irq = platform_get_irq(pdev, 1);
+ status = request_irq(err_irq, dma_ccerr_handler, 0,
+ "edma_error", &pdev->dev);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+ err_irq, status);
+ goto fail;
+ }
+
+ if (tc_errs_handled) {
+ status = request_irq(IRQ_TCERRINT0, dma_tc0err_handler, 0,
+ "edma_tc0", &pdev->dev);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "request_irq %d failed --> %d\n",
+ IRQ_TCERRINT0, status);
+ return status;
+ }
+ status = request_irq(IRQ_TCERRINT, dma_tc1err_handler, 0,
+ "edma_tc1", &pdev->dev);
+ if (status < 0) {
+ dev_dbg(&pdev->dev, "request_irq %d --> %d\n",
+ IRQ_TCERRINT, status);
+ return status;
+ }
+ }
+
+ /* Everything lives on transfer controller 1 until otherwise specified.
+ * This way, long transfers on the low priority queue
+ * started by the codec engine will not cause audio defects.
+ */
+ for (i = 0; i < num_channels; i++)
+ map_dmach_queue(i, EVENTQ_1);
+
+ /* Event queue to TC mapping */
+ for (i = 0; queue_tc_mapping[i][0] != -1; i++)
+ map_queue_tc(queue_tc_mapping[i][0], queue_tc_mapping[i][1]);
+
+ /* Event queue priority mapping */
+ for (i = 0; queue_priority_mapping[i][0] != -1; i++)
+ assign_priority_to_queue(queue_priority_mapping[i][0],
+ queue_priority_mapping[i][1]);
+
+ for (i = 0; i < info->n_region; i++) {
+ edma_write_array2(EDMA_DRAE, i, 0, 0x0);
+ edma_write_array2(EDMA_DRAE, i, 1, 0x0);
+ edma_write_array(EDMA_QRAE, i, 0x0);
+ }
+
+ return 0;
+
+fail:
+ if (err_irq)
+ free_irq(err_irq, NULL);
+ if (irq)
+ free_irq(irq, NULL);
+ iounmap(edmacc_regs_base);
+fail1:
+ release_mem_region(r->start, len);
+ return status;
+}
+
+
+static struct platform_driver edma_driver = {
+ .driver.name = "edma",
+};
+
+static int __init edma_init(void)
+{
+ return platform_driver_probe(&edma_driver, edma_probe);
+}
+arch_initcall(edma_init);
+
#include <linux/irq.h>
#include <linux/bitops.h>
+#include <mach/cputype.h>
#include <mach/irqs.h>
#include <mach/hardware.h>
#include <mach/gpio.h>
static struct davinci_gpio chips[DIV_ROUND_UP(DAVINCI_N_GPIO, 32)];
+static unsigned __initdata ngpio;
/* create a non-inlined version */
-static struct gpio_controller *__iomem __init gpio2controller(unsigned gpio)
+static struct gpio_controller __iomem * __init gpio2controller(unsigned gpio)
{
return __gpio_to_controller(gpio);
}
{
int i, base;
- for (i = 0, base = 0;
- i < ARRAY_SIZE(chips);
- i++, base += 32) {
+ /* The gpio banks conceptually expose a segmented bitmap,
+ * and "ngpio" is one more than the largest zero-based
+ * bit index that's valid.
+ */
+ if (cpu_is_davinci_dm355()) { /* or dm335() */
+ ngpio = 104;
+ } else if (cpu_is_davinci_dm644x()) { /* or dm337() */
+ ngpio = 71;
+ } else if (cpu_is_davinci_dm646x()) {
+ /* NOTE: each bank has several "reserved" bits,
+ * unusable as GPIOs. Only 33 of the GPIO numbers
+ * are usable, and we're not rejecting the others.
+ */
+ ngpio = 43;
+ } else {
+ /* if cpu_is_davinci_dm643x() ngpio = 111 */
+ pr_err("GPIO setup: how many GPIOs?\n");
+ return -EINVAL;
+ }
+
+ if (WARN_ON(DAVINCI_N_GPIO < ngpio))
+ ngpio = DAVINCI_N_GPIO;
+
+ for (i = 0, base = 0; base < ngpio; i++, base += 32) {
chips[i].chip.label = "DaVinci";
chips[i].chip.direction_input = davinci_direction_in;
chips[i].chip.set = davinci_gpio_set;
chips[i].chip.base = base;
- chips[i].chip.ngpio = DAVINCI_N_GPIO - base;
+ chips[i].chip.ngpio = ngpio - base;
if (chips[i].chip.ngpio > 32)
chips[i].chip.ngpio = 32;
* We expect irqs will normally be set up as input pins, but they can also be
* used as output pins ... which is convenient for testing.
*
- * NOTE: GPIO0..GPIO7 also have direct INTC hookups, which work in addition
- * to their GPIOBNK0 irq (but with a bit less overhead). But we don't have
- * a good way to hook those up ...
+ * NOTE: The first few GPIOs also have direct INTC hookups in addition
+ * to their GPIOBNK0 irq, with a bit less overhead but less flexibility
+ * on triggering (e.g. no edge options). We don't try to use those.
*
- * All those INTC hookups (GPIO0..GPIO7 plus five IRQ banks) can also
+ * All those INTC hookups (direct, plus several IRQ banks) can also
* serve as EDMA event triggers.
*/
}
/*
- * NOTE: for suspend/resume, probably best to make a sysdev (and class)
- * with its suspend/resume calls hooking into the results of the set_wake()
+ * NOTE: for suspend/resume, probably best to make a platform_device with
+ * suspend_late/resume_resume calls hooking into results of the set_wake()
* calls ... so if no gpios are wakeup events the clock can be disabled,
* with outputs left at previously set levels, and so that VDD3P3V.IOPWDN0
- * can be set appropriately for GPIOV33 pins.
+ * (dm6446) can be set appropriately for GPIOV33 pins.
*/
static int __init davinci_gpio_irq_setup(void)
{
unsigned gpio, irq, bank;
+ unsigned bank_irq;
struct clk *clk;
+ u32 binten = 0;
+
+ if (cpu_is_davinci_dm355()) { /* or dm335() */
+ bank_irq = IRQ_DM355_GPIOBNK0;
+ } else if (cpu_is_davinci_dm644x()) {
+ bank_irq = IRQ_GPIOBNK0;
+ } else if (cpu_is_davinci_dm646x()) {
+ bank_irq = IRQ_DM646X_GPIOBNK0;
+ } else {
+ printk(KERN_ERR "Don't know first GPIO bank IRQ.\n");
+ return -EINVAL;
+ }
clk = clk_get(NULL, "gpio");
if (IS_ERR(clk)) {
printk(KERN_ERR "Error %ld getting gpio clock?\n",
PTR_ERR(clk));
- return 0;
+ return PTR_ERR(clk);
}
-
clk_enable(clk);
- for (gpio = 0, irq = gpio_to_irq(0), bank = IRQ_GPIOBNK0;
- gpio < DAVINCI_N_GPIO; bank++) {
+ for (gpio = 0, irq = gpio_to_irq(0), bank = 0;
+ gpio < ngpio;
+ bank++, bank_irq++) {
struct gpio_controller *__iomem g = gpio2controller(gpio);
unsigned i;
__raw_writel(~0, &g->clr_rising);
/* set up all irqs in this bank */
- set_irq_chained_handler(bank, gpio_irq_handler);
- set_irq_chip_data(bank, g);
- set_irq_data(bank, (void *)irq);
+ set_irq_chained_handler(bank_irq, gpio_irq_handler);
+ set_irq_chip_data(bank_irq, g);
+ set_irq_data(bank_irq, (void *)irq);
- for (i = 0; i < 16 && gpio < DAVINCI_N_GPIO;
- i++, irq++, gpio++) {
+ for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
set_irq_chip(irq, &gpio_irqchip);
set_irq_chip_data(irq, g);
set_irq_handler(irq, handle_simple_irq);
set_irq_flags(irq, IRQF_VALID);
}
+
+ binten |= BIT(bank);
}
/* BINTEN -- per-bank interrupt enable. genirq would also let these
* bits be set/cleared dynamically.
*/
- __raw_writel(0x1f, (void *__iomem)
+ __raw_writel(binten, (void *__iomem)
IO_ADDRESS(DAVINCI_GPIO_BASE + 0x08));
printk(KERN_INFO "DaVinci: %d gpio irqs\n", irq - gpio_to_irq(0));
return 0;
}
-
arch_initcall(davinci_gpio_irq_setup);
#include <linux/init.h>
#include <linux/io.h>
-#define JTAG_ID_BASE 0x01c40028
+#define JTAG_ID_BASE IO_ADDRESS(0x01c40028)
+
+static unsigned int davinci_revision;
struct davinci_id {
u8 variant; /* JTAG ID bits 31:28 */
.manufacturer = 0x017,
.type = 0x64460000,
},
+ {
+ /* DM646X */
+ .part_no = 0xb770,
+ .variant = 0x0,
+ .manufacturer = 0x017,
+ .type = 0x64670000,
+ },
+ {
+ /* DM355 */
+ .part_no = 0xb73b,
+ .variant = 0x0,
+ .manufacturer = 0x00f,
+ .type = 0x03550000,
+ },
};
/*
{
u32 dev_id, part_no;
- dev_id = davinci_readl(JTAG_ID_BASE);
+ dev_id = __raw_readl(JTAG_ID_BASE);
part_no = ((dev_id >> 12) & 0xffff);
{
u32 variant;
- variant = davinci_readl(JTAG_ID_BASE);
+ variant = __raw_readl(JTAG_ID_BASE);
variant = (variant >> 28) & 0xf;
return variant;
}
+unsigned int davinci_rev(void)
+{
+ return davinci_revision >> 16;
+}
+EXPORT_SYMBOL(davinci_rev);
+
void __init davinci_check_revision(void)
{
int i;
/* First check only the major version in a safe way */
for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
if (part_no == (davinci_ids[i].part_no)) {
- system_rev = davinci_ids[i].type;
+ davinci_revision = davinci_ids[i].type;
break;
}
}
for (i = 0; i < ARRAY_SIZE(davinci_ids); i++) {
if (part_no == davinci_ids[i].part_no &&
variant == davinci_ids[i].variant) {
- system_rev = davinci_ids[i].type;
+ davinci_revision = davinci_ids[i].type;
break;
}
}
- printk("DaVinci DM%04x variant 0x%x\n", system_rev >> 16, variant);
+ printk(KERN_INFO "DaVinci DM%04x variant 0x%x\n",
+ davinci_rev(), variant);
}
--- /dev/null
+/*
+ * DaVinci DM6446 EVM board specific headers
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * 2007 (c) Deep Root Systems, LLC. 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 ifndef.
+ */
+
+#ifndef _MACH_DAVINCI_DM6446EVM_H
+#define _MACH_DAVINCI_DM6446EVM_H
+
+#include <linux/types.h>
+
+int dm6446evm_eeprom_read(char *buf, off_t off, size_t count);
+int dm6446evm_eeprom_write(char *buf, off_t off, size_t count);
+
+#endif
--- /dev/null
+#ifndef __MACH_CLKDEV_H
+#define __MACH_CLKDEV_H
+
+static inline int __clk_get(struct clk *clk)
+{
+ return 1;
+}
+
+static inline void __clk_put(struct clk *clk)
+{
+}
+
+#endif
extern int clk_register(struct clk *clk);
extern void clk_unregister(struct clk *clk);
-extern int davinci_clk_init(void);
#endif
extern struct sys_timer davinci_timer;
+extern void davinci_irq_init(void);
+extern void davinci_map_common_io(void);
+
+/* parameters describe VBUS sourcing for host mode */
+extern void setup_usb(unsigned mA, unsigned potpgt_msec);
+
/* parameters describe VBUS sourcing for host mode */
extern void setup_usb(unsigned mA, unsigned potpgt_msec);
--- /dev/null
+/*
+ * DaVinci CPU type detection
+ *
+ * Author: Kevin Hilman, Deep Root Systems, LLC
+ *
+ * Defines the cpu_is_*() macros for runtime detection of DaVinci
+ * device type. In addtion, if support for a given device is not
+ * compiled in to the kernel, the macros return 0 so that
+ * resulting code can be optimized out.
+ *
+ * 2009 (c) Deep Root Systems, LLC. 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.
+ */
+#ifndef _ASM_ARCH_CPU_H
+#define _ASM_ARCH_CPU_H
+
+extern unsigned int davinci_rev(void);
+
+#define IS_DAVINCI_CPU(type, id) \
+static inline int is_davinci_dm ##type(void) \
+{ \
+ return (davinci_rev() == (id)) ? 1 : 0; \
+}
+
+IS_DAVINCI_CPU(644x, 0x6446)
+IS_DAVINCI_CPU(646x, 0x6467)
+IS_DAVINCI_CPU(355, 0x355)
+
+#ifdef CONFIG_ARCH_DAVINCI_DM644x
+#define cpu_is_davinci_dm644x() is_davinci_dm644x()
+#else
+#define cpu_is_davinci_dm644x() 0
+#endif
+
+#ifdef CONFIG_ARCH_DAVINCI_DM646x
+#define cpu_is_davinci_dm646x() is_davinci_dm646x()
+#else
+#define cpu_is_davinci_dm646x() 0
+#endif
+
+#ifdef CONFIG_ARCH_DAVINCI_DM355
+#define cpu_is_davinci_dm355() is_davinci_dm355()
+#else
+#define cpu_is_davinci_dm355() 0
+#endif
+
+#endif
--- /dev/null
+/*
+ * This file contains the processor specific definitions
+ * of the TI DM644x.
+ *
+ * Copyright (C) 2008 Texas Instruments.
+ *
+ * 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
+ *
+ */
+#ifndef __ASM_ARCH_DM644X_H
+#define __ASM_ARCH_DM644X_H
+
+#include <linux/platform_device.h>
+#include <mach/hardware.h>
+
+#define DM644X_EMAC_BASE (0x01C80000)
+#define DM644X_EMAC_CNTRL_OFFSET (0x0000)
+#define DM644X_EMAC_CNTRL_MOD_OFFSET (0x1000)
+#define DM644X_EMAC_CNTRL_RAM_OFFSET (0x2000)
+#define DM644X_EMAC_MDIO_OFFSET (0x4000)
+#define DM644X_EMAC_CNTRL_RAM_SIZE (0x2000)
+
+void __init dm644x_init(void);
+
+#endif /* __ASM_ARCH_DM644X_H */
--- /dev/null
+/*
+ * TI DAVINCI dma definitions
+ *
+ * Copyright (C) 2006-2009 Texas Instruments.
+ *
+ * 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 SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
+ * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 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.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+/*
+ * This EDMA3 programming framework exposes two basic kinds of resource:
+ *
+ * Channel Triggers transfers, usually from a hardware event but
+ * also manually or by "chaining" from DMA completions.
+ * Each channel is coupled to a Parameter RAM (PaRAM) slot.
+ *
+ * Slot Each PaRAM slot holds a DMA transfer descriptor (PaRAM
+ * "set"), source and destination addresses, a link to a
+ * next PaRAM slot (if any), options for the transfer, and
+ * instructions for updating those addresses. There are
+ * more than twice as many slots as event channels.
+ *
+ * Each PaRAM set describes a sequence of transfers, either for one large
+ * buffer or for several discontiguous smaller buffers. An EDMA transfer
+ * is driven only from a channel, which performs the transfers specified
+ * in its PaRAM slot until there are no more transfers. When that last
+ * transfer completes, the "link" field may be used to reload the channel's
+ * PaRAM slot with a new transfer descriptor.
+ *
+ * The EDMA Channel Controller (CC) maps requests from channels into physical
+ * Transfer Controller (TC) requests when the channel triggers (by hardware
+ * or software events, or by chaining). The two physical DMA channels provided
+ * by the TCs are thus shared by many logical channels.
+ *
+ * DaVinci hardware also has a "QDMA" mechanism which is not currently
+ * supported through this interface. (DSP firmware uses it though.)
+ */
+
+#ifndef EDMA_H_
+#define EDMA_H_
+
+/* PaRAM slots are laid out like this */
+struct edmacc_param {
+ unsigned int opt;
+ unsigned int src;
+ unsigned int a_b_cnt;
+ unsigned int dst;
+ unsigned int src_dst_bidx;
+ unsigned int link_bcntrld;
+ unsigned int src_dst_cidx;
+ unsigned int ccnt;
+};
+
+#define CCINT0_INTERRUPT 16
+#define CCERRINT_INTERRUPT 17
+#define TCERRINT0_INTERRUPT 18
+#define TCERRINT1_INTERRUPT 19
+
+/* fields in edmacc_param.opt */
+#define SAM BIT(0)
+#define DAM BIT(1)
+#define SYNCDIM BIT(2)
+#define STATIC BIT(3)
+#define EDMA_FWID (0x07 << 8)
+#define TCCMODE BIT(11)
+#define EDMA_TCC(t) ((t) << 12)
+#define TCINTEN BIT(20)
+#define ITCINTEN BIT(21)
+#define TCCHEN BIT(22)
+#define ITCCHEN BIT(23)
+
+#define TRWORD (0x7<<2)
+#define PAENTRY (0x1ff<<5)
+
+/* Drivers should avoid using these symbolic names for dm644x
+ * channels, and use platform_device IORESOURCE_DMA resources
+ * instead. (Other DaVinci chips have different peripherals
+ * and thus have different DMA channel mappings.)
+ */
+#define DAVINCI_DMA_MCBSP_TX 2
+#define DAVINCI_DMA_MCBSP_RX 3
+#define DAVINCI_DMA_VPSS_HIST 4
+#define DAVINCI_DMA_VPSS_H3A 5
+#define DAVINCI_DMA_VPSS_PRVU 6
+#define DAVINCI_DMA_VPSS_RSZ 7
+#define DAVINCI_DMA_IMCOP_IMXINT 8
+#define DAVINCI_DMA_IMCOP_VLCDINT 9
+#define DAVINCI_DMA_IMCO_PASQINT 10
+#define DAVINCI_DMA_IMCOP_DSQINT 11
+#define DAVINCI_DMA_SPI_SPIX 16
+#define DAVINCI_DMA_SPI_SPIR 17
+#define DAVINCI_DMA_UART0_URXEVT0 18
+#define DAVINCI_DMA_UART0_UTXEVT0 19
+#define DAVINCI_DMA_UART1_URXEVT1 20
+#define DAVINCI_DMA_UART1_UTXEVT1 21
+#define DAVINCI_DMA_UART2_URXEVT2 22
+#define DAVINCI_DMA_UART2_UTXEVT2 23
+#define DAVINCI_DMA_MEMSTK_MSEVT 24
+#define DAVINCI_DMA_MMCRXEVT 26
+#define DAVINCI_DMA_MMCTXEVT 27
+#define DAVINCI_DMA_I2C_ICREVT 28
+#define DAVINCI_DMA_I2C_ICXEVT 29
+#define DAVINCI_DMA_GPIO_GPINT0 32
+#define DAVINCI_DMA_GPIO_GPINT1 33
+#define DAVINCI_DMA_GPIO_GPINT2 34
+#define DAVINCI_DMA_GPIO_GPINT3 35
+#define DAVINCI_DMA_GPIO_GPINT4 36
+#define DAVINCI_DMA_GPIO_GPINT5 37
+#define DAVINCI_DMA_GPIO_GPINT6 38
+#define DAVINCI_DMA_GPIO_GPINT7 39
+#define DAVINCI_DMA_GPIO_GPBNKINT0 40
+#define DAVINCI_DMA_GPIO_GPBNKINT1 41
+#define DAVINCI_DMA_GPIO_GPBNKINT2 42
+#define DAVINCI_DMA_GPIO_GPBNKINT3 43
+#define DAVINCI_DMA_GPIO_GPBNKINT4 44
+#define DAVINCI_DMA_TIMER0_TINT0 48
+#define DAVINCI_DMA_TIMER1_TINT1 49
+#define DAVINCI_DMA_TIMER2_TINT2 50
+#define DAVINCI_DMA_TIMER3_TINT3 51
+#define DAVINCI_DMA_PWM0 52
+#define DAVINCI_DMA_PWM1 53
+#define DAVINCI_DMA_PWM2 54
+
+/*ch_status paramater of callback function possible values*/
+#define DMA_COMPLETE 1
+#define DMA_CC_ERROR 2
+#define DMA_TC1_ERROR 3
+#define DMA_TC2_ERROR 4
+
+enum address_mode {
+ INCR = 0,
+ FIFO = 1
+};
+
+enum fifo_width {
+ W8BIT = 0,
+ W16BIT = 1,
+ W32BIT = 2,
+ W64BIT = 3,
+ W128BIT = 4,
+ W256BIT = 5
+};
+
+enum dma_event_q {
+ EVENTQ_0 = 0,
+ EVENTQ_1 = 1,
+ EVENTQ_DEFAULT = -1
+};
+
+enum sync_dimension {
+ ASYNC = 0,
+ ABSYNC = 1
+};
+
+#define EDMA_CHANNEL_ANY -1 /* for edma_alloc_channel() */
+#define EDMA_SLOT_ANY -1 /* for edma_alloc_slot() */
+
+/* alloc/free DMA channels and their dedicated parameter RAM slots */
+int edma_alloc_channel(int channel,
+ void (*callback)(unsigned channel, u16 ch_status, void *data),
+ void *data, enum dma_event_q);
+void edma_free_channel(unsigned channel);
+
+/* alloc/free parameter RAM slots */
+int edma_alloc_slot(int slot);
+void edma_free_slot(unsigned slot);
+
+/* calls that operate on part of a parameter RAM slot */
+void edma_set_src(unsigned slot, dma_addr_t src_port,
+ enum address_mode mode, enum fifo_width);
+void edma_set_dest(unsigned slot, dma_addr_t dest_port,
+ enum address_mode mode, enum fifo_width);
+void edma_get_position(unsigned slot, dma_addr_t *src, dma_addr_t *dst);
+void edma_set_src_index(unsigned slot, s16 src_bidx, s16 src_cidx);
+void edma_set_dest_index(unsigned slot, s16 dest_bidx, s16 dest_cidx);
+void edma_set_transfer_params(unsigned slot, u16 acnt, u16 bcnt, u16 ccnt,
+ u16 bcnt_rld, enum sync_dimension sync_mode);
+void edma_link(unsigned from, unsigned to);
+void edma_unlink(unsigned from);
+
+/* calls that operate on an entire parameter RAM slot */
+void edma_write_slot(unsigned slot, const struct edmacc_param *params);
+void edma_read_slot(unsigned slot, struct edmacc_param *params);
+
+/* channel control operations */
+int edma_start(unsigned channel);
+void edma_stop(unsigned channel);
+void edma_clean_channel(unsigned channel);
+void edma_clear_event(unsigned channel);
+void edma_pause(unsigned channel);
+void edma_resume(unsigned channel);
+
+/* UNRELATED TO DMA */
+int davinci_alloc_iram(unsigned size);
+void davinci_free_iram(unsigned addr, unsigned size);
+
+/* platform_data for EDMA driver */
+struct edma_soc_info {
+
+ /* how many dma resources of each type */
+ unsigned n_channel;
+ unsigned n_region;
+ unsigned n_slot;
+ unsigned n_tc;
+
+ /* list of channels with no even trigger; terminated by "-1" */
+ const s8 *noevent;
+};
+
+#endif
#include <linux/io.h>
#include <asm-generic/gpio.h>
-#include <mach/hardware.h>
+
#include <mach/irqs.h>
+#define DAVINCI_GPIO_BASE 0x01C67000
+
/*
* basic gpio routines
*
* go through boot loaders.
*
* the gpio clock will be turned on when gpios are used, and you may also
- * need to pay attention to PINMUX0 and PINMUX1 to be sure those pins are
+ * need to pay attention to PINMUX registers to be sure those pins are
* used as gpios, not with other peripherals.
*
* On-chip GPIOs are numbered 0..(DAVINCI_N_GPIO-1). For documentation,
- * and maybe for later updates, code should write GPIO(N) or:
- * - GPIOV18(N) for 1.8V pins, N in 0..53; same as GPIO(0)..GPIO(53)
- * - GPIOV33(N) for 3.3V pins, N in 0..17; same as GPIO(54)..GPIO(70)
- *
- * For GPIO IRQs use gpio_to_irq(GPIO(N)) or gpio_to_irq(GPIOV33(N)) etc
- * for now, that's != GPIO(N)
+ * and maybe for later updates, code may write GPIO(N). These may be
+ * all 1.8V signals, all 3.3V ones, or a mix of the two. A given chip
+ * may not support all the GPIOs in that range.
*
* GPIOs can also be on external chips, numbered after the ones built-in
* to the DaVinci chip. For now, they won't be usable as IRQ sources.
*/
-#define GPIO(X) (X) /* 0 <= X <= 70 */
-#define GPIOV18(X) (X) /* 1.8V i/o; 0 <= X <= 53 */
-#define GPIOV33(X) ((X)+54) /* 3.3V i/o; 0 <= X <= 17 */
+#define GPIO(X) (X) /* 0 <= X <= (DAVINCI_N_GPIO - 1) */
struct gpio_controller {
u32 dir;
{
void *__iomem ptr;
- if (gpio < 32)
+ if (gpio < 32 * 1)
ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x10);
- else if (gpio < 64)
+ else if (gpio < 32 * 2)
ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x38);
- else if (gpio < DAVINCI_N_GPIO)
+ else if (gpio < 32 * 3)
ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x60);
+ else if (gpio < 32 * 4)
+ ptr = IO_ADDRESS(DAVINCI_GPIO_BASE + 0x88);
else
ptr = NULL;
return ptr;
/*
- * Common hardware definitions
+ * Hardware definitions common to all DaVinci family processors
*
- * Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
+ * Author: Kevin Hilman, Deep Root Systems, LLC
*
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
+ * 2007 (c) Deep Root Systems, LLC. 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.
#define __ASM_ARCH_HARDWARE_H
/*
- * Base register addresses
+ * Before you add anything to ths file:
+ *
+ * This header is for defines common to ALL DaVinci family chips.
+ * Anything that is chip specific should go in <chipname>.h,
+ * and the chip/board init code should then explicitly include
+ * <chipname>.h
*/
-#define DAVINCI_DMA_3PCC_BASE (0x01C00000)
-#define DAVINCI_DMA_3PTC0_BASE (0x01C10000)
-#define DAVINCI_DMA_3PTC1_BASE (0x01C10400)
-#define DAVINCI_I2C_BASE (0x01C21000)
-#define DAVINCI_PWM0_BASE (0x01C22000)
-#define DAVINCI_PWM1_BASE (0x01C22400)
-#define DAVINCI_PWM2_BASE (0x01C22800)
-#define DAVINCI_SYSTEM_MODULE_BASE (0x01C40000)
-#define DAVINCI_PLL_CNTRL0_BASE (0x01C40800)
-#define DAVINCI_PLL_CNTRL1_BASE (0x01C40C00)
-#define DAVINCI_PWR_SLEEP_CNTRL_BASE (0x01C41000)
-#define DAVINCI_SYSTEM_DFT_BASE (0x01C42000)
-#define DAVINCI_IEEE1394_BASE (0x01C60000)
-#define DAVINCI_USB_OTG_BASE (0x01C64000)
-#define DAVINCI_CFC_ATA_BASE (0x01C66000)
-#define DAVINCI_SPI_BASE (0x01C66800)
-#define DAVINCI_GPIO_BASE (0x01C67000)
-#define DAVINCI_UHPI_BASE (0x01C67800)
-#define DAVINCI_VPSS_REGS_BASE (0x01C70000)
-#define DAVINCI_EMAC_CNTRL_REGS_BASE (0x01C80000)
-#define DAVINCI_EMAC_WRAPPER_CNTRL_REGS_BASE (0x01C81000)
-#define DAVINCI_EMAC_WRAPPER_RAM_BASE (0x01C82000)
-#define DAVINCI_MDIO_CNTRL_REGS_BASE (0x01C84000)
-#define DAVINCI_IMCOP_BASE (0x01CC0000)
-#define DAVINCI_ASYNC_EMIF_CNTRL_BASE (0x01E00000)
-#define DAVINCI_VLYNQ_BASE (0x01E01000)
-#define DAVINCI_MCBSP_BASE (0x01E02000)
-#define DAVINCI_MMC_SD_BASE (0x01E10000)
-#define DAVINCI_MS_BASE (0x01E20000)
-#define DAVINCI_ASYNC_EMIF_DATA_CE0_BASE (0x02000000)
-#define DAVINCI_ASYNC_EMIF_DATA_CE1_BASE (0x04000000)
-#define DAVINCI_ASYNC_EMIF_DATA_CE2_BASE (0x06000000)
-#define DAVINCI_ASYNC_EMIF_DATA_CE3_BASE (0x08000000)
-#define DAVINCI_VLYNQ_REMOTE_BASE (0x0C000000)
+#define DAVINCI_SYSTEM_MODULE_BASE 0x01C40000
+
+/* System control register offsets */
+#define DM64XX_VDD3P3V_PWDN 0x48
#endif /* __ASM_ARCH_HARDWARE_H */
#else
#define IOMEM(x) ((void __force __iomem *)(x))
-/*
- * Functions to access the DaVinci IO region
- *
- * NOTE: - Use davinci_read/write[bwl] for physical register addresses
- * - Use __raw_read/write[bwl]() for virtual register addresses
- * - Use IO_ADDRESS(phys_addr) to convert registers to virtual addresses
- * - DO NOT use hardcoded virtual addresses to allow changing the
- * IO address space again if needed
- */
-#define davinci_readb(a) __raw_readb(IO_ADDRESS(a))
-#define davinci_readw(a) __raw_readw(IO_ADDRESS(a))
-#define davinci_readl(a) __raw_readl(IO_ADDRESS(a))
+#define __arch_ioremap(p, s, t) davinci_ioremap(p, s, t)
+#define __arch_iounmap(v) davinci_iounmap(v)
-#define davinci_writeb(v, a) __raw_writeb(v, IO_ADDRESS(a))
-#define davinci_writew(v, a) __raw_writew(v, IO_ADDRESS(a))
-#define davinci_writel(v, a) __raw_writel(v, IO_ADDRESS(a))
+void __iomem *davinci_ioremap(unsigned long phys, size_t size,
+ unsigned int type);
+void davinci_iounmap(volatile void __iomem *addr);
#endif /* __ASSEMBLER__ */
#endif /* __ASM_ARCH_IO_H */
#define IRQ_EMUINT 63
#define DAVINCI_N_AINTC_IRQ 64
-#define DAVINCI_N_GPIO 71
+#define DAVINCI_N_GPIO 104
#define NR_IRQS (DAVINCI_N_AINTC_IRQ + DAVINCI_N_GPIO)
#define ARCH_TIMER_IRQ IRQ_TINT1_TINT34
+/* DaVinci DM6467-specific Interrupts */
+#define IRQ_DM646X_VP_VERTINT0 0
+#define IRQ_DM646X_VP_VERTINT1 1
+#define IRQ_DM646X_VP_VERTINT2 2
+#define IRQ_DM646X_VP_VERTINT3 3
+#define IRQ_DM646X_VP_ERRINT 4
+#define IRQ_DM646X_RESERVED_1 5
+#define IRQ_DM646X_RESERVED_2 6
+#define IRQ_DM646X_WDINT 7
+#define IRQ_DM646X_CRGENINT0 8
+#define IRQ_DM646X_CRGENINT1 9
+#define IRQ_DM646X_TSIFINT0 10
+#define IRQ_DM646X_TSIFINT1 11
+#define IRQ_DM646X_VDCEINT 12
+#define IRQ_DM646X_USBINT 13
+#define IRQ_DM646X_USBDMAINT 14
+#define IRQ_DM646X_PCIINT 15
+#define IRQ_DM646X_TCERRINT2 20
+#define IRQ_DM646X_TCERRINT3 21
+#define IRQ_DM646X_IDE 22
+#define IRQ_DM646X_HPIINT 23
+#define IRQ_DM646X_EMACRXTHINT 24
+#define IRQ_DM646X_EMACRXINT 25
+#define IRQ_DM646X_EMACTXINT 26
+#define IRQ_DM646X_EMACMISCINT 27
+#define IRQ_DM646X_MCASP0TXINT 28
+#define IRQ_DM646X_MCASP0RXINT 29
+#define IRQ_DM646X_RESERVED_3 31
+#define IRQ_DM646X_MCASP1TXINT 32
+#define IRQ_DM646X_VLQINT 38
+#define IRQ_DM646X_UARTINT2 42
+#define IRQ_DM646X_SPINT0 43
+#define IRQ_DM646X_SPINT1 44
+#define IRQ_DM646X_DSP2ARMINT 45
+#define IRQ_DM646X_RESERVED_4 46
+#define IRQ_DM646X_PSCINT 47
+#define IRQ_DM646X_GPIO0 48
+#define IRQ_DM646X_GPIO1 49
+#define IRQ_DM646X_GPIO2 50
+#define IRQ_DM646X_GPIO3 51
+#define IRQ_DM646X_GPIO4 52
+#define IRQ_DM646X_GPIO5 53
+#define IRQ_DM646X_GPIO6 54
+#define IRQ_DM646X_GPIO7 55
+#define IRQ_DM646X_GPIOBNK0 56
+#define IRQ_DM646X_GPIOBNK1 57
+#define IRQ_DM646X_GPIOBNK2 58
+#define IRQ_DM646X_DDRINT 59
+#define IRQ_DM646X_AEMIFINT 60
+
+/* DaVinci DM355-specific Interrupts */
+#define IRQ_DM355_CCDC_VDINT0 0
+#define IRQ_DM355_CCDC_VDINT1 1
+#define IRQ_DM355_CCDC_VDINT2 2
+#define IRQ_DM355_IPIPE_HST 3
+#define IRQ_DM355_H3AINT 4
+#define IRQ_DM355_IPIPE_SDR 5
+#define IRQ_DM355_IPIPEIFINT 6
+#define IRQ_DM355_OSDINT 7
+#define IRQ_DM355_VENCINT 8
+#define IRQ_DM355_IMCOPINT 11
+#define IRQ_DM355_RTOINT 13
+#define IRQ_DM355_TINT4 13
+#define IRQ_DM355_TINT2_TINT12 13
+#define IRQ_DM355_UARTINT2 14
+#define IRQ_DM355_TINT5 14
+#define IRQ_DM355_TINT2_TINT34 14
+#define IRQ_DM355_TINT6 15
+#define IRQ_DM355_TINT3_TINT12 15
+#define IRQ_DM355_SPINT1_0 17
+#define IRQ_DM355_SPINT1_1 18
+#define IRQ_DM355_SPINT2_0 19
+#define IRQ_DM355_SPINT2_1 21
+#define IRQ_DM355_TINT7 22
+#define IRQ_DM355_TINT3_TINT34 22
+#define IRQ_DM355_SDIOINT0 23
+#define IRQ_DM355_MMCINT0 26
+#define IRQ_DM355_MSINT 26
+#define IRQ_DM355_MMCINT1 27
+#define IRQ_DM355_PWMINT3 28
+#define IRQ_DM355_SDIOINT1 31
+#define IRQ_DM355_SPINT0_0 42
+#define IRQ_DM355_SPINT0_1 43
+#define IRQ_DM355_GPIO0 44
+#define IRQ_DM355_GPIO1 45
+#define IRQ_DM355_GPIO2 46
+#define IRQ_DM355_GPIO3 47
+#define IRQ_DM355_GPIO4 48
+#define IRQ_DM355_GPIO5 49
+#define IRQ_DM355_GPIO6 50
+#define IRQ_DM355_GPIO7 51
+#define IRQ_DM355_GPIO8 52
+#define IRQ_DM355_GPIO9 53
+#define IRQ_DM355_GPIOBNK0 54
+#define IRQ_DM355_GPIOBNK1 55
+#define IRQ_DM355_GPIOBNK2 56
+#define IRQ_DM355_GPIOBNK3 57
+#define IRQ_DM355_GPIOBNK4 58
+#define IRQ_DM355_GPIOBNK5 59
+#define IRQ_DM355_GPIOBNK6 60
+
#endif /* __ASM_ARCH_IRQS_H */
/*
- * DaVinci pin multiplexing defines
+ * Table of the DAVINCI register configurations for the PINMUX combinations
*
* Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
*
+ * Based on linux/include/asm-arm/arch-omap/mux.h:
+ * Copyright (C) 2003 - 2005 Nokia Corporation
+ *
+ * Written by Tony Lindgren
+ *
* 2007 (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.
+ *
+ * Copyright (C) 2008 Texas Instruments.
*/
-#ifndef __ASM_ARCH_MUX_H
-#define __ASM_ARCH_MUX_H
-
-#define DAVINCI_MUX_AEAW0 0
-#define DAVINCI_MUX_AEAW1 1
-#define DAVINCI_MUX_AEAW2 2
-#define DAVINCI_MUX_AEAW3 3
-#define DAVINCI_MUX_AEAW4 4
-#define DAVINCI_MUX_AECS4 10
-#define DAVINCI_MUX_AECS5 11
-#define DAVINCI_MUX_VLYNQWD0 12
-#define DAVINCI_MUX_VLYNQWD1 13
-#define DAVINCI_MUX_VLSCREN 14
-#define DAVINCI_MUX_VLYNQEN 15
-#define DAVINCI_MUX_HDIREN 16
-#define DAVINCI_MUX_ATAEN 17
-#define DAVINCI_MUX_RGB666 22
-#define DAVINCI_MUX_RGB888 23
-#define DAVINCI_MUX_LOEEN 24
-#define DAVINCI_MUX_LFLDEN 25
-#define DAVINCI_MUX_CWEN 26
-#define DAVINCI_MUX_CFLDEN 27
-#define DAVINCI_MUX_HPIEN 29
-#define DAVINCI_MUX_1394EN 30
-#define DAVINCI_MUX_EMACEN 31
-
-#define DAVINCI_MUX_LEVEL2 32
-#define DAVINCI_MUX_UART0 (DAVINCI_MUX_LEVEL2 + 0)
-#define DAVINCI_MUX_UART1 (DAVINCI_MUX_LEVEL2 + 1)
-#define DAVINCI_MUX_UART2 (DAVINCI_MUX_LEVEL2 + 2)
-#define DAVINCI_MUX_U2FLO (DAVINCI_MUX_LEVEL2 + 3)
-#define DAVINCI_MUX_PWM0 (DAVINCI_MUX_LEVEL2 + 4)
-#define DAVINCI_MUX_PWM1 (DAVINCI_MUX_LEVEL2 + 5)
-#define DAVINCI_MUX_PWM2 (DAVINCI_MUX_LEVEL2 + 6)
-#define DAVINCI_MUX_I2C (DAVINCI_MUX_LEVEL2 + 7)
-#define DAVINCI_MUX_SPI (DAVINCI_MUX_LEVEL2 + 8)
-#define DAVINCI_MUX_MSTK (DAVINCI_MUX_LEVEL2 + 9)
-#define DAVINCI_MUX_ASP (DAVINCI_MUX_LEVEL2 + 10)
-#define DAVINCI_MUX_CLK0 (DAVINCI_MUX_LEVEL2 + 16)
-#define DAVINCI_MUX_CLK1 (DAVINCI_MUX_LEVEL2 + 17)
-#define DAVINCI_MUX_TIMIN (DAVINCI_MUX_LEVEL2 + 18)
-
-extern void davinci_mux_peripheral(unsigned int mux, unsigned int enable);
-
-#endif /* __ASM_ARCH_MUX_H */
+
+#ifndef __INC_MACH_MUX_H
+#define __INC_MACH_MUX_H
+
+/* System module registers */
+#define PINMUX0 0x00
+#define PINMUX1 0x04
+/* dm355 only */
+#define PINMUX2 0x08
+#define PINMUX3 0x0c
+#define PINMUX4 0x10
+#define INTMUX 0x18
+#define EVTMUX 0x1c
+
+struct mux_config {
+ const char *name;
+ const char *mux_reg_name;
+ const unsigned char mux_reg;
+ const unsigned char mask_offset;
+ const unsigned char mask;
+ const unsigned char mode;
+ bool debug;
+};
+
+enum davinci_dm644x_index {
+ /* ATA and HDDIR functions */
+ DM644X_HDIREN,
+ DM644X_ATAEN,
+ DM644X_ATAEN_DISABLE,
+
+ /* HPI functions */
+ DM644X_HPIEN_DISABLE,
+
+ /* AEAW functions */
+ DM644X_AEAW,
+
+ /* Memory Stick */
+ DM644X_MSTK,
+
+ /* I2C */
+ DM644X_I2C,
+
+ /* ASP function */
+ DM644X_MCBSP,
+
+ /* UART1 */
+ DM644X_UART1,
+
+ /* UART2 */
+ DM644X_UART2,
+
+ /* PWM0 */
+ DM644X_PWM0,
+
+ /* PWM1 */
+ DM644X_PWM1,
+
+ /* PWM2 */
+ DM644X_PWM2,
+
+ /* VLYNQ function */
+ DM644X_VLYNQEN,
+ DM644X_VLSCREN,
+ DM644X_VLYNQWD,
+
+ /* EMAC and MDIO function */
+ DM644X_EMACEN,
+
+ /* GPIO3V[0:16] pins */
+ DM644X_GPIO3V,
+
+ /* GPIO pins */
+ DM644X_GPIO0,
+ DM644X_GPIO3,
+ DM644X_GPIO43_44,
+ DM644X_GPIO46_47,
+
+ /* VPBE */
+ DM644X_RGB666,
+
+ /* LCD */
+ DM644X_LOEEN,
+ DM644X_LFLDEN,
+};
+
+enum davinci_dm646x_index {
+ /* ATA function */
+ DM646X_ATAEN,
+
+ /* AUDIO Clock */
+ DM646X_AUDCK1,
+ DM646X_AUDCK0,
+
+ /* CRGEN Control */
+ DM646X_CRGMUX,
+
+ /* VPIF Control */
+ DM646X_STSOMUX_DISABLE,
+ DM646X_STSIMUX_DISABLE,
+ DM646X_PTSOMUX_DISABLE,
+ DM646X_PTSIMUX_DISABLE,
+
+ /* TSIF Control */
+ DM646X_STSOMUX,
+ DM646X_STSIMUX,
+ DM646X_PTSOMUX_PARALLEL,
+ DM646X_PTSIMUX_PARALLEL,
+ DM646X_PTSOMUX_SERIAL,
+ DM646X_PTSIMUX_SERIAL,
+};
+
+enum davinci_dm355_index {
+ /* MMC/SD 0 */
+ DM355_MMCSD0,
+
+ /* MMC/SD 1 */
+ DM355_SD1_CLK,
+ DM355_SD1_CMD,
+ DM355_SD1_DATA3,
+ DM355_SD1_DATA2,
+ DM355_SD1_DATA1,
+ DM355_SD1_DATA0,
+
+ /* I2C */
+ DM355_I2C_SDA,
+ DM355_I2C_SCL,
+
+ /* ASP0 function */
+ DM355_MCBSP0_BDX,
+ DM355_MCBSP0_X,
+ DM355_MCBSP0_BFSX,
+ DM355_MCBSP0_BDR,
+ DM355_MCBSP0_R,
+ DM355_MCBSP0_BFSR,
+
+ /* SPI0 */
+ DM355_SPI0_SDI,
+ DM355_SPI0_SDENA0,
+ DM355_SPI0_SDENA1,
+
+ /* IRQ muxing */
+ DM355_INT_EDMA_CC,
+ DM355_INT_EDMA_TC0_ERR,
+ DM355_INT_EDMA_TC1_ERR,
+
+ /* EDMA event muxing */
+ DM355_EVT8_ASP1_TX,
+ DM355_EVT9_ASP1_RX,
+ DM355_EVT26_MMC0_RX,
+};
+
+#ifdef CONFIG_DAVINCI_MUX
+/* setup pin muxing */
+extern void davinci_mux_init(void);
+extern int davinci_mux_register(const struct mux_config *pins,
+ unsigned long size);
+extern int davinci_cfg_reg(unsigned long reg_cfg);
+#else
+/* boot loader does it all (no warnings from CONFIG_DAVINCI_MUX_WARNINGS) */
+static inline void davinci_mux_init(void) {}
+static inline int davinci_mux_register(const struct mux_config *pins,
+ unsigned long size) { return 0; }
+static inline int davinci_cfg_reg(unsigned long reg_cfg) { return 0; }
+#endif
+
+#endif /* __INC_MACH_MUX_H */
#define DAVINCI_LPSC_TPTC1 4
#define DAVINCI_LPSC_EMAC 5
#define DAVINCI_LPSC_EMAC_WRAPPER 6
-#define DAVINCI_LPSC_MDIO 7
-#define DAVINCI_LPSC_IEEE1394 8
#define DAVINCI_LPSC_USB 9
#define DAVINCI_LPSC_ATA 10
#define DAVINCI_LPSC_VLYNQ 11
#define DAVINCI_LPSC_DDR_EMIF 13
#define DAVINCI_LPSC_AEMIF 14
#define DAVINCI_LPSC_MMC_SD 15
-#define DAVINCI_LPSC_MEMSTICK 16
#define DAVINCI_LPSC_McBSP 17
#define DAVINCI_LPSC_I2C 18
#define DAVINCI_LPSC_UART0 19
#define DAVINCI_LPSC_GEM 39
#define DAVINCI_LPSC_IMCOP 40
+#define DM355_LPSC_TIMER3 5
+#define DM355_LPSC_SPI1 6
+#define DM355_LPSC_MMC_SD1 7
+#define DM355_LPSC_McBSP1 8
+#define DM355_LPSC_PWM3 10
+#define DM355_LPSC_SPI2 11
+#define DM355_LPSC_RTO 12
+#define DM355_LPSC_VPSS_DAC 41
+
+/*
+ * LPSC Assignments
+ */
+#define DM646X_LPSC_ARM 0
+#define DM646X_LPSC_C64X_CPU 1
+#define DM646X_LPSC_HDVICP0 2
+#define DM646X_LPSC_HDVICP1 3
+#define DM646X_LPSC_TPCC 4
+#define DM646X_LPSC_TPTC0 5
+#define DM646X_LPSC_TPTC1 6
+#define DM646X_LPSC_TPTC2 7
+#define DM646X_LPSC_TPTC3 8
+#define DM646X_LPSC_PCI 13
+#define DM646X_LPSC_EMAC 14
+#define DM646X_LPSC_VDCE 15
+#define DM646X_LPSC_VPSSMSTR 16
+#define DM646X_LPSC_VPSSSLV 17
+#define DM646X_LPSC_TSIF0 18
+#define DM646X_LPSC_TSIF1 19
+#define DM646X_LPSC_DDR_EMIF 20
+#define DM646X_LPSC_AEMIF 21
+#define DM646X_LPSC_McASP0 22
+#define DM646X_LPSC_McASP1 23
+#define DM646X_LPSC_CRGEN0 24
+#define DM646X_LPSC_CRGEN1 25
+#define DM646X_LPSC_UART0 26
+#define DM646X_LPSC_UART1 27
+#define DM646X_LPSC_UART2 28
+#define DM646X_LPSC_PWM0 29
+#define DM646X_LPSC_PWM1 30
+#define DM646X_LPSC_I2C 31
+#define DM646X_LPSC_SPI 32
+#define DM646X_LPSC_GPIO 33
+#define DM646X_LPSC_TIMER0 34
+#define DM646X_LPSC_TIMER1 35
+#define DM646X_LPSC_ARM_INTC 45
+
+extern int davinci_psc_is_clk_active(unsigned int id);
+extern void davinci_psc_config(unsigned int domain, unsigned int id,
+ char enable);
+
#endif /* __ASM_ARCH_PSC_H */
#include <mach/io.h>
-#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000)
-#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400)
-#define DAVINCI_UART2_BASE (IO_PHYS + 0x20800)
+#define DAVINCI_MAX_NR_UARTS 3
+#define DAVINCI_UART0_BASE (IO_PHYS + 0x20000)
+#define DAVINCI_UART1_BASE (IO_PHYS + 0x20400)
+#define DAVINCI_UART2_BASE (IO_PHYS + 0x20800)
+
+#define DM355_UART2_BASE (IO_PHYS + 0x206000)
+
+/* DaVinci UART register offsets */
+#define UART_DAVINCI_PWREMU 0x0c
+#define UART_DM646X_SCR 0x10
+#define UART_DM646X_SCR_TX_WATERMARK 0x08
+
+struct davinci_uart_config {
+ /* Bit field of UARTs present; bit 0 --> UART1 */
+ unsigned int enabled_uarts;
+};
+
+extern void davinci_serial_init(struct davinci_uart_config *);
#endif /* __ASM_ARCH_SERIAL_H */
davinci_check_revision();
}
-void __init davinci_init_common_hw(void)
+#define BETWEEN(p, st, sz) ((p) >= (st) && (p) < ((st) + (sz)))
+#define XLATE(p, pst, vst) ((void __iomem *)((p) - (pst) + (vst)))
+
+/*
+ * Intercept ioremap() requests for addresses in our fixed mapping regions.
+ */
+void __iomem *davinci_ioremap(unsigned long p, size_t size, unsigned int type)
+{
+ if (BETWEEN(p, IO_PHYS, IO_SIZE))
+ return XLATE(p, IO_PHYS, IO_VIRT);
+
+ return __arm_ioremap(p, size, type);
+}
+EXPORT_SYMBOL(davinci_ioremap);
+
+void davinci_iounmap(volatile void __iomem *addr)
{
- davinci_clk_init();
+ unsigned long virt = (unsigned long)addr;
+
+ if (virt >= VMALLOC_START && virt < VMALLOC_END)
+ __iounmap(addr);
}
+EXPORT_SYMBOL(davinci_iounmap);
#include <linux/io.h>
#include <mach/hardware.h>
+#include <mach/cputype.h>
#include <asm/mach/irq.h>
#define IRQ_BIT(irq) ((irq) & 0x1f)
#define IRQ_INTPRI0_REG_OFFSET 0x0030
#define IRQ_INTPRI7_REG_OFFSET 0x004C
+const u8 *davinci_def_priorities;
+
+#define INTC_BASE IO_ADDRESS(DAVINCI_ARM_INTC_BASE)
+
static inline unsigned int davinci_irq_readl(int offset)
{
- return davinci_readl(DAVINCI_ARM_INTC_BASE + offset);
+ return __raw_readl(INTC_BASE + offset);
}
static inline void davinci_irq_writel(unsigned long value, int offset)
{
- davinci_writel(value, DAVINCI_ARM_INTC_BASE + offset);
+ __raw_writel(value, INTC_BASE + offset);
}
/* Disable interrupt */
.unmask = davinci_unmask_irq,
};
-
/* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
-static const u8 default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
+static const u8 dm644x_default_priorities[DAVINCI_N_AINTC_IRQ] __initdata = {
[IRQ_VDINT0] = 2,
[IRQ_VDINT1] = 6,
[IRQ_VDINT2] = 6,
[IRQ_EMUINT] = 7,
};
+static const u8 dm646x_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+ [IRQ_DM646X_VP_VERTINT0] = 7,
+ [IRQ_DM646X_VP_VERTINT1] = 7,
+ [IRQ_DM646X_VP_VERTINT2] = 7,
+ [IRQ_DM646X_VP_VERTINT3] = 7,
+ [IRQ_DM646X_VP_ERRINT] = 7,
+ [IRQ_DM646X_RESERVED_1] = 7,
+ [IRQ_DM646X_RESERVED_2] = 7,
+ [IRQ_DM646X_WDINT] = 7,
+ [IRQ_DM646X_CRGENINT0] = 7,
+ [IRQ_DM646X_CRGENINT1] = 7,
+ [IRQ_DM646X_TSIFINT0] = 7,
+ [IRQ_DM646X_TSIFINT1] = 7,
+ [IRQ_DM646X_VDCEINT] = 7,
+ [IRQ_DM646X_USBINT] = 7,
+ [IRQ_DM646X_USBDMAINT] = 7,
+ [IRQ_DM646X_PCIINT] = 7,
+ [IRQ_CCINT0] = 7, /* dma */
+ [IRQ_CCERRINT] = 7, /* dma */
+ [IRQ_TCERRINT0] = 7, /* dma */
+ [IRQ_TCERRINT] = 7, /* dma */
+ [IRQ_DM646X_TCERRINT2] = 7,
+ [IRQ_DM646X_TCERRINT3] = 7,
+ [IRQ_DM646X_IDE] = 7,
+ [IRQ_DM646X_HPIINT] = 7,
+ [IRQ_DM646X_EMACRXTHINT] = 7,
+ [IRQ_DM646X_EMACRXINT] = 7,
+ [IRQ_DM646X_EMACTXINT] = 7,
+ [IRQ_DM646X_EMACMISCINT] = 7,
+ [IRQ_DM646X_MCASP0TXINT] = 7,
+ [IRQ_DM646X_MCASP0RXINT] = 7,
+ [IRQ_AEMIFINT] = 7,
+ [IRQ_DM646X_RESERVED_3] = 7,
+ [IRQ_DM646X_MCASP1TXINT] = 7, /* clockevent */
+ [IRQ_TINT0_TINT34] = 7, /* clocksource */
+ [IRQ_TINT1_TINT12] = 7, /* DSP timer */
+ [IRQ_TINT1_TINT34] = 7, /* system tick */
+ [IRQ_PWMINT0] = 7,
+ [IRQ_PWMINT1] = 7,
+ [IRQ_DM646X_VLQINT] = 7,
+ [IRQ_I2C] = 7,
+ [IRQ_UARTINT0] = 7,
+ [IRQ_UARTINT1] = 7,
+ [IRQ_DM646X_UARTINT2] = 7,
+ [IRQ_DM646X_SPINT0] = 7,
+ [IRQ_DM646X_SPINT1] = 7,
+ [IRQ_DM646X_DSP2ARMINT] = 7,
+ [IRQ_DM646X_RESERVED_4] = 7,
+ [IRQ_DM646X_PSCINT] = 7,
+ [IRQ_DM646X_GPIO0] = 7,
+ [IRQ_DM646X_GPIO1] = 7,
+ [IRQ_DM646X_GPIO2] = 7,
+ [IRQ_DM646X_GPIO3] = 7,
+ [IRQ_DM646X_GPIO4] = 7,
+ [IRQ_DM646X_GPIO5] = 7,
+ [IRQ_DM646X_GPIO6] = 7,
+ [IRQ_DM646X_GPIO7] = 7,
+ [IRQ_DM646X_GPIOBNK0] = 7,
+ [IRQ_DM646X_GPIOBNK1] = 7,
+ [IRQ_DM646X_GPIOBNK2] = 7,
+ [IRQ_DM646X_DDRINT] = 7,
+ [IRQ_DM646X_AEMIFINT] = 7,
+ [IRQ_COMMTX] = 7,
+ [IRQ_COMMRX] = 7,
+ [IRQ_EMUINT] = 7,
+};
+
+static const u8 dm355_default_priorities[DAVINCI_N_AINTC_IRQ] = {
+ [IRQ_DM355_CCDC_VDINT0] = 2,
+ [IRQ_DM355_CCDC_VDINT1] = 6,
+ [IRQ_DM355_CCDC_VDINT2] = 6,
+ [IRQ_DM355_IPIPE_HST] = 6,
+ [IRQ_DM355_H3AINT] = 6,
+ [IRQ_DM355_IPIPE_SDR] = 6,
+ [IRQ_DM355_IPIPEIFINT] = 6,
+ [IRQ_DM355_OSDINT] = 7,
+ [IRQ_DM355_VENCINT] = 6,
+ [IRQ_ASQINT] = 6,
+ [IRQ_IMXINT] = 6,
+ [IRQ_USBINT] = 4,
+ [IRQ_DM355_RTOINT] = 4,
+ [IRQ_DM355_UARTINT2] = 7,
+ [IRQ_DM355_TINT6] = 7,
+ [IRQ_CCINT0] = 5, /* dma */
+ [IRQ_CCERRINT] = 5, /* dma */
+ [IRQ_TCERRINT0] = 5, /* dma */
+ [IRQ_TCERRINT] = 5, /* dma */
+ [IRQ_DM355_SPINT2_1] = 7,
+ [IRQ_DM355_TINT7] = 4,
+ [IRQ_DM355_SDIOINT0] = 7,
+ [IRQ_MBXINT] = 7,
+ [IRQ_MBRINT] = 7,
+ [IRQ_MMCINT] = 7,
+ [IRQ_DM355_MMCINT1] = 7,
+ [IRQ_DM355_PWMINT3] = 7,
+ [IRQ_DDRINT] = 7,
+ [IRQ_AEMIFINT] = 7,
+ [IRQ_DM355_SDIOINT1] = 4,
+ [IRQ_TINT0_TINT12] = 2, /* clockevent */
+ [IRQ_TINT0_TINT34] = 2, /* clocksource */
+ [IRQ_TINT1_TINT12] = 7, /* DSP timer */
+ [IRQ_TINT1_TINT34] = 7, /* system tick */
+ [IRQ_PWMINT0] = 7,
+ [IRQ_PWMINT1] = 7,
+ [IRQ_PWMINT2] = 7,
+ [IRQ_I2C] = 3,
+ [IRQ_UARTINT0] = 3,
+ [IRQ_UARTINT1] = 3,
+ [IRQ_DM355_SPINT0_0] = 3,
+ [IRQ_DM355_SPINT0_1] = 3,
+ [IRQ_DM355_GPIO0] = 3,
+ [IRQ_DM355_GPIO1] = 7,
+ [IRQ_DM355_GPIO2] = 4,
+ [IRQ_DM355_GPIO3] = 4,
+ [IRQ_DM355_GPIO4] = 7,
+ [IRQ_DM355_GPIO5] = 7,
+ [IRQ_DM355_GPIO6] = 7,
+ [IRQ_DM355_GPIO7] = 7,
+ [IRQ_DM355_GPIO8] = 7,
+ [IRQ_DM355_GPIO9] = 7,
+ [IRQ_DM355_GPIOBNK0] = 7,
+ [IRQ_DM355_GPIOBNK1] = 7,
+ [IRQ_DM355_GPIOBNK2] = 7,
+ [IRQ_DM355_GPIOBNK3] = 7,
+ [IRQ_DM355_GPIOBNK4] = 7,
+ [IRQ_DM355_GPIOBNK5] = 7,
+ [IRQ_DM355_GPIOBNK6] = 7,
+ [IRQ_COMMTX] = 7,
+ [IRQ_COMMRX] = 7,
+ [IRQ_EMUINT] = 7,
+};
+
/* ARM Interrupt Controller Initialization */
void __init davinci_irq_init(void)
{
unsigned i;
- const u8 *priority = default_priorities;
+
+ if (cpu_is_davinci_dm644x())
+ davinci_def_priorities = dm644x_default_priorities;
+ else if (cpu_is_davinci_dm646x())
+ davinci_def_priorities = dm646x_default_priorities;
+ else if (cpu_is_davinci_dm355())
+ davinci_def_priorities = dm355_default_priorities;
/* Clear all interrupt requests */
davinci_irq_writel(~0x0, FIQ_REG0_OFFSET);
unsigned j;
u32 pri;
- for (j = 0, pri = 0; j < 32; j += 4, priority++)
- pri |= (*priority & 0x07) << j;
+ for (j = 0, pri = 0; j < 32; j += 4, davinci_def_priorities++)
+ pri |= (*davinci_def_priorities & 0x07) << j;
davinci_irq_writel(pri, i);
}
/*
- * DaVinci pin multiplexing configurations
+ * Utility to set the DAVINCI MUX register from a table in mux.h
*
* Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
*
+ * Based on linux/arch/arm/plat-omap/mux.c:
+ * Copyright (C) 2003 - 2005 Nokia Corporation
+ *
+ * Written by Tony Lindgren
+ *
* 2007 (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.
+ *
+ * Copyright (C) 2008 Texas Instruments.
*/
#include <linux/io.h>
+#include <linux/module.h>
#include <linux/spinlock.h>
#include <mach/hardware.h>
-
#include <mach/mux.h>
-/* System control register offsets */
-#define PINMUX0 0x00
-#define PINMUX1 0x04
+static const struct mux_config *mux_table;
+static unsigned long pin_table_sz;
+
+int __init davinci_mux_register(const struct mux_config *pins,
+ unsigned long size)
+{
+ mux_table = pins;
+ pin_table_sz = size;
-static DEFINE_SPINLOCK(mux_lock);
+ return 0;
+}
-void davinci_mux_peripheral(unsigned int mux, unsigned int enable)
+/*
+ * Sets the DAVINCI MUX register based on the table
+ */
+int __init_or_module davinci_cfg_reg(const unsigned long index)
{
- u32 pinmux, muxreg = PINMUX0;
+ static DEFINE_SPINLOCK(mux_spin_lock);
+ void __iomem *base = IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE);
+ unsigned long flags;
+ const struct mux_config *cfg;
+ unsigned int reg_orig = 0, reg = 0;
+ unsigned int mask, warn = 0;
+
+ if (!mux_table)
+ BUG();
+
+ if (index >= pin_table_sz) {
+ printk(KERN_ERR "Invalid pin mux index: %lu (%lu)\n",
+ index, pin_table_sz);
+ dump_stack();
+ return -ENODEV;
+ }
+
+ cfg = &mux_table[index];
+
+ if (cfg->name == NULL) {
+ printk(KERN_ERR "No entry for the specified index\n");
+ return -ENODEV;
+ }
+
+ /* Update the mux register in question */
+ if (cfg->mask) {
+ unsigned tmp1, tmp2;
+
+ spin_lock_irqsave(&mux_spin_lock, flags);
+ reg_orig = __raw_readl(base + cfg->mux_reg);
+
+ mask = (cfg->mask << cfg->mask_offset);
+ tmp1 = reg_orig & mask;
+ reg = reg_orig & ~mask;
+
+ tmp2 = (cfg->mode << cfg->mask_offset);
+ reg |= tmp2;
+
+ if (tmp1 != tmp2)
+ warn = 1;
+
+ __raw_writel(reg, base + cfg->mux_reg);
+ spin_unlock_irqrestore(&mux_spin_lock, flags);
+ }
+
+ if (warn) {
+#ifdef CONFIG_DAVINCI_MUX_WARNINGS
+ printk(KERN_WARNING "MUX: initialized %s\n", cfg->name);
+#endif
+ }
- if (mux >= DAVINCI_MUX_LEVEL2) {
- muxreg = PINMUX1;
- mux -= DAVINCI_MUX_LEVEL2;
+#ifdef CONFIG_DAVINCI_MUX_DEBUG
+ if (cfg->debug || warn) {
+ printk(KERN_WARNING "MUX: Setting register %s\n", cfg->name);
+ printk(KERN_WARNING " %s (0x%08x) = 0x%08x -> 0x%08x\n",
+ cfg->mux_reg_name, cfg->mux_reg, reg_orig, reg);
}
+#endif
- spin_lock(&mux_lock);
- pinmux = davinci_readl(DAVINCI_SYSTEM_MODULE_BASE + muxreg);
- if (enable)
- pinmux |= (1 << mux);
- else
- pinmux &= ~(1 << mux);
- davinci_writel(pinmux, DAVINCI_SYSTEM_MODULE_BASE + muxreg);
- spin_unlock(&mux_lock);
+ return 0;
}
+EXPORT_SYMBOL(davinci_cfg_reg);
--- /dev/null
+/*
+ * Pin-multiplex helper macros for TI DaVinci family devices
+ *
+ * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com>
+ *
+ * 2007 (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.
+ *
+ * Copyright (C) 2008 Texas Instruments.
+ */
+#ifndef _MACH_DAVINCI_MUX_H_
+#define _MACH_DAVINCI_MUX_H_
+
+#include <mach/mux.h>
+
+#define MUX_CFG(soc, desc, muxreg, mode_offset, mode_mask, mux_mode, dbg)\
+[soc##_##desc] = { \
+ .name = #desc, \
+ .debug = dbg, \
+ .mux_reg_name = "PINMUX"#muxreg, \
+ .mux_reg = PINMUX##muxreg, \
+ .mask_offset = mode_offset, \
+ .mask = mode_mask, \
+ .mode = mux_mode, \
+ },
+
+#define INT_CFG(soc, desc, mode_offset, mode_mask, mux_mode, dbg) \
+[soc##_##desc] = { \
+ .name = #desc, \
+ .debug = dbg, \
+ .mux_reg_name = "INTMUX", \
+ .mux_reg = INTMUX, \
+ .mask_offset = mode_offset, \
+ .mask = mode_mask, \
+ .mode = mux_mode, \
+ },
+
+#define EVT_CFG(soc, desc, mode_offset, mode_mask, mux_mode, dbg) \
+[soc##_##desc] = { \
+ .name = #desc, \
+ .debug = dbg, \
+ .mux_reg_name = "EVTMUX", \
+ .mux_reg = EVTMUX, \
+ .mask_offset = mode_offset, \
+ .mask = mode_mask, \
+ .mode = mux_mode, \
+ },
+
+#endif /* _MACH_DAVINCI_MUX_H */
#include <linux/init.h>
#include <linux/io.h>
+#include <mach/cputype.h>
#include <mach/hardware.h>
#include <mach/psc.h>
#include <mach/mux.h>
+#define DAVINCI_PWR_SLEEP_CNTRL_BASE 0x01C41000
+
/* PSC register offsets */
#define EPCPR 0x070
#define PTCMD 0x120
#define MDSTAT 0x800
#define MDCTL 0xA00
-/* System control register offsets */
-#define VDD3P3V_PWDN 0x48
+#define MDSTAT_STATE_MASK 0x1f
-static void davinci_psc_mux(unsigned int id)
+/* Return nonzero iff the domain's clock is active */
+int __init davinci_psc_is_clk_active(unsigned int id)
{
- switch (id) {
- case DAVINCI_LPSC_ATA:
- davinci_mux_peripheral(DAVINCI_MUX_HDIREN, 1);
- davinci_mux_peripheral(DAVINCI_MUX_ATAEN, 1);
- break;
- case DAVINCI_LPSC_MMC_SD:
- /* VDD power manupulations are done in U-Boot for CPMAC
- * so applies to MMC as well
- */
- /*Set up the pull regiter for MMC */
- davinci_writel(0, DAVINCI_SYSTEM_MODULE_BASE + VDD3P3V_PWDN);
- davinci_mux_peripheral(DAVINCI_MUX_MSTK, 0);
- break;
- case DAVINCI_LPSC_I2C:
- davinci_mux_peripheral(DAVINCI_MUX_I2C, 1);
- break;
- case DAVINCI_LPSC_McBSP:
- davinci_mux_peripheral(DAVINCI_MUX_ASP, 1);
- break;
- default:
- break;
- }
+ void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE);
+ u32 mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
+
+ /* if clocked, state can be "Enable" or "SyncReset" */
+ return mdstat & BIT(12);
}
/* Enable or disable a PSC domain */
void davinci_psc_config(unsigned int domain, unsigned int id, char enable)
{
- u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl, mdstat_mask;
+ u32 epcpr, ptcmd, ptstat, pdstat, pdctl1, mdstat, mdctl;
+ void __iomem *psc_base = IO_ADDRESS(DAVINCI_PWR_SLEEP_CNTRL_BASE);
+ u32 next_state = enable ? 0x3 : 0x2; /* 0x3 enables, 0x2 disables */
- mdctl = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
- if (enable)
- mdctl |= 0x00000003; /* Enable Module */
- else
- mdctl &= 0xFFFFFFF2; /* Disable Module */
- davinci_writel(mdctl, DAVINCI_PWR_SLEEP_CNTRL_BASE + MDCTL + 4 * id);
+ mdctl = __raw_readl(psc_base + MDCTL + 4 * id);
+ mdctl &= ~MDSTAT_STATE_MASK;
+ mdctl |= next_state;
+ __raw_writel(mdctl, psc_base + MDCTL + 4 * id);
- pdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDSTAT);
+ pdstat = __raw_readl(psc_base + PDSTAT);
if ((pdstat & 0x00000001) == 0) {
- pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ pdctl1 = __raw_readl(psc_base + PDCTL1);
pdctl1 |= 0x1;
- davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ __raw_writel(pdctl1, psc_base + PDCTL1);
ptcmd = 1 << domain;
- davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+ __raw_writel(ptcmd, psc_base + PTCMD);
do {
- epcpr = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
- EPCPR);
+ epcpr = __raw_readl(psc_base + EPCPR);
} while ((((epcpr >> domain) & 1) == 0));
- pdctl1 = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ pdctl1 = __raw_readl(psc_base + PDCTL1);
pdctl1 |= 0x100;
- davinci_writel(pdctl1, DAVINCI_PWR_SLEEP_CNTRL_BASE + PDCTL1);
+ __raw_writel(pdctl1, psc_base + PDCTL1);
do {
- ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
+ ptstat = __raw_readl(psc_base +
PTSTAT);
} while (!(((ptstat >> domain) & 1) == 0));
} else {
ptcmd = 1 << domain;
- davinci_writel(ptcmd, DAVINCI_PWR_SLEEP_CNTRL_BASE + PTCMD);
+ __raw_writel(ptcmd, psc_base + PTCMD);
do {
- ptstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
- PTSTAT);
+ ptstat = __raw_readl(psc_base + PTSTAT);
} while (!(((ptstat >> domain) & 1) == 0));
}
- if (enable)
- mdstat_mask = 0x3;
- else
- mdstat_mask = 0x2;
-
do {
- mdstat = davinci_readl(DAVINCI_PWR_SLEEP_CNTRL_BASE +
- MDSTAT + 4 * id);
- } while (!((mdstat & 0x0000001F) == mdstat_mask));
-
- if (enable)
- davinci_psc_mux(id);
-}
-
-void __init davinci_psc_init(void)
-{
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSMSTR, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_VPSSSLV, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPCC, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC0, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TPTC1, 1);
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_GPIO, 1);
-
- /* Turn on WatchDog timer LPSC. Needed for RESET to work */
- davinci_psc_config(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1);
+ mdstat = __raw_readl(psc_base + MDSTAT + 4 * id);
+ } while (!((mdstat & MDSTAT_STATE_MASK) == next_state));
}
#include <mach/hardware.h>
#include <mach/serial.h>
#include <mach/irqs.h>
+#include <mach/cputype.h>
+#include "clock.h"
-#define UART_DAVINCI_PWREMU 0x0c
-
-static inline unsigned int davinci_serial_in(struct plat_serial8250_port *up,
- int offset)
+static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
+ int offset)
{
offset <<= up->regshift;
- return (unsigned int)__raw_readb(up->membase + offset);
+ return (unsigned int)__raw_readl(IO_ADDRESS(up->mapbase) + offset);
}
-static inline void davinci_serial_outp(struct plat_serial8250_port *p,
- int offset, int value)
+static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
+ int value)
{
offset <<= p->regshift;
- __raw_writeb(value, p->membase + offset);
+ __raw_writel(value, IO_ADDRESS(p->mapbase) + offset);
}
static struct plat_serial8250_port serial_platform_data[] = {
{
- .membase = (char *)IO_ADDRESS(DAVINCI_UART0_BASE),
- .mapbase = (unsigned long)DAVINCI_UART0_BASE,
+ .mapbase = DAVINCI_UART0_BASE,
.irq = IRQ_UARTINT0,
- .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+ UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ },
+ {
+ .mapbase = DAVINCI_UART1_BASE,
+ .irq = IRQ_UARTINT1,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+ UPF_IOREMAP,
+ .iotype = UPIO_MEM,
+ .regshift = 2,
+ },
+ {
+ .mapbase = DAVINCI_UART2_BASE,
+ .irq = IRQ_UARTINT2,
+ .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
+ UPF_IOREMAP,
.iotype = UPIO_MEM,
.regshift = 2,
- .uartclk = 27000000,
},
{
.flags = 0
static void __init davinci_serial_reset(struct plat_serial8250_port *p)
{
- /* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
unsigned int pwremu = 0;
- davinci_serial_outp(p, UART_IER, 0); /* disable all interrupts */
+ serial_write_reg(p, UART_IER, 0); /* disable all interrupts */
- davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu);
+ /* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
+ serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu);
mdelay(10);
pwremu |= (0x3 << 13);
pwremu |= 0x1;
- davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu);
+ serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu);
+
+ if (cpu_is_davinci_dm646x())
+ serial_write_reg(p, UART_DM646X_SCR,
+ UART_DM646X_SCR_TX_WATERMARK);
+}
+
+void __init davinci_serial_init(struct davinci_uart_config *info)
+{
+ int i;
+ char name[16];
+ struct clk *uart_clk;
+ struct device *dev = &serial_device.dev;
+
+ /*
+ * Make sure the serial ports are muxed on at this point.
+ * You have to mux them off in device drivers later on
+ * if not needed.
+ */
+ for (i = 0; i < DAVINCI_MAX_NR_UARTS; i++) {
+ struct plat_serial8250_port *p = serial_platform_data + i;
+
+ if (!(info->enabled_uarts & (1 << i))) {
+ p->flags = 0;
+ continue;
+ }
+
+ if (cpu_is_davinci_dm646x())
+ p->iotype = UPIO_MEM32;
+
+ if (cpu_is_davinci_dm355()) {
+ if (i == 2) {
+ p->mapbase = (unsigned long)DM355_UART2_BASE;
+ p->irq = IRQ_DM355_UARTINT2;
+ }
+ }
+
+ sprintf(name, "uart%d", i);
+ uart_clk = clk_get(dev, name);
+ if (IS_ERR(uart_clk))
+ printk(KERN_ERR "%s:%d: failed to get UART%d clock\n",
+ __func__, __LINE__, i);
+ else {
+ clk_enable(uart_clk);
+ p->uartclk = clk_get_rate(uart_clk);
+ davinci_serial_reset(p);
+ }
+ }
}
static int __init davinci_init(void)
{
- davinci_serial_reset(&serial_platform_data[0]);
return platform_device_register(&serial_device);
}
#include <linux/clockchips.h>
#include <linux/spinlock.h>
#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/device.h>
#include <mach/hardware.h>
#include <asm/system.h>
#include <asm/mach/time.h>
#include <asm/errno.h>
#include <mach/io.h>
+#include <mach/cputype.h>
+#include "clock.h"
static struct clock_event_device clockevent_davinci;
+static unsigned int davinci_clock_tick_rate;
#define DAVINCI_TIMER0_BASE (IO_PHYS + 0x21400)
#define DAVINCI_TIMER1_BASE (IO_PHYS + 0x21800)
unsigned int id;
unsigned long period;
unsigned long opts;
- unsigned long reg_base;
- unsigned long tim_reg;
- unsigned long prd_reg;
+ void __iomem *base;
+ unsigned long tim_off;
+ unsigned long prd_off;
unsigned long enamode_shift;
struct irqaction irqaction;
};
static int timer32_config(struct timer_s *t)
{
- u32 tcr = davinci_readl(t->reg_base + TCR);
+ u32 tcr = __raw_readl(t->base + TCR);
/* disable timer */
tcr &= ~(TCR_ENAMODE_MASK << t->enamode_shift);
- davinci_writel(tcr, t->reg_base + TCR);
+ __raw_writel(tcr, t->base + TCR);
/* reset counter to zero, set new period */
- davinci_writel(0, t->tim_reg);
- davinci_writel(t->period, t->prd_reg);
+ __raw_writel(0, t->base + t->tim_off);
+ __raw_writel(t->period, t->base + t->prd_off);
/* Set enable mode */
if (t->opts & TIMER_OPTS_ONESHOT) {
tcr |= TCR_ENAMODE_PERIODIC << t->enamode_shift;
}
- davinci_writel(tcr, t->reg_base + TCR);
+ __raw_writel(tcr, t->base + TCR);
return 0;
}
static inline u32 timer32_read(struct timer_s *t)
{
- return davinci_readl(t->tim_reg);
+ return __raw_readl(t->base + t->tim_off);
}
static irqreturn_t timer_interrupt(int irq, void *dev_id)
static void __init timer_init(void)
{
- u32 bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE};
+ u32 phys_bases[] = {DAVINCI_TIMER0_BASE, DAVINCI_TIMER1_BASE};
int i;
/* Global init of each 64-bit timer as a whole */
for(i=0; i<2; i++) {
- u32 tgcr, base = bases[i];
+ u32 tgcr;
+ void __iomem *base = IO_ADDRESS(phys_bases[i]);
/* Disabled, Internal clock source */
- davinci_writel(0, base + TCR);
+ __raw_writel(0, base + TCR);
/* reset both timers, no pre-scaler for timer34 */
tgcr = 0;
- davinci_writel(tgcr, base + TGCR);
+ __raw_writel(tgcr, base + TGCR);
/* Set both timers to unchained 32-bit */
tgcr = TGCR_TIMMODE_32BIT_UNCHAINED << TGCR_TIMMODE_SHIFT;
- davinci_writel(tgcr, base + TGCR);
+ __raw_writel(tgcr, base + TGCR);
/* Unreset timers */
tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
- davinci_writel(tgcr, base + TGCR);
+ __raw_writel(tgcr, base + TGCR);
/* Init both counters to zero */
- davinci_writel(0, base + TIM12);
- davinci_writel(0, base + TIM34);
+ __raw_writel(0, base + TIM12);
+ __raw_writel(0, base + TIM34);
}
/* Init of each timer as a 32-bit timer */
for (i=0; i< ARRAY_SIZE(timers); i++) {
struct timer_s *t = &timers[i];
+ u32 phys_base;
if (t->name) {
t->id = i;
- t->reg_base = (IS_TIMER1(t->id) ?
+ phys_base = (IS_TIMER1(t->id) ?
DAVINCI_TIMER1_BASE : DAVINCI_TIMER0_BASE);
+ t->base = IO_ADDRESS(phys_base);
if (IS_TIMER_BOT(t->id)) {
t->enamode_shift = 6;
- t->tim_reg = t->reg_base + TIM12;
- t->prd_reg = t->reg_base + PRD12;
+ t->tim_off = TIM12;
+ t->prd_off = PRD12;
} else {
t->enamode_shift = 22;
- t->tim_reg = t->reg_base + TIM34;
- t->prd_reg = t->reg_base + PRD34;
+ t->tim_off = TIM34;
+ t->prd_off = PRD34;
}
/* Register interrupt */
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
- t->period = CLOCK_TICK_RATE / (HZ);
+ t->period = davinci_clock_tick_rate / (HZ);
t->opts = TIMER_OPTS_PERIODIC;
timer32_config(t);
break;
static void __init davinci_timer_init(void)
{
+ struct clk *timer_clk;
+
static char err[] __initdata = KERN_ERR
"%s: can't register clocksource!\n";
/* init timer hw */
timer_init();
+ timer_clk = clk_get(NULL, "timer0");
+ BUG_ON(IS_ERR(timer_clk));
+ clk_enable(timer_clk);
+
+ davinci_clock_tick_rate = clk_get_rate(timer_clk);
+
/* setup clocksource */
clocksource_davinci.mult =
- clocksource_khz2mult(CLOCK_TICK_RATE/1000,
+ clocksource_khz2mult(davinci_clock_tick_rate/1000,
clocksource_davinci.shift);
if (clocksource_register(&clocksource_davinci))
printk(err, clocksource_davinci.name);
/* setup clockevent */
- clockevent_davinci.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
+ clockevent_davinci.mult = div_sc(davinci_clock_tick_rate, NSEC_PER_SEC,
clockevent_davinci.shift);
clockevent_davinci.max_delta_ns =
clockevent_delta2ns(0xfffffffe, &clockevent_davinci);
/* reset board using watchdog timer */
void davinci_watchdog_reset(void) {
- u32 tgcr, wdtcr, base = DAVINCI_WDOG_BASE;
+ u32 tgcr, wdtcr;
+ void __iomem *base = IO_ADDRESS(DAVINCI_WDOG_BASE);
+ struct device dev;
+ struct clk *wd_clk;
+ char *name = "watchdog";
+
+ dev_set_name(&dev, name);
+ wd_clk = clk_get(&dev, NULL);
+ if (WARN_ON(IS_ERR(wd_clk)))
+ return;
+ clk_enable(wd_clk);
/* disable, internal clock source */
- davinci_writel(0, base + TCR);
+ __raw_writel(0, base + TCR);
/* reset timer, set mode to 64-bit watchdog, and unreset */
tgcr = 0;
- davinci_writel(tgcr, base + TCR);
+ __raw_writel(tgcr, base + TCR);
tgcr = TGCR_TIMMODE_64BIT_WDOG << TGCR_TIMMODE_SHIFT;
tgcr |= (TGCR_UNRESET << TGCR_TIM12RS_SHIFT) |
(TGCR_UNRESET << TGCR_TIM34RS_SHIFT);
- davinci_writel(tgcr, base + TCR);
+ __raw_writel(tgcr, base + TCR);
/* clear counter and period regs */
- davinci_writel(0, base + TIM12);
- davinci_writel(0, base + TIM34);
- davinci_writel(0, base + PRD12);
- davinci_writel(0, base + PRD34);
+ __raw_writel(0, base + TIM12);
+ __raw_writel(0, base + TIM34);
+ __raw_writel(0, base + PRD12);
+ __raw_writel(0, base + PRD34);
/* enable */
- wdtcr = davinci_readl(base + WDTCR);
+ wdtcr = __raw_readl(base + WDTCR);
wdtcr |= WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT;
- davinci_writel(wdtcr, base + WDTCR);
+ __raw_writel(wdtcr, base + WDTCR);
/* put watchdog in pre-active state */
wdtcr = (WDTCR_WDKEY_SEQ0 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
- davinci_writel(wdtcr, base + WDTCR);
+ __raw_writel(wdtcr, base + WDTCR);
/* put watchdog in active state */
wdtcr = (WDTCR_WDKEY_SEQ1 << WDTCR_WDKEY_SHIFT) |
(WDTCR_WDEN_ENABLE << WDTCR_WDEN_SHIFT);
- davinci_writel(wdtcr, base + WDTCR);
+ __raw_writel(wdtcr, base + WDTCR);
/* write an invalid value to the WDKEY field to trigger
* a watchdog reset */
wdtcr = 0x00004000;
- davinci_writel(wdtcr, base + WDTCR);
+ __raw_writel(wdtcr, base + WDTCR);
}
#include <mach/hardware.h>
#include <mach/irqs.h>
+#define DAVINCI_USB_OTG_BASE 0x01C64000
+
#if defined(CONFIG_USB_MUSB_HDRC) || defined(CONFIG_USB_MUSB_HDRC_MODULE)
static struct musb_hdrc_eps_bits musb_eps[] = {
{ "ep1_tx", 8, },
static int mmc_set_power(struct device *dev, int slot, int power_on,
int vdd)
{
- if (power_on)
- gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 1);
- else
- gpio_direction_output(H2_TPS_GPIO_MMC_PWR_EN, 0);
-
+ gpio_set_value(H2_TPS_GPIO_MMC_PWR_EN, power_on);
return 0;
}
static int mmc_late_init(struct device *dev)
{
- int ret;
-
- ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
+ int ret = gpio_request(H2_TPS_GPIO_MMC_PWR_EN, "MMC power");
if (ret < 0)
return ret;
return ret;
}
-static void mmc_shutdown(struct device *dev)
+static void mmc_cleanup(struct device *dev)
{
gpio_free(H2_TPS_GPIO_MMC_PWR_EN);
}
static struct omap_mmc_platform_data mmc1_data = {
.nr_slots = 1,
.init = mmc_late_init,
- .shutdown = mmc_shutdown,
+ .cleanup = mmc_cleanup,
.dma_mask = 0xffffffff,
.slots[0] = {
.set_power = mmc_set_power,
static int mmc_set_power(struct device *dev, int slot, int power_on,
int vdd)
{
- if (power_on)
- gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 1);
- else
- gpio_direction_output(H3_TPS_GPIO_MMC_PWR_EN, 0);
-
+ gpio_set_value(H3_TPS_GPIO_MMC_PWR_EN, power_on);
return 0;
}
#include <asm/mach/flash.h>
#include <asm/mach/map.h>
-#include <mach/gpioexpander.h>
#include <mach/irqs.h>
#include <mach/mux.h>
#include <mach/tc.h>
#include <mach/nand.h>
-#include <mach/irda.h>
#include <mach/usb.h>
#include <mach/keypad.h>
#include <mach/dma.h>
.resource = h3_kp_resources,
};
-
-/* Select between the IrDA and aGPS module
- */
-static int h3_select_irda(struct device *dev, int state)
-{
- unsigned char expa;
- int err = 0;
-
- if ((err = read_gpio_expa(&expa, 0x26))) {
- printk(KERN_ERR "Error reading from I/O EXPANDER \n");
- return err;
- }
-
- /* 'P6' enable/disable IRDA_TX and IRDA_RX */
- if (state & IR_SEL) { /* IrDA */
- if ((err = write_gpio_expa(expa | 0x40, 0x26))) {
- printk(KERN_ERR "Error writing to I/O EXPANDER \n");
- return err;
- }
- } else {
- if ((err = write_gpio_expa(expa & ~0x40, 0x26))) {
- printk(KERN_ERR "Error writing to I/O EXPANDER \n");
- return err;
- }
- }
- return err;
-}
-
-static void set_trans_mode(struct work_struct *work)
-{
- struct omap_irda_config *irda_config =
- container_of(work, struct omap_irda_config, gpio_expa.work);
- int mode = irda_config->mode;
- unsigned char expa;
- int err = 0;
-
- if ((err = read_gpio_expa(&expa, 0x27)) != 0) {
- printk(KERN_ERR "Error reading from I/O expander\n");
- }
-
- expa &= ~0x03;
-
- if (mode & IR_SIRMODE) {
- expa |= 0x01;
- } else { /* MIR/FIR */
- expa |= 0x03;
- }
-
- if ((err = write_gpio_expa(expa, 0x27)) != 0) {
- printk(KERN_ERR "Error writing to I/O expander\n");
- }
-}
-
-static int h3_transceiver_mode(struct device *dev, int mode)
-{
- struct omap_irda_config *irda_config = dev->platform_data;
-
- irda_config->mode = mode;
- cancel_delayed_work(&irda_config->gpio_expa);
- PREPARE_DELAYED_WORK(&irda_config->gpio_expa, set_trans_mode);
- schedule_delayed_work(&irda_config->gpio_expa, 0);
-
- return 0;
-}
-
-static struct omap_irda_config h3_irda_data = {
- .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
- .transceiver_mode = h3_transceiver_mode,
- .select_irda = h3_select_irda,
- .rx_channel = OMAP_DMA_UART3_RX,
- .tx_channel = OMAP_DMA_UART3_TX,
- .dest_start = UART3_THR,
- .src_start = UART3_RHR,
- .tx_trigger = 0,
- .rx_trigger = 0,
-};
-
-static struct resource h3_irda_resources[] = {
- [0] = {
- .start = INT_UART3,
- .end = INT_UART3,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static u64 irda_dmamask = 0xffffffff;
-
-static struct platform_device h3_irda_device = {
- .name = "omapirda",
- .id = 0,
- .dev = {
- .platform_data = &h3_irda_data,
- .dma_mask = &irda_dmamask,
- },
- .num_resources = ARRAY_SIZE(h3_irda_resources),
- .resource = h3_irda_resources,
-};
-
static struct platform_device h3_lcd_device = {
.name = "lcd_h3",
.id = -1,
&nand_device,
&smc91x_device,
&intlat_device,
- &h3_irda_device,
&h3_kp_device,
&h3_lcd_device,
};
static int nokia770_mmc_set_power(struct device *dev, int slot, int power_on,
int vdd)
{
- if (power_on)
- gpio_set_value(NOKIA770_GPIO_MMC_POWER, 1);
- else
- gpio_set_value(NOKIA770_GPIO_MMC_POWER, 0);
-
+ gpio_set_value(NOKIA770_GPIO_MMC_POWER, power_on);
return 0;
}
*/
if (id == OMAP_MCBSP1 || id == OMAP_MCBSP3) {
if (dsp_use++ == 0) {
- api_clk = clk_get(NULL, "api_clk");
- dsp_clk = clk_get(NULL, "dsp_clk");
+ api_clk = clk_get(NULL, "api_ck");
+ dsp_clk = clk_get(NULL, "dsp_ck");
if (!IS_ERR(api_clk) && !IS_ERR(dsp_clk)) {
clk_enable(api_clk);
clk_enable(dsp_clk);
#include <mach/control.h>
#include <mach/gpio.h>
-#include <mach/gpioexpander.h>
#include <mach/mux.h>
#include <mach/usb.h>
-#include <mach/irda.h>
#include <mach/board.h>
#include <mach/common.h>
#include <mach/keypad.h>
.resource = &h4_flash_resource,
};
-/* Select between the IrDA and aGPS module
- */
-static int h4_select_irda(struct device *dev, int state)
-{
- unsigned char expa;
- int err = 0;
-
- if ((err = read_gpio_expa(&expa, 0x21))) {
- printk(KERN_ERR "Error reading from I/O expander\n");
- return err;
- }
-
- /* 'P6' enable/disable IRDA_TX and IRDA_RX */
- if (state & IR_SEL) { /* IrDa */
- if ((err = write_gpio_expa(expa | 0x01, 0x21))) {
- printk(KERN_ERR "Error writing to I/O expander\n");
- return err;
- }
- } else {
- if ((err = write_gpio_expa(expa & ~0x01, 0x21))) {
- printk(KERN_ERR "Error writing to I/O expander\n");
- return err;
- }
- }
- return err;
-}
-
-static void set_trans_mode(struct work_struct *work)
-{
- struct omap_irda_config *irda_config =
- container_of(work, struct omap_irda_config, gpio_expa.work);
- int mode = irda_config->mode;
- unsigned char expa;
- int err = 0;
-
- if ((err = read_gpio_expa(&expa, 0x20)) != 0) {
- printk(KERN_ERR "Error reading from I/O expander\n");
- }
-
- expa &= ~0x01;
-
- if (!(mode & IR_SIRMODE)) { /* MIR/FIR */
- expa |= 0x01;
- }
-
- if ((err = write_gpio_expa(expa, 0x20)) != 0) {
- printk(KERN_ERR "Error writing to I/O expander\n");
- }
-}
-
-static int h4_transceiver_mode(struct device *dev, int mode)
-{
- struct omap_irda_config *irda_config = dev->platform_data;
-
- irda_config->mode = mode;
- cancel_delayed_work(&irda_config->gpio_expa);
- PREPARE_DELAYED_WORK(&irda_config->gpio_expa, set_trans_mode);
- schedule_delayed_work(&irda_config->gpio_expa, 0);
-
- return 0;
-}
-
-static struct omap_irda_config h4_irda_data = {
- .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE,
- .transceiver_mode = h4_transceiver_mode,
- .select_irda = h4_select_irda,
- .rx_channel = OMAP24XX_DMA_UART3_RX,
- .tx_channel = OMAP24XX_DMA_UART3_TX,
- .dest_start = OMAP_UART3_BASE,
- .src_start = OMAP_UART3_BASE,
- .tx_trigger = OMAP24XX_DMA_UART3_TX,
- .rx_trigger = OMAP24XX_DMA_UART3_RX,
-};
-
-static struct resource h4_irda_resources[] = {
- [0] = {
- .start = INT_24XX_UART3_IRQ,
- .end = INT_24XX_UART3_IRQ,
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device h4_irda_device = {
- .name = "omapirda",
- .id = -1,
- .dev = {
- .platform_data = &h4_irda_data,
- },
- .num_resources = 1,
- .resource = h4_irda_resources,
-};
-
static struct omap_kp_platform_data h4_kp_data = {
.rows = 6,
.cols = 7,
static struct platform_device *h4_devices[] __initdata = {
&h4_flash_device,
- &h4_irda_device,
&h4_kp_device,
&h4_lcd_device,
};
#include <mach/nand.h>
#include <mach/mux.h>
#include <mach/usb.h>
+#include <mach/timer-gp.h>
#include "mmc-twl4030.h"
{
omap2_init_common_hw(NULL);
omap_init_irq();
+#ifdef CONFIG_OMAP_32K_TIMER
+ omap2_gp_clockevent_set_gptimer(12);
+#endif
omap_gpio_init();
}
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
-#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/hardware.h>
}, \
}
-#define CK_243X (1 << 0)
-#define CK_242X (1 << 1)
+#define CK_243X RATE_IN_243X
+#define CK_242X RATE_IN_242X
static struct omap_clk omap24xx_clks[] = {
/* external root sources */
CLK(NULL, "func_32k_ck", &func_32k_ck, CK_243X | CK_242X),
+ CLK(NULL, "secure_32k_ck", &secure_32k_ck, CK_243X | CK_242X),
CLK(NULL, "osc_ck", &osc_ck, CK_243X | CK_242X),
CLK(NULL, "sys_ck", &sys_ck, CK_243X | CK_242X),
CLK(NULL, "alt_ck", &alt_ck, CK_243X | CK_242X),
{
struct prcm_config *prcm;
struct omap_clk *c;
- u32 clkrate, cpu_mask;
+ u32 clkrate;
if (cpu_is_omap242x())
cpu_mask = RATE_IN_242X;
clk_init(&omap2_clk_functions);
+ for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
+ clk_init_one(c->lk.clk);
+
osc_ck.rate = omap2_osc_clk_recalc(&osc_ck);
propagate_rate(&osc_ck);
sys_ck.rate = omap2_sys_clk_recalc(&sys_ck);
propagate_rate(&sys_ck);
- for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
- clk_init_one(c->lk.clk);
-
- cpu_mask = 0;
- if (cpu_is_omap2420())
- cpu_mask |= CK_242X;
- if (cpu_is_omap2430())
- cpu_mask |= CK_243X;
-
for (c = omap24xx_clks; c < omap24xx_clks + ARRAY_SIZE(omap24xx_clks); c++)
if (c->cpu & cpu_mask) {
clkdev_add(&c->lk);
.clkdm_name = "wkup_clkdm",
};
+static struct clk secure_32k_ck = {
+ .name = "secure_32k_ck",
+ .ops = &clkops_null,
+ .rate = 32768,
+ .flags = RATE_FIXED,
+ .clkdm_name = "wkup_clkdm",
+};
+
/* Typical 12/13MHz in standalone mode, will be 26Mhz in chassis mode */
static struct clk osc_ck = { /* (*12, *13, 19.2, *26, 38.4)MHz */
.name = "osc_ck",
static struct clk gpt12_fck = {
.name = "gpt12_fck",
.ops = &clkops_omap2_dflt_wait,
- .parent = &func_32k_ck,
+ .parent = &secure_32k_ck,
.clkdm_name = "core_l4_clkdm",
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
.enable_bit = OMAP24XX_EN_GPT12_SHIFT,
static struct clk cam_mclk = {
.name = "cam_mclk",
- .ops = &clkops_omap2_dflt_wait,
+ .ops = &clkops_omap2_dflt,
.parent = &dpll4_m5x2_ck,
.enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
.enable_bit = OMAP3430_EN_CAM_SHIFT,
static struct clk cam_ick = {
/* Handles both L3 and L4 clocks */
.name = "cam_ick",
- .ops = &clkops_omap2_dflt_wait,
+ .ops = &clkops_omap2_dflt,
.parent = &l4_ick,
.init = &omap2_init_clk_clkdm,
.enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
static struct clk csi2_96m_fck = {
.name = "csi2_96m_fck",
- .ops = &clkops_omap2_dflt_wait,
+ .ops = &clkops_omap2_dflt,
.parent = &core_96m_fck,
.init = &omap2_init_clk_clkdm,
.enable_reg = OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_FCLKEN),
/* SECURE_32K_FCK clocks */
-/* XXX This clock no longer exists in 3430 TRM rev F */
static struct clk gpt12_fck = {
.name = "gpt12_fck",
.ops = &clkops_null,
#include <mach/board.h>
#include <mach/mux.h>
#include <mach/gpio.h>
-#include <mach/eac.h>
#include <mach/mmc.h>
#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
static inline void omap_init_mcspi(void) {}
#endif
-#ifdef CONFIG_SND_OMAP24XX_EAC
-
-#define OMAP2_EAC_BASE 0x48090000
-
-static struct resource omap2_eac_resources[] = {
- {
- .start = OMAP2_EAC_BASE,
- .end = OMAP2_EAC_BASE + 0x109,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct platform_device omap2_eac_device = {
- .name = "omap24xx-eac",
- .id = -1,
- .num_resources = ARRAY_SIZE(omap2_eac_resources),
- .resource = omap2_eac_resources,
- .dev = {
- .platform_data = NULL,
- },
-};
-
-void omap_init_eac(struct eac_platform_data *pdata)
-{
- omap2_eac_device.dev.platform_data = pdata;
- platform_device_register(&omap2_eac_device);
-}
-
-#else
-void omap_init_eac(struct eac_platform_data *pdata) {}
-#endif
-
#ifdef CONFIG_OMAP_SHA1_MD5
static struct resource sha1_md5_resources[] = {
{
u32 sir, spurious;
sir = intc_bank_read_reg(&irq_banks[0], INTC_SIR);
- spurious = sir >> 6;
+ spurious = sir >> 7;
- if (spurious > 1) {
+ if (spurious) {
printk(KERN_WARNING "Spurious irq %i: 0x%08x, please flush "
"posted write for irq %i\n",
irq, sir, previous_irq);
*
* OMAP2 GP timer support.
*
+ * Copyright (C) 2009 Nokia Corporation
+ *
* Update to use new clocksource/clockevent layers
* Author: Kevin Hilman, MontaVista Software, Inc. <source@mvista.com>
* Copyright (C) 2007 MontaVista Software, Inc.
#include <asm/mach/time.h>
#include <mach/dmtimer.h>
+/* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
+#define MAX_GPTIMER_ID 12
+
static struct omap_dm_timer *gptimer;
static struct clock_event_device clockevent_gpt;
+static u8 __initdata gptimer_id = 1;
+static u8 __initdata inited;
static irqreturn_t omap2_gp_timer_interrupt(int irq, void *dev_id)
{
.set_mode = omap2_gp_timer_set_mode,
};
+/**
+ * omap2_gp_clockevent_set_gptimer - set which GPTIMER is used for clockevents
+ * @id: GPTIMER to use (1..MAX_GPTIMER_ID)
+ *
+ * Define the GPTIMER that the system should use for the tick timer.
+ * Meant to be called from board-*.c files in the event that GPTIMER1, the
+ * default, is unsuitable. Returns -EINVAL on error or 0 on success.
+ */
+int __init omap2_gp_clockevent_set_gptimer(u8 id)
+{
+ if (id < 1 || id > MAX_GPTIMER_ID)
+ return -EINVAL;
+
+ BUG_ON(inited);
+
+ gptimer_id = id;
+
+ return 0;
+}
+
static void __init omap2_gp_clockevent_init(void)
{
u32 tick_rate;
+ int src;
+
+ inited = 1;
- gptimer = omap_dm_timer_request_specific(1);
+ gptimer = omap_dm_timer_request_specific(gptimer_id);
BUG_ON(gptimer == NULL);
#if defined(CONFIG_OMAP_32K_TIMER)
- omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_32_KHZ);
+ src = OMAP_TIMER_SRC_32_KHZ;
#else
- omap_dm_timer_set_source(gptimer, OMAP_TIMER_SRC_SYS_CLK);
+ src = OMAP_TIMER_SRC_SYS_CLK;
+ WARN(gptimer_id == 12, "WARNING: GPTIMER12 can only use the "
+ "secure 32KiHz clock source\n");
#endif
+
+ if (gptimer_id != 12)
+ WARN(IS_ERR_VALUE(omap_dm_timer_set_source(gptimer, src)),
+ "timer-gp: omap_dm_timer_set_source() failed\n");
+
tick_rate = clk_get_rate(omap_dm_timer_get_fclk(gptimer));
+ pr_info("OMAP clockevent source: GPTIMER%d at %u Hz\n",
+ gptimer_id, tick_rate);
+
omap2_gp_timer_irq.dev_id = (void *)gptimer;
setup_irq(omap_dm_timer_get_irq(gptimer), &omap2_gp_timer_irq);
omap_dm_timer_set_int_enable(gptimer, OMAP_TIMER_INT_OVERFLOW);
clockevents_register_device(&clockevent_gpt);
}
+/* Clocksource code */
+
#ifdef CONFIG_OMAP_32K_TIMER
/*
* When 32k-timer is enabled, don't use GPTimer for clocksource
unsigned sysclk_ps;
int status;
- if (!refclk_psec)
+ if (!refclk_psec || sysclk_ps == 0)
return -ENODEV;
sysclk_ps = is_refclk ? refclk_psec : TUSB6010_OSCCLK_60;
config MACH_TAVOREVB
bool "PXA930 Evaluation Board (aka TavorEVB)"
select PXA3xx
- select PXA930
+ select CPU_PXA930
config MACH_SAAR
bool "PXA930 Handheld Platform (aka SAAR)"
select PXA3xx
- select PXA930
+ select CPU_PXA930
config MACH_ARMCORE
bool "CompuLab CM-X255/CM-X270 modules"
.num_chipselect = 3,
};
+static void corgi_wait_for_hsync(void)
+{
+ while (gpio_get_value(CORGI_GPIO_HSYNC))
+ cpu_relax();
+
+ while (!gpio_get_value(CORGI_GPIO_HSYNC))
+ cpu_relax();
+}
+
static struct ads7846_platform_data corgi_ads7846_info = {
.model = 7846,
.vref_delay_usecs = 100,
.x_plate_ohms = 419,
.y_plate_ohms = 486,
.gpio_pendown = CORGI_GPIO_TP_INT,
+ .wait_for_sync = corgi_wait_for_hsync,
};
static void corgi_ads7846_cs(u32 command)
},
};
+static struct da9034_touch_pdata littleton_da9034_touch = {
+ .x_inverted = 1,
+ .interval_ms = 20,
+};
+
static struct da903x_subdev_info littleton_da9034_subdevs[] = {
{
.name = "da903x-led",
}, {
.name = "da903x-backlight",
.id = DA9034_ID_WLED,
+ }, {
+ .name = "da9034-touch",
+ .id = DA9034_ID_TOUCH,
+ .platform_data = &littleton_da9034_touch,
},
};
.num_chipselect = 3,
};
+static void spitz_wait_for_hsync(void)
+{
+ while (gpio_get_value(SPITZ_GPIO_HSYNC))
+ cpu_relax();
+
+ while (!gpio_get_value(SPITZ_GPIO_HSYNC))
+ cpu_relax();
+}
+
static struct ads7846_platform_data spitz_ads7846_info = {
.model = 7846,
.vref_delay_usecs = 100,
.x_plate_ohms = 419,
.y_plate_ohms = 486,
.gpio_pendown = SPITZ_GPIO_TP_INT,
+ .wait_for_sync = spitz_wait_for_hsync,
};
static void spitz_ads7846_cs(u32 command)
GPIO25_AC97_SDATA_IN_0,
GPIO27_AC97_SDATA_OUT,
GPIO28_AC97_SYNC,
+ GPIO17_GPIO, /* SDATA_IN_1 but unused - configure to GPIO */
/* SSP3 */
GPIO91_SSP3_SCLK,
/* Standard I2C */
GPIO21_I2C_SCL,
GPIO22_I2C_SDA,
+
+ /* GPIO */
+ GPIO18_GPIO, /* GPIO Expander #0 INT_N */
+ GPIO19_GPIO, /* GPIO Expander #1 INT_N */
};
static mfp_cfg_t pxa300_mfp_cfg[] __initdata = {
GPIO38_AC97_SYNC,
GPIO39_AC97_BITCLK,
GPIO40_AC97_nACRESET,
+ GPIO36_GPIO, /* SDATA_IN_1 but unused - configure to GPIO */
/* SSP3 */
GPIO89_SSP3_SCLK,
#include <linux/io.h>
#include <mach/hardware.h>
+#include <asm/cacheflush.h>
#include <asm/irq.h>
#include <mach/regs-power.h>
{
unsigned long tmp;
+ flush_cache_all();
+
/* set our standby method to sleep */
tmp = __raw_readl(S3C2412_PWRCFG);
#define S3C64XX_PA_FB (0x77100000)
#define S3C64XX_PA_SYSCON (0x7E00F000)
+#define S3C64XX_PA_IIS0 (0x7F002000)
+#define S3C64XX_PA_IIS1 (0x7F003000)
#define S3C64XX_PA_TIMER (0x7F006000)
#define S3C64XX_PA_IIC0 (0x7F004000)
#define S3C64XX_PA_IIC1 (0x7F00F000)
#include <mach/hardware.h>
#include <asm/setup.h>
#include <asm/mach-types.h>
+#include <asm/page.h>
#include <asm/mach/arch.h>
#include <asm/mach/map.h>
#define D_CACHE_LINE_SIZE 32
#define BTB_FLUSH_SIZE 8
+#ifdef CONFIG_ARM_ERRATA_411920
+/*
+ * Invalidate the entire I cache (this code is a workaround for the ARM1136
+ * erratum 411920 - Invalidate Instruction Cache operation can fail. This
+ * erratum is present in 1136, 1156 and 1176. It does not affect the MPCore.
+ *
+ * Registers:
+ * r0 - set to 0
+ * r1 - corrupted
+ */
+ENTRY(v6_icache_inval_all)
+ mov r0, #0
+ mrs r1, cpsr
+ cpsid ifa @ disable interrupts
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
+ mcr p15, 0, r0, c7, c5, 0 @ invalidate entire I-cache
+ msr cpsr_cx, r1 @ restore interrupts
+ .rept 11 @ ARM Ltd recommends at least
+ nop @ 11 NOPs
+ .endr
+ mov pc, lr
+#endif
+
/*
* v6_flush_cache_all()
*
mov r0, #0
#ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c14, 0 @ D cache clean+invalidate
+#ifndef CONFIG_ARM_ERRATA_411920
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
+#else
+ b v6_icache_inval_all
+#endif
#else
mcr p15, 0, r0, c7, c15, 0 @ Cache clean+invalidate
#endif
mov r0, #0
#ifdef HARVARD_CACHE
mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
+#ifndef CONFIG_ARM_ERRATA_411920
mcr p15, 0, r0, c7, c5, 0 @ I+BTB cache invalidate
+#else
+ b v6_icache_inval_all
+#endif
#else
mcr p15, 0, r0, c7, c5, 6 @ invalidate BTB
#endif
#include "mm.h"
+#ifdef CONFIG_ARM_ERRATA_411920
+extern void v6_icache_inval_all(void);
+#endif
+
#ifdef CONFIG_CPU_CACHE_VIPT
#define ALIAS_FLUSH_START 0xffff4000
asm( "mcrr p15, 0, %1, %0, c14\n"
" mcr p15, 0, %2, c7, c10, 4\n"
+#ifndef CONFIG_ARM_ERRATA_411920
" mcr p15, 0, %2, c7, c5, 0\n"
+#endif
:
: "r" (to), "r" (to + PAGE_SIZE - L1_CACHE_BYTES), "r" (zero)
: "cc");
+#ifdef CONFIG_ARM_ERRATA_411920
+ v6_icache_inval_all();
+#endif
}
void flush_cache_mm(struct mm_struct *mm)
if (cache_is_vipt_aliasing()) {
asm( "mcr p15, 0, %0, c7, c14, 0\n"
+ " mcr p15, 0, %0, c7, c10, 4\n"
+#ifndef CONFIG_ARM_ERRATA_411920
" mcr p15, 0, %0, c7, c5, 0\n"
- " mcr p15, 0, %0, c7, c10, 4"
+#endif
:
: "r" (0)
: "cc");
+#ifdef CONFIG_ARM_ERRATA_411920
+ v6_icache_inval_all();
+#endif
}
}
if (cache_is_vipt_aliasing()) {
asm( "mcr p15, 0, %0, c7, c14, 0\n"
+ " mcr p15, 0, %0, c7, c10, 4\n"
+#ifndef CONFIG_ARM_ERRATA_411920
" mcr p15, 0, %0, c7, c5, 0\n"
- " mcr p15, 0, %0, c7, c10, 4"
+#endif
:
: "r" (0)
: "cc");
+#ifdef CONFIG_ARM_ERRATA_411920
+ v6_icache_inval_all();
+#endif
}
}
mov r2, #0
ldr r1, [r1, #MM_CONTEXT_ID] @ get mm->context.id
orr r0, r0, #TTB_FLAGS
+#ifdef CONFIG_ARM_ERRATA_430973
+ mcr p15, 0, r2, c7, c5, 6 @ flush BTAC/BTB
+#endif
mcr p15, 0, r2, c13, c0, 1 @ set reserved context ID
isb
1: mcr p15, 0, r0, c2, c0, 0 @ set TTB 0
stmia r12, {r0-r5, r7, r9, r11, lr}
bl v7_flush_dcache_all
ldmia r12, {r0-r5, r7, r9, r11, lr}
+#ifdef CONFIG_ARM_ERRATA_430973
+ mrc p15, 0, r10, c1, c0, 1 @ read aux control register
+ orr r10, r10, #(1 << 6) @ set IBE to 1
+ mcr p15, 0, r10, c1, c0, 1 @ write aux control register
+#endif
+#ifdef CONFIG_ARM_ERRATA_458693
+ mrc p15, 0, r10, c1, c0, 1 @ read aux control register
+ orr r10, r10, #(1 << 5) @ set L1NEON to 1
+ orr r10, r10, #(1 << 9) @ set PLDNOP to 1
+ mcr p15, 0, r10, c1, c0, 1 @ write aux control register
+#endif
+#ifdef CONFIG_ARM_ERRATA_460075
+ mrc p15, 1, r10, c9, c0, 2 @ read L2 cache aux ctrl register
+ orr r10, r10, #(1 << 22) @ set the Write Allocate disable bit
+ mcr p15, 1, r10, c9, c0, 2 @ write the L2 cache aux ctrl register
+#endif
mov r10, #0
#ifdef HARVARD_CACHE
mcr p15, 0, r10, c7, c5, 0 @ I+BTB cache invalidate
local_irq_restore(flags);
return -EBUSY;
}
+ memset(imxdma, 0, sizeof(imxdma));
+ imxdma->name = name;
+ local_irq_restore(flags); /* request_irq() can block */
#ifdef CONFIG_ARCH_MX2
ret = request_irq(MXC_INT_DMACH0 + channel, dma_irq_handler, 0, "DMA",
NULL);
if (ret) {
- local_irq_restore(flags);
+ imxdma->name = NULL;
printk(KERN_CRIT "Can't register IRQ %d for DMA channel %d\n",
MXC_INT_DMACH0 + channel, channel);
return ret;
imxdma->watchdog.data = channel;
#endif
- imxdma->name = name;
- imxdma->irq_handler = NULL;
- imxdma->err_handler = NULL;
- imxdma->data = NULL;
- imxdma->sg = NULL;
-
- local_irq_restore(flags);
return ret;
}
EXPORT_SYMBOL(imx_dma_request);
local_irq_save(flags);
/* Disable interrupts */
- __raw_writel(__raw_readl(DMA_BASE + DMA_DIMR) | (1 << channel),
- DMA_BASE + DMA_DIMR);
- __raw_writel(__raw_readl(DMA_BASE + DMA_CCR(channel)) & ~CCR_CEN,
- DMA_BASE + DMA_CCR(channel));
+ imx_dma_disable(channel);
imxdma->name = NULL;
#ifdef CONFIG_ARCH_MX2
irq_stat = __raw_readl(port->base + GPIO_ISR) &
__raw_readl(port->base + GPIO_IMR);
- BUG_ON(!irq_stat);
+
mxc_gpio_irq_handler(port, irq_stat);
}
#endif
/*
* Base address of PBC controller, CS4
*/
-#define PBC_BASE_ADDRESS 0xEB000000
+#define PBC_BASE_ADDRESS 0xf4300000
#define PBC_REG_ADDR(offset) (void __force __iomem *) \
(PBC_BASE_ADDRESS + (offset))
}
}
+/**
+ * clk_init_one - initialize any fields in the struct clk before clk init
+ * @clk: struct clk * to initialize
+ *
+ * Initialize any struct clk fields needed before normal clk initialization
+ * can run. No return value.
+ */
void clk_init_one(struct clk *clk)
{
INIT_LIST_HEAD(&clk->children);
{
unsigned long flags;
- spin_lock_irqsave(&dma_chan_lock, flags);
if (dma_chan[lch].dev_id == -1) {
pr_err("omap_dma: trying to free unallocated DMA channel %d\n",
lch);
- spin_unlock_irqrestore(&dma_chan_lock, flags);
return;
}
- dma_chan[lch].dev_id = -1;
- dma_chan[lch].next_lch = -1;
- dma_chan[lch].callback = NULL;
- spin_unlock_irqrestore(&dma_chan_lock, flags);
-
if (cpu_class_is_omap1()) {
/* Disable all DMA interrupts for the channel. */
dma_write(0, CICR(lch));
dma_write(0, CCR(lch));
omap_clear_dma(lch);
}
+
+ spin_lock_irqsave(&dma_chan_lock, flags);
+ dma_chan[lch].dev_id = -1;
+ dma_chan[lch].next_lch = -1;
+ dma_chan[lch].callback = NULL;
+ spin_unlock_irqrestore(&dma_chan_lock, flags);
}
EXPORT_SYMBOL(omap_free_dma);
{ .phys_base = 0x49040000, .irq = INT_24XX_GPTIMER9 },
{ .phys_base = 0x48086000, .irq = INT_24XX_GPTIMER10 },
{ .phys_base = 0x48088000, .irq = INT_24XX_GPTIMER11 },
- { .phys_base = 0x48304000, .irq = INT_24XX_GPTIMER12 },
+ { .phys_base = 0x48304000, .irq = INT_34XX_GPT12_IRQ },
};
static const char *omap3_dm_source_names[] __initdata = {
l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
/*
- * Enable wake-up only for GPT1 on OMAP2 CPUs.
- * FIXME: All timers should have wake-up enabled and clear
- * PRCM status.
+ * Enable wake-up on OMAP2 CPUs.
*/
- if (cpu_class_is_omap2() && (timer == &dm_timers[0]))
+ if (cpu_class_is_omap2())
l |= 1 << 2;
omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
#ifdef CONFIG_ARCH_OMAP1
-void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
int n = (timer - dm_timers) << 1;
u32 l;
l = omap_readl(MOD_CONF_CTRL_1) & ~(0x03 << n);
l |= source << n;
omap_writel(l, MOD_CONF_CTRL_1);
+
+ return 0;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
#else
-void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
+ int ret = -EINVAL;
+
if (source < 0 || source >= 3)
- return;
+ return -EINVAL;
clk_disable(timer->fclk);
- clk_set_parent(timer->fclk, dm_source_clocks[source]);
+ ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
clk_enable(timer->fclk);
- /* When the functional clock disappears, too quick writes seem to
- * cause an abort. */
+ /*
+ * When the functional clock disappears, too quick writes seem
+ * to cause an abort. XXX Is this still necessary?
+ */
__delay(150000);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
/* Workaround for clearing DSP GPIO interrupts to allow retention */
#if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX)
+ reg = bank->base + OMAP24XX_GPIO_IRQSTATUS2;
if (cpu_is_omap24xx() || cpu_is_omap34xx())
- __raw_writel(gpio_mask, bank->base + OMAP24XX_GPIO_IRQSTATUS2);
+ __raw_writel(gpio_mask, reg);
+
+ /* Flush posted write for the irq status to avoid spurious interrupts */
+ __raw_readl(reg);
#endif
}
case METHOD_MPUIO:
case METHOD_GPIO_1610:
spin_lock_irqsave(&bank->lock, flags);
- if (enable) {
+ if (enable)
bank->suspend_wakeup |= (1 << gpio);
- enable_irq_wake(bank->irq);
- } else {
- disable_irq_wake(bank->irq);
+ else
bank->suspend_wakeup &= ~(1 << gpio);
- }
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
#endif
return -EINVAL;
}
spin_lock_irqsave(&bank->lock, flags);
- if (enable) {
+ if (enable)
bank->suspend_wakeup |= (1 << gpio);
- enable_irq_wake(bank->irq);
- } else {
- disable_irq_wake(bank->irq);
+ else
bank->suspend_wakeup &= ~(1 << gpio);
- }
spin_unlock_irqrestore(&bank->lock, flags);
return 0;
#endif
void omap_dm_timer_start(struct omap_dm_timer *timer);
void omap_dm_timer_stop(struct omap_dm_timer *timer);
-void omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
+int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source);
void omap_dm_timer_set_load(struct omap_dm_timer *timer, int autoreload, unsigned int value);
void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload, unsigned int value);
void omap_dm_timer_set_match(struct omap_dm_timer *timer, int enable, unsigned int match);
+++ /dev/null
-/*
- * arch/arm/plat-omap/include/mach2/eac.h
- *
- * Defines for Enhanced Audio Controller
- *
- * Contact: Jarkko Nikula <jarkko.nikula@nokia.com>
- *
- * Copyright (C) 2006 Nokia Corporation
- * Copyright (C) 2004 Texas Instruments, Inc.
- *
- * 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __ASM_ARM_ARCH_OMAP2_EAC_H
-#define __ASM_ARM_ARCH_OMAP2_EAC_H
-
-#include <mach/io.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <sound/core.h>
-
-/* master codec clock source */
-#define EAC_MCLK_EXT_MASK 0x100
-enum eac_mclk_src {
- EAC_MCLK_INT_11290000, /* internal 96 MHz / 8.5 = 11.29 Mhz */
- EAC_MCLK_EXT_11289600 = EAC_MCLK_EXT_MASK,
- EAC_MCLK_EXT_12288000,
- EAC_MCLK_EXT_2x11289600,
- EAC_MCLK_EXT_2x12288000,
-};
-
-/* codec port interface mode */
-enum eac_codec_mode {
- EAC_CODEC_PCM,
- EAC_CODEC_AC97,
- EAC_CODEC_I2S_MASTER, /* codec port, I.e. EAC is the master */
- EAC_CODEC_I2S_SLAVE,
-};
-
-/* configuration structure for I2S mode */
-struct eac_i2s_conf {
- /* if enabled, then first data slot (left channel) is signaled as
- * positive level of frame sync EAC.AC_FS */
- unsigned polarity_changed_mode:1;
- /* if enabled, then serial data starts one clock cycle after the
- * of EAC.AC_FS for first audio slot */
- unsigned sync_delay_enable:1;
-};
-
-/* configuration structure for EAC codec port */
-struct eac_codec {
- enum eac_mclk_src mclk_src;
-
- enum eac_codec_mode codec_mode;
- union {
- struct eac_i2s_conf i2s;
- } codec_conf;
-
- int default_rate; /* audio sampling rate */
-
- int (* set_power)(void *private_data, int dac, int adc);
- int (* register_controls)(void *private_data,
- struct snd_card *card);
- const char *short_name;
-
- void *private_data;
-};
-
-/* structure for passing platform dependent data to the EAC driver */
-struct eac_platform_data {
- int (* init)(struct device *eac_dev);
- void (* cleanup)(struct device *eac_dev);
- /* these callbacks are used to configure & control external MCLK
- * source. NULL if not used */
- int (* enable_ext_clocks)(struct device *eac_dev);
- void (* disable_ext_clocks)(struct device *eac_dev);
-};
-
-extern void omap_init_eac(struct eac_platform_data *pdata);
-
-extern int eac_register_codec(struct device *eac_dev, struct eac_codec *codec);
-extern void eac_unregister_codec(struct device *eac_dev);
-
-extern int eac_set_mode(struct device *eac_dev, int play, int rec);
-
-#endif /* __ASM_ARM_ARCH_OMAP2_EAC_H */
+++ /dev/null
-/*
- * arch/arm/plat-omap/include/mach/gpioexpander.h
- *
- *
- * Copyright (C) 2004 Texas Instruments, Inc.
- *
- * This package 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.
- *
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#ifndef __ASM_ARCH_OMAP_GPIOEXPANDER_H
-#define __ASM_ARCH_OMAP_GPIOEXPANDER_H
-
-/* Function Prototypes for GPIO Expander functions */
-
-#ifdef CONFIG_GPIOEXPANDER_OMAP
-int read_gpio_expa(u8 *, int);
-int write_gpio_expa(u8 , int);
-#else
-static inline int read_gpio_expa(u8 *val, int addr)
-{
- return 0;
-}
-static inline int write_gpio_expa(u8 val, int addr)
-{
- return 0;
-}
-#endif
-
-#endif /* __ASM_ARCH_OMAP_GPIOEXPANDER_H */
int transceiver_cap;
int (*transceiver_mode)(struct device *dev, int mode);
int (*select_irda)(struct device *dev, int state);
- /* Very specific to the needs of some platforms (h3,h4)
- * having calls which can sleep in irda_set_speed.
- */
- struct delayed_work gpio_expa;
int rx_channel;
int tx_channel;
unsigned long dest_start;
/* use the internal clock */
unsigned internal_clock:1;
- s16 power_pin;
int switch_pin; /* gpio (card detect) */
int gpio_wp; /* gpio (write protect) */
--- /dev/null
+/*
+ * OMAP2/3 GPTIMER support.headers
+ *
+ * Copyright (C) 2009 Nokia Corporation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_TIMER_GP_H
+
+int __init omap2_gp_clockevent_set_gptimer(u8 id);
+
+#endif
+
return -ENOMEM;
}
+ memset(chips, 0, nbanks * sizeof(struct pxa_gpio_chip));
+
for (i = 0, gpio = 0; i < nbanks; i++, gpio += 32) {
struct gpio_chip *c = &chips[i].chip;
return 0;
}
+/* Update only those GRERx and GFERx edge detection register bits if those
+ * bits are set in c->irq_mask
+ */
+static inline void update_edge_detect(struct pxa_gpio_chip *c)
+{
+ uint32_t grer, gfer;
+
+ grer = __raw_readl(c->regbase + GRER_OFFSET) & ~c->irq_mask;
+ gfer = __raw_readl(c->regbase + GFER_OFFSET) & ~c->irq_mask;
+ grer |= c->irq_edge_rise & c->irq_mask;
+ gfer |= c->irq_edge_fall & c->irq_mask;
+ __raw_writel(grer, c->regbase + GRER_OFFSET);
+ __raw_writel(gfer, c->regbase + GFER_OFFSET);
+}
+
static int pxa_gpio_irq_type(unsigned int irq, unsigned int type)
{
struct pxa_gpio_chip *c;
else
c->irq_edge_fall &= ~mask;
- __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET);
- __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET);
+ update_edge_detect(c);
pr_debug("%s: IRQ%d (GPIO%d) - edge%s%s\n", __func__, irq, gpio,
((type & IRQ_TYPE_EDGE_RISING) ? " rising" : ""),
struct pxa_gpio_chip *c = gpio_to_chip(gpio);
c->irq_mask |= GPIO_bit(gpio);
- __raw_writel(c->irq_edge_rise & c->irq_mask, c->regbase + GRER_OFFSET);
- __raw_writel(c->irq_edge_fall & c->irq_mask, c->regbase + GFER_OFFSET);
+ update_edge_detect(c);
}
static struct irq_chip pxa_muxed_gpio_chip = {
drivers-$(CONFIG_OPROFILE) += arch/avr32/oprofile/
libs-y += arch/avr32/lib/
-CLEAN_FILES += include/asm-avr32/.arch include/asm-avr32/arch
-
BOOT_TARGETS := vmlinux.elf vmlinux.bin uImage uImage.srec
.PHONY: $(BOOT_TARGETS) install
--- /dev/null
+#ifndef _ASM_IA64_IDLE_H
+#define _ASM_IA64_IDLE_H
+
+static inline void enter_idle(void) { }
+static inline void exit_idle(void) { }
+
+#endif /* _ASM_IA64_IDLE_H */
return !(ia64_psr(regs)->i);
}
-static inline void xen_do_IRQ(int irq, struct pt_regs *regs)
+static inline void handle_irq(int irq, struct pt_regs *regs)
{
- struct pt_regs *old_regs;
- old_regs = set_irq_regs(regs);
- irq_enter();
__do_IRQ(irq);
- irq_exit();
- set_irq_regs(old_regs);
}
#define irq_ctx_init(cpu) do { } while (0)
#define isBP p3 // are we the Bootstrap Processor?
- .text
-
GLOBAL_ENTRY(xen_setup_hook)
mov r8=XEN_PV_DOMAIN_ASM
(isBP) movl r9=xen_domain_type;;
targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o \
piggy.o vmlinux.lds
-EXTRA_AFLAGS := -traditional
OBJECTS = $(obj)/head.o $(obj)/misc.o
* This file contains M32R architecture specific macro definitions.
*/
+#include <linux/stringify.h>
+
+#undef __STR
-#ifndef __STR
#ifdef __ASSEMBLY__
#define __STR(x) x
#else
-#define __STR(x) #x
+#define __STR(x) __stringify(x)
#endif
-#endif /* __STR */
#ifdef CONFIG_SMP
#define M32R_LOCK __STR(lock)
obj-$(CONFIG_SMP) += smp.o smpboot.o
obj-$(CONFIG_MODULES) += module.o
-
-EXTRA_AFLAGS := -traditional
{},
};
-/* Platform drivers register/unregister */
-static inline int of_register_platform_driver(struct of_platform_driver *drv)
-{
- return of_register_driver(drv, &of_platform_bus_type);
-}
-static inline void of_unregister_platform_driver(struct of_platform_driver *drv)
-{
- of_unregister_driver(drv);
-}
-
/* Platform devices and busses creation */
extern struct of_device *of_platform_device_create(struct device_node *np,
const char *bus_id,
default y if PMAC_APM_EMU
bool
+config DTC
+ bool
+ default y
+
config DEFAULT_UIMAGE
bool
help
BOOTCFLAGS += -fno-stack-protector
endif
-BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj) -I$(srctree)/$(src)/libfdt
+BOOTCFLAGS += -I$(obj) -I$(srctree)/$(obj)
DTS_FLAGS ?= -p 1024
$(addprefix $(obj)/,$(zlib) cuboot-c2k.o gunzip_util.o main.o prpmc2800.o): \
$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
-src-libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+libfdt := fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+libfdtheader := fdt.h libfdt.h libfdt_internal.h
+
+$(addprefix $(obj)/,$(libfdt) libfdt-wrapper.o simpleboot.o): \
+ $(addprefix $(obj)/,$(libfdtheader))
+
src-wlib := string.S crt0.S crtsavres.S stdio.c main.c \
- $(addprefix libfdt/,$(src-libfdt)) libfdt-wrapper.c \
+ $(libfdt) libfdt-wrapper.c \
ns16550.c serial.c simple_alloc.c div64.S util.S \
gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
$(addprefix $(obj)/,$(zliblinuxheader)): $(obj)/%: $(srctree)/include/linux/%
$(call cmd,copy_zliblinuxheader)
+quiet_cmd_copy_libfdt = COPY $@
+ cmd_copy_libfdt = cp $< $@
+
+$(addprefix $(obj)/,$(libfdt) $(libfdtheader)): $(obj)/%: $(srctree)/scripts/dtc/libfdt/%
+ $(call cmd,copy_libfdt)
+
$(obj)/empty.c:
@touch $@
@cp $< $@
clean-files := $(zlib) $(zlibheader) $(zliblinuxheader) \
+ $(libfdt) $(libfdtheader) \
empty.c zImage.coff.lds zImage.ps3.lds zImage.lds
quiet_cmd_bootcc = BOOTCC $@
quiet_cmd_bootar = BOOTAR $@
cmd_bootar = $(CROSS32AR) -cr $@.$$$$ $(filter-out FORCE,$^); mv $@.$$$$ $@
+$(obj-libfdt): $(obj)/%.o: $(srctree)/scripts/dtc/libfdt/%.c FORCE
+ $(call if_changed_dep,bootcc)
$(patsubst %.c,%.o, $(filter %.c, $(src-boot))): %.o: %.c FORCE
$(Q)mkdir -p $(dir $@)
$(call if_changed_dep,bootcc)
$(obj)/wrapper.a: $(obj-wlib) FORCE
$(call if_changed,bootar)
-hostprogs-y := addnote addRamDisk hack-coff mktree dtc
+hostprogs-y := addnote addRamDisk hack-coff mktree
targets += $(patsubst $(obj)/%,%,$(obj-boot) wrapper.a)
extra-y := $(obj)/wrapper.a $(obj-plat) $(obj)/empty.o \
dtstree := $(srctree)/$(src)/dts
wrapper :=$(srctree)/$(src)/wrapper
-wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree dtc) \
+wrapperbits := $(extra-y) $(addprefix $(obj)/,addnote hack-coff mktree) \
$(wrapper) FORCE
-#############
-# Bits for building dtc
-# DTC_GENPARSER := 1 # Uncomment to rebuild flex/bison output
-
-dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o srcpos.o checks.o
-dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
-dtc-objs := $(addprefix dtc-src/, $(dtc-objs))
-
-# prerequisites on generated files needs to be explicit
-$(obj)/dtc-src/dtc-parser.tab.o: $(obj)/dtc-src/dtc-parser.tab.c $(obj)/dtc-src/dtc-parser.tab.h
-$(obj)/dtc-src/dtc-lexer.lex.o: $(obj)/dtc-src/dtc-lexer.lex.c $(obj)/dtc-src/dtc-parser.tab.h
-
-HOSTCFLAGS += -I$(src)/dtc-src/ -I$(src)/libfdt/
-
-targets += dtc-src/dtc-parser.tab.c
-targets += dtc-src/dtc-lexer.lex.c
-
-clean-files += dtc-src/dtc-parser.tab.h
-
-ifdef DTC_GENPARSER
-BISON = bison
-FLEX = flex
-
-quiet_cmd_bison = BISON $@
- cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped
-quiet_cmd_flex = FLEX $@
- cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
-
-$(obj)/dtc-src/dtc-parser.tab.c: $(src)/dtc-src/dtc-parser.y FORCE
- $(call if_changed,bison)
-
-$(obj)/dtc-src/dtc-parser.tab.h: $(obj)/dtc-src/dtc-parser.tab.c
-
-$(obj)/dtc-src/dtc-lexer.lex.c: $(src)/dtc-src/dtc-lexer.l FORCE
- $(call if_changed,flex)
-endif
-
#############
# Bits for building various flavours of zImage
$(call if_changed,wrap,treeboot-$*,,$(obj)/$*.dtb)
# Rule to build device tree blobs
-$(obj)/%.dtb: $(dtstree)/%.dts $(obj)/dtc
- $(obj)/dtc -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts
+DTC = $(objtree)/scripts/dtc/dtc
+
+$(obj)/%.dtb: $(dtstree)/%.dts
+ $(DTC) -O dtb -o $(obj)/$*.dtb -b 0 $(DTS_FLAGS) $(dtstree)/$*.dts
# If there isn't a platform selected then just strip the vmlinux.
ifeq (,$(image-y))
+++ /dev/null
-# Makefile.dtc
-#
-# This is not a complete Makefile of itself. Instead, it is designed to
-# be easily embeddable into other systems of Makefiles.
-#
-DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
- checks.c
-DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
-DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
+++ /dev/null
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007.
- *
- *
- * 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 "dtc.h"
-
-#ifdef TRACE_CHECKS
-#define TRACE(c, ...) \
- do { \
- fprintf(stderr, "=== %s: ", (c)->name); \
- fprintf(stderr, __VA_ARGS__); \
- fprintf(stderr, "\n"); \
- } while (0)
-#else
-#define TRACE(c, fmt, ...) do { } while (0)
-#endif
-
-enum checklevel {
- IGNORE = 0,
- WARN = 1,
- ERROR = 2,
-};
-
-enum checkstatus {
- UNCHECKED = 0,
- PREREQ,
- PASSED,
- FAILED,
-};
-
-struct check;
-
-typedef void (*tree_check_fn)(struct check *c, struct node *dt);
-typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
-typedef void (*prop_check_fn)(struct check *c, struct node *dt,
- struct node *node, struct property *prop);
-
-struct check {
- const char *name;
- tree_check_fn tree_fn;
- node_check_fn node_fn;
- prop_check_fn prop_fn;
- void *data;
- enum checklevel level;
- enum checkstatus status;
- int inprogress;
- int num_prereqs;
- struct check **prereq;
-};
-
-#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
- static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
- static struct check nm = { \
- .name = #nm, \
- .tree_fn = (tfn), \
- .node_fn = (nfn), \
- .prop_fn = (pfn), \
- .data = (d), \
- .level = (lvl), \
- .status = UNCHECKED, \
- .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
- .prereq = nm##_prereqs, \
- };
-
-#define TREE_CHECK(nm, d, lvl, ...) \
- CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
-#define NODE_CHECK(nm, d, lvl, ...) \
- CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
-#define PROP_CHECK(nm, d, lvl, ...) \
- CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
-#define BATCH_CHECK(nm, lvl, ...) \
- CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
-
-#ifdef __GNUC__
-static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
-#endif
-static inline void check_msg(struct check *c, const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
-
- if ((c->level < WARN) || (c->level <= quiet))
- return; /* Suppress message */
-
- fprintf(stderr, "%s (%s): ",
- (c->level == ERROR) ? "ERROR" : "Warning", c->name);
- vfprintf(stderr, fmt, ap);
- fprintf(stderr, "\n");
-}
-
-#define FAIL(c, ...) \
- do { \
- TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
- (c)->status = FAILED; \
- check_msg((c), __VA_ARGS__); \
- } while (0)
-
-static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
-{
- struct node *child;
- struct property *prop;
-
- TRACE(c, "%s", node->fullpath);
- if (c->node_fn)
- c->node_fn(c, dt, node);
-
- if (c->prop_fn)
- for_each_property(node, prop) {
- TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
- c->prop_fn(c, dt, node, prop);
- }
-
- for_each_child(node, child)
- check_nodes_props(c, dt, child);
-}
-
-static int run_check(struct check *c, struct node *dt)
-{
- int error = 0;
- int i;
-
- assert(!c->inprogress);
-
- if (c->status != UNCHECKED)
- goto out;
-
- c->inprogress = 1;
-
- for (i = 0; i < c->num_prereqs; i++) {
- struct check *prq = c->prereq[i];
- error |= run_check(prq, dt);
- if (prq->status != PASSED) {
- c->status = PREREQ;
- check_msg(c, "Failed prerequisite '%s'",
- c->prereq[i]->name);
- }
- }
-
- if (c->status != UNCHECKED)
- goto out;
-
- if (c->node_fn || c->prop_fn)
- check_nodes_props(c, dt, dt);
-
- if (c->tree_fn)
- c->tree_fn(c, dt);
- if (c->status == UNCHECKED)
- c->status = PASSED;
-
- TRACE(c, "\tCompleted, status %d", c->status);
-
-out:
- c->inprogress = 0;
- if ((c->status != PASSED) && (c->level == ERROR))
- error = 1;
- return error;
-}
-
-/*
- * Utility check functions
- */
-
-static void check_is_string(struct check *c, struct node *root,
- struct node *node)
-{
- struct property *prop;
- char *propname = c->data;
-
- prop = get_property(node, propname);
- if (!prop)
- return; /* Not present, assumed ok */
-
- if (!data_is_one_string(prop->val))
- FAIL(c, "\"%s\" property in %s is not a string",
- propname, node->fullpath);
-}
-#define CHECK_IS_STRING(nm, propname, lvl) \
- CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
-
-static void check_is_cell(struct check *c, struct node *root,
- struct node *node)
-{
- struct property *prop;
- char *propname = c->data;
-
- prop = get_property(node, propname);
- if (!prop)
- return; /* Not present, assumed ok */
-
- if (prop->val.len != sizeof(cell_t))
- FAIL(c, "\"%s\" property in %s is not a single cell",
- propname, node->fullpath);
-}
-#define CHECK_IS_CELL(nm, propname, lvl) \
- CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
-
-/*
- * Structural check functions
- */
-
-static void check_duplicate_node_names(struct check *c, struct node *dt,
- struct node *node)
-{
- struct node *child, *child2;
-
- for_each_child(node, child)
- for (child2 = child->next_sibling;
- child2;
- child2 = child2->next_sibling)
- if (streq(child->name, child2->name))
- FAIL(c, "Duplicate node name %s",
- child->fullpath);
-}
-NODE_CHECK(duplicate_node_names, NULL, ERROR);
-
-static void check_duplicate_property_names(struct check *c, struct node *dt,
- struct node *node)
-{
- struct property *prop, *prop2;
-
- for_each_property(node, prop)
- for (prop2 = prop->next; prop2; prop2 = prop2->next)
- if (streq(prop->name, prop2->name))
- FAIL(c, "Duplicate property name %s in %s",
- prop->name, node->fullpath);
-}
-NODE_CHECK(duplicate_property_names, NULL, ERROR);
-
-#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
-#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
-#define DIGITS "0123456789"
-#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
-
-static void check_node_name_chars(struct check *c, struct node *dt,
- struct node *node)
-{
- int n = strspn(node->name, c->data);
-
- if (n < strlen(node->name))
- FAIL(c, "Bad character '%c' in node %s",
- node->name[n], node->fullpath);
-}
-NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
-
-static void check_node_name_format(struct check *c, struct node *dt,
- struct node *node)
-{
- if (strchr(get_unitname(node), '@'))
- FAIL(c, "Node %s has multiple '@' characters in name",
- node->fullpath);
-}
-NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
-
-static void check_property_name_chars(struct check *c, struct node *dt,
- struct node *node, struct property *prop)
-{
- int n = strspn(prop->name, c->data);
-
- if (n < strlen(prop->name))
- FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
- prop->name[n], prop->name, node->fullpath);
-}
-PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
-
-static void check_explicit_phandles(struct check *c, struct node *root,
- struct node *node)
-{
- struct property *prop;
- struct node *other;
- cell_t phandle;
-
- prop = get_property(node, "linux,phandle");
- if (! prop)
- return; /* No phandle, that's fine */
-
- if (prop->val.len != sizeof(cell_t)) {
- FAIL(c, "%s has bad length (%d) linux,phandle property",
- node->fullpath, prop->val.len);
- return;
- }
-
- phandle = propval_cell(prop);
- if ((phandle == 0) || (phandle == -1)) {
- FAIL(c, "%s has invalid linux,phandle value 0x%x",
- node->fullpath, phandle);
- return;
- }
-
- other = get_node_by_phandle(root, phandle);
- if (other) {
- FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
- node->fullpath, phandle, other->fullpath);
- return;
- }
-
- node->phandle = phandle;
-}
-NODE_CHECK(explicit_phandles, NULL, ERROR);
-
-static void check_name_properties(struct check *c, struct node *root,
- struct node *node)
-{
- struct property **pp, *prop = NULL;
-
- for (pp = &node->proplist; *pp; pp = &((*pp)->next))
- if (streq((*pp)->name, "name")) {
- prop = *pp;
- break;
- }
-
- if (!prop)
- return; /* No name property, that's fine */
-
- if ((prop->val.len != node->basenamelen+1)
- || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
- FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
- " of base node name)", node->fullpath, prop->val.val);
- } else {
- /* The name property is correct, and therefore redundant.
- * Delete it */
- *pp = prop->next;
- free(prop->name);
- data_free(prop->val);
- free(prop);
- }
-}
-CHECK_IS_STRING(name_is_string, "name", ERROR);
-NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
-
-/*
- * Reference fixup functions
- */
-
-static void fixup_phandle_references(struct check *c, struct node *dt,
- struct node *node, struct property *prop)
-{
- struct marker *m = prop->val.markers;
- struct node *refnode;
- cell_t phandle;
-
- for_each_marker_of_type(m, REF_PHANDLE) {
- assert(m->offset + sizeof(cell_t) <= prop->val.len);
-
- refnode = get_node_by_ref(dt, m->ref);
- if (! refnode) {
- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
- m->ref);
- continue;
- }
-
- phandle = get_node_phandle(dt, refnode);
- *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
- }
-}
-CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
- &duplicate_node_names, &explicit_phandles);
-
-static void fixup_path_references(struct check *c, struct node *dt,
- struct node *node, struct property *prop)
-{
- struct marker *m = prop->val.markers;
- struct node *refnode;
- char *path;
-
- for_each_marker_of_type(m, REF_PATH) {
- assert(m->offset <= prop->val.len);
-
- refnode = get_node_by_ref(dt, m->ref);
- if (!refnode) {
- FAIL(c, "Reference to non-existent node or label \"%s\"\n",
- m->ref);
- continue;
- }
-
- path = refnode->fullpath;
- prop->val = data_insert_at_marker(prop->val, m, path,
- strlen(path) + 1);
- }
-}
-CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
- &duplicate_node_names);
-
-/*
- * Semantic checks
- */
-CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
-CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
-CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
-
-CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
-CHECK_IS_STRING(model_is_string, "model", WARN);
-CHECK_IS_STRING(status_is_string, "status", WARN);
-
-static void fixup_addr_size_cells(struct check *c, struct node *dt,
- struct node *node)
-{
- struct property *prop;
-
- node->addr_cells = -1;
- node->size_cells = -1;
-
- prop = get_property(node, "#address-cells");
- if (prop)
- node->addr_cells = propval_cell(prop);
-
- prop = get_property(node, "#size-cells");
- if (prop)
- node->size_cells = propval_cell(prop);
-}
-CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
- &address_cells_is_cell, &size_cells_is_cell);
-
-#define node_addr_cells(n) \
- (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
-#define node_size_cells(n) \
- (((n)->size_cells == -1) ? 1 : (n)->size_cells)
-
-static void check_reg_format(struct check *c, struct node *dt,
- struct node *node)
-{
- struct property *prop;
- int addr_cells, size_cells, entrylen;
-
- prop = get_property(node, "reg");
- if (!prop)
- return; /* No "reg", that's fine */
-
- if (!node->parent) {
- FAIL(c, "Root node has a \"reg\" property");
- return;
- }
-
- if (prop->val.len == 0)
- FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
-
- addr_cells = node_addr_cells(node->parent);
- size_cells = node_size_cells(node->parent);
- entrylen = (addr_cells + size_cells) * sizeof(cell_t);
-
- if ((prop->val.len % entrylen) != 0)
- FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
- "(#address-cells == %d, #size-cells == %d)",
- node->fullpath, prop->val.len, addr_cells, size_cells);
-}
-NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
-
-static void check_ranges_format(struct check *c, struct node *dt,
- struct node *node)
-{
- struct property *prop;
- int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
-
- prop = get_property(node, "ranges");
- if (!prop)
- return;
-
- if (!node->parent) {
- FAIL(c, "Root node has a \"ranges\" property");
- return;
- }
-
- p_addr_cells = node_addr_cells(node->parent);
- p_size_cells = node_size_cells(node->parent);
- c_addr_cells = node_addr_cells(node);
- c_size_cells = node_size_cells(node);
- entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
-
- if (prop->val.len == 0) {
- if (p_addr_cells != c_addr_cells)
- FAIL(c, "%s has empty \"ranges\" property but its "
- "#address-cells (%d) differs from %s (%d)",
- node->fullpath, c_addr_cells, node->parent->fullpath,
- p_addr_cells);
- if (p_size_cells != c_size_cells)
- FAIL(c, "%s has empty \"ranges\" property but its "
- "#size-cells (%d) differs from %s (%d)",
- node->fullpath, c_size_cells, node->parent->fullpath,
- p_size_cells);
- } else if ((prop->val.len % entrylen) != 0) {
- FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
- "(parent #address-cells == %d, child #address-cells == %d, "
- "#size-cells == %d)", node->fullpath, prop->val.len,
- p_addr_cells, c_addr_cells, c_size_cells);
- }
-}
-NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
-
-/*
- * Style checks
- */
-static void check_avoid_default_addr_size(struct check *c, struct node *dt,
- struct node *node)
-{
- struct property *reg, *ranges;
-
- if (!node->parent)
- return; /* Ignore root node */
-
- reg = get_property(node, "reg");
- ranges = get_property(node, "ranges");
-
- if (!reg && !ranges)
- return;
-
- if ((node->parent->addr_cells == -1))
- FAIL(c, "Relying on default #address-cells value for %s",
- node->fullpath);
-
- if ((node->parent->size_cells == -1))
- FAIL(c, "Relying on default #size-cells value for %s",
- node->fullpath);
-}
-NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
-
-static void check_obsolete_chosen_interrupt_controller(struct check *c,
- struct node *dt)
-{
- struct node *chosen;
- struct property *prop;
-
- chosen = get_node_by_path(dt, "/chosen");
- if (!chosen)
- return;
-
- prop = get_property(chosen, "interrupt-controller");
- if (prop)
- FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
- "property");
-}
-TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
-
-static struct check *check_table[] = {
- &duplicate_node_names, &duplicate_property_names,
- &node_name_chars, &node_name_format, &property_name_chars,
- &name_is_string, &name_properties,
- &explicit_phandles,
- &phandle_references, &path_references,
-
- &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
- &device_type_is_string, &model_is_string, &status_is_string,
-
- &addr_size_cells, ®_format, &ranges_format,
-
- &avoid_default_addr_size,
- &obsolete_chosen_interrupt_controller,
-};
-
-void process_checks(int force, struct boot_info *bi)
-{
- struct node *dt = bi->dt;
- int i;
- int error = 0;
-
- for (i = 0; i < ARRAY_SIZE(check_table); i++) {
- struct check *c = check_table[i];
-
- if (c->level != IGNORE)
- error = error || run_check(c, dt);
- }
-
- if (error) {
- if (!force) {
- fprintf(stderr, "ERROR: Input tree has errors, aborting "
- "(use -f to force output)\n");
- exit(2);
- } else if (quiet < 3) {
- fprintf(stderr, "Warning: Input tree has errors, "
- "output forced\n");
- }
- }
-}
+++ /dev/null
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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 "dtc.h"
-
-void data_free(struct data d)
-{
- struct marker *m, *nm;
-
- m = d.markers;
- while (m) {
- nm = m->next;
- free(m->ref);
- free(m);
- m = nm;
- }
-
- if (d.val)
- free(d.val);
-}
-
-struct data data_grow_for(struct data d, int xlen)
-{
- struct data nd;
- int newsize;
-
- if (xlen == 0)
- return d;
-
- nd = d;
-
- newsize = xlen;
-
- while ((d.len + xlen) > newsize)
- newsize *= 2;
-
- nd.val = xrealloc(d.val, newsize);
-
- return nd;
-}
-
-struct data data_copy_mem(const char *mem, int len)
-{
- struct data d;
-
- d = data_grow_for(empty_data, len);
-
- d.len = len;
- memcpy(d.val, mem, len);
-
- return d;
-}
-
-static char get_oct_char(const char *s, int *i)
-{
- char x[4];
- char *endx;
- long val;
-
- x[3] = '\0';
- strncpy(x, s + *i, 3);
-
- val = strtol(x, &endx, 8);
-
- assert(endx > x);
-
- (*i) += endx - x;
- return val;
-}
-
-static char get_hex_char(const char *s, int *i)
-{
- char x[3];
- char *endx;
- long val;
-
- x[2] = '\0';
- strncpy(x, s + *i, 2);
-
- val = strtol(x, &endx, 16);
- if (!(endx > x))
- die("\\x used with no following hex digits\n");
-
- (*i) += endx - x;
- return val;
-}
-
-struct data data_copy_escape_string(const char *s, int len)
-{
- int i = 0;
- struct data d;
- char *q;
-
- d = data_grow_for(empty_data, strlen(s)+1);
-
- q = d.val;
- while (i < len) {
- char c = s[i++];
-
- if (c != '\\') {
- q[d.len++] = c;
- continue;
- }
-
- c = s[i++];
- assert(c);
- switch (c) {
- case 'a':
- q[d.len++] = '\a';
- break;
- case 'b':
- q[d.len++] = '\b';
- break;
- case 't':
- q[d.len++] = '\t';
- break;
- case 'n':
- q[d.len++] = '\n';
- break;
- case 'v':
- q[d.len++] = '\v';
- break;
- case 'f':
- q[d.len++] = '\f';
- break;
- case 'r':
- q[d.len++] = '\r';
- break;
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- i--; /* need to re-read the first digit as
- * part of the octal value */
- q[d.len++] = get_oct_char(s, &i);
- break;
- case 'x':
- q[d.len++] = get_hex_char(s, &i);
- break;
- default:
- q[d.len++] = c;
- }
- }
-
- q[d.len++] = '\0';
- return d;
-}
-
-struct data data_copy_file(FILE *f, size_t maxlen)
-{
- struct data d = empty_data;
-
- while (!feof(f) && (d.len < maxlen)) {
- size_t chunksize, ret;
-
- if (maxlen == -1)
- chunksize = 4096;
- else
- chunksize = maxlen - d.len;
-
- d = data_grow_for(d, chunksize);
- ret = fread(d.val + d.len, 1, chunksize, f);
-
- if (ferror(f))
- die("Error reading file into data: %s", strerror(errno));
-
- if (d.len + ret < d.len)
- die("Overflow reading file into data\n");
-
- d.len += ret;
- }
-
- return d;
-}
-
-struct data data_append_data(struct data d, const void *p, int len)
-{
- d = data_grow_for(d, len);
- memcpy(d.val + d.len, p, len);
- d.len += len;
- return d;
-}
-
-struct data data_insert_at_marker(struct data d, struct marker *m,
- const void *p, int len)
-{
- d = data_grow_for(d, len);
- memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
- memcpy(d.val + m->offset, p, len);
- d.len += len;
-
- /* Adjust all markers after the one we're inserting at */
- m = m->next;
- for_each_marker(m)
- m->offset += len;
- return d;
-}
-
-struct data data_append_markers(struct data d, struct marker *m)
-{
- struct marker **mp = &d.markers;
-
- /* Find the end of the markerlist */
- while (*mp)
- mp = &((*mp)->next);
- *mp = m;
- return d;
-}
-
-struct data data_merge(struct data d1, struct data d2)
-{
- struct data d;
- struct marker *m2 = d2.markers;
-
- d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
-
- /* Adjust for the length of d1 */
- for_each_marker(m2)
- m2->offset += d1.len;
-
- d2.markers = NULL; /* So data_free() doesn't clobber them */
- data_free(d2);
-
- return d;
-}
-
-struct data data_append_cell(struct data d, cell_t word)
-{
- cell_t beword = cpu_to_fdt32(word);
-
- return data_append_data(d, &beword, sizeof(beword));
-}
-
-struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
-{
- struct fdt_reserve_entry bere;
-
- bere.address = cpu_to_fdt64(re->address);
- bere.size = cpu_to_fdt64(re->size);
-
- return data_append_data(d, &bere, sizeof(bere));
-}
-
-struct data data_append_addr(struct data d, uint64_t addr)
-{
- uint64_t beaddr = cpu_to_fdt64(addr);
-
- return data_append_data(d, &beaddr, sizeof(beaddr));
-}
-
-struct data data_append_byte(struct data d, uint8_t byte)
-{
- return data_append_data(d, &byte, 1);
-}
-
-struct data data_append_zeroes(struct data d, int len)
-{
- d = data_grow_for(d, len);
-
- memset(d.val + d.len, 0, len);
- d.len += len;
- return d;
-}
-
-struct data data_append_align(struct data d, int align)
-{
- int newlen = ALIGN(d.len, align);
- return data_append_zeroes(d, newlen - d.len);
-}
-
-struct data data_add_marker(struct data d, enum markertype type, char *ref)
-{
- struct marker *m;
-
- m = xmalloc(sizeof(*m));
- m->offset = d.len;
- m->type = type;
- m->ref = ref;
- m->next = NULL;
-
- return data_append_markers(d, m);
-}
-
-int data_is_one_string(struct data d)
-{
- int i;
- int len = d.len;
-
- if (len == 0)
- return 0;
-
- for (i = 0; i < len-1; i++)
- if (d.val[i] == '\0')
- return 0;
-
- if (d.val[len-1] != '\0')
- return 0;
-
- return 1;
-}
+++ /dev/null
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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
- */
-
-%option noyywrap nounput yylineno
-
-%x INCLUDE
-%x BYTESTRING
-%x PROPNODENAME
-%s V1
-
-PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
-PATHCHAR ({PROPNODECHAR}|[/])
-LABEL [a-zA-Z_][a-zA-Z0-9_]*
-STRING \"([^\\"]|\\.)*\"
-WS [[:space:]]
-COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
-LINECOMMENT "//".*\n
-
-%{
-#include "dtc.h"
-#include "srcpos.h"
-#include "dtc-parser.tab.h"
-
-
-/*#define LEXDEBUG 1*/
-
-#ifdef LEXDEBUG
-#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
-#else
-#define DPRINT(fmt, ...) do { } while (0)
-#endif
-
-static int dts_version; /* = 0 */
-
-#define BEGIN_DEFAULT() if (dts_version == 0) { \
- DPRINT("<INITIAL>\n"); \
- BEGIN(INITIAL); \
- } else { \
- DPRINT("<V1>\n"); \
- BEGIN(V1); \
- }
-
-static void push_input_file(const char *filename);
-static int pop_input_file(void);
-%}
-
-%%
-<*>"/include/"{WS}*{STRING} {
- char *name = strchr(yytext, '\"') + 1;
- yytext[yyleng-1] = '\0';
- push_input_file(name);
- }
-
-<*><<EOF>> {
- if (!pop_input_file()) {
- yyterminate();
- }
- }
-
-<*>{STRING} {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("String: %s\n", yytext);
- yylval.data = data_copy_escape_string(yytext+1,
- yyleng-2);
- yylloc.first_line = yylineno;
- return DT_STRING;
- }
-
-<*>"/dts-v1/" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Keyword: /dts-v1/\n");
- dts_version = 1;
- BEGIN_DEFAULT();
- return DT_V1;
- }
-
-<*>"/memreserve/" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Keyword: /memreserve/\n");
- BEGIN_DEFAULT();
- return DT_MEMRESERVE;
- }
-
-<*>{LABEL}: {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Label: %s\n", yytext);
- yylval.labelref = strdup(yytext);
- yylval.labelref[yyleng-1] = '\0';
- return DT_LABEL;
- }
-
-<INITIAL>[bodh]# {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- if (*yytext == 'b')
- yylval.cbase = 2;
- else if (*yytext == 'o')
- yylval.cbase = 8;
- else if (*yytext == 'd')
- yylval.cbase = 10;
- else
- yylval.cbase = 16;
- DPRINT("Base: %d\n", yylval.cbase);
- return DT_BASE;
- }
-
-<INITIAL>[0-9a-fA-F]+ {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.literal = strdup(yytext);
- DPRINT("Literal: '%s'\n", yylval.literal);
- return DT_LEGACYLITERAL;
- }
-
-<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.literal = strdup(yytext);
- DPRINT("Literal: '%s'\n", yylval.literal);
- return DT_LITERAL;
- }
-
-\&{LABEL} { /* label reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Ref: %s\n", yytext+1);
- yylval.labelref = strdup(yytext+1);
- return DT_REF;
- }
-
-"&{/"{PATHCHAR}+\} { /* new-style path reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yytext[yyleng-1] = '\0';
- DPRINT("Ref: %s\n", yytext+2);
- yylval.labelref = strdup(yytext+2);
- return DT_REF;
- }
-
-<INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Ref: %s\n", yytext+1);
- yylval.labelref = strdup(yytext+1);
- return DT_REF;
- }
-
-<BYTESTRING>[0-9a-fA-F]{2} {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.byte = strtol(yytext, NULL, 16);
- DPRINT("Byte: %02x\n", (int)yylval.byte);
- return DT_BYTE;
- }
-
-<BYTESTRING>"]" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("/BYTESTRING\n");
- BEGIN_DEFAULT();
- return ']';
- }
-
-<PROPNODENAME>{PROPNODECHAR}+ {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("PropNodeName: %s\n", yytext);
- yylval.propnodename = strdup(yytext);
- BEGIN_DEFAULT();
- return DT_PROPNODENAME;
- }
-
-"/incbin/" {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Binary Include\n");
- return DT_INCBIN;
- }
-
-<*>{WS}+ /* eat whitespace */
-<*>{COMMENT}+ /* eat C-style comments */
-<*>{LINECOMMENT}+ /* eat C++-style comments */
-
-<*>. {
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Char: %c (\\x%02x)\n", yytext[0],
- (unsigned)yytext[0]);
- if (yytext[0] == '[') {
- DPRINT("<BYTESTRING>\n");
- BEGIN(BYTESTRING);
- }
- if ((yytext[0] == '{')
- || (yytext[0] == ';')) {
- DPRINT("<PROPNODENAME>\n");
- BEGIN(PROPNODENAME);
- }
- return yytext[0];
- }
-
-%%
-
-
-/*
- * Stack of nested include file contexts.
- */
-
-struct incl_file {
- struct dtc_file *file;
- YY_BUFFER_STATE yy_prev_buf;
- int yy_prev_lineno;
- struct incl_file *prev;
-};
-
-static struct incl_file *incl_file_stack;
-
-
-/*
- * Detect infinite include recursion.
- */
-#define MAX_INCLUDE_DEPTH (100)
-
-static int incl_depth = 0;
-
-
-static void push_input_file(const char *filename)
-{
- struct incl_file *incl_file;
- struct dtc_file *newfile;
- struct search_path search, *searchptr = NULL;
-
- assert(filename);
-
- if (incl_depth++ >= MAX_INCLUDE_DEPTH)
- die("Includes nested too deeply");
-
- if (srcpos_file) {
- search.dir = srcpos_file->dir;
- search.next = NULL;
- search.prev = NULL;
- searchptr = &search;
- }
-
- newfile = dtc_open_file(filename, searchptr);
-
- incl_file = xmalloc(sizeof(struct incl_file));
-
- /*
- * Save current context.
- */
- incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
- incl_file->yy_prev_lineno = yylineno;
- incl_file->file = srcpos_file;
- incl_file->prev = incl_file_stack;
-
- incl_file_stack = incl_file;
-
- /*
- * Establish new context.
- */
- srcpos_file = newfile;
- yylineno = 1;
- yyin = newfile->file;
- yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
-}
-
-
-static int pop_input_file(void)
-{
- struct incl_file *incl_file;
-
- if (incl_file_stack == 0)
- return 0;
-
- dtc_close_file(srcpos_file);
-
- /*
- * Pop.
- */
- --incl_depth;
- incl_file = incl_file_stack;
- incl_file_stack = incl_file->prev;
-
- /*
- * Recover old context.
- */
- yy_delete_buffer(YY_CURRENT_BUFFER);
- yy_switch_to_buffer(incl_file->yy_prev_buf);
- yylineno = incl_file->yy_prev_lineno;
- srcpos_file = incl_file->file;
- yyin = incl_file->file ? incl_file->file->file : NULL;
-
- /*
- * Free old state.
- */
- free(incl_file);
-
- return 1;
-}
+++ /dev/null
-#line 2 "dtc-lexer.lex.c"
-
-#line 4 "dtc-lexer.lex.c"
-
-#define YY_INT_ALIGNED short int
-
-/* A lexical scanner generated by flex */
-
-#define FLEX_SCANNER
-#define YY_FLEX_MAJOR_VERSION 2
-#define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 34
-#if YY_FLEX_SUBMINOR_VERSION > 0
-#define FLEX_BETA
-#endif
-
-/* First, we deal with platform-specific or compiler-specific issues. */
-
-/* begin standard C headers. */
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <stdlib.h>
-
-/* end standard C headers. */
-
-/* flex integer type definitions */
-
-#ifndef FLEXINT_H
-#define FLEXINT_H
-
-/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
-
-#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
-
-/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
- * if you want the limit (max/min) macros for int types.
- */
-#ifndef __STDC_LIMIT_MACROS
-#define __STDC_LIMIT_MACROS 1
-#endif
-
-#include <inttypes.h>
-typedef int8_t flex_int8_t;
-typedef uint8_t flex_uint8_t;
-typedef int16_t flex_int16_t;
-typedef uint16_t flex_uint16_t;
-typedef int32_t flex_int32_t;
-typedef uint32_t flex_uint32_t;
-#else
-typedef signed char flex_int8_t;
-typedef short int flex_int16_t;
-typedef int flex_int32_t;
-typedef unsigned char flex_uint8_t;
-typedef unsigned short int flex_uint16_t;
-typedef unsigned int flex_uint32_t;
-#endif /* ! C99 */
-
-/* Limits of integral types. */
-#ifndef INT8_MIN
-#define INT8_MIN (-128)
-#endif
-#ifndef INT16_MIN
-#define INT16_MIN (-32767-1)
-#endif
-#ifndef INT32_MIN
-#define INT32_MIN (-2147483647-1)
-#endif
-#ifndef INT8_MAX
-#define INT8_MAX (127)
-#endif
-#ifndef INT16_MAX
-#define INT16_MAX (32767)
-#endif
-#ifndef INT32_MAX
-#define INT32_MAX (2147483647)
-#endif
-#ifndef UINT8_MAX
-#define UINT8_MAX (255U)
-#endif
-#ifndef UINT16_MAX
-#define UINT16_MAX (65535U)
-#endif
-#ifndef UINT32_MAX
-#define UINT32_MAX (4294967295U)
-#endif
-
-#endif /* ! FLEXINT_H */
-
-#ifdef __cplusplus
-
-/* The "const" storage-class-modifier is valid. */
-#define YY_USE_CONST
-
-#else /* ! __cplusplus */
-
-/* C99 requires __STDC__ to be defined as 1. */
-#if defined (__STDC__)
-
-#define YY_USE_CONST
-
-#endif /* defined (__STDC__) */
-#endif /* ! __cplusplus */
-
-#ifdef YY_USE_CONST
-#define yyconst const
-#else
-#define yyconst
-#endif
-
-/* Returned upon end-of-file. */
-#define YY_NULL 0
-
-/* Promotes a possibly negative, possibly signed char to an unsigned
- * integer for use as an array index. If the signed char is negative,
- * we want to instead treat it as an 8-bit unsigned char, hence the
- * double cast.
- */
-#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
-
-/* Enter a start condition. This macro really ought to take a parameter,
- * but we do it the disgusting crufty way forced on us by the ()-less
- * definition of BEGIN.
- */
-#define BEGIN (yy_start) = 1 + 2 *
-
-/* Translate the current start state into a value that can be later handed
- * to BEGIN to return to the state. The YYSTATE alias is for lex
- * compatibility.
- */
-#define YY_START (((yy_start) - 1) / 2)
-#define YYSTATE YY_START
-
-/* Action number for EOF rule of a given start state. */
-#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
-
-/* Special action meaning "start processing a new file". */
-#define YY_NEW_FILE yyrestart(yyin )
-
-#define YY_END_OF_BUFFER_CHAR 0
-
-/* Size of default input buffer. */
-#ifndef YY_BUF_SIZE
-#define YY_BUF_SIZE 16384
-#endif
-
-/* The state buf must be large enough to hold one state per character in the main buffer.
- */
-#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
-
-#ifndef YY_TYPEDEF_YY_BUFFER_STATE
-#define YY_TYPEDEF_YY_BUFFER_STATE
-typedef struct yy_buffer_state *YY_BUFFER_STATE;
-#endif
-
-extern int yyleng;
-
-extern FILE *yyin, *yyout;
-
-#define EOB_ACT_CONTINUE_SCAN 0
-#define EOB_ACT_END_OF_FILE 1
-#define EOB_ACT_LAST_MATCH 2
-
- /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
- * access to the local variable yy_act. Since yyless() is a macro, it would break
- * existing scanners that call yyless() from OUTSIDE yylex.
- * One obvious solution it to make yy_act a global. I tried that, and saw
- * a 5% performance hit in a non-yylineno scanner, because yy_act is
- * normally declared as a register variable-- so it is not worth it.
- */
- #define YY_LESS_LINENO(n) \
- do { \
- int yyl;\
- for ( yyl = n; yyl < yyleng; ++yyl )\
- if ( yytext[yyl] == '\n' )\
- --yylineno;\
- }while(0)
-
-/* Return all but the first "n" matched characters back to the input stream. */
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- int yyless_macro_arg = (n); \
- YY_LESS_LINENO(yyless_macro_arg);\
- *yy_cp = (yy_hold_char); \
- YY_RESTORE_YY_MORE_OFFSET \
- (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
- YY_DO_BEFORE_ACTION; /* set up yytext again */ \
- } \
- while ( 0 )
-
-#define unput(c) yyunput( c, (yytext_ptr) )
-
-/* The following is because we cannot portably get our hands on size_t
- * (without autoconf's help, which isn't available because we want
- * flex-generated scanners to compile on their own).
- * Given that the standard has decreed that size_t exists since 1989,
- * I guess we can afford to depend on it. Manoj.
- */
-
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
-#ifndef YY_STRUCT_YY_BUFFER_STATE
-#define YY_STRUCT_YY_BUFFER_STATE
-struct yy_buffer_state
- {
- FILE *yy_input_file;
-
- char *yy_ch_buf; /* input buffer */
- char *yy_buf_pos; /* current position in input buffer */
-
- /* Size of input buffer in bytes, not including room for EOB
- * characters.
- */
- yy_size_t yy_buf_size;
-
- /* Number of characters read into yy_ch_buf, not including EOB
- * characters.
- */
- int yy_n_chars;
-
- /* Whether we "own" the buffer - i.e., we know we created it,
- * and can realloc() it to grow it, and should free() it to
- * delete it.
- */
- int yy_is_our_buffer;
-
- /* Whether this is an "interactive" input source; if so, and
- * if we're using stdio for input, then we want to use getc()
- * instead of fread(), to make sure we stop fetching input after
- * each newline.
- */
- int yy_is_interactive;
-
- /* Whether we're considered to be at the beginning of a line.
- * If so, '^' rules will be active on the next match, otherwise
- * not.
- */
- int yy_at_bol;
-
- int yy_bs_lineno; /**< The line count. */
- int yy_bs_column; /**< The column count. */
-
- /* Whether to try to fill the input buffer when we reach the
- * end of it.
- */
- int yy_fill_buffer;
-
- int yy_buffer_status;
-
-#define YY_BUFFER_NEW 0
-#define YY_BUFFER_NORMAL 1
- /* When an EOF's been seen but there's still some text to process
- * then we mark the buffer as YY_EOF_PENDING, to indicate that we
- * shouldn't try reading from the input source any more. We might
- * still have a bunch of tokens to match, though, because of
- * possible backing-up.
- *
- * When we actually see the EOF, we change the status to "new"
- * (via yyrestart()), so that the user can continue scanning by
- * just pointing yyin at a new input file.
- */
-#define YY_BUFFER_EOF_PENDING 2
-
- };
-#endif /* !YY_STRUCT_YY_BUFFER_STATE */
-
-/* Stack of input buffers. */
-static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
-static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
-static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
-
-/* We provide macros for accessing buffer states in case in the
- * future we want to put the buffer states in a more general
- * "scanner state".
- *
- * Returns the top of the stack, or NULL.
- */
-#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
- ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
- : NULL)
-
-/* Same as previous macro, but useful when we know that the buffer stack is not
- * NULL or when we need an lvalue. For internal use only.
- */
-#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
-
-/* yy_hold_char holds the character lost when yytext is formed. */
-static char yy_hold_char;
-static int yy_n_chars; /* number of characters read into yy_ch_buf */
-int yyleng;
-
-/* Points to current character in buffer. */
-static char *yy_c_buf_p = (char *) 0;
-static int yy_init = 0; /* whether we need to initialize */
-static int yy_start = 0; /* start state number */
-
-/* Flag which is used to allow yywrap()'s to do buffer switches
- * instead of setting up a fresh yyin. A bit of a hack ...
- */
-static int yy_did_buffer_switch_on_eof;
-
-void yyrestart (FILE *input_file );
-void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
-YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
-void yy_delete_buffer (YY_BUFFER_STATE b );
-void yy_flush_buffer (YY_BUFFER_STATE b );
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
-void yypop_buffer_state (void );
-
-static void yyensure_buffer_stack (void );
-static void yy_load_buffer_state (void );
-static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
-
-#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
-
-YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
-YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
-YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
-
-void *yyalloc (yy_size_t );
-void *yyrealloc (void *,yy_size_t );
-void yyfree (void * );
-
-#define yy_new_buffer yy_create_buffer
-
-#define yy_set_interactive(is_interactive) \
- { \
- if ( ! YY_CURRENT_BUFFER ){ \
- yyensure_buffer_stack (); \
- YY_CURRENT_BUFFER_LVALUE = \
- yy_create_buffer(yyin,YY_BUF_SIZE ); \
- } \
- YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
- }
-
-#define yy_set_bol(at_bol) \
- { \
- if ( ! YY_CURRENT_BUFFER ){\
- yyensure_buffer_stack (); \
- YY_CURRENT_BUFFER_LVALUE = \
- yy_create_buffer(yyin,YY_BUF_SIZE ); \
- } \
- YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
- }
-
-#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
-
-/* Begin user sect3 */
-
-#define yywrap(n) 1
-#define YY_SKIP_YYWRAP
-
-typedef unsigned char YY_CHAR;
-
-FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
-
-typedef int yy_state_type;
-
-extern int yylineno;
-
-int yylineno = 1;
-
-extern char *yytext;
-#define yytext_ptr yytext
-
-static yy_state_type yy_get_previous_state (void );
-static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
-static int yy_get_next_buffer (void );
-static void yy_fatal_error (yyconst char msg[] );
-
-/* Done after the current pattern has been matched and before the
- * corresponding action - sets up yytext.
- */
-#define YY_DO_BEFORE_ACTION \
- (yytext_ptr) = yy_bp; \
- yyleng = (size_t) (yy_cp - yy_bp); \
- (yy_hold_char) = *yy_cp; \
- *yy_cp = '\0'; \
- (yy_c_buf_p) = yy_cp;
-
-#define YY_NUM_RULES 20
-#define YY_END_OF_BUFFER 21
-/* This struct is not used in this scanner,
- but its presence is necessary. */
-struct yy_trans_info
- {
- flex_int32_t yy_verify;
- flex_int32_t yy_nxt;
- };
-static yyconst flex_int16_t yy_accept[104] =
- { 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 21, 19, 16, 16, 19, 19, 19, 7, 7, 19,
- 7, 19, 19, 19, 19, 13, 14, 14, 19, 8,
- 8, 16, 0, 2, 0, 0, 9, 0, 0, 0,
- 0, 0, 0, 7, 7, 5, 0, 6, 0, 12,
- 12, 14, 14, 8, 0, 11, 9, 0, 0, 0,
- 0, 18, 0, 0, 0, 0, 8, 0, 17, 0,
- 0, 0, 0, 0, 10, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 3, 15,
- 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
-
- 0, 4, 0
- } ;
-
-static yyconst flex_int32_t yy_ec[256] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
- 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 2, 1, 4, 5, 1, 1, 6, 1, 1,
- 1, 7, 8, 8, 9, 8, 10, 11, 12, 13,
- 13, 13, 13, 13, 13, 13, 13, 14, 1, 1,
- 1, 1, 8, 8, 15, 15, 15, 15, 15, 15,
- 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
- 16, 16, 16, 16, 16, 16, 16, 17, 16, 16,
- 1, 18, 19, 1, 16, 1, 15, 20, 21, 22,
-
- 23, 15, 16, 24, 25, 16, 16, 26, 27, 28,
- 24, 16, 16, 29, 30, 31, 32, 33, 16, 17,
- 16, 16, 34, 1, 35, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1
- } ;
-
-static yyconst flex_int32_t yy_meta[36] =
- { 0,
- 1, 1, 1, 1, 2, 1, 2, 2, 2, 3,
- 4, 4, 4, 5, 6, 7, 7, 1, 1, 6,
- 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 8, 1
- } ;
-
-static yyconst flex_int16_t yy_base[117] =
- { 0,
- 0, 0, 30, 0, 44, 0, 67, 0, 97, 105,
- 302, 303, 35, 44, 40, 94, 112, 0, 129, 152,
- 296, 295, 159, 0, 176, 303, 0, 116, 95, 165,
- 49, 46, 102, 303, 296, 0, 0, 288, 290, 293,
- 264, 266, 270, 0, 0, 303, 0, 303, 264, 303,
- 0, 0, 195, 101, 0, 0, 0, 0, 284, 125,
- 277, 265, 225, 230, 216, 218, 0, 202, 224, 221,
- 217, 107, 196, 188, 303, 206, 179, 186, 178, 185,
- 183, 162, 161, 150, 169, 160, 145, 125, 303, 303,
- 137, 109, 190, 103, 203, 167, 108, 197, 303, 123,
-
- 29, 303, 303, 215, 221, 226, 229, 234, 240, 246,
- 250, 257, 265, 270, 275, 282
- } ;
-
-static yyconst flex_int16_t yy_def[117] =
- { 0,
- 103, 1, 1, 3, 3, 5, 103, 7, 3, 3,
- 103, 103, 103, 103, 104, 105, 103, 106, 103, 19,
- 19, 20, 103, 107, 20, 103, 108, 109, 105, 103,
- 103, 103, 104, 103, 104, 110, 111, 103, 112, 113,
- 103, 103, 103, 106, 19, 103, 20, 103, 103, 103,
- 20, 108, 109, 103, 114, 110, 111, 115, 112, 112,
- 113, 103, 103, 103, 103, 103, 114, 115, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 116, 103, 116, 103, 116,
-
- 103, 103, 0, 103, 103, 103, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 103
- } ;
-
-static yyconst flex_int16_t yy_nxt[339] =
- { 0,
- 12, 13, 14, 15, 12, 16, 12, 12, 12, 17,
- 18, 18, 18, 12, 19, 20, 20, 12, 12, 21,
- 19, 21, 19, 22, 20, 20, 20, 20, 20, 20,
- 20, 20, 20, 12, 12, 12, 32, 32, 102, 23,
- 12, 12, 12, 34, 20, 32, 32, 32, 32, 20,
- 20, 20, 20, 20, 24, 24, 24, 35, 25, 54,
- 54, 54, 26, 25, 25, 25, 25, 12, 13, 14,
- 15, 27, 12, 27, 27, 27, 23, 27, 27, 27,
- 12, 28, 28, 28, 12, 12, 28, 28, 28, 28,
- 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
-
- 12, 12, 29, 36, 103, 34, 17, 30, 31, 31,
- 29, 54, 54, 54, 17, 30, 31, 31, 39, 35,
- 52, 40, 52, 52, 52, 103, 78, 38, 38, 46,
- 101, 60, 79, 41, 69, 97, 42, 94, 43, 45,
- 45, 45, 46, 45, 47, 47, 93, 92, 45, 45,
- 45, 45, 47, 47, 47, 47, 47, 47, 47, 47,
- 47, 47, 47, 47, 47, 39, 47, 91, 40, 90,
- 99, 47, 47, 47, 47, 54, 54, 54, 89, 88,
- 41, 55, 87, 49, 100, 43, 51, 51, 51, 86,
- 51, 95, 95, 96, 85, 51, 51, 51, 51, 52,
-
- 99, 52, 52, 52, 95, 95, 96, 84, 46, 83,
- 82, 81, 39, 79, 100, 33, 33, 33, 33, 33,
- 33, 33, 33, 37, 80, 77, 37, 37, 37, 44,
- 40, 44, 50, 76, 50, 52, 75, 52, 74, 52,
- 52, 53, 73, 53, 53, 53, 53, 56, 56, 56,
- 72, 56, 56, 57, 71, 57, 57, 59, 59, 59,
- 59, 59, 59, 59, 59, 61, 61, 61, 61, 61,
- 61, 61, 61, 67, 70, 67, 68, 68, 68, 62,
- 68, 68, 98, 98, 98, 98, 98, 98, 98, 98,
- 60, 66, 65, 64, 63, 62, 60, 58, 103, 48,
-
- 48, 103, 11, 103, 103, 103, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103
- } ;
-
-static yyconst flex_int16_t yy_chk[339] =
- { 0,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 3, 13, 13, 101, 3,
- 3, 3, 3, 15, 3, 14, 14, 32, 32, 3,
- 3, 3, 3, 3, 5, 5, 5, 15, 5, 31,
- 31, 31, 5, 5, 5, 5, 5, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
- 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
-
- 7, 7, 9, 16, 29, 33, 9, 9, 9, 9,
- 10, 54, 54, 54, 10, 10, 10, 10, 17, 33,
- 28, 17, 28, 28, 28, 100, 72, 16, 29, 28,
- 97, 60, 72, 17, 60, 94, 17, 92, 17, 19,
- 19, 19, 19, 19, 19, 19, 91, 88, 19, 19,
- 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
- 19, 19, 20, 20, 20, 23, 20, 87, 23, 86,
- 96, 20, 20, 20, 20, 30, 30, 30, 85, 84,
- 23, 30, 83, 23, 96, 23, 25, 25, 25, 82,
- 25, 93, 93, 93, 81, 25, 25, 25, 25, 53,
-
- 98, 53, 53, 53, 95, 95, 95, 80, 53, 79,
- 78, 77, 76, 74, 98, 104, 104, 104, 104, 104,
- 104, 104, 104, 105, 73, 71, 105, 105, 105, 106,
- 70, 106, 107, 69, 107, 108, 68, 108, 66, 108,
- 108, 109, 65, 109, 109, 109, 109, 110, 110, 110,
- 64, 110, 110, 111, 63, 111, 111, 112, 112, 112,
- 112, 112, 112, 112, 112, 113, 113, 113, 113, 113,
- 113, 113, 113, 114, 62, 114, 115, 115, 115, 61,
- 115, 115, 116, 116, 116, 116, 116, 116, 116, 116,
- 59, 49, 43, 42, 41, 40, 39, 38, 35, 22,
-
- 21, 11, 103, 103, 103, 103, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
- 103, 103, 103, 103, 103, 103, 103, 103
- } ;
-
-/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[21] =
- { 0,
-1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
- 0, };
-
-static yy_state_type yy_last_accepting_state;
-static char *yy_last_accepting_cpos;
-
-extern int yy_flex_debug;
-int yy_flex_debug = 0;
-
-/* The intent behind this definition is that it'll catch
- * any uses of REJECT which flex missed.
- */
-#define REJECT reject_used_but_not_detected
-#define yymore() yymore_used_but_not_detected
-#define YY_MORE_ADJ 0
-#define YY_RESTORE_YY_MORE_OFFSET
-char *yytext;
-#line 1 "dtc-lexer.l"
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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
- */
-
-
-
-
-#line 37 "dtc-lexer.l"
-#include "dtc.h"
-#include "srcpos.h"
-#include "dtc-parser.tab.h"
-
-
-/*#define LEXDEBUG 1*/
-
-#ifdef LEXDEBUG
-#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
-#else
-#define DPRINT(fmt, ...) do { } while (0)
-#endif
-
-static int dts_version; /* = 0 */
-
-#define BEGIN_DEFAULT() if (dts_version == 0) { \
- DPRINT("<INITIAL>\n"); \
- BEGIN(INITIAL); \
- } else { \
- DPRINT("<V1>\n"); \
- BEGIN(V1); \
- }
-
-static void push_input_file(const char *filename);
-static int pop_input_file(void);
-#line 638 "dtc-lexer.lex.c"
-
-#define INITIAL 0
-#define INCLUDE 1
-#define BYTESTRING 2
-#define PROPNODENAME 3
-#define V1 4
-
-#ifndef YY_NO_UNISTD_H
-/* Special case for "unistd.h", since it is non-ANSI. We include it way
- * down here because we want the user's section 1 to have been scanned first.
- * The user has a chance to override it with an option.
- */
-#include <unistd.h>
-#endif
-
-#ifndef YY_EXTRA_TYPE
-#define YY_EXTRA_TYPE void *
-#endif
-
-static int yy_init_globals (void );
-
-/* Macros after this point can all be overridden by user definitions in
- * section 1.
- */
-
-#ifndef YY_SKIP_YYWRAP
-#ifdef __cplusplus
-extern "C" int yywrap (void );
-#else
-extern int yywrap (void );
-#endif
-#endif
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char *,yyconst char *,int );
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * );
-#endif
-
-#ifndef YY_NO_INPUT
-
-#ifdef __cplusplus
-static int yyinput (void );
-#else
-static int input (void );
-#endif
-
-#endif
-
-/* Amount of stuff to slurp up with each read. */
-#ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
-#endif
-
-/* Copy whatever the last rule matched to the standard output. */
-#ifndef ECHO
-/* This used to be an fputs(), but since the string might contain NUL's,
- * we now use fwrite().
- */
-#define ECHO fwrite( yytext, yyleng, 1, yyout )
-#endif
-
-/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
- * is returned in "result".
- */
-#ifndef YY_INPUT
-#define YY_INPUT(buf,result,max_size) \
- if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
- { \
- int c = '*'; \
- int n; \
- for ( n = 0; n < max_size && \
- (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
- buf[n] = (char) c; \
- if ( c == '\n' ) \
- buf[n++] = (char) c; \
- if ( c == EOF && ferror( yyin ) ) \
- YY_FATAL_ERROR( "input in flex scanner failed" ); \
- result = n; \
- } \
- else \
- { \
- errno=0; \
- while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
- { \
- if( errno != EINTR) \
- { \
- YY_FATAL_ERROR( "input in flex scanner failed" ); \
- break; \
- } \
- errno=0; \
- clearerr(yyin); \
- } \
- }\
-\
-
-#endif
-
-/* No semi-colon after return; correct usage is to write "yyterminate();" -
- * we don't want an extra ';' after the "return" because that will cause
- * some compilers to complain about unreachable statements.
- */
-#ifndef yyterminate
-#define yyterminate() return YY_NULL
-#endif
-
-/* Number of entries by which start-condition stack grows. */
-#ifndef YY_START_STACK_INCR
-#define YY_START_STACK_INCR 25
-#endif
-
-/* Report a fatal error. */
-#ifndef YY_FATAL_ERROR
-#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
-#endif
-
-/* end tables serialization structures and prototypes */
-
-/* Default declaration of generated scanner - a define so the user can
- * easily add parameters.
- */
-#ifndef YY_DECL
-#define YY_DECL_IS_OURS 1
-
-extern int yylex (void);
-
-#define YY_DECL int yylex (void)
-#endif /* !YY_DECL */
-
-/* Code executed at the beginning of each rule, after yytext and yyleng
- * have been set up.
- */
-#ifndef YY_USER_ACTION
-#define YY_USER_ACTION
-#endif
-
-/* Code executed at the end of each rule. */
-#ifndef YY_BREAK
-#define YY_BREAK break;
-#endif
-
-#define YY_RULE_SETUP \
- YY_USER_ACTION
-
-/** The main scanner function which does all the work.
- */
-YY_DECL
-{
- register yy_state_type yy_current_state;
- register char *yy_cp, *yy_bp;
- register int yy_act;
-
-#line 64 "dtc-lexer.l"
-
-#line 795 "dtc-lexer.lex.c"
-
- if ( !(yy_init) )
- {
- (yy_init) = 1;
-
-#ifdef YY_USER_INIT
- YY_USER_INIT;
-#endif
-
- if ( ! (yy_start) )
- (yy_start) = 1; /* first start state */
-
- if ( ! yyin )
- yyin = stdin;
-
- if ( ! yyout )
- yyout = stdout;
-
- if ( ! YY_CURRENT_BUFFER ) {
- yyensure_buffer_stack ();
- YY_CURRENT_BUFFER_LVALUE =
- yy_create_buffer(yyin,YY_BUF_SIZE );
- }
-
- yy_load_buffer_state( );
- }
-
- while ( 1 ) /* loops until end-of-file is reached */
- {
- yy_cp = (yy_c_buf_p);
-
- /* Support of yytext. */
- *yy_cp = (yy_hold_char);
-
- /* yy_bp points to the position in yy_ch_buf of the start of
- * the current run.
- */
- yy_bp = yy_cp;
-
- yy_current_state = (yy_start);
-yy_match:
- do
- {
- register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
- if ( yy_accept[yy_current_state] )
- {
- (yy_last_accepting_state) = yy_current_state;
- (yy_last_accepting_cpos) = yy_cp;
- }
- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
- {
- yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 104 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- ++yy_cp;
- }
- while ( yy_base[yy_current_state] != 303 );
-
-yy_find_action:
- yy_act = yy_accept[yy_current_state];
- if ( yy_act == 0 )
- { /* have to back up */
- yy_cp = (yy_last_accepting_cpos);
- yy_current_state = (yy_last_accepting_state);
- yy_act = yy_accept[yy_current_state];
- }
-
- YY_DO_BEFORE_ACTION;
-
- if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
- {
- int yyl;
- for ( yyl = 0; yyl < yyleng; ++yyl )
- if ( yytext[yyl] == '\n' )
-
- yylineno++;
-;
- }
-
-do_action: /* This label is used only to access EOF actions. */
-
- switch ( yy_act )
- { /* beginning of action switch */
- case 0: /* must back up */
- /* undo the effects of YY_DO_BEFORE_ACTION */
- *yy_cp = (yy_hold_char);
- yy_cp = (yy_last_accepting_cpos);
- yy_current_state = (yy_last_accepting_state);
- goto yy_find_action;
-
-case 1:
-/* rule 1 can match eol */
-YY_RULE_SETUP
-#line 65 "dtc-lexer.l"
-{
- char *name = strchr(yytext, '\"') + 1;
- yytext[yyleng-1] = '\0';
- push_input_file(name);
- }
- YY_BREAK
-case YY_STATE_EOF(INITIAL):
-case YY_STATE_EOF(INCLUDE):
-case YY_STATE_EOF(BYTESTRING):
-case YY_STATE_EOF(PROPNODENAME):
-case YY_STATE_EOF(V1):
-#line 71 "dtc-lexer.l"
-{
- if (!pop_input_file()) {
- yyterminate();
- }
- }
- YY_BREAK
-case 2:
-/* rule 2 can match eol */
-YY_RULE_SETUP
-#line 77 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("String: %s\n", yytext);
- yylval.data = data_copy_escape_string(yytext+1,
- yyleng-2);
- yylloc.first_line = yylineno;
- return DT_STRING;
- }
- YY_BREAK
-case 3:
-YY_RULE_SETUP
-#line 87 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Keyword: /dts-v1/\n");
- dts_version = 1;
- BEGIN_DEFAULT();
- return DT_V1;
- }
- YY_BREAK
-case 4:
-YY_RULE_SETUP
-#line 96 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Keyword: /memreserve/\n");
- BEGIN_DEFAULT();
- return DT_MEMRESERVE;
- }
- YY_BREAK
-case 5:
-YY_RULE_SETUP
-#line 104 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Label: %s\n", yytext);
- yylval.labelref = strdup(yytext);
- yylval.labelref[yyleng-1] = '\0';
- return DT_LABEL;
- }
- YY_BREAK
-case 6:
-YY_RULE_SETUP
-#line 113 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- if (*yytext == 'b')
- yylval.cbase = 2;
- else if (*yytext == 'o')
- yylval.cbase = 8;
- else if (*yytext == 'd')
- yylval.cbase = 10;
- else
- yylval.cbase = 16;
- DPRINT("Base: %d\n", yylval.cbase);
- return DT_BASE;
- }
- YY_BREAK
-case 7:
-YY_RULE_SETUP
-#line 128 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.literal = strdup(yytext);
- DPRINT("Literal: '%s'\n", yylval.literal);
- return DT_LEGACYLITERAL;
- }
- YY_BREAK
-case 8:
-YY_RULE_SETUP
-#line 136 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.literal = strdup(yytext);
- DPRINT("Literal: '%s'\n", yylval.literal);
- return DT_LITERAL;
- }
- YY_BREAK
-case 9:
-YY_RULE_SETUP
-#line 144 "dtc-lexer.l"
-{ /* label reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Ref: %s\n", yytext+1);
- yylval.labelref = strdup(yytext+1);
- return DT_REF;
- }
- YY_BREAK
-case 10:
-YY_RULE_SETUP
-#line 152 "dtc-lexer.l"
-{ /* new-style path reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yytext[yyleng-1] = '\0';
- DPRINT("Ref: %s\n", yytext+2);
- yylval.labelref = strdup(yytext+2);
- return DT_REF;
- }
- YY_BREAK
-case 11:
-YY_RULE_SETUP
-#line 161 "dtc-lexer.l"
-{ /* old-style path reference */
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Ref: %s\n", yytext+1);
- yylval.labelref = strdup(yytext+1);
- return DT_REF;
- }
- YY_BREAK
-case 12:
-YY_RULE_SETUP
-#line 169 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- yylval.byte = strtol(yytext, NULL, 16);
- DPRINT("Byte: %02x\n", (int)yylval.byte);
- return DT_BYTE;
- }
- YY_BREAK
-case 13:
-YY_RULE_SETUP
-#line 177 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("/BYTESTRING\n");
- BEGIN_DEFAULT();
- return ']';
- }
- YY_BREAK
-case 14:
-YY_RULE_SETUP
-#line 185 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("PropNodeName: %s\n", yytext);
- yylval.propnodename = strdup(yytext);
- BEGIN_DEFAULT();
- return DT_PROPNODENAME;
- }
- YY_BREAK
-case 15:
-YY_RULE_SETUP
-#line 194 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Binary Include\n");
- return DT_INCBIN;
- }
- YY_BREAK
-case 16:
-/* rule 16 can match eol */
-YY_RULE_SETUP
-#line 201 "dtc-lexer.l"
-/* eat whitespace */
- YY_BREAK
-case 17:
-/* rule 17 can match eol */
-YY_RULE_SETUP
-#line 202 "dtc-lexer.l"
-/* eat C-style comments */
- YY_BREAK
-case 18:
-/* rule 18 can match eol */
-YY_RULE_SETUP
-#line 203 "dtc-lexer.l"
-/* eat C++-style comments */
- YY_BREAK
-case 19:
-YY_RULE_SETUP
-#line 205 "dtc-lexer.l"
-{
- yylloc.file = srcpos_file;
- yylloc.first_line = yylineno;
- DPRINT("Char: %c (\\x%02x)\n", yytext[0],
- (unsigned)yytext[0]);
- if (yytext[0] == '[') {
- DPRINT("<BYTESTRING>\n");
- BEGIN(BYTESTRING);
- }
- if ((yytext[0] == '{')
- || (yytext[0] == ';')) {
- DPRINT("<PROPNODENAME>\n");
- BEGIN(PROPNODENAME);
- }
- return yytext[0];
- }
- YY_BREAK
-case 20:
-YY_RULE_SETUP
-#line 222 "dtc-lexer.l"
-ECHO;
- YY_BREAK
-#line 1120 "dtc-lexer.lex.c"
-
- case YY_END_OF_BUFFER:
- {
- /* Amount of text matched not including the EOB char. */
- int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
-
- /* Undo the effects of YY_DO_BEFORE_ACTION. */
- *yy_cp = (yy_hold_char);
- YY_RESTORE_YY_MORE_OFFSET
-
- if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
- {
- /* We're scanning a new file or input source. It's
- * possible that this happened because the user
- * just pointed yyin at a new source and called
- * yylex(). If so, then we have to assure
- * consistency between YY_CURRENT_BUFFER and our
- * globals. Here is the right place to do so, because
- * this is the first action (other than possibly a
- * back-up) that will match for the new input source.
- */
- (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
- YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
- YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
- }
-
- /* Note that here we test for yy_c_buf_p "<=" to the position
- * of the first EOB in the buffer, since yy_c_buf_p will
- * already have been incremented past the NUL character
- * (since all states make transitions on EOB to the
- * end-of-buffer state). Contrast this with the test
- * in input().
- */
- if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
- { /* This was really a NUL. */
- yy_state_type yy_next_state;
-
- (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
-
- yy_current_state = yy_get_previous_state( );
-
- /* Okay, we're now positioned to make the NUL
- * transition. We couldn't have
- * yy_get_previous_state() go ahead and do it
- * for us because it doesn't know how to deal
- * with the possibility of jamming (and we don't
- * want to build jamming into it because then it
- * will run more slowly).
- */
-
- yy_next_state = yy_try_NUL_trans( yy_current_state );
-
- yy_bp = (yytext_ptr) + YY_MORE_ADJ;
-
- if ( yy_next_state )
- {
- /* Consume the NUL. */
- yy_cp = ++(yy_c_buf_p);
- yy_current_state = yy_next_state;
- goto yy_match;
- }
-
- else
- {
- yy_cp = (yy_c_buf_p);
- goto yy_find_action;
- }
- }
-
- else switch ( yy_get_next_buffer( ) )
- {
- case EOB_ACT_END_OF_FILE:
- {
- (yy_did_buffer_switch_on_eof) = 0;
-
- if ( yywrap( ) )
- {
- /* Note: because we've taken care in
- * yy_get_next_buffer() to have set up
- * yytext, we can now set up
- * yy_c_buf_p so that if some total
- * hoser (like flex itself) wants to
- * call the scanner after we return the
- * YY_NULL, it'll still work - another
- * YY_NULL will get returned.
- */
- (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
-
- yy_act = YY_STATE_EOF(YY_START);
- goto do_action;
- }
-
- else
- {
- if ( ! (yy_did_buffer_switch_on_eof) )
- YY_NEW_FILE;
- }
- break;
- }
-
- case EOB_ACT_CONTINUE_SCAN:
- (yy_c_buf_p) =
- (yytext_ptr) + yy_amount_of_matched_text;
-
- yy_current_state = yy_get_previous_state( );
-
- yy_cp = (yy_c_buf_p);
- yy_bp = (yytext_ptr) + YY_MORE_ADJ;
- goto yy_match;
-
- case EOB_ACT_LAST_MATCH:
- (yy_c_buf_p) =
- &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
-
- yy_current_state = yy_get_previous_state( );
-
- yy_cp = (yy_c_buf_p);
- yy_bp = (yytext_ptr) + YY_MORE_ADJ;
- goto yy_find_action;
- }
- break;
- }
-
- default:
- YY_FATAL_ERROR(
- "fatal flex scanner internal error--no action found" );
- } /* end of action switch */
- } /* end of scanning one token */
-} /* end of yylex */
-
-/* yy_get_next_buffer - try to read in a new buffer
- *
- * Returns a code representing an action:
- * EOB_ACT_LAST_MATCH -
- * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
- * EOB_ACT_END_OF_FILE - end of file
- */
-static int yy_get_next_buffer (void)
-{
- register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
- register char *source = (yytext_ptr);
- register int number_to_move, i;
- int ret_val;
-
- if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
- YY_FATAL_ERROR(
- "fatal flex scanner internal error--end of buffer missed" );
-
- if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
- { /* Don't try to fill the buffer, so this is an EOF. */
- if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
- {
- /* We matched a single character, the EOB, so
- * treat this as a final EOF.
- */
- return EOB_ACT_END_OF_FILE;
- }
-
- else
- {
- /* We matched some text prior to the EOB, first
- * process it.
- */
- return EOB_ACT_LAST_MATCH;
- }
- }
-
- /* Try to read more data. */
-
- /* First move last chars to start of buffer. */
- number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
-
- for ( i = 0; i < number_to_move; ++i )
- *(dest++) = *(source++);
-
- if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
- /* don't do the read, it's not guaranteed to return an EOF,
- * just force an EOF
- */
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
-
- else
- {
- int num_to_read =
- YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
-
- while ( num_to_read <= 0 )
- { /* Not enough room in the buffer - grow it. */
-
- /* just a shorter name for the current buffer */
- YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
-
- int yy_c_buf_p_offset =
- (int) ((yy_c_buf_p) - b->yy_ch_buf);
-
- if ( b->yy_is_our_buffer )
- {
- int new_size = b->yy_buf_size * 2;
-
- if ( new_size <= 0 )
- b->yy_buf_size += b->yy_buf_size / 8;
- else
- b->yy_buf_size *= 2;
-
- b->yy_ch_buf = (char *)
- /* Include room in for 2 EOB chars. */
- yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
- }
- else
- /* Can't grow it, we don't own it. */
- b->yy_ch_buf = 0;
-
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR(
- "fatal error - scanner input buffer overflow" );
-
- (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
-
- num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
- number_to_move - 1;
-
- }
-
- if ( num_to_read > YY_READ_BUF_SIZE )
- num_to_read = YY_READ_BUF_SIZE;
-
- /* Read in more data. */
- YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
- (yy_n_chars), (size_t) num_to_read );
-
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
- }
-
- if ( (yy_n_chars) == 0 )
- {
- if ( number_to_move == YY_MORE_ADJ )
- {
- ret_val = EOB_ACT_END_OF_FILE;
- yyrestart(yyin );
- }
-
- else
- {
- ret_val = EOB_ACT_LAST_MATCH;
- YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
- YY_BUFFER_EOF_PENDING;
- }
- }
-
- else
- ret_val = EOB_ACT_CONTINUE_SCAN;
-
- if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
- /* Extend the array by 50%, plus the number we really need. */
- yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
- if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
- }
-
- (yy_n_chars) += number_to_move;
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
- YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
-
- (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
-
- return ret_val;
-}
-
-/* yy_get_previous_state - get the state just before the EOB char was reached */
-
- static yy_state_type yy_get_previous_state (void)
-{
- register yy_state_type yy_current_state;
- register char *yy_cp;
-
- yy_current_state = (yy_start);
-
- for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
- {
- register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
- if ( yy_accept[yy_current_state] )
- {
- (yy_last_accepting_state) = yy_current_state;
- (yy_last_accepting_cpos) = yy_cp;
- }
- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
- {
- yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 104 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- }
-
- return yy_current_state;
-}
-
-/* yy_try_NUL_trans - try to make a transition on the NUL character
- *
- * synopsis
- * next_state = yy_try_NUL_trans( current_state );
- */
- static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
-{
- register int yy_is_jam;
- register char *yy_cp = (yy_c_buf_p);
-
- register YY_CHAR yy_c = 1;
- if ( yy_accept[yy_current_state] )
- {
- (yy_last_accepting_state) = yy_current_state;
- (yy_last_accepting_cpos) = yy_cp;
- }
- while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
- {
- yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 104 )
- yy_c = yy_meta[(unsigned int) yy_c];
- }
- yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 103);
-
- return yy_is_jam ? 0 : yy_current_state;
-}
-
-#ifndef YY_NO_INPUT
-#ifdef __cplusplus
- static int yyinput (void)
-#else
- static int input (void)
-#endif
-
-{
- int c;
-
- *(yy_c_buf_p) = (yy_hold_char);
-
- if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
- {
- /* yy_c_buf_p now points to the character we want to return.
- * If this occurs *before* the EOB characters, then it's a
- * valid NUL; if not, then we've hit the end of the buffer.
- */
- if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
- /* This was really a NUL. */
- *(yy_c_buf_p) = '\0';
-
- else
- { /* need more input */
- int offset = (yy_c_buf_p) - (yytext_ptr);
- ++(yy_c_buf_p);
-
- switch ( yy_get_next_buffer( ) )
- {
- case EOB_ACT_LAST_MATCH:
- /* This happens because yy_g_n_b()
- * sees that we've accumulated a
- * token and flags that we need to
- * try matching the token before
- * proceeding. But for input(),
- * there's no matching to consider.
- * So convert the EOB_ACT_LAST_MATCH
- * to EOB_ACT_END_OF_FILE.
- */
-
- /* Reset buffer status. */
- yyrestart(yyin );
-
- /*FALLTHROUGH*/
-
- case EOB_ACT_END_OF_FILE:
- {
- if ( yywrap( ) )
- return EOF;
-
- if ( ! (yy_did_buffer_switch_on_eof) )
- YY_NEW_FILE;
-#ifdef __cplusplus
- return yyinput();
-#else
- return input();
-#endif
- }
-
- case EOB_ACT_CONTINUE_SCAN:
- (yy_c_buf_p) = (yytext_ptr) + offset;
- break;
- }
- }
- }
-
- c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
- *(yy_c_buf_p) = '\0'; /* preserve yytext */
- (yy_hold_char) = *++(yy_c_buf_p);
-
- if ( c == '\n' )
-
- yylineno++;
-;
-
- return c;
-}
-#endif /* ifndef YY_NO_INPUT */
-
-/** Immediately switch to a different input stream.
- * @param input_file A readable stream.
- *
- * @note This function does not reset the start condition to @c INITIAL .
- */
- void yyrestart (FILE * input_file )
-{
-
- if ( ! YY_CURRENT_BUFFER ){
- yyensure_buffer_stack ();
- YY_CURRENT_BUFFER_LVALUE =
- yy_create_buffer(yyin,YY_BUF_SIZE );
- }
-
- yy_init_buffer(YY_CURRENT_BUFFER,input_file );
- yy_load_buffer_state( );
-}
-
-/** Switch to a different input buffer.
- * @param new_buffer The new input buffer.
- *
- */
- void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
-{
-
- /* TODO. We should be able to replace this entire function body
- * with
- * yypop_buffer_state();
- * yypush_buffer_state(new_buffer);
- */
- yyensure_buffer_stack ();
- if ( YY_CURRENT_BUFFER == new_buffer )
- return;
-
- if ( YY_CURRENT_BUFFER )
- {
- /* Flush out information for old buffer. */
- *(yy_c_buf_p) = (yy_hold_char);
- YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
- }
-
- YY_CURRENT_BUFFER_LVALUE = new_buffer;
- yy_load_buffer_state( );
-
- /* We don't actually know whether we did this switch during
- * EOF (yywrap()) processing, but the only time this flag
- * is looked at is after yywrap() is called, so it's safe
- * to go ahead and always set it.
- */
- (yy_did_buffer_switch_on_eof) = 1;
-}
-
-static void yy_load_buffer_state (void)
-{
- (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
- (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
- yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
- (yy_hold_char) = *(yy_c_buf_p);
-}
-
-/** Allocate and initialize an input buffer state.
- * @param file A readable stream.
- * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
- *
- * @return the allocated buffer state.
- */
- YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
-{
- YY_BUFFER_STATE b;
-
- b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
- b->yy_buf_size = size;
-
- /* yy_ch_buf has to be 2 characters longer than the size given because
- * we need to put in 2 end-of-buffer characters.
- */
- b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
- if ( ! b->yy_ch_buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
-
- b->yy_is_our_buffer = 1;
-
- yy_init_buffer(b,file );
-
- return b;
-}
-
-/** Destroy the buffer.
- * @param b a buffer created with yy_create_buffer()
- *
- */
- void yy_delete_buffer (YY_BUFFER_STATE b )
-{
-
- if ( ! b )
- return;
-
- if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
- YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
-
- if ( b->yy_is_our_buffer )
- yyfree((void *) b->yy_ch_buf );
-
- yyfree((void *) b );
-}
-
-#ifndef __cplusplus
-extern int isatty (int );
-#endif /* __cplusplus */
-
-/* Initializes or reinitializes a buffer.
- * This function is sometimes called more than once on the same buffer,
- * such as during a yyrestart() or at EOF.
- */
- static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
-
-{
- int oerrno = errno;
-
- yy_flush_buffer(b );
-
- b->yy_input_file = file;
- b->yy_fill_buffer = 1;
-
- /* If b is the current buffer, then yy_init_buffer was _probably_
- * called from yyrestart() or through yy_get_next_buffer.
- * In that case, we don't want to reset the lineno or column.
- */
- if (b != YY_CURRENT_BUFFER){
- b->yy_bs_lineno = 1;
- b->yy_bs_column = 0;
- }
-
- b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
-
- errno = oerrno;
-}
-
-/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
- * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
- *
- */
- void yy_flush_buffer (YY_BUFFER_STATE b )
-{
- if ( ! b )
- return;
-
- b->yy_n_chars = 0;
-
- /* We always need two end-of-buffer characters. The first causes
- * a transition to the end-of-buffer state. The second causes
- * a jam in that state.
- */
- b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
- b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
-
- b->yy_buf_pos = &b->yy_ch_buf[0];
-
- b->yy_at_bol = 1;
- b->yy_buffer_status = YY_BUFFER_NEW;
-
- if ( b == YY_CURRENT_BUFFER )
- yy_load_buffer_state( );
-}
-
-/** Pushes the new state onto the stack. The new state becomes
- * the current state. This function will allocate the stack
- * if necessary.
- * @param new_buffer The new state.
- *
- */
-void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
-{
- if (new_buffer == NULL)
- return;
-
- yyensure_buffer_stack();
-
- /* This block is copied from yy_switch_to_buffer. */
- if ( YY_CURRENT_BUFFER )
- {
- /* Flush out information for old buffer. */
- *(yy_c_buf_p) = (yy_hold_char);
- YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
- YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
- }
-
- /* Only push if top exists. Otherwise, replace top. */
- if (YY_CURRENT_BUFFER)
- (yy_buffer_stack_top)++;
- YY_CURRENT_BUFFER_LVALUE = new_buffer;
-
- /* copied from yy_switch_to_buffer. */
- yy_load_buffer_state( );
- (yy_did_buffer_switch_on_eof) = 1;
-}
-
-/** Removes and deletes the top of the stack, if present.
- * The next element becomes the new top.
- *
- */
-void yypop_buffer_state (void)
-{
- if (!YY_CURRENT_BUFFER)
- return;
-
- yy_delete_buffer(YY_CURRENT_BUFFER );
- YY_CURRENT_BUFFER_LVALUE = NULL;
- if ((yy_buffer_stack_top) > 0)
- --(yy_buffer_stack_top);
-
- if (YY_CURRENT_BUFFER) {
- yy_load_buffer_state( );
- (yy_did_buffer_switch_on_eof) = 1;
- }
-}
-
-/* Allocates the stack if it does not exist.
- * Guarantees space for at least one push.
- */
-static void yyensure_buffer_stack (void)
-{
- int num_to_alloc;
-
- if (!(yy_buffer_stack)) {
-
- /* First allocation is just for 2 elements, since we don't know if this
- * scanner will even need a stack. We use 2 instead of 1 to avoid an
- * immediate realloc on the next call.
- */
- num_to_alloc = 1;
- (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
- (num_to_alloc * sizeof(struct yy_buffer_state*)
- );
- if ( ! (yy_buffer_stack) )
- YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
- memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
-
- (yy_buffer_stack_max) = num_to_alloc;
- (yy_buffer_stack_top) = 0;
- return;
- }
-
- if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
-
- /* Increase the buffer to prepare for a possible push. */
- int grow_size = 8 /* arbitrary grow size */;
-
- num_to_alloc = (yy_buffer_stack_max) + grow_size;
- (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
- ((yy_buffer_stack),
- num_to_alloc * sizeof(struct yy_buffer_state*)
- );
- if ( ! (yy_buffer_stack) )
- YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
-
- /* zero only the new slots.*/
- memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
- (yy_buffer_stack_max) = num_to_alloc;
- }
-}
-
-/** Setup the input buffer state to scan directly from a user-specified character buffer.
- * @param base the character buffer
- * @param size the size in bytes of the character buffer
- *
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
-{
- YY_BUFFER_STATE b;
-
- if ( size < 2 ||
- base[size-2] != YY_END_OF_BUFFER_CHAR ||
- base[size-1] != YY_END_OF_BUFFER_CHAR )
- /* They forgot to leave room for the EOB's. */
- return 0;
-
- b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
- if ( ! b )
- YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
-
- b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
- b->yy_buf_pos = b->yy_ch_buf = base;
- b->yy_is_our_buffer = 0;
- b->yy_input_file = 0;
- b->yy_n_chars = b->yy_buf_size;
- b->yy_is_interactive = 0;
- b->yy_at_bol = 1;
- b->yy_fill_buffer = 0;
- b->yy_buffer_status = YY_BUFFER_NEW;
-
- yy_switch_to_buffer(b );
-
- return b;
-}
-
-/** Setup the input buffer state to scan a string. The next call to yylex() will
- * scan from a @e copy of @a str.
- * @param yystr a NUL-terminated string to scan
- *
- * @return the newly allocated buffer state object.
- * @note If you want to scan bytes that may contain NUL values, then use
- * yy_scan_bytes() instead.
- */
-YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
-{
-
- return yy_scan_bytes(yystr,strlen(yystr) );
-}
-
-/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
- * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
- *
- * @return the newly allocated buffer state object.
- */
-YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
-{
- YY_BUFFER_STATE b;
- char *buf;
- yy_size_t n;
- int i;
-
- /* Get memory for full buffer, including space for trailing EOB's. */
- n = _yybytes_len + 2;
- buf = (char *) yyalloc(n );
- if ( ! buf )
- YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
-
- for ( i = 0; i < _yybytes_len; ++i )
- buf[i] = yybytes[i];
-
- buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
-
- b = yy_scan_buffer(buf,n );
- if ( ! b )
- YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
-
- /* It's okay to grow etc. this buffer, and we should throw it
- * away when we're done.
- */
- b->yy_is_our_buffer = 1;
-
- return b;
-}
-
-#ifndef YY_EXIT_FAILURE
-#define YY_EXIT_FAILURE 2
-#endif
-
-static void yy_fatal_error (yyconst char* msg )
-{
- (void) fprintf( stderr, "%s\n", msg );
- exit( YY_EXIT_FAILURE );
-}
-
-/* Redefine yyless() so it works in section 3 code. */
-
-#undef yyless
-#define yyless(n) \
- do \
- { \
- /* Undo effects of setting up yytext. */ \
- int yyless_macro_arg = (n); \
- YY_LESS_LINENO(yyless_macro_arg);\
- yytext[yyleng] = (yy_hold_char); \
- (yy_c_buf_p) = yytext + yyless_macro_arg; \
- (yy_hold_char) = *(yy_c_buf_p); \
- *(yy_c_buf_p) = '\0'; \
- yyleng = yyless_macro_arg; \
- } \
- while ( 0 )
-
-/* Accessor methods (get/set functions) to struct members. */
-
-/** Get the current line number.
- *
- */
-int yyget_lineno (void)
-{
-
- return yylineno;
-}
-
-/** Get the input stream.
- *
- */
-FILE *yyget_in (void)
-{
- return yyin;
-}
-
-/** Get the output stream.
- *
- */
-FILE *yyget_out (void)
-{
- return yyout;
-}
-
-/** Get the length of the current token.
- *
- */
-int yyget_leng (void)
-{
- return yyleng;
-}
-
-/** Get the current token.
- *
- */
-
-char *yyget_text (void)
-{
- return yytext;
-}
-
-/** Set the current line number.
- * @param line_number
- *
- */
-void yyset_lineno (int line_number )
-{
-
- yylineno = line_number;
-}
-
-/** Set the input stream. This does not discard the current
- * input buffer.
- * @param in_str A readable stream.
- *
- * @see yy_switch_to_buffer
- */
-void yyset_in (FILE * in_str )
-{
- yyin = in_str ;
-}
-
-void yyset_out (FILE * out_str )
-{
- yyout = out_str ;
-}
-
-int yyget_debug (void)
-{
- return yy_flex_debug;
-}
-
-void yyset_debug (int bdebug )
-{
- yy_flex_debug = bdebug ;
-}
-
-static int yy_init_globals (void)
-{
- /* Initialization is the same as for the non-reentrant scanner.
- * This function is called from yylex_destroy(), so don't allocate here.
- */
-
- /* We do not touch yylineno unless the option is enabled. */
- yylineno = 1;
-
- (yy_buffer_stack) = 0;
- (yy_buffer_stack_top) = 0;
- (yy_buffer_stack_max) = 0;
- (yy_c_buf_p) = (char *) 0;
- (yy_init) = 0;
- (yy_start) = 0;
-
-/* Defined in main.c */
-#ifdef YY_STDINIT
- yyin = stdin;
- yyout = stdout;
-#else
- yyin = (FILE *) 0;
- yyout = (FILE *) 0;
-#endif
-
- /* For future reference: Set errno on error, since we are called by
- * yylex_init()
- */
- return 0;
-}
-
-/* yylex_destroy is for both reentrant and non-reentrant scanners. */
-int yylex_destroy (void)
-{
-
- /* Pop the buffer stack, destroying each element. */
- while(YY_CURRENT_BUFFER){
- yy_delete_buffer(YY_CURRENT_BUFFER );
- YY_CURRENT_BUFFER_LVALUE = NULL;
- yypop_buffer_state();
- }
-
- /* Destroy the stack itself. */
- yyfree((yy_buffer_stack) );
- (yy_buffer_stack) = NULL;
-
- /* Reset the globals. This is important in a non-reentrant scanner so the next time
- * yylex() is called, initialization will occur. */
- yy_init_globals( );
-
- return 0;
-}
-
-/*
- * Internal utility routines.
- */
-
-#ifndef yytext_ptr
-static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
-{
- register int i;
- for ( i = 0; i < n; ++i )
- s1[i] = s2[i];
-}
-#endif
-
-#ifdef YY_NEED_STRLEN
-static int yy_flex_strlen (yyconst char * s )
-{
- register int n;
- for ( n = 0; s[n]; ++n )
- ;
-
- return n;
-}
-#endif
-
-void *yyalloc (yy_size_t size )
-{
- return (void *) malloc( size );
-}
-
-void *yyrealloc (void * ptr, yy_size_t size )
-{
- /* The cast to (char *) in the following accommodates both
- * implementations that use char* generic pointers, and those
- * that use void* generic pointers. It works with the latter
- * because both ANSI C and C++ allow castless assignment from
- * any pointer type to void*, and deal with argument conversions
- * as though doing an assignment.
- */
- return (void *) realloc( (char *) ptr, size );
-}
-
-void yyfree (void * ptr )
-{
- free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
-}
-
-#define YYTABLES_NAME "yytables"
-
-#line 222 "dtc-lexer.l"
-
-
-
-
-/*
- * Stack of nested include file contexts.
- */
-
-struct incl_file {
- struct dtc_file *file;
- YY_BUFFER_STATE yy_prev_buf;
- int yy_prev_lineno;
- struct incl_file *prev;
-};
-
-static struct incl_file *incl_file_stack;
-
-
-/*
- * Detect infinite include recursion.
- */
-#define MAX_INCLUDE_DEPTH (100)
-
-static int incl_depth = 0;
-
-
-static void push_input_file(const char *filename)
-{
- struct incl_file *incl_file;
- struct dtc_file *newfile;
- struct search_path search, *searchptr = NULL;
-
- assert(filename);
-
- if (incl_depth++ >= MAX_INCLUDE_DEPTH)
- die("Includes nested too deeply");
-
- if (srcpos_file) {
- search.dir = srcpos_file->dir;
- search.next = NULL;
- search.prev = NULL;
- searchptr = &search;
- }
-
- newfile = dtc_open_file(filename, searchptr);
-
- incl_file = xmalloc(sizeof(struct incl_file));
-
- /*
- * Save current context.
- */
- incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
- incl_file->yy_prev_lineno = yylineno;
- incl_file->file = srcpos_file;
- incl_file->prev = incl_file_stack;
-
- incl_file_stack = incl_file;
-
- /*
- * Establish new context.
- */
- srcpos_file = newfile;
- yylineno = 1;
- yyin = newfile->file;
- yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
-}
-
-
-static int pop_input_file(void)
-{
- struct incl_file *incl_file;
-
- if (incl_file_stack == 0)
- return 0;
-
- dtc_close_file(srcpos_file);
-
- /*
- * Pop.
- */
- --incl_depth;
- incl_file = incl_file_stack;
- incl_file_stack = incl_file->prev;
-
- /*
- * Recover old context.
- */
- yy_delete_buffer(YY_CURRENT_BUFFER);
- yy_switch_to_buffer(incl_file->yy_prev_buf);
- yylineno = incl_file->yy_prev_lineno;
- srcpos_file = incl_file->file;
- yyin = incl_file->file ? incl_file->file->file : NULL;
-
- /*
- * Free old state.
- */
- free(incl_file);
-
- return 1;
-}
-
+++ /dev/null
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Skeleton implementation for Bison's Yacc-like parsers in C
-
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
-
- 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, 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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* C LALR(1) parser skeleton written by Richard Stallman, by
- simplifying the original so-called "semantic" parser. */
-
-/* All symbols defined below should begin with yy or YY, to avoid
- infringing on user name space. This should be done even for local
- variables, as they might otherwise be expanded by user macros.
- There are some unavoidable exceptions within include files to
- define necessary library symbols; they are noted "INFRINGES ON
- USER NAME SPACE" below. */
-
-/* Identify Bison output. */
-#define YYBISON 1
-
-/* Bison version. */
-#define YYBISON_VERSION "2.3"
-
-/* Skeleton name. */
-#define YYSKELETON_NAME "yacc.c"
-
-/* Pure parsers. */
-#define YYPURE 0
-
-/* Using locations. */
-#define YYLSP_NEEDED 1
-
-
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- DT_V1 = 258,
- DT_MEMRESERVE = 259,
- DT_PROPNODENAME = 260,
- DT_LITERAL = 261,
- DT_LEGACYLITERAL = 262,
- DT_BASE = 263,
- DT_BYTE = 264,
- DT_STRING = 265,
- DT_LABEL = 266,
- DT_REF = 267,
- DT_INCBIN = 268
- };
-#endif
-/* Tokens. */
-#define DT_V1 258
-#define DT_MEMRESERVE 259
-#define DT_PROPNODENAME 260
-#define DT_LITERAL 261
-#define DT_LEGACYLITERAL 262
-#define DT_BASE 263
-#define DT_BYTE 264
-#define DT_STRING 265
-#define DT_LABEL 266
-#define DT_REF 267
-#define DT_INCBIN 268
-
-
-
-
-/* Copy the first part of user declarations. */
-#line 23 "dtc-parser.y"
-
-#include <stdio.h>
-
-#include "dtc.h"
-#include "srcpos.h"
-
-extern int yylex(void);
-
-extern struct boot_info *the_boot_info;
-extern int treesource_error;
-
-static unsigned long long eval_literal(const char *s, int base, int bits);
-
-
-/* Enabling traces. */
-#ifndef YYDEBUG
-# define YYDEBUG 0
-#endif
-
-/* Enabling verbose error messages. */
-#ifdef YYERROR_VERBOSE
-# undef YYERROR_VERBOSE
-# define YYERROR_VERBOSE 1
-#else
-# define YYERROR_VERBOSE 0
-#endif
-
-/* Enabling the token table. */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 37 "dtc-parser.y"
-{
- char *propnodename;
- char *literal;
- char *labelref;
- unsigned int cbase;
- uint8_t byte;
- struct data data;
-
- uint64_t addr;
- cell_t cell;
- struct property *prop;
- struct property *proplist;
- struct node *node;
- struct node *nodelist;
- struct reserve_info *re;
-}
-/* Line 187 of yacc.c. */
-#line 153 "dtc-parser.tab.c"
- YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
-{
- int first_line;
- int first_column;
- int last_line;
- int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-
-/* Copy the second part of user declarations. */
-
-
-/* Line 216 of yacc.c. */
-#line 178 "dtc-parser.tab.c"
-
-#ifdef short
-# undef short
-#endif
-
-#ifdef YYTYPE_UINT8
-typedef YYTYPE_UINT8 yytype_uint8;
-#else
-typedef unsigned char yytype_uint8;
-#endif
-
-#ifdef YYTYPE_INT8
-typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
-#else
-typedef short int yytype_int8;
-#endif
-
-#ifdef YYTYPE_UINT16
-typedef YYTYPE_UINT16 yytype_uint16;
-#else
-typedef unsigned short int yytype_uint16;
-#endif
-
-#ifdef YYTYPE_INT16
-typedef YYTYPE_INT16 yytype_int16;
-#else
-typedef short int yytype_int16;
-#endif
-
-#ifndef YYSIZE_T
-# ifdef __SIZE_TYPE__
-# define YYSIZE_T __SIZE_TYPE__
-# elif defined size_t
-# define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
-# define YYSIZE_T size_t
-# else
-# define YYSIZE_T unsigned int
-# endif
-#endif
-
-#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
-
-#ifndef YY_
-# if YYENABLE_NLS
-# if ENABLE_NLS
-# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-# define YY_(msgid) dgettext ("bison-runtime", msgid)
-# endif
-# endif
-# ifndef YY_
-# define YY_(msgid) msgid
-# endif
-#endif
-
-/* Suppress unused-variable warnings by "using" E. */
-#if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
-#else
-# define YYUSE(e) /* empty */
-#endif
-
-/* Identity function, used to suppress warnings about constant conditions. */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int i)
-#else
-static int
-YYID (i)
- int i;
-#endif
-{
- return i;
-}
-#endif
-
-#if ! defined yyoverflow || YYERROR_VERBOSE
-
-/* The parser invokes alloca or malloc; define the necessary symbols. */
-
-# ifdef YYSTACK_USE_ALLOCA
-# if YYSTACK_USE_ALLOCA
-# ifdef __GNUC__
-# define YYSTACK_ALLOC __builtin_alloca
-# elif defined __BUILTIN_VA_ARG_INCR
-# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
-# elif defined _AIX
-# define YYSTACK_ALLOC __alloca
-# elif defined _MSC_VER
-# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
-# define alloca _alloca
-# else
-# define YYSTACK_ALLOC alloca
-# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
-# endif
-# endif
-# endif
-# endif
-# endif
-
-# ifdef YYSTACK_ALLOC
- /* Pacify GCC's `empty if-body' warning. */
-# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
-# ifndef YYSTACK_ALLOC_MAXIMUM
- /* The OS might guarantee only one guard page at the bottom of the stack,
- and a page size can be as small as 4096 bytes. So we cannot safely
- invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
- to allow for a few compiler-allocated temporary stack slots. */
-# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
-# endif
-# else
-# define YYSTACK_ALLOC YYMALLOC
-# define YYSTACK_FREE YYFREE
-# ifndef YYSTACK_ALLOC_MAXIMUM
-# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
-# endif
-# if (defined __cplusplus && ! defined _STDLIB_H \
- && ! ((defined YYMALLOC || defined malloc) \
- && (defined YYFREE || defined free)))
-# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
-# ifndef _STDLIB_H
-# define _STDLIB_H 1
-# endif
-# endif
-# ifndef YYMALLOC
-# define YYMALLOC malloc
-# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# ifndef YYFREE
-# define YYFREE free
-# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-void free (void *); /* INFRINGES ON USER NAME SPACE */
-# endif
-# endif
-# endif
-#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
-
-
-#if (! defined yyoverflow \
- && (! defined __cplusplus \
- || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
- && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
-
-/* A type that is properly aligned for any stack member. */
-union yyalloc
-{
- yytype_int16 yyss;
- YYSTYPE yyvs;
- YYLTYPE yyls;
-};
-
-/* The size of the maximum gap between one aligned stack and the next. */
-# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
-
-/* The size of an array large to enough to hold all stacks, each with
- N elements. */
-# define YYSTACK_BYTES(N) \
- ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
- + 2 * YYSTACK_GAP_MAXIMUM)
-
-/* Copy COUNT objects from FROM to TO. The source and destination do
- not overlap. */
-# ifndef YYCOPY
-# if defined __GNUC__ && 1 < __GNUC__
-# define YYCOPY(To, From, Count) \
- __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
-# else
-# define YYCOPY(To, From, Count) \
- do \
- { \
- YYSIZE_T yyi; \
- for (yyi = 0; yyi < (Count); yyi++) \
- (To)[yyi] = (From)[yyi]; \
- } \
- while (YYID (0))
-# endif
-# endif
-
-/* Relocate STACK from its old location to the new one. The
- local variables YYSIZE and YYSTACKSIZE give the old and new number of
- elements in the stack, and YYPTR gives the new location of the
- stack. Advance YYPTR to a properly aligned location for the next
- stack. */
-# define YYSTACK_RELOCATE(Stack) \
- do \
- { \
- YYSIZE_T yynewbytes; \
- YYCOPY (&yyptr->Stack, Stack, yysize); \
- Stack = &yyptr->Stack; \
- yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
- yyptr += yynewbytes / sizeof (*yyptr); \
- } \
- while (YYID (0))
-
-#endif
-
-/* YYFINAL -- State number of the termination state. */
-#define YYFINAL 9
-/* YYLAST -- Last index in YYTABLE. */
-#define YYLAST 73
-
-/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 27
-/* YYNNTS -- Number of nonterminals. */
-#define YYNNTS 20
-/* YYNRULES -- Number of rules. */
-#define YYNRULES 45
-/* YYNRULES -- Number of states. */
-#define YYNSTATES 76
-
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
-#define YYUNDEFTOK 2
-#define YYMAXUTOK 268
-
-#define YYTRANSLATE(YYX) \
- ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
-
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
-static const yytype_uint8 yytranslate[] =
-{
- 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 24, 26, 2, 2, 25, 15, 2, 16, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 14,
- 20, 19, 21, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 22, 2, 23, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 17, 2, 18, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9, 10, 11, 12, 13
-};
-
-#if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
- YYRHS. */
-static const yytype_uint8 yyprhs[] =
-{
- 0, 0, 3, 8, 11, 12, 15, 21, 22, 25,
- 27, 34, 36, 38, 41, 47, 48, 51, 57, 61,
- 64, 69, 74, 77, 87, 93, 96, 97, 100, 103,
- 104, 107, 110, 113, 114, 116, 118, 121, 122, 125,
- 128, 129, 132, 135, 139, 140
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS. */
-static const yytype_int8 yyrhs[] =
-{
- 28, 0, -1, 3, 14, 29, 34, -1, 31, 34,
- -1, -1, 30, 29, -1, 46, 4, 33, 33, 14,
- -1, -1, 32, 31, -1, 30, -1, 46, 4, 33,
- 15, 33, 14, -1, 6, -1, 7, -1, 16, 35,
- -1, 17, 36, 44, 18, 14, -1, -1, 36, 37,
- -1, 46, 5, 19, 38, 14, -1, 46, 5, 14,
- -1, 39, 10, -1, 39, 20, 40, 21, -1, 39,
- 22, 43, 23, -1, 39, 12, -1, 39, 13, 24,
- 10, 25, 33, 25, 33, 26, -1, 39, 13, 24,
- 10, 26, -1, 38, 11, -1, -1, 38, 25, -1,
- 39, 11, -1, -1, 40, 42, -1, 40, 12, -1,
- 40, 11, -1, -1, 8, -1, 6, -1, 41, 7,
- -1, -1, 43, 9, -1, 43, 11, -1, -1, 45,
- 44, -1, 45, 37, -1, 46, 5, 35, -1, -1,
- 11, -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
-static const yytype_uint16 yyrline[] =
-{
- 0, 89, 89, 93, 101, 104, 111, 119, 122, 129,
- 133, 140, 144, 151, 158, 166, 169, 176, 180, 187,
- 191, 195, 199, 203, 220, 231, 239, 242, 246, 254,
- 257, 261, 266, 274, 277, 281, 285, 293, 296, 300,
- 308, 311, 315, 323, 331, 334
-};
-#endif
-
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
-/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
- First, the terminals, then, starting at YYNTOKENS, nonterminals. */
-static const char *const yytname[] =
-{
- "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
- "DT_PROPNODENAME", "DT_LITERAL", "DT_LEGACYLITERAL", "DT_BASE",
- "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'-'",
- "'/'", "'{'", "'}'", "'='", "'<'", "'>'", "'['", "']'", "'('", "','",
- "')'", "$accept", "sourcefile", "memreserves", "memreserve",
- "v0_memreserves", "v0_memreserve", "addr", "devicetree", "nodedef",
- "proplist", "propdef", "propdata", "propdataprefix", "celllist",
- "cellbase", "cellval", "bytestring", "subnodes", "subnode", "label", 0
-};
-#endif
-
-# ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
- token YYLEX-NUM. */
-static const yytype_uint16 yytoknum[] =
-{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
- 265, 266, 267, 268, 59, 45, 47, 123, 125, 61,
- 60, 62, 91, 93, 40, 44, 41
-};
-# endif
-
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
-static const yytype_uint8 yyr1[] =
-{
- 0, 27, 28, 28, 29, 29, 30, 31, 31, 32,
- 32, 33, 33, 34, 35, 36, 36, 37, 37, 38,
- 38, 38, 38, 38, 38, 38, 39, 39, 39, 40,
- 40, 40, 40, 41, 41, 42, 42, 43, 43, 43,
- 44, 44, 44, 45, 46, 46
-};
-
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
-static const yytype_uint8 yyr2[] =
-{
- 0, 2, 4, 2, 0, 2, 5, 0, 2, 1,
- 6, 1, 1, 2, 5, 0, 2, 5, 3, 2,
- 4, 4, 2, 9, 5, 2, 0, 2, 2, 0,
- 2, 2, 2, 0, 1, 1, 2, 0, 2, 2,
- 0, 2, 2, 3, 0, 1
-};
-
-/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
- STATE-NUM when YYTABLE doesn't specify something else to do. Zero
- means the default is an error. */
-static const yytype_uint8 yydefact[] =
-{
- 7, 0, 45, 0, 9, 0, 7, 0, 4, 1,
- 0, 3, 8, 0, 0, 4, 0, 15, 13, 11,
- 12, 0, 2, 5, 0, 40, 0, 0, 0, 16,
- 0, 40, 0, 0, 6, 0, 42, 41, 0, 10,
- 14, 18, 26, 43, 0, 0, 25, 17, 27, 19,
- 28, 22, 0, 29, 37, 0, 33, 0, 0, 35,
- 34, 32, 31, 20, 0, 30, 38, 39, 21, 0,
- 24, 36, 0, 0, 0, 23
-};
-
-/* YYDEFGOTO[NTERM-NUM]. */
-static const yytype_int8 yydefgoto[] =
-{
- -1, 3, 14, 4, 5, 6, 27, 11, 18, 25,
- 29, 44, 45, 56, 64, 65, 57, 30, 31, 7
-};
-
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
- STATE-NUM. */
-#define YYPACT_NINF -14
-static const yytype_int8 yypact[] =
-{
- 30, -11, -14, 7, -14, -1, 27, 13, 27, -14,
- 8, -14, -14, 40, -1, 27, 35, -14, -14, -14,
- -14, 21, -14, -14, 40, 24, 40, 28, 40, -14,
- 32, 24, 46, 38, -14, 39, -14, -14, 26, -14,
- -14, -14, -14, -14, -9, 10, -14, -14, -14, -14,
- -14, -14, 31, -14, -14, 44, -2, 3, 23, -14,
- -14, -14, -14, -14, 50, -14, -14, -14, -14, 40,
- -14, -14, 33, 40, 36, -14
-};
-
-/* YYPGOTO[NTERM-NUM]. */
-static const yytype_int8 yypgoto[] =
-{
- -14, -14, 48, 29, 53, -14, -13, 47, 34, -14,
- 37, -14, -14, -14, -14, -14, -14, 42, -14, -7
-};
-
-/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
- positive, shift that token. If negative, reduce the rule which
- number is the opposite. If zero, do what YYDEFACT says.
- If YYTABLE_NINF, syntax error. */
-#define YYTABLE_NINF -45
-static const yytype_int8 yytable[] =
-{
- 21, 16, 46, 8, 59, 47, 60, 9, 16, 61,
- 62, 28, 66, 33, 67, 10, 48, 13, 32, 63,
- 49, 50, 51, 52, 32, 17, 68, 19, 20, -44,
- 53, -44, 54, 1, -44, 2, 26, 15, 2, 24,
- 41, 2, 34, 17, 15, 42, 19, 20, 69, 70,
- 35, 38, 39, 40, 58, 55, 72, 71, 73, 12,
- 74, 22, 75, 23, 0, 0, 0, 0, 36, 0,
- 0, 0, 43, 37
-};
-
-static const yytype_int8 yycheck[] =
-{
- 13, 8, 11, 14, 6, 14, 8, 0, 15, 11,
- 12, 24, 9, 26, 11, 16, 25, 4, 25, 21,
- 10, 11, 12, 13, 31, 17, 23, 6, 7, 5,
- 20, 4, 22, 3, 4, 11, 15, 8, 11, 4,
- 14, 11, 14, 17, 15, 19, 6, 7, 25, 26,
- 18, 5, 14, 14, 10, 24, 69, 7, 25, 6,
- 73, 14, 26, 15, -1, -1, -1, -1, 31, -1,
- -1, -1, 38, 31
-};
-
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
- symbol of state STATE-NUM. */
-static const yytype_uint8 yystos[] =
-{
- 0, 3, 11, 28, 30, 31, 32, 46, 14, 0,
- 16, 34, 31, 4, 29, 30, 46, 17, 35, 6,
- 7, 33, 34, 29, 4, 36, 15, 33, 33, 37,
- 44, 45, 46, 33, 14, 18, 37, 44, 5, 14,
- 14, 14, 19, 35, 38, 39, 11, 14, 25, 10,
- 11, 12, 13, 20, 22, 24, 40, 43, 10, 6,
- 8, 11, 12, 21, 41, 42, 9, 11, 23, 25,
- 26, 7, 33, 25, 33, 26
-};
-
-#define yyerrok (yyerrstatus = 0)
-#define yyclearin (yychar = YYEMPTY)
-#define YYEMPTY (-2)
-#define YYEOF 0
-
-#define YYACCEPT goto yyacceptlab
-#define YYABORT goto yyabortlab
-#define YYERROR goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror. This remains here temporarily
- to ease the transition to the new meaning of YYERROR, for GCC.
- Once GCC version 2 has supplanted version 1, this can go. */
-
-#define YYFAIL goto yyerrlab
-
-#define YYRECOVERING() (!!yyerrstatus)
-
-#define YYBACKUP(Token, Value) \
-do \
- if (yychar == YYEMPTY && yylen == 1) \
- { \
- yychar = (Token); \
- yylval = (Value); \
- yytoken = YYTRANSLATE (yychar); \
- YYPOPSTACK (1); \
- goto yybackup; \
- } \
- else \
- { \
- yyerror (YY_("syntax error: cannot back up")); \
- YYERROR; \
- } \
-while (YYID (0))
-
-
-#define YYTERROR 1
-#define YYERRCODE 256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
- If N is 0, then set CURRENT to the empty location which ends
- the previous symbol: RHS[0] (always defined). */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- } \
- while (YYID (0))
-#endif
-
-
-/* YY_LOCATION_PRINT -- Print the location on the stream.
- This macro was not mandated originally: define only if we know
- we won't break user code: when these are the locations we know. */
-
-#ifndef YY_LOCATION_PRINT
-# if YYLTYPE_IS_TRIVIAL
-# define YY_LOCATION_PRINT(File, Loc) \
- fprintf (File, "%d.%d-%d.%d", \
- (Loc).first_line, (Loc).first_column, \
- (Loc).last_line, (Loc).last_column)
-# else
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-# endif
-#endif
-
-
-/* YYLEX -- calling `yylex' with the right arguments. */
-
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
-
-/* Enable debugging if requested. */
-#if YYDEBUG
-
-# ifndef YYFPRINTF
-# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
-# define YYFPRINTF fprintf
-# endif
-
-# define YYDPRINTF(Args) \
-do { \
- if (yydebug) \
- YYFPRINTF Args; \
-} while (YYID (0))
-
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
-do { \
- if (yydebug) \
- { \
- YYFPRINTF (stderr, "%s ", Title); \
- yy_symbol_print (stderr, \
- Type, Value, Location); \
- YYFPRINTF (stderr, "\n"); \
- } \
-} while (YYID (0))
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
- YYLTYPE const * const yylocationp;
-#endif
-{
- if (!yyvaluep)
- return;
- YYUSE (yylocationp);
-# ifdef YYPRINT
- if (yytype < YYNTOKENS)
- YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
- YYUSE (yyoutput);
-# endif
- switch (yytype)
- {
- default:
- break;
- }
-}
-
-
-/*--------------------------------.
-| Print this symbol on YYOUTPUT. |
-`--------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
- FILE *yyoutput;
- int yytype;
- YYSTYPE const * const yyvaluep;
- YYLTYPE const * const yylocationp;
-#endif
-{
- if (yytype < YYNTOKENS)
- YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
- else
- YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
-
- YY_LOCATION_PRINT (yyoutput, *yylocationp);
- YYFPRINTF (yyoutput, ": ");
- yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp);
- YYFPRINTF (yyoutput, ")");
-}
-
-/*------------------------------------------------------------------.
-| yy_stack_print -- Print the state stack from its BOTTOM up to its |
-| TOP (included). |
-`------------------------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
-#else
-static void
-yy_stack_print (bottom, top)
- yytype_int16 *bottom;
- yytype_int16 *top;
-#endif
-{
- YYFPRINTF (stderr, "Stack now");
- for (; bottom <= top; ++bottom)
- YYFPRINTF (stderr, " %d", *bottom);
- YYFPRINTF (stderr, "\n");
-}
-
-# define YY_STACK_PRINT(Bottom, Top) \
-do { \
- if (yydebug) \
- yy_stack_print ((Bottom), (Top)); \
-} while (YYID (0))
-
-
-/*------------------------------------------------.
-| Report that the YYRULE is going to be reduced. |
-`------------------------------------------------*/
-
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yylsp, yyrule)
- YYSTYPE *yyvsp;
- YYLTYPE *yylsp;
- int yyrule;
-#endif
-{
- int yynrhs = yyr2[yyrule];
- int yyi;
- unsigned long int yylno = yyrline[yyrule];
- YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
- yyrule - 1, yylno);
- /* The symbols being reduced. */
- for (yyi = 0; yyi < yynrhs; yyi++)
- {
- fprintf (stderr, " $%d = ", yyi + 1);
- yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
- &(yyvsp[(yyi + 1) - (yynrhs)])
- , &(yylsp[(yyi + 1) - (yynrhs)]) );
- fprintf (stderr, "\n");
- }
-}
-
-# define YY_REDUCE_PRINT(Rule) \
-do { \
- if (yydebug) \
- yy_reduce_print (yyvsp, yylsp, Rule); \
-} while (YYID (0))
-
-/* Nonzero means print parse trace. It is left uninitialized so that
- multiple parsers can coexist. */
-int yydebug;
-#else /* !YYDEBUG */
-# define YYDPRINTF(Args)
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
-# define YY_STACK_PRINT(Bottom, Top)
-# define YY_REDUCE_PRINT(Rule)
-#endif /* !YYDEBUG */
-
-
-/* YYINITDEPTH -- initial size of the parser's stacks. */
-#ifndef YYINITDEPTH
-# define YYINITDEPTH 200
-#endif
-
-/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
- if the built-in stack extension method is used).
-
- Do not make this value too large; the results are undefined if
- YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
- evaluated with infinite-precision integer arithmetic. */
-
-#ifndef YYMAXDEPTH
-# define YYMAXDEPTH 10000
-#endif
-
-\f
-
-#if YYERROR_VERBOSE
-
-# ifndef yystrlen
-# if defined __GLIBC__ && defined _STRING_H
-# define yystrlen strlen
-# else
-/* Return the length of YYSTR. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static YYSIZE_T
-yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
- const char *yystr;
-#endif
-{
- YYSIZE_T yylen;
- for (yylen = 0; yystr[yylen]; yylen++)
- continue;
- return yylen;
-}
-# endif
-# endif
-
-# ifndef yystpcpy
-# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
-# define yystpcpy stpcpy
-# else
-/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
- YYDEST. */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static char *
-yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
- char *yydest;
- const char *yysrc;
-#endif
-{
- char *yyd = yydest;
- const char *yys = yysrc;
-
- while ((*yyd++ = *yys++) != '\0')
- continue;
-
- return yyd - 1;
-}
-# endif
-# endif
-
-# ifndef yytnamerr
-/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
- quotes and backslashes, so that it's suitable for yyerror. The
- heuristic is that double-quoting is unnecessary unless the string
- contains an apostrophe, a comma, or backslash (other than
- backslash-backslash). YYSTR is taken from yytname. If YYRES is
- null, do not copy; instead, return the length of what the result
- would have been. */
-static YYSIZE_T
-yytnamerr (char *yyres, const char *yystr)
-{
- if (*yystr == '"')
- {
- YYSIZE_T yyn = 0;
- char const *yyp = yystr;
-
- for (;;)
- switch (*++yyp)
- {
- case '\'':
- case ',':
- goto do_not_strip_quotes;
-
- case '\\':
- if (*++yyp != '\\')
- goto do_not_strip_quotes;
- /* Fall through. */
- default:
- if (yyres)
- yyres[yyn] = *yyp;
- yyn++;
- break;
-
- case '"':
- if (yyres)
- yyres[yyn] = '\0';
- return yyn;
- }
- do_not_strip_quotes: ;
- }
-
- if (! yyres)
- return yystrlen (yystr);
-
- return yystpcpy (yyres, yystr) - yyres;
-}
-# endif
-
-/* Copy into YYRESULT an error message about the unexpected token
- YYCHAR while in state YYSTATE. Return the number of bytes copied,
- including the terminating null byte. If YYRESULT is null, do not
- copy anything; just return the number of bytes that would be
- copied. As a special case, return 0 if an ordinary "syntax error"
- message will do. Return YYSIZE_MAXIMUM if overflow occurs during
- size calculation. */
-static YYSIZE_T
-yysyntax_error (char *yyresult, int yystate, int yychar)
-{
- int yyn = yypact[yystate];
-
- if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
- return 0;
- else
- {
- int yytype = YYTRANSLATE (yychar);
- YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
- YYSIZE_T yysize = yysize0;
- YYSIZE_T yysize1;
- int yysize_overflow = 0;
- enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
- char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
- int yyx;
-
-# if 0
- /* This is so xgettext sees the translatable formats that are
- constructed on the fly. */
- YY_("syntax error, unexpected %s");
- YY_("syntax error, unexpected %s, expecting %s");
- YY_("syntax error, unexpected %s, expecting %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s");
- YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
-# endif
- char *yyfmt;
- char const *yyf;
- static char const yyunexpected[] = "syntax error, unexpected %s";
- static char const yyexpecting[] = ", expecting %s";
- static char const yyor[] = " or %s";
- char yyformat[sizeof yyunexpected
- + sizeof yyexpecting - 1
- + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
- * (sizeof yyor - 1))];
- char const *yyprefix = yyexpecting;
-
- /* Start YYX at -YYN if negative to avoid negative indexes in
- YYCHECK. */
- int yyxbegin = yyn < 0 ? -yyn : 0;
-
- /* Stay within bounds of both yycheck and yytname. */
- int yychecklim = YYLAST - yyn + 1;
- int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
- int yycount = 1;
-
- yyarg[0] = yytname[yytype];
- yyfmt = yystpcpy (yyformat, yyunexpected);
-
- for (yyx = yyxbegin; yyx < yyxend; ++yyx)
- if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
- {
- if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
- {
- yycount = 1;
- yysize = yysize0;
- yyformat[sizeof yyunexpected - 1] = '\0';
- break;
- }
- yyarg[yycount++] = yytname[yyx];
- yysize1 = yysize + yytnamerr (0, yytname[yyx]);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
- yyfmt = yystpcpy (yyfmt, yyprefix);
- yyprefix = yyor;
- }
-
- yyf = YY_(yyformat);
- yysize1 = yysize + yystrlen (yyf);
- yysize_overflow |= (yysize1 < yysize);
- yysize = yysize1;
-
- if (yysize_overflow)
- return YYSIZE_MAXIMUM;
-
- if (yyresult)
- {
- /* Avoid sprintf, as that infringes on the user's name space.
- Don't have undefined behavior even if the translation
- produced a string with the wrong number of "%s"s. */
- char *yyp = yyresult;
- int yyi = 0;
- while ((*yyp = *yyf) != '\0')
- {
- if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
- {
- yyp += yytnamerr (yyp, yyarg[yyi++]);
- yyf += 2;
- }
- else
- {
- yyp++;
- yyf++;
- }
- }
- }
- return yysize;
- }
-}
-#endif /* YYERROR_VERBOSE */
-\f
-
-/*-----------------------------------------------.
-| Release the memory associated to this symbol. |
-`-----------------------------------------------*/
-
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-static void
-yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep, yylocationp)
- const char *yymsg;
- int yytype;
- YYSTYPE *yyvaluep;
- YYLTYPE *yylocationp;
-#endif
-{
- YYUSE (yyvaluep);
- YYUSE (yylocationp);
-
- if (!yymsg)
- yymsg = "Deleting";
- YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
-
- switch (yytype)
- {
-
- default:
- break;
- }
-}
-\f
-
-/* Prevent warnings from -Wmissing-prototypes. */
-
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
-
-
-
-/* The look-ahead symbol. */
-int yychar;
-
-/* The semantic value of the look-ahead symbol. */
-YYSTYPE yylval;
-
-/* Number of syntax errors so far. */
-int yynerrs;
-/* Location data for the look-ahead symbol. */
-YYLTYPE yylloc;
-
-
-
-/*----------.
-| yyparse. |
-`----------*/
-
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
- void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
- || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
-{
-
- int yystate;
- int yyn;
- int yyresult;
- /* Number of tokens to shift before error messages enabled. */
- int yyerrstatus;
- /* Look-ahead token as an internal (translated) token number. */
- int yytoken = 0;
-#if YYERROR_VERBOSE
- /* Buffer for error messages, and its allocated size. */
- char yymsgbuf[128];
- char *yymsg = yymsgbuf;
- YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
-#endif
-
- /* Three stacks and their tools:
- `yyss': related to states,
- `yyvs': related to semantic values,
- `yyls': related to locations.
-
- Refer to the stacks thru separate pointers, to allow yyoverflow
- to reallocate them elsewhere. */
-
- /* The state stack. */
- yytype_int16 yyssa[YYINITDEPTH];
- yytype_int16 *yyss = yyssa;
- yytype_int16 *yyssp;
-
- /* The semantic value stack. */
- YYSTYPE yyvsa[YYINITDEPTH];
- YYSTYPE *yyvs = yyvsa;
- YYSTYPE *yyvsp;
-
- /* The location stack. */
- YYLTYPE yylsa[YYINITDEPTH];
- YYLTYPE *yyls = yylsa;
- YYLTYPE *yylsp;
- /* The locations where the error started and ended. */
- YYLTYPE yyerror_range[2];
-
-#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
-
- YYSIZE_T yystacksize = YYINITDEPTH;
-
- /* The variables used to return semantic value and location from the
- action routines. */
- YYSTYPE yyval;
- YYLTYPE yyloc;
-
- /* The number of symbols on the RHS of the reduced rule.
- Keep to zero when no symbol should be popped. */
- int yylen = 0;
-
- YYDPRINTF ((stderr, "Starting parse\n"));
-
- yystate = 0;
- yyerrstatus = 0;
- yynerrs = 0;
- yychar = YYEMPTY; /* Cause a token to be read. */
-
- /* Initialize stack pointers.
- Waste one element of value and location stack
- so that they stay on the same level as the state stack.
- The wasted elements are never initialized. */
-
- yyssp = yyss;
- yyvsp = yyvs;
- yylsp = yyls;
-#if YYLTYPE_IS_TRIVIAL
- /* Initialize the default location before parsing starts. */
- yylloc.first_line = yylloc.last_line = 1;
- yylloc.first_column = yylloc.last_column = 0;
-#endif
-
- goto yysetstate;
-
-/*------------------------------------------------------------.
-| yynewstate -- Push a new state, which is found in yystate. |
-`------------------------------------------------------------*/
- yynewstate:
- /* In all cases, when you get here, the value and location stacks
- have just been pushed. So pushing a state here evens the stacks. */
- yyssp++;
-
- yysetstate:
- *yyssp = yystate;
-
- if (yyss + yystacksize - 1 <= yyssp)
- {
- /* Get the current used size of the three stacks, in elements. */
- YYSIZE_T yysize = yyssp - yyss + 1;
-
-#ifdef yyoverflow
- {
- /* Give user a chance to reallocate the stack. Use copies of
- these so that the &'s don't force the real ones into
- memory. */
- YYSTYPE *yyvs1 = yyvs;
- yytype_int16 *yyss1 = yyss;
- YYLTYPE *yyls1 = yyls;
-
- /* Each stack pointer address is followed by the size of the
- data in use in that stack, in bytes. This used to be a
- conditional around just the two extra args, but that might
- be undefined if yyoverflow is a macro. */
- yyoverflow (YY_("memory exhausted"),
- &yyss1, yysize * sizeof (*yyssp),
- &yyvs1, yysize * sizeof (*yyvsp),
- &yyls1, yysize * sizeof (*yylsp),
- &yystacksize);
- yyls = yyls1;
- yyss = yyss1;
- yyvs = yyvs1;
- }
-#else /* no yyoverflow */
-# ifndef YYSTACK_RELOCATE
- goto yyexhaustedlab;
-# else
- /* Extend the stack our own way. */
- if (YYMAXDEPTH <= yystacksize)
- goto yyexhaustedlab;
- yystacksize *= 2;
- if (YYMAXDEPTH < yystacksize)
- yystacksize = YYMAXDEPTH;
-
- {
- yytype_int16 *yyss1 = yyss;
- union yyalloc *yyptr =
- (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
- if (! yyptr)
- goto yyexhaustedlab;
- YYSTACK_RELOCATE (yyss);
- YYSTACK_RELOCATE (yyvs);
- YYSTACK_RELOCATE (yyls);
-# undef YYSTACK_RELOCATE
- if (yyss1 != yyssa)
- YYSTACK_FREE (yyss1);
- }
-# endif
-#endif /* no yyoverflow */
-
- yyssp = yyss + yysize - 1;
- yyvsp = yyvs + yysize - 1;
- yylsp = yyls + yysize - 1;
-
- YYDPRINTF ((stderr, "Stack size increased to %lu\n",
- (unsigned long int) yystacksize));
-
- if (yyss + yystacksize - 1 <= yyssp)
- YYABORT;
- }
-
- YYDPRINTF ((stderr, "Entering state %d\n", yystate));
-
- goto yybackup;
-
-/*-----------.
-| yybackup. |
-`-----------*/
-yybackup:
-
- /* Do appropriate processing given the current state. Read a
- look-ahead token if we need one and don't already have one. */
-
- /* First try to decide what to do without reference to look-ahead token. */
- yyn = yypact[yystate];
- if (yyn == YYPACT_NINF)
- goto yydefault;
-
- /* Not known => get a look-ahead token if don't already have one. */
-
- /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
- if (yychar == YYEMPTY)
- {
- YYDPRINTF ((stderr, "Reading a token: "));
- yychar = YYLEX;
- }
-
- if (yychar <= YYEOF)
- {
- yychar = yytoken = YYEOF;
- YYDPRINTF ((stderr, "Now at end of input.\n"));
- }
- else
- {
- yytoken = YYTRANSLATE (yychar);
- YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
- }
-
- /* If the proper action on seeing token YYTOKEN is to reduce or to
- detect an error, take that action. */
- yyn += yytoken;
- if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
- goto yydefault;
- yyn = yytable[yyn];
- if (yyn <= 0)
- {
- if (yyn == 0 || yyn == YYTABLE_NINF)
- goto yyerrlab;
- yyn = -yyn;
- goto yyreduce;
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- /* Count tokens shifted since error; after three, turn off error
- status. */
- if (yyerrstatus)
- yyerrstatus--;
-
- /* Shift the look-ahead token. */
- YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
-
- /* Discard the shifted token unless it is eof. */
- if (yychar != YYEOF)
- yychar = YYEMPTY;
-
- yystate = yyn;
- *++yyvsp = yylval;
- *++yylsp = yylloc;
- goto yynewstate;
-
-
-/*-----------------------------------------------------------.
-| yydefault -- do the default action for the current state. |
-`-----------------------------------------------------------*/
-yydefault:
- yyn = yydefact[yystate];
- if (yyn == 0)
- goto yyerrlab;
- goto yyreduce;
-
-
-/*-----------------------------.
-| yyreduce -- Do a reduction. |
-`-----------------------------*/
-yyreduce:
- /* yyn is the number of a rule to reduce with. */
- yylen = yyr2[yyn];
-
- /* If YYLEN is nonzero, implement the default value of the action:
- `$$ = $1'.
-
- Otherwise, the following line sets YYVAL to garbage.
- This behavior is undocumented and Bison
- users should not rely upon it. Assigning to YYVAL
- unconditionally makes the parser a bit smaller, and it avoids a
- GCC warning that YYVAL may be used uninitialized. */
- yyval = yyvsp[1-yylen];
-
- /* Default location. */
- YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
- YY_REDUCE_PRINT (yyn);
- switch (yyn)
- {
- case 2:
-#line 90 "dtc-parser.y"
- {
- the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node), 0);
- ;}
- break;
-
- case 3:
-#line 94 "dtc-parser.y"
- {
- the_boot_info = build_boot_info((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].node), 0);
- ;}
- break;
-
- case 4:
-#line 101 "dtc-parser.y"
- {
- (yyval.re) = NULL;
- ;}
- break;
-
- case 5:
-#line 105 "dtc-parser.y"
- {
- (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
- ;}
- break;
-
- case 6:
-#line 112 "dtc-parser.y"
- {
- (yyval.re) = build_reserve_entry((yyvsp[(3) - (5)].addr), (yyvsp[(4) - (5)].addr), (yyvsp[(1) - (5)].labelref));
- ;}
- break;
-
- case 7:
-#line 119 "dtc-parser.y"
- {
- (yyval.re) = NULL;
- ;}
- break;
-
- case 8:
-#line 123 "dtc-parser.y"
- {
- (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
- ;}
- break;
-
- case 9:
-#line 130 "dtc-parser.y"
- {
- (yyval.re) = (yyvsp[(1) - (1)].re);
- ;}
- break;
-
- case 10:
-#line 134 "dtc-parser.y"
- {
- (yyval.re) = build_reserve_entry((yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr) - (yyvsp[(3) - (6)].addr) + 1, (yyvsp[(1) - (6)].labelref));
- ;}
- break;
-
- case 11:
-#line 141 "dtc-parser.y"
- {
- (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
- ;}
- break;
-
- case 12:
-#line 145 "dtc-parser.y"
- {
- (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 16, 64);
- ;}
- break;
-
- case 13:
-#line 152 "dtc-parser.y"
- {
- (yyval.node) = name_node((yyvsp[(2) - (2)].node), "", NULL);
- ;}
- break;
-
- case 14:
-#line 159 "dtc-parser.y"
- {
- (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
- ;}
- break;
-
- case 15:
-#line 166 "dtc-parser.y"
- {
- (yyval.proplist) = NULL;
- ;}
- break;
-
- case 16:
-#line 170 "dtc-parser.y"
- {
- (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
- ;}
- break;
-
- case 17:
-#line 177 "dtc-parser.y"
- {
- (yyval.prop) = build_property((yyvsp[(2) - (5)].propnodename), (yyvsp[(4) - (5)].data), (yyvsp[(1) - (5)].labelref));
- ;}
- break;
-
- case 18:
-#line 181 "dtc-parser.y"
- {
- (yyval.prop) = build_property((yyvsp[(2) - (3)].propnodename), empty_data, (yyvsp[(1) - (3)].labelref));
- ;}
- break;
-
- case 19:
-#line 188 "dtc-parser.y"
- {
- (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
- ;}
- break;
-
- case 20:
-#line 192 "dtc-parser.y"
- {
- (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
- ;}
- break;
-
- case 21:
-#line 196 "dtc-parser.y"
- {
- (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
- ;}
- break;
-
- case 22:
-#line 200 "dtc-parser.y"
- {
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
- ;}
- break;
-
- case 23:
-#line 204 "dtc-parser.y"
- {
- struct search_path path = { srcpos_file->dir, NULL, NULL };
- struct dtc_file *file = dtc_open_file((yyvsp[(4) - (9)].data).val, &path);
- struct data d = empty_data;
-
- if ((yyvsp[(6) - (9)].addr) != 0)
- if (fseek(file->file, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0)
- yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
- (unsigned long long)(yyvsp[(6) - (9)].addr),
- (yyvsp[(4) - (9)].data).val, strerror(errno));
-
- d = data_copy_file(file->file, (yyvsp[(8) - (9)].addr));
-
- (yyval.data) = data_merge((yyvsp[(1) - (9)].data), d);
- dtc_close_file(file);
- ;}
- break;
-
- case 24:
-#line 221 "dtc-parser.y"
- {
- struct search_path path = { srcpos_file->dir, NULL, NULL };
- struct dtc_file *file = dtc_open_file((yyvsp[(4) - (5)].data).val, &path);
- struct data d = empty_data;
-
- d = data_copy_file(file->file, -1);
-
- (yyval.data) = data_merge((yyvsp[(1) - (5)].data), d);
- dtc_close_file(file);
- ;}
- break;
-
- case 25:
-#line 232 "dtc-parser.y"
- {
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
- ;}
- break;
-
- case 26:
-#line 239 "dtc-parser.y"
- {
- (yyval.data) = empty_data;
- ;}
- break;
-
- case 27:
-#line 243 "dtc-parser.y"
- {
- (yyval.data) = (yyvsp[(1) - (2)].data);
- ;}
- break;
-
- case 28:
-#line 247 "dtc-parser.y"
- {
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
- ;}
- break;
-
- case 29:
-#line 254 "dtc-parser.y"
- {
- (yyval.data) = empty_data;
- ;}
- break;
-
- case 30:
-#line 258 "dtc-parser.y"
- {
- (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
- ;}
- break;
-
- case 31:
-#line 262 "dtc-parser.y"
- {
- (yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
- (yyvsp[(2) - (2)].labelref)), -1);
- ;}
- break;
-
- case 32:
-#line 267 "dtc-parser.y"
- {
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
- ;}
- break;
-
- case 33:
-#line 274 "dtc-parser.y"
- {
- (yyval.cbase) = 16;
- ;}
- break;
-
- case 35:
-#line 282 "dtc-parser.y"
- {
- (yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
- ;}
- break;
-
- case 36:
-#line 286 "dtc-parser.y"
- {
- (yyval.cell) = eval_literal((yyvsp[(2) - (2)].literal), (yyvsp[(1) - (2)].cbase), 32);
- ;}
- break;
-
- case 37:
-#line 293 "dtc-parser.y"
- {
- (yyval.data) = empty_data;
- ;}
- break;
-
- case 38:
-#line 297 "dtc-parser.y"
- {
- (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
- ;}
- break;
-
- case 39:
-#line 301 "dtc-parser.y"
- {
- (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
- ;}
- break;
-
- case 40:
-#line 308 "dtc-parser.y"
- {
- (yyval.nodelist) = NULL;
- ;}
- break;
-
- case 41:
-#line 312 "dtc-parser.y"
- {
- (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
- ;}
- break;
-
- case 42:
-#line 316 "dtc-parser.y"
- {
- yyerror("syntax error: properties must precede subnodes");
- YYERROR;
- ;}
- break;
-
- case 43:
-#line 324 "dtc-parser.y"
- {
- (yyval.node) = name_node((yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].propnodename), (yyvsp[(1) - (3)].labelref));
- ;}
- break;
-
- case 44:
-#line 331 "dtc-parser.y"
- {
- (yyval.labelref) = NULL;
- ;}
- break;
-
- case 45:
-#line 335 "dtc-parser.y"
- {
- (yyval.labelref) = (yyvsp[(1) - (1)].labelref);
- ;}
- break;
-
-
-/* Line 1267 of yacc.c. */
-#line 1780 "dtc-parser.tab.c"
- default: break;
- }
- YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
-
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
-
- *++yyvsp = yyval;
- *++yylsp = yyloc;
-
- /* Now `shift' the result of the reduction. Determine what state
- that goes to, based on the state we popped back to and the rule
- number reduced by. */
-
- yyn = yyr1[yyn];
-
- yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
- if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
- yystate = yytable[yystate];
- else
- yystate = yydefgoto[yyn - YYNTOKENS];
-
- goto yynewstate;
-
-
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
-yyerrlab:
- /* If not already recovering from an error, report this error. */
- if (!yyerrstatus)
- {
- ++yynerrs;
-#if ! YYERROR_VERBOSE
- yyerror (YY_("syntax error"));
-#else
- {
- YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
- if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
- {
- YYSIZE_T yyalloc = 2 * yysize;
- if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
- yyalloc = YYSTACK_ALLOC_MAXIMUM;
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
- yymsg = (char *) YYSTACK_ALLOC (yyalloc);
- if (yymsg)
- yymsg_alloc = yyalloc;
- else
- {
- yymsg = yymsgbuf;
- yymsg_alloc = sizeof yymsgbuf;
- }
- }
-
- if (0 < yysize && yysize <= yymsg_alloc)
- {
- (void) yysyntax_error (yymsg, yystate, yychar);
- yyerror (yymsg);
- }
- else
- {
- yyerror (YY_("syntax error"));
- if (yysize != 0)
- goto yyexhaustedlab;
- }
- }
-#endif
- }
-
- yyerror_range[0] = yylloc;
-
- if (yyerrstatus == 3)
- {
- /* If just tried and failed to reuse look-ahead token after an
- error, discard it. */
-
- if (yychar <= YYEOF)
- {
- /* Return failure if at end of input. */
- if (yychar == YYEOF)
- YYABORT;
- }
- else
- {
- yydestruct ("Error: discarding",
- yytoken, &yylval, &yylloc);
- yychar = YYEMPTY;
- }
- }
-
- /* Else will try to reuse look-ahead token after shifting the error
- token. */
- goto yyerrlab1;
-
-
-/*---------------------------------------------------.
-| yyerrorlab -- error raised explicitly by YYERROR. |
-`---------------------------------------------------*/
-yyerrorlab:
-
- /* Pacify compilers like GCC when the user code never invokes
- YYERROR and the label yyerrorlab therefore never appears in user
- code. */
- if (/*CONSTCOND*/ 0)
- goto yyerrorlab;
-
- yyerror_range[0] = yylsp[1-yylen];
- /* Do not reclaim the symbols of the rule which action triggered
- this YYERROR. */
- YYPOPSTACK (yylen);
- yylen = 0;
- YY_STACK_PRINT (yyss, yyssp);
- yystate = *yyssp;
- goto yyerrlab1;
-
-
-/*-------------------------------------------------------------.
-| yyerrlab1 -- common code for both syntax error and YYERROR. |
-`-------------------------------------------------------------*/
-yyerrlab1:
- yyerrstatus = 3; /* Each real token shifted decrements this. */
-
- for (;;)
- {
- yyn = yypact[yystate];
- if (yyn != YYPACT_NINF)
- {
- yyn += YYTERROR;
- if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
- {
- yyn = yytable[yyn];
- if (0 < yyn)
- break;
- }
- }
-
- /* Pop the current state because it cannot handle the error token. */
- if (yyssp == yyss)
- YYABORT;
-
- yyerror_range[0] = *yylsp;
- yydestruct ("Error: popping",
- yystos[yystate], yyvsp, yylsp);
- YYPOPSTACK (1);
- yystate = *yyssp;
- YY_STACK_PRINT (yyss, yyssp);
- }
-
- if (yyn == YYFINAL)
- YYACCEPT;
-
- *++yyvsp = yylval;
-
- yyerror_range[1] = yylloc;
- /* Using YYLLOC is tempting, but would change the location of
- the look-ahead. YYLOC is available though. */
- YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
- *++yylsp = yyloc;
-
- /* Shift the error token. */
- YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
-
- yystate = yyn;
- goto yynewstate;
-
-
-/*-------------------------------------.
-| yyacceptlab -- YYACCEPT comes here. |
-`-------------------------------------*/
-yyacceptlab:
- yyresult = 0;
- goto yyreturn;
-
-/*-----------------------------------.
-| yyabortlab -- YYABORT comes here. |
-`-----------------------------------*/
-yyabortlab:
- yyresult = 1;
- goto yyreturn;
-
-#ifndef yyoverflow
-/*-------------------------------------------------.
-| yyexhaustedlab -- memory exhaustion comes here. |
-`-------------------------------------------------*/
-yyexhaustedlab:
- yyerror (YY_("memory exhausted"));
- yyresult = 2;
- /* Fall through. */
-#endif
-
-yyreturn:
- if (yychar != YYEOF && yychar != YYEMPTY)
- yydestruct ("Cleanup: discarding lookahead",
- yytoken, &yylval, &yylloc);
- /* Do not reclaim the symbols of the rule which action triggered
- this YYABORT or YYACCEPT. */
- YYPOPSTACK (yylen);
- YY_STACK_PRINT (yyss, yyssp);
- while (yyssp != yyss)
- {
- yydestruct ("Cleanup: popping",
- yystos[*yyssp], yyvsp, yylsp);
- YYPOPSTACK (1);
- }
-#ifndef yyoverflow
- if (yyss != yyssa)
- YYSTACK_FREE (yyss);
-#endif
-#if YYERROR_VERBOSE
- if (yymsg != yymsgbuf)
- YYSTACK_FREE (yymsg);
-#endif
- /* Make sure YYID is used. */
- return YYID (yyresult);
-}
-
-
-#line 340 "dtc-parser.y"
-
-
-void yyerrorf(char const *s, ...)
-{
- const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
- va_list va;
- va_start(va, s);
-
- if (strcmp(fname, "-") == 0)
- fname = "stdin";
-
- fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
- vfprintf(stderr, s, va);
- fprintf(stderr, "\n");
-
- treesource_error = 1;
- va_end(va);
-}
-
-void yyerror (char const *s)
-{
- yyerrorf("%s", s);
-}
-
-static unsigned long long eval_literal(const char *s, int base, int bits)
-{
- unsigned long long val;
- char *e;
-
- errno = 0;
- val = strtoull(s, &e, base);
- if (*e)
- yyerror("bad characters in literal");
- else if ((errno == ERANGE)
- || ((bits < 64) && (val >= (1ULL << bits))))
- yyerror("literal out of range");
- else if (errno != 0)
- yyerror("bad literal");
- return val;
-}
-
+++ /dev/null
-/* A Bison parser, made by GNU Bison 2.3. */
-
-/* Skeleton interface for Bison's Yacc-like parsers in C
-
- Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
- Free Software Foundation, Inc.
-
- 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, 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., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA. */
-
-/* As a special exception, you may create a larger work that contains
- part or all of the Bison parser skeleton and distribute that work
- under terms of your choice, so long as that work isn't itself a
- parser generator using the skeleton or a modified version thereof
- as a parser skeleton. Alternatively, if you modify or redistribute
- the parser skeleton itself, you may (at your option) remove this
- special exception, which will cause the skeleton and the resulting
- Bison output files to be licensed under the GNU General Public
- License without this special exception.
-
- This special exception was added by the Free Software Foundation in
- version 2.2 of Bison. */
-
-/* Tokens. */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
- /* Put the tokens into the symbol table, so that GDB and other debuggers
- know about them. */
- enum yytokentype {
- DT_V1 = 258,
- DT_MEMRESERVE = 259,
- DT_PROPNODENAME = 260,
- DT_LITERAL = 261,
- DT_LEGACYLITERAL = 262,
- DT_BASE = 263,
- DT_BYTE = 264,
- DT_STRING = 265,
- DT_LABEL = 266,
- DT_REF = 267,
- DT_INCBIN = 268
- };
-#endif
-/* Tokens. */
-#define DT_V1 258
-#define DT_MEMRESERVE 259
-#define DT_PROPNODENAME 260
-#define DT_LITERAL 261
-#define DT_LEGACYLITERAL 262
-#define DT_BASE 263
-#define DT_BYTE 264
-#define DT_STRING 265
-#define DT_LABEL 266
-#define DT_REF 267
-#define DT_INCBIN 268
-
-
-
-
-#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
-#line 37 "dtc-parser.y"
-{
- char *propnodename;
- char *literal;
- char *labelref;
- unsigned int cbase;
- uint8_t byte;
- struct data data;
-
- uint64_t addr;
- cell_t cell;
- struct property *prop;
- struct property *proplist;
- struct node *node;
- struct node *nodelist;
- struct reserve_info *re;
-}
-/* Line 1489 of yacc.c. */
-#line 92 "dtc-parser.tab.h"
- YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
-#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
-typedef struct YYLTYPE
-{
- int first_line;
- int first_column;
- int last_line;
- int last_column;
-} YYLTYPE;
-# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
-# define YYLTYPE_IS_DECLARED 1
-# define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYLTYPE yylloc;
+++ /dev/null
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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
- */
-
-%locations
-
-%{
-#include <stdio.h>
-
-#include "dtc.h"
-#include "srcpos.h"
-
-extern int yylex(void);
-
-extern struct boot_info *the_boot_info;
-extern int treesource_error;
-
-static unsigned long long eval_literal(const char *s, int base, int bits);
-%}
-
-%union {
- char *propnodename;
- char *literal;
- char *labelref;
- unsigned int cbase;
- uint8_t byte;
- struct data data;
-
- uint64_t addr;
- cell_t cell;
- struct property *prop;
- struct property *proplist;
- struct node *node;
- struct node *nodelist;
- struct reserve_info *re;
-}
-
-%token DT_V1
-%token DT_MEMRESERVE
-%token <propnodename> DT_PROPNODENAME
-%token <literal> DT_LITERAL
-%token <literal> DT_LEGACYLITERAL
-%token <cbase> DT_BASE
-%token <byte> DT_BYTE
-%token <data> DT_STRING
-%token <labelref> DT_LABEL
-%token <labelref> DT_REF
-%token DT_INCBIN
-
-%type <data> propdata
-%type <data> propdataprefix
-%type <re> memreserve
-%type <re> memreserves
-%type <re> v0_memreserve
-%type <re> v0_memreserves
-%type <addr> addr
-%type <data> celllist
-%type <cbase> cellbase
-%type <cell> cellval
-%type <data> bytestring
-%type <prop> propdef
-%type <proplist> proplist
-
-%type <node> devicetree
-%type <node> nodedef
-%type <node> subnode
-%type <nodelist> subnodes
-%type <labelref> label
-
-%%
-
-sourcefile:
- DT_V1 ';' memreserves devicetree
- {
- the_boot_info = build_boot_info($3, $4, 0);
- }
- | v0_memreserves devicetree
- {
- the_boot_info = build_boot_info($1, $2, 0);
- }
- ;
-
-memreserves:
- /* empty */
- {
- $$ = NULL;
- }
- | memreserve memreserves
- {
- $$ = chain_reserve_entry($1, $2);
- }
- ;
-
-memreserve:
- label DT_MEMRESERVE addr addr ';'
- {
- $$ = build_reserve_entry($3, $4, $1);
- }
- ;
-
-v0_memreserves:
- /* empty */
- {
- $$ = NULL;
- }
- | v0_memreserve v0_memreserves
- {
- $$ = chain_reserve_entry($1, $2);
- };
- ;
-
-v0_memreserve:
- memreserve
- {
- $$ = $1;
- }
- | label DT_MEMRESERVE addr '-' addr ';'
- {
- $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
- }
- ;
-
-addr:
- DT_LITERAL
- {
- $$ = eval_literal($1, 0, 64);
- }
- | DT_LEGACYLITERAL
- {
- $$ = eval_literal($1, 16, 64);
- }
- ;
-
-devicetree:
- '/' nodedef
- {
- $$ = name_node($2, "", NULL);
- }
- ;
-
-nodedef:
- '{' proplist subnodes '}' ';'
- {
- $$ = build_node($2, $3);
- }
- ;
-
-proplist:
- /* empty */
- {
- $$ = NULL;
- }
- | proplist propdef
- {
- $$ = chain_property($2, $1);
- }
- ;
-
-propdef:
- label DT_PROPNODENAME '=' propdata ';'
- {
- $$ = build_property($2, $4, $1);
- }
- | label DT_PROPNODENAME ';'
- {
- $$ = build_property($2, empty_data, $1);
- }
- ;
-
-propdata:
- propdataprefix DT_STRING
- {
- $$ = data_merge($1, $2);
- }
- | propdataprefix '<' celllist '>'
- {
- $$ = data_merge($1, $3);
- }
- | propdataprefix '[' bytestring ']'
- {
- $$ = data_merge($1, $3);
- }
- | propdataprefix DT_REF
- {
- $$ = data_add_marker($1, REF_PATH, $2);
- }
- | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
- {
- struct search_path path = { srcpos_file->dir, NULL, NULL };
- struct dtc_file *file = dtc_open_file($4.val, &path);
- struct data d = empty_data;
-
- if ($6 != 0)
- if (fseek(file->file, $6, SEEK_SET) != 0)
- yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
- (unsigned long long)$6,
- $4.val, strerror(errno));
-
- d = data_copy_file(file->file, $8);
-
- $$ = data_merge($1, d);
- dtc_close_file(file);
- }
- | propdataprefix DT_INCBIN '(' DT_STRING ')'
- {
- struct search_path path = { srcpos_file->dir, NULL, NULL };
- struct dtc_file *file = dtc_open_file($4.val, &path);
- struct data d = empty_data;
-
- d = data_copy_file(file->file, -1);
-
- $$ = data_merge($1, d);
- dtc_close_file(file);
- }
- | propdata DT_LABEL
- {
- $$ = data_add_marker($1, LABEL, $2);
- }
- ;
-
-propdataprefix:
- /* empty */
- {
- $$ = empty_data;
- }
- | propdata ','
- {
- $$ = $1;
- }
- | propdataprefix DT_LABEL
- {
- $$ = data_add_marker($1, LABEL, $2);
- }
- ;
-
-celllist:
- /* empty */
- {
- $$ = empty_data;
- }
- | celllist cellval
- {
- $$ = data_append_cell($1, $2);
- }
- | celllist DT_REF
- {
- $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
- $2), -1);
- }
- | celllist DT_LABEL
- {
- $$ = data_add_marker($1, LABEL, $2);
- }
- ;
-
-cellbase:
- /* empty */
- {
- $$ = 16;
- }
- | DT_BASE
- ;
-
-cellval:
- DT_LITERAL
- {
- $$ = eval_literal($1, 0, 32);
- }
- | cellbase DT_LEGACYLITERAL
- {
- $$ = eval_literal($2, $1, 32);
- }
- ;
-
-bytestring:
- /* empty */
- {
- $$ = empty_data;
- }
- | bytestring DT_BYTE
- {
- $$ = data_append_byte($1, $2);
- }
- | bytestring DT_LABEL
- {
- $$ = data_add_marker($1, LABEL, $2);
- }
- ;
-
-subnodes:
- /* empty */
- {
- $$ = NULL;
- }
- | subnode subnodes
- {
- $$ = chain_node($1, $2);
- }
- | subnode propdef
- {
- yyerror("syntax error: properties must precede subnodes");
- YYERROR;
- }
- ;
-
-subnode:
- label DT_PROPNODENAME nodedef
- {
- $$ = name_node($3, $2, $1);
- }
- ;
-
-label:
- /* empty */
- {
- $$ = NULL;
- }
- | DT_LABEL
- {
- $$ = $1;
- }
- ;
-
-%%
-
-void yyerrorf(char const *s, ...)
-{
- const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
- va_list va;
- va_start(va, s);
-
- if (strcmp(fname, "-") == 0)
- fname = "stdin";
-
- fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
- vfprintf(stderr, s, va);
- fprintf(stderr, "\n");
-
- treesource_error = 1;
- va_end(va);
-}
-
-void yyerror (char const *s)
-{
- yyerrorf("%s", s);
-}
-
-static unsigned long long eval_literal(const char *s, int base, int bits)
-{
- unsigned long long val;
- char *e;
-
- errno = 0;
- val = strtoull(s, &e, base);
- if (*e)
- yyerror("bad characters in literal");
- else if ((errno == ERANGE)
- || ((bits < 64) && (val >= (1ULL << bits))))
- yyerror("literal out of range");
- else if (errno != 0)
- yyerror("bad literal");
- return val;
-}
+++ /dev/null
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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 "dtc.h"
-#include "srcpos.h"
-
-#include "version_gen.h"
-
-/*
- * Command line options
- */
-int quiet; /* Level of quietness */
-int reservenum; /* Number of memory reservation slots */
-int minsize; /* Minimum blob size */
-int padsize; /* Additional padding to blob */
-
-char *join_path(const char *path, const char *name)
-{
- int lenp = strlen(path);
- int lenn = strlen(name);
- int len;
- int needslash = 1;
- char *str;
-
- len = lenp + lenn + 2;
- if ((lenp > 0) && (path[lenp-1] == '/')) {
- needslash = 0;
- len--;
- }
-
- str = xmalloc(len);
- memcpy(str, path, lenp);
- if (needslash) {
- str[lenp] = '/';
- lenp++;
- }
- memcpy(str+lenp, name, lenn+1);
- return str;
-}
-
-static void fill_fullpaths(struct node *tree, const char *prefix)
-{
- struct node *child;
- const char *unit;
-
- tree->fullpath = join_path(prefix, tree->name);
-
- unit = strchr(tree->name, '@');
- if (unit)
- tree->basenamelen = unit - tree->name;
- else
- tree->basenamelen = strlen(tree->name);
-
- for_each_child(tree, child)
- fill_fullpaths(child, tree->fullpath);
-}
-
-static void __attribute__ ((noreturn)) usage(void)
-{
- fprintf(stderr, "Usage:\n");
- fprintf(stderr, "\tdtc [options] <input file>\n");
- fprintf(stderr, "\nOptions:\n");
- fprintf(stderr, "\t-h\n");
- fprintf(stderr, "\t\tThis help text\n");
- fprintf(stderr, "\t-q\n");
- fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n");
- fprintf(stderr, "\t-I <input format>\n");
- fprintf(stderr, "\t\tInput formats are:\n");
- fprintf(stderr, "\t\t\tdts - device tree source text\n");
- fprintf(stderr, "\t\t\tdtb - device tree blob\n");
- fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
- fprintf(stderr, "\t-o <output file>\n");
- fprintf(stderr, "\t-O <output format>\n");
- fprintf(stderr, "\t\tOutput formats are:\n");
- fprintf(stderr, "\t\t\tdts - device tree source text\n");
- fprintf(stderr, "\t\t\tdtb - device tree blob\n");
- fprintf(stderr, "\t\t\tasm - assembler source\n");
- fprintf(stderr, "\t-V <output version>\n");
- fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
- fprintf(stderr, "\t-R <number>\n");
- fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
- fprintf(stderr, "\t-S <bytes>\n");
- fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n");
- fprintf(stderr, "\t-p <bytes>\n");
- fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n");
- fprintf(stderr, "\t-b <number>\n");
- fprintf(stderr, "\t\tSet the physical boot cpu\n");
- fprintf(stderr, "\t-f\n");
- fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
- fprintf(stderr, "\t-v\n");
- fprintf(stderr, "\t\tPrint DTC version and exit\n");
- exit(3);
-}
-
-int main(int argc, char *argv[])
-{
- struct boot_info *bi;
- const char *inform = "dts";
- const char *outform = "dts";
- const char *outname = "-";
- int force = 0, check = 0;
- const char *arg;
- int opt;
- FILE *outf = NULL;
- int outversion = DEFAULT_FDT_VERSION;
- long long cmdline_boot_cpuid = -1;
-
- quiet = 0;
- reservenum = 0;
- minsize = 0;
- padsize = 0;
-
- while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) {
- switch (opt) {
- case 'I':
- inform = optarg;
- break;
- case 'O':
- outform = optarg;
- break;
- case 'o':
- outname = optarg;
- break;
- case 'V':
- outversion = strtol(optarg, NULL, 0);
- break;
- case 'R':
- reservenum = strtol(optarg, NULL, 0);
- break;
- case 'S':
- minsize = strtol(optarg, NULL, 0);
- break;
- case 'p':
- padsize = strtol(optarg, NULL, 0);
- break;
- case 'f':
- force = 1;
- break;
- case 'c':
- check = 1;
- break;
- case 'q':
- quiet++;
- break;
- case 'b':
- cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
- break;
- case 'v':
- printf("Version: %s\n", DTC_VERSION);
- exit(0);
- case 'h':
- default:
- usage();
- }
- }
-
- if (argc > (optind+1))
- usage();
- else if (argc < (optind+1))
- arg = "-";
- else
- arg = argv[optind];
-
- /* minsize and padsize are mutually exclusive */
- if (minsize && padsize)
- die("Can't set both -p and -S\n");
-
- fprintf(stderr, "DTC: %s->%s on file \"%s\"\n",
- inform, outform, arg);
-
- if (streq(inform, "dts"))
- bi = dt_from_source(arg);
- else if (streq(inform, "fs"))
- bi = dt_from_fs(arg);
- else if(streq(inform, "dtb"))
- bi = dt_from_blob(arg);
- else
- die("Unknown input format \"%s\"\n", inform);
-
- if (cmdline_boot_cpuid != -1)
- bi->boot_cpuid_phys = cmdline_boot_cpuid;
-
- fill_fullpaths(bi->dt, "");
- process_checks(force, bi);
-
-
- if (streq(outname, "-")) {
- outf = stdout;
- } else {
- outf = fopen(outname, "w");
- if (! outf)
- die("Couldn't open output file %s: %s\n",
- outname, strerror(errno));
- }
-
- if (streq(outform, "dts")) {
- dt_to_source(outf, bi);
- } else if (streq(outform, "dtb")) {
- dt_to_blob(outf, bi, outversion);
- } else if (streq(outform, "asm")) {
- dt_to_asm(outf, bi, outversion);
- } else if (streq(outform, "null")) {
- /* do nothing */
- } else {
- die("Unknown output format \"%s\"\n", outform);
- }
-
- exit(0);
-}
+++ /dev/null
-#ifndef _DTC_H
-#define _DTC_H
-
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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 <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <libfdt_env.h>
-#include <fdt.h>
-
-#define DEFAULT_FDT_VERSION 17
-/*
- * Command line options
- */
-extern int quiet; /* Level of quietness */
-extern int reservenum; /* Number of memory reservation slots */
-extern int minsize; /* Minimum blob size */
-extern int padsize; /* Additional padding to blob */
-
-static inline void __attribute__((noreturn)) die(char * str, ...)
-{
- va_list ap;
-
- va_start(ap, str);
- fprintf(stderr, "FATAL ERROR: ");
- vfprintf(stderr, str, ap);
- exit(1);
-}
-
-static inline void *xmalloc(size_t len)
-{
- void *new = malloc(len);
-
- if (! new)
- die("malloc() failed\n");
-
- return new;
-}
-
-static inline void *xrealloc(void *p, size_t len)
-{
- void *new = realloc(p, len);
-
- if (! new)
- die("realloc() failed (len=%d)\n", len);
-
- return new;
-}
-
-typedef uint32_t cell_t;
-
-
-#define streq(a, b) (strcmp((a), (b)) == 0)
-#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
-
-#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
-/* Data blobs */
-enum markertype {
- REF_PHANDLE,
- REF_PATH,
- LABEL,
-};
-
-struct marker {
- enum markertype type;
- int offset;
- char *ref;
- struct marker *next;
-};
-
-struct data {
- int len;
- char *val;
- struct marker *markers;
-};
-
-
-#define empty_data ((struct data){ /* all .members = 0 or NULL */ })
-
-#define for_each_marker(m) \
- for (; (m); (m) = (m)->next)
-#define for_each_marker_of_type(m, t) \
- for_each_marker(m) \
- if ((m)->type == (t))
-
-void data_free(struct data d);
-
-struct data data_grow_for(struct data d, int xlen);
-
-struct data data_copy_mem(const char *mem, int len);
-struct data data_copy_escape_string(const char *s, int len);
-struct data data_copy_file(FILE *f, size_t len);
-
-struct data data_append_data(struct data d, const void *p, int len);
-struct data data_insert_at_marker(struct data d, struct marker *m,
- const void *p, int len);
-struct data data_merge(struct data d1, struct data d2);
-struct data data_append_cell(struct data d, cell_t word);
-struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
-struct data data_append_addr(struct data d, uint64_t addr);
-struct data data_append_byte(struct data d, uint8_t byte);
-struct data data_append_zeroes(struct data d, int len);
-struct data data_append_align(struct data d, int align);
-
-struct data data_add_marker(struct data d, enum markertype type, char *ref);
-
-int data_is_one_string(struct data d);
-
-/* DT constraints */
-
-#define MAX_PROPNAME_LEN 31
-#define MAX_NODENAME_LEN 31
-
-/* Live trees */
-struct property {
- char *name;
- struct data val;
-
- struct property *next;
-
- char *label;
-};
-
-struct node {
- char *name;
- struct property *proplist;
- struct node *children;
-
- struct node *parent;
- struct node *next_sibling;
-
- char *fullpath;
- int basenamelen;
-
- cell_t phandle;
- int addr_cells, size_cells;
-
- char *label;
-};
-
-#define for_each_property(n, p) \
- for ((p) = (n)->proplist; (p); (p) = (p)->next)
-
-#define for_each_child(n, c) \
- for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
-
-struct property *build_property(char *name, struct data val, char *label);
-struct property *chain_property(struct property *first, struct property *list);
-struct property *reverse_properties(struct property *first);
-
-struct node *build_node(struct property *proplist, struct node *children);
-struct node *name_node(struct node *node, char *name, char *label);
-struct node *chain_node(struct node *first, struct node *list);
-
-void add_property(struct node *node, struct property *prop);
-void add_child(struct node *parent, struct node *child);
-
-const char *get_unitname(struct node *node);
-struct property *get_property(struct node *node, const char *propname);
-cell_t propval_cell(struct property *prop);
-struct node *get_subnode(struct node *node, const char *nodename);
-struct node *get_node_by_path(struct node *tree, const char *path);
-struct node *get_node_by_label(struct node *tree, const char *label);
-struct node *get_node_by_phandle(struct node *tree, cell_t phandle);
-struct node *get_node_by_ref(struct node *tree, const char *ref);
-cell_t get_node_phandle(struct node *root, struct node *node);
-
-/* Boot info (tree plus memreserve information */
-
-struct reserve_info {
- struct fdt_reserve_entry re;
-
- struct reserve_info *next;
-
- char *label;
-};
-
-struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len, char *label);
-struct reserve_info *chain_reserve_entry(struct reserve_info *first,
- struct reserve_info *list);
-struct reserve_info *add_reserve_entry(struct reserve_info *list,
- struct reserve_info *new);
-
-
-struct boot_info {
- struct reserve_info *reservelist;
- struct node *dt; /* the device tree */
- uint32_t boot_cpuid_phys;
-};
-
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
- struct node *tree, uint32_t boot_cpuid_phys);
-
-/* Checks */
-
-void process_checks(int force, struct boot_info *bi);
-
-/* Flattened trees */
-
-void dt_to_blob(FILE *f, struct boot_info *bi, int version);
-void dt_to_asm(FILE *f, struct boot_info *bi, int version);
-
-struct boot_info *dt_from_blob(const char *fname);
-
-/* Tree source */
-
-void dt_to_source(FILE *f, struct boot_info *bi);
-struct boot_info *dt_from_source(const char *f);
-
-/* FS trees */
-
-struct boot_info *dt_from_fs(const char *dirname);
-
-/* misc */
-
-char *join_path(const char *path, const char *name);
-
-#endif /* _DTC_H */
+++ /dev/null
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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 "dtc.h"
-#include "srcpos.h"
-
-#define FTF_FULLPATH 0x1
-#define FTF_VARALIGN 0x2
-#define FTF_NAMEPROPS 0x4
-#define FTF_BOOTCPUID 0x8
-#define FTF_STRTABSIZE 0x10
-#define FTF_STRUCTSIZE 0x20
-#define FTF_NOPS 0x40
-
-static struct version_info {
- int version;
- int last_comp_version;
- int hdr_size;
- int flags;
-} version_table[] = {
- {1, 1, FDT_V1_SIZE,
- FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS},
- {2, 1, FDT_V2_SIZE,
- FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID},
- {3, 1, FDT_V3_SIZE,
- FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE},
- {16, 16, FDT_V3_SIZE,
- FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS},
- {17, 16, FDT_V17_SIZE,
- FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS},
-};
-
-struct emitter {
- void (*cell)(void *, cell_t);
- void (*string)(void *, char *, int);
- void (*align)(void *, int);
- void (*data)(void *, struct data);
- void (*beginnode)(void *, const char *);
- void (*endnode)(void *, const char *);
- void (*property)(void *, const char *);
-};
-
-static void bin_emit_cell(void *e, cell_t val)
-{
- struct data *dtbuf = e;
-
- *dtbuf = data_append_cell(*dtbuf, val);
-}
-
-static void bin_emit_string(void *e, char *str, int len)
-{
- struct data *dtbuf = e;
-
- if (len == 0)
- len = strlen(str);
-
- *dtbuf = data_append_data(*dtbuf, str, len);
- *dtbuf = data_append_byte(*dtbuf, '\0');
-}
-
-static void bin_emit_align(void *e, int a)
-{
- struct data *dtbuf = e;
-
- *dtbuf = data_append_align(*dtbuf, a);
-}
-
-static void bin_emit_data(void *e, struct data d)
-{
- struct data *dtbuf = e;
-
- *dtbuf = data_append_data(*dtbuf, d.val, d.len);
-}
-
-static void bin_emit_beginnode(void *e, const char *label)
-{
- bin_emit_cell(e, FDT_BEGIN_NODE);
-}
-
-static void bin_emit_endnode(void *e, const char *label)
-{
- bin_emit_cell(e, FDT_END_NODE);
-}
-
-static void bin_emit_property(void *e, const char *label)
-{
- bin_emit_cell(e, FDT_PROP);
-}
-
-static struct emitter bin_emitter = {
- .cell = bin_emit_cell,
- .string = bin_emit_string,
- .align = bin_emit_align,
- .data = bin_emit_data,
- .beginnode = bin_emit_beginnode,
- .endnode = bin_emit_endnode,
- .property = bin_emit_property,
-};
-
-static void emit_label(FILE *f, const char *prefix, const char *label)
-{
- fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
- fprintf(f, "%s_%s:\n", prefix, label);
- fprintf(f, "_%s_%s:\n", prefix, label);
-}
-
-static void emit_offset_label(FILE *f, const char *label, int offset)
-{
- fprintf(f, "\t.globl\t%s\n", label);
- fprintf(f, "%s\t= . + %d\n", label, offset);
-}
-
-static void asm_emit_cell(void *e, cell_t val)
-{
- FILE *f = e;
-
- fprintf(f, "\t.long\t0x%x\n", val);
-}
-
-static void asm_emit_string(void *e, char *str, int len)
-{
- FILE *f = e;
- char c = 0;
-
- if (len != 0) {
- /* XXX: ewww */
- c = str[len];
- str[len] = '\0';
- }
-
- fprintf(f, "\t.string\t\"%s\"\n", str);
-
- if (len != 0) {
- str[len] = c;
- }
-}
-
-static void asm_emit_align(void *e, int a)
-{
- FILE *f = e;
-
- fprintf(f, "\t.balign\t%d\n", a);
-}
-
-static void asm_emit_data(void *e, struct data d)
-{
- FILE *f = e;
- int off = 0;
- struct marker *m = d.markers;
-
- for_each_marker_of_type(m, LABEL)
- emit_offset_label(f, m->ref, m->offset);
-
- while ((d.len - off) >= sizeof(uint32_t)) {
- fprintf(f, "\t.long\t0x%x\n",
- fdt32_to_cpu(*((uint32_t *)(d.val+off))));
- off += sizeof(uint32_t);
- }
-
- while ((d.len - off) >= 1) {
- fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]);
- off += 1;
- }
-
- assert(off == d.len);
-}
-
-static void asm_emit_beginnode(void *e, const char *label)
-{
- FILE *f = e;
-
- if (label) {
- fprintf(f, "\t.globl\t%s\n", label);
- fprintf(f, "%s:\n", label);
- }
- fprintf(f, "\t.long\tFDT_BEGIN_NODE\n");
-}
-
-static void asm_emit_endnode(void *e, const char *label)
-{
- FILE *f = e;
-
- fprintf(f, "\t.long\tFDT_END_NODE\n");
- if (label) {
- fprintf(f, "\t.globl\t%s_end\n", label);
- fprintf(f, "%s_end:\n", label);
- }
-}
-
-static void asm_emit_property(void *e, const char *label)
-{
- FILE *f = e;
-
- if (label) {
- fprintf(f, "\t.globl\t%s\n", label);
- fprintf(f, "%s:\n", label);
- }
- fprintf(f, "\t.long\tFDT_PROP\n");
-}
-
-static struct emitter asm_emitter = {
- .cell = asm_emit_cell,
- .string = asm_emit_string,
- .align = asm_emit_align,
- .data = asm_emit_data,
- .beginnode = asm_emit_beginnode,
- .endnode = asm_emit_endnode,
- .property = asm_emit_property,
-};
-
-static int stringtable_insert(struct data *d, const char *str)
-{
- int i;
-
- /* FIXME: do this more efficiently? */
-
- for (i = 0; i < d->len; i++) {
- if (streq(str, d->val + i))
- return i;
- }
-
- *d = data_append_data(*d, str, strlen(str)+1);
- return i;
-}
-
-static void flatten_tree(struct node *tree, struct emitter *emit,
- void *etarget, struct data *strbuf,
- struct version_info *vi)
-{
- struct property *prop;
- struct node *child;
- int seen_name_prop = 0;
-
- emit->beginnode(etarget, tree->label);
-
- if (vi->flags & FTF_FULLPATH)
- emit->string(etarget, tree->fullpath, 0);
- else
- emit->string(etarget, tree->name, 0);
-
- emit->align(etarget, sizeof(cell_t));
-
- for_each_property(tree, prop) {
- int nameoff;
-
- if (streq(prop->name, "name"))
- seen_name_prop = 1;
-
- nameoff = stringtable_insert(strbuf, prop->name);
-
- emit->property(etarget, prop->label);
- emit->cell(etarget, prop->val.len);
- emit->cell(etarget, nameoff);
-
- if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8))
- emit->align(etarget, 8);
-
- emit->data(etarget, prop->val);
- emit->align(etarget, sizeof(cell_t));
- }
-
- if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
- emit->property(etarget, NULL);
- emit->cell(etarget, tree->basenamelen+1);
- emit->cell(etarget, stringtable_insert(strbuf, "name"));
-
- if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8))
- emit->align(etarget, 8);
-
- emit->string(etarget, tree->name, tree->basenamelen);
- emit->align(etarget, sizeof(cell_t));
- }
-
- for_each_child(tree, child) {
- flatten_tree(child, emit, etarget, strbuf, vi);
- }
-
- emit->endnode(etarget, tree->label);
-}
-
-static struct data flatten_reserve_list(struct reserve_info *reservelist,
- struct version_info *vi)
-{
- struct reserve_info *re;
- struct data d = empty_data;
- static struct fdt_reserve_entry null_re = {0,0};
- int j;
-
- for (re = reservelist; re; re = re->next) {
- d = data_append_re(d, &re->re);
- }
- /*
- * Add additional reserved slots if the user asked for them.
- */
- for (j = 0; j < reservenum; j++) {
- d = data_append_re(d, &null_re);
- }
-
- return d;
-}
-
-static void make_fdt_header(struct fdt_header *fdt,
- struct version_info *vi,
- int reservesize, int dtsize, int strsize,
- int boot_cpuid_phys)
-{
- int reserve_off;
-
- reservesize += sizeof(struct fdt_reserve_entry);
-
- memset(fdt, 0xff, sizeof(*fdt));
-
- fdt->magic = cpu_to_fdt32(FDT_MAGIC);
- fdt->version = cpu_to_fdt32(vi->version);
- fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
-
- /* Reserve map should be doubleword aligned */
- reserve_off = ALIGN(vi->hdr_size, 8);
-
- fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off);
- fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize);
- fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize
- + dtsize);
- fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize);
-
- if (vi->flags & FTF_BOOTCPUID)
- fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys);
- if (vi->flags & FTF_STRTABSIZE)
- fdt->size_dt_strings = cpu_to_fdt32(strsize);
- if (vi->flags & FTF_STRUCTSIZE)
- fdt->size_dt_struct = cpu_to_fdt32(dtsize);
-}
-
-void dt_to_blob(FILE *f, struct boot_info *bi, int version)
-{
- struct version_info *vi = NULL;
- int i;
- struct data blob = empty_data;
- struct data reservebuf = empty_data;
- struct data dtbuf = empty_data;
- struct data strbuf = empty_data;
- struct fdt_header fdt;
- int padlen = 0;
-
- for (i = 0; i < ARRAY_SIZE(version_table); i++) {
- if (version_table[i].version == version)
- vi = &version_table[i];
- }
- if (!vi)
- die("Unknown device tree blob version %d\n", version);
-
- flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi);
- bin_emit_cell(&dtbuf, FDT_END);
-
- reservebuf = flatten_reserve_list(bi->reservelist, vi);
-
- /* Make header */
- make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
- bi->boot_cpuid_phys);
-
- /*
- * If the user asked for more space than is used, adjust the totalsize.
- */
- if (minsize > 0) {
- padlen = minsize - fdt32_to_cpu(fdt.totalsize);
- if ((padlen < 0) && (quiet < 1))
- fprintf(stderr,
- "Warning: blob size %d >= minimum size %d\n",
- fdt32_to_cpu(fdt.totalsize), minsize);
- }
-
- if (padsize > 0)
- padlen = padsize;
-
- if (padlen > 0) {
- int tsize = fdt32_to_cpu(fdt.totalsize);
- tsize += padlen;
- fdt.totalsize = cpu_to_fdt32(tsize);
- }
-
- /*
- * Assemble the blob: start with the header, add with alignment
- * the reserve buffer, add the reserve map terminating zeroes,
- * the device tree itself, and finally the strings.
- */
- blob = data_append_data(blob, &fdt, vi->hdr_size);
- blob = data_append_align(blob, 8);
- blob = data_merge(blob, reservebuf);
- blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry));
- blob = data_merge(blob, dtbuf);
- blob = data_merge(blob, strbuf);
-
- /*
- * If the user asked for more space than is used, pad out the blob.
- */
- if (padlen > 0)
- blob = data_append_zeroes(blob, padlen);
-
- fwrite(blob.val, blob.len, 1, f);
-
- if (ferror(f))
- die("Error writing device tree blob: %s\n", strerror(errno));
-
- /*
- * data_merge() frees the right-hand element so only the blob
- * remains to be freed.
- */
- data_free(blob);
-}
-
-static void dump_stringtable_asm(FILE *f, struct data strbuf)
-{
- const char *p;
- int len;
-
- p = strbuf.val;
-
- while (p < (strbuf.val + strbuf.len)) {
- len = strlen(p);
- fprintf(f, "\t.string \"%s\"\n", p);
- p += len+1;
- }
-}
-
-void dt_to_asm(FILE *f, struct boot_info *bi, int version)
-{
- struct version_info *vi = NULL;
- int i;
- struct data strbuf = empty_data;
- struct reserve_info *re;
- const char *symprefix = "dt";
-
- for (i = 0; i < ARRAY_SIZE(version_table); i++) {
- if (version_table[i].version == version)
- vi = &version_table[i];
- }
- if (!vi)
- die("Unknown device tree blob version %d\n", version);
-
- fprintf(f, "/* autogenerated by dtc, do not edit */\n\n");
- fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC);
- fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE);
- fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE);
- fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP);
- fprintf(f, "#define FDT_END 0x%x\n", FDT_END);
- fprintf(f, "\n");
-
- emit_label(f, symprefix, "blob_start");
- emit_label(f, symprefix, "header");
- fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n");
- fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n",
- symprefix, symprefix);
- fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n",
- symprefix, symprefix);
- fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n",
- symprefix, symprefix);
- fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n",
- symprefix, symprefix);
- fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version);
- fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n",
- vi->last_comp_version);
-
- if (vi->flags & FTF_BOOTCPUID)
- fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n",
- bi->boot_cpuid_phys);
-
- if (vi->flags & FTF_STRTABSIZE)
- fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
- symprefix, symprefix);
-
- if (vi->flags & FTF_STRUCTSIZE)
- fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n",
- symprefix, symprefix);
-
- /*
- * Reserve map entries.
- * Align the reserve map to a doubleword boundary.
- * Each entry is an (address, size) pair of u64 values.
- * Always supply a zero-sized temination entry.
- */
- asm_emit_align(f, 8);
- emit_label(f, symprefix, "reserve_map");
-
- fprintf(f, "/* Memory reserve map from source file */\n");
-
- /*
- * Use .long on high and low halfs of u64s to avoid .quad
- * as it appears .quad isn't available in some assemblers.
- */
- for (re = bi->reservelist; re; re = re->next) {
- if (re->label) {
- fprintf(f, "\t.globl\t%s\n", re->label);
- fprintf(f, "%s:\n", re->label);
- }
- fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
- (unsigned int)(re->re.address >> 32),
- (unsigned int)(re->re.address & 0xffffffff));
- fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
- (unsigned int)(re->re.size >> 32),
- (unsigned int)(re->re.size & 0xffffffff));
- }
- for (i = 0; i < reservenum; i++) {
- fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
- }
-
- fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
-
- emit_label(f, symprefix, "struct_start");
- flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
- fprintf(f, "\t.long\tFDT_END\n");
- emit_label(f, symprefix, "struct_end");
-
- emit_label(f, symprefix, "strings_start");
- dump_stringtable_asm(f, strbuf);
- emit_label(f, symprefix, "strings_end");
-
- emit_label(f, symprefix, "blob_end");
-
- /*
- * If the user asked for more space than is used, pad it out.
- */
- if (minsize > 0) {
- fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n",
- minsize, symprefix, symprefix);
- }
- if (padsize > 0) {
- fprintf(f, "\t.space\t%d, 0\n", padsize);
- }
- emit_label(f, symprefix, "blob_abs_end");
-
- data_free(strbuf);
-}
-
-struct inbuf {
- char *base, *limit, *ptr;
-};
-
-static void inbuf_init(struct inbuf *inb, void *base, void *limit)
-{
- inb->base = base;
- inb->limit = limit;
- inb->ptr = inb->base;
-}
-
-static void flat_read_chunk(struct inbuf *inb, void *p, int len)
-{
- if ((inb->ptr + len) > inb->limit)
- die("Premature end of data parsing flat device tree\n");
-
- memcpy(p, inb->ptr, len);
-
- inb->ptr += len;
-}
-
-static uint32_t flat_read_word(struct inbuf *inb)
-{
- uint32_t val;
-
- assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
-
- flat_read_chunk(inb, &val, sizeof(val));
-
- return fdt32_to_cpu(val);
-}
-
-static void flat_realign(struct inbuf *inb, int align)
-{
- int off = inb->ptr - inb->base;
-
- inb->ptr = inb->base + ALIGN(off, align);
- if (inb->ptr > inb->limit)
- die("Premature end of data parsing flat device tree\n");
-}
-
-static char *flat_read_string(struct inbuf *inb)
-{
- int len = 0;
- const char *p = inb->ptr;
- char *str;
-
- do {
- if (p >= inb->limit)
- die("Premature end of data parsing flat device tree\n");
- len++;
- } while ((*p++) != '\0');
-
- str = strdup(inb->ptr);
-
- inb->ptr += len;
-
- flat_realign(inb, sizeof(uint32_t));
-
- return str;
-}
-
-static struct data flat_read_data(struct inbuf *inb, int len)
-{
- struct data d = empty_data;
-
- if (len == 0)
- return empty_data;
-
- d = data_grow_for(d, len);
- d.len = len;
-
- flat_read_chunk(inb, d.val, len);
-
- flat_realign(inb, sizeof(uint32_t));
-
- return d;
-}
-
-static char *flat_read_stringtable(struct inbuf *inb, int offset)
-{
- const char *p;
-
- p = inb->base + offset;
- while (1) {
- if (p >= inb->limit || p < inb->base)
- die("String offset %d overruns string table\n",
- offset);
-
- if (*p == '\0')
- break;
-
- p++;
- }
-
- return strdup(inb->base + offset);
-}
-
-static struct property *flat_read_property(struct inbuf *dtbuf,
- struct inbuf *strbuf, int flags)
-{
- uint32_t proplen, stroff;
- char *name;
- struct data val;
-
- proplen = flat_read_word(dtbuf);
- stroff = flat_read_word(dtbuf);
-
- name = flat_read_stringtable(strbuf, stroff);
-
- if ((flags & FTF_VARALIGN) && (proplen >= 8))
- flat_realign(dtbuf, 8);
-
- val = flat_read_data(dtbuf, proplen);
-
- return build_property(name, val, NULL);
-}
-
-
-static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
-{
- struct reserve_info *reservelist = NULL;
- struct reserve_info *new;
- const char *p;
- struct fdt_reserve_entry re;
-
- /*
- * Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
- * List terminates at an entry with size equal to zero.
- *
- * First pass, count entries.
- */
- p = inb->ptr;
- while (1) {
- flat_read_chunk(inb, &re, sizeof(re));
- re.address = fdt64_to_cpu(re.address);
- re.size = fdt64_to_cpu(re.size);
- if (re.size == 0)
- break;
-
- new = build_reserve_entry(re.address, re.size, NULL);
- reservelist = add_reserve_entry(reservelist, new);
- }
-
- return reservelist;
-}
-
-
-static char *nodename_from_path(const char *ppath, const char *cpath)
-{
- int plen;
-
- plen = strlen(ppath);
-
- if (!strneq(ppath, cpath, plen))
- die("Path \"%s\" is not valid as a child of \"%s\"\n",
- cpath, ppath);
-
- /* root node is a special case */
- if (!streq(ppath, "/"))
- plen++;
-
- return strdup(cpath + plen);
-}
-
-static struct node *unflatten_tree(struct inbuf *dtbuf,
- struct inbuf *strbuf,
- const char *parent_flatname, int flags)
-{
- struct node *node;
- char *flatname;
- uint32_t val;
-
- node = build_node(NULL, NULL);
-
- flatname = flat_read_string(dtbuf);
-
- if (flags & FTF_FULLPATH)
- node->name = nodename_from_path(parent_flatname, flatname);
- else
- node->name = flatname;
-
- do {
- struct property *prop;
- struct node *child;
-
- val = flat_read_word(dtbuf);
- switch (val) {
- case FDT_PROP:
- if (node->children)
- fprintf(stderr, "Warning: Flat tree input has "
- "subnodes preceding a property.\n");
- prop = flat_read_property(dtbuf, strbuf, flags);
- add_property(node, prop);
- break;
-
- case FDT_BEGIN_NODE:
- child = unflatten_tree(dtbuf,strbuf, flatname, flags);
- add_child(node, child);
- break;
-
- case FDT_END_NODE:
- break;
-
- case FDT_END:
- die("Premature FDT_END in device tree blob\n");
- break;
-
- case FDT_NOP:
- if (!(flags & FTF_NOPS))
- fprintf(stderr, "Warning: NOP tag found in flat tree"
- " version <16\n");
-
- /* Ignore */
- break;
-
- default:
- die("Invalid opcode word %08x in device tree blob\n",
- val);
- }
- } while (val != FDT_END_NODE);
-
- return node;
-}
-
-
-struct boot_info *dt_from_blob(const char *fname)
-{
- struct dtc_file *dtcf;
- uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
- uint32_t off_dt, off_str, off_mem_rsvmap;
- int rc;
- char *blob;
- struct fdt_header *fdt;
- char *p;
- struct inbuf dtbuf, strbuf;
- struct inbuf memresvbuf;
- int sizeleft;
- struct reserve_info *reservelist;
- struct node *tree;
- uint32_t val;
- int flags = 0;
-
- dtcf = dtc_open_file(fname, NULL);
-
- rc = fread(&magic, sizeof(magic), 1, dtcf->file);
- if (ferror(dtcf->file))
- die("Error reading DT blob magic number: %s\n",
- strerror(errno));
- if (rc < 1) {
- if (feof(dtcf->file))
- die("EOF reading DT blob magic number\n");
- else
- die("Mysterious short read reading magic number\n");
- }
-
- magic = fdt32_to_cpu(magic);
- if (magic != FDT_MAGIC)
- die("Blob has incorrect magic number\n");
-
- rc = fread(&totalsize, sizeof(totalsize), 1, dtcf->file);
- if (ferror(dtcf->file))
- die("Error reading DT blob size: %s\n", strerror(errno));
- if (rc < 1) {
- if (feof(dtcf->file))
- die("EOF reading DT blob size\n");
- else
- die("Mysterious short read reading blob size\n");
- }
-
- totalsize = fdt32_to_cpu(totalsize);
- if (totalsize < FDT_V1_SIZE)
- die("DT blob size (%d) is too small\n", totalsize);
-
- blob = xmalloc(totalsize);
-
- fdt = (struct fdt_header *)blob;
- fdt->magic = cpu_to_fdt32(magic);
- fdt->totalsize = cpu_to_fdt32(totalsize);
-
- sizeleft = totalsize - sizeof(magic) - sizeof(totalsize);
- p = blob + sizeof(magic) + sizeof(totalsize);
-
- while (sizeleft) {
- if (feof(dtcf->file))
- die("EOF before reading %d bytes of DT blob\n",
- totalsize);
-
- rc = fread(p, 1, sizeleft, dtcf->file);
- if (ferror(dtcf->file))
- die("Error reading DT blob: %s\n",
- strerror(errno));
-
- sizeleft -= rc;
- p += rc;
- }
-
- off_dt = fdt32_to_cpu(fdt->off_dt_struct);
- off_str = fdt32_to_cpu(fdt->off_dt_strings);
- off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap);
- version = fdt32_to_cpu(fdt->version);
- boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys);
-
- if (off_mem_rsvmap >= totalsize)
- die("Mem Reserve structure offset exceeds total size\n");
-
- if (off_dt >= totalsize)
- die("DT structure offset exceeds total size\n");
-
- if (off_str > totalsize)
- die("String table offset exceeds total size\n");
-
- if (version >= 3) {
- uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
- if (off_str+size_str > totalsize)
- die("String table extends past total size\n");
- inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
- } else {
- inbuf_init(&strbuf, blob + off_str, blob + totalsize);
- }
-
- if (version >= 17) {
- size_dt = fdt32_to_cpu(fdt->size_dt_struct);
- if (off_dt+size_dt > totalsize)
- die("Structure block extends past total size\n");
- }
-
- if (version < 16) {
- flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN;
- } else {
- flags |= FTF_NOPS;
- }
-
- inbuf_init(&memresvbuf,
- blob + off_mem_rsvmap, blob + totalsize);
- inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
-
- reservelist = flat_read_mem_reserve(&memresvbuf);
-
- val = flat_read_word(&dtbuf);
-
- if (val != FDT_BEGIN_NODE)
- die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val);
-
- tree = unflatten_tree(&dtbuf, &strbuf, "", flags);
-
- val = flat_read_word(&dtbuf);
- if (val != FDT_END)
- die("Device tree blob doesn't end with FDT_END\n");
-
- free(blob);
-
- dtc_close_file(dtcf);
-
- return build_boot_info(reservelist, tree, boot_cpuid_phys);
-}
+++ /dev/null
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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 "dtc.h"
-
-#include <dirent.h>
-#include <sys/stat.h>
-
-static struct node *read_fstree(const char *dirname)
-{
- DIR *d;
- struct dirent *de;
- struct stat st;
- struct node *tree;
-
- d = opendir(dirname);
- if (!d)
- die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
-
- tree = build_node(NULL, NULL);
-
- while ((de = readdir(d)) != NULL) {
- char *tmpnam;
-
- if (streq(de->d_name, ".")
- || streq(de->d_name, ".."))
- continue;
-
- tmpnam = join_path(dirname, de->d_name);
-
- if (lstat(tmpnam, &st) < 0)
- die("stat(%s): %s\n", tmpnam, strerror(errno));
-
- if (S_ISREG(st.st_mode)) {
- struct property *prop;
- FILE *pfile;
-
- pfile = fopen(tmpnam, "r");
- if (! pfile) {
- fprintf(stderr,
- "WARNING: Cannot open %s: %s\n",
- tmpnam, strerror(errno));
- } else {
- prop = build_property(strdup(de->d_name),
- data_copy_file(pfile,
- st.st_size),
- NULL);
- add_property(tree, prop);
- fclose(pfile);
- }
- } else if (S_ISDIR(st.st_mode)) {
- struct node *newchild;
-
- newchild = read_fstree(tmpnam);
- newchild = name_node(newchild, strdup(de->d_name),
- NULL);
- add_child(tree, newchild);
- }
-
- free(tmpnam);
- }
-
- return tree;
-}
-
-struct boot_info *dt_from_fs(const char *dirname)
-{
- struct node *tree;
-
- tree = read_fstree(dirname);
- tree = name_node(tree, "", NULL);
-
- return build_boot_info(NULL, tree, 0);
-}
-
+++ /dev/null
-#ifndef _LIBFDT_ENV_H
-#define _LIBFDT_ENV_H
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#define _B(n) ((unsigned long long)((uint8_t *)&x)[n])
-static inline uint32_t fdt32_to_cpu(uint32_t x)
-{
- return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
-}
-#define cpu_to_fdt32(x) fdt32_to_cpu(x)
-
-static inline uint64_t fdt64_to_cpu(uint64_t x)
-{
- return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
- | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
-}
-#define cpu_to_fdt64(x) fdt64_to_cpu(x)
-#undef _B
-
-#endif /* _LIBFDT_ENV_H */
+++ /dev/null
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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 "dtc.h"
-
-/*
- * Tree building functions
- */
-
-struct property *build_property(char *name, struct data val, char *label)
-{
- struct property *new = xmalloc(sizeof(*new));
-
- new->name = name;
- new->val = val;
-
- new->next = NULL;
-
- new->label = label;
-
- return new;
-}
-
-struct property *chain_property(struct property *first, struct property *list)
-{
- assert(first->next == NULL);
-
- first->next = list;
- return first;
-}
-
-struct property *reverse_properties(struct property *first)
-{
- struct property *p = first;
- struct property *head = NULL;
- struct property *next;
-
- while (p) {
- next = p->next;
- p->next = head;
- head = p;
- p = next;
- }
- return head;
-}
-
-struct node *build_node(struct property *proplist, struct node *children)
-{
- struct node *new = xmalloc(sizeof(*new));
- struct node *child;
-
- memset(new, 0, sizeof(*new));
-
- new->proplist = reverse_properties(proplist);
- new->children = children;
-
- for_each_child(new, child) {
- child->parent = new;
- }
-
- return new;
-}
-
-struct node *name_node(struct node *node, char *name, char * label)
-{
- assert(node->name == NULL);
-
- node->name = name;
-
- node->label = label;
-
- return node;
-}
-
-struct node *chain_node(struct node *first, struct node *list)
-{
- assert(first->next_sibling == NULL);
-
- first->next_sibling = list;
- return first;
-}
-
-void add_property(struct node *node, struct property *prop)
-{
- struct property **p;
-
- prop->next = NULL;
-
- p = &node->proplist;
- while (*p)
- p = &((*p)->next);
-
- *p = prop;
-}
-
-void add_child(struct node *parent, struct node *child)
-{
- struct node **p;
-
- child->next_sibling = NULL;
- child->parent = parent;
-
- p = &parent->children;
- while (*p)
- p = &((*p)->next_sibling);
-
- *p = child;
-}
-
-struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size,
- char *label)
-{
- struct reserve_info *new = xmalloc(sizeof(*new));
-
- new->re.address = address;
- new->re.size = size;
-
- new->next = NULL;
-
- new->label = label;
-
- return new;
-}
-
-struct reserve_info *chain_reserve_entry(struct reserve_info *first,
- struct reserve_info *list)
-{
- assert(first->next == NULL);
-
- first->next = list;
- return first;
-}
-
-struct reserve_info *add_reserve_entry(struct reserve_info *list,
- struct reserve_info *new)
-{
- struct reserve_info *last;
-
- new->next = NULL;
-
- if (! list)
- return new;
-
- for (last = list; last->next; last = last->next)
- ;
-
- last->next = new;
-
- return list;
-}
-
-struct boot_info *build_boot_info(struct reserve_info *reservelist,
- struct node *tree, uint32_t boot_cpuid_phys)
-{
- struct boot_info *bi;
-
- bi = xmalloc(sizeof(*bi));
- bi->reservelist = reservelist;
- bi->dt = tree;
- bi->boot_cpuid_phys = boot_cpuid_phys;
-
- return bi;
-}
-
-/*
- * Tree accessor functions
- */
-
-const char *get_unitname(struct node *node)
-{
- if (node->name[node->basenamelen] == '\0')
- return "";
- else
- return node->name + node->basenamelen + 1;
-}
-
-struct property *get_property(struct node *node, const char *propname)
-{
- struct property *prop;
-
- for_each_property(node, prop)
- if (streq(prop->name, propname))
- return prop;
-
- return NULL;
-}
-
-cell_t propval_cell(struct property *prop)
-{
- assert(prop->val.len == sizeof(cell_t));
- return fdt32_to_cpu(*((cell_t *)prop->val.val));
-}
-
-struct node *get_subnode(struct node *node, const char *nodename)
-{
- struct node *child;
-
- for_each_child(node, child)
- if (streq(child->name, nodename))
- return child;
-
- return NULL;
-}
-
-struct node *get_node_by_path(struct node *tree, const char *path)
-{
- const char *p;
- struct node *child;
-
- if (!path || ! (*path))
- return tree;
-
- while (path[0] == '/')
- path++;
-
- p = strchr(path, '/');
-
- for_each_child(tree, child) {
- if (p && strneq(path, child->name, p-path))
- return get_node_by_path(child, p+1);
- else if (!p && streq(path, child->name))
- return child;
- }
-
- return NULL;
-}
-
-struct node *get_node_by_label(struct node *tree, const char *label)
-{
- struct node *child, *node;
-
- assert(label && (strlen(label) > 0));
-
- if (tree->label && streq(tree->label, label))
- return tree;
-
- for_each_child(tree, child) {
- node = get_node_by_label(child, label);
- if (node)
- return node;
- }
-
- return NULL;
-}
-
-struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
-{
- struct node *child, *node;
-
- assert((phandle != 0) && (phandle != -1));
-
- if (tree->phandle == phandle)
- return tree;
-
- for_each_child(tree, child) {
- node = get_node_by_phandle(child, phandle);
- if (node)
- return node;
- }
-
- return NULL;
-}
-
-struct node *get_node_by_ref(struct node *tree, const char *ref)
-{
- if (ref[0] == '/')
- return get_node_by_path(tree, ref);
- else
- return get_node_by_label(tree, ref);
-}
-
-cell_t get_node_phandle(struct node *root, struct node *node)
-{
- static cell_t phandle = 1; /* FIXME: ick, static local */
-
- if ((node->phandle != 0) && (node->phandle != -1))
- return node->phandle;
-
- assert(! get_property(node, "linux,phandle"));
-
- while (get_node_by_phandle(root, phandle))
- phandle++;
-
- node->phandle = phandle;
- add_property(node,
- build_property("linux,phandle",
- data_append_cell(empty_data, phandle),
- NULL));
-
- return node->phandle;
-}
+++ /dev/null
-/*
- * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
- *
- * 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 "dtc.h"
-#include "srcpos.h"
-
-/*
- * Like yylineno, this is the current open file pos.
- */
-
-struct dtc_file *srcpos_file;
-
-static int dtc_open_one(struct dtc_file *file,
- const char *search,
- const char *fname)
-{
- char *fullname;
-
- if (search) {
- fullname = xmalloc(strlen(search) + strlen(fname) + 2);
-
- strcpy(fullname, search);
- strcat(fullname, "/");
- strcat(fullname, fname);
- } else {
- fullname = strdup(fname);
- }
-
- file->file = fopen(fullname, "r");
- if (!file->file) {
- free(fullname);
- return 0;
- }
-
- file->name = fullname;
- return 1;
-}
-
-
-struct dtc_file *dtc_open_file(const char *fname,
- const struct search_path *search)
-{
- static const struct search_path default_search = { NULL, NULL, NULL };
-
- struct dtc_file *file;
- const char *slash;
-
- file = xmalloc(sizeof(struct dtc_file));
-
- slash = strrchr(fname, '/');
- if (slash) {
- char *dir = xmalloc(slash - fname + 1);
-
- memcpy(dir, fname, slash - fname);
- dir[slash - fname] = 0;
- file->dir = dir;
- } else {
- file->dir = NULL;
- }
-
- if (streq(fname, "-")) {
- file->name = "stdin";
- file->file = stdin;
- return file;
- }
-
- if (fname[0] == '/') {
- file->file = fopen(fname, "r");
- if (!file->file)
- goto fail;
-
- file->name = strdup(fname);
- return file;
- }
-
- if (!search)
- search = &default_search;
-
- while (search) {
- if (dtc_open_one(file, search->dir, fname))
- return file;
-
- if (errno != ENOENT)
- goto fail;
-
- search = search->next;
- }
-
-fail:
- die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
-}
-
-void dtc_close_file(struct dtc_file *file)
-{
- if (fclose(file->file))
- die("Error closing \"%s\": %s\n", file->name, strerror(errno));
-
- free(file->dir);
- free(file);
-}
+++ /dev/null
-/*
- * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
- *
- * 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
- */
-
-/*
- * Augment the standard YYLTYPE with a filenum index into an
- * array of all opened filenames.
- */
-
-#include <stdio.h>
-
-struct dtc_file {
- char *dir;
- const char *name;
- FILE *file;
-};
-
-#if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED)
-typedef struct YYLTYPE {
- int first_line;
- int first_column;
- int last_line;
- int last_column;
- struct dtc_file *file;
-} YYLTYPE;
-
-#define YYLTYPE_IS_DECLARED 1
-#define YYLTYPE_IS_TRIVIAL 1
-#endif
-
-/* Cater to old parser templates. */
-#ifndef YYID
-#define YYID(n) (n)
-#endif
-
-#define YYLLOC_DEFAULT(Current, Rhs, N) \
- do \
- if (YYID (N)) \
- { \
- (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
- (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
- (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
- (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
- (Current).file = YYRHSLOC (Rhs, N).file; \
- } \
- else \
- { \
- (Current).first_line = (Current).last_line = \
- YYRHSLOC (Rhs, 0).last_line; \
- (Current).first_column = (Current).last_column = \
- YYRHSLOC (Rhs, 0).last_column; \
- (Current).file = YYRHSLOC (Rhs, 0).file; \
- } \
- while (YYID (0))
-
-
-
-extern void yyerror(char const *);
-extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
-
-extern struct dtc_file *srcpos_file;
-
-struct search_path {
- const char *dir; /* NULL for current directory */
- struct search_path *prev, *next;
-};
-
-extern struct dtc_file *dtc_open_file(const char *fname,
- const struct search_path *search);
-extern void dtc_close_file(struct dtc_file *file);
+++ /dev/null
-/*
- * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
- *
- *
- * 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 "dtc.h"
-#include "srcpos.h"
-
-extern FILE *yyin;
-extern int yyparse(void);
-
-struct boot_info *the_boot_info;
-int treesource_error;
-
-struct boot_info *dt_from_source(const char *fname)
-{
- the_boot_info = NULL;
- treesource_error = 0;
-
- srcpos_file = dtc_open_file(fname, NULL);
- yyin = srcpos_file->file;
-
- if (yyparse() != 0)
- die("Unable to parse input tree\n");
-
- if (treesource_error)
- die("Syntax error parsing input tree\n");
-
- return the_boot_info;
-}
-
-static void write_prefix(FILE *f, int level)
-{
- int i;
-
- for (i = 0; i < level; i++)
- fputc('\t', f);
-}
-
-int isstring(char c)
-{
- return (isprint(c)
- || (c == '\0')
- || strchr("\a\b\t\n\v\f\r", c));
-}
-
-static void write_propval_string(FILE *f, struct data val)
-{
- const char *str = val.val;
- int i;
- int newchunk = 1;
- struct marker *m = val.markers;
-
- assert(str[val.len-1] == '\0');
-
- for (i = 0; i < (val.len-1); i++) {
- char c = str[i];
-
- if (newchunk) {
- while (m && (m->offset <= i)) {
- if (m->type == LABEL) {
- assert(m->offset == i);
- fprintf(f, "%s: ", m->ref);
- }
- m = m->next;
- }
- fprintf(f, "\"");
- newchunk = 0;
- }
-
- switch (c) {
- case '\a':
- fprintf(f, "\\a");
- break;
- case '\b':
- fprintf(f, "\\b");
- break;
- case '\t':
- fprintf(f, "\\t");
- break;
- case '\n':
- fprintf(f, "\\n");
- break;
- case '\v':
- fprintf(f, "\\v");
- break;
- case '\f':
- fprintf(f, "\\f");
- break;
- case '\r':
- fprintf(f, "\\r");
- break;
- case '\\':
- fprintf(f, "\\\\");
- break;
- case '\"':
- fprintf(f, "\\\"");
- break;
- case '\0':
- fprintf(f, "\", ");
- newchunk = 1;
- break;
- default:
- if (isprint(c))
- fprintf(f, "%c", c);
- else
- fprintf(f, "\\x%02hhx", c);
- }
- }
- fprintf(f, "\"");
-
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m, LABEL) {
- assert (m->offset == val.len);
- fprintf(f, " %s:", m->ref);
- }
-}
-
-static void write_propval_cells(FILE *f, struct data val)
-{
- void *propend = val.val + val.len;
- cell_t *cp = (cell_t *)val.val;
- struct marker *m = val.markers;
-
- fprintf(f, "<");
- for (;;) {
- while (m && (m->offset <= ((char *)cp - val.val))) {
- if (m->type == LABEL) {
- assert(m->offset == ((char *)cp - val.val));
- fprintf(f, "%s: ", m->ref);
- }
- m = m->next;
- }
-
- fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
- if ((void *)cp >= propend)
- break;
- fprintf(f, " ");
- }
-
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m, LABEL) {
- assert (m->offset == val.len);
- fprintf(f, " %s:", m->ref);
- }
- fprintf(f, ">");
-}
-
-static void write_propval_bytes(FILE *f, struct data val)
-{
- void *propend = val.val + val.len;
- const char *bp = val.val;
- struct marker *m = val.markers;
-
- fprintf(f, "[");
- for (;;) {
- while (m && (m->offset == (bp-val.val))) {
- if (m->type == LABEL)
- fprintf(f, "%s: ", m->ref);
- m = m->next;
- }
-
- fprintf(f, "%02hhx", *bp++);
- if ((const void *)bp >= propend)
- break;
- fprintf(f, " ");
- }
-
- /* Wrap up any labels at the end of the value */
- for_each_marker_of_type(m, LABEL) {
- assert (m->offset == val.len);
- fprintf(f, " %s:", m->ref);
- }
- fprintf(f, "]");
-}
-
-static void write_propval(FILE *f, struct property *prop)
-{
- int len = prop->val.len;
- const char *p = prop->val.val;
- struct marker *m = prop->val.markers;
- int nnotstring = 0, nnul = 0;
- int nnotstringlbl = 0, nnotcelllbl = 0;
- int i;
-
- if (len == 0) {
- fprintf(f, ";\n");
- return;
- }
-
- for (i = 0; i < len; i++) {
- if (! isstring(p[i]))
- nnotstring++;
- if (p[i] == '\0')
- nnul++;
- }
-
- for_each_marker_of_type(m, LABEL) {
- if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
- nnotstringlbl++;
- if ((m->offset % sizeof(cell_t)) != 0)
- nnotcelllbl++;
- }
-
- fprintf(f, " = ");
- if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
- && (nnotstringlbl == 0)) {
- write_propval_string(f, prop->val);
- } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
- write_propval_cells(f, prop->val);
- } else {
- write_propval_bytes(f, prop->val);
- }
-
- fprintf(f, ";\n");
-}
-
-static void write_tree_source_node(FILE *f, struct node *tree, int level)
-{
- struct property *prop;
- struct node *child;
-
- write_prefix(f, level);
- if (tree->label)
- fprintf(f, "%s: ", tree->label);
- if (tree->name && (*tree->name))
- fprintf(f, "%s {\n", tree->name);
- else
- fprintf(f, "/ {\n");
-
- for_each_property(tree, prop) {
- write_prefix(f, level+1);
- if (prop->label)
- fprintf(f, "%s: ", prop->label);
- fprintf(f, "%s", prop->name);
- write_propval(f, prop);
- }
- for_each_child(tree, child) {
- fprintf(f, "\n");
- write_tree_source_node(f, child, level+1);
- }
- write_prefix(f, level);
- fprintf(f, "};\n");
-}
-
-
-void dt_to_source(FILE *f, struct boot_info *bi)
-{
- struct reserve_info *re;
-
- fprintf(f, "/dts-v1/;\n\n");
-
- for (re = bi->reservelist; re; re = re->next) {
- if (re->label)
- fprintf(f, "%s: ", re->label);
- fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
- (unsigned long long)re->re.address,
- (unsigned long long)re->re.size);
- }
-
- write_tree_source_node(f, bi->dt, 0);
-}
-
+++ /dev/null
-#define DTC_VERSION "DTC 1.2.0"
+++ /dev/null
-# Makefile.libfdt
-#
-# This is not a complete Makefile of itself. Instead, it is designed to
-# be easily embeddable into other systems of Makefiles.
-#
-LIBFDT_INCLUDES = fdt.h libfdt.h
-LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
-LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
+++ /dev/null
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library 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 library 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 library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "libfdt_env.h"
-
-#include <fdt.h>
-#include <libfdt.h>
-
-#include "libfdt_internal.h"
-
-int fdt_check_header(const void *fdt)
-{
- if (fdt_magic(fdt) == FDT_MAGIC) {
- /* Complete tree */
- if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
- return -FDT_ERR_BADVERSION;
- if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
- return -FDT_ERR_BADVERSION;
- } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
- /* Unfinished sequential-write blob */
- if (fdt_size_dt_struct(fdt) == 0)
- return -FDT_ERR_BADSTATE;
- } else {
- return -FDT_ERR_BADMAGIC;
- }
-
- return 0;
-}
-
-const void *fdt_offset_ptr(const void *fdt, int offset, int len)
-{
- const char *p;
-
- if (fdt_version(fdt) >= 0x11)
- if (((offset + len) < offset)
- || ((offset + len) > fdt_size_dt_struct(fdt)))
- return NULL;
-
- p = _fdt_offset_ptr(fdt, offset);
-
- if (p + len < p)
- return NULL;
- return p;
-}
-
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
-{
- const uint32_t *tagp, *lenp;
- uint32_t tag;
- const char *p;
-
- if (offset % FDT_TAGSIZE)
- return -1;
-
- tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
- if (! tagp)
- return FDT_END; /* premature end */
- tag = fdt32_to_cpu(*tagp);
- offset += FDT_TAGSIZE;
-
- switch (tag) {
- case FDT_BEGIN_NODE:
- /* skip name */
- do {
- p = fdt_offset_ptr(fdt, offset++, 1);
- } while (p && (*p != '\0'));
- if (! p)
- return FDT_END;
- break;
- case FDT_PROP:
- lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
- if (! lenp)
- return FDT_END;
- /* skip name offset, length and value */
- offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
- break;
- }
-
- if (nextoffset)
- *nextoffset = FDT_TAGALIGN(offset);
-
- return tag;
-}
-
-int _fdt_check_node_offset(const void *fdt, int offset)
-{
- if ((offset < 0) || (offset % FDT_TAGSIZE)
- || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
- return -FDT_ERR_BADOFFSET;
-
- return offset;
-}
-
-int fdt_next_node(const void *fdt, int offset, int *depth)
-{
- int nextoffset = 0;
- uint32_t tag;
-
- if (offset >= 0)
- if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
- return nextoffset;
-
- do {
- offset = nextoffset;
- tag = fdt_next_tag(fdt, offset, &nextoffset);
-
- switch (tag) {
- case FDT_PROP:
- case FDT_NOP:
- break;
-
- case FDT_BEGIN_NODE:
- if (depth)
- (*depth)++;
- break;
-
- case FDT_END_NODE:
- if (depth)
- (*depth)--;
- break;
-
- case FDT_END:
- return -FDT_ERR_NOTFOUND;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
- }
- } while (tag != FDT_BEGIN_NODE);
-
- return offset;
-}
-
-const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
-{
- int len = strlen(s) + 1;
- const char *last = strtab + tabsize - len;
- const char *p;
-
- for (p = strtab; p <= last; p++)
- if (memcmp(p, s, len) == 0)
- return p;
- return NULL;
-}
-
-int fdt_move(const void *fdt, void *buf, int bufsize)
-{
- FDT_CHECK_HEADER(fdt);
-
- if (fdt_totalsize(fdt) > bufsize)
- return -FDT_ERR_NOSPACE;
-
- memmove(buf, fdt, fdt_totalsize(fdt));
- return 0;
-}
+++ /dev/null
-#ifndef _FDT_H
-#define _FDT_H
-
-#ifndef __ASSEMBLY__
-
-struct fdt_header {
- uint32_t magic; /* magic word FDT_MAGIC */
- uint32_t totalsize; /* total size of DT block */
- uint32_t off_dt_struct; /* offset to structure */
- uint32_t off_dt_strings; /* offset to strings */
- uint32_t off_mem_rsvmap; /* offset to memory reserve map */
- uint32_t version; /* format version */
- uint32_t last_comp_version; /* last compatible version */
-
- /* version 2 fields below */
- uint32_t boot_cpuid_phys; /* Which physical CPU id we're
- booting on */
- /* version 3 fields below */
- uint32_t size_dt_strings; /* size of the strings block */
-
- /* version 17 fields below */
- uint32_t size_dt_struct; /* size of the structure block */
-};
-
-struct fdt_reserve_entry {
- uint64_t address;
- uint64_t size;
-};
-
-struct fdt_node_header {
- uint32_t tag;
- char name[0];
-};
-
-struct fdt_property {
- uint32_t tag;
- uint32_t len;
- uint32_t nameoff;
- char data[0];
-};
-
-#endif /* !__ASSEMBLY */
-
-#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
-#define FDT_TAGSIZE sizeof(uint32_t)
-
-#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
-#define FDT_END_NODE 0x2 /* End node */
-#define FDT_PROP 0x3 /* Property: name off,
- size, content */
-#define FDT_NOP 0x4 /* nop */
-#define FDT_END 0x9
-
-#define FDT_V1_SIZE (7*sizeof(uint32_t))
-#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t))
-#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t))
-#define FDT_V16_SIZE FDT_V3_SIZE
-#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t))
-
-#endif /* _FDT_H */
+++ /dev/null
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library 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 library 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 library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "libfdt_env.h"
-
-#include <fdt.h>
-#include <libfdt.h>
-
-#include "libfdt_internal.h"
-
-static int _fdt_nodename_eq(const void *fdt, int offset,
- const char *s, int len)
-{
- const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
-
- if (! p)
- /* short match */
- return 0;
-
- if (memcmp(p, s, len) != 0)
- return 0;
-
- if (p[len] == '\0')
- return 1;
- else if (!memchr(s, '@', len) && (p[len] == '@'))
- return 1;
- else
- return 0;
-}
-
-const char *fdt_string(const void *fdt, int stroffset)
-{
- return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
-}
-
-int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
-{
- FDT_CHECK_HEADER(fdt);
- *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
- *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
- return 0;
-}
-
-int fdt_num_mem_rsv(const void *fdt)
-{
- int i = 0;
-
- while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
- i++;
- return i;
-}
-
-int fdt_subnode_offset_namelen(const void *fdt, int offset,
- const char *name, int namelen)
-{
- int depth;
-
- FDT_CHECK_HEADER(fdt);
-
- for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
- (offset >= 0) && (depth > 0);
- offset = fdt_next_node(fdt, offset, &depth)) {
- if (depth < 0)
- return -FDT_ERR_NOTFOUND;
- else if ((depth == 1)
- && _fdt_nodename_eq(fdt, offset, name, namelen))
- return offset;
- }
-
- if (offset < 0)
- return offset; /* error */
- else
- return -FDT_ERR_NOTFOUND;
-}
-
-int fdt_subnode_offset(const void *fdt, int parentoffset,
- const char *name)
-{
- return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
-}
-
-int fdt_path_offset(const void *fdt, const char *path)
-{
- const char *end = path + strlen(path);
- const char *p = path;
- int offset = 0;
-
- FDT_CHECK_HEADER(fdt);
-
- if (*path != '/')
- return -FDT_ERR_BADPATH;
-
- while (*p) {
- const char *q;
-
- while (*p == '/')
- p++;
- if (! *p)
- return offset;
- q = strchr(p, '/');
- if (! q)
- q = end;
-
- offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
- if (offset < 0)
- return offset;
-
- p = q;
- }
-
- return offset;
-}
-
-const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
-{
- const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
- int err;
-
- if (((err = fdt_check_header(fdt)) != 0)
- || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
- goto fail;
-
- if (len)
- *len = strlen(nh->name);
-
- return nh->name;
-
- fail:
- if (len)
- *len = err;
- return NULL;
-}
-
-const struct fdt_property *fdt_get_property(const void *fdt,
- int nodeoffset,
- const char *name, int *lenp)
-{
- uint32_t tag;
- const struct fdt_property *prop;
- int namestroff;
- int offset, nextoffset;
- int err;
-
- if (((err = fdt_check_header(fdt)) != 0)
- || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
- goto fail;
-
- nextoffset = err;
- do {
- offset = nextoffset;
-
- tag = fdt_next_tag(fdt, offset, &nextoffset);
- switch (tag) {
- case FDT_END:
- err = -FDT_ERR_TRUNCATED;
- goto fail;
-
- case FDT_BEGIN_NODE:
- case FDT_END_NODE:
- case FDT_NOP:
- break;
-
- case FDT_PROP:
- err = -FDT_ERR_BADSTRUCTURE;
- prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
- if (! prop)
- goto fail;
- namestroff = fdt32_to_cpu(prop->nameoff);
- if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
- /* Found it! */
- int len = fdt32_to_cpu(prop->len);
- prop = fdt_offset_ptr(fdt, offset,
- sizeof(*prop)+len);
- if (! prop)
- goto fail;
-
- if (lenp)
- *lenp = len;
-
- return prop;
- }
- break;
-
- default:
- err = -FDT_ERR_BADSTRUCTURE;
- goto fail;
- }
- } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
-
- err = -FDT_ERR_NOTFOUND;
- fail:
- if (lenp)
- *lenp = err;
- return NULL;
-}
-
-const void *fdt_getprop(const void *fdt, int nodeoffset,
- const char *name, int *lenp)
-{
- const struct fdt_property *prop;
-
- prop = fdt_get_property(fdt, nodeoffset, name, lenp);
- if (! prop)
- return NULL;
-
- return prop->data;
-}
-
-uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
-{
- const uint32_t *php;
- int len;
-
- php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
- if (!php || (len != sizeof(*php)))
- return 0;
-
- return fdt32_to_cpu(*php);
-}
-
-int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
-{
- int pdepth = 0, p = 0;
- int offset, depth, namelen;
- const char *name;
-
- FDT_CHECK_HEADER(fdt);
-
- if (buflen < 2)
- return -FDT_ERR_NOSPACE;
-
- for (offset = 0, depth = 0;
- (offset >= 0) && (offset <= nodeoffset);
- offset = fdt_next_node(fdt, offset, &depth)) {
- if (pdepth < depth)
- continue; /* overflowed buffer */
-
- while (pdepth > depth) {
- do {
- p--;
- } while (buf[p-1] != '/');
- pdepth--;
- }
-
- name = fdt_get_name(fdt, offset, &namelen);
- if (!name)
- return namelen;
- if ((p + namelen + 1) <= buflen) {
- memcpy(buf + p, name, namelen);
- p += namelen;
- buf[p++] = '/';
- pdepth++;
- }
-
- if (offset == nodeoffset) {
- if (pdepth < (depth + 1))
- return -FDT_ERR_NOSPACE;
-
- if (p > 1) /* special case so that root path is "/", not "" */
- p--;
- buf[p] = '\0';
- return p;
- }
- }
-
- if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
- return -FDT_ERR_BADOFFSET;
- else if (offset == -FDT_ERR_BADOFFSET)
- return -FDT_ERR_BADSTRUCTURE;
-
- return offset; /* error from fdt_next_node() */
-}
-
-int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
- int supernodedepth, int *nodedepth)
-{
- int offset, depth;
- int supernodeoffset = -FDT_ERR_INTERNAL;
-
- FDT_CHECK_HEADER(fdt);
-
- if (supernodedepth < 0)
- return -FDT_ERR_NOTFOUND;
-
- for (offset = 0, depth = 0;
- (offset >= 0) && (offset <= nodeoffset);
- offset = fdt_next_node(fdt, offset, &depth)) {
- if (depth == supernodedepth)
- supernodeoffset = offset;
-
- if (offset == nodeoffset) {
- if (nodedepth)
- *nodedepth = depth;
-
- if (supernodedepth > depth)
- return -FDT_ERR_NOTFOUND;
- else
- return supernodeoffset;
- }
- }
-
- if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
- return -FDT_ERR_BADOFFSET;
- else if (offset == -FDT_ERR_BADOFFSET)
- return -FDT_ERR_BADSTRUCTURE;
-
- return offset; /* error from fdt_next_node() */
-}
-
-int fdt_node_depth(const void *fdt, int nodeoffset)
-{
- int nodedepth;
- int err;
-
- err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
- if (err)
- return (err < 0) ? err : -FDT_ERR_INTERNAL;
- return nodedepth;
-}
-
-int fdt_parent_offset(const void *fdt, int nodeoffset)
-{
- int nodedepth = fdt_node_depth(fdt, nodeoffset);
-
- if (nodedepth < 0)
- return nodedepth;
- return fdt_supernode_atdepth_offset(fdt, nodeoffset,
- nodedepth - 1, NULL);
-}
-
-int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
- const char *propname,
- const void *propval, int proplen)
-{
- int offset;
- const void *val;
- int len;
-
- FDT_CHECK_HEADER(fdt);
-
- /* FIXME: The algorithm here is pretty horrible: we scan each
- * property of a node in fdt_getprop(), then if that didn't
- * find what we want, we scan over them again making our way
- * to the next node. Still it's the easiest to implement
- * approach; performance can come later. */
- for (offset = fdt_next_node(fdt, startoffset, NULL);
- offset >= 0;
- offset = fdt_next_node(fdt, offset, NULL)) {
- val = fdt_getprop(fdt, offset, propname, &len);
- if (val && (len == proplen)
- && (memcmp(val, propval, len) == 0))
- return offset;
- }
-
- return offset; /* error from fdt_next_node() */
-}
-
-int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
-{
- if ((phandle == 0) || (phandle == -1))
- return -FDT_ERR_BADPHANDLE;
- phandle = cpu_to_fdt32(phandle);
- return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
- &phandle, sizeof(phandle));
-}
-
-int _stringlist_contains(const char *strlist, int listlen, const char *str)
-{
- int len = strlen(str);
- const char *p;
-
- while (listlen >= len) {
- if (memcmp(str, strlist, len+1) == 0)
- return 1;
- p = memchr(strlist, '\0', listlen);
- if (!p)
- return 0; /* malformed strlist.. */
- listlen -= (p-strlist) + 1;
- strlist = p + 1;
- }
- return 0;
-}
-
-int fdt_node_check_compatible(const void *fdt, int nodeoffset,
- const char *compatible)
-{
- const void *prop;
- int len;
-
- prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
- if (!prop)
- return len;
- if (_stringlist_contains(prop, len, compatible))
- return 0;
- else
- return 1;
-}
-
-int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
- const char *compatible)
-{
- int offset, err;
-
- FDT_CHECK_HEADER(fdt);
-
- /* FIXME: The algorithm here is pretty horrible: we scan each
- * property of a node in fdt_node_check_compatible(), then if
- * that didn't find what we want, we scan over them again
- * making our way to the next node. Still it's the easiest to
- * implement approach; performance can come later. */
- for (offset = fdt_next_node(fdt, startoffset, NULL);
- offset >= 0;
- offset = fdt_next_node(fdt, offset, NULL)) {
- err = fdt_node_check_compatible(fdt, offset, compatible);
- if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
- return err;
- else if (err == 0)
- return offset;
- }
-
- return offset; /* error from fdt_next_node() */
-}
+++ /dev/null
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library 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 library 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 library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "libfdt_env.h"
-
-#include <fdt.h>
-#include <libfdt.h>
-
-#include "libfdt_internal.h"
-
-static int _fdt_blocks_misordered(const void *fdt,
- int mem_rsv_size, int struct_size)
-{
- return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
- || (fdt_off_dt_struct(fdt) <
- (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
- || (fdt_off_dt_strings(fdt) <
- (fdt_off_dt_struct(fdt) + struct_size))
- || (fdt_totalsize(fdt) <
- (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
-}
-
-static int _fdt_rw_check_header(void *fdt)
-{
- FDT_CHECK_HEADER(fdt);
-
- if (fdt_version(fdt) < 17)
- return -FDT_ERR_BADVERSION;
- if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
- fdt_size_dt_struct(fdt)))
- return -FDT_ERR_BADLAYOUT;
- if (fdt_version(fdt) > 17)
- fdt_set_version(fdt, 17);
-
- return 0;
-}
-
-#define FDT_RW_CHECK_HEADER(fdt) \
- { \
- int err; \
- if ((err = _fdt_rw_check_header(fdt)) != 0) \
- return err; \
- }
-
-static inline int _fdt_data_size(void *fdt)
-{
- return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
-}
-
-static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
-{
- char *p = splicepoint;
- char *end = (char *)fdt + _fdt_data_size(fdt);
-
- if (((p + oldlen) < p) || ((p + oldlen) > end))
- return -FDT_ERR_BADOFFSET;
- if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
- return -FDT_ERR_NOSPACE;
- memmove(p + newlen, p + oldlen, end - p - oldlen);
- return 0;
-}
-
-static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
- int oldn, int newn)
-{
- int delta = (newn - oldn) * sizeof(*p);
- int err;
- err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
- if (err)
- return err;
- fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
- fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
- return 0;
-}
-
-static int _fdt_splice_struct(void *fdt, void *p,
- int oldlen, int newlen)
-{
- int delta = newlen - oldlen;
- int err;
-
- if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
- return err;
-
- fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
- fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
- return 0;
-}
-
-static int _fdt_splice_string(void *fdt, int newlen)
-{
- void *p = (char *)fdt
- + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
- int err;
-
- if ((err = _fdt_splice(fdt, p, 0, newlen)))
- return err;
-
- fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
- return 0;
-}
-
-static int _fdt_find_add_string(void *fdt, const char *s)
-{
- char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
- const char *p;
- char *new;
- int len = strlen(s) + 1;
- int err;
-
- p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
- if (p)
- /* found it */
- return (p - strtab);
-
- new = strtab + fdt_size_dt_strings(fdt);
- err = _fdt_splice_string(fdt, len);
- if (err)
- return err;
-
- memcpy(new, s, len);
- return (new - strtab);
-}
-
-int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
-{
- struct fdt_reserve_entry *re;
- int err;
-
- FDT_RW_CHECK_HEADER(fdt);
-
- re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
- err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
- if (err)
- return err;
-
- re->address = cpu_to_fdt64(address);
- re->size = cpu_to_fdt64(size);
- return 0;
-}
-
-int fdt_del_mem_rsv(void *fdt, int n)
-{
- struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
- int err;
-
- FDT_RW_CHECK_HEADER(fdt);
-
- if (n >= fdt_num_mem_rsv(fdt))
- return -FDT_ERR_NOTFOUND;
-
- err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
- if (err)
- return err;
- return 0;
-}
-
-static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
- int len, struct fdt_property **prop)
-{
- int oldlen;
- int err;
-
- *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
- if (! (*prop))
- return oldlen;
-
- if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
- FDT_TAGALIGN(len))))
- return err;
-
- (*prop)->len = cpu_to_fdt32(len);
- return 0;
-}
-
-static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
- int len, struct fdt_property **prop)
-{
- int proplen;
- int nextoffset;
- int namestroff;
- int err;
-
- if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
- return nextoffset;
-
- namestroff = _fdt_find_add_string(fdt, name);
- if (namestroff < 0)
- return namestroff;
-
- *prop = _fdt_offset_ptr_w(fdt, nextoffset);
- proplen = sizeof(**prop) + FDT_TAGALIGN(len);
-
- err = _fdt_splice_struct(fdt, *prop, 0, proplen);
- if (err)
- return err;
-
- (*prop)->tag = cpu_to_fdt32(FDT_PROP);
- (*prop)->nameoff = cpu_to_fdt32(namestroff);
- (*prop)->len = cpu_to_fdt32(len);
- return 0;
-}
-
-int fdt_set_name(void *fdt, int nodeoffset, const char *name)
-{
- char *namep;
- int oldlen, newlen;
- int err;
-
- FDT_RW_CHECK_HEADER(fdt);
-
- namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
- if (!namep)
- return oldlen;
-
- newlen = strlen(name);
-
- err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
- FDT_TAGALIGN(newlen+1));
- if (err)
- return err;
-
- memcpy(namep, name, newlen+1);
- return 0;
-}
-
-int fdt_setprop(void *fdt, int nodeoffset, const char *name,
- const void *val, int len)
-{
- struct fdt_property *prop;
- int err;
-
- FDT_RW_CHECK_HEADER(fdt);
-
- err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
- if (err == -FDT_ERR_NOTFOUND)
- err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
- if (err)
- return err;
-
- memcpy(prop->data, val, len);
- return 0;
-}
-
-int fdt_delprop(void *fdt, int nodeoffset, const char *name)
-{
- struct fdt_property *prop;
- int len, proplen;
-
- FDT_RW_CHECK_HEADER(fdt);
-
- prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
- if (! prop)
- return len;
-
- proplen = sizeof(*prop) + FDT_TAGALIGN(len);
- return _fdt_splice_struct(fdt, prop, proplen, 0);
-}
-
-int fdt_add_subnode_namelen(void *fdt, int parentoffset,
- const char *name, int namelen)
-{
- struct fdt_node_header *nh;
- int offset, nextoffset;
- int nodelen;
- int err;
- uint32_t tag;
- uint32_t *endtag;
-
- FDT_RW_CHECK_HEADER(fdt);
-
- offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
- if (offset >= 0)
- return -FDT_ERR_EXISTS;
- else if (offset != -FDT_ERR_NOTFOUND)
- return offset;
-
- /* Try to place the new node after the parent's properties */
- fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
- do {
- offset = nextoffset;
- tag = fdt_next_tag(fdt, offset, &nextoffset);
- } while ((tag == FDT_PROP) || (tag == FDT_NOP));
-
- nh = _fdt_offset_ptr_w(fdt, offset);
- nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
-
- err = _fdt_splice_struct(fdt, nh, 0, nodelen);
- if (err)
- return err;
-
- nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
- memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
- memcpy(nh->name, name, namelen);
- endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
- *endtag = cpu_to_fdt32(FDT_END_NODE);
-
- return offset;
-}
-
-int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
-{
- return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
-}
-
-int fdt_del_node(void *fdt, int nodeoffset)
-{
- int endoffset;
-
- FDT_RW_CHECK_HEADER(fdt);
-
- endoffset = _fdt_node_end_offset(fdt, nodeoffset);
- if (endoffset < 0)
- return endoffset;
-
- return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
- endoffset - nodeoffset, 0);
-}
-
-static void _fdt_packblocks(const char *old, char *new,
- int mem_rsv_size, int struct_size)
-{
- int mem_rsv_off, struct_off, strings_off;
-
- mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
- struct_off = mem_rsv_off + mem_rsv_size;
- strings_off = struct_off + struct_size;
-
- memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
- fdt_set_off_mem_rsvmap(new, mem_rsv_off);
-
- memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
- fdt_set_off_dt_struct(new, struct_off);
- fdt_set_size_dt_struct(new, struct_size);
-
- memmove(new + strings_off, old + fdt_off_dt_strings(old),
- fdt_size_dt_strings(old));
- fdt_set_off_dt_strings(new, strings_off);
- fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
-}
-
-int fdt_open_into(const void *fdt, void *buf, int bufsize)
-{
- int err;
- int mem_rsv_size, struct_size;
- int newsize;
- const char *fdtstart = fdt;
- const char *fdtend = fdtstart + fdt_totalsize(fdt);
- char *tmp;
-
- FDT_CHECK_HEADER(fdt);
-
- mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
- * sizeof(struct fdt_reserve_entry);
-
- if (fdt_version(fdt) >= 17) {
- struct_size = fdt_size_dt_struct(fdt);
- } else {
- struct_size = 0;
- while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
- ;
- }
-
- if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
- /* no further work necessary */
- err = fdt_move(fdt, buf, bufsize);
- if (err)
- return err;
- fdt_set_version(buf, 17);
- fdt_set_size_dt_struct(buf, struct_size);
- fdt_set_totalsize(buf, bufsize);
- return 0;
- }
-
- /* Need to reorder */
- newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
- + struct_size + fdt_size_dt_strings(fdt);
-
- if (bufsize < newsize)
- return -FDT_ERR_NOSPACE;
-
- /* First attempt to build converted tree at beginning of buffer */
- tmp = buf;
- /* But if that overlaps with the old tree... */
- if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
- /* Try right after the old tree instead */
- tmp = (char *)(uintptr_t)fdtend;
- if ((tmp + newsize) > ((char *)buf + bufsize))
- return -FDT_ERR_NOSPACE;
- }
-
- _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
- memmove(buf, tmp, newsize);
-
- fdt_set_magic(buf, FDT_MAGIC);
- fdt_set_totalsize(buf, bufsize);
- fdt_set_version(buf, 17);
- fdt_set_last_comp_version(buf, 16);
- fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
-
- return 0;
-}
-
-int fdt_pack(void *fdt)
-{
- int mem_rsv_size;
-
- FDT_RW_CHECK_HEADER(fdt);
-
- mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
- * sizeof(struct fdt_reserve_entry);
- _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
- fdt_set_totalsize(fdt, _fdt_data_size(fdt));
-
- return 0;
-}
+++ /dev/null
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library 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 library 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 library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "libfdt_env.h"
-
-#include <fdt.h>
-#include <libfdt.h>
-
-#include "libfdt_internal.h"
-
-struct fdt_errtabent {
- const char *str;
-};
-
-#define FDT_ERRTABENT(val) \
- [(val)] = { .str = #val, }
-
-static struct fdt_errtabent fdt_errtable[] = {
- FDT_ERRTABENT(FDT_ERR_NOTFOUND),
- FDT_ERRTABENT(FDT_ERR_EXISTS),
- FDT_ERRTABENT(FDT_ERR_NOSPACE),
-
- FDT_ERRTABENT(FDT_ERR_BADOFFSET),
- FDT_ERRTABENT(FDT_ERR_BADPATH),
- FDT_ERRTABENT(FDT_ERR_BADSTATE),
-
- FDT_ERRTABENT(FDT_ERR_TRUNCATED),
- FDT_ERRTABENT(FDT_ERR_BADMAGIC),
- FDT_ERRTABENT(FDT_ERR_BADVERSION),
- FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
- FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
-};
-#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
-
-const char *fdt_strerror(int errval)
-{
- if (errval > 0)
- return "<valid offset/length>";
- else if (errval == 0)
- return "<no error>";
- else if (errval > -FDT_ERRTABSIZE) {
- const char *s = fdt_errtable[-errval].str;
-
- if (s)
- return s;
- }
-
- return "<unknown error>";
-}
+++ /dev/null
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library 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 library 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 library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "libfdt_env.h"
-
-#include <fdt.h>
-#include <libfdt.h>
-
-#include "libfdt_internal.h"
-
-static int _fdt_sw_check_header(void *fdt)
-{
- if (fdt_magic(fdt) != FDT_SW_MAGIC)
- return -FDT_ERR_BADMAGIC;
- /* FIXME: should check more details about the header state */
- return 0;
-}
-
-#define FDT_SW_CHECK_HEADER(fdt) \
- { \
- int err; \
- if ((err = _fdt_sw_check_header(fdt)) != 0) \
- return err; \
- }
-
-static void *_fdt_grab_space(void *fdt, int len)
-{
- int offset = fdt_size_dt_struct(fdt);
- int spaceleft;
-
- spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
- - fdt_size_dt_strings(fdt);
-
- if ((offset + len < offset) || (offset + len > spaceleft))
- return NULL;
-
- fdt_set_size_dt_struct(fdt, offset + len);
- return fdt_offset_ptr_w(fdt, offset, len);
-}
-
-int fdt_create(void *buf, int bufsize)
-{
- void *fdt = buf;
-
- if (bufsize < sizeof(struct fdt_header))
- return -FDT_ERR_NOSPACE;
-
- memset(buf, 0, bufsize);
-
- fdt_set_magic(fdt, FDT_SW_MAGIC);
- fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
- fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
- fdt_set_totalsize(fdt, bufsize);
-
- fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
- sizeof(struct fdt_reserve_entry)));
- fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
- fdt_set_off_dt_strings(fdt, bufsize);
-
- return 0;
-}
-
-int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
-{
- struct fdt_reserve_entry *re;
- int offset;
-
- FDT_SW_CHECK_HEADER(fdt);
-
- if (fdt_size_dt_struct(fdt))
- return -FDT_ERR_BADSTATE;
-
- offset = fdt_off_dt_struct(fdt);
- if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
- return -FDT_ERR_NOSPACE;
-
- re = (struct fdt_reserve_entry *)((char *)fdt + offset);
- re->address = cpu_to_fdt64(addr);
- re->size = cpu_to_fdt64(size);
-
- fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
-
- return 0;
-}
-
-int fdt_finish_reservemap(void *fdt)
-{
- return fdt_add_reservemap_entry(fdt, 0, 0);
-}
-
-int fdt_begin_node(void *fdt, const char *name)
-{
- struct fdt_node_header *nh;
- int namelen = strlen(name) + 1;
-
- FDT_SW_CHECK_HEADER(fdt);
-
- nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
- if (! nh)
- return -FDT_ERR_NOSPACE;
-
- nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
- memcpy(nh->name, name, namelen);
- return 0;
-}
-
-int fdt_end_node(void *fdt)
-{
- uint32_t *en;
-
- FDT_SW_CHECK_HEADER(fdt);
-
- en = _fdt_grab_space(fdt, FDT_TAGSIZE);
- if (! en)
- return -FDT_ERR_NOSPACE;
-
- *en = cpu_to_fdt32(FDT_END_NODE);
- return 0;
-}
-
-static int _fdt_find_add_string(void *fdt, const char *s)
-{
- char *strtab = (char *)fdt + fdt_totalsize(fdt);
- const char *p;
- int strtabsize = fdt_size_dt_strings(fdt);
- int len = strlen(s) + 1;
- int struct_top, offset;
-
- p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
- if (p)
- return p - strtab;
-
- /* Add it */
- offset = -strtabsize - len;
- struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
- if (fdt_totalsize(fdt) + offset < struct_top)
- return 0; /* no more room :( */
-
- memcpy(strtab + offset, s, len);
- fdt_set_size_dt_strings(fdt, strtabsize + len);
- return offset;
-}
-
-int fdt_property(void *fdt, const char *name, const void *val, int len)
-{
- struct fdt_property *prop;
- int nameoff;
-
- FDT_SW_CHECK_HEADER(fdt);
-
- nameoff = _fdt_find_add_string(fdt, name);
- if (nameoff == 0)
- return -FDT_ERR_NOSPACE;
-
- prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
- if (! prop)
- return -FDT_ERR_NOSPACE;
-
- prop->tag = cpu_to_fdt32(FDT_PROP);
- prop->nameoff = cpu_to_fdt32(nameoff);
- prop->len = cpu_to_fdt32(len);
- memcpy(prop->data, val, len);
- return 0;
-}
-
-int fdt_finish(void *fdt)
-{
- char *p = (char *)fdt;
- uint32_t *end;
- int oldstroffset, newstroffset;
- uint32_t tag;
- int offset, nextoffset;
-
- FDT_SW_CHECK_HEADER(fdt);
-
- /* Add terminator */
- end = _fdt_grab_space(fdt, sizeof(*end));
- if (! end)
- return -FDT_ERR_NOSPACE;
- *end = cpu_to_fdt32(FDT_END);
-
- /* Relocate the string table */
- oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
- newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
- memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
- fdt_set_off_dt_strings(fdt, newstroffset);
-
- /* Walk the structure, correcting string offsets */
- offset = 0;
- while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
- if (tag == FDT_PROP) {
- struct fdt_property *prop =
- fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
- int nameoff;
-
- if (! prop)
- return -FDT_ERR_BADSTRUCTURE;
-
- nameoff = fdt32_to_cpu(prop->nameoff);
- nameoff += fdt_size_dt_strings(fdt);
- prop->nameoff = cpu_to_fdt32(nameoff);
- }
- offset = nextoffset;
- }
-
- /* Finally, adjust the header */
- fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
- fdt_set_magic(fdt, FDT_MAGIC);
- return 0;
-}
+++ /dev/null
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library 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 library 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 library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "libfdt_env.h"
-
-#include <fdt.h>
-#include <libfdt.h>
-
-#include "libfdt_internal.h"
-
-int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
- const void *val, int len)
-{
- void *propval;
- int proplen;
-
- propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
- if (! propval)
- return proplen;
-
- if (proplen != len)
- return -FDT_ERR_NOSPACE;
-
- memcpy(propval, val, len);
- return 0;
-}
-
-static void _fdt_nop_region(void *start, int len)
-{
- uint32_t *p;
-
- for (p = start; (char *)p < ((char *)start + len); p++)
- *p = cpu_to_fdt32(FDT_NOP);
-}
-
-int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
-{
- struct fdt_property *prop;
- int len;
-
- prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
- if (! prop)
- return len;
-
- _fdt_nop_region(prop, len + sizeof(*prop));
-
- return 0;
-}
-
-int _fdt_node_end_offset(void *fdt, int nodeoffset)
-{
- int level = 0;
- uint32_t tag;
- int offset, nextoffset;
-
- tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
- if (tag != FDT_BEGIN_NODE)
- return -FDT_ERR_BADOFFSET;
- do {
- offset = nextoffset;
- tag = fdt_next_tag(fdt, offset, &nextoffset);
-
- switch (tag) {
- case FDT_END:
- return offset;
-
- case FDT_BEGIN_NODE:
- level++;
- break;
-
- case FDT_END_NODE:
- level--;
- break;
-
- case FDT_PROP:
- case FDT_NOP:
- break;
-
- default:
- return -FDT_ERR_BADSTRUCTURE;
- }
- } while (level >= 0);
-
- return nextoffset;
-}
-
-int fdt_nop_node(void *fdt, int nodeoffset)
-{
- int endoffset;
-
- endoffset = _fdt_node_end_offset(fdt, nodeoffset);
- if (endoffset < 0)
- return endoffset;
-
- _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
- endoffset - nodeoffset);
- return 0;
-}
+++ /dev/null
-#ifndef _LIBFDT_H
-#define _LIBFDT_H
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library 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 library 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 library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <libfdt_env.h>
-#include <fdt.h>
-
-#define FDT_FIRST_SUPPORTED_VERSION 0x10
-#define FDT_LAST_SUPPORTED_VERSION 0x11
-
-/* Error codes: informative error codes */
-#define FDT_ERR_NOTFOUND 1
- /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
-#define FDT_ERR_EXISTS 2
- /* FDT_ERR_EXISTS: Attemped to create a node or property which
- * already exists */
-#define FDT_ERR_NOSPACE 3
- /* FDT_ERR_NOSPACE: Operation needed to expand the device
- * tree, but its buffer did not have sufficient space to
- * contain the expanded tree. Use fdt_open_into() to move the
- * device tree to a buffer with more space. */
-
-/* Error codes: codes for bad parameters */
-#define FDT_ERR_BADOFFSET 4
- /* FDT_ERR_BADOFFSET: Function was passed a structure block
- * offset which is out-of-bounds, or which points to an
- * unsuitable part of the structure for the operation. */
-#define FDT_ERR_BADPATH 5
- /* FDT_ERR_BADPATH: Function was passed a badly formatted path
- * (e.g. missing a leading / for a function which requires an
- * absolute path) */
-#define FDT_ERR_BADPHANDLE 6
- /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
- * value. phandle values of 0 and -1 are not permitted. */
-#define FDT_ERR_BADSTATE 7
- /* FDT_ERR_BADSTATE: Function was passed an incomplete device
- * tree created by the sequential-write functions, which is
- * not sufficiently complete for the requested operation. */
-
-/* Error codes: codes for bad device tree blobs */
-#define FDT_ERR_TRUNCATED 8
- /* FDT_ERR_TRUNCATED: Structure block of the given device tree
- * ends without an FDT_END tag. */
-#define FDT_ERR_BADMAGIC 9
- /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
- * device tree at all - it is missing the flattened device
- * tree magic number. */
-#define FDT_ERR_BADVERSION 10
- /* FDT_ERR_BADVERSION: Given device tree has a version which
- * can't be handled by the requested operation. For
- * read-write functions, this may mean that fdt_open_into() is
- * required to convert the tree to the expected version. */
-#define FDT_ERR_BADSTRUCTURE 11
- /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
- * structure block or other serious error (e.g. misnested
- * nodes, or subnodes preceding properties). */
-#define FDT_ERR_BADLAYOUT 12
- /* FDT_ERR_BADLAYOUT: For read-write functions, the given
- * device tree has it's sub-blocks in an order that the
- * function can't handle (memory reserve map, then structure,
- * then strings). Use fdt_open_into() to reorganize the tree
- * into a form suitable for the read-write operations. */
-
-/* "Can't happen" error indicating a bug in libfdt */
-#define FDT_ERR_INTERNAL 13
- /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
- * Should never be returned, if it is, it indicates a bug in
- * libfdt itself. */
-
-#define FDT_ERR_MAX 13
-
-/**********************************************************************/
-/* Low-level functions (you probably don't need these) */
-/**********************************************************************/
-
-const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
-static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
-{
- return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
-}
-
-uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
-
-/**********************************************************************/
-/* Traversal functions */
-/**********************************************************************/
-
-int fdt_next_node(const void *fdt, int offset, int *depth);
-
-/**********************************************************************/
-/* General functions */
-/**********************************************************************/
-
-#define fdt_get_header(fdt, field) \
- (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
-#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
-#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
-#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
-#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
-#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
-#define fdt_version(fdt) (fdt_get_header(fdt, version))
-#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
-#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
-#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
-#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
-
-#define __fdt_set_hdr(name) \
- static inline void fdt_set_##name(void *fdt, uint32_t val) \
- { \
- struct fdt_header *fdth = fdt; \
- fdth->name = cpu_to_fdt32(val); \
- }
-__fdt_set_hdr(magic);
-__fdt_set_hdr(totalsize);
-__fdt_set_hdr(off_dt_struct);
-__fdt_set_hdr(off_dt_strings);
-__fdt_set_hdr(off_mem_rsvmap);
-__fdt_set_hdr(version);
-__fdt_set_hdr(last_comp_version);
-__fdt_set_hdr(boot_cpuid_phys);
-__fdt_set_hdr(size_dt_strings);
-__fdt_set_hdr(size_dt_struct);
-#undef __fdt_set_hdr
-
-/**
- * fdt_check_header - sanity check a device tree or possible device tree
- * @fdt: pointer to data which might be a flattened device tree
- *
- * fdt_check_header() checks that the given buffer contains what
- * appears to be a flattened device tree with sane information in its
- * header.
- *
- * returns:
- * 0, if the buffer appears to contain a valid device tree
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE, standard meanings, as above
- */
-int fdt_check_header(const void *fdt);
-
-/**
- * fdt_move - move a device tree around in memory
- * @fdt: pointer to the device tree to move
- * @buf: pointer to memory where the device is to be moved
- * @bufsize: size of the memory space at buf
- *
- * fdt_move() relocates, if possible, the device tree blob located at
- * fdt to the buffer at buf of size bufsize. The buffer may overlap
- * with the existing device tree blob at fdt. Therefore,
- * fdt_move(fdt, fdt, fdt_totalsize(fdt))
- * should always succeed.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE, standard meanings
- */
-int fdt_move(const void *fdt, void *buf, int bufsize);
-
-/**********************************************************************/
-/* Read-only functions */
-/**********************************************************************/
-
-/**
- * fdt_string - retrieve a string from the strings block of a device tree
- * @fdt: pointer to the device tree blob
- * @stroffset: offset of the string within the strings block (native endian)
- *
- * fdt_string() retrieves a pointer to a single string from the
- * strings block of the device tree blob at fdt.
- *
- * returns:
- * a pointer to the string, on success
- * NULL, if stroffset is out of bounds
- */
-const char *fdt_string(const void *fdt, int stroffset);
-
-/**
- * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
- * @fdt: pointer to the device tree blob
- *
- * Returns the number of entries in the device tree blob's memory
- * reservation map. This does not include the terminating 0,0 entry
- * or any other (0,0) entries reserved for expansion.
- *
- * returns:
- * the number of entries
- */
-int fdt_num_mem_rsv(const void *fdt);
-
-/**
- * fdt_get_mem_rsv - retrieve one memory reserve map entry
- * @fdt: pointer to the device tree blob
- * @address, @size: pointers to 64-bit variables
- *
- * On success, *address and *size will contain the address and size of
- * the n-th reserve map entry from the device tree blob, in
- * native-endian format.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE, standard meanings
- */
-int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
-
-/**
- * fdt_subnode_offset_namelen - find a subnode based on substring
- * @fdt: pointer to the device tree blob
- * @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
- * @namelen: number of characters of name to consider
- *
- * Identical to fdt_subnode_offset(), but only examine the first
- * namelen characters of name for matching the subnode name. This is
- * useful for finding subnodes based on a portion of a larger string,
- * such as a full path.
- */
-int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
- const char *name, int namelen);
-/**
- * fdt_subnode_offset - find a subnode of a given node
- * @fdt: pointer to the device tree blob
- * @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
- *
- * fdt_subnode_offset() finds a subnode of the node at structure block
- * offset parentoffset with the given name. name may include a unit
- * address, in which case fdt_subnode_offset() will find the subnode
- * with that unit address, or the unit address may be omitted, in
- * which case fdt_subnode_offset() will find an arbitrary subnode
- * whose name excluding unit address matches the given name.
- *
- * returns:
- * structure block offset of the requested subnode (>=0), on success
- * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
- * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings.
- */
-int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
-
-/**
- * fdt_path_offset - find a tree node by its full path
- * @fdt: pointer to the device tree blob
- * @path: full path of the node to locate
- *
- * fdt_path_offset() finds a node of a given path in the device tree.
- * Each path component may omit the unit address portion, but the
- * results of this are undefined if any such path component is
- * ambiguous (that is if there are multiple nodes at the relevant
- * level matching the given component, differentiated only by unit
- * address).
- *
- * returns:
- * structure block offset of the node with the requested path (>=0), on success
- * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
- * -FDT_ERR_NOTFOUND, if the requested node does not exist
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings.
- */
-int fdt_path_offset(const void *fdt, const char *path);
-
-/**
- * fdt_get_name - retrieve the name of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: structure block offset of the starting node
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_get_name() retrieves the name (including unit address) of the
- * device tree node at structure block offset nodeoffset. If lenp is
- * non-NULL, the length of this name is also returned, in the integer
- * pointed to by lenp.
- *
- * returns:
- * pointer to the node's name, on success
- * If lenp is non-NULL, *lenp contains the length of that name (>=0)
- * NULL, on error
- * if lenp is non-NULL *lenp contains an error code (<0):
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE, standard meanings
- */
-const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
-
-/**
- * fdt_get_property - find a given property in a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to find
- * @name: name of the property to find
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_get_property() retrieves a pointer to the fdt_property
- * structure within the device tree blob corresponding to the property
- * named 'name' of the node at offset nodeoffset. If lenp is
- * non-NULL, the length of the property value is also returned, in the
- * integer pointed to by lenp.
- *
- * returns:
- * pointer to the structure representing the property
- * if lenp is non-NULL, *lenp contains the length of the property
- * value (>=0)
- * NULL, on error
- * if lenp is non-NULL, *lenp contains an error code (<0):
- * -FDT_ERR_NOTFOUND, node does not have named property
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
- const char *name, int *lenp);
-static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
- const char *name,
- int *lenp)
-{
- return (struct fdt_property *)(uintptr_t)
- fdt_get_property(fdt, nodeoffset, name, lenp);
-}
-
-/**
- * fdt_getprop - retrieve the value of a given property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to find
- * @name: name of the property to find
- * @lenp: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_getprop() retrieves a pointer to the value of the property
- * named 'name' of the node at offset nodeoffset (this will be a
- * pointer to within the device blob itself, not a copy of the value).
- * If lenp is non-NULL, the length of the property value is also
- * returned, in the integer pointed to by lenp.
- *
- * returns:
- * pointer to the property's value
- * if lenp is non-NULL, *lenp contains the length of the property
- * value (>=0)
- * NULL, on error
- * if lenp is non-NULL, *lenp contains an error code (<0):
- * -FDT_ERR_NOTFOUND, node does not have named property
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-const void *fdt_getprop(const void *fdt, int nodeoffset,
- const char *name, int *lenp);
-static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
- const char *name, int *lenp)
-{
- return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
-}
-
-/**
- * fdt_get_phandle - retrieve the phandle of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: structure block offset of the node
- *
- * fdt_get_phandle() retrieves the phandle of the device tree node at
- * structure block offset nodeoffset.
- *
- * returns:
- * the phandle of the node at nodeoffset, on success (!= 0, != -1)
- * 0, if the node has no phandle, or another error occurs
- */
-uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
-
-/**
- * fdt_get_path - determine the full path of a node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose path to find
- * @buf: character buffer to contain the returned path (will be overwritten)
- * @buflen: size of the character buffer at buf
- *
- * fdt_get_path() computes the full path of the node at offset
- * nodeoffset, and records that path in the buffer at buf.
- *
- * NOTE: This function is expensive, as it must scan the device tree
- * structure from the start to nodeoffset.
- *
- * returns:
- * 0, on success
- * buf contains the absolute path of the node at
- * nodeoffset, as a NUL-terminated string.
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
- * characters and will not fit in the given buffer.
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
-
-/**
- * fdt_supernode_atdepth_offset - find a specific ancestor of a node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose parent to find
- * @supernodedepth: depth of the ancestor to find
- * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
- *
- * fdt_supernode_atdepth_offset() finds an ancestor of the given node
- * at a specific depth from the root (where the root itself has depth
- * 0, its immediate subnodes depth 1 and so forth). So
- * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
- * will always return 0, the offset of the root node. If the node at
- * nodeoffset has depth D, then:
- * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
- * will return nodeoffset itself.
- *
- * NOTE: This function is expensive, as it must scan the device tree
- * structure from the start to nodeoffset.
- *
- * returns:
-
- * structure block offset of the node at node offset's ancestor
- * of depth supernodedepth (>=0), on success
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
-* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
- int supernodedepth, int *nodedepth);
-
-/**
- * fdt_node_depth - find the depth of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose parent to find
- *
- * fdt_node_depth() finds the depth of a given node. The root node
- * has depth 0, its immediate subnodes depth 1 and so forth.
- *
- * NOTE: This function is expensive, as it must scan the device tree
- * structure from the start to nodeoffset.
- *
- * returns:
- * depth of the node at nodeoffset (>=0), on success
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_depth(const void *fdt, int nodeoffset);
-
-/**
- * fdt_parent_offset - find the parent of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose parent to find
- *
- * fdt_parent_offset() locates the parent node of a given node (that
- * is, it finds the offset of the node which contains the node at
- * nodeoffset as a subnode).
- *
- * NOTE: This function is expensive, as it must scan the device tree
- * structure from the start to nodeoffset, *twice*.
- *
- * returns:
- * structure block offset of the parent of the node at nodeoffset
- * (>=0), on success
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_parent_offset(const void *fdt, int nodeoffset);
-
-/**
- * fdt_node_offset_by_prop_value - find nodes with a given property value
- * @fdt: pointer to the device tree blob
- * @startoffset: only find nodes after this offset
- * @propname: property name to check
- * @propval: property value to search for
- * @proplen: length of the value in propval
- *
- * fdt_node_offset_by_prop_value() returns the offset of the first
- * node after startoffset, which has a property named propname whose
- * value is of length proplen and has value equal to propval; or if
- * startoffset is -1, the very first such node in the tree.
- *
- * To iterate through all nodes matching the criterion, the following
- * idiom can be used:
- * offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
- * propval, proplen);
- * while (offset != -FDT_ERR_NOTFOUND) {
- * // other code here
- * offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
- * propval, proplen);
- * }
- *
- * Note the -1 in the first call to the function, if 0 is used here
- * instead, the function will never locate the root node, even if it
- * matches the criterion.
- *
- * returns:
- * structure block offset of the located node (>= 0, >startoffset),
- * on success
- * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
- * tree after startoffset
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
- const char *propname,
- const void *propval, int proplen);
-
-/**
- * fdt_node_offset_by_phandle - find the node with a given phandle
- * @fdt: pointer to the device tree blob
- * @phandle: phandle value
- *
- * fdt_node_offset_by_phandle() returns the offset of the node
- * which has the given phandle value. If there is more than one node
- * in the tree with the given phandle (an invalid tree), results are
- * undefined.
- *
- * returns:
- * structure block offset of the located node (>= 0), on success
- * -FDT_ERR_NOTFOUND, no node with that phandle exists
- * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
-
-/**
- * fdt_node_check_compatible: check a node's compatible property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of a tree node
- * @compatible: string to match against
- *
- *
- * fdt_node_check_compatible() returns 0 if the given node contains a
- * 'compatible' property with the given string as one of its elements,
- * it returns non-zero otherwise, or on error.
- *
- * returns:
- * 0, if the node has a 'compatible' property listing the given string
- * 1, if the node has a 'compatible' property, but it does not list
- * the given string
- * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
- * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_check_compatible(const void *fdt, int nodeoffset,
- const char *compatible);
-
-/**
- * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
- * @fdt: pointer to the device tree blob
- * @startoffset: only find nodes after this offset
- * @compatible: 'compatible' string to match against
- *
- * fdt_node_offset_by_compatible() returns the offset of the first
- * node after startoffset, which has a 'compatible' property which
- * lists the given compatible string; or if startoffset is -1, the
- * very first such node in the tree.
- *
- * To iterate through all nodes matching the criterion, the following
- * idiom can be used:
- * offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
- * while (offset != -FDT_ERR_NOTFOUND) {
- * // other code here
- * offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
- * }
- *
- * Note the -1 in the first call to the function, if 0 is used here
- * instead, the function will never locate the root node, even if it
- * matches the criterion.
- *
- * returns:
- * structure block offset of the located node (>= 0, >startoffset),
- * on success
- * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
- * tree after startoffset
- * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE, standard meanings
- */
-int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
- const char *compatible);
-
-/**********************************************************************/
-/* Write-in-place functions */
-/**********************************************************************/
-
-/**
- * fdt_setprop_inplace - change a property's value, but not its size
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: pointer to data to replace the property value with
- * @len: length of the property value
- *
- * fdt_setprop_inplace() replaces the value of a given property with
- * the data in val, of length len. This function cannot change the
- * size of a property, and so will only work if len is equal to the
- * current length of the property.
- *
- * This function will alter only the bytes in the blob which contain
- * the given property value, and will not alter or move any other part
- * of the tree.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOSPACE, if len is not equal to the property's current length
- * -FDT_ERR_NOTFOUND, node does not have the named property
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
- const void *val, int len);
-
-/**
- * fdt_setprop_inplace_cell - change the value of a single-cell property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: cell (32-bit integer) value to replace the property with
- *
- * fdt_setprop_inplace_cell() replaces the value of a given property
- * with the 32-bit integer cell value in val, converting val to
- * big-endian if necessary. This function cannot change the size of a
- * property, and so will only work if the property already exists and
- * has length 4.
- *
- * This function will alter only the bytes in the blob which contain
- * the given property value, and will not alter or move any other part
- * of the tree.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOSPACE, if the property's length is not equal to 4
- * -FDT_ERR_NOTFOUND, node does not have the named property
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
- const char *name, uint32_t val)
-{
- val = cpu_to_fdt32(val);
- return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
-}
-
-/**
- * fdt_nop_property - replace a property with nop tags
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to nop
- * @name: name of the property to nop
- *
- * fdt_nop_property() will replace a given property's representation
- * in the blob with FDT_NOP tags, effectively removing it from the
- * tree.
- *
- * This function will alter only the bytes in the blob which contain
- * the property, and will not alter or move any other part of the
- * tree.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOTFOUND, node does not have the named property
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
-
-/**
- * fdt_nop_node - replace a node (subtree) with nop tags
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node to nop
- *
- * fdt_nop_node() will replace a given node's representation in the
- * blob, including all its subnodes, if any, with FDT_NOP tags,
- * effectively removing it from the tree.
- *
- * This function will alter only the bytes in the blob which contain
- * the node and its properties and subnodes, and will not alter or
- * move any other part of the tree.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_nop_node(void *fdt, int nodeoffset);
-
-/**********************************************************************/
-/* Sequential write functions */
-/**********************************************************************/
-
-int fdt_create(void *buf, int bufsize);
-int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
-int fdt_finish_reservemap(void *fdt);
-int fdt_begin_node(void *fdt, const char *name);
-int fdt_property(void *fdt, const char *name, const void *val, int len);
-static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
-{
- val = cpu_to_fdt32(val);
- return fdt_property(fdt, name, &val, sizeof(val));
-}
-#define fdt_property_string(fdt, name, str) \
- fdt_property(fdt, name, str, strlen(str)+1)
-int fdt_end_node(void *fdt);
-int fdt_finish(void *fdt);
-
-/**********************************************************************/
-/* Read-write functions */
-/**********************************************************************/
-
-int fdt_open_into(const void *fdt, void *buf, int bufsize);
-int fdt_pack(void *fdt);
-
-/**
- * fdt_add_mem_rsv - add one memory reserve map entry
- * @fdt: pointer to the device tree blob
- * @address, @size: 64-bit values (native endian)
- *
- * Adds a reserve map entry to the given blob reserving a region at
- * address address of length size.
- *
- * This function will insert data into the reserve map and will
- * therefore change the indexes of some entries in the table.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- * contain the new reservation entry
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
-
-/**
- * fdt_del_mem_rsv - remove a memory reserve map entry
- * @fdt: pointer to the device tree blob
- * @n: entry to remove
- *
- * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
- * the blob.
- *
- * This function will delete data from the reservation table and will
- * therefore change the indexes of some entries in the table.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
- * are less than n+1 reserve map entries)
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_del_mem_rsv(void *fdt, int n);
-
-/**
- * fdt_set_name - change the name of a given node
- * @fdt: pointer to the device tree blob
- * @nodeoffset: structure block offset of a node
- * @name: name to give the node
- *
- * fdt_set_name() replaces the name (including unit address, if any)
- * of the given node with the given string. NOTE: this function can't
- * efficiently check if the new name is unique amongst the given
- * node's siblings; results are undefined if this function is invoked
- * with a name equal to one of the given node's siblings.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOSPACE, there is insufficient free space in the blob
- * to contain the new name
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE, standard meanings
- */
-int fdt_set_name(void *fdt, int nodeoffset, const char *name);
-
-/**
- * fdt_setprop - create or change a property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: pointer to data to set the property value to
- * @len: length of the property value
- *
- * fdt_setprop() sets the value of the named property in the given
- * node to the given value and length, creating the property if it
- * does not already exist.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- * contain the new property value
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_setprop(void *fdt, int nodeoffset, const char *name,
- const void *val, int len);
-
-/**
- * fdt_setprop_cell - set a property to a single cell value
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @val: 32-bit integer value for the property (native endian)
- *
- * fdt_setprop_cell() sets the value of the named property in the
- * given node to the given cell value (converting to big-endian if
- * necessary), or creates a new property with that value if it does
- * not already exist.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- * contain the new property value
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
- uint32_t val)
-{
- val = cpu_to_fdt32(val);
- return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
-}
-
-/**
- * fdt_setprop_string - set a property to a string value
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to change
- * @name: name of the property to change
- * @str: string value for the property
- *
- * fdt_setprop_string() sets the value of the named property in the
- * given node to the given string value (using the length of the
- * string to determine the new length of the property), or creates a
- * new property with that value if it does not already exist.
- *
- * This function may insert or delete data from the blob, and will
- * therefore change the offsets of some existing nodes.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
- * contain the new property value
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-#define fdt_setprop_string(fdt, nodeoffset, name, str) \
- fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
-
-/**
- * fdt_delprop - delete a property
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node whose property to nop
- * @name: name of the property to nop
- *
- * fdt_del_property() will delete the given property.
- *
- * This function will delete data from the blob, and will therefore
- * change the offsets of some existing nodes.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_NOTFOUND, node does not have the named property
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_delprop(void *fdt, int nodeoffset, const char *name);
-
-/**
- * fdt_add_subnode_namelen - creates a new node based on substring
- * @fdt: pointer to the device tree blob
- * @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
- * @namelen: number of characters of name to consider
- *
- * Identical to fdt_add_subnode(), but use only the first namelen
- * characters of name as the name of the new node. This is useful for
- * creating subnodes based on a portion of a larger string, such as a
- * full path.
- */
-int fdt_add_subnode_namelen(void *fdt, int parentoffset,
- const char *name, int namelen);
-
-/**
- * fdt_add_subnode - creates a new node
- * @fdt: pointer to the device tree blob
- * @parentoffset: structure block offset of a node
- * @name: name of the subnode to locate
- *
- * fdt_add_subnode() creates a new node as a subnode of the node at
- * structure block offset parentoffset, with the given name (which
- * should include the unit address, if any).
- *
- * This function will insert data into the blob, and will therefore
- * change the offsets of some existing nodes.
-
- * returns:
- * structure block offset of the created nodeequested subnode (>=0), on success
- * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
- * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
- * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
- * the given name
- * -FDT_ERR_NOSPACE, if there is insufficient free space in the
- * blob to contain the new node
- * -FDT_ERR_NOSPACE
- * -FDT_ERR_BADLAYOUT
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings.
- */
-int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
-
-/**
- * fdt_del_node - delete a node (subtree)
- * @fdt: pointer to the device tree blob
- * @nodeoffset: offset of the node to nop
- *
- * fdt_del_node() will remove the given node, including all its
- * subnodes if any, from the blob.
- *
- * This function will delete data from the blob, and will therefore
- * change the offsets of some existing nodes.
- *
- * returns:
- * 0, on success
- * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
- * -FDT_ERR_BADLAYOUT,
- * -FDT_ERR_BADMAGIC,
- * -FDT_ERR_BADVERSION,
- * -FDT_ERR_BADSTATE,
- * -FDT_ERR_BADSTRUCTURE,
- * -FDT_ERR_TRUNCATED, standard meanings
- */
-int fdt_del_node(void *fdt, int nodeoffset);
-
-/**********************************************************************/
-/* Debugging / informational functions */
-/**********************************************************************/
-
-const char *fdt_strerror(int errval);
-
-#endif /* _LIBFDT_H */
+++ /dev/null
-#ifndef _LIBFDT_INTERNAL_H
-#define _LIBFDT_INTERNAL_H
-/*
- * libfdt - Flat Device Tree manipulation
- * Copyright (C) 2006 David Gibson, IBM Corporation.
- *
- * libfdt is dual licensed: you can use it either under the terms of
- * the GPL, or the BSD license, at your option.
- *
- * a) This library 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 library 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 library; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
- * MA 02110-1301 USA
- *
- * Alternatively,
- *
- * b) Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the following
- * disclaimer.
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
- * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
- * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <fdt.h>
-
-#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
-#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
-
-#define FDT_CHECK_HEADER(fdt) \
- { \
- int err; \
- if ((err = fdt_check_header(fdt)) != 0) \
- return err; \
- }
-
-uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
-int _fdt_check_node_offset(const void *fdt, int offset);
-const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
-int _fdt_node_end_offset(void *fdt, int nodeoffset);
-
-static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
-{
- return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
-}
-
-static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
-{
- return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
-}
-
-static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
-{
- const struct fdt_reserve_entry *rsv_table =
- (const struct fdt_reserve_entry *)
- ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
-
- return rsv_table + n;
-}
-static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
-{
- return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
-}
-
-#define FDT_SW_MAGIC (~FDT_MAGIC)
-
-#endif /* _LIBFDT_INTERNAL_H */
#include "types.h"
#include "io.h"
#include "stdio.h"
-#include "libfdt/libfdt.h"
+#include <libfdt.h>
BSS_STACK(4*1024);
*
*/
-/* Platform drivers register/unregister */
-static inline int of_register_platform_driver(struct of_platform_driver *drv)
-{
- return of_register_driver(drv, &of_platform_bus_type);
-}
-static inline void of_unregister_platform_driver(struct of_platform_driver *drv)
-{
- of_unregister_driver(drv);
-}
-
/* Platform devices and busses creation */
extern struct of_device *of_platform_device_create(struct device_node *np,
const char *bus_id,
.icache_bsize = 128,
.dcache_bsize = 128,
.machine_check = machine_check_generic,
- .oprofile_cpu_type = "ppc64/compat-power5+",
+ .oprofile_cpu_type = "ppc64/ibm-compat-v1",
+ .oprofile_type = PPC_OPROFILE_POWER4,
.platform = "power5+",
},
{ /* Power6 */
.icache_bsize = 128,
.dcache_bsize = 128,
.machine_check = machine_check_generic,
- .oprofile_cpu_type = "ppc64/compat-power6",
+ .oprofile_cpu_type = "ppc64/ibm-compat-v1",
+ .oprofile_type = PPC_OPROFILE_POWER4,
.platform = "power6",
},
{ /* 2.06-compliant processor, i.e. Power7 "architected" mode */
.icache_bsize = 128,
.dcache_bsize = 128,
.machine_check = machine_check_generic,
- .oprofile_cpu_type = "ppc64/compat-power7",
+ .oprofile_type = PPC_OPROFILE_POWER4,
+ .oprofile_cpu_type = "ppc64/ibm-compat-v1",
.platform = "power7",
},
{ /* Power7 */
* and, in that case, keep the current value for
* oprofile_cpu_type.
*/
- if (old.oprofile_cpu_type == NULL)
- t->oprofile_cpu_type = s->oprofile_cpu_type;
+ if (old.oprofile_cpu_type == NULL) {
+ t->oprofile_cpu_type = old.oprofile_cpu_type;
+ t->oprofile_type = old.oprofile_type;
+ }
}
*PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
enum mcp_flags {
MCP_TIMESTAMP = (1 << 0), /* log time stamp */
MCP_UC = (1 << 1), /* log uncorrected errors */
+ MCP_DONTLOG = (1 << 2), /* only clear, don't log */
};
extern void machine_check_poll(enum mcp_flags flags, mce_banks_t *b);
#define IVHD_DEV_EXT_SELECT 0x46
#define IVHD_DEV_EXT_SELECT_RANGE 0x47
-#define IVHD_FLAG_HT_TUN_EN 0x00
-#define IVHD_FLAG_PASSPW_EN 0x01
-#define IVHD_FLAG_RESPASSPW_EN 0x02
-#define IVHD_FLAG_ISOC_EN 0x03
+#define IVHD_FLAG_HT_TUN_EN_MASK 0x01
+#define IVHD_FLAG_PASSPW_EN_MASK 0x02
+#define IVHD_FLAG_RESPASSPW_EN_MASK 0x04
+#define IVHD_FLAG_ISOC_EN_MASK 0x08
#define IVMD_FLAG_EXCL_RANGE 0x08
#define IVMD_FLAG_UNITY_MAP 0x01
* First set the recommended feature enable bits from ACPI
* into the IOMMU control registers
*/
- h->flags & IVHD_FLAG_HT_TUN_EN ?
+ h->flags & IVHD_FLAG_HT_TUN_EN_MASK ?
iommu_feature_enable(iommu, CONTROL_HT_TUN_EN) :
iommu_feature_disable(iommu, CONTROL_HT_TUN_EN);
- h->flags & IVHD_FLAG_PASSPW_EN ?
+ h->flags & IVHD_FLAG_PASSPW_EN_MASK ?
iommu_feature_enable(iommu, CONTROL_PASSPW_EN) :
iommu_feature_disable(iommu, CONTROL_PASSPW_EN);
- h->flags & IVHD_FLAG_RESPASSPW_EN ?
+ h->flags & IVHD_FLAG_RESPASSPW_EN_MASK ?
iommu_feature_enable(iommu, CONTROL_RESPASSPW_EN) :
iommu_feature_disable(iommu, CONTROL_RESPASSPW_EN);
- h->flags & IVHD_FLAG_ISOC_EN ?
+ h->flags & IVHD_FLAG_ISOC_EN_MASK ?
iommu_feature_enable(iommu, CONTROL_ISOC_EN) :
iommu_feature_disable(iommu, CONTROL_ISOC_EN);
load_TR_desc();
load_LDT(&init_mm.context);
+ t->x86_tss.io_bitmap_base = offsetof(struct tss_struct, io_bitmap);
+
#ifdef CONFIG_DOUBLEFAULT
/* Set up doublefault TSS pointer in the GDT */
__set_tss_desc(cpu, GDT_ENTRY_DOUBLEFAULT_TSS, &doublefault_tss);
* Don't get the IP here because it's unlikely to
* have anything to do with the actual error location.
*/
-
- mce_log(&m);
- add_taint(TAINT_MACHINE_CHECK);
+ if (!(flags & MCP_DONTLOG)) {
+ mce_log(&m);
+ add_taint(TAINT_MACHINE_CHECK);
+ }
/*
* Clear state for this bank.
*/
static int check_interval = 5 * 60; /* 5 minutes */
-static int next_interval; /* in jiffies */
+static DEFINE_PER_CPU(int, next_interval); /* in jiffies */
static void mcheck_timer(unsigned long);
static DEFINE_PER_CPU(struct timer_list, mce_timer);
static void mcheck_timer(unsigned long data)
{
struct timer_list *t = &per_cpu(mce_timer, data);
+ int *n;
WARN_ON(smp_processor_id() != data);
* Alert userspace if needed. If we logged an MCE, reduce the
* polling interval, otherwise increase the polling interval.
*/
+ n = &__get_cpu_var(next_interval);
if (mce_notify_user()) {
- next_interval = max(next_interval/2, HZ/100);
+ *n = max(*n/2, HZ/100);
} else {
- next_interval = min(next_interval * 2,
- (int)round_jiffies_relative(check_interval*HZ));
+ *n = min(*n*2, (int)round_jiffies_relative(check_interval*HZ));
}
- t->expires = jiffies + next_interval;
+ t->expires = jiffies + *n;
add_timer(t);
}
* Log the machine checks left over from the previous reset.
*/
bitmap_fill(all_banks, MAX_NR_BANKS);
- machine_check_poll(MCP_UC, &all_banks);
+ machine_check_poll(MCP_UC|(!mce_bootlog ? MCP_DONTLOG : 0), &all_banks);
set_in_cr4(X86_CR4_MCE);
static void mce_init_timer(void)
{
struct timer_list *t = &__get_cpu_var(mce_timer);
+ int *n = &__get_cpu_var(next_interval);
- /* data race harmless because everyone sets to the same value */
- if (!next_interval)
- next_interval = check_interval * HZ;
- if (!next_interval)
+ *n = check_interval * HZ;
+ if (!*n)
return;
setup_timer(t, mcheck_timer, smp_processor_id());
- t->expires = round_jiffies(jiffies + next_interval);
+ t->expires = round_jiffies(jiffies + *n);
add_timer(t);
}
/* Reinit MCEs after user configuration changes */
static void mce_restart(void)
{
- next_interval = check_interval * HZ;
on_each_cpu(mce_cpu_restart, NULL, 1);
}
break;
case CPU_DOWN_FAILED:
case CPU_DOWN_FAILED_FROZEN:
- t->expires = round_jiffies(jiffies + next_interval);
+ t->expires = round_jiffies(jiffies +
+ __get_cpu_var(next_interval));
add_timer_on(t, cpu);
smp_call_function_single(cpu, mce_reenable_cpu, &action, 1);
break;
if (c->x86_max_cores * smp_num_siblings > 1) {
seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
seq_printf(m, "siblings\t: %d\n",
- cpumask_weight(cpu_sibling_mask(cpu)));
+ cpumask_weight(cpu_core_mask(cpu)));
seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
seq_printf(m, "apicid\t\t: %d\n", c->apicid);
{
struct kmmio_probe *p;
list_for_each_entry_rcu(p, &kmmio_probes, list) {
- if (addr >= p->addr && addr <= (p->addr + p->len))
+ if (addr >= p->addr && addr < (p->addr + p->len))
return p;
}
return NULL;
{
long ret;
if (likely(gtod->sysctl_enabled && gtod->clock.vread)) {
- BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
- offsetof(struct timespec, tv_nsec) ||
- sizeof(*tv) != sizeof(struct timespec));
- do_realtime((struct timespec *)tv);
- tv->tv_usec /= 1000;
+ if (likely(tv != NULL)) {
+ BUILD_BUG_ON(offsetof(struct timeval, tv_usec) !=
+ offsetof(struct timespec, tv_nsec) ||
+ sizeof(*tv) != sizeof(struct timespec));
+ do_realtime((struct timespec *)tv);
+ tv->tv_usec /= 1000;
+ }
if (unlikely(tz != NULL)) {
/* Avoid memcpy. Some old compilers fail to inline it */
tz->tz_minuteswest = gtod->sys_tz.tz_minuteswest;
package_element = *top_object_list;
+ /* We must have a valid Package object */
+
+ if (!package_element ||
+ (package_element->common.type != ACPI_TYPE_PACKAGE)) {
+ return_ACPI_STATUS (AE_AML_OPERAND_TYPE);
+ }
+
/*
* The sub_object_list will now point to an array of the
* four IRQ elements: Address, Pin, Source and source_index
#include <linux/bug.h>
#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/iommu.h>
* value is not cryptographically secure but for several uses the cost of
* depleting entropy is too high
*/
+DEFINE_PER_CPU(__u32 [4], get_random_int_hash);
unsigned int get_random_int(void)
{
- /*
- * Use IP's RNG. It suits our purpose perfectly: it re-keys itself
- * every second, from the entropy pool (and thus creates a limited
- * drain on it), and uses halfMD4Transform within the second. We
- * also mix it with jiffies and the PID:
- */
- return secure_ip_id((__force __be32)(current->pid + jiffies));
+ struct keydata *keyptr;
+ __u32 *hash = get_cpu_var(get_random_int_hash);
+ int ret;
+
+ keyptr = get_keyptr();
+ hash[0] += current->pid + jiffies + get_cycles() + (int)(long)&ret;
+
+ ret = half_md4_transform(hash, keyptr->secret);
+ put_cpu_var(get_random_int_hash);
+
+ return ret;
}
/*
case KIOCSOUND:
if (!perm)
goto eperm;
+ /* FIXME: This is an old broken API but we need to keep it
+ supported and somehow separate the historic advertised
+ tick rate from any real one */
if (arg)
arg = CLOCK_TICK_RATE / arg;
kd_mksound(arg, 0);
*/
ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
count = ticks ? (arg & 0xffff) : 0;
+ /* FIXME: This is an old broken API but we need to keep it
+ supported and somehow separate the historic advertised
+ tick rate from any real one */
if (count)
count = CLOCK_TICK_RATE / count;
kd_mksound(count, ticks);
rc = 1;
break;
case ibft_eth_ip_addr:
- if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
+ if (memcmp(nic->ip_addr, nulls, sizeof(nic->ip_addr)))
rc = 1;
break;
case ibft_eth_subnet_mask:
- if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp)))
+ if (nic->subnet_mask_prefix)
rc = 1;
break;
case ibft_eth_origin:
int saved_x, saved_y;
struct drm_encoder *encoder;
bool ret = true;
- bool depth_changed, bpp_changed;
adjusted_mode = drm_mode_duplicate(dev, mode);
if (!crtc->enabled)
return true;
- if (old_fb && crtc->fb) {
- depth_changed = (old_fb->depth != crtc->fb->depth);
- bpp_changed = (old_fb->bits_per_pixel !=
- crtc->fb->bits_per_pixel);
- } else {
- depth_changed = true;
- bpp_changed = true;
- }
-
saved_mode = crtc->mode;
saved_x = crtc->x;
saved_y = crtc->y;
crtc->x = x;
crtc->y = y;
- if (drm_mode_equal(&saved_mode, &crtc->mode)) {
- if (saved_x != crtc->x || saved_y != crtc->y ||
- depth_changed || bpp_changed) {
- ret = !crtc_funcs->mode_set_base(crtc, crtc->x, crtc->y,
- old_fb);
- goto done;
- }
- }
-
/* Pass our mode to the connectors and the CRTC to give them a chance to
* adjust it according to limitations or connector properties, and also
* a chance to reject the mode entirely.
retcode = -EINVAL;
} else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) ||
((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) ||
- ((ioctl->flags & DRM_MASTER) && !file_priv->is_master)) {
+ ((ioctl->flags & DRM_MASTER) && !file_priv->is_master) ||
+ (!(ioctl->flags & DRM_CONTROL_ALLOW) && (file_priv->minor->type == DRM_MINOR_CONTROL))) {
retcode = -EACCES;
} else {
if (cmd & (IOC_IN | IOC_OUT)) {
if (dev->driver->load) {
ret = dev->driver->load(dev, ent->driver_data);
if (ret)
- goto err_g3;
+ goto err_g4;
}
/* setup the grouping for the legacy output */
if (drm_core_check_feature(dev, DRIVER_MODESET)) {
ret = drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
if (ret)
- goto err_g3;
+ goto err_g4;
}
list_add_tail(&dev->driver_item, &driver->device_list);
return 0;
-err_g3:
+err_g4:
drm_put_minor(&dev->primary);
+err_g3:
+ if (drm_core_check_feature(dev, DRIVER_MODESET))
+ drm_put_minor(&dev->control);
err_g2:
pci_disable_device(pdev);
err_g1:
dev->agp = NULL;
}
- drm_ht_remove(&dev->map_hash);
- drm_ctxbitmap_cleanup(dev);
-
list_for_each_entry_safe(r_list, list_temp, &dev->maplist, head)
drm_rmmap(dev, r_list->map);
+ drm_ht_remove(&dev->map_hash);
+
+ drm_ctxbitmap_cleanup(dev);
if (drm_core_check_feature(dev, DRIVER_MODESET))
drm_put_minor(&dev->control);
return 0;
- device_unregister(&minor->kdev);
err_out:
-
return err;
}
#if __OS_HAS_AGP
if (!dev_priv->is_pci) {
- drm_core_ioremap(dev_priv->cce_ring, dev);
- drm_core_ioremap(dev_priv->ring_rptr, dev);
- drm_core_ioremap(dev->agp_buffer_map, dev);
+ drm_core_ioremap_wc(dev_priv->cce_ring, dev);
+ drm_core_ioremap_wc(dev_priv->ring_rptr, dev);
+ drm_core_ioremap_wc(dev->agp_buffer_map, dev);
if (!dev_priv->cce_ring->handle ||
!dev_priv->ring_rptr->handle ||
!dev->agp_buffer_map->handle) {
* 1.27- Add support for IGP GART
* 1.28- Add support for VBL on CRTC2
* 1.29- R500 3D cmd buffer support
+ * 1.30- Add support for occlusion queries
*/
#define DRIVER_MAJOR 1
-#define DRIVER_MINOR 29
+#define DRIVER_MINOR 30
#define DRIVER_PATCHLEVEL 0
/*
if (fnmode) {
int do_translate;
- trans = apple_find_translation((hid->product < 0x220 ||
+ trans = apple_find_translation((hid->product < 0x21d ||
hid->product >= 0x300) ?
powerbook_fn_keys : apple_fn_keys,
usage->code);
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FORCE3D_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) },
{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) },
struct hid_input *hidinput;
int i;
+ if (!(hid->claimed & HID_CLAIMED_INPUT))
+ return 0;
+
list_for_each_entry(hidinput, &hid->inputs, list) {
for (i = 0; i < BITS_TO_LONGS(KEY_MAX); i++)
if (hidinput->input->key[i])
#define USB_DEVICE_ID_LOGITECH_FORCE3D_PRO 0xc286
#define USB_DEVICE_ID_LOGITECH_WHEEL 0xc294
#define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL 0xc295
+#define USB_DEVICE_ID_LOGITECH_G25_WHEEL 0xc299
#define USB_DEVICE_ID_LOGITECH_ELITE_KBD 0xc30a
#define USB_DEVICE_ID_S510_RECEIVER 0xc50c
#define USB_DEVICE_ID_S510_RECEIVER_2 0xc517
.driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2),
.driver_data = LG_FF },
+ { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
+ .driver_data = LG_FF },
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2),
.driver_data = LG_FF2 },
{ }
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWNAME(0))) {
int len;
- if (!hid->name)
- return 0;
+ if (!hid->name) {
+ ret = 0;
+ break;
+ }
len = strlen(hid->name) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGRAWPHYS(0))) {
int len;
- if (!hid->phys)
- return 0;
+ if (!hid->phys) {
+ ret = 0;
+ break;
+ }
len = strlen(hid->phys) + 1;
if (len > _IOC_SIZE(cmd))
len = _IOC_SIZE(cmd);
spin_lock_irq(&usbhid->lock);
if (!--hid->open) {
spin_unlock_irq(&usbhid->lock);
+ hid_cancel_delayed_stuff(usbhid);
usb_kill_urb(usbhid->urbin);
- flush_scheduled_work();
usbhid->intf->needs_remote_wakeup = 0;
} else {
spin_unlock_irq(&usbhid->lock);
* chips may hold it low ("clock stretching") while they
* are processing data internally.
*/
- if (time_after_eq(jiffies, start + adap->timeout))
+ if (time_after(jiffies, start + adap->timeout))
return -ETIMEDOUT;
cond_resched();
}
case 0x30: /* Data byte in I2CDAT has been transmitted; NOT ACK has been received */
DEB2("NOT ACK received after data byte\n");
+ pca_stop(adap);
goto out;
case 0x38: /* Arbitration lost during SLA+W, SLA+R or data bytes */
DEB2("Arbitration lost\n");
+ /*
+ * The PCA9564 data sheet (2006-09-01) says "A
+ * START condition will be transmitted when the
+ * bus becomes free (STOP or SCL and SDA high)"
+ * when the STA bit is set (p. 11).
+ *
+ * In case this won't work, try pca_reset()
+ * instead.
+ */
+ pca_start(adap);
goto out;
case 0x58: /* Data byte has been received; NOT ACK has been returned */
&& (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n");
}
&& (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
result = -ETIMEDOUT;
dev_err(&adap->dev, "SMBus Timeout!\n");
}
} while ((temp & (GS_HST_STS | GS_SMB_STS)) &&
(timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "Busy wait timeout (%04x)\n", temp);
goto abort;
}
} while ((temp & GS_HST_STS) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "Completion timeout!\n");
goto abort;
}
status = inb_p(SMBHSTSTS);
} while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
- result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+ result = i801_check_post(status, timeout > MAX_TIMEOUT);
if (result < 0)
return result;
} while ((!(status & SMBHSTSTS_INTR))
&& (timeout++ < MAX_TIMEOUT));
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT)
dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
- }
+
outb_p(status, SMBHSTSTS);
}
while ((!(status & SMBHSTSTS_BYTE_DONE))
&& (timeout++ < MAX_TIMEOUT));
- result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+ result = i801_check_post(status, timeout > MAX_TIMEOUT);
if (result < 0)
return result;
} while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
temp = inb_p(NVIDIA_SMB_STS);
} while ((!temp) && (timeout++ < MAX_TIMEOUT));
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
if (smbus->can_abort)
nforce2_abort(adap);
} while (!(temp & 0x40) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
} while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&adap->dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}
} while (!(temp & 0x0e) && (timeout++ < MAX_TIMEOUT));
/* If the SMBus is still busy, we give up */
- if (timeout >= MAX_TIMEOUT) {
+ if (timeout > MAX_TIMEOUT) {
dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp);
result = -ETIMEDOUT;
}
ide_hwif_t *hwif = drive->hwif;
struct request *rq = hwif->rq;
int err, sense_key, do_end_request = 0;
- u8 quiet = rq->cmd_flags & REQ_QUIET;
/* get the IDE error register */
err = ide_read_error(drive);
} else {
cdrom_saw_media_change(drive);
- if (blk_fs_request(rq) && !quiet)
+ if (blk_fs_request(rq) && !blk_rq_quiet(rq))
printk(KERN_ERR PFX "%s: tray open\n",
drive->name);
}
* No point in retrying after an illegal request or data
* protect error.
*/
- if (!quiet)
+ if (!blk_rq_quiet(rq))
ide_dump_status(drive, "command error", stat);
do_end_request = 1;
break;
* No point in re-trying a zillion times on a bad sector.
* If we got here the error is not correctable.
*/
- if (!quiet)
+ if (!blk_rq_quiet(rq))
ide_dump_status(drive, "media error "
"(bad sector)", stat);
do_end_request = 1;
break;
case BLANK_CHECK:
/* disk appears blank? */
- if (!quiet)
+ if (!blk_rq_quiet(rq))
ide_dump_status(drive, "media error (blank)",
stat);
do_end_request = 1;
.eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_target_reset_handler= iscsi_eh_target_reset,
+ .target_alloc = iscsi_target_alloc,
.use_clustering = DISABLE_CLUSTERING,
.proc_name = "iscsi_iser",
.this_id = -1,
#define INPUT_DEVICES 256
+/*
+ * EV_ABS events which should not be cached are listed here.
+ */
+static unsigned int input_abs_bypass_init_data[] __initdata = {
+ ABS_MT_TOUCH_MAJOR,
+ ABS_MT_TOUCH_MINOR,
+ ABS_MT_WIDTH_MAJOR,
+ ABS_MT_WIDTH_MINOR,
+ ABS_MT_ORIENTATION,
+ ABS_MT_POSITION_X,
+ ABS_MT_POSITION_Y,
+ ABS_MT_TOOL_TYPE,
+ ABS_MT_BLOB_ID,
+ 0
+};
+static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)];
+
static LIST_HEAD(input_dev_list);
static LIST_HEAD(input_handler_list);
disposition = INPUT_PASS_TO_HANDLERS;
}
break;
+ case SYN_MT_REPORT:
+ dev->sync = 0;
+ disposition = INPUT_PASS_TO_HANDLERS;
+ break;
}
break;
case EV_ABS:
if (is_event_supported(code, dev->absbit, ABS_MAX)) {
+ if (test_bit(code, input_abs_bypass)) {
+ disposition = INPUT_PASS_TO_HANDLERS;
+ break;
+ }
+
value = input_defuzz_abs_event(value,
dev->abs[code], dev->absfuzz[code]);
.open = input_open_file,
};
+static void __init input_init_abs_bypass(void)
+{
+ const unsigned int *p;
+
+ for (p = input_abs_bypass_init_data; *p; p++)
+ input_abs_bypass[BIT_WORD(*p)] |= BIT_MASK(*p);
+}
+
static int __init input_init(void)
{
int err;
+ input_init_abs_bypass();
+
err = class_register(&input_class);
if (err) {
printk(KERN_ERR "input: unable to register input_dev class\n");
/* disable keyboard interrupt and schedule for handling */
if (cpu_is_omap24xx()) {
int i;
- for (i = 0; i < omap_kp->rows; i++)
- disable_irq(gpio_to_irq(row_gpios[i]));
+
+ for (i = 0; i < omap_kp->rows; i++) {
+ int gpio_irq = gpio_to_irq(row_gpios[i]);
+ /*
+ * The interrupt which we're currently handling should
+ * be disabled _nosync() to avoid deadlocks waiting
+ * for this handler to complete. All others should
+ * be disabled the regular way for SMP safety.
+ */
+ if (gpio_irq == irq)
+ disable_irq_nosync(gpio_irq);
+ else
+ disable_irq(gpio_irq);
+ }
} else
/* disable keyboard interrupt and schedule for handling */
omap_writew(1, OMAP_MPUIO_BASE + OMAP_MPUIO_KBD_MASKIT);
#define ALPS_FW_BK_2 0x40
static const struct alps_model_info alps_model_data[] = {
+ { { 0x32, 0x02, 0x14 }, 0xf8, 0xf8, ALPS_PASS | ALPS_DUALPOINT }, /* Toshiba Salellite Pro M10 */
{ { 0x33, 0x02, 0x0a }, 0x88, 0xf8, ALPS_OLDPROTO }, /* UMAX-530T */
{ { 0x53, 0x02, 0x0a }, 0xf8, 0xf8, 0 },
{ { 0x53, 0x02, 0x14 }, 0xf8, 0xf8, 0 },
*/
static int atp_geyser_init(struct usb_device *udev)
{
- char data[8];
+ char *data;
int size;
int i;
+ int ret;
+
+ data = kmalloc(8, GFP_KERNEL);
+ if (!data) {
+ err("Out of memory");
+ return -ENOMEM;
+ }
size = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
ATP_GEYSER_MODE_READ_REQUEST_ID,
USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
ATP_GEYSER_MODE_REQUEST_VALUE,
- ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
+ ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000);
if (size != 8) {
dprintk("atp_geyser_init: read error\n");
dprintk("appletouch[%d]: %d\n", i, data[i]);
err("Failed to read mode from device.");
- return -EIO;
+ ret = -EIO;
+ goto out_free;
}
/* Apply the mode switch */
ATP_GEYSER_MODE_WRITE_REQUEST_ID,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
ATP_GEYSER_MODE_REQUEST_VALUE,
- ATP_GEYSER_MODE_REQUEST_INDEX, &data, 8, 5000);
+ ATP_GEYSER_MODE_REQUEST_INDEX, data, 8, 5000);
if (size != 8) {
dprintk("atp_geyser_init: write error\n");
dprintk("appletouch[%d]: %d\n", i, data[i]);
err("Failed to request geyser raw mode");
- return -EIO;
+ ret = -EIO;
+ goto out_free;
}
- return 0;
+ ret = 0;
+out_free:
+ kfree(data);
+ return ret;
}
/*
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI 0x0230
#define USB_DEVICE_ID_APPLE_WELLSPRING2_ISO 0x0231
#define USB_DEVICE_ID_APPLE_WELLSPRING2_JIS 0x0232
+/* Macbook5,1 (unibody), aka wellspring3 */
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI 0x0236
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_ISO 0x0237
+#define USB_DEVICE_ID_APPLE_WELLSPRING3_JIS 0x0238
#define BCM5974_DEVICE(prod) { \
.match_flags = (USB_DEVICE_ID_MATCH_DEVICE | \
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_ISO),
BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING2_JIS),
+ /* Macbook5,1 */
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_ISO),
+ BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING3_JIS),
/* Terminating entry */
{}
};
u8 rel_y; /* relative y coordinate */
};
-/* trackpad header structure */
-struct tp_header {
- u8 unknown1[16]; /* constants, timers, etc */
- u8 fingers; /* number of fingers on trackpad */
- u8 unknown2[9]; /* constants, timers, etc */
+/* trackpad header types */
+enum tp_type {
+ TYPE1, /* plain trackpad */
+ TYPE2 /* button integrated in trackpad */
};
-/* trackpad finger structure */
+/* trackpad finger data offsets, le16-aligned */
+#define FINGER_TYPE1 (13 * sizeof(__le16))
+#define FINGER_TYPE2 (15 * sizeof(__le16))
+
+/* trackpad button data offsets */
+#define BUTTON_TYPE2 15
+
+/* list of device capability bits */
+#define HAS_INTEGRATED_BUTTON 1
+
+/* trackpad finger structure, le16-aligned */
struct tp_finger {
__le16 origin; /* zero when switching track finger */
__le16 abs_x; /* absolute x coodinate */
__le16 force_minor; /* trackpad force, minor axis? */
__le16 unused[3]; /* zeros */
__le16 multi; /* one finger: varies, more fingers: constant */
-};
+} __attribute__((packed,aligned(2)));
-/* trackpad data structure, empirically at least ten fingers */
-struct tp_data {
- struct tp_header header;
- struct tp_finger finger[16];
-};
+/* trackpad finger data size, empirically at least ten fingers */
+#define SIZEOF_FINGER sizeof(struct tp_finger)
+#define SIZEOF_ALL_FINGERS (16 * SIZEOF_FINGER)
/* device-specific parameters */
struct bcm5974_param {
/* device-specific configuration */
struct bcm5974_config {
int ansi, iso, jis; /* the product id of this device */
+ int caps; /* device capability bitmask */
int bt_ep; /* the endpoint of the button interface */
int bt_datalen; /* data length of the button interface */
int tp_ep; /* the endpoint of the trackpad interface */
+ enum tp_type tp_type; /* type of trackpad interface */
+ int tp_offset; /* offset to trackpad finger data */
int tp_datalen; /* data length of the trackpad interface */
struct bcm5974_param p; /* finger pressure limits */
struct bcm5974_param w; /* finger width limits */
struct urb *bt_urb; /* button usb request block */
struct bt_data *bt_data; /* button transferred data */
struct urb *tp_urb; /* trackpad usb request block */
- struct tp_data *tp_data; /* trackpad transferred data */
+ u8 *tp_data; /* trackpad transferred data */
int fingers; /* number of fingers on trackpad */
};
USB_DEVICE_ID_APPLE_WELLSPRING_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING_JIS,
+ 0,
0x84, sizeof(struct bt_data),
- 0x81, sizeof(struct tp_data),
+ 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
{ DIM_X, DIM_X / SN_COORD, -4824, 5342 },
USB_DEVICE_ID_APPLE_WELLSPRING2_ANSI,
USB_DEVICE_ID_APPLE_WELLSPRING2_ISO,
USB_DEVICE_ID_APPLE_WELLSPRING2_JIS,
+ 0,
0x84, sizeof(struct bt_data),
- 0x81, sizeof(struct tp_data),
+ 0x81, TYPE1, FINGER_TYPE1, FINGER_TYPE1 + SIZEOF_ALL_FINGERS,
{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 256 },
{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
{ DIM_X, DIM_X / SN_COORD, -4824, 4824 },
{ DIM_Y, DIM_Y / SN_COORD, -172, 4290 }
},
+ {
+ USB_DEVICE_ID_APPLE_WELLSPRING3_ANSI,
+ USB_DEVICE_ID_APPLE_WELLSPRING3_ISO,
+ USB_DEVICE_ID_APPLE_WELLSPRING3_JIS,
+ HAS_INTEGRATED_BUTTON,
+ 0x84, sizeof(struct bt_data),
+ 0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+ { DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+ { DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+ { DIM_X, DIM_X / SN_COORD, -4460, 5166 },
+ { DIM_Y, DIM_Y / SN_COORD, -75, 6700 }
+ },
{}
};
__set_bit(BTN_TOOL_FINGER, input_dev->keybit);
__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
+ __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit);
__set_bit(BTN_LEFT, input_dev->keybit);
}
if (size != sizeof(struct bt_data))
return -EIO;
+ dprintk(7,
+ "bcm5974: button data: %x %x %x %x\n",
+ dev->bt_data->unknown1, dev->bt_data->button,
+ dev->bt_data->rel_x, dev->bt_data->rel_y);
+
input_report_key(dev->input, BTN_LEFT, dev->bt_data->button);
input_sync(dev->input);
static int report_tp_state(struct bcm5974 *dev, int size)
{
const struct bcm5974_config *c = &dev->cfg;
- const struct tp_finger *f = dev->tp_data->finger;
+ const struct tp_finger *f;
struct input_dev *input = dev->input;
- const int fingers = (size - 26) / 28;
- int raw_p, raw_w, raw_x, raw_y;
- int ptest = 0, origin = 0, nmin = 0, nmax = 0;
+ int raw_p, raw_w, raw_x, raw_y, raw_n;
+ int ptest = 0, origin = 0, ibt = 0, nmin = 0, nmax = 0;
int abs_p = 0, abs_w = 0, abs_x = 0, abs_y = 0;
- if (size < 26 || (size - 26) % 28 != 0)
+ if (size < c->tp_offset || (size - c->tp_offset) % SIZEOF_FINGER != 0)
return -EIO;
+ /* finger data, le16-aligned */
+ f = (const struct tp_finger *)(dev->tp_data + c->tp_offset);
+ raw_n = (size - c->tp_offset) / SIZEOF_FINGER;
+
/* always track the first finger; when detached, start over */
- if (fingers) {
+ if (raw_n) {
raw_p = raw2int(f->force_major);
raw_w = raw2int(f->size_major);
raw_x = raw2int(f->abs_x);
raw_y = raw2int(f->abs_y);
dprintk(9,
- "bcm5974: raw: p: %+05d w: %+05d x: %+05d y: %+05d\n",
- raw_p, raw_w, raw_x, raw_y);
+ "bcm5974: "
+ "raw: p: %+05d w: %+05d x: %+05d y: %+05d n: %d\n",
+ raw_p, raw_w, raw_x, raw_y, raw_n);
ptest = int2bound(&c->p, raw_p);
origin = raw2int(f->origin);
+
+ /* set the integrated button if applicable */
+ if (c->tp_type == TYPE2)
+ ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
}
/* while tracking finger still valid, count all fingers */
abs_w = int2bound(&c->w, raw_w);
abs_x = int2bound(&c->x, raw_x - c->x.devmin);
abs_y = int2bound(&c->y, c->y.devmax - raw_y);
- for (; f != dev->tp_data->finger + fingers; f++) {
+ while (raw_n--) {
ptest = int2bound(&c->p, raw2int(f->force_major));
if (ptest > PRESSURE_LOW)
nmax++;
if (ptest > PRESSURE_HIGH)
nmin++;
+ f++;
}
}
input_report_key(input, BTN_TOUCH, dev->fingers > 0);
input_report_key(input, BTN_TOOL_FINGER, dev->fingers == 1);
input_report_key(input, BTN_TOOL_DOUBLETAP, dev->fingers == 2);
- input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers > 2);
+ input_report_key(input, BTN_TOOL_TRIPLETAP, dev->fingers == 3);
+ input_report_key(input, BTN_TOOL_QUADTAP, dev->fingers > 3);
input_report_abs(input, ABS_PRESSURE, abs_p);
input_report_abs(input, ABS_TOOL_WIDTH, abs_w);
dprintk(8,
"bcm5974: abs: p: %+05d w: %+05d x: %+05d y: %+05d "
- "nmin: %d nmax: %d n: %d\n",
- abs_p, abs_w, abs_x, abs_y, nmin, nmax, dev->fingers);
+ "nmin: %d nmax: %d n: %d ibt: %d\n", abs_p, abs_w,
+ abs_x, abs_y, nmin, nmax, dev->fingers, ibt);
}
+ /* type 2 reports button events via ibt only */
+ if (c->tp_type == TYPE2)
+ input_report_key(input, BTN_LEFT, ibt);
+
input_sync(input);
return 0;
input_dev->name = "bcm5974";
input_dev->phys = dev->phys;
usb_to_input_id(dev->udev, &input_dev->id);
+ /* report driver capabilities via the version field */
+ input_dev->id.version = cfg->caps;
input_dev->dev.parent = &iface->dev;
input_set_drvdata(input_dev, dev);
/*
- * Elantech Touchpad driver (v5)
+ * Elantech Touchpad driver (v6)
*
- * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net>
+ * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net>
*
* 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
struct elantech_data *etd = psmouse->private;
unsigned char *packet = psmouse->packet;
int fingers;
+ static int old_fingers;
if (etd->fw_version_maj == 0x01) {
/* byte 0: D U p1 p2 1 p3 R L
fingers = (packet[0] & 0xc0) >> 6;
}
+ if (etd->jumpy_cursor) {
+ /* Discard packets that are likely to have bogus coordinates */
+ if (fingers > old_fingers) {
+ elantech_debug("elantech.c: discarding packet\n");
+ goto discard_packet_v1;
+ }
+ }
+
input_report_key(dev, BTN_TOUCH, fingers != 0);
/* byte 2: x7 x6 x5 x4 x3 x2 x1 x0
}
input_sync(dev);
+
+ discard_packet_v1:
+ old_fingers = fingers;
}
/*
rc = -1;
break;
}
+ }
+
+ if (rc == 0) {
/*
- * Read back reg 0x10. The touchpad is probably initalising
- * and not ready until we read back the value we just wrote.
+ * Read back reg 0x10. For hardware version 1 we must make
+ * sure the absolute mode bit is set. For hardware version 2
+ * the touchpad is probably initalising and not ready until
+ * we read back the value we just wrote.
*/
do {
rc = elantech_read_reg(psmouse, 0x10, &val);
break;
tries--;
elantech_debug("elantech.c: retrying read (%d).\n",
- tries);
+ tries);
msleep(ETP_READ_BACK_DELAY);
} while (tries > 0);
- if (rc)
+
+ if (rc) {
pr_err("elantech.c: failed to read back register 0x10.\n");
- break;
+ } else if (etd->hw_version == 1 &&
+ !(val & ETP_R10_ABSOLUTE_MODE)) {
+ pr_err("elantech.c: touchpad refuses "
+ "to switch to absolute mode.\n");
+ rc = -1;
+ }
}
if (rc)
param[0], param[1], param[2]);
etd->capabilities = param[0];
+ /*
+ * This firmware seems to suffer from misreporting coordinates when
+ * a touch action starts causing the mouse cursor or scrolled page
+ * to jump. Enable a workaround.
+ */
+ if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) {
+ pr_info("elantech.c: firmware version 2.34 detected, "
+ "enabling jumpy cursor workaround\n");
+ etd->jumpy_cursor = 1;
+ }
+
if (elantech_set_absolute_mode(psmouse)) {
pr_err("elantech.c: failed to put touchpad into absolute mode.\n");
goto init_fail;
/*
- * Elantech Touchpad driver (v5)
+ * Elantech Touchpad driver (v6)
*
- * Copyright (C) 2007-2008 Arjan Opmeer <arjan@opmeer.net>
+ * Copyright (C) 2007-2009 Arjan Opmeer <arjan@opmeer.net>
*
* 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
unsigned char fw_version_min;
unsigned char hw_version;
unsigned char paritycheck;
+ unsigned char jumpy_cursor;
unsigned char parity[256];
};
DMI_MATCH(DMI_PRODUCT_NAME, "LIFEBOOK B Series"),
},
},
+ {
+ .ident = "Lifebook B-2130",
+ .matches = {
+ DMI_MATCH(DMI_BOARD_NAME, "ZEPHYR"),
+ },
+ },
{
.ident = "Lifebook B213x/B2150",
.matches = {
spin_lock(&ps2if->lock);
status = sa1111_readl(ps2if->base + SA1111_PS2STAT);
if (ps2if->head == ps2if->tail) {
- disable_irq(irq);
+ disable_irq_nosync(irq);
/* done */
} else if (status & PS2STAT_TXE) {
sa1111_writel(ps2if->buf[ps2if->tail], ps2if->base + SA1111_PS2DATA);
* Copyright (c) 2000 Daniel Egger <egger@suse.de>
* Copyright (c) 2001 Frederic Lepied <flepied@mandrakesoft.com>
* Copyright (c) 2004 Panagiotis Issaris <panagiotis.issaris@mech.kuleuven.ac.be>
- * Copyright (c) 2002-2008 Ping Cheng <pingc@wacom.com>
+ * Copyright (c) 2002-2009 Ping Cheng <pingc@wacom.com>
*
* ChangeLog:
* v0.1 (vp) - Initial release
* v1.47 (pc) - Added support for Bamboo
* v1.48 (pc) - Added support for Bamboo1, BambooFun, and Cintiq 12WX
* v1.49 (pc) - Added support for USB Tablet PC (0x90, 0x93, and 0x9A)
+ * v1.50 (pc) - Fixed a TabletPC touch bug in 2.6.28
*/
/*
/*
* Version Information
*/
-#define DRIVER_VERSION "v1.49"
+#define DRIVER_VERSION "v1.50"
#define DRIVER_AUTHOR "Vojtech Pavlik <vojtech@ucw.cz>"
#define DRIVER_DESC "USB Wacom Graphire and Wacom Intuos tablet driver"
#define DRIVER_LICENSE "GPL"
5000); /* 5 secs */
} while (result < 0 && limit++ < 5);
+ /* No need to parse the Descriptor. It isn't an error though */
if (result < 0)
goto out;
}
}
- result = 0;
-
out:
+ result = 0;
kfree(report);
return result;
}
endpoint = &intf->cur_altsetting->endpoint[0].desc;
+ /* Initialize touch_x_max and touch_y_max in case it is not defined */
+ if (wacom_wac->features->type == TABLETPC) {
+ features->touch_x_max = 1023;
+ features->touch_y_max = 1023;
+ } else {
+ features->touch_x_max = 0;
+ features->touch_y_max = 0;
+ }
+
/* TabletPC need to retrieve the physical and logical maximum from report descriptor */
if (wacom_wac->features->type == TABLETPC) {
if (usb_get_extra_descriptor(interface, HID_DEVICET_HID, &hid_desc)) {
spin_lock_irqsave(&ts->lock, flags);
if (likely(ts->get_pendown_state())) {
- disable_irq(ts->irq);
+ disable_irq_nosync(ts->irq);
hrtimer_start(&ts->timer, ktime_set(0, TS_POLL_DELAY),
HRTIMER_MODE_REL);
}
struct ucb1400_ts *ucb = devid;
if (irqnr == ucb->irq) {
- disable_irq(ucb->irq);
+ disable_irq_nosync(ucb->irq);
ucb->irq_pending = 1;
wake_up(&ucb->ts_wait);
return IRQ_HANDLED;
oldindex = index;
oldpage = page;
+ bitmap->filemap[bitmap->file_pages++] = page;
+ bitmap->last_page_size = count;
+
if (outofdate) {
/*
* if bitmap is out of date, dirty the
write_page(bitmap, page, 1);
ret = -EIO;
- if (bitmap->flags & BITMAP_WRITE_ERROR) {
- /* release, page not in filemap yet */
- put_page(page);
+ if (bitmap->flags & BITMAP_WRITE_ERROR)
goto err;
- }
}
-
- bitmap->filemap[bitmap->file_pages++] = page;
- bitmap->last_page_size = count;
}
paddr = kmap_atomic(page, KM_USER0);
if (bitmap->flags & BITMAP_HOSTENDIAN)
kunmap_atomic(paddr, KM_USER0);
if (b) {
/* if the disk bit is set, set the memory bit */
- bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap),
- ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start)
- );
+ int needed = ((sector_t)(i+1) << (CHUNK_BLOCK_SHIFT(bitmap))
+ >= start);
+ bitmap_set_memory_bits(bitmap,
+ (sector_t)i << CHUNK_BLOCK_SHIFT(bitmap),
+ needed);
bit_cnt++;
set_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
spin_lock_irqsave(&bitmap->lock, flags);
clear_page_attr(bitmap, page, BITMAP_PAGE_CLEAN);
}
- bmc = bitmap_get_counter(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
- &blocks, 0);
+ bmc = bitmap_get_counter(bitmap,
+ (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
+ &blocks, 0);
if (bmc) {
/*
if (j < 100) printk("bitmap: j=%lu, *bmc = 0x%x\n", j, *bmc);
} else if (*bmc == 1) {
/* we can clear the bit */
*bmc = 0;
- bitmap_count_page(bitmap, j << CHUNK_BLOCK_SHIFT(bitmap),
+ bitmap_count_page(bitmap,
+ (sector_t)j << CHUNK_BLOCK_SHIFT(bitmap),
-1);
/* clear the bit */
unsigned long chunk;
for (chunk = s; chunk <= e; chunk++) {
- sector_t sec = chunk << CHUNK_BLOCK_SHIFT(bitmap);
+ sector_t sec = (sector_t)chunk << CHUNK_BLOCK_SHIFT(bitmap);
bitmap_set_memory_bits(bitmap, sec, 1);
bitmap_file_set_bit(bitmap, sec);
}
} else
err = -EBUSY;
spin_unlock_irq(&mddev->write_lock);
- } else {
- mddev->ro = 0;
- mddev->recovery_cp = MaxSector;
- err = do_md_run(mddev);
- }
+ } else
+ err = -EINVAL;
break;
case active:
if (mddev->pers) {
{
int err = 0;
struct gendisk *disk = mddev->gendisk;
+ mdk_rdev_t *rdev;
if (atomic_read(&mddev->openers) > is_open) {
printk("md: %s still in use.\n",mdname(mddev));
/* tell userspace to handle 'inactive' */
sysfs_notify_dirent(mddev->sysfs_state);
+ list_for_each_entry(rdev, &mddev->disks, same_set)
+ if (rdev->raid_disk >= 0) {
+ char nm[20];
+ sprintf(nm, "rd%d", rdev->raid_disk);
+ sysfs_remove_link(&mddev->kobj, nm);
+ }
+
set_capacity(disk, 0);
mddev->changed = 1;
* Free resources if final stop
*/
if (mode == 0) {
- mdk_rdev_t *rdev;
printk(KERN_INFO "md: %s stopped.\n", mdname(mddev));
}
mddev->bitmap_offset = 0;
- list_for_each_entry(rdev, &mddev->disks, same_set)
- if (rdev->raid_disk >= 0) {
- char nm[20];
- sprintf(nm, "rd%d", rdev->raid_disk);
- sysfs_remove_link(&mddev->kobj, nm);
- }
-
/* make sure all md_delayed_delete calls have finished */
flush_scheduled_work();
static void status_resync(struct seq_file *seq, mddev_t * mddev)
{
- sector_t max_blocks, resync, res;
- unsigned long dt, db, rt;
+ sector_t max_sectors, resync, res;
+ unsigned long dt, db;
+ sector_t rt;
int scale;
unsigned int per_milli;
- resync = (mddev->curr_resync - atomic_read(&mddev->recovery_active))/2;
+ resync = mddev->curr_resync - atomic_read(&mddev->recovery_active);
if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery))
- max_blocks = mddev->resync_max_sectors >> 1;
+ max_sectors = mddev->resync_max_sectors;
else
- max_blocks = mddev->dev_sectors / 2;
+ max_sectors = mddev->dev_sectors;
/*
* Should not happen.
*/
- if (!max_blocks) {
+ if (!max_sectors) {
MD_BUG();
return;
}
/* Pick 'scale' such that (resync>>scale)*1000 will fit
- * in a sector_t, and (max_blocks>>scale) will fit in a
+ * in a sector_t, and (max_sectors>>scale) will fit in a
* u32, as those are the requirements for sector_div.
* Thus 'scale' must be at least 10
*/
scale = 10;
if (sizeof(sector_t) > sizeof(unsigned long)) {
- while ( max_blocks/2 > (1ULL<<(scale+32)))
+ while ( max_sectors/2 > (1ULL<<(scale+32)))
scale++;
}
res = (resync>>scale)*1000;
- sector_div(res, (u32)((max_blocks>>scale)+1));
+ sector_div(res, (u32)((max_sectors>>scale)+1));
per_milli = res;
{
(test_bit(MD_RECOVERY_SYNC, &mddev->recovery) ?
"resync" : "recovery"))),
per_milli/10, per_milli % 10,
- (unsigned long long) resync,
- (unsigned long long) max_blocks);
+ (unsigned long long) resync/2,
+ (unsigned long long) max_sectors/2);
/*
- * We do not want to overflow, so the order of operands and
- * the * 100 / 100 trick are important. We do a +1 to be
- * safe against division by zero. We only estimate anyway.
- *
* dt: time from mark until now
* db: blocks written from mark until now
* rt: remaining time
+ *
+ * rt is a sector_t, so could be 32bit or 64bit.
+ * So we divide before multiply in case it is 32bit and close
+ * to the limit.
+ * We scale the divisor (db) by 32 to avoid loosing precision
+ * near the end of resync when the number of remaining sectors
+ * is close to 'db'.
+ * We then divide rt by 32 after multiplying by db to compensate.
+ * The '+1' avoids division by zero if db is very small.
*/
dt = ((jiffies - mddev->resync_mark) / HZ);
if (!dt) dt++;
db = (mddev->curr_mark_cnt - atomic_read(&mddev->recovery_active))
- mddev->resync_mark_cnt;
- rt = (dt * ((unsigned long)(max_blocks-resync) / (db/2/100+1)))/100;
- seq_printf(seq, " finish=%lu.%lumin", rt / 60, (rt % 60)/6);
+ rt = max_sectors - resync; /* number of remaining sectors */
+ sector_div(rt, db/32+1);
+ rt *= dt;
+ rt >>= 5;
+
+ seq_printf(seq, " finish=%lu.%lumin", (unsigned long)rt / 60,
+ ((unsigned long)rt % 60)/6);
seq_printf(seq, " speed=%ldK/sec", db/2/dt);
}
return 0;
}
-static struct seq_operations md_seq_ops = {
+static const struct seq_operations md_seq_ops = {
.start = md_seq_start,
.next = md_seq_next,
.stop = md_seq_stop,
r10_bio->sector = sect;
raid10_find_phys(conf, r10_bio);
- /* Need to check if this section will still be
+
+ /* Need to check if the array will still be
* degraded
*/
- for (j=0; j<conf->copies;j++) {
- int d = r10_bio->devs[j].devnum;
- if (conf->mirrors[d].rdev == NULL ||
- test_bit(Faulty, &conf->mirrors[d].rdev->flags)) {
+ for (j=0; j<conf->raid_disks; j++)
+ if (conf->mirrors[j].rdev == NULL ||
+ test_bit(Faulty, &conf->mirrors[j].rdev->flags)) {
still_degraded = 1;
break;
}
- }
+
must_sync = bitmap_start_sync(mddev->bitmap, sect,
&sync_blocks, still_degraded);
struct i2c_client *client;
struct mutex lock;
u8 reg_cache[ISL29003_NUM_CACHABLE_REGS];
+ u8 power_state_before_suspend;
};
static int gain_range[] = {
#ifdef CONFIG_PM
static int isl29003_suspend(struct i2c_client *client, pm_message_t mesg)
{
+ struct isl29003_data *data = i2c_get_clientdata(client);
+
+ data->power_state_before_suspend = isl29003_get_power_state(client);
return isl29003_set_power_state(client, 0);
}
/* restore registers from cache */
for (i = 0; i < ARRAY_SIZE(data->reg_cache); i++)
- if (!i2c_smbus_write_byte_data(client, i, data->reg_cache[i]))
+ if (i2c_smbus_write_byte_data(client, i, data->reg_cache[i]))
return -EIO;
- return 0;
+ return isl29003_set_power_state(client,
+ data->power_state_before_suspend);
}
#else
brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC;
brq.data.blocks = req->nr_sectors;
+ /*
+ * The block layer doesn't support all sector count
+ * restrictions, so we need to be prepared for too big
+ * requests.
+ */
+ if (brq.data.blocks > card->host->max_blk_count)
+ brq.data.blocks = card->host->max_blk_count;
+
/*
* After a read error, we redo the request one sector at a time
* in order to accurately determine which sectors can be read
* This delay should be sufficient to allow the power supply
* to reach the minimum voltage.
*/
- mmc_delay(2);
+ mmc_delay(10);
host->ios.clock = host->f_min;
host->ios.power_mode = MMC_POWER_ON;
* This delay must be at least 74 clock sizes, or 1 ms, or the
* time required to reach a stable voltage.
*/
- mmc_delay(2);
+ mmc_delay(10);
}
static void mmc_power_off(struct mmc_host *host)
}
host = mmc_priv(mmc);
+ host->mmc = mmc;
/* Bits 12 thru 19 is the designer */
host->hw_designer = (dev->periphid >> 12) & 0xff;
/* Bits 20 thru 23 is the revison */
host->mclk = clk_get_rate(host->clk);
DBG(host, "eventual mclk rate: %u Hz\n", host->mclk);
}
- host->mmc = mmc;
host->base = ioremap(dev->res.start, SZ_4K);
if (!host->base) {
ret = -ENOMEM;
}
#ifdef CONFIG_PM
-static int mvsd_suspend(struct platform_device *dev, pm_message_t state,
- u32 level)
+static int mvsd_suspend(struct platform_device *dev, pm_message_t state)
{
struct mmc_host *mmc = platform_get_drvdata(dev);
int ret = 0;
- if (mmc && level == SUSPEND_DISABLE)
+ if (mmc)
ret = mmc_suspend_host(mmc, state);
return ret;
}
-static int mvsd_resume(struct platform_device *dev, u32 level)
+static int mvsd_resume(struct platform_device *dev)
{
- struct mmc_host *mmc = platform_dev_get_drvdata(dev);
+ struct mmc_host *mmc = platform_get_drvdata(dev);
int ret = 0;
- if (mmc && level == RESUME_ENABLE)
+ if (mmc)
ret = mmc_resume_host(mmc);
return ret;
struct timer_list dma_timer;
unsigned dma_len;
- short power_pin;
-
struct mmc_omap_slot *slots[OMAP_MMC_MAX_SLOTS];
struct mmc_omap_slot *current_slot;
spinlock_t slot_lock;
host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot));
if (IS_ERR(host)) {
- ret = PTR_ERR(host);
- goto unmap;
+ dev_err(&pdev->dev, "cannot allocate host\n");
+ return ERR_PTR(PTR_ERR(host));
}
slot = sdhci_priv(host);
ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
if (ret) {
dev_err(&pdev->dev, "cannot request region\n");
- return ERR_PTR(ret);
+ goto free;
}
addr = pci_resource_start(pdev, bar);
release:
pci_release_region(pdev, bar);
+
+free:
sdhci_free_host(host);
return ERR_PTR(ret);
#define SDHCI_INT_DATA_MASK (SDHCI_INT_DATA_END | SDHCI_INT_DMA_END | \
SDHCI_INT_DATA_AVAIL | SDHCI_INT_SPACE_AVAIL | \
SDHCI_INT_DATA_TIMEOUT | SDHCI_INT_DATA_CRC | \
- SDHCI_INT_DATA_END_BIT)
+ SDHCI_INT_DATA_END_BIT | SDHCI_ADMA_ERROR)
#define SDHCI_INT_ALL_MASK ((unsigned int)-1)
#define SDHCI_ACMD12_ERR 0x3C
* Called with RTNL
*/
int bond_alb_set_mac_address(struct net_device *bond_dev, void *addr)
- __releases(&bond->curr_slave_lock)
- __releases(&bond->lock)
__acquires(&bond->lock)
- __acquires(&bond->curr_slave_lock)
+ __releases(&bond->lock)
{
struct bonding *bond = netdev_priv(bond_dev);
struct sockaddr *sa = addr;
}
}
- write_unlock_bh(&bond->curr_slave_lock);
- read_unlock(&bond->lock);
-
if (swap_slave) {
alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
bond->alb_info.rlb_enabled);
+ read_lock(&bond->lock);
alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
if (bond->alb_info.rlb_enabled) {
/* inform clients mac address has changed */
rlb_req_update_slave_clients(bond, bond->curr_active_slave);
}
+ read_unlock(&bond->lock);
}
- read_lock(&bond->lock);
- write_lock_bh(&bond->curr_slave_lock);
-
return 0;
}
{
struct bonding *bond = netdev_priv(bond_dev);
struct slave *slave;
- int i, found = 0;
-
- if (info->slave_id < 0) {
- return -ENODEV;
- }
+ int i, res = -ENODEV;
read_lock(&bond->lock);
bond_for_each_slave(bond, slave, i) {
if (i == (int)info->slave_id) {
- found = 1;
+ res = 0;
+ strcpy(info->slave_name, slave->dev->name);
+ info->link = slave->link;
+ info->state = slave->state;
+ info->link_failure_count = slave->link_failure_count;
break;
}
}
read_unlock(&bond->lock);
- if (found) {
- strcpy(info->slave_name, slave->dev->name);
- info->link = slave->link;
- info->state = slave->state;
- info->link_failure_count = slave->link_failure_count;
- } else {
- return -ENODEV;
- }
-
- return 0;
+ return res;
}
/*-------------------------------- Monitoring -------------------------------*/
up_write(&bonding_rwsem);
rtnl_unlock(); /* allows sysfs registration of net device */
res = bond_create_sysfs_entry(netdev_priv(bond_dev));
- if (res < 0) {
- rtnl_lock();
- down_write(&bonding_rwsem);
- bond_deinit(bond_dev);
- unregister_netdevice(bond_dev);
- goto out_rtnl;
- }
+ if (res < 0)
+ goto out_unreg;
return 0;
+out_unreg:
+ rtnl_lock();
+ down_write(&bonding_rwsem);
+ unregister_netdevice(bond_dev);
out_bond:
bond_deinit(bond_dev);
out_netdev:
adapter->params.info = ai;
adapter->params.nports = ai->nports0 + ai->nports1;
- adapter->params.chan_map = !!ai->nports0 | (!!ai->nports1 << 1);
+ adapter->params.chan_map = (!!ai->nports0) | (!!ai->nports1 << 1);
adapter->params.rev = t3_read_reg(adapter, A_PL_REV);
/*
* We used to only run the "adapter check task" once a second if
struct e1000_hw *hw = &adapter->hw;
u32 rctl, icr = er32(ICR);
- if (unlikely((!icr) || test_bit(__E1000_RESETTING, &adapter->flags)))
+ if (unlikely((!icr) || test_bit(__E1000_DOWN, &adapter->flags)))
return IRQ_NONE; /* Not our interrupt */
/* IMS will not auto-mask if INT_ASSERTED is not set, and if it is
#include <asm/io.h>
#define DRV_NAME "ehea"
-#define DRV_VERSION "EHEA_0100"
+#define DRV_VERSION "EHEA_0101"
/* eHEA capability flags */
#define DLPAR_PORT_ADD_REM 1
x &= (arr_len - 1);
pref = skb_array[x];
- prefetchw(pref);
- prefetchw(pref + EHEA_CACHE_LINE);
-
- pref = (skb_array[x]->data);
- prefetch(pref);
- prefetch(pref + EHEA_CACHE_LINE);
- prefetch(pref + EHEA_CACHE_LINE * 2);
- prefetch(pref + EHEA_CACHE_LINE * 3);
+ if (pref) {
+ prefetchw(pref);
+ prefetchw(pref + EHEA_CACHE_LINE);
+
+ pref = (skb_array[x]->data);
+ prefetch(pref);
+ prefetch(pref + EHEA_CACHE_LINE);
+ prefetch(pref + EHEA_CACHE_LINE * 2);
+ prefetch(pref + EHEA_CACHE_LINE * 3);
+ }
+
skb = skb_array[skb_index];
skb_array[skb_index] = NULL;
return skb;
x &= (arr_len - 1);
pref = skb_array[x];
- prefetchw(pref);
- prefetchw(pref + EHEA_CACHE_LINE);
+ if (pref) {
+ prefetchw(pref);
+ prefetchw(pref + EHEA_CACHE_LINE);
- pref = (skb_array[x]->data);
- prefetchw(pref);
- prefetchw(pref + EHEA_CACHE_LINE);
+ pref = (skb_array[x]->data);
+ prefetchw(pref);
+ prefetchw(pref + EHEA_CACHE_LINE);
+ }
skb = skb_array[wqe_index];
skb_array[wqe_index] = NULL;
struct work_struct tx_timeout_task;
struct napi_struct napi;
+ u8 oom;
u8 work_link;
u8 work_tx;
u8 work_tx_end;
u8 work_rx;
u8 work_rx_refill;
- u8 work_rx_oom;
int skb_size;
struct sk_buff_head rx_recycle;
dma_get_cache_alignment() - 1);
if (skb == NULL) {
- mp->work_rx_oom |= 1 << rxq->index;
+ mp->oom = 1;
goto oom;
}
spin_lock_bh(&mp->mib_counters_lock);
p->good_octets_received += mib_read(mp, 0x00);
- p->good_octets_received += (u64)mib_read(mp, 0x04) << 32;
p->bad_octets_received += mib_read(mp, 0x08);
p->internal_mac_transmit_err += mib_read(mp, 0x0c);
p->good_frames_received += mib_read(mp, 0x10);
p->frames_512_to_1023_octets += mib_read(mp, 0x30);
p->frames_1024_to_max_octets += mib_read(mp, 0x34);
p->good_octets_sent += mib_read(mp, 0x38);
- p->good_octets_sent += (u64)mib_read(mp, 0x3c) << 32;
p->good_frames_sent += mib_read(mp, 0x40);
p->excessive_collision += mib_read(mp, 0x44);
p->multicast_frames_sent += mib_read(mp, 0x48);
mp = container_of(napi, struct mv643xx_eth_private, napi);
- mp->work_rx_refill |= mp->work_rx_oom;
- mp->work_rx_oom = 0;
+ if (unlikely(mp->oom)) {
+ mp->oom = 0;
+ del_timer(&mp->rx_oom);
+ }
work_done = 0;
while (work_done < budget) {
continue;
}
- queue_mask = mp->work_tx | mp->work_tx_end |
- mp->work_rx | mp->work_rx_refill;
+ queue_mask = mp->work_tx | mp->work_tx_end | mp->work_rx;
+ if (likely(!mp->oom))
+ queue_mask |= mp->work_rx_refill;
+
if (!queue_mask) {
if (mv643xx_eth_collect_events(mp))
continue;
txq_maybe_wake(mp->txq + queue);
} else if (mp->work_rx & queue_mask) {
work_done += rxq_process(mp->rxq + queue, work_tbd);
- } else if (mp->work_rx_refill & queue_mask) {
+ } else if (!mp->oom && (mp->work_rx_refill & queue_mask)) {
work_done += rxq_refill(mp->rxq + queue, work_tbd);
} else {
BUG();
}
if (work_done < budget) {
- if (mp->work_rx_oom)
+ if (mp->oom)
mod_timer(&mp->rx_oom, jiffies + (HZ / 10));
napi_complete(napi);
wrlp(mp, INT_MASK, INT_TX_END | INT_RX | INT_EXT);
rxq_refill(mp->rxq + i, INT_MAX);
}
- if (mp->work_rx_oom) {
+ if (mp->oom) {
mp->rx_oom.expires = jiffies + (HZ / 10);
add_timer(&mp->rx_oom);
}
dev->ethtool_ops = &ne2k_pci_ethtool_ops;
NS8390_init(dev, 0);
+ memcpy(dev->dev_addr, SA_prom, 6);
+ memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
+
i = register_netdev(dev);
if (i)
goto err_out_free_netdev;
- for(i = 0; i < 6; i++)
- dev->dev_addr[i] = SA_prom[i];
printk("%s: %s found at %#lx, IRQ %d, %pM.\n",
dev->name, pci_clone_list[chip_idx].name, ioaddr, dev->irq,
dev->dev_addr);
- memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len);
-
return 0;
err_out_free_netdev:
struct netconsole_target *nt;
struct net_device *dev = ptr;
- if (!(event == NETDEV_CHANGENAME))
+ if (!(event == NETDEV_CHANGENAME || event == NETDEV_UNREGISTER))
goto done;
spin_lock_irqsave(&target_list_lock, flags);
case NETDEV_CHANGENAME:
strlcpy(nt->np.dev_name, dev->name, IFNAMSIZ);
break;
+ case NETDEV_UNREGISTER:
+ if (!nt->enabled)
+ break;
+ netpoll_cleanup(&nt->np);
+ nt->enabled = 0;
+ printk(KERN_INFO "netconsole: network logging stopped"
+ ", interface %s unregistered\n",
+ dev->name);
+ break;
}
}
netconsole_target_put(nt);
IEEE 802 "local assignment" bit is set in the address, a "usbX"
name is used instead.
+config USB_NET_CDC_EEM
+ tristate "CDC EEM support"
+ depends on USB_USBNET && EXPERIMENTAL
+ help
+ This option supports devices conforming to the Communication Device
+ Class (CDC) Ethernet Emulation Model, a specification that's easy to
+ implement in device firmware. The CDC EEM specifications are available
+ from <http://www.usb.org/>.
+
+ This driver creates an interface named "ethX", where X depends on
+ what other networking devices you have in use. However, if the
+ IEEE 802 "local assignment" bit is set in the address, a "usbX"
+ name is used instead.
+
config USB_NET_DM9601
tristate "Davicom DM9601 based USB 1.1 10/100 ethernet devices"
depends on USB_USBNET
obj-$(CONFIG_USB_HSO) += hso.o
obj-$(CONFIG_USB_NET_AX8817X) += asix.o
obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o
+obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o
obj-$(CONFIG_USB_NET_DM9601) += dm9601.o
obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o
obj-$(CONFIG_USB_NET_GL620A) += gl620a.o
--- /dev/null
+/*
+ * USB CDC EEM network interface driver
+ * Copyright (C) 2009 Oberthur Technologies
+ * by Omar Laazimani, Olivier Condemine
+ *
+ * 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/module.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ctype.h>
+#include <linux/ethtool.h>
+#include <linux/workqueue.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/crc32.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+
+
+/*
+ * This driver is an implementation of the CDC "Ethernet Emulation
+ * Model" (EEM) specification, which encapsulates Ethernet frames
+ * for transport over USB using a simpler USB device model than the
+ * previous CDC "Ethernet Control Model" (ECM, or "CDC Ethernet").
+ *
+ * For details, see www.usb.org/developers/devclass_docs/CDC_EEM10.pdf
+ *
+ * This version has been tested with GIGAntIC WuaoW SIM Smart Card on 2.6.24,
+ * 2.6.27 and 2.6.30rc2 kernel.
+ * It has also been validated on Openmoko Om 2008.12 (based on 2.6.24 kernel).
+ * build on 23-April-2009
+ */
+
+#define EEM_HEAD 2 /* 2 byte header */
+
+/*-------------------------------------------------------------------------*/
+
+static void eem_linkcmd_complete(struct urb *urb)
+{
+ dev_kfree_skb(urb->context);
+ usb_free_urb(urb);
+}
+
+static void eem_linkcmd(struct usbnet *dev, struct sk_buff *skb)
+{
+ struct urb *urb;
+ int status;
+
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb)
+ goto fail;
+
+ usb_fill_bulk_urb(urb, dev->udev, dev->out,
+ skb->data, skb->len, eem_linkcmd_complete, skb);
+
+ status = usb_submit_urb(urb, GFP_ATOMIC);
+ if (status) {
+ usb_free_urb(urb);
+fail:
+ dev_kfree_skb(skb);
+ devwarn(dev, "link cmd failure\n");
+ return;
+ }
+}
+
+static int eem_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+ int status = 0;
+
+ status = usbnet_get_endpoints(dev, intf);
+ if (status < 0) {
+ usb_set_intfdata(intf, NULL);
+ usb_driver_release_interface(driver_of(intf), intf);
+ return status;
+ }
+
+ /* no jumbogram (16K) support for now */
+
+ dev->net->hard_header_len += EEM_HEAD + ETH_FCS_LEN;
+
+ return 0;
+}
+
+/*
+ * EEM permits packing multiple Ethernet frames into USB transfers
+ * (a "bundle"), but for TX we don't try to do that.
+ */
+static struct sk_buff *eem_tx_fixup(struct usbnet *dev, struct sk_buff *skb,
+ gfp_t flags)
+{
+ struct sk_buff *skb2 = NULL;
+ u16 len = skb->len;
+ u32 crc = 0;
+ int padlen = 0;
+
+ /* When ((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket) is
+ * zero, stick two bytes of zero length EEM packet on the end.
+ * Else the framework would add invalid single byte padding,
+ * since it can't know whether ZLPs will be handled right by
+ * all the relevant hardware and software.
+ */
+ if (!((len + EEM_HEAD + ETH_FCS_LEN) % dev->maxpacket))
+ padlen += 2;
+
+ if (!skb_cloned(skb)) {
+ int headroom = skb_headroom(skb);
+ int tailroom = skb_tailroom(skb);
+
+ if ((tailroom >= ETH_FCS_LEN + padlen)
+ && (headroom >= EEM_HEAD))
+ goto done;
+
+ if ((headroom + tailroom)
+ > (EEM_HEAD + ETH_FCS_LEN + padlen)) {
+ skb->data = memmove(skb->head +
+ EEM_HEAD,
+ skb->data,
+ skb->len);
+ skb_set_tail_pointer(skb, len);
+ goto done;
+ }
+ }
+
+ skb2 = skb_copy_expand(skb, EEM_HEAD, ETH_FCS_LEN + padlen, flags);
+ if (!skb2)
+ return NULL;
+
+ dev_kfree_skb_any(skb);
+ skb = skb2;
+
+done:
+ /* we don't use the "no Ethernet CRC" option */
+ crc = crc32_le(~0, skb->data, skb->len);
+ crc = ~crc;
+
+ put_unaligned_le32(crc, skb_put(skb, 4));
+
+ /* EEM packet header format:
+ * b0..13: length of ethernet frame
+ * b14: bmCRC (1 == valid Ethernet CRC)
+ * b15: bmType (0 == data)
+ */
+ len = skb->len;
+ put_unaligned_le16(BIT(14) | len, skb_push(skb, 2));
+
+ /* Bundle a zero length EEM packet if needed */
+ if (padlen)
+ put_unaligned_le16(0, skb_put(skb, 2));
+
+ return skb;
+}
+
+static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+ /*
+ * Our task here is to strip off framing, leaving skb with one
+ * data frame for the usbnet framework code to process. But we
+ * may have received multiple EEM payloads, or command payloads.
+ * So we must process _everything_ as if it's a header, except
+ * maybe the last data payload
+ *
+ * REVISIT the framework needs updating so that when we consume
+ * all payloads (the last or only message was a command, or a
+ * zero length EEM packet) that is not accounted as an rx_error.
+ */
+ do {
+ struct sk_buff *skb2 = NULL;
+ u16 header;
+ u16 len = 0;
+
+ /* incomplete EEM header? */
+ if (skb->len < EEM_HEAD)
+ return 0;
+
+ /*
+ * EEM packet header format:
+ * b0..14: EEM type dependant (Data or Command)
+ * b15: bmType
+ */
+ header = get_unaligned_le16(skb->data);
+ skb_pull(skb, EEM_HEAD);
+
+ /*
+ * The bmType bit helps to denote when EEM
+ * packet is data or command :
+ * bmType = 0 : EEM data payload
+ * bmType = 1 : EEM (link) command
+ */
+ if (header & BIT(15)) {
+ u16 bmEEMCmd;
+
+ /*
+ * EEM (link) command packet:
+ * b0..10: bmEEMCmdParam
+ * b11..13: bmEEMCmd
+ * b14: bmReserved (must be 0)
+ * b15: 1 (EEM command)
+ */
+ if (header & BIT(14)) {
+ devdbg(dev, "reserved command %04x\n", header);
+ continue;
+ }
+
+ bmEEMCmd = (header >> 11) & 0x7;
+ switch (bmEEMCmd) {
+
+ /* Responding to echo requests is mandatory. */
+ case 0: /* Echo command */
+ len = header & 0x7FF;
+
+ /* bogus command? */
+ if (skb->len < len)
+ return 0;
+
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (unlikely(!skb2))
+ goto next;
+ skb_trim(skb2, len);
+ put_unaligned_le16(BIT(15) | (1 << 11) | len,
+ skb_push(skb2, 2));
+ eem_linkcmd(dev, skb2);
+ break;
+
+ /*
+ * Host may choose to ignore hints.
+ * - suspend: peripheral ready to suspend
+ * - response: suggest N millisec polling
+ * - response complete: suggest N sec polling
+ */
+ case 2: /* Suspend hint */
+ case 3: /* Response hint */
+ case 4: /* Response complete hint */
+ continue;
+
+ /*
+ * Hosts should never receive host-to-peripheral
+ * or reserved command codes; or responses to an
+ * echo command we didn't send.
+ */
+ case 1: /* Echo response */
+ case 5: /* Tickle */
+ default: /* reserved */
+ devwarn(dev, "unexpected link command %d\n",
+ bmEEMCmd);
+ continue;
+ }
+
+ } else {
+ u32 crc, crc2;
+ int is_last;
+
+ /* zero length EEM packet? */
+ if (header == 0)
+ continue;
+
+ /*
+ * EEM data packet header :
+ * b0..13: length of ethernet frame
+ * b14: bmCRC
+ * b15: 0 (EEM data)
+ */
+ len = header & 0x3FFF;
+
+ /* bogus EEM payload? */
+ if (skb->len < len)
+ return 0;
+
+ /* bogus ethernet frame? */
+ if (len < (ETH_HLEN + ETH_FCS_LEN))
+ goto next;
+
+ /*
+ * Treat the last payload differently: framework
+ * code expects our "fixup" to have stripped off
+ * headers, so "skb" is a data packet (or error).
+ * Else if it's not the last payload, keep "skb"
+ * for further processing.
+ */
+ is_last = (len == skb->len);
+ if (is_last)
+ skb2 = skb;
+ else {
+ skb2 = skb_clone(skb, GFP_ATOMIC);
+ if (unlikely(!skb2))
+ return 0;
+ }
+
+ crc = get_unaligned_le32(skb2->data
+ + len - ETH_FCS_LEN);
+ skb_trim(skb2, len - ETH_FCS_LEN);
+
+ /*
+ * The bmCRC helps to denote when the CRC field in
+ * the Ethernet frame contains a calculated CRC:
+ * bmCRC = 1 : CRC is calculated
+ * bmCRC = 0 : CRC = 0xDEADBEEF
+ */
+ if (header & BIT(14))
+ crc2 = ~crc32_le(~0, skb2->data, len);
+ else
+ crc2 = 0xdeadbeef;
+
+ if (is_last)
+ return crc == crc2;
+
+ if (unlikely(crc != crc2)) {
+ dev->stats.rx_errors++;
+ dev_kfree_skb_any(skb2);
+ } else
+ usbnet_skb_return(dev, skb2);
+ }
+
+next:
+ skb_pull(skb, len);
+ } while (skb->len);
+
+ return 1;
+}
+
+static const struct driver_info eem_info = {
+ .description = "CDC EEM Device",
+ .flags = FLAG_ETHER,
+ .bind = eem_bind,
+ .rx_fixup = eem_rx_fixup,
+ .tx_fixup = eem_tx_fixup,
+};
+
+/*-------------------------------------------------------------------------*/
+
+static const struct usb_device_id products[] = {
+{
+ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_EEM,
+ USB_CDC_PROTO_EEM),
+ .driver_info = (unsigned long) &eem_info,
+},
+{
+ /* EMPTY == end of list */
+},
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver eem_driver = {
+ .name = "cdc_eem",
+ .id_table = products,
+ .probe = usbnet_probe,
+ .disconnect = usbnet_disconnect,
+ .suspend = usbnet_suspend,
+ .resume = usbnet_resume,
+};
+
+
+static int __init eem_init(void)
+{
+ return usb_register(&eem_driver);
+}
+module_init(eem_init);
+
+static void __exit eem_exit(void)
+{
+ usb_deregister(&eem_driver);
+}
+module_exit(eem_exit);
+
+MODULE_AUTHOR("Omar Laazimani <omar.oberthur@gmail.com>");
+MODULE_DESCRIPTION("USB CDC EEM");
+MODULE_LICENSE("GPL");
if (netif_msg_ifup(dev))
devdbg(dev, "ID_REV = 0x%08x", read_buf);
+ /* Configure GPIO pins as LED outputs */
+ write_buf = LED_GPIO_CFG_SPD_LED | LED_GPIO_CFG_LNK_LED |
+ LED_GPIO_CFG_FDX_LED;
+ ret = smsc95xx_write_reg(dev, LED_GPIO_CFG, write_buf);
+ if (ret < 0) {
+ devwarn(dev, "Failed to write LED_GPIO_CFG register, ret=%d",
+ ret);
+ return ret;
+ }
+
/* Init Tx */
write_buf = 0;
ret = smsc95xx_write_reg(dev, FLOW, write_buf);
USB_DEVICE(0x0424, 0x9500),
.driver_info = (unsigned long) &smsc95xx_info,
},
+ {
+ /* SMSC9512/9514 USB Hub & Ethernet Device */
+ USB_DEVICE(0x0424, 0xec00),
+ .driver_info = (unsigned long) &smsc95xx_info,
+ },
{ }, /* END */
};
MODULE_DEVICE_TABLE(usb, products);
#define PM_CTL_WUPS_MULTI_ (0x00000003)
#define LED_GPIO_CFG (0x24)
+#define LED_GPIO_CFG_SPD_LED (0x01000000)
+#define LED_GPIO_CFG_LNK_LED (0x00100000)
+#define LED_GPIO_CFG_FDX_LED (0x00010000)
#define GPIO_CFG (0x28)
static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd,
struct scatterlist *data, int out, int in)
{
- struct scatterlist sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
+ struct scatterlist *s, sg[VIRTNET_SEND_COMMAND_SG_MAX + 2];
struct virtio_net_ctrl_hdr ctrl;
virtio_net_ctrl_ack status = ~0;
unsigned int tmp;
+ int i;
if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)) {
BUG(); /* Caller should know better */
sg_init_table(sg, out + in);
sg_set_buf(&sg[0], &ctrl, sizeof(ctrl));
- memcpy(&sg[1], data, sizeof(struct scatterlist) * (out + in - 2));
+ for_each_sg(data, s, out + in - 2, i)
+ sg_set_buf(&sg[i + 1], sg_virt(s), s->length);
sg_set_buf(&sg[out + in - 1], &status, sizeof(status));
if (vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) != 0)
promisc = ((dev->flags & IFF_PROMISC) != 0);
allmulti = ((dev->flags & IFF_ALLMULTI) != 0);
- sg_set_buf(sg, &promisc, sizeof(promisc));
+ sg_init_one(sg, &promisc, sizeof(promisc));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
VIRTIO_NET_CTRL_RX_PROMISC,
dev_warn(&dev->dev, "Failed to %sable promisc mode.\n",
promisc ? "en" : "dis");
- sg_set_buf(sg, &allmulti, sizeof(allmulti));
+ sg_init_one(sg, &allmulti, sizeof(allmulti));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX,
VIRTIO_NET_CTRL_RX_ALLMULTI,
return;
}
+ sg_init_table(sg, 2);
+
/* Store the unicast list and count in the front of the buffer */
mac_data->entries = dev->uc_count;
addr = dev->uc_list;
kfree(buf);
}
-static void virnet_vlan_rx_add_vid(struct net_device *dev, u16 vid)
+static void virtnet_vlan_rx_add_vid(struct net_device *dev, u16 vid)
{
struct virtnet_info *vi = netdev_priv(dev);
struct scatterlist sg;
- sg_set_buf(&sg, &vid, sizeof(vid));
+ sg_init_one(&sg, &vid, sizeof(vid));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
VIRTIO_NET_CTRL_VLAN_ADD, &sg, 1, 0))
dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid);
}
-static void virnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
+static void virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid)
{
struct virtnet_info *vi = netdev_priv(dev);
struct scatterlist sg;
- sg_set_buf(&sg, &vid, sizeof(vid));
+ sg_init_one(&sg, &vid, sizeof(vid));
if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN,
VIRTIO_NET_CTRL_VLAN_DEL, &sg, 1, 0))
.ndo_set_mac_address = virtnet_set_mac_address,
.ndo_set_rx_mode = virtnet_set_rx_mode,
.ndo_change_mtu = virtnet_change_mtu,
- .ndo_vlan_rx_add_vid = virnet_vlan_rx_add_vid,
- .ndo_vlan_rx_kill_vid = virnet_vlan_rx_kill_vid,
+ .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid,
+ .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid,
#ifdef CONFIG_NET_POLL_CONTROLLER
.ndo_poll_controller = virtnet_netpoll,
#endif
for (b = 0; b < IEEE80211_NUM_BANDS; b++) {
struct ieee80211_supported_band *band = &sc->sbands[b];
- char bname[5];
+ char bname[6];
switch (band->band) {
case IEEE80211_BAND_2GHZ:
strcpy(bname, "2 GHz");
IWL_DEBUG_SCAN(priv, "SCAN complete scan\n");
+ ieee80211_scan_completed(priv->hw, false);
+
if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return;
- ieee80211_scan_completed(priv->hw, false);
-
/* Since setting the TXPOWER may have been deferred while
* performing the scan, fire one off */
mutex_lock(&priv->mutex);
rxq->free_count = 0;
spin_unlock_irqrestore(&rxq->lock, flags);
}
-EXPORT_SYMBOL(iwl3945_rx_queue_reset);
/*
* this should be called while priv->lock is locked
mutex_init(&priv->command_lock);
spin_lock_init(&priv->stats_lock);
+ /* because rndis_command() sleeps we need to use workqueue */
+ priv->workqueue = create_singlethread_workqueue("rndis_wlan");
+ INIT_WORK(&priv->work, rndis_wext_worker);
+ INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
+
/* try bind rndis_host */
retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS);
if (retval < 0)
disassociate(usbdev, 1);
netif_carrier_off(usbdev->net);
- /* because rndis_command() sleeps we need to use workqueue */
- priv->workqueue = create_singlethread_workqueue("rndis_wlan");
- INIT_DELAYED_WORK(&priv->stats_work, rndis_update_wireless_stats);
queue_delayed_work(priv->workqueue, &priv->stats_work,
round_jiffies_relative(STATS_UPDATE_JIFFIES));
- INIT_WORK(&priv->work, rndis_wext_worker);
return 0;
fail:
+ cancel_delayed_work_sync(&priv->stats_work);
+ cancel_work_sync(&priv->work);
+ flush_workqueue(priv->workqueue);
+ destroy_workqueue(priv->workqueue);
+
kfree(priv);
return retval;
}
ccw_device_set_online(adapter->ccw_device);
zfcp_erp_wait(adapter);
- wait_event(adapter->erp_done_wqh,
- !(atomic_read(&unit->status) &
- ZFCP_STATUS_UNIT_SCSI_WORK_PENDING));
+ flush_work(&unit->scsi_work);
down(&zfcp_data.config_sema);
zfcp_unit_put(unit);
atomic_set(&unit->refcount, 0);
init_waitqueue_head(&unit->remove_wq);
+ INIT_WORK(&unit->scsi_work, zfcp_scsi_scan);
unit->port = port;
unit->fcp_lun = fcp_lun;
atomic_clear_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status);
+ zfcp_fc_nameserver_init(adapter);
+
if (!zfcp_adapter_scsi_register(adapter))
return 0;
cancel_work_sync(&adapter->scan_work);
cancel_work_sync(&adapter->stat_work);
- cancel_delayed_work_sync(&adapter->nsp.work);
zfcp_adapter_scsi_unregister(adapter);
sysfs_remove_group(&adapter->ccw_device->dev.kobj,
&zfcp_sysfs_adapter_attrs);
list_del(&port->list);
write_unlock_irq(&zfcp_data.config_lock);
if (port->rport)
- fc_remote_port_delete(port->rport);
- port->rport = NULL;
+ port->rport->dd_data = NULL;
zfcp_adapter_put(port->adapter);
sysfs_remove_group(&port->sysfs_device.kobj, &zfcp_sysfs_port_attrs);
device_unregister(&port->sysfs_device);
/* initialize request counter */
BUG_ON(!zfcp_reqlist_isempty(adapter));
adapter->req_no = 0;
- zfcp_fc_nameserver_init(adapter);
zfcp_erp_modify_adapter_status(adapter, "ccsonl1", NULL,
ZFCP_STATUS_COMMON_RUNNING, ZFCP_SET);
* Userspace interface for accessing the
* Access Control Lists / Control File Data Channel
*
- * Copyright IBM Corporation 2008
+ * Copyright IBM Corporation 2008, 2009
*/
#define KMSG_COMPONENT "zfcp"
retval = -ENXIO;
goto free_buffer;
}
+ zfcp_adapter_get(adapter);
retval = zfcp_cfdc_sg_setup(data->command, fsf_cfdc->sg,
data_user->control_file);
/* logical unit status */
#define ZFCP_STATUS_UNIT_SHARED 0x00000004
#define ZFCP_STATUS_UNIT_READONLY 0x00000008
-#define ZFCP_STATUS_UNIT_SCSI_WORK_PENDING 0x00000020
/* FSF request status (this does not have a common part) */
#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT 0x00000002
struct zfcp_erp_action erp_action; /* pending error recovery */
atomic_t erp_counter;
struct zfcp_latencies latencies;
+ struct work_struct scsi_work;
};
/* FSF request */
zfcp_qdio_close(adapter);
zfcp_fsf_req_dismiss_all(adapter);
adapter->fsf_req_seq_no = 0;
+ zfcp_fc_wka_port_force_offline(&adapter->nsp);
/* all ports and units are closed */
zfcp_erp_modify_adapter_status(adapter, "erascl1", NULL,
ZFCP_STATUS_COMMON_OPEN, ZFCP_CLEAR);
}
}
-struct zfcp_erp_add_work {
- struct zfcp_unit *unit;
- struct work_struct work;
-};
-
-static void zfcp_erp_scsi_scan(struct work_struct *work)
-{
- struct zfcp_erp_add_work *p =
- container_of(work, struct zfcp_erp_add_work, work);
- struct zfcp_unit *unit = p->unit;
- struct fc_rport *rport = unit->port->rport;
-
- if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
- scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
- scsilun_to_int((struct scsi_lun *)&unit->fcp_lun), 0);
- atomic_clear_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
- zfcp_unit_put(unit);
- wake_up(&unit->port->adapter->erp_done_wqh);
- kfree(p);
-}
-
-static void zfcp_erp_schedule_work(struct zfcp_unit *unit)
-{
- struct zfcp_erp_add_work *p;
-
- p = kzalloc(sizeof(*p), GFP_KERNEL);
- if (!p) {
- dev_err(&unit->port->adapter->ccw_device->dev,
- "Registering unit 0x%016Lx on port 0x%016Lx failed\n",
- (unsigned long long)unit->fcp_lun,
- (unsigned long long)unit->port->wwpn);
- return;
- }
-
- zfcp_unit_get(unit);
- atomic_set_mask(ZFCP_STATUS_UNIT_SCSI_WORK_PENDING, &unit->status);
- INIT_WORK(&p->work, zfcp_erp_scsi_scan);
- p->unit = unit;
- if (!queue_work(zfcp_data.work_queue, &p->work))
- zfcp_unit_put(unit);
-}
-
static void zfcp_erp_action_cleanup(struct zfcp_erp_action *act, int result)
{
struct zfcp_adapter *adapter = act->adapter;
switch (act->action) {
case ZFCP_ERP_ACTION_REOPEN_UNIT:
- flush_work(&port->rport_work);
if ((result == ZFCP_ERP_SUCCEEDED) && !unit->device) {
- if (!(atomic_read(&unit->status) &
- ZFCP_STATUS_UNIT_SCSI_WORK_PENDING))
- zfcp_erp_schedule_work(unit);
+ zfcp_unit_get(unit);
+ if (scsi_queue_work(unit->port->adapter->scsi_host,
+ &unit->scsi_work) <= 0)
+ zfcp_unit_put(unit);
}
zfcp_unit_put(unit);
break;
while (!(atomic_read(&adapter->status) &
ZFCP_STATUS_ADAPTER_ERP_THREAD_KILL)) {
+
+ zfcp_rec_dbf_event_thread_lock("erthrd1", adapter);
+ ignore = down_interruptible(&adapter->erp_ready_sem);
+ zfcp_rec_dbf_event_thread_lock("erthrd2", adapter);
+
write_lock_irqsave(&adapter->erp_lock, flags);
next = adapter->erp_ready_head.next;
write_unlock_irqrestore(&adapter->erp_lock, flags);
if (zfcp_erp_strategy(act) != ZFCP_ERP_DISMISSED)
zfcp_erp_wakeup(adapter);
}
-
- zfcp_rec_dbf_event_thread_lock("erthrd1", adapter);
- ignore = down_interruptible(&adapter->erp_ready_sem);
- zfcp_rec_dbf_event_thread_lock("erthrd2", adapter);
}
atomic_clear_mask(ZFCP_STATUS_ADAPTER_ERP_THREAD_UP, &adapter->status);
extern void zfcp_test_link(struct zfcp_port *);
extern void zfcp_fc_link_test_work(struct work_struct *);
extern void zfcp_fc_nameserver_init(struct zfcp_adapter *);
+extern void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *);
/* zfcp_fsf.c */
extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
extern void zfcp_scsi_schedule_rport_block(struct zfcp_port *);
extern void zfcp_scsi_schedule_rports_block(struct zfcp_adapter *);
+extern void zfcp_scsi_scan(struct work_struct *);
/* zfcp_sysfs.c */
extern struct attribute_group zfcp_sysfs_unit_attrs;
struct zfcp_wka_port *wka_port =
container_of(dw, struct zfcp_wka_port, work);
- /* Don't wait forvever. If the wka_port is too busy take it offline
- through a new call later */
- if (!wait_event_timeout(wka_port->completion_wq,
- atomic_read(&wka_port->refcount) == 0,
- HZ >> 1))
- return;
-
mutex_lock(&wka_port->mutex);
if ((atomic_read(&wka_port->refcount) != 0) ||
(wka_port->status != ZFCP_WKA_PORT_ONLINE))
INIT_DELAYED_WORK(&wka_port->work, zfcp_wka_port_offline);
}
+void zfcp_fc_wka_port_force_offline(struct zfcp_wka_port *wka)
+{
+ cancel_delayed_work_sync(&wka->work);
+ mutex_lock(&wka->mutex);
+ wka->status = ZFCP_WKA_PORT_OFFLINE;
+ mutex_unlock(&wka->mutex);
+}
+
static void _zfcp_fc_incoming_rscn(struct zfcp_fsf_req *fsf_req, u32 range,
struct fcp_rscn_element *elem)
{
if (adisc->els.status) {
/* request rejected or timed out */
- zfcp_erp_port_forced_reopen(port, 0, "fcadh_1", NULL);
+ zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
+ "fcadh_1", NULL);
goto out;
}
container_of(work, struct zfcp_port, test_link_work);
int retval;
- if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_UNBLOCKED)) {
- zfcp_port_put(port);
- return; /* port erp is running and will update rport status */
- }
-
zfcp_port_get(port);
port->rport_task = RPORT_DEL;
zfcp_scsi_rport_work(&port->rport_work);
{
struct zfcp_adapter *adapter = port->adapter;
+ if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC))
+ return;
+
atomic_clear_mask(ZFCP_STATUS_COMMON_NOESC, &port->status);
if ((port->supported_classes != 0) ||
if (acc->wwpn == fc_host_port_name(adapter->scsi_host))
continue;
port = zfcp_get_port_by_wwpn(adapter, acc->wwpn);
- if (port) {
- zfcp_port_get(port);
+ if (port)
continue;
- }
port = zfcp_port_enqueue(adapter, acc->wwpn,
ZFCP_STATUS_COMMON_NOESC, d_id);
max_entries = chain ? ZFCP_GPN_FT_MAX_ENTRIES : ZFCP_GPN_FT_ENTRIES;
max_bytes = chain ? ZFCP_GPN_FT_MAX_SIZE : ZFCP_CT_SIZE_ONE_PAGE;
- if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT)
+ if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT &&
+ fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
return 0;
ret = zfcp_wka_port_get(&adapter->nsp);
struct fsf_link_down_info *link_down)
{
struct zfcp_adapter *adapter = req->adapter;
+ unsigned long flags;
if (atomic_read(&adapter->status) & ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED)
return;
atomic_set_mask(ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED, &adapter->status);
+
+ read_lock_irqsave(&zfcp_data.config_lock, flags);
zfcp_scsi_schedule_rports_block(adapter);
+ read_unlock_irqrestore(&zfcp_data.config_lock, flags);
if (!link_down)
goto out;
}
}
-static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
- __releases(&adapter->req_q_lock)
- __acquires(&adapter->req_q_lock)
+static int zfcp_fsf_sbal_check(struct zfcp_adapter *adapter)
{
struct zfcp_qdio_queue *req_q = &adapter->req_q;
- long ret;
- if (atomic_read(&req_q->count) <= -REQUEST_LIST_SIZE)
- return -EIO;
- if (atomic_read(&req_q->count) > 0)
- return 0;
+ spin_lock_bh(&adapter->req_q_lock);
+ if (atomic_read(&req_q->count))
+ return 1;
+ spin_unlock_bh(&adapter->req_q_lock);
+ return 0;
+}
+
+static int zfcp_fsf_req_sbal_get(struct zfcp_adapter *adapter)
+{
+ long ret;
- atomic_dec(&req_q->count);
spin_unlock_bh(&adapter->req_q_lock);
ret = wait_event_interruptible_timeout(adapter->request_wq,
- atomic_read(&req_q->count) >= 0,
- 5 * HZ);
- spin_lock_bh(&adapter->req_q_lock);
- atomic_inc(&req_q->count);
-
+ zfcp_fsf_sbal_check(adapter), 5 * HZ);
if (ret > 0)
return 0;
if (!ret)
atomic_inc(&adapter->qdio_outb_full);
+
+ spin_lock_bh(&adapter->req_q_lock);
return -EIO;
}
static int zfcp_fsf_req_send(struct zfcp_fsf_req *req)
{
struct zfcp_adapter *adapter = req->adapter;
- unsigned long flags;
- int idx;
+ unsigned long flags;
+ int idx;
+ int with_qtcb = (req->qtcb != NULL);
/* put allocated FSF request into hash table */
spin_lock_irqsave(&adapter->req_list_lock, flags);
}
/* Don't increase for unsolicited status */
- if (req->qtcb)
+ if (with_qtcb)
adapter->fsf_req_seq_no++;
adapter->req_no++;
spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
- goto out;
+ goto out_unlock;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA,
0, NULL);
if (IS_ERR(req)) {
retval = PTR_ERR(req);
- goto out;
+ goto out_unlock;
}
sbale = zfcp_qdio_sbale_req(req);
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
-out:
spin_unlock_bh(&adapter->req_q_lock);
if (!retval)
wait_event(req->completion_wq,
req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
zfcp_fsf_req_free(req);
+ return retval;
+out_unlock:
+ spin_unlock_bh(&adapter->req_q_lock);
return retval;
}
spin_lock_bh(&adapter->req_q_lock);
if (zfcp_fsf_req_sbal_get(adapter))
- goto out;
+ goto out_unlock;
req = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, 0,
NULL);
if (IS_ERR(req)) {
retval = PTR_ERR(req);
- goto out;
+ goto out_unlock;
}
if (data)
req->handler = zfcp_fsf_exchange_port_data_handler;
zfcp_fsf_start_timer(req, ZFCP_FSF_REQUEST_TIMEOUT);
retval = zfcp_fsf_req_send(req);
-out:
spin_unlock_bh(&adapter->req_q_lock);
+
if (!retval)
wait_event(req->completion_wq,
req->status & ZFCP_STATUS_FSFREQ_COMPLETED);
zfcp_fsf_req_free(req);
return retval;
+
+out_unlock:
+ spin_unlock_bh(&adapter->req_q_lock);
+ return retval;
}
static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
static void zfcp_fsf_control_file_handler(struct zfcp_fsf_req *req)
{
- if (req->qtcb->header.fsf_status != FSF_GOOD)
- req->status |= ZFCP_STATUS_FSFREQ_ERROR;
}
/**
write_unlock_irqrestore(&adapter->abort_lock, flags);
zfcp_scsi_dbf_event_abort("lte1", adapter, scpnt, NULL,
old_req_id);
- return SUCCESS;
+ return FAILED; /* completion could be in progress */
}
old_req->data = NULL;
*/
static void zfcp_scsi_dev_loss_tmo_callbk(struct fc_rport *rport)
{
- struct zfcp_port *port = rport->dd_data;
+ struct zfcp_port *port;
write_lock_irq(&zfcp_data.config_lock);
- port->rport = NULL;
+ port = rport->dd_data;
+ if (port)
+ port->rport = NULL;
write_unlock_irq(&zfcp_data.config_lock);
}
*/
static void zfcp_scsi_terminate_rport_io(struct fc_rport *rport)
{
- struct zfcp_port *port = rport->dd_data;
+ struct zfcp_port *port;
+
+ write_lock_irq(&zfcp_data.config_lock);
+ port = rport->dd_data;
+ if (port)
+ zfcp_port_get(port);
+ write_unlock_irq(&zfcp_data.config_lock);
- zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
+ if (port) {
+ zfcp_erp_port_reopen(port, 0, "sctrpi1", NULL);
+ zfcp_port_put(port);
+ }
}
static void zfcp_scsi_rport_register(struct zfcp_port *port)
static void zfcp_scsi_rport_block(struct zfcp_port *port)
{
- if (port->rport)
- fc_remote_port_delete(port->rport);
+ struct fc_rport *rport = port->rport;
+
+ if (rport)
+ fc_remote_port_delete(rport);
}
void zfcp_scsi_schedule_rport_register(struct zfcp_port *port)
}
+void zfcp_scsi_scan(struct work_struct *work)
+{
+ struct zfcp_unit *unit = container_of(work, struct zfcp_unit,
+ scsi_work);
+ struct fc_rport *rport;
+
+ flush_work(&unit->port->rport_work);
+ rport = unit->port->rport;
+
+ if (rport && rport->port_state == FC_PORTSTATE_ONLINE)
+ scsi_scan_target(&rport->dev, 0, rport->scsi_target_id,
+ scsilun_to_int((struct scsi_lun *)
+ &unit->fcp_lun), 0);
+
+ zfcp_unit_put(unit);
+}
+
struct fc_function_template zfcp_transport_functions = {
.show_starget_port_id = 1,
.show_starget_port_name = 1,
write_lock_irq(&zfcp_data.config_lock);
unit = zfcp_get_unit_by_lun(port, fcp_lun);
- if (unit && (atomic_read(&unit->refcount) == 0)) {
- zfcp_unit_get(unit);
- atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &unit->status);
- list_move(&unit->list, &unit_remove_lh);
- } else
- unit = NULL;
+ if (unit) {
+ write_unlock_irq(&zfcp_data.config_lock);
+ /* wait for possible timeout during SCSI probe */
+ flush_work(&unit->scsi_work);
+ write_lock_irq(&zfcp_data.config_lock);
+
+ if (atomic_read(&unit->refcount) == 0) {
+ zfcp_unit_get(unit);
+ atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE,
+ &unit->status);
+ list_move(&unit->list, &unit_remove_lh);
+ } else {
+ unit = NULL;
+ }
+ }
write_unlock_irq(&zfcp_data.config_lock);
#include "cxgb3i_offload.h"
#include "cxgb3i_ddp.h"
-#define CXGB3I_SCSI_QDEPTH_DFLT 128
+#define CXGB3I_SCSI_HOST_QDEPTH 1024
#define CXGB3I_MAX_TARGET CXGB3I_MAX_CONN
#define CXGB3I_MAX_LUN 512
#define ISCSI_PDU_NONPAYLOAD_MAX \
}
static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp,
- int start, int max, int count,
+ unsigned int start, unsigned int max,
+ unsigned int count,
struct cxgb3i_gather_list *gl)
{
- unsigned int i, j;
+ unsigned int i, j, k;
+ /* not enough entries */
+ if ((max - start) < count)
+ return -EBUSY;
+
+ max -= count;
spin_lock(&ddp->map_lock);
- for (i = start; i <= max;) {
- for (j = 0; j < count; j++) {
- if (ddp->gl_map[i + j])
+ for (i = start; i < max;) {
+ for (j = 0, k = i; j < count; j++, k++) {
+ if (ddp->gl_map[k])
break;
}
if (j == count) {
- for (j = 0; j < count; j++)
- ddp->gl_map[i + j] = gl;
+ for (j = 0, k = i; j < count; j++, k++)
+ ddp->gl_map[k] = gl;
spin_unlock(&ddp->map_lock);
return i;
}
struct cxgb3i_ddp_info *ddp = tdev->ulp_iscsi;
struct pagepod_hdr hdr;
unsigned int npods;
- int idx = -1, idx_max;
+ int idx = -1;
int err = -ENOMEM;
u32 sw_tag = *tagp;
u32 tag;
}
npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
- idx_max = ddp->nppods - npods + 1;
if (ddp->idx_last == ddp->nppods)
- idx = ddp_find_unused_entries(ddp, 0, idx_max, npods, gl);
+ idx = ddp_find_unused_entries(ddp, 0, ddp->nppods, npods, gl);
else {
idx = ddp_find_unused_entries(ddp, ddp->idx_last + 1,
- idx_max, npods, gl);
- if (idx < 0 && ddp->idx_last >= npods)
+ ddp->nppods, npods, gl);
+ if (idx < 0 && ddp->idx_last >= npods) {
idx = ddp_find_unused_entries(ddp, 0,
- ddp->idx_last - npods + 1,
+ min(ddp->idx_last + npods, ddp->nppods),
npods, gl);
+ }
}
if (idx < 0) {
ddp_log_debug("xferlen %u, gl %u, npods %u NO DDP.\n",
.proc_name = "cxgb3i",
.queuecommand = iscsi_queuecommand,
.change_queue_depth = iscsi_change_queue_depth,
- .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1,
+ .can_queue = CXGB3I_SCSI_HOST_QDEPTH,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
- .cmd_per_lun = CXGB3I_SCSI_QDEPTH_DFLT,
+ .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
.eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_target_reset,
+ .target_alloc = iscsi_target_alloc,
.use_clustering = DISABLE_CLUSTERING,
.this_id = -1,
};
c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n",
c3cn, c3cn->write_seq, c3cn->snd_una,
cxgb3_snd_win);
- err = -EAGAIN;
+ err = -ENOBUFS;
goto out_err;
}
out_err:
if (copied == 0 && err == -EPIPE)
copied = c3cn->err ? c3cn->err : -EPIPE;
+ else
+ copied = err;
goto done;
}
return 0;
}
- if (err < 0 && err != -EAGAIN) {
- kfree_skb(skb);
- cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
- task->itt, skb, skb->len, skb->data_len, err);
- iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
- iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+ if (err == -EAGAIN || err == -ENOBUFS) {
+ /* reset skb to send when we are called again */
+ tdata->skb = skb;
return err;
}
- /* reset skb to send when we are called again */
- tdata->skb = skb;
- return -EAGAIN;
+
+ kfree_skb(skb);
+ cxgb3i_tx_debug("itt 0x%x, skb 0x%p, len %u/%u, xmit err %d.\n",
+ task->itt, skb, skb->len, skb->data_len, err);
+ iscsi_conn_printk(KERN_ERR, task->conn, "xmit err %d.\n", err);
+ iscsi_conn_failure(task->conn, ISCSI_ERR_XMIT_FAILED);
+ return err;
}
int cxgb3i_pdu_init(void)
DEFINE_TIMER(fcoe_timer, NULL, 0, 0);
DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
-/* Function Prototyes */
+/* Function Prototypes */
static int fcoe_reset(struct Scsi_Host *shost);
static int fcoe_xmit(struct fc_lport *, struct fc_frame *);
static int fcoe_rcv(struct sk_buff *, struct net_device *,
/**
* fcoe_lport_config() - sets up the fc_lport
* @lp: ptr to the fc_lport
- * @shost: ptr to the parent scsi host
*
* Returns: 0 for success
*/
rtnl_lock();
memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
+ dev_mc_add(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
rtnl_unlock();
/*
dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
rtnl_unlock();
- /* Free the per-CPU revieve threads */
+ /* Free the per-CPU receive threads */
fcoe_percpu_clean(lp);
/* Free existing skbs */
}
#else
/*
- * This a non-SMP scenario where the singluar Rx thread is
+ * This a non-SMP scenario where the singular Rx thread is
* being removed. Free all skbs and stop the thread.
*/
spin_lock_bh(&p->fcoe_rx_list.lock);
* @skb: the receive skb
* @dev: associated net device
* @ptype: context
- * @odldev: last device
+ * @olddev: last device
*
* this function will receive the packet and build fc frame and pass it up
*
kfree_skb(skb);
return -1;
}
-EXPORT_SYMBOL_GPL(fcoe_rcv);
/**
* fcoe_start_io() - pass to netdev to start xmit for fcoe
}
/**
- * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof
+ * fcoe_get_paged_crc_eof() - in case we need to alloc a page for crc_eof
* @skb: the skb to be xmitted
* @tlen: total len
*
/**
* fcoe_fc_crc() - calculates FC CRC in this fcoe skb
- * @fp: the fc_frame containg data to be checksummed
+ * @fp: the fc_frame containing data to be checksummed
*
* This uses crc32() to calculate the crc for fc frame
* Return : 32 bit crc
wlen = skb->len / FCOE_WORD_TO_BYTE;
if (!lp->link_up) {
- kfree(skb);
+ kfree_skb(skb);
return 0;
}
cp = NULL;
}
- /* adjust skb netowrk/transport offsets to match mac/fcoe/fc */
+ /* adjust skb network/transport offsets to match mac/fcoe/fc */
skb_push(skb, elen + hlen);
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
return 0;
}
-EXPORT_SYMBOL_GPL(fcoe_xmit);
/**
* fcoe_percpu_receive_thread() - recv thread per cpu
/**
- * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue
- * @lp: the fc_port for this skb
- * @skb: the associated skb to be xmitted
+ * fcoe_check_wait_queue() - attempt to clear the transmit backlog
+ * @lp: the fc_lport
*
* This empties the wait_queue, dequeue the head of the wait_queue queue
* and calls fcoe_start_io() for each packet, if all skb have been
* transmitted, return qlen or -1 if a error occurs, then restore
- * wait_queue and try again later.
+ * wait_queue and try again later.
*
* The wait_queue is used when the skb transmit fails. skb will go
- * in the wait_queue which will be emptied by the time function OR
+ * in the wait_queue which will be emptied by the timer function or
* by the next skb transmit.
*
* Returns: 0 for success
*/
static void fcoe_dev_setup()
{
- /*
- * here setup a interface specific wd time to
- * monitor the link state
- */
register_netdevice_notifier(&fcoe_notifier);
}
/**
* fcoe_if_to_netdev() - parse a name buffer to get netdev
- * @ifname: fixed array for output parsed ifname
* @buffer: incoming buffer to be copied
*
- * Returns: NULL or ptr to netdeive
+ * Returns: NULL or ptr to net_device
*/
static struct net_device *fcoe_if_to_netdev(const char *buffer)
{
}
/**
- * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev
+ * fcoe_netdev_to_module_owner() - finds out the driver module of the netdev
* @netdev: the target netdev
*
* Returns: ptr to the struct module, NULL for failure
* Holds the Ethernet driver module by try_module_get() for
* the corresponding netdev.
*
- * Returns: 0 for succsss
+ * Returns: 0 for success
*/
static int fcoe_ethdrv_get(const struct net_device *netdev)
{
* Releases the Ethernet driver module by module_put for
* the corresponding netdev.
*
- * Returns: 0 for succsss
+ * Returns: 0 for success
*/
static int fcoe_ethdrv_put(const struct net_device *netdev)
{
/**
* fcoe_destroy() - handles the destroy from sysfs
- * @buffer: expcted to be a eth if name
+ * @buffer: expected to be an eth if name
* @kp: associated kernel param
*
* Returns: 0 for success
/**
* fcoe_create() - Handles the create call from sysfs
- * @buffer: expcted to be a eth if name
+ * @buffer: expected to be an eth if name
* @kp: associated kernel param
*
* Returns: 0 for success
return rc;
}
-EXPORT_SYMBOL_GPL(fcoe_link_ok);
/**
* fcoe_percpu_clean() - Clear the pending skbs for an lport
spin_unlock_bh(&pp->fcoe_rx_list.lock);
}
}
-EXPORT_SYMBOL_GPL(fcoe_percpu_clean);
/**
* fcoe_clean_pending_queue() - Dequeue a skb and free it
}
spin_unlock_bh(&fc->fcoe_pending_queue.lock);
}
-EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
/**
* fcoe_reset() - Resets the fcoe
fc_lport_reset(lport);
return 0;
}
-EXPORT_SYMBOL_GPL(fcoe_reset);
/**
* fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device
- * @device: this is currently ptr to net_device
+ * @dev: this is currently ptr to net_device
*
* Returns: NULL or the located fcoe_softc
*/
return (fc) ? fc->ctlr.lp : NULL;
}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup);
/**
* fcoe_hostlist_add() - Add a lport to lports list
- * @lp: ptr to the fc_lport to badded
+ * @lp: ptr to the fc_lport to be added
*
* Returns: 0 for success
*/
}
return 0;
}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_add);
/**
* fcoe_hostlist_remove() - remove a lport from lports list
- * @lp: ptr to the fc_lport to badded
+ * @lp: ptr to the fc_lport to be removed
*
* Returns: 0 for success
*/
return 0;
}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_remove);
/**
* fcoe_init() - fcoe module loading initialization
}
/**
- * fcoe_ctrl_destroy() - Disable and tear-down the FCoE controller.
+ * fcoe_ctlr_destroy() - Disable and tear-down the FCoE controller.
* @fip: FCoE controller.
*
* This is called by FCoE drivers before freeing the &fcoe_ctlr.
{
struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) sdev->host->hostdata;
struct ipr_resource_entry *res;
+ struct ata_port *ap = NULL;
unsigned long lock_flags = 0;
spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags);
}
if (ipr_is_vset_device(res) || ipr_is_scsi_disk(res))
sdev->allow_restart = 1;
- if (ipr_is_gata(res) && res->sata_port) {
+ if (ipr_is_gata(res) && res->sata_port)
+ ap = res->sata_port->ap;
+ spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
+
+ if (ap) {
scsi_adjust_queue_depth(sdev, 0, IPR_MAX_CMD_PER_ATA_LUN);
- ata_sas_slave_configure(sdev, res->sata_port->ap);
- } else {
+ ata_sas_slave_configure(sdev, ap);
+ } else
scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
- }
+ return 0;
}
spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
return 0;
}
if (err) {
- iscsi_conn_failure(conn, err);
+ /* got invalid offset/len */
return -EIO;
}
return 0;
.use_clustering = DISABLE_CLUSTERING,
.slave_alloc = iscsi_sw_tcp_slave_alloc,
.slave_configure = iscsi_sw_tcp_slave_configure,
+ .target_alloc = iscsi_target_alloc,
.proc_name = "iscsi_tcp",
.this_id = -1,
};
lport->tt.rport_logoff(rport);
}
+ list_for_each_entry_safe(rdata, next, &disc->rogue_rports, peers) {
+ rport = PRIV_TO_RPORT(rdata);
+ lport->tt.rport_logoff(rport);
+ }
+
mutex_unlock(&disc->disc_mutex);
}
{
struct fc_rport_libfc_priv *rdata = rport->dd_data;
struct fc_disc *disc = &lport->disc;
- int found = 0;
FC_DEBUG_DISC("Received a %d event for port (%6x)\n", event,
rport->port_id);
- if (event == RPORT_EV_CREATED) {
+ switch (event) {
+ case RPORT_EV_CREATED:
if (disc) {
- found = 1;
mutex_lock(&disc->disc_mutex);
list_add_tail(&rdata->peers, &disc->rports);
mutex_unlock(&disc->disc_mutex);
}
+ break;
+ case RPORT_EV_LOGO:
+ case RPORT_EV_FAILED:
+ case RPORT_EV_STOP:
+ mutex_lock(&disc->disc_mutex);
+ mutex_lock(&rdata->rp_mutex);
+ if (rdata->trans_state == FC_PORTSTATE_ROGUE)
+ list_del(&rdata->peers);
+ mutex_unlock(&rdata->rp_mutex);
+ mutex_unlock(&disc->disc_mutex);
+ break;
+ default:
+ break;
}
- if (!found)
- FC_DEBUG_DISC("The rport (%6x) is not maintained "
- "by the discovery layer\n", rport->port_id);
}
/**
rdata = rport->dd_data;
rdata->ops = &fc_disc_rport_ops;
rdata->rp_state = RPORT_ST_INIT;
+ list_add_tail(&rdata->peers, &disc->rogue_rports);
lport->tt.rport_login(rport);
}
}
/**
* fc_disc_done() - Discovery has been completed
* @disc: FC discovery context
+ * Locking Note: This function expects that the disc mutex is locked before
+ * it is called. The discovery callback is then made with the lock released,
+ * and the lock is re-taken before returning from this function
*/
static void fc_disc_done(struct fc_disc *disc)
{
struct fc_lport *lport = disc->lport;
+ enum fc_disc_event event;
FC_DEBUG_DISC("Discovery complete for port (%6x)\n",
fc_host_port_id(lport->host));
- disc->disc_callback(lport, disc->event);
+ event = disc->event;
disc->event = DISC_EV_NONE;
if (disc->requested)
fc_disc_gpn_ft_req(disc);
else
disc->pending = 0;
+
+ mutex_unlock(&disc->disc_mutex);
+ disc->disc_callback(lport, event);
+ mutex_lock(&disc->disc_mutex);
}
/**
rdata = rport->dd_data;
rdata->ops = &fc_disc_rport_ops;
rdata->local_port = lport;
+ list_add_tail(&rdata->peers,
+ &disc->rogue_rports);
lport->tt.rport_login(rport);
} else
FC_DBG("Failed to allocate memory for "
* @fp: response frame
* @lp_arg: Fibre Channel host port instance
*
- * Locking Note: This function expects that the disc_mutex is locked
- * before it is called.
+ * Locking Note: This function is called without disc mutex held, and
+ * should do all its processing with the mutex held
*/
static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
void *disc_arg)
unsigned int len;
int error;
+ mutex_lock(&disc->disc_mutex);
FC_DEBUG_DISC("Received a GPN_FT response on port (%6x)\n",
fc_host_port_id(disc->lport->host));
if (IS_ERR(fp)) {
fc_disc_error(disc, fp);
+ mutex_unlock(&disc->disc_mutex);
return;
}
disc->seq_count++;
}
fc_frame_free(fp);
+
+ mutex_unlock(&disc->disc_mutex);
}
/**
static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
{
struct fc_lport *lport;
- struct fc_rport *rport;
struct fc_rport *new_rport;
struct fc_rport_libfc_priv *rdata;
if (dp->ids.port_id == fc_host_port_id(lport->host))
goto out;
- rport = lport->tt.rport_lookup(lport, dp->ids.port_id);
- if (rport)
- fc_disc_del_target(disc, rport);
-
new_rport = lport->tt.rport_create(dp);
if (new_rport) {
rdata = new_rport->dd_data;
rdata->ops = &fc_disc_rport_ops;
kfree(dp);
+ list_add_tail(&rdata->peers, &disc->rogue_rports);
lport->tt.rport_login(new_rport);
}
return;
INIT_DELAYED_WORK(&disc->disc_work, fc_disc_timeout);
mutex_init(&disc->disc_mutex);
INIT_LIST_HEAD(&disc->rports);
+ INIT_LIST_HEAD(&disc->rogue_rports);
disc->lport = lport;
disc->delay = FC_DISC_DELAY;
void *arg, u32 timer_msec)
{
enum fc_rctl r_ctl;
- u32 did;
+ u32 did = FC_FID_NONE;
enum fc_fh_type fh_type;
int rc;
static void fc_fcp_recv(struct fc_seq *seq, struct fc_frame *fp, void *arg)
{
struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)arg;
- struct fc_lport *lp;
+ struct fc_lport *lport = fsp->lp;
struct fc_frame_header *fh;
struct fcp_txrdy *dd;
u8 r_ctl;
fh = fc_frame_header_get(fp);
r_ctl = fh->fh_r_ctl;
- lp = fsp->lp;
- if (!(lp->state & LPORT_ST_READY))
+ if (!(lport->state & LPORT_ST_READY))
goto out;
if (fc_fcp_lock_pkt(fsp))
goto out;
if (IS_ERR(fp))
fc_fcp_error(fsp, fp);
else if (rc == -ENOMEM)
- fc_fcp_reduce_can_queue(lp);
+ fc_fcp_reduce_can_queue(lport);
}
static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
{
lport->tt.disc_stop_final(lport);
mutex_lock(&lport->lp_mutex);
+ if (lport->dns_rp)
+ lport->tt.rport_logoff(lport->dns_rp);
+ mutex_unlock(&lport->lp_mutex);
+ lport->tt.rport_flush_queue();
+ mutex_lock(&lport->lp_mutex);
fc_lport_enter_logo(lport);
mutex_unlock(&lport->lp_mutex);
cancel_delayed_work_sync(&lport->retry_work);
*/
int fc_lport_destroy(struct fc_lport *lport)
{
+ mutex_lock(&lport->lp_mutex);
+ lport->state = LPORT_ST_NONE;
+ lport->link_up = 0;
lport->tt.frame_send = fc_frame_drop;
+ mutex_unlock(&lport->lp_mutex);
+
lport->tt.fcp_abort_io(lport);
lport->tt.exch_mgr_reset(lport, 0, 0);
return 0;
FC_DEBUG_LPORT("Received a RFT_ID response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_RFT_ID) {
FC_DBG("Received a RFT_ID response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct));
FC_DEBUG_LPORT("Received a RPN_ID response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_RPN_ID) {
FC_DBG("Received a RPN_ID response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct));
if (fh && ct && fh->fh_type == FC_TYPE_CT &&
FC_DEBUG_LPORT("Received a SCR response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_SCR) {
FC_DBG("Received a SCR response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC)
fc_lport_enter_ready(lport);
FC_DEBUG_LPORT("Received a LOGO response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_LOGO) {
FC_DBG("Received a LOGO response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC)
fc_lport_enter_reset(lport);
fc_lport_state_enter(lport, LPORT_ST_LOGO);
- /* DNS session should be closed so we can release it here */
- if (lport->dns_rp)
- lport->tt.rport_logoff(lport->dns_rp);
-
fp = fc_frame_alloc(lport, sizeof(*logo));
if (!fp) {
fc_lport_error(lport, fp);
FC_DEBUG_LPORT("Received a FLOGI response\n");
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
if (lport->state != LPORT_ST_FLOGI) {
FC_DBG("Received a FLOGI response, but in state %s\n",
fc_lport_state(lport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
fh = fc_frame_header_get(fp);
did = ntoh24(fh->fh_d_id);
if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
"(%6x).\n", ids.port_id);
event = RPORT_EV_FAILED;
}
+ if (rport->port_id != FC_FID_DIR_SERV)
+ if (rport_ops->event_callback)
+ rport_ops->event_callback(lport, rport,
+ RPORT_EV_FAILED);
put_device(&rport->dev);
rport = new_rport;
rdata = new_rport->dd_data;
int fc_rport_logoff(struct fc_rport *rport)
{
struct fc_rport_libfc_priv *rdata = rport->dd_data;
+ struct fc_lport *lport = rdata->local_port;
mutex_lock(&rdata->rp_mutex);
FC_DEBUG_RPORT("Remove port (%6x)\n", rport->port_id);
+ if (rdata->rp_state == RPORT_ST_NONE) {
+ FC_DEBUG_RPORT("(%6x): Port (%6x) in NONE state,"
+ " not removing", fc_host_port_id(lport->host),
+ rport->port_id);
+ mutex_unlock(&rdata->rp_mutex);
+ goto out;
+ }
+
fc_rport_enter_logo(rport);
/*
mutex_unlock(&rdata->rp_mutex);
+out:
return 0;
}
case RPORT_ST_PRLI:
case RPORT_ST_LOGO:
rdata->event = RPORT_EV_FAILED;
+ fc_rport_state_enter(rport, RPORT_ST_NONE);
queue_work(rport_event_queue,
&rdata->event_work);
break;
struct fc_rport *rport = rp_arg;
struct fc_rport_libfc_priv *rdata = rport->dd_data;
struct fc_lport *lport = rdata->local_port;
- struct fc_els_flogi *plp;
+ struct fc_els_flogi *plp = NULL;
unsigned int tov;
u16 csp_seq;
u16 cssp_seq;
FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n",
rport->port_id);
- if (IS_ERR(fp)) {
- fc_rport_error_retry(rport, fp);
- goto err;
- }
-
if (rdata->rp_state != RPORT_ST_PLOGI) {
FC_DBG("Received a PLOGI response, but in state %s\n",
fc_rport_state(rport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_rport_error_retry(rport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC &&
(plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n",
rport->port_id);
- if (IS_ERR(fp)) {
- fc_rport_error_retry(rport, fp);
- goto err;
- }
-
if (rdata->rp_state != RPORT_ST_PRLI) {
FC_DBG("Received a PRLI response, but in state %s\n",
fc_rport_state(rport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_rport_error_retry(rport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
pp = fc_frame_payload_get(fp, sizeof(*pp));
} else {
FC_DBG("Bad ELS response\n");
rdata->event = RPORT_EV_FAILED;
+ fc_rport_state_enter(rport, RPORT_ST_NONE);
queue_work(rport_event_queue, &rdata->event_work);
}
FC_DEBUG_RPORT("Received a LOGO response from port (%6x)\n",
rport->port_id);
- if (IS_ERR(fp)) {
- fc_rport_error_retry(rport, fp);
- goto err;
- }
-
if (rdata->rp_state != RPORT_ST_LOGO) {
FC_DEBUG_RPORT("Received a LOGO response, but in state %s\n",
fc_rport_state(rport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_rport_error_retry(rport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
fc_rport_enter_rtv(rport);
} else {
FC_DBG("Bad ELS response\n");
rdata->event = RPORT_EV_LOGO;
+ fc_rport_state_enter(rport, RPORT_ST_NONE);
queue_work(rport_event_queue, &rdata->event_work);
}
FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n",
rport->port_id);
- if (IS_ERR(fp)) {
- fc_rport_error(rport, fp);
- goto err;
- }
-
if (rdata->rp_state != RPORT_ST_RTV) {
FC_DBG("Received a RTV response, but in state %s\n",
fc_rport_state(rport));
+ if (IS_ERR(fp))
+ goto err;
goto out;
}
+ if (IS_ERR(fp)) {
+ fc_rport_error(rport, fp);
+ goto err;
+ }
+
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
struct fc_els_rtv_acc *rtv;
default:
FC_DEBUG_RPORT("incoming PLOGI from %x in unexpected "
"state %d\n", sid, rdata->rp_state);
+ fc_frame_free(fp);
+ return;
break;
}
reason = ELS_RJT_NONE;
break;
default:
+ fc_frame_free(rx_fp);
+ return;
break;
}
len = fr_len(rx_fp) - sizeof(*fh);
"while in state %s\n", ntoh24(fh->fh_s_id),
fc_rport_state(rport));
+ if (rdata->rp_state == RPORT_ST_NONE) {
+ fc_frame_free(fp);
+ return;
+ }
+
rjt_data.fp = NULL;
rjt_data.reason = ELS_RJT_UNAB;
rjt_data.explan = ELS_EXPL_NONE;
"while in state %s\n", ntoh24(fh->fh_s_id),
fc_rport_state(rport));
+ if (rdata->rp_state == RPORT_ST_NONE) {
+ fc_frame_free(fp);
+ return;
+ }
+
rdata->event = RPORT_EV_LOGO;
+ fc_rport_state_enter(rport, RPORT_ST_NONE);
queue_work(rport_event_queue, &rdata->event_work);
lport->tt.seq_els_rsp_send(sp, ELS_LS_ACC, NULL);
}
EXPORT_SYMBOL_GPL(iscsi_change_queue_depth);
+int iscsi_target_alloc(struct scsi_target *starget)
+{
+ struct iscsi_cls_session *cls_session = starget_to_session(starget);
+ struct iscsi_session *session = cls_session->dd_data;
+
+ starget->can_queue = session->scsi_cmds_max;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(iscsi_target_alloc);
+
void iscsi_session_recovery_timedout(struct iscsi_cls_session *cls_session)
{
struct iscsi_session *session = cls_session->dd_data;
rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent,
r2t->data_count);
- if (rc)
+ if (rc) {
+ iscsi_conn_failure(conn, ISCSI_ERR_XMIT_FAILED);
return rc;
+ }
+
r2t->sent += r2t->data_count;
goto flush;
}
uint32_t hba_flag; /* hba generic flags */
#define HBA_ERATT_HANDLED 0x1 /* This flag is set when eratt handled */
+#define DEFER_ERATT 0x4 /* Deferred error attention in progress */
struct lpfc_dmabuf slim2p;
MAILBOX_t *mbox;
return;
}
-
#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8"
/**
- * lpfc_jedec_to_ascii: Hex to ascii convertor according to JEDEC rules.
+ * lpfc_jedec_to_ascii - Hex to ascii convertor according to JEDEC rules
* @incr: integer to convert.
* @hdw: ascii string holding converted integer plus a string terminator.
*
}
/**
- * lpfc_drvr_version_show: Return the Emulex driver string with version number.
+ * lpfc_drvr_version_show - Return the Emulex driver string with version number
* @dev: class unused variable.
* @attr: device attribute, not used.
* @buf: on return contains the module description text.
}
/**
- * lpfc_info_show: Return some pci info about the host in ascii.
+ * lpfc_info_show - Return some pci info about the host in ascii
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the formatted text from lpfc_info().
}
/**
- * lpfc_serialnum_show: Return the hba serial number in ascii.
+ * lpfc_serialnum_show - Return the hba serial number in ascii
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the formatted text serial number.
}
/**
- * lpfc_temp_sensor_show: Return the temperature sensor level.
+ * lpfc_temp_sensor_show - Return the temperature sensor level
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the formatted support level.
}
/**
- * lpfc_modeldesc_show: Return the model description of the hba.
+ * lpfc_modeldesc_show - Return the model description of the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd model description.
}
/**
- * lpfc_modelname_show: Return the model name of the hba.
+ * lpfc_modelname_show - Return the model name of the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd model name.
}
/**
- * lpfc_programtype_show: Return the program type of the hba.
+ * lpfc_programtype_show - Return the program type of the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd program type.
}
/**
- * lpfc_mlomgmt_show: Return the Menlo Maintenance sli flag.
+ * lpfc_mlomgmt_show - Return the Menlo Maintenance sli flag
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the Menlo Maintenance sli flag.
}
/**
- * lpfc_vportnum_show: Return the port number in ascii of the hba.
+ * lpfc_vportnum_show - Return the port number in ascii of the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains scsi vpd program type.
}
/**
- * lpfc_fwrev_show: Return the firmware rev running in the hba.
+ * lpfc_fwrev_show - Return the firmware rev running in the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd program type.
}
/**
- * lpfc_hdw_show: Return the jedec information about the hba.
+ * lpfc_hdw_show - Return the jedec information about the hba
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the scsi vpd program type.
}
/**
- * lpfc_option_rom_version_show: Return the adapter ROM FCode version.
+ * lpfc_option_rom_version_show - Return the adapter ROM FCode version
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the ROM and FCode ascii strings.
}
/**
- * lpfc_state_show: Return the link state of the port.
+ * lpfc_state_show - Return the link state of the port
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains text describing the state of the link.
}
/**
- * lpfc_num_discovered_ports_show: Return sum of mapped and unmapped vports.
+ * lpfc_num_discovered_ports_show - Return sum of mapped and unmapped vports
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the sum of fc mapped and unmapped.
}
/**
- * lpfc_issue_lip: Misnomer, name carried over from long ago.
+ * lpfc_issue_lip - Misnomer, name carried over from long ago
* @shost: Scsi_Host pointer.
*
* Description:
}
/**
- * lpfc_do_offline: Issues a mailbox command to bring the link down.
+ * lpfc_do_offline - Issues a mailbox command to bring the link down
* @phba: lpfc_hba pointer.
* @type: LPFC_EVT_OFFLINE, LPFC_EVT_WARM_START, LPFC_EVT_KILL.
*
* Assumes any error from lpfc_do_offline() will be negative.
* Can wait up to 5 seconds for the port ring buffers count
* to reach zero, prints a warning if it is not zero and continues.
- * lpfc_workq_post_event() returns a non-zero return coce if call fails.
+ * lpfc_workq_post_event() returns a non-zero return code if call fails.
*
* Returns:
* -EIO error posting the event
}
/**
- * lpfc_selective_reset: Offline then onlines the port.
+ * lpfc_selective_reset - Offline then onlines the port
* @phba: lpfc_hba pointer.
*
* Description:
}
/**
- * lpfc_issue_reset: Selectively resets an adapter.
+ * lpfc_issue_reset - Selectively resets an adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing the string "selective".
}
/**
- * lpfc_nport_evt_cnt_show: Return the number of nport events.
+ * lpfc_nport_evt_cnt_show - Return the number of nport events
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the ascii number of nport events.
}
/**
- * lpfc_board_mode_show: Return the state of the board.
+ * lpfc_board_mode_show - Return the state of the board
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the state of the adapter.
}
/**
- * lpfc_board_mode_store: Puts the hba in online, offline, warm or error state.
+ * lpfc_board_mode_store - Puts the hba in online, offline, warm or error state
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing one of the strings "online", "offline", "warm" or "error".
}
/**
- * lpfc_get_hba_info: Return various bits of informaton about the adapter.
+ * lpfc_get_hba_info - Return various bits of informaton about the adapter
* @phba: pointer to the adapter structure.
- * @mxri max xri count.
- * @axri available xri count.
- * @mrpi max rpi count.
- * @arpi available rpi count.
- * @mvpi max vpi count.
- * @avpi available vpi count.
+ * @mxri: max xri count.
+ * @axri: available xri count.
+ * @mrpi: max rpi count.
+ * @arpi: available rpi count.
+ * @mvpi: max vpi count.
+ * @avpi: available vpi count.
*
* Description:
* If an integer pointer for an count is not null then the value for the
}
/**
- * lpfc_max_rpi_show: Return maximum rpi.
+ * lpfc_max_rpi_show - Return maximum rpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the maximum rpi count in decimal or "Unknown".
}
/**
- * lpfc_used_rpi_show: Return maximum rpi minus available rpi.
+ * lpfc_used_rpi_show - Return maximum rpi minus available rpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing the used rpi count in decimal or "Unknown".
}
/**
- * lpfc_max_xri_show: Return maximum xri.
+ * lpfc_max_xri_show - Return maximum xri
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the maximum xri count in decimal or "Unknown".
}
/**
- * lpfc_used_xri_show: Return maximum xpi minus the available xpi.
+ * lpfc_used_xri_show - Return maximum xpi minus the available xpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the used xri count in decimal or "Unknown".
}
/**
- * lpfc_max_vpi_show: Return maximum vpi.
+ * lpfc_max_vpi_show - Return maximum vpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the maximum vpi count in decimal or "Unknown".
}
/**
- * lpfc_used_vpi_show: Return maximum vpi minus the available vpi.
+ * lpfc_used_vpi_show - Return maximum vpi minus the available vpi
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the used vpi count in decimal or "Unknown".
}
/**
- * lpfc_npiv_info_show: Return text about NPIV support for the adapter.
+ * lpfc_npiv_info_show - Return text about NPIV support for the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: text that must be interpreted to determine if npiv is supported.
}
/**
- * lpfc_poll_show: Return text about poll support for the adapter.
+ * lpfc_poll_show - Return text about poll support for the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: on return contains the cfg_poll in hex.
}
/**
- * lpfc_poll_store: Set the value of cfg_poll for the adapter.
+ * lpfc_poll_store - Set the value of cfg_poll for the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: one or more lpfc_polling_flags values.
}
/**
- * lpfc_param_show: Return a cfg attribute value in decimal.
+ * lpfc_param_show - Return a cfg attribute value in decimal
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
}
/**
- * lpfc_param_hex_show: Return a cfg attribute value in hex.
+ * lpfc_param_hex_show - Return a cfg attribute value in hex
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
* lpfc_##attr##_show: Return the hex value of an adapters cfg_xxx field.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: on return contains the attribute value in hexidecimal.
+ * @buf: on return contains the attribute value in hexadecimal.
*
* Returns: size of formatted string.
**/
}
/**
- * lpfc_param_init: Intializes a cfg attribute.
+ * lpfc_param_init - Intializes a cfg attribute
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
}
/**
- * lpfc_param_set: Set a cfg attribute value.
+ * lpfc_param_set - Set a cfg attribute value
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
}
/**
- * lpfc_param_store: Set a vport attribute value.
+ * lpfc_param_store - Set a vport attribute value
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
}
/**
- * lpfc_vport_param_show: Return decimal formatted cfg attribute value.
+ * lpfc_vport_param_show - Return decimal formatted cfg attribute value
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
}
/**
- * lpfc_vport_param_hex_show: Return hex formatted attribute value.
+ * lpfc_vport_param_hex_show - Return hex formatted attribute value
*
* Description:
* Macro that given an attr e.g.
* hba_queue_depth expands into a function with the name
* lpfc_hba_queue_depth_show
*
- * lpfc_##attr##_show: prints the attribute value in hexidecimal.
+ * lpfc_##attr##_show: prints the attribute value in hexadecimal.
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: on return contains the attribute value in hexidecimal.
+ * @buf: on return contains the attribute value in hexadecimal.
*
* Returns: length of formatted string.
**/
}
/**
- * lpfc_vport_param_init: Initialize a vport cfg attribute.
+ * lpfc_vport_param_init - Initialize a vport cfg attribute
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
}
/**
- * lpfc_vport_param_set: Set a vport cfg attribute.
+ * lpfc_vport_param_set - Set a vport cfg attribute
*
* Description:
* Macro that given an attr e.g. hba_queue_depth expands
}
/**
- * lpfc_vport_param_store: Set a vport attribute.
+ * lpfc_vport_param_store - Set a vport attribute
*
* Description:
* Macro that given an attr e.g. hba_queue_depth
static char *lpfc_soft_wwn_key = "C99G71SL8032A";
/**
- * lpfc_soft_wwn_enable_store: Allows setting of the wwn if the key is valid.
+ * lpfc_soft_wwn_enable_store - Allows setting of the wwn if the key is valid
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
* @buf: containing the string lpfc_soft_wwn_key.
lpfc_soft_wwn_enable_store);
/**
- * lpfc_soft_wwpn_show: Return the cfg soft ww port name of the adapter.
+ * lpfc_soft_wwpn_show - Return the cfg soft ww port name of the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: on return contains the wwpn in hexidecimal.
+ * @buf: on return contains the wwpn in hexadecimal.
*
* Returns: size of formatted string.
**/
}
/**
- * lpfc_soft_wwpn_store: Set the ww port name of the adapter.
+ * lpfc_soft_wwpn_store - Set the ww port name of the adapter
* @dev class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: contains the wwpn in hexidecimal.
+ * @buf: contains the wwpn in hexadecimal.
* @count: number of wwpn bytes in buf
*
* Returns:
lpfc_soft_wwpn_show, lpfc_soft_wwpn_store);
/**
- * lpfc_soft_wwnn_show: Return the cfg soft ww node name for the adapter.
+ * lpfc_soft_wwnn_show - Return the cfg soft ww node name for the adapter
* @dev: class device that is converted into a Scsi_host.
* @attr: device attribute, not used.
- * @buf: on return contains the wwnn in hexidecimal.
+ * @buf: on return contains the wwnn in hexadecimal.
*
* Returns: size of formatted string.
**/
}
/**
- * lpfc_soft_wwnn_store: sets the ww node name of the adapter.
+ * lpfc_soft_wwnn_store - sets the ww node name of the adapter
* @cdev: class device that is converted into a Scsi_host.
- * @buf: contains the ww node name in hexidecimal.
+ * @buf: contains the ww node name in hexadecimal.
* @count: number of wwnn bytes in buf.
*
* Returns:
"for a device to come back");
/**
- * lpfc_nodev_tmo_show: Return the hba dev loss timeout value.
+ * lpfc_nodev_tmo_show - Return the hba dev loss timeout value
* @dev: class converted to a Scsi_host structure.
* @attr: device attribute, not used.
* @buf: on return contains the dev loss timeout in decimal.
}
/**
- * lpfc_nodev_tmo_init: Set the hba nodev timeout value.
+ * lpfc_nodev_tmo_init - Set the hba nodev timeout value
* @vport: lpfc vport structure pointer.
* @val: contains the nodev timeout value.
*
}
/**
- * lpfc_update_rport_devloss_tmo: Update dev loss tmo value.
+ * lpfc_update_rport_devloss_tmo - Update dev loss tmo value
* @vport: lpfc vport structure pointer.
*
* Description:
}
/**
- * lpfc_nodev_tmo_set: Set the vport nodev tmo and devloss tmo values.
+ * lpfc_nodev_tmo_set - Set the vport nodev tmo and devloss tmo values
* @vport: lpfc vport structure pointer.
* @val: contains the tmo value.
*
lpfc_vport_param_show(devloss_tmo)
/**
- * lpfc_devloss_tmo_set: Sets vport nodev tmo, devloss tmo values, changed bit.
+ * lpfc_devloss_tmo_set - Sets vport nodev tmo, devloss tmo values, changed bit
* @vport: lpfc vport structure pointer.
* @val: contains the tmo value.
*
lpfc_vport_param_show(restrict_login);
/**
- * lpfc_restrict_login_init: Set the vport restrict login flag.
+ * lpfc_restrict_login_init - Set the vport restrict login flag
* @vport: lpfc vport structure pointer.
* @val: contains the restrict login value.
*
}
/**
- * lpfc_restrict_login_set: Set the vport restrict login flag.
+ * lpfc_restrict_login_set - Set the vport restrict login flag
* @vport: lpfc vport structure pointer.
* @val: contains the restrict login value.
*
*/
/**
- * lpfc_topology_set: Set the adapters topology field.
+ * lpfc_topology_set - Set the adapters topology field
* @phba: lpfc_hba pointer.
* @val: topology value.
*
* non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range
**/
-static int
-lpfc_topology_set(struct lpfc_hba *phba, int val)
+static ssize_t
+lpfc_topology_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ int val = 0;
+ int nolip = 0;
+ const char *val_buf = buf;
int err;
uint32_t prev_val;
+
+ if (!strncmp(buf, "nolip ", strlen("nolip "))) {
+ nolip = 1;
+ val_buf = &buf[strlen("nolip ")];
+ }
+
+ if (!isdigit(val_buf[0]))
+ return -EINVAL;
+ if (sscanf(val_buf, "%i", &val) != 1)
+ return -EINVAL;
+
if (val >= 0 && val <= 6) {
prev_val = phba->cfg_topology;
phba->cfg_topology = val;
+ if (nolip)
+ return strlen(buf);
+
err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
- if (err)
+ if (err) {
phba->cfg_topology = prev_val;
- return err;
+ return -EINVAL;
+ } else
+ return strlen(buf);
}
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"%d:0467 lpfc_topology attribute cannot be set to %d, "
MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology");
lpfc_param_show(topology)
lpfc_param_init(topology, 0, 0, 6)
-lpfc_param_store(topology)
static DEVICE_ATTR(lpfc_topology, S_IRUGO | S_IWUSR,
lpfc_topology_show, lpfc_topology_store);
/**
- * lpfc_stat_data_ctrl_store: write call back for lpfc_stat_data_ctrl
- * sysfs file.
+ * lpfc_stat_data_ctrl_store - write call back for lpfc_stat_data_ctrl sysfs file
* @dev: Pointer to class device.
* @buf: Data buffer.
* @count: Size of the data buffer.
unsigned long base, step, bucket_type;
if (!strncmp(buf, "setbucket", strlen("setbucket"))) {
- if (strlen(buf) > LPFC_MAX_DATA_CTRL_LEN)
+ if (strlen(buf) > (LPFC_MAX_DATA_CTRL_LEN - 1))
return -EINVAL;
strcpy(bucket_data, buf);
/**
- * lpfc_stat_data_ctrl_show: Read callback function for
- * lpfc_stat_data_ctrl sysfs file.
+ * lpfc_stat_data_ctrl_show - Read function for lpfc_stat_data_ctrl sysfs file
* @dev: Pointer to class device object.
* @buf: Data buffer.
*
/**
- * sysfs_drvr_stat_data_read: Read callback function for lpfc_drvr_stat_data
- * sysfs attribute.
+ * sysfs_drvr_stat_data_read - Read function for lpfc_drvr_stat_data attribute
* @kobj: Pointer to the kernel object
* @bin_attr: Attribute object
* @buff: Buffer pointer
*/
/**
- * lpfc_link_speed_set: Set the adapters link speed.
+ * lpfc_link_speed_set - Set the adapters link speed
* @phba: lpfc_hba pointer.
* @val: link speed value.
*
* non-zero return value from lpfc_issue_lip()
* -EINVAL val out of range
**/
-static int
-lpfc_link_speed_set(struct lpfc_hba *phba, int val)
+static ssize_t
+lpfc_link_speed_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
{
+ struct Scsi_Host *shost = class_to_shost(dev);
+ struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+ struct lpfc_hba *phba = vport->phba;
+ int val = 0;
+ int nolip = 0;
+ const char *val_buf = buf;
int err;
uint32_t prev_val;
+ if (!strncmp(buf, "nolip ", strlen("nolip "))) {
+ nolip = 1;
+ val_buf = &buf[strlen("nolip ")];
+ }
+
+ if (!isdigit(val_buf[0]))
+ return -EINVAL;
+ if (sscanf(val_buf, "%i", &val) != 1)
+ return -EINVAL;
+
if (((val == LINK_SPEED_1G) && !(phba->lmt & LMT_1Gb)) ||
((val == LINK_SPEED_2G) && !(phba->lmt & LMT_2Gb)) ||
((val == LINK_SPEED_4G) && !(phba->lmt & LMT_4Gb)) ||
((val == LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)))
return -EINVAL;
- if ((val >= 0 && val <= LPFC_MAX_LINK_SPEED)
+ if ((val >= 0 && val <= 8)
&& (LPFC_LINK_SPEED_BITMAP & (1 << val))) {
prev_val = phba->cfg_link_speed;
phba->cfg_link_speed = val;
+ if (nolip)
+ return strlen(buf);
+
err = lpfc_issue_lip(lpfc_shost_from_vport(phba->pport));
- if (err)
+ if (err) {
phba->cfg_link_speed = prev_val;
- return err;
+ return -EINVAL;
+ } else
+ return strlen(buf);
}
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
lpfc_param_show(link_speed)
/**
- * lpfc_link_speed_init: Set the adapters link speed.
+ * lpfc_link_speed_init - Set the adapters link speed
* @phba: lpfc_hba pointer.
* @val: link speed value.
*
return -EINVAL;
}
-lpfc_param_store(link_speed)
static DEVICE_ATTR(lpfc_link_speed, S_IRUGO | S_IWUSR,
lpfc_link_speed_show, lpfc_link_speed_store);
/*
- * lpfc_sg_seg_cnt: Initial Maximum DMA Segment Count
+ * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
* This value can be set to values between 64 and 256. The default value is
* 64, but may be increased to allow for larger Max I/O sizes. The scsi layer
* will be allowed to request I/Os of sizes up to (MAX_SEG_COUNT * SEG_SIZE).
};
/**
- * sysfs_ctlreg_write: Write method for writing to ctlreg.
+ * sysfs_ctlreg_write - Write method for writing to ctlreg
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: contains the data to be written to the adapter IOREG space.
}
/**
- * sysfs_ctlreg_read: Read method for reading from ctlreg.
+ * sysfs_ctlreg_read - Read method for reading from ctlreg
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: if succesful contains the data from the adapter IOREG space.
};
/**
- * sysfs_mbox_idle: frees the sysfs mailbox.
+ * sysfs_mbox_idle - frees the sysfs mailbox
* @phba: lpfc_hba pointer
**/
static void
}
/**
- * sysfs_mbox_write: Write method for writing information via mbox.
+ * sysfs_mbox_write - Write method for writing information via mbox
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: contains the data to be written to sysfs mbox.
}
/**
- * sysfs_mbox_read: Read method for reading information via mbox.
+ * sysfs_mbox_read - Read method for reading information via mbox
* @kobj: kernel kobject that contains the kernel class device.
* @bin_attr: kernel attributes passed to us.
* @buf: contains the data to be read from sysfs mbox.
};
/**
- * lpfc_alloc_sysfs_attr: Creates the ctlreg and mbox entries.
+ * lpfc_alloc_sysfs_attr - Creates the ctlreg and mbox entries
* @vport: address of lpfc vport structure.
*
* Return codes:
}
/**
- * lpfc_free_sysfs_attr: Removes the ctlreg and mbox entries.
+ * lpfc_free_sysfs_attr - Removes the ctlreg and mbox entries
* @vport: address of lpfc vport structure.
**/
void
*/
/**
- * lpfc_get_host_port_id: Copy the vport DID into the scsi host port id.
+ * lpfc_get_host_port_id - Copy the vport DID into the scsi host port id
* @shost: kernel scsi host pointer.
**/
static void
}
/**
- * lpfc_get_host_port_type: Set the value of the scsi host port type.
+ * lpfc_get_host_port_type - Set the value of the scsi host port type
* @shost: kernel scsi host pointer.
**/
static void
}
/**
- * lpfc_get_host_port_state: Set the value of the scsi host port state.
+ * lpfc_get_host_port_state - Set the value of the scsi host port state
* @shost: kernel scsi host pointer.
**/
static void
}
/**
- * lpfc_get_host_speed: Set the value of the scsi host speed.
+ * lpfc_get_host_speed - Set the value of the scsi host speed
* @shost: kernel scsi host pointer.
**/
static void
}
/**
- * lpfc_get_host_fabric_name: Set the value of the scsi host fabric name.
+ * lpfc_get_host_fabric_name - Set the value of the scsi host fabric name
* @shost: kernel scsi host pointer.
**/
static void
}
/**
- * lpfc_get_stats: Return statistical information about the adapter.
+ * lpfc_get_stats - Return statistical information about the adapter
* @shost: kernel scsi host pointer.
*
* Notes:
}
/**
- * lpfc_reset_stats: Copy the adapter link stats information.
+ * lpfc_reset_stats - Copy the adapter link stats information
* @shost: kernel scsi host pointer.
**/
static void
*/
/**
- * lpfc_get_node_by_target: Return the nodelist for a target.
+ * lpfc_get_node_by_target - Return the nodelist for a target
* @starget: kernel scsi target pointer.
*
* Returns:
}
/**
- * lpfc_get_starget_port_id: Set the target port id to the ndlp DID or -1.
+ * lpfc_get_starget_port_id - Set the target port id to the ndlp DID or -1
* @starget: kernel scsi target pointer.
**/
static void
}
/**
- * lpfc_get_starget_node_name: Set the target node name.
+ * lpfc_get_starget_node_name - Set the target node name
* @starget: kernel scsi target pointer.
*
* Description: Set the target node name to the ndlp node name wwn or zero.
}
/**
- * lpfc_get_starget_port_name: Set the target port name.
+ * lpfc_get_starget_port_name - Set the target port name
* @starget: kernel scsi target pointer.
*
* Description: set the target port name to the ndlp port name wwn or zero.
}
/**
- * lpfc_set_rport_loss_tmo: Set the rport dev loss tmo.
+ * lpfc_set_rport_loss_tmo - Set the rport dev loss tmo
* @rport: fc rport address.
* @timeout: new value for dev loss tmo.
*
}
/**
- * lpfc_rport_show_function: Return rport target information.
+ * lpfc_rport_show_function - Return rport target information
*
* Description:
* Macro that uses field to generate a function with the name lpfc_show_rport_
static FC_RPORT_ATTR(field, S_IRUGO, lpfc_show_rport_##field, NULL)
/**
- * lpfc_set_vport_symbolic_name: Set the vport's symbolic name.
+ * lpfc_set_vport_symbolic_name - Set the vport's symbolic name
* @fc_vport: The fc_vport who's symbolic name has been changed.
*
* Description:
};
/**
- * lpfc_get_cfgparam: Used during probe_one to init the adapter structure.
+ * lpfc_get_cfgparam - Used during probe_one to init the adapter structure
* @phba: lpfc_hba pointer.
**/
void
}
/**
- * lpfc_get_vport_cfgparam: Used during port create, init the vport structure.
+ * lpfc_get_vport_cfgparam - Used during port create, init the vport structure
* @vport: lpfc_vport pointer.
**/
void
struct lpfc_iocbq * lpfc_sli_get_iocbq(struct lpfc_hba *);
void lpfc_sli_release_iocbq(struct lpfc_hba *, struct lpfc_iocbq *);
uint16_t lpfc_sli_next_iotag(struct lpfc_hba *, struct lpfc_iocbq *);
+void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t,
+ uint32_t);
void lpfc_reset_barrier(struct lpfc_hba * phba);
int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
#include "lpfc_debugfs.h"
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
-/**
+/*
* debugfs interface
*
* To access this interface the user should:
MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc,
"Set debugfs slow ring trace depth");
-int lpfc_debugfs_mask_disc_trc;
+static int lpfc_debugfs_mask_disc_trc;
module_param(lpfc_debugfs_mask_disc_trc, int, 0);
MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
"Set debugfs discovery trace mask");
static unsigned long lpfc_debugfs_start_time = 0L;
/**
- * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer.
+ * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer
* @vport: The vport to gather the log info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
}
/**
- * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer.
+ * lpfc_debugfs_slow_ring_trc_data - Dump slow ring logging to a buffer
* @phba: The HBA to gather the log info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
static int lpfc_debugfs_last_hbq = -1;
/**
- * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer.
+ * lpfc_debugfs_hbqinfo_data - Dump host buffer queue info to a buffer
* @phba: The HBA to gather host buffer info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
static int lpfc_debugfs_last_hba_slim_off;
/**
- * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer.
+ * lpfc_debugfs_dumpHBASlim_data - Dump HBA SLIM info to a buffer
* @phba: The HBA to gather SLIM info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
len += snprintf(buf+len, size-len, "HBA SLIM\n");
lpfc_memcpy_from_slim(buffer,
- ((uint8_t *)phba->MBslimaddr) + lpfc_debugfs_last_hba_slim_off,
- 1024);
+ phba->MBslimaddr + lpfc_debugfs_last_hba_slim_off, 1024);
ptr = (uint32_t *)&buffer[0];
off = lpfc_debugfs_last_hba_slim_off;
}
/**
- * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer.
+ * lpfc_debugfs_dumpHostSlim_data - Dump host SLIM info to a buffer
* @phba: The HBA to gather Host SLIM info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
}
/**
- * lpfc_debugfs_nodelist_data - Dump target node list to a buffer.
+ * lpfc_debugfs_nodelist_data - Dump target node list to a buffer
* @vport: The vport to gather target node info from.
* @buf: The buffer to dump log into.
* @size: The maximum amount of data to process.
#endif
/**
- * lpfc_debugfs_disc_trc - Store discovery trace log.
+ * lpfc_debugfs_disc_trc - Store discovery trace log
* @vport: The vport to associate this trace string with for retrieval.
* @mask: Log entry classification.
* @fmt: Format string to be displayed when dumping the log.
}
/**
- * lpfc_debugfs_slow_ring_trc - Store slow ring trace log.
+ * lpfc_debugfs_slow_ring_trc - Store slow ring trace log
* @phba: The phba to associate this trace string with for retrieval.
* @fmt: Format string to be displayed when dumping the log.
* @data1: 1st data parameter to be applied to @fmt.
#ifdef CONFIG_SCSI_LPFC_DEBUG_FS
/**
- * lpfc_debugfs_disc_trc_open - Open the discovery trace log.
+ * lpfc_debugfs_disc_trc_open - Open the discovery trace log
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
}
/**
- * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log.
+ * lpfc_debugfs_slow_ring_trc_open - Open the Slow Ring trace log
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
}
/**
- * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer.
+ * lpfc_debugfs_hbqinfo_open - Open the hbqinfo debugfs buffer
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
}
/**
- * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer.
+ * lpfc_debugfs_dumpHBASlim_open - Open the Dump HBA SLIM debugfs buffer
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
}
/**
- * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer.
+ * lpfc_debugfs_dumpHostSlim_open - Open the Dump Host SLIM debugfs buffer
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
/**
- * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file.
+ * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
* @inode: The inode pointer that contains a vport pointer.
* @file: The file pointer to attach the log output.
*
}
/**
- * lpfc_debugfs_lseek - Seek through a debugfs file.
+ * lpfc_debugfs_lseek - Seek through a debugfs file
* @file: The file pointer to seek through.
* @off: The offset to seek to or the amount to seek by.
* @whence: Indicates how to seek.
}
/**
- * lpfc_debugfs_read - Read a debugfs file.
+ * lpfc_debugfs_read - Read a debugfs file
* @file: The file pointer to read from.
* @buf: The buffer to copy the data to.
* @nbytes: The number of bytes to read.
}
/**
- * lpfc_debugfs_release - Release the buffer used to store debugfs file data.
+ * lpfc_debugfs_release - Release the buffer used to store debugfs file data
* @inode: The inode pointer that contains a vport pointer. (unused)
* @file: The file pointer that contains the buffer to release.
*
#endif
/**
- * lpfc_debugfs_initialize - Initialize debugfs for a vport.
+ * lpfc_debugfs_initialize - Initialize debugfs for a vport
* @vport: The vport pointer to initialize.
*
* Description:
}
/**
- * lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport.
+ * lpfc_debugfs_terminate - Tear down debugfs infrastructure for this vport
* @vport: The vport pointer to remove from debugfs.
*
* Description:
#define NLP_USG_FREE_ACK_BIT 0x8 /* Indicate ndlp memory free invoked */
struct timer_list nlp_delayfunc; /* Used for delayed ELS cmds */
+ struct lpfc_hba *phba;
struct fc_rport *rport; /* Corresponding FC transport
port structure */
struct lpfc_vport *vport;
static int lpfc_max_els_tries = 3;
/**
- * lpfc_els_chk_latt: Check host link attention event for a vport.
+ * lpfc_els_chk_latt - Check host link attention event for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine checks whether there is an outstanding host link
}
/**
- * lpfc_prep_els_iocb: Allocate and prepare a lpfc iocb data structure.
+ * lpfc_prep_els_iocb - Allocate and prepare a lpfc iocb data structure
* @vport: pointer to a host virtual N_Port data structure.
* @expectRsp: flag indicating whether response is expected.
* @cmdSize: size of the ELS command.
}
/**
- * lpfc_issue_fabric_reglogin: Issue fabric registration login for a vport.
+ * lpfc_issue_fabric_reglogin - Issue fabric registration login for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues a fabric registration login for a @vport. An
}
/**
- * lpfc_cmpl_els_flogi_fabric: Completion function for flogi to a fabric port.
+ * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @sp: pointer to service parameter data structure.
}
/**
- * lpfc_cmpl_els_flogi_nport: Completion function for flogi to an N_Port.
+ * lpfc_cmpl_els_flogi_nport - Completion function for flogi to an N_Port
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @sp: pointer to service parameter data structure.
}
/**
- * lpfc_cmpl_els_flogi: Completion callback function for flogi.
+ * lpfc_cmpl_els_flogi - Completion callback function for flogi
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_issue_els_flogi: Issue an flogi iocb command for a vport.
+ * lpfc_issue_els_flogi - Issue an flogi iocb command for a vport
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
}
/**
- * lpfc_els_abort_flogi: Abort all outstanding flogi iocbs.
+ * lpfc_els_abort_flogi - Abort all outstanding flogi iocbs
* @phba: pointer to lpfc hba data structure.
*
* This routine aborts all the outstanding Fabric Login (FLOGI) IOCBs
}
/**
- * lpfc_initial_flogi: Issue an initial fabric login for a vport.
+ * lpfc_initial_flogi - Issue an initial fabric login for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues an initial Fabric Login (FLOGI) for the @vport
}
/**
- * lpfc_initial_fdisc: Issue an initial fabric discovery for a vport.
+ * lpfc_initial_fdisc - Issue an initial fabric discovery for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues an initial Fabric Discover (FDISC) for the @vport
}
/**
- * lpfc_more_plogi: Check and issue remaining plogis for a vport.
+ * lpfc_more_plogi - Check and issue remaining plogis for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine checks whether there are more remaining Port Logins
}
/**
- * lpfc_plogi_confirm_nport: Confirm pologi wwpn matches stored ndlp.
+ * lpfc_plogi_confirm_nport - Confirm pologi wwpn matches stored ndlp
* @phba: pointer to lpfc hba data structure.
* @prsp: pointer to response IOCB payload.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_end_rscn: Check and handle more rscn for a vport.
+ * lpfc_end_rscn - Check and handle more rscn for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine checks whether more Registration State Change
}
/**
- * lpfc_cmpl_els_plogi: Completion callback function for plogi.
+ * lpfc_cmpl_els_plogi - Completion callback function for plogi
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_issue_els_plogi: Issue an plogi iocb command for a vport.
+ * lpfc_issue_els_plogi - Issue an plogi iocb command for a vport
* @vport: pointer to a host virtual N_Port data structure.
* @did: destination port identifier.
* @retry: number of retries to the command IOCB.
}
/**
- * lpfc_cmpl_els_prli: Completion callback function for prli.
+ * lpfc_cmpl_els_prli - Completion callback function for prli
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_issue_els_prli: Issue a prli iocb command for a vport.
+ * lpfc_issue_els_prli - Issue a prli iocb command for a vport
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
}
/**
- * lpfc_rscn_disc: Perform rscn discovery for a vport.
+ * lpfc_rscn_disc - Perform rscn discovery for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine performs Registration State Change Notification (RSCN)
}
/**
- * lpfc_adisc_done: Complete the adisc phase of discovery.
+ * lpfc_adisc_done - Complete the adisc phase of discovery
* @vport: pointer to lpfc_vport hba data structure that finished all ADISCs.
*
* This function is called when the final ADISC is completed during discovery.
}
/**
- * lpfc_more_adisc: Issue more adisc as needed.
+ * lpfc_more_adisc - Issue more adisc as needed
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine determines whether there are more ndlps on a @vport
}
/**
- * lpfc_cmpl_els_adisc: Completion callback function for adisc.
+ * lpfc_cmpl_els_adisc - Completion callback function for adisc
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_issue_els_adisc: Issue an address discover iocb to an node on a vport.
+ * lpfc_issue_els_adisc - Issue an address discover iocb to an node on a vport
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
}
/**
- * lpfc_cmpl_els_logo: Completion callback function for logo.
+ * lpfc_cmpl_els_logo - Completion callback function for logo
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_issue_els_logo: Issue a logo to an node on a vport.
+ * lpfc_issue_els_logo - Issue a logo to an node on a vport
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
}
/**
- * lpfc_cmpl_els_cmd: Completion callback function for generic els command.
+ * lpfc_cmpl_els_cmd - Completion callback function for generic els command
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_issue_els_scr: Issue a scr to an node on a vport.
+ * lpfc_issue_els_scr - Issue a scr to an node on a vport
* @vport: pointer to a host virtual N_Port data structure.
* @nportid: N_Port identifier to the remote node.
* @retry: number of retries to the command IOCB.
}
/**
- * lpfc_issue_els_farpr: Issue a farp to an node on a vport.
+ * lpfc_issue_els_farpr - Issue a farp to an node on a vport
* @vport: pointer to a host virtual N_Port data structure.
* @nportid: N_Port identifier to the remote node.
* @retry: number of retries to the command IOCB.
}
/**
- * lpfc_cancel_retry_delay_tmo: Cancel the timer with delayed iocb-cmd retry.
+ * lpfc_cancel_retry_delay_tmo - Cancel the timer with delayed iocb-cmd retry
* @vport: pointer to a host virtual N_Port data structure.
* @nlp: pointer to a node-list data structure.
*
}
/**
- * lpfc_els_retry_delay: Timer function with a ndlp delayed function timer.
+ * lpfc_els_retry_delay - Timer function with a ndlp delayed function timer
* @ptr: holder for the pointer to the timer function associated data (ndlp).
*
* This routine is invoked by the ndlp delayed-function timer to check
}
/**
- * lpfc_els_retry_delay_handler: Work thread handler for ndlp delayed function.
+ * lpfc_els_retry_delay_handler - Work thread handler for ndlp delayed function
* @ndlp: pointer to a node-list data structure.
*
* This routine is the worker-thread handler for processing the @ndlp delayed
}
/**
- * lpfc_els_retry: Make retry decision on an els command iocb.
+ * lpfc_els_retry - Make retry decision on an els command iocb
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_els_free_data: Free lpfc dma buffer and data structure with an iocb.
+ * lpfc_els_free_data - Free lpfc dma buffer and data structure with an iocb
* @phba: pointer to lpfc hba data structure.
* @buf_ptr1: pointer to the lpfc DMA buffer data structure.
*
}
/**
- * lpfc_els_free_bpl: Free lpfc dma buffer and data structure with bpl.
+ * lpfc_els_free_bpl - Free lpfc dma buffer and data structure with bpl
* @phba: pointer to lpfc hba data structure.
* @buf_ptr: pointer to the lpfc dma buffer data structure.
*
}
/**
- * lpfc_els_free_iocb: Free a command iocb and its associated resources.
+ * lpfc_els_free_iocb - Free a command iocb and its associated resources
* @phba: pointer to lpfc hba data structure.
* @elsiocb: pointer to lpfc els command iocb data structure.
*
}
/**
- * lpfc_cmpl_els_logo_acc: Completion callback function to logo acc response.
+ * lpfc_cmpl_els_logo_acc - Completion callback function to logo acc response
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_mbx_cmpl_dflt_rpi: Completion callbk func for unreg dflt rpi mbox cmd.
+ * lpfc_mbx_cmpl_dflt_rpi - Completion callbk func for unreg dflt rpi mbox cmd
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_cmpl_els_rsp: Completion callback function for els response iocb cmd.
+ * lpfc_cmpl_els_rsp - Completion callback function for els response iocb cmd
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_els_rsp_acc: Prepare and issue an acc response iocb command.
+ * lpfc_els_rsp_acc - Prepare and issue an acc response iocb command
* @vport: pointer to a host virtual N_Port data structure.
* @flag: the els command code to be accepted.
* @oldiocb: pointer to the original lpfc command iocb data structure.
}
/**
- * lpfc_els_rsp_reject: Propare and issue a rjt response iocb command.
+ * lpfc_els_rsp_reject - Propare and issue a rjt response iocb command
* @vport: pointer to a virtual N_Port data structure.
* @rejectError:
* @oldiocb: pointer to the original lpfc command iocb data structure.
}
/**
- * lpfc_els_rsp_adisc_acc: Prepare and issue acc response to adisc iocb cmd.
+ * lpfc_els_rsp_adisc_acc - Prepare and issue acc response to adisc iocb cmd
* @vport: pointer to a virtual N_Port data structure.
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_rsp_prli_acc: Prepare and issue acc response to prli iocb cmd.
+ * lpfc_els_rsp_prli_acc - Prepare and issue acc response to prli iocb cmd
* @vport: pointer to a virtual N_Port data structure.
* @oldiocb: pointer to the original lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_rsp_rnid_acc: Issue rnid acc response iocb command.
+ * lpfc_els_rsp_rnid_acc - Issue rnid acc response iocb command
* @vport: pointer to a virtual N_Port data structure.
* @format: rnid command format.
* @oldiocb: pointer to the original lpfc command iocb data structure.
}
/**
- * lpfc_els_disc_adisc: Issue remaining adisc iocbs to npr nodes of a vport.
+ * lpfc_els_disc_adisc - Issue remaining adisc iocbs to npr nodes of a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues Address Discover (ADISC) ELS commands to those
}
/**
- * lpfc_els_disc_plogi: Issue plogi for all npr nodes of a vport before adisc.
+ * lpfc_els_disc_plogi - Issue plogi for all npr nodes of a vport before adisc
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine issues Port Login (PLOGI) ELS commands to all the N_Ports
}
/**
- * lpfc_els_flush_rscn: Clean up any rscn activities with a vport.
+ * lpfc_els_flush_rscn - Clean up any rscn activities with a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine cleans up any Registration State Change Notification
}
/**
- * lpfc_rscn_payload_check: Check whether there is a pending rscn to a did.
+ * lpfc_rscn_payload_check - Check whether there is a pending rscn to a did
* @vport: pointer to a host virtual N_Port data structure.
* @did: remote destination port identifier.
*
}
/**
- * lpfc_rscn_recovery_check: Send recovery event to vport nodes matching rscn
+ * lpfc_rscn_recovery_check - Send recovery event to vport nodes matching rscn
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine sends recovery (NLP_EVT_DEVICE_RECOVERY) event to the
}
/**
- * lpfc_send_rscn_event: Send an RSCN event to management application.
+ * lpfc_send_rscn_event - Send an RSCN event to management application
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
*
}
/**
- * lpfc_els_rcv_rscn: Process an unsolicited rscn iocb.
+ * lpfc_els_rcv_rscn - Process an unsolicited rscn iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_handle_rscn: Handle rscn for a vport.
+ * lpfc_els_handle_rscn - Handle rscn for a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine handles the Registration State Configuration Notification
}
/**
- * lpfc_els_rcv_flogi: Process an unsolicited flogi iocb.
+ * lpfc_els_rcv_flogi - Process an unsolicited flogi iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_rcv_rnid: Process an unsolicited rnid iocb.
+ * lpfc_els_rcv_rnid - Process an unsolicited rnid iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_rcv_lirr: Process an unsolicited lirr iocb.
+ * lpfc_els_rcv_lirr - Process an unsolicited lirr iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_rsp_rps_acc: Completion callbk func for MBX_READ_LNK_STAT mbox cmd.
+ * lpfc_els_rsp_rps_acc - Completion callbk func for MBX_READ_LNK_STAT mbox cmd
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_els_rcv_rps: Process an unsolicited rps iocb.
+ * lpfc_els_rcv_rps - Process an unsolicited rps iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_rsp_rpl_acc: Issue an accept rpl els command.
+ * lpfc_els_rsp_rpl_acc - Issue an accept rpl els command
* @vport: pointer to a host virtual N_Port data structure.
* @cmdsize: size of the ELS command.
* @oldiocb: pointer to the original lpfc command iocb data structure.
}
/**
- * lpfc_els_rcv_rpl: Process an unsolicited rpl iocb.
+ * lpfc_els_rcv_rpl - Process an unsolicited rpl iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_rcv_farp: Process an unsolicited farp request els command.
+ * lpfc_els_rcv_farp - Process an unsolicited farp request els command
* @vport: pointer to a virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_rcv_farpr: Process an unsolicited farp response iocb.
+ * lpfc_els_rcv_farpr - Process an unsolicited farp response iocb
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_rcv_fan: Process an unsolicited fan iocb command.
+ * lpfc_els_rcv_fan - Process an unsolicited fan iocb command
* @vport: pointer to a host virtual N_Port data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @fan_ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_els_timeout: Handler funciton to the els timer.
+ * lpfc_els_timeout - Handler funciton to the els timer
* @ptr: holder for the timer function associated data.
*
* This routine is invoked by the ELS timer after timeout. It posts the ELS
}
/**
- * lpfc_els_timeout_handler: Process an els timeout event.
+ * lpfc_els_timeout_handler - Process an els timeout event
* @vport: pointer to a virtual N_Port data structure.
*
* This routine is the actual handler function that processes an ELS timeout
}
/**
- * lpfc_els_flush_cmd: Clean up the outstanding els commands to a vport.
+ * lpfc_els_flush_cmd - Clean up the outstanding els commands to a vport
* @vport: pointer to a host virtual N_Port data structure.
*
* This routine is used to clean up all the outstanding ELS commands on a
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- cmd = &piocb->iocb;
- list_del_init(&piocb->list);
-
- if (!piocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, piocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
- }
+ /* Cancell all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
return;
}
/**
- * lpfc_els_flush_all_cmd: Clean up all the outstanding els commands to a HBA.
+ * lpfc_els_flush_all_cmd - Clean up all the outstanding els commands to a HBA
* @phba: pointer to lpfc hba data structure.
*
* This routine is used to clean up all the outstanding ELS commands on a
lpfc_sli_issue_abort_iotag(phba, pring, piocb);
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- cmd = &piocb->iocb;
- list_del_init(&piocb->list);
- if (!piocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, piocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
- }
+
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
+
return;
}
/**
- * lpfc_send_els_failure_event: Posts an ELS command failure event.
+ * lpfc_send_els_failure_event - Posts an ELS command failure event
* @phba: Pointer to hba context object.
* @cmdiocbp: Pointer to command iocb which reported error.
* @rspiocbp: Pointer to response iocb which reported error.
}
/**
- * lpfc_send_els_event: Posts unsolicited els event.
+ * lpfc_send_els_event - Posts unsolicited els event
* @vport: Pointer to vport object.
* @ndlp: Pointer FC node object.
* @cmd: ELS command code.
/**
- * lpfc_els_unsol_buffer: Process an unsolicited event data buffer.
+ * lpfc_els_unsol_buffer - Process an unsolicited event data buffer
* @phba: pointer to lpfc hba data structure.
* @pring: pointer to a SLI ring.
* @vport: pointer to a host virtual N_Port data structure.
}
/**
- * lpfc_find_vport_by_vpid: Find a vport on a HBA through vport identifier.
+ * lpfc_find_vport_by_vpid - Find a vport on a HBA through vport identifier
* @phba: pointer to lpfc hba data structure.
* @vpi: host virtual N_Port identifier.
*
}
/**
- * lpfc_els_unsol_event: Process an unsolicited event from an els sli ring.
+ * lpfc_els_unsol_event - Process an unsolicited event from an els sli ring
* @phba: pointer to lpfc hba data structure.
* @pring: pointer to a SLI ring.
* @elsiocb: pointer to lpfc els iocb data structure.
}
/**
- * lpfc_do_scr_ns_plogi: Issue a plogi to the name server for scr.
+ * lpfc_do_scr_ns_plogi - Issue a plogi to the name server for scr
* @phba: pointer to lpfc hba data structure.
* @vport: pointer to a virtual N_Port data structure.
*
}
/**
- * lpfc_cmpl_reg_new_vport: Completion callback function to register new vport.
+ * lpfc_cmpl_reg_new_vport - Completion callback function to register new vport
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_register_new_vport: Register a new vport with a HBA.
+ * lpfc_register_new_vport - Register a new vport with a HBA
* @phba: pointer to lpfc hba data structure.
* @vport: pointer to a host virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
}
/**
- * lpfc_cmpl_els_fdisc: Completion function for fdisc iocb command.
+ * lpfc_cmpl_els_fdisc - Completion function for fdisc iocb command
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_issue_els_fdisc: Issue a fdisc iocb command.
+ * lpfc_issue_els_fdisc - Issue a fdisc iocb command
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
* @retry: number of retries to the command IOCB.
}
/**
- * lpfc_cmpl_els_npiv_logo: Completion function with vport logo.
+ * lpfc_cmpl_els_npiv_logo - Completion function with vport logo
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_issue_els_npiv_logo: Issue a logo off a vport.
+ * lpfc_issue_els_npiv_logo - Issue a logo off a vport
* @vport: pointer to a virtual N_Port data structure.
* @ndlp: pointer to a node-list data structure.
*
}
/**
- * lpfc_fabric_block_timeout: Handler function to the fabric block timer.
+ * lpfc_fabric_block_timeout - Handler function to the fabric block timer
* @ptr: holder for the timer function associated data.
*
* This routine is invoked by the fabric iocb block timer after
}
/**
- * lpfc_resume_fabric_iocbs: Issue a fabric iocb from driver internal list.
+ * lpfc_resume_fabric_iocbs - Issue a fabric iocb from driver internal list
* @phba: pointer to lpfc hba data structure.
*
* This routine issues one fabric iocb from the driver internal list to
}
/**
- * lpfc_unblock_fabric_iocbs: Unblock issuing fabric iocb command.
+ * lpfc_unblock_fabric_iocbs - Unblock issuing fabric iocb command
* @phba: pointer to lpfc hba data structure.
*
* This routine unblocks the issuing fabric iocb command. The function
}
/**
- * lpfc_block_fabric_iocbs: Block issuing fabric iocb command.
+ * lpfc_block_fabric_iocbs - Block issuing fabric iocb command
* @phba: pointer to lpfc hba data structure.
*
* This routine blocks the issuing fabric iocb for a specified amount of
}
/**
- * lpfc_cmpl_fabric_iocb: Completion callback function for fabric iocb.
+ * lpfc_cmpl_fabric_iocb - Completion callback function for fabric iocb
* @phba: pointer to lpfc hba data structure.
* @cmdiocb: pointer to lpfc command iocb data structure.
* @rspiocb: pointer to lpfc response iocb data structure.
}
/**
- * lpfc_issue_fabric_iocb: Issue a fabric iocb command.
+ * lpfc_issue_fabric_iocb - Issue a fabric iocb command
* @phba: pointer to lpfc hba data structure.
* @iocb: pointer to lpfc command iocb data structure.
*
}
/**
- * lpfc_fabric_abort_vport: Abort a vport's iocbs from driver fabric iocb list.
+ * lpfc_fabric_abort_vport - Abort a vport's iocbs from driver fabric iocb list
* @vport: pointer to a virtual N_Port data structure.
*
* This routine aborts all the IOCBs associated with a @vport from the
LIST_HEAD(completions);
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *tmp_iocb, *piocb;
- IOCB_t *cmd;
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&piocb->list);
-
- cmd = &piocb->iocb;
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
/**
- * lpfc_fabric_abort_nport: Abort a ndlp's iocbs from driver fabric iocb list.
+ * lpfc_fabric_abort_nport - Abort a ndlp's iocbs from driver fabric iocb list
* @ndlp: pointer to a node-list data structure.
*
* This routine aborts all the IOCBs associated with an @ndlp from the
void lpfc_fabric_abort_nport(struct lpfc_nodelist *ndlp)
{
LIST_HEAD(completions);
- struct lpfc_hba *phba = ndlp->vport->phba;
+ struct lpfc_hba *phba = ndlp->phba;
struct lpfc_iocbq *tmp_iocb, *piocb;
struct lpfc_sli_ring *pring = &phba->sli.ring[LPFC_ELS_RING];
- IOCB_t *cmd;
spin_lock_irq(&phba->hbalock);
list_for_each_entry_safe(piocb, tmp_iocb, &phba->fabric_iocb_list,
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&piocb->list);
-
- cmd = &piocb->iocb;
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
/**
- * lpfc_fabric_abort_hba: Abort all iocbs on driver fabric iocb list.
+ * lpfc_fabric_abort_hba - Abort all iocbs on driver fabric iocb list
* @phba: pointer to lpfc hba data structure.
*
* This routine aborts all the IOCBs currently on the driver internal
void lpfc_fabric_abort_hba(struct lpfc_hba *phba)
{
LIST_HEAD(completions);
- struct lpfc_iocbq *piocb;
- IOCB_t *cmd;
spin_lock_irq(&phba->hbalock);
list_splice_init(&phba->fabric_iocb_list, &completions);
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- piocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&piocb->list);
-
- cmd = &piocb->iocb;
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (piocb->iocb_cmpl) (phba, piocb, piocb);
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
return;
}
- phba = ndlp->vport->phba;
+ phba = ndlp->phba;
lpfc_debugfs_disc_trc(ndlp->vport, LPFC_DISC_TRC_RPORT,
"rport terminate: sid:x%x did:x%x flg:x%x",
}
/**
- * lpfc_alloc_fast_evt: Allocates data structure for posting event.
+ * lpfc_alloc_fast_evt - Allocates data structure for posting event
* @phba: Pointer to hba context object.
*
* This function is called from the functions which need to post
}
/**
- * lpfc_free_fast_evt: Frees event data structure.
+ * lpfc_free_fast_evt - Frees event data structure
* @phba: Pointer to hba context object.
* @evt: Event object which need to be freed.
*
}
/**
- * lpfc_send_fastpath_evt: Posts events generated from fast path.
+ * lpfc_send_fastpath_evt - Posts events generated from fast path
* @phba: Pointer to hba context object.
* @evtp: Event data structure.
*
NLP_STE_UNUSED_NODE);
}
/**
- * lpfc_initialize_node: Initialize all fields of node object.
+ * lpfc_initialize_node - Initialize all fields of node object
* @vport: Pointer to Virtual Port object.
* @ndlp: Pointer to FC node object.
* @did: FC_ID of the node.
- * This function is always called when node object need to
- * be initialized. It initializes all the fields of the node
- * object.
+ *
+ * This function is always called when node object need to be initialized.
+ * It initializes all the fields of the node object. Although the reference
+ * to phba from @ndlp can be obtained indirectly through it's reference to
+ * @vport, a direct reference to phba is taken here by @ndlp. This is due
+ * to the life-span of the @ndlp might go beyond the existence of @vport as
+ * the final release of ndlp is determined by its reference count. And, the
+ * operation on @ndlp needs the reference to phba.
**/
static inline void
lpfc_initialize_node(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp,
ndlp->nlp_delayfunc.data = (unsigned long)ndlp;
ndlp->nlp_DID = did;
ndlp->vport = vport;
+ ndlp->phba = vport->phba;
ndlp->nlp_sid = NLP_NO_SID;
kref_init(&ndlp->kref);
NLP_INT_NODE_ACT(ndlp);
struct lpfc_sli *psli;
struct lpfc_sli_ring *pring;
struct lpfc_iocbq *iocb, *next_iocb;
- IOCB_t *icmd;
uint32_t rpi, i;
lpfc_fabric_abort_nport(ndlp);
}
}
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- icmd = &iocb->iocb;
- icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl)(phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
return 0;
}
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->context1 = NULL;
rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
- if (rc == MBX_NOT_FINISHED) {
+ if (rc != MBX_TIMEOUT)
mempool_free(mbox, phba->mbox_mem_pool);
- }
+
+ if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED))
+ lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
+ "1836 Could not issue "
+ "unreg_login(all_rpis) status %d\n", rc);
}
}
mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
mbox->context1 = NULL;
rc = lpfc_sli_issue_mbox_wait(phba, mbox, LPFC_MBOX_TMO);
- if (rc == MBX_NOT_FINISHED) {
+ if (rc != MBX_TIMEOUT)
+ mempool_free(mbox, phba->mbox_mem_pool);
+
+ if ((rc == MBX_TIMEOUT) || (rc == MBX_NOT_FINISHED))
lpfc_printf_vlog(vport, KERN_ERR, LOG_MBOX | LOG_VPORT,
"1815 Could not issue "
- "unreg_did (default rpis)\n");
- mempool_free(mbox, phba->mbox_mem_pool);
- }
+ "unreg_did (default rpis) status %d\n",
+ rc);
}
}
if (ndlp->nlp_flag & NLP_RCV_PLOGI)
return NULL;
- spin_lock_irq(shost->host_lock);
- ndlp->nlp_flag |= NLP_NPR_2B_DISC;
- spin_unlock_irq(shost->host_lock);
-
/* Since this node is marked for discovery,
* delay timeout is not needed.
*/
lpfc_cancel_retry_delay_tmo(vport, ndlp);
+ spin_lock_irq(shost->host_lock);
+ ndlp->nlp_flag |= NLP_NPR_2B_DISC;
+ spin_unlock_irq(shost->host_lock);
} else
ndlp = NULL;
} else {
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq, list);
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- icmd = &iocb->iocb;
- icmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- icmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
static void
lpfc_nlp_remove(ndlp->vport, ndlp);
/* clear the ndlp active flag for all release cases */
- phba = ndlp->vport->phba;
+ phba = ndlp->phba;
spin_lock_irqsave(&phba->ndlp_lock, flags);
NLP_CLR_NODE_ACT(ndlp);
spin_unlock_irqrestore(&phba->ndlp_lock, flags);
/* free ndlp memory for final ndlp release */
if (NLP_CHK_FREE_REQ(ndlp)) {
kfree(ndlp->lat_data);
- mempool_free(ndlp, ndlp->vport->phba->nlp_mem_pool);
+ mempool_free(ndlp, ndlp->phba->nlp_mem_pool);
}
}
* ndlp reference count that is in the process of being
* released.
*/
- phba = ndlp->vport->phba;
+ phba = ndlp->phba;
spin_lock_irqsave(&phba->ndlp_lock, flags);
if (!NLP_CHK_NODE_ACT(ndlp) || NLP_CHK_FREE_ACK(ndlp)) {
spin_unlock_irqrestore(&phba->ndlp_lock, flags);
"node put: did:x%x flg:x%x refcnt:x%x",
ndlp->nlp_DID, ndlp->nlp_flag,
atomic_read(&ndlp->kref.refcount));
- phba = ndlp->vport->phba;
+ phba = ndlp->phba;
spin_lock_irqsave(&phba->ndlp_lock, flags);
/* Check the ndlp memory free acknowledge flag to avoid the
* possible race condition that kref_put got invoked again
static DEFINE_IDR(lpfc_hba_index);
/**
- * lpfc_config_port_prep: Perform lpfc initialization prior to config port.
+ * lpfc_config_port_prep - Perform lpfc initialization prior to config port
* @phba: pointer to lpfc hba data structure.
*
* This routine will do LPFC initialization prior to issuing the CONFIG_PORT
}
/**
- * lpfc_config_async_cmpl: Completion handler for config async event mbox cmd.
+ * lpfc_config_async_cmpl - Completion handler for config async event mbox cmd
* @phba: pointer to lpfc hba data structure.
* @pmboxq: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_dump_wakeup_param_cmpl: Completion handler for dump memory mailbox
- * command used for getting wake up parameters.
+ * lpfc_dump_wakeup_param_cmpl - dump memory mailbox command completion handler
* @phba: pointer to lpfc hba data structure.
* @pmboxq: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_config_port_post: Perform lpfc initialization after config port.
+ * lpfc_config_port_post - Perform lpfc initialization after config port
* @phba: pointer to lpfc hba data structure.
*
* This routine will do LPFC initialization after the CONFIG_PORT mailbox
lpfc_config_port_post(struct lpfc_hba *phba)
{
struct lpfc_vport *vport = phba->pport;
+ struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
LPFC_MBOXQ_t *pmb;
MAILBOX_t *mb;
struct lpfc_dmabuf *mp;
sizeof (struct lpfc_name));
memcpy(&vport->fc_portname, &vport->fc_sparam.portName,
sizeof (struct lpfc_name));
+
+ /* Update the fc_host data structures with new wwn. */
+ fc_host_node_name(shost) = wwn_to_u64(vport->fc_nodename.u.wwn);
+ fc_host_port_name(shost) = wwn_to_u64(vport->fc_portname.u.wwn);
+
/* If no serial number in VPD data, use low 6 bytes of WWNN */
/* This should be consolidated into parse_vpd ? - mr */
if (phba->SerialNumber[0] == 0) {
}
/**
- * lpfc_hba_down_prep: Perform lpfc uninitialization prior to HBA reset.
+ * lpfc_hba_down_prep - Perform lpfc uninitialization prior to HBA reset
* @phba: pointer to lpfc HBA data structure.
*
* This routine will do LPFC uninitialization before the HBA is reset when
}
/**
- * lpfc_hba_down_post: Perform lpfc uninitialization after HBA reset.
+ * lpfc_hba_down_post - Perform lpfc uninitialization after HBA reset
* @phba: pointer to lpfc HBA data structure.
*
* This routine will do uninitialization after the HBA is reset when bring
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
struct lpfc_dmabuf *mp, *next_mp;
- struct lpfc_iocbq *iocb;
- IOCB_t *cmd = NULL;
LIST_HEAD(completions);
int i;
pring->txcmplq_cnt = 0;
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq,
- list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
lpfc_sli_abort_iocb_ring(phba, pring);
spin_lock_irq(&phba->hbalock);
}
/**
- * lpfc_hb_timeout: The HBA-timer timeout handler.
+ * lpfc_hb_timeout - The HBA-timer timeout handler
* @ptr: unsigned long holds the pointer to lpfc hba data structure.
*
* This is the HBA-timer timeout handler registered to the lpfc driver. When
}
/**
- * lpfc_hb_mbox_cmpl: The lpfc heart-beat mailbox command callback function.
+ * lpfc_hb_mbox_cmpl - The lpfc heart-beat mailbox command callback function
* @phba: pointer to lpfc hba data structure.
* @pmboxq: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_hb_timeout_handler: The HBA-timer timeout handler.
+ * lpfc_hb_timeout_handler - The HBA-timer timeout handler
* @phba: pointer to lpfc hba data structure.
*
* This is the actual HBA-timer timeout handler to be invoked by the worker
}
/**
- * lpfc_offline_eratt: Bring lpfc offline on hardware error attention.
+ * lpfc_offline_eratt - Bring lpfc offline on hardware error attention
* @phba: pointer to lpfc hba data structure.
*
* This routine is called to bring the HBA offline when HBA hardware error
}
/**
- * lpfc_handle_eratt: The HBA hardware error handler.
+ * lpfc_handle_deferred_eratt - The HBA hardware deferred error handler
+ * @phba: pointer to lpfc hba data structure.
+ *
+ * This routine is invoked to handle the deferred HBA hardware error
+ * conditions. This type of error is indicated by HBA by setting ER1
+ * and another ER bit in the host status register. The driver will
+ * wait until the ER1 bit clears before handling the error condition.
+ **/
+static void
+lpfc_handle_deferred_eratt(struct lpfc_hba *phba)
+{
+ uint32_t old_host_status = phba->work_hs;
+ struct lpfc_sli_ring *pring;
+ struct lpfc_sli *psli = &phba->sli;
+
+ lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+ "0479 Deferred Adapter Hardware Error "
+ "Data: x%x x%x x%x\n",
+ phba->work_hs,
+ phba->work_status[0], phba->work_status[1]);
+
+ spin_lock_irq(&phba->hbalock);
+ psli->sli_flag &= ~LPFC_SLI2_ACTIVE;
+ spin_unlock_irq(&phba->hbalock);
+
+
+ /*
+ * Firmware stops when it triggred erratt. That could cause the I/Os
+ * dropped by the firmware. Error iocb (I/O) on txcmplq and let the
+ * SCSI layer retry it after re-establishing link.
+ */
+ pring = &psli->ring[psli->fcp_ring];
+ lpfc_sli_abort_iocb_ring(phba, pring);
+
+ /*
+ * There was a firmware error. Take the hba offline and then
+ * attempt to restart it.
+ */
+ lpfc_offline_prep(phba);
+ lpfc_offline(phba);
+
+ /* Wait for the ER1 bit to clear.*/
+ while (phba->work_hs & HS_FFER1) {
+ msleep(100);
+ phba->work_hs = readl(phba->HSregaddr);
+ /* If driver is unloading let the worker thread continue */
+ if (phba->pport->load_flag & FC_UNLOADING) {
+ phba->work_hs = 0;
+ break;
+ }
+ }
+
+ /*
+ * This is to ptrotect against a race condition in which
+ * first write to the host attention register clear the
+ * host status register.
+ */
+ if ((!phba->work_hs) && (!(phba->pport->load_flag & FC_UNLOADING)))
+ phba->work_hs = old_host_status & ~HS_FFER1;
+
+ phba->hba_flag &= ~DEFER_ERATT;
+ phba->work_status[0] = readl(phba->MBslimaddr + 0xa8);
+ phba->work_status[1] = readl(phba->MBslimaddr + 0xac);
+}
+
+/**
+ * lpfc_handle_eratt - The HBA hardware error handler
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to handle the following HBA hardware error
(char *) &board_event,
LPFC_NL_VENDOR_ID);
+ if (phba->hba_flag & DEFER_ERATT)
+ lpfc_handle_deferred_eratt(phba);
+
if (phba->work_hs & HS_FFER6) {
/* Re-establishing Link */
lpfc_printf_log(phba, KERN_INFO, LOG_LINK_EVENT,
}
/**
- * lpfc_handle_latt: The HBA link event handler.
+ * lpfc_handle_latt - The HBA link event handler
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked from the worker thread to handle a HBA host
}
/**
- * lpfc_parse_vpd: Parse VPD (Vital Product Data).
+ * lpfc_parse_vpd - Parse VPD (Vital Product Data)
* @phba: pointer to lpfc hba data structure.
* @vpd: pointer to the vital product data.
* @len: length of the vital product data in bytes.
}
/**
- * lpfc_get_hba_model_desc: Retrieve HBA device model name and description.
+ * lpfc_get_hba_model_desc - Retrieve HBA device model name and description
* @phba: pointer to lpfc hba data structure.
* @mdp: pointer to the data structure to hold the derived model name.
* @descp: pointer to the data structure to hold the derived description.
m = (typeof(m)){"LPe11000", max_speed, "PCIe"};
break;
case PCI_DEVICE_ID_ZEPHYR_DCSP:
- m = (typeof(m)){"LPe11002-SP", max_speed, "PCIe"};
+ m = (typeof(m)){"LP2105", max_speed, "PCIe"};
+ GE = 1;
break;
case PCI_DEVICE_ID_ZMID:
m = (typeof(m)){"LPe1150", max_speed, "PCIe"};
}
/**
- * lpfc_post_buffer: Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring.
+ * lpfc_post_buffer - Post IOCB(s) with DMA buffer descriptor(s) to a IOCB ring
* @phba: pointer to lpfc hba data structure.
* @pring: pointer to a IOCB ring.
* @cnt: the number of IOCBs to be posted to the IOCB ring.
}
/**
- * lpfc_post_rcv_buf: Post the initial receive IOCB buffers to ELS ring.
+ * lpfc_post_rcv_buf - Post the initial receive IOCB buffers to ELS ring
* @phba: pointer to lpfc hba data structure.
*
* This routine posts initial receive IOCB buffers to the ELS ring. The
#define S(N,V) (((V)<<(N))|((V)>>(32-(N))))
/**
- * lpfc_sha_init: Set up initial array of hash table entries.
+ * lpfc_sha_init - Set up initial array of hash table entries
* @HashResultPointer: pointer to an array as hash table.
*
* This routine sets up the initial values to the array of hash table entries
}
/**
- * lpfc_sha_iterate: Iterate initial hash table with the working hash table.
+ * lpfc_sha_iterate - Iterate initial hash table with the working hash table
* @HashResultPointer: pointer to an initial/result hash table.
* @HashWorkingPointer: pointer to an working hash table.
*
}
/**
- * lpfc_challenge_key: Create challenge key based on WWPN of the HBA.
+ * lpfc_challenge_key - Create challenge key based on WWPN of the HBA
* @RandomChallenge: pointer to the entry of host challenge random number array.
* @HashWorking: pointer to the entry of the working hash array.
*
}
/**
- * lpfc_hba_init: Perform special handling for LC HBA initialization.
+ * lpfc_hba_init - Perform special handling for LC HBA initialization
* @phba: pointer to lpfc hba data structure.
* @hbainit: pointer to an array of unsigned 32-bit integers.
*
}
/**
- * lpfc_cleanup: Performs vport cleanups before deleting a vport.
+ * lpfc_cleanup - Performs vport cleanups before deleting a vport
* @vport: pointer to a virtual N_Port data structure.
*
* This routine performs the necessary cleanups before deleting the @vport.
}
/**
- * lpfc_stop_vport_timers: Stop all the timers associated with a vport.
+ * lpfc_stop_vport_timers - Stop all the timers associated with a vport
* @vport: pointer to a virtual N_Port data structure.
*
* This routine stops all the timers associated with a @vport. This function
}
/**
- * lpfc_stop_phba_timers: Stop all the timers associated with an HBA.
+ * lpfc_stop_phba_timers - Stop all the timers associated with an HBA
* @phba: pointer to lpfc hba data structure.
*
* This routine stops all the timers associated with a HBA. This function is
}
/**
- * lpfc_block_mgmt_io: Mark a HBA's management interface as blocked.
+ * lpfc_block_mgmt_io - Mark a HBA's management interface as blocked
* @phba: pointer to lpfc hba data structure.
*
* This routine marks a HBA's management interface as blocked. Once the HBA's
}
/**
- * lpfc_online: Initialize and bring a HBA online.
+ * lpfc_online - Initialize and bring a HBA online
* @phba: pointer to lpfc hba data structure.
*
* This routine initializes the HBA and brings a HBA online. During this
}
/**
- * lpfc_unblock_mgmt_io: Mark a HBA's management interface to be not blocked.
+ * lpfc_unblock_mgmt_io - Mark a HBA's management interface to be not blocked
* @phba: pointer to lpfc hba data structure.
*
* This routine marks a HBA's management interface as not blocked. Once the
}
/**
- * lpfc_offline_prep: Prepare a HBA to be brought offline.
+ * lpfc_offline_prep - Prepare a HBA to be brought offline
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to prepare a HBA to be brought offline. It performs
}
/**
- * lpfc_offline: Bring a HBA offline.
+ * lpfc_offline - Bring a HBA offline
* @phba: pointer to lpfc hba data structure.
*
* This routine actually brings a HBA offline. It stops all the timers
}
/**
- * lpfc_scsi_free: Free all the SCSI buffers and IOCBs from driver lists.
+ * lpfc_scsi_free - Free all the SCSI buffers and IOCBs from driver lists
* @phba: pointer to lpfc hba data structure.
*
* This routine is to free all the SCSI buffers and IOCBs from the driver
}
/**
- * lpfc_create_port: Create an FC port.
+ * lpfc_create_port - Create an FC port
* @phba: pointer to lpfc hba data structure.
* @instance: a unique integer ID to this FC port.
* @dev: pointer to the device data structure.
}
/**
- * destroy_port: Destroy an FC port.
+ * destroy_port - destroy an FC port
* @vport: pointer to an lpfc virtual N_Port data structure.
*
* This routine destroys a FC port from the upper layer protocol. All the
}
/**
- * lpfc_get_instance: Get a unique integer ID.
+ * lpfc_get_instance - Get a unique integer ID
*
* This routine allocates a unique integer ID from lpfc_hba_index pool. It
* uses the kernel idr facility to perform the task.
}
/**
- * lpfc_scan_finished: method for SCSI layer to detect whether scan is done.
+ * lpfc_scan_finished - method for SCSI layer to detect whether scan is done
* @shost: pointer to SCSI host data structure.
* @time: elapsed time of the scan in jiffies.
*
}
/**
- * lpfc_host_attrib_init: Initialize SCSI host attributes on a FC port.
+ * lpfc_host_attrib_init - Initialize SCSI host attributes on a FC port
* @shost: pointer to SCSI host data structure.
*
* This routine initializes a given SCSI host attributes on a FC port. The
}
/**
- * lpfc_enable_msix: Enable MSI-X interrupt mode.
+ * lpfc_enable_msix - Enable MSI-X interrupt mode
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to enable the MSI-X interrupt vectors. The kernel
}
/**
- * lpfc_disable_msix: Disable MSI-X interrupt mode.
+ * lpfc_disable_msix - Disable MSI-X interrupt mode
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to release the MSI-X vectors and then disable the
}
/**
- * lpfc_enable_msi: Enable MSI interrupt mode.
+ * lpfc_enable_msi - Enable MSI interrupt mode
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to enable the MSI interrupt mode. The kernel
}
/**
- * lpfc_disable_msi: Disable MSI interrupt mode.
+ * lpfc_disable_msi - Disable MSI interrupt mode
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to disable the MSI interrupt mode. The driver
}
/**
- * lpfc_log_intr_mode: Log the active interrupt mode
+ * lpfc_log_intr_mode - Log the active interrupt mode
* @phba: pointer to lpfc hba data structure.
* @intr_mode: active interrupt mode adopted.
*
}
/**
- * lpfc_enable_intr: Enable device interrupt.
+ * lpfc_enable_intr - Enable device interrupt
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to enable device interrupt and associate driver's
}
/**
- * lpfc_disable_intr: Disable device interrupt.
+ * lpfc_disable_intr - Disable device interrupt
* @phba: pointer to lpfc hba data structure.
*
* This routine is invoked to disable device interrupt and disassociate the
}
/**
- * lpfc_pci_probe_one: lpfc PCI probe func to register device to PCI subsystem.
+ * lpfc_pci_probe_one - lpfc PCI probe func to register device to PCI subsystem
* @pdev: pointer to PCI device
* @pid: pointer to PCI device identifier
*
}
/**
- * lpfc_pci_remove_one: lpfc PCI func to unregister device from PCI subsystem.
+ * lpfc_pci_remove_one - lpfc PCI func to unregister device from PCI subsystem
* @pdev: pointer to PCI device
*
* This routine is to be registered to the kernel's PCI subsystem. When an
lpfc_free_sysfs_attr(vport);
- kthread_stop(phba->worker_thread);
-
/* Release all the vports against this physical port */
vports = lpfc_create_vport_work_array(phba);
if (vports != NULL)
* clears the rings, discards all mailbox commands, and resets
* the HBA.
*/
+
+ /* HBA interrupt will be diabled after this call */
lpfc_sli_hba_down(phba);
+ /* Stop kthread signal shall trigger work_done one more time */
+ kthread_stop(phba->worker_thread);
+ /* Final cleanup of txcmplq and reset the HBA */
lpfc_sli_brdrestart(phba);
lpfc_stop_phba_timers(phba);
}
/**
- * lpfc_pci_suspend_one: lpfc PCI func to suspend device for power management.
+ * lpfc_pci_suspend_one - lpfc PCI func to suspend device for power management
* @pdev: pointer to PCI device
* @msg: power management message
*
}
/**
- * lpfc_pci_resume_one: lpfc PCI func to resume device for power management.
+ * lpfc_pci_resume_one - lpfc PCI func to resume device for power management
* @pdev: pointer to PCI device
*
* This routine is to be registered to the kernel's PCI subsystem to support
}
/**
- * lpfc_io_error_detected: Driver method for handling PCI I/O error detected.
+ * lpfc_io_error_detected - Driver method for handling PCI I/O error detected
* @pdev: pointer to PCI device.
* @state: the current PCI connection state.
*
}
/**
- * lpfc_io_slot_reset: Restart a PCI device from scratch.
+ * lpfc_io_slot_reset - Restart a PCI device from scratch
* @pdev: pointer to PCI device.
*
* This routine is registered to the PCI subsystem for error handling. This is
}
/**
- * lpfc_io_resume: Resume PCI I/O operation.
+ * lpfc_io_resume - Resume PCI I/O operation
* @pdev: pointer to PCI device
*
* This routine is registered to the PCI subsystem for error handling. It is
};
/**
- * lpfc_init: lpfc module initialization routine.
+ * lpfc_init - lpfc module initialization routine
*
* This routine is to be invoked when the lpfc module is loaded into the
* kernel. The special kernel macro module_init() is used to indicate the
}
/**
- * lpfc_exit: lpfc module removal routine.
+ * lpfc_exit - lpfc module removal routine
*
* This routine is invoked when the lpfc module is removed from the kernel.
* The special kernel macro module_exit() is used to indicate the role of
#define LOG_FCP 0x40 /* FCP traffic history */
#define LOG_NODE 0x80 /* Node table events */
#define LOG_TEMP 0x100 /* Temperature sensor events */
-#define LOG_BG 0x200 /* BlockBuard events */
+#define LOG_BG 0x200 /* BlockGuard events */
#define LOG_MISC 0x400 /* Miscellaneous events */
#define LOG_SLI 0x800 /* SLI events */
#define LOG_FCP_ERROR 0x1000 /* log errors, not underruns */
#include "lpfc_compat.h"
/**
- * lpfc_dump_mem: Prepare a mailbox command for retrieving HBA's VPD memory.
+ * lpfc_dump_mem - Prepare a mailbox command for retrieving HBA's VPD memory
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @offset: offset for dumping VPD memory mailbox command.
}
/**
- * lpfc_dump_mem: Prepare a mailbox command for retrieving wakeup params.
+ * lpfc_dump_wakeup_param - Prepare mailbox command for retrieving wakeup params
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
+ *
* This function create a dump memory mailbox command to dump wake up
* parameters.
*/
}
/**
- * lpfc_read_nv: Prepare a mailbox command for reading HBA's NVRAM param.
+ * lpfc_read_nv - Prepare a mailbox command for reading HBA's NVRAM param
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_config_async: Prepare a mailbox command for enabling HBA async event.
+ * lpfc_config_async - Prepare a mailbox command for enabling HBA async event
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @ring: ring number for the asynchronous event to be configured.
}
/**
- * lpfc_heart_beat: Prepare a mailbox command for heart beat.
+ * lpfc_heart_beat - Prepare a mailbox command for heart beat
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_read_la: Prepare a mailbox command for reading HBA link attention.
+ * lpfc_read_la - Prepare a mailbox command for reading HBA link attention
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @mp: DMA buffer memory for reading the link attention information into.
}
/**
- * lpfc_clear_la: Prepare a mailbox command for clearing HBA link attention.
+ * lpfc_clear_la - Prepare a mailbox command for clearing HBA link attention
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_config_link: Prepare a mailbox command for configuring link on a HBA.
+ * lpfc_config_link - Prepare a mailbox command for configuring link on a HBA
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_config_msi: Prepare a mailbox command for configuring msi-x.
+ * lpfc_config_msi - Prepare a mailbox command for configuring msi-x
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_init_link: Prepare a mailbox command for initialize link on a HBA.
+ * lpfc_init_link - Prepare a mailbox command for initialize link on a HBA
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @topology: the link topology for the link to be initialized to.
}
/**
- * lpfc_read_sparam: Prepare a mailbox command for reading HBA parameters.
+ * lpfc_read_sparam - Prepare a mailbox command for reading HBA parameters
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
* @vpi: virtual N_Port identifier.
}
/**
- * lpfc_unreg_did: Prepare a mailbox command for unregistering DID.
+ * lpfc_unreg_did - Prepare a mailbox command for unregistering DID
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @did: remote port identifier.
}
/**
- * lpfc_read_config: Prepare a mailbox command for reading HBA configuration.
+ * lpfc_read_config - Prepare a mailbox command for reading HBA configuration
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_read_lnk_stat: Prepare a mailbox command for reading HBA link stats.
+ * lpfc_read_lnk_stat - Prepare a mailbox command for reading HBA link stats
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_reg_login: Prepare a mailbox command for registering remote login.
+ * lpfc_reg_login - Prepare a mailbox command for registering remote login
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @did: remote port identifier.
}
/**
- * lpfc_unreg_login: Prepare a mailbox command for unregistering remote login.
+ * lpfc_unreg_login - Prepare a mailbox command for unregistering remote login
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @rpi: remote port identifier
}
/**
- * lpfc_reg_vpi: Prepare a mailbox command for registering vport identifier.
+ * lpfc_reg_vpi - Prepare a mailbox command for registering vport identifier
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @sid: Fibre Channel S_ID (N_Port_ID assigned to a virtual N_Port).
}
/**
- * lpfc_unreg_vpi: Prepare a mailbox command for unregistering vport id.
+ * lpfc_unreg_vpi - Prepare a mailbox command for unregistering vport id
* @phba: pointer to lpfc hba data structure.
* @vpi: virtual N_Port identifier.
* @pmb: pointer to the driver internal queue element for mailbox command.
}
/**
- * lpfc_config_pcb_setup: Set up IOCB rings in the Port Control Block (PCB)
+ * lpfc_config_pcb_setup - Set up IOCB rings in the Port Control Block (PCB)
* @phba: pointer to lpfc hba data structure.
*
* This routine sets up and initializes the IOCB rings in the Port Control
}
/**
- * lpfc_read_rev: Prepare a mailbox command for reading HBA revision.
+ * lpfc_read_rev - Prepare a mailbox command for reading HBA revision
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_build_hbq_profile2: Set up the HBQ Selection Profile 2.
+ * lpfc_build_hbq_profile2 - Set up the HBQ Selection Profile 2
* @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
* @hbq_desc: pointer to the HBQ selection profile descriptor.
*
}
/**
- * lpfc_build_hbq_profile3: Set up the HBQ Selection Profile 3.
+ * lpfc_build_hbq_profile3 - Set up the HBQ Selection Profile 3
* @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
* @hbq_desc: pointer to the HBQ selection profile descriptor.
*
}
/**
- * lpfc_build_hbq_profile5: Set up the HBQ Selection Profile 5.
+ * lpfc_build_hbq_profile5 - Set up the HBQ Selection Profile 5
* @hbqmb: pointer to the HBQ configuration data structure in mailbox command.
* @hbq_desc: pointer to the HBQ selection profile descriptor.
*
}
/**
- * lpfc_config_hbq: Prepare a mailbox command for configuring an HBQ.
+ * lpfc_config_hbq - Prepare a mailbox command for configuring an HBQ
* @phba: pointer to lpfc hba data structure.
* @id: HBQ identifier.
* @hbq_desc: pointer to the HBA descriptor data structure.
}
/**
- * lpfc_config_ring: Prepare a mailbox command for configuring an IOCB ring.
+ * lpfc_config_ring - Prepare a mailbox command for configuring an IOCB ring
* @phba: pointer to lpfc hba data structure.
* @ring:
* @pmb: pointer to the driver internal queue element for mailbox command.
}
/**
- * lpfc_config_port: Prepare a mailbox command for configuring port.
+ * lpfc_config_port - Prepare a mailbox command for configuring port
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_kill_board: Prepare a mailbox command for killing board.
+ * lpfc_kill_board - Prepare a mailbox command for killing board
* @phba: pointer to lpfc hba data structure.
* @pmb: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_mbox_put: Put a mailbox cmd into the tail of driver's mailbox queue.
+ * lpfc_mbox_put - Put a mailbox cmd into the tail of driver's mailbox queue
* @phba: pointer to lpfc hba data structure.
* @mbq: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_mbox_get: Remove a mailbox cmd from the head of driver's mailbox queue.
+ * lpfc_mbox_get - Remove a mailbox cmd from the head of driver's mailbox queue
* @phba: pointer to lpfc hba data structure.
*
* Driver maintains a internal mailbox command queue implemented as a linked
}
/**
- * lpfc_mbox_cmpl_put: Put mailbox command into mailbox command complete list.
+ * lpfc_mbox_cmpl_put - Put mailbox command into mailbox command complete list
* @phba: pointer to lpfc hba data structure.
* @mbq: pointer to the driver internal queue element for mailbox command.
*
}
/**
- * lpfc_mbox_tmo_val: Retrieve mailbox command timeout value.
+ * lpfc_mbox_tmo_val - Retrieve mailbox command timeout value
* @phba: pointer to lpfc hba data structure.
* @cmd: mailbox command code.
*
/**
- * lpfc_mem_alloc: create and allocate all PCI and memory pools
+ * lpfc_mem_alloc - create and allocate all PCI and memory pools
* @phba: HBA to allocate pools for
*
* Description: Creates and allocates PCI pools lpfc_scsi_dma_buf_pool,
}
/**
- * lpfc_mem_free: Frees all PCI and memory allocated by lpfc_mem_alloc
+ * lpfc_mem_free - Frees all PCI and memory allocated by lpfc_mem_alloc
* @phba: HBA to free memory for
*
* Description: Frees PCI pools lpfc_scsi_dma_buf_pool, lpfc_mbuf_pool,
* lpfc_hbq_pool. Frees kmalloc-backed mempools for LPFC_MBOXQ_t and
- * lpfc_nodelist. Also frees the VPI bitmask.
+ * lpfc_nodelist. Also frees the VPI bitmask
*
* Returns: None
**/
}
/**
- * lpfc_mbuf_alloc: Allocate an mbuf from the lpfc_mbuf_pool PCI pool
+ * lpfc_mbuf_alloc - Allocate an mbuf from the lpfc_mbuf_pool PCI pool
* @phba: HBA which owns the pool to allocate from
* @mem_flags: indicates if this is a priority (MEM_PRI) allocation
* @handle: used to return the DMA-mapped address of the mbuf
}
/**
- * __lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (locked)
+ * __lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (locked)
* @phba: HBA which owns the pool to return to
* @virt: mbuf to free
* @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
}
/**
- * lpfc_mem_free: Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked)
+ * lpfc_mbuf_free - Free an mbuf from the lpfc_mbuf_pool PCI pool (unlocked)
* @phba: HBA which owns the pool to return to
* @virt: mbuf to free
* @dma: the DMA-mapped address of the lpfc_mbuf_pool to be freed
* Returns: None
**/
void
-
lpfc_mbuf_free(struct lpfc_hba * phba, void *virt, dma_addr_t dma)
{
unsigned long iflags;
}
/**
- * lpfc_els_hbq_alloc: Allocate an HBQ buffer
+ * lpfc_els_hbq_alloc - Allocate an HBQ buffer
* @phba: HBA to allocate HBQ buffer for
*
* Description: Allocates a DMA-mapped HBQ buffer from the lpfc_hbq_pool PCI
}
/**
- * lpfc_mem_hbq_free: Frees an HBQ buffer allocated with lpfc_els_hbq_alloc
+ * lpfc_mem_hbq_free - Frees an HBQ buffer allocated with lpfc_els_hbq_alloc
* @phba: HBA buffer was allocated for
* @hbqbp: HBQ container returned by lpfc_els_hbq_alloc
*
}
/**
- * lpfc_in_buf_free: Free a DMA buffer
+ * lpfc_in_buf_free - Free a DMA buffer
* @phba: HBA buffer is associated with
* @mp: Buffer to free
*
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring = &psli->ring[LPFC_ELS_RING];
struct lpfc_iocbq *iocb, *next_iocb;
- IOCB_t *cmd;
/* Abort outstanding I/O on NPort <nlp_DID> */
lpfc_printf_vlog(ndlp->vport, KERN_INFO, LOG_DISCOVERY,
}
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
+
lpfc_cancel_retry_delay_tmo(phba->pport, ndlp);
return 0;
}
}
/**
- * lpfc_update_stats: Update statistical data for the command completion.
+ * lpfc_update_stats - Update statistical data for the command completion
* @phba: Pointer to HBA object.
* @lpfc_cmd: lpfc scsi command object pointer.
*
}
/**
- * lpfc_send_sdev_queuedepth_change_event: Posts a queuedepth change
- * event.
+ * lpfc_send_sdev_queuedepth_change_event - Posts a queuedepth change event
* @phba: Pointer to HBA context object.
* @vport: Pointer to vport object.
* @ndlp: Pointer to FC node associated with the target.
}
/**
- * lpfc_rampdown_queue_depth: Post RAMP_DOWN_QUEUE event to worker thread.
+ * lpfc_rampdown_queue_depth - Post RAMP_DOWN_QUEUE event to worker thread
* @phba: The Hba for which this call is being executed.
*
* This routine is called when there is resource error in driver or firmware.
}
/**
- * lpfc_rampup_queue_depth: Post RAMP_UP_QUEUE event for worker thread.
+ * lpfc_rampup_queue_depth - Post RAMP_UP_QUEUE event for worker thread
* @phba: The Hba for which this call is being executed.
*
* This routine post WORKER_RAMP_UP_QUEUE event for @phba vport. This routine
**/
static inline void
lpfc_rampup_queue_depth(struct lpfc_vport *vport,
- struct scsi_device *sdev)
+ uint32_t queue_depth)
{
unsigned long flags;
struct lpfc_hba *phba = vport->phba;
uint32_t evt_posted;
atomic_inc(&phba->num_cmd_success);
- if (vport->cfg_lun_queue_depth <= sdev->queue_depth)
+ if (vport->cfg_lun_queue_depth <= queue_depth)
return;
spin_lock_irqsave(&phba->hbalock, flags);
if (((phba->last_ramp_up_time + QUEUE_RAMP_UP_INTERVAL) > jiffies) ||
}
/**
- * lpfc_ramp_down_queue_handler: WORKER_RAMP_DOWN_QUEUE event handler.
+ * lpfc_ramp_down_queue_handler - WORKER_RAMP_DOWN_QUEUE event handler
* @phba: The Hba for which this call is being executed.
*
* This routine is called to process WORKER_RAMP_DOWN_QUEUE event for worker
}
/**
- * lpfc_ramp_up_queue_handler: WORKER_RAMP_UP_QUEUE event handler.
+ * lpfc_ramp_up_queue_handler - WORKER_RAMP_UP_QUEUE event handler
* @phba: The Hba for which this call is being executed.
*
* This routine is called to process WORKER_RAMP_UP_QUEUE event for worker
}
/**
- * lpfc_scsi_dev_block: set all scsi hosts to block state.
+ * lpfc_scsi_dev_block - set all scsi hosts to block state
* @phba: Pointer to HBA context object.
*
* This function walks vport list and set each SCSI host to block state
}
/**
- * lpfc_new_scsi_buf: Scsi buffer allocator.
+ * lpfc_new_scsi_buf - Scsi buffer allocator
* @vport: The virtual port for which this call being executed.
*
* This routine allocates a scsi buffer, which contains all the necessary
}
/**
- * lpfc_get_scsi_buf: Get a scsi buffer from lpfc_scsi_buf_list list of Hba.
+ * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list list of Hba
* @phba: The Hba for which this call is being executed.
*
* This routine removes a scsi buffer from head of @phba lpfc_scsi_buf_list list
}
/**
- * lpfc_release_scsi_buf: Return a scsi buffer back to hba lpfc_scsi_buf_list list.
+ * lpfc_release_scsi_buf - Return a scsi buffer back to hba's lpfc_scsi_buf_list
* @phba: The Hba for which this call is being executed.
* @psb: The scsi buffer which is being released.
*
}
/**
- * lpfc_scsi_prep_dma_buf: Routine to do DMA mapping for scsi buffer.
+ * lpfc_scsi_prep_dma_buf - Routine to do DMA mapping for scsi buffer
* @phba: The Hba for which this call is being executed.
* @lpfc_cmd: The scsi buffer which is going to be mapped.
*
* Due to difference in data length between DIF/non-DIF paths,
* we need to set word 4 of IOCB here
*/
- iocb_cmd->un.fcpi.fcpi_parm = le32_to_cpu(scsi_bufflen(scsi_cmnd));
+ iocb_cmd->un.fcpi.fcpi_parm = scsi_bufflen(scsi_cmnd);
return 0;
}
/**
* lpfc_get_cmd_dif_parms - Extract DIF parameters from SCSI command
* @sc: in: SCSI command
- * @apptagmask out: app tag mask
- * @apptagval out: app tag value
- * @reftag out: ref tag (reference tag)
+ * @apptagmask: out: app tag mask
+ * @apptagval: out: app tag value
+ * @reftag: out: ref tag (reference tag)
*
* Description:
* Extract DIF paramters from the command if possible. Otherwise,
}
/**
- * lpfc_send_scsi_error_event: Posts an event when there is SCSI error.
+ * lpfc_send_scsi_error_event - Posts an event when there is SCSI error
* @phba: Pointer to hba context object.
* @vport: Pointer to vport object.
* @lpfc_cmd: Pointer to lpfc scsi command which reported the error.
}
/**
- * lpfc_scsi_unprep_dma_buf: Routine to un-map DMA mapping of scatter gather.
+ * lpfc_scsi_unprep_dma_buf - Routine to un-map DMA mapping of scatter gather
* @phba: The Hba for which this call is being executed.
* @psb: The scsi buffer which is going to be un-mapped.
*
}
/**
- * lpfc_handler_fcp_err: FCP response handler.
+ * lpfc_handler_fcp_err - FCP response handler
* @vport: The virtual port for which this call is being executed.
* @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
* @rsp_iocb: The response IOCB which contains FCP error.
}
/**
- * lpfc_scsi_cmd_iocb_cmpl: Scsi cmnd IOCB completion routine.
+ * lpfc_scsi_cmd_iocb_cmpl - Scsi cmnd IOCB completion routine
* @phba: The Hba for which this call is being executed.
* @pIocbIn: The command IOCBQ for the scsi cmnd.
* @pIocbOut: The response IOCBQ for the scsi cmnd .
struct lpfc_nodelist *pnode = rdata->pnode;
struct scsi_cmnd *cmd = lpfc_cmd->pCmd;
int result;
- struct scsi_device *sdev, *tmp_sdev;
+ struct scsi_device *tmp_sdev;
int depth = 0;
unsigned long flags;
struct lpfc_fast_path_event *fast_path_evt;
+ struct Scsi_Host *shost = cmd->device->host;
+ uint32_t queue_depth, scsi_id;
lpfc_cmd->result = pIocbOut->iocb.un.ulpWord[4];
lpfc_cmd->status = pIocbOut->iocb.ulpStatus;
lpfc_update_stats(phba, lpfc_cmd);
result = cmd->result;
- sdev = cmd->device;
if (vport->cfg_max_scsicmpl_time &&
time_after(jiffies, lpfc_cmd->start_time +
msecs_to_jiffies(vport->cfg_max_scsicmpl_time))) {
- spin_lock_irqsave(sdev->host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
if (pnode && NLP_CHK_NODE_ACT(pnode)) {
if (pnode->cmd_qdepth >
atomic_read(&pnode->cmd_pending) &&
pnode->last_change_time = jiffies;
}
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
} else if (pnode && NLP_CHK_NODE_ACT(pnode)) {
if ((pnode->cmd_qdepth < LPFC_MAX_TGT_QDEPTH) &&
time_after(jiffies, pnode->last_change_time +
msecs_to_jiffies(LPFC_TGTQ_INTERVAL))) {
- spin_lock_irqsave(sdev->host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
pnode->cmd_qdepth += pnode->cmd_qdepth *
LPFC_TGTQ_RAMPUP_PCENT / 100;
if (pnode->cmd_qdepth > LPFC_MAX_TGT_QDEPTH)
pnode->cmd_qdepth = LPFC_MAX_TGT_QDEPTH;
pnode->last_change_time = jiffies;
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
}
}
lpfc_scsi_unprep_dma_buf(phba, lpfc_cmd);
+
+ /* The sdev is not guaranteed to be valid post scsi_done upcall. */
+ queue_depth = cmd->device->queue_depth;
+ scsi_id = cmd->device->id;
cmd->scsi_done(cmd);
if (phba->cfg_poll & ENABLE_FCP_RING_POLLING) {
* If there is a thread waiting for command completion
* wake up the thread.
*/
- spin_lock_irqsave(sdev->host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
lpfc_cmd->pCmd = NULL;
if (lpfc_cmd->waitq)
wake_up(lpfc_cmd->waitq);
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
lpfc_release_scsi_buf(phba, lpfc_cmd);
return;
}
if (!result)
- lpfc_rampup_queue_depth(vport, sdev);
+ lpfc_rampup_queue_depth(vport, queue_depth);
if (!result && pnode && NLP_CHK_NODE_ACT(pnode) &&
((jiffies - pnode->last_ramp_up_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
((jiffies - pnode->last_q_full_time) >
LPFC_Q_RAMP_UP_INTERVAL * HZ) &&
- (vport->cfg_lun_queue_depth > sdev->queue_depth)) {
- shost_for_each_device(tmp_sdev, sdev->host) {
+ (vport->cfg_lun_queue_depth > queue_depth)) {
+ shost_for_each_device(tmp_sdev, shost) {
if (vport->cfg_lun_queue_depth > tmp_sdev->queue_depth){
- if (tmp_sdev->id != sdev->id)
+ if (tmp_sdev->id != scsi_id)
continue;
if (tmp_sdev->ordered_tags)
scsi_adjust_queue_depth(tmp_sdev,
}
lpfc_send_sdev_queuedepth_change_event(phba, vport, pnode,
0xFFFFFFFF,
- sdev->queue_depth - 1, sdev->queue_depth);
+ queue_depth , queue_depth + 1);
}
/*
NLP_CHK_NODE_ACT(pnode)) {
pnode->last_q_full_time = jiffies;
- shost_for_each_device(tmp_sdev, sdev->host) {
- if (tmp_sdev->id != sdev->id)
+ shost_for_each_device(tmp_sdev, shost) {
+ if (tmp_sdev->id != scsi_id)
continue;
depth = scsi_track_queue_full(tmp_sdev,
tmp_sdev->queue_depth - 1);
* scsi_track_queue_full.
*/
if (depth == -1)
- depth = sdev->host->cmd_per_lun;
+ depth = shost->cmd_per_lun;
if (depth) {
lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
* If there is a thread waiting for command completion
* wake up the thread.
*/
- spin_lock_irqsave(sdev->host->host_lock, flags);
+ spin_lock_irqsave(shost->host_lock, flags);
lpfc_cmd->pCmd = NULL;
if (lpfc_cmd->waitq)
wake_up(lpfc_cmd->waitq);
- spin_unlock_irqrestore(sdev->host->host_lock, flags);
+ spin_unlock_irqrestore(shost->host_lock, flags);
lpfc_release_scsi_buf(phba, lpfc_cmd);
}
/**
- * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB.
+ * lpfc_fcpcmd_to_iocb - copy the fcp_cmd data into the IOCB
* @data: A pointer to the immediate command data portion of the IOCB.
* @fcp_cmnd: The FCP Command that is provided by the SCSI layer.
*
}
/**
- * lpfc_scsi_prep_cmnd: Routine to convert scsi cmnd to FCP information unit.
+ * lpfc_scsi_prep_cmnd - Routine to convert scsi cmnd to FCP information unit
* @vport: The virtual port for which this call is being executed.
* @lpfc_cmd: The scsi command which needs to send.
* @pnode: Pointer to lpfc_nodelist.
}
/**
- * lpfc_scsi_prep_task_mgmt_cmnd: Convert scsi TM cmnd to FCP information unit.
+ * lpfc_scsi_prep_task_mgmt_cmnd - Convert scsi TM cmnd to FCP information unit
* @vport: The virtual port for which this call is being executed.
* @lpfc_cmd: Pointer to lpfc_scsi_buf data structure.
* @lun: Logical unit number.
}
/**
- * lpc_taskmgmt_def_cmpl: IOCB completion routine for task management command.
+ * lpfc_taskmgmt_def_cmpl - IOCB completion routine for task management command
* @phba: The Hba for which this call is being executed.
* @cmdiocbq: Pointer to lpfc_iocbq data structure.
* @rspiocbq: Pointer to lpfc_iocbq data structure.
}
/**
- * lpfc_scsi_tgt_reset: Target reset handler.
+ * lpfc_scsi_tgt_reset - Target reset handler
* @lpfc_cmd: Pointer to lpfc_scsi_buf data structure
* @vport: The virtual port for which this call is being executed.
* @tgt_id: Target ID.
}
/**
- * lpfc_info: Info entry point of scsi_host_template data structure.
+ * lpfc_info - Info entry point of scsi_host_template data structure
* @host: The scsi host for which this call is being executed.
*
* This routine provides module information about hba.
}
/**
- * lpfc_poll_rearm_time: Routine to modify fcp_poll timer of hba.
+ * lpfc_poll_rearm_time - Routine to modify fcp_poll timer of hba
* @phba: The Hba for which this call is being executed.
*
* This routine modifies fcp_poll_timer field of @phba by cfg_poll_tmo.
}
/**
- * lpfc_poll_start_timer: Routine to start fcp_poll_timer of HBA.
+ * lpfc_poll_start_timer - Routine to start fcp_poll_timer of HBA
* @phba: The Hba for which this call is being executed.
*
* This routine starts the fcp_poll_timer of @phba.
}
/**
- * lpfc_poll_timeout: Restart polling timer.
+ * lpfc_poll_timeout - Restart polling timer
* @ptr: Map to lpfc_hba data structure pointer.
*
* This routine restarts fcp_poll timer, when FCP ring polling is enable
}
/**
- * lpfc_queuecommand: Queuecommand entry point of Scsi Host Templater data
- * structure.
+ * lpfc_queuecommand - scsi_host_template queuecommand entry point
* @cmnd: Pointer to scsi_cmnd data structure.
* @done: Pointer to done routine.
*
}
/**
- * lpfc_block_error_handler: Routine to block error handler.
+ * lpfc_block_error_handler - Routine to block error handler
* @cmnd: Pointer to scsi_cmnd data structure.
*
* This routine blocks execution till fc_rport state is not FC_PORSTAT_BLCOEKD.
}
/**
- * lpfc_abort_handler: Eh_abort_handler entry point of Scsi Host Template data
- *structure.
+ * lpfc_abort_handler - scsi_host_template eh_abort_handler entry point
* @cmnd: Pointer to scsi_cmnd data structure.
*
* This routine aborts @cmnd pending in base driver.
}
/**
- * lpfc_device_reset_handler: eh_device_reset entry point of Scsi Host Template
- *data structure.
+ * lpfc_device_reset_handler - scsi_host_template eh_device_reset entry point
* @cmnd: Pointer to scsi_cmnd data structure.
*
* This routine does a device reset by sending a TARGET_RESET task management
*
* Return code :
* 0x2003 - Error
- * 0ex2002 - Success
+ * 0x2002 - Success
**/
static int
lpfc_device_reset_handler(struct scsi_cmnd *cmnd)
}
/**
- * lpfc_bus_reset_handler: eh_bus_reset_handler entry point of Scsi Host
- * Template data structure.
+ * lpfc_bus_reset_handler - scsi_host_template eh_bus_reset_handler entry point
* @cmnd: Pointer to scsi_cmnd data structure.
*
* This routine does target reset to all target on @cmnd->device->host.
}
/**
- * lpfc_slave_alloc: slave_alloc entry point of Scsi Host Template data
- * structure.
+ * lpfc_slave_alloc - scsi_host_template slave_alloc entry point
* @sdev: Pointer to scsi_device.
*
* This routine populates the cmds_per_lun count + 2 scsi_bufs into this host's
}
/**
- * lpfc_slave_configure: slave_configure entry point of Scsi Host Templater data
- * structure.
+ * lpfc_slave_configure - scsi_host_template slave_configure entry point
* @sdev: Pointer to scsi_device.
*
* This routine configures following items
}
/**
- * lpfc_slave_destroy: slave_destroy entry point of SHT data structure.
+ * lpfc_slave_destroy - slave_destroy entry point of SHT data structure
* @sdev: Pointer to scsi_device.
*
* This routine sets @sdev hostatdata filed to null.
} lpfc_iocb_type;
/**
- * lpfc_cmd_iocb: Get next command iocb entry in the ring.
+ * lpfc_cmd_iocb - Get next command iocb entry in the ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
}
/**
- * lpfc_resp_iocb: Get next response iocb entry in the ring.
+ * lpfc_resp_iocb - Get next response iocb entry in the ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
}
/**
- * __lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool.
+ * __lpfc_sli_get_iocbq - Allocates an iocb object from iocb pool
* @phba: Pointer to HBA context object.
*
* This function is called with hbalock held. This function
}
/**
- * lpfc_sli_get_iocbq: Allocates an iocb object from iocb pool.
+ * lpfc_sli_get_iocbq - Allocates an iocb object from iocb pool
* @phba: Pointer to HBA context object.
*
* This function is called with no lock held. This function
}
/**
- * __lpfc_sli_release_iocbq: Release iocb to the iocb pool.
+ * __lpfc_sli_release_iocbq - Release iocb to the iocb pool
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
}
/**
- * lpfc_sli_release_iocbq: Release iocb to the iocb pool.
+ * lpfc_sli_release_iocbq - Release iocb to the iocb pool
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
}
/**
- * lpfc_sli_iocb_cmd_type: Get the iocb type.
- * @iocb_cmnd : iocb command code.
+ * lpfc_sli_cancel_iocbs - Cancel all iocbs from a list.
+ * @phba: Pointer to HBA context object.
+ * @iocblist: List of IOCBs.
+ * @ulpstatus: ULP status in IOCB command field.
+ * @ulpWord4: ULP word-4 in IOCB command field.
+ *
+ * This function is called with a list of IOCBs to cancel. It cancels the IOCB
+ * on the list by invoking the complete callback function associated with the
+ * IOCB with the provided @ulpstatus and @ulpword4 set to the IOCB commond
+ * fields.
+ **/
+void
+lpfc_sli_cancel_iocbs(struct lpfc_hba *phba, struct list_head *iocblist,
+ uint32_t ulpstatus, uint32_t ulpWord4)
+{
+ struct lpfc_iocbq *piocb;
+
+ while (!list_empty(iocblist)) {
+ list_remove_head(iocblist, piocb, struct lpfc_iocbq, list);
+
+ if (!piocb->iocb_cmpl)
+ lpfc_sli_release_iocbq(phba, piocb);
+ else {
+ piocb->iocb.ulpStatus = ulpstatus;
+ piocb->iocb.un.ulpWord[4] = ulpWord4;
+ (piocb->iocb_cmpl) (phba, piocb, piocb);
+ }
+ }
+ return;
+}
+
+/**
+ * lpfc_sli_iocb_cmd_type - Get the iocb type
+ * @iocb_cmnd: iocb command code.
*
* This function is called by ring event handler function to get the iocb type.
* This function translates the iocb command to an iocb command type used to
}
/**
- * lpfc_sli_ring_map: Issue config_ring mbox for all rings.
+ * lpfc_sli_ring_map - Issue config_ring mbox for all rings
* @phba: Pointer to HBA context object.
*
* This function is called from SLI initialization code
}
/**
- * lpfc_sli_ringtxcmpl_put: Adds new iocb to the txcmplq.
+ * lpfc_sli_ringtxcmpl_put - Adds new iocb to the txcmplq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to the driver iocb object.
}
/**
- * lpfc_sli_ringtx_get: Get first element of the txq.
+ * lpfc_sli_ringtx_get - Get first element of the txq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
}
/**
- * lpfc_sli_next_iocb_slot: Get next iocb slot in the ring.
+ * lpfc_sli_next_iocb_slot - Get next iocb slot in the ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
}
/**
- * lpfc_sli_next_iotag: Get an iotag for the iocb.
+ * lpfc_sli_next_iotag - Get an iotag for the iocb
* @phba: Pointer to HBA context object.
* @iocbq: Pointer to driver iocb object.
*
}
/**
- * lpfc_sli_submit_iocb: Submit an iocb to the firmware.
+ * lpfc_sli_submit_iocb - Submit an iocb to the firmware
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @iocb: Pointer to iocb slot in the ring.
}
/**
- * lpfc_sli_update_full_ring: Update the chip attention register.
+ * lpfc_sli_update_full_ring - Update the chip attention register
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
}
/**
- * lpfc_sli_update_ring: Update chip attention register.
+ * lpfc_sli_update_ring - Update chip attention register
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
}
/**
- * lpfc_sli_resume_iocb: Process iocbs in the txq.
+ * lpfc_sli_resume_iocb - Process iocbs in the txq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
}
/**
- * lpfc_sli_next_hbq_slot: Get next hbq entry for the HBQ.
+ * lpfc_sli_next_hbq_slot - Get next hbq entry for the HBQ
* @phba: Pointer to HBA context object.
* @hbqno: HBQ number.
*
}
/**
- * lpfc_sli_hbqbuf_free_all: Free all the hbq buffers.
+ * lpfc_sli_hbqbuf_free_all - Free all the hbq buffers
* @phba: Pointer to HBA context object.
*
* This function is called with no lock held to free all the
}
/**
- * lpfc_sli_hbq_to_firmware: Post the hbq buffer to firmware.
+ * lpfc_sli_hbq_to_firmware - Post the hbq buffer to firmware
* @phba: Pointer to HBA context object.
* @hbqno: HBQ number.
* @hbq_buf: Pointer to HBQ buffer.
.profile = 0,
.ring_mask = (1 << LPFC_ELS_RING),
.buffer_count = 0,
- .init_count = 20,
- .add_count = 5,
+ .init_count = 40,
+ .add_count = 40,
};
/* HBQ for the extra ring if needed */
};
/**
- * lpfc_sli_hbqbuf_fill_hbqs: Post more hbq buffers to HBQ.
+ * lpfc_sli_hbqbuf_fill_hbqs - Post more hbq buffers to HBQ
* @phba: Pointer to HBA context object.
* @hbqno: HBQ number.
* @count: Number of HBQ buffers to be posted.
}
/**
- * lpfc_sli_hbqbuf_add_hbqs: Post more HBQ buffers to firmware.
+ * lpfc_sli_hbqbuf_add_hbqs - Post more HBQ buffers to firmware
* @phba: Pointer to HBA context object.
* @qno: HBQ number.
*
}
/**
- * lpfc_sli_hbqbuf_init_hbqs: Post initial buffers to the HBQ.
+ * lpfc_sli_hbqbuf_init_hbqs - Post initial buffers to the HBQ
* @phba: Pointer to HBA context object.
* @qno: HBQ queue number.
*
}
/**
- * lpfc_sli_hbqbuf_find: Find the hbq buffer associated with a tag.
+ * lpfc_sli_hbqbuf_find - Find the hbq buffer associated with a tag
* @phba: Pointer to HBA context object.
* @tag: Tag of the hbq buffer.
*
}
/**
- * lpfc_sli_free_hbq: Give back the hbq buffer to firmware.
+ * lpfc_sli_free_hbq - Give back the hbq buffer to firmware
* @phba: Pointer to HBA context object.
* @hbq_buffer: Pointer to HBQ buffer.
*
}
/**
- * lpfc_sli_chk_mbx_command: Check if the mailbox is a legitimate mailbox.
+ * lpfc_sli_chk_mbx_command - Check if the mailbox is a legitimate mailbox
* @mbxCommand: mailbox command code.
*
* This function is called by the mailbox event handler function to verify
}
/**
- * lpfc_sli_wake_mbox_wait: Completion handler for mbox issued from
- * lpfc_sli_issue_mbox_wait.
+ * lpfc_sli_wake_mbox_wait - lpfc_sli_issue_mbox_wait mbox completion handler
* @phba: Pointer to HBA context object.
* @pmboxq: Pointer to mailbox command.
*
/**
- * lpfc_sli_def_mbox_cmpl: Default mailbox completion handler.
+ * lpfc_sli_def_mbox_cmpl - Default mailbox completion handler
* @phba: Pointer to HBA context object.
* @pmb: Pointer to mailbox object.
*
}
/**
- * lpfc_sli_handle_mb_event: Handle mailbox completions from firmware.
+ * lpfc_sli_handle_mb_event - Handle mailbox completions from firmware
* @phba: Pointer to HBA context object.
*
* This function is called with no lock held. This function processes all
}
/**
- * lpfc_sli_get_buff: Get the buffer associated with the buffer tag.
+ * lpfc_sli_get_buff - Get the buffer associated with the buffer tag
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @tag: buffer tag.
/**
- * lpfc_sli_process_unsol_iocb: Unsolicited iocb handler.
+ * lpfc_sli_process_unsol_iocb - Unsolicited iocb handler
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @saveq: Pointer to the unsolicited iocb.
}
/**
- * lpfc_sli_iocbq_lookup: Find command iocb for the given response iocb.
+ * lpfc_sli_iocbq_lookup - Find command iocb for the given response iocb
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @prspiocb: Pointer to response iocb object.
}
/**
- * lpfc_sli_process_sol_iocb: process solicited iocb completion.
+ * lpfc_sli_process_sol_iocb - process solicited iocb completion
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @saveq: Pointer to the response iocb to be processed.
* Ring <ringno> handler: unexpected completion IoTag
* <IoTag>
*/
- lpfc_printf_vlog(cmdiocbp->vport, KERN_WARNING, LOG_SLI,
+ lpfc_printf_log(phba, KERN_WARNING, LOG_SLI,
"0322 Ring %d handler: "
"unexpected completion IoTag x%x "
"Data: x%x x%x x%x x%x\n",
}
/**
- * lpfc_sli_rsp_pointers_error: Response ring pointer error handler.
+ * lpfc_sli_rsp_pointers_error - Response ring pointer error handler
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
}
/**
- * lpfc_poll_eratt: Error attention polling timer timeout handler.
+ * lpfc_poll_eratt - Error attention polling timer timeout handler
* @ptr: Pointer to address of HBA context object.
*
* This function is invoked by the Error Attention polling timer when the
}
/**
- * lpfc_sli_poll_fcp_ring: Handle FCP ring completion in polling mode.
+ * lpfc_sli_poll_fcp_ring - Handle FCP ring completion in polling mode
* @phba: Pointer to HBA context object.
*
* This function is called from lpfc_queuecommand, lpfc_poll_timeout,
}
/**
- * lpfc_sli_handle_fast_ring_event: Handle ring events on FCP ring.
+ * lpfc_sli_handle_fast_ring_event - Handle ring events on FCP ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @mask: Host attention register mask for this ring.
}
/**
- * lpfc_sli_handle_slow_ring_event: Handle ring events for non-FCP rings.
+ * lpfc_sli_handle_slow_ring_event - Handle ring events for non-FCP rings
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @mask: Host attention register mask for this ring.
}
/**
- * lpfc_sli_abort_iocb_ring: Abort all iocbs in the ring.
+ * lpfc_sli_abort_iocb_ring - Abort all iocbs in the ring
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
*
{
LIST_HEAD(completions);
struct lpfc_iocbq *iocb, *next_iocb;
- IOCB_t *cmd = NULL;
if (pring->ringno == LPFC_ELS_RING) {
lpfc_fabric_abort_hba(phba);
spin_unlock_irq(&phba->hbalock);
- while (!list_empty(&completions)) {
- iocb = list_get_first(&completions, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_ABORTED;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_ABORTED);
}
/**
- * lpfc_sli_flush_fcp_rings: flush all iocbs in the fcp ring.
+ * lpfc_sli_flush_fcp_rings - flush all iocbs in the fcp ring
* @phba: Pointer to HBA context object.
*
* This function flushes all iocbs in the fcp ring and frees all the iocb
{
LIST_HEAD(txq);
LIST_HEAD(txcmplq);
- struct lpfc_iocbq *iocb;
- IOCB_t *cmd = NULL;
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
spin_unlock_irq(&phba->hbalock);
/* Flush the txq */
- while (!list_empty(&txq)) {
- iocb = list_get_first(&txq, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ lpfc_sli_cancel_iocbs(phba, &txq, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
/* Flush the txcmpq */
- while (!list_empty(&txcmplq)) {
- iocb = list_get_first(&txcmplq, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
- list_del_init(&iocb->list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ lpfc_sli_cancel_iocbs(phba, &txcmplq, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
}
/**
- * lpfc_sli_brdready: Check for host status bits.
+ * lpfc_sli_brdready - Check for host status bits
* @phba: Pointer to HBA context object.
* @mask: Bit mask to be checked.
*
#define BARRIER_TEST_PATTERN (0xdeadbeef)
/**
- * lpfc_reset_barrier: Make HBA ready for HBA reset.
+ * lpfc_reset_barrier - Make HBA ready for HBA reset
* @phba: Pointer to HBA context object.
*
* This function is called before resetting an HBA. This
}
/**
- * lpfc_sli_brdkill: Issue a kill_board mailbox command.
+ * lpfc_sli_brdkill - Issue a kill_board mailbox command
* @phba: Pointer to HBA context object.
*
* This function issues a kill_board mailbox command and waits for
}
/**
- * lpfc_sli_brdreset: Reset the HBA.
+ * lpfc_sli_brdreset - Reset the HBA
* @phba: Pointer to HBA context object.
*
* This function resets the HBA by writing HC_INITFF to the control
}
/**
- * lpfc_sli_brdrestart: Restart the HBA.
+ * lpfc_sli_brdrestart - Restart the HBA
* @phba: Pointer to HBA context object.
*
* This function is called in the SLI initialization code path to
}
/**
- * lpfc_sli_chipset_init: Wait for the restart of the HBA after a restart.
+ * lpfc_sli_chipset_init - Wait for the restart of the HBA after a restart
* @phba: Pointer to HBA context object.
*
* This function is called after a HBA restart to wait for successful
}
/**
- * lpfc_sli_hbq_count: Get the number of HBQs to be configured.
+ * lpfc_sli_hbq_count - Get the number of HBQs to be configured
*
* This function calculates and returns the number of HBQs required to be
* configured.
}
/**
- * lpfc_sli_hbq_entry_count: Calculate total number of hbq entries.
+ * lpfc_sli_hbq_entry_count - Calculate total number of hbq entries
*
* This function adds the number of hbq entries in every HBQ to get
* the total number of hbq entries required for the HBA and returns
}
/**
- * lpfc_sli_hbq_size: Calculate memory required for all hbq entries.
+ * lpfc_sli_hbq_size - Calculate memory required for all hbq entries
*
* This function calculates amount of memory required for all hbq entries
* to be configured and returns the total memory required.
}
/**
- * lpfc_sli_hbq_setup: configure and initialize HBQs.
+ * lpfc_sli_hbq_setup - configure and initialize HBQs
* @phba: Pointer to HBA context object.
*
* This function is called during the SLI initialization to configure
}
/**
- * lpfc_sli_config_port: Issue config port mailbox command.
+ * lpfc_sli_config_port - Issue config port mailbox command
* @phba: Pointer to HBA context object.
* @sli_mode: sli mode - 2/3
*
/**
- * lpfc_sli_hba_setup: SLI intialization function.
+ * lpfc_sli_hba_setup - SLI intialization function
* @phba: Pointer to HBA context object.
*
* This function is the main SLI intialization function. This function
/**
- * lpfc_mbox_timeout: Timeout call back function for mbox timer.
+ * lpfc_mbox_timeout - Timeout call back function for mbox timer
* @ptr: context object - pointer to hba structure.
*
* This is the callback function for mailbox timer. The mailbox
/**
- * lpfc_mbox_timeout_handler: Worker thread function to handle mailbox timeout.
+ * lpfc_mbox_timeout_handler - Worker thread function to handle mailbox timeout
* @phba: Pointer to HBA context object.
*
* This function is called from worker thread when a mailbox command times out.
struct lpfc_sli *psli = &phba->sli;
struct lpfc_sli_ring *pring;
+ /* Check the pmbox pointer first. There is a race condition
+ * between the mbox timeout handler getting executed in the
+ * worklist and the mailbox actually completing. When this
+ * race condition occurs, the mbox_active will be NULL.
+ */
+ spin_lock_irq(&phba->hbalock);
+ if (pmbox == NULL) {
+ lpfc_printf_log(phba, KERN_WARNING,
+ LOG_MBOX | LOG_SLI,
+ "0353 Active Mailbox cleared - mailbox timeout "
+ "exiting\n");
+ spin_unlock_irq(&phba->hbalock);
+ return;
+ }
+
/* Mbox cmd <mbxCommand> timeout */
lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
"0310 Mailbox command x%x timeout Data: x%x x%x x%p\n",
phba->pport->port_state,
phba->sli.sli_flag,
phba->sli.mbox_active);
+ spin_unlock_irq(&phba->hbalock);
/* Setting state unknown so lpfc_sli_abort_iocb_ring
* would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
}
/**
- * lpfc_sli_issue_mbox: Issue a mailbox command to firmware.
+ * lpfc_sli_issue_mbox - Issue a mailbox command to firmware
* @phba: Pointer to HBA context object.
* @pmbox: Pointer to mailbox object.
* @flag: Flag indicating how the mailbox need to be processed.
goto out_not_finished;
}
+ /* If HBA has a deferred error attention, fail the iocb. */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+ goto out_not_finished;
+ }
+
psli = &phba->sli;
mb = &pmbox->mb;
}
/**
- * __lpfc_sli_ringtx_put: Add an iocb to the txq.
+ * __lpfc_sli_ringtx_put - Add an iocb to the txq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to address of newly added command iocb.
}
/**
- * lpfc_sli_next_iocb: Get the next iocb in the txq.
+ * lpfc_sli_next_iocb - Get the next iocb in the txq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to address of newly added command iocb.
}
/**
- * __lpfc_sli_issue_iocb: Lockless version of lpfc_sli_issue_iocb.
+ * __lpfc_sli_issue_iocb - Lockless version of lpfc_sli_issue_iocb
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to command iocb.
if (unlikely(pci_channel_offline(phba->pcidev)))
return IOCB_ERROR;
+ /* If HBA has a deferred error attention, fail the iocb. */
+ if (unlikely(phba->hba_flag & DEFER_ERATT))
+ return IOCB_ERROR;
+
/*
* We should never get an IOCB if we are in a < LINK_DOWN state
*/
/**
- * lpfc_sli_issue_iocb: Wrapper function for __lpfc_sli_issue_iocb.
+ * lpfc_sli_issue_iocb - Wrapper function for __lpfc_sli_issue_iocb
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @piocb: Pointer to command iocb.
}
/**
- * lpfc_extra_ring_setup: Extra ring setup function.
+ * lpfc_extra_ring_setup - Extra ring setup function
* @phba: Pointer to HBA context object.
*
* This function is called while driver attaches with the
}
/**
- * lpfc_sli_async_event_handler: ASYNC iocb handler function.
+ * lpfc_sli_async_event_handler - ASYNC iocb handler function
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @iocbq: Pointer to iocb object.
uint16_t temp;
struct temp_event temp_event_data;
struct Scsi_Host *shost;
+ uint32_t *iocb_w;
icmd = &iocbq->iocb;
evt_code = icmd->un.asyncstat.evt_code;
if ((evt_code != ASYNC_TEMP_WARN) &&
(evt_code != ASYNC_TEMP_SAFE)) {
+ iocb_w = (uint32_t *) icmd;
lpfc_printf_log(phba,
KERN_ERR,
LOG_SLI,
"0346 Ring %d handler: unexpected ASYNC_STATUS"
- " evt_code 0x%x\n",
+ " evt_code 0x%x \n"
+ "W0 0x%08x W1 0x%08x W2 0x%08x W3 0x%08x\n"
+ "W4 0x%08x W5 0x%08x W6 0x%08x W7 0x%08x\n"
+ "W8 0x%08x W9 0x%08x W10 0x%08x W11 0x%08x\n"
+ "W12 0x%08x W13 0x%08x W14 0x%08x W15 0x%08x\n",
pring->ringno,
- icmd->un.asyncstat.evt_code);
+ icmd->un.asyncstat.evt_code,
+ iocb_w[0], iocb_w[1], iocb_w[2], iocb_w[3],
+ iocb_w[4], iocb_w[5], iocb_w[6], iocb_w[7],
+ iocb_w[8], iocb_w[9], iocb_w[10], iocb_w[11],
+ iocb_w[12], iocb_w[13], iocb_w[14], iocb_w[15]);
+
return;
}
temp_event_data.data = (uint32_t)temp;
/**
- * lpfc_sli_setup: SLI ring setup function.
+ * lpfc_sli_setup - SLI ring setup function
* @phba: Pointer to HBA context object.
*
* lpfc_sli_setup sets up rings of the SLI interface with
}
/**
- * lpfc_sli_queue_setup: Queue initialization function.
+ * lpfc_sli_queue_setup - Queue initialization function
* @phba: Pointer to HBA context object.
*
* lpfc_sli_queue_setup sets up mailbox queues and iocb queues for each
}
/**
- * lpfc_sli_host_down: Vport cleanup function.
+ * lpfc_sli_host_down - Vport cleanup function
* @vport: Pointer to virtual port object.
*
* lpfc_sli_host_down is called to clean up the resources
spin_unlock_irqrestore(&phba->hbalock, flags);
- while (!list_empty(&completions)) {
- list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- iocb->iocb.ulpStatus = IOSTAT_LOCAL_REJECT;
- iocb->iocb.un.ulpWord[4] = IOERR_SLI_DOWN;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
return 1;
}
/**
- * lpfc_sli_hba_down: Resource cleanup function for the HBA.
+ * lpfc_sli_hba_down - Resource cleanup function for the HBA
* @phba: Pointer to HBA context object.
*
* This function cleans up all iocb, buffers, mailbox commands
struct lpfc_sli_ring *pring;
struct lpfc_dmabuf *buf_ptr;
LPFC_MBOXQ_t *pmb;
- struct lpfc_iocbq *iocb;
- IOCB_t *cmd = NULL;
int i;
unsigned long flags = 0;
}
spin_unlock_irqrestore(&phba->hbalock, flags);
- while (!list_empty(&completions)) {
- list_remove_head(&completions, iocb, struct lpfc_iocbq, list);
- cmd = &iocb->iocb;
-
- if (!iocb->iocb_cmpl)
- lpfc_sli_release_iocbq(phba, iocb);
- else {
- cmd->ulpStatus = IOSTAT_LOCAL_REJECT;
- cmd->un.ulpWord[4] = IOERR_SLI_DOWN;
- (iocb->iocb_cmpl) (phba, iocb, iocb);
- }
- }
+ /* Cancel all the IOCBs from the completions list */
+ lpfc_sli_cancel_iocbs(phba, &completions, IOSTAT_LOCAL_REJECT,
+ IOERR_SLI_DOWN);
spin_lock_irqsave(&phba->hbalock, flags);
list_splice_init(&phba->elsbuf, &completions);
}
/**
- * lpfc_sli_pcimem_bcopy: SLI memory copy function.
+ * lpfc_sli_pcimem_bcopy - SLI memory copy function
* @srcp: Source memory pointer.
* @destp: Destination memory pointer.
* @cnt: Number of words required to be copied.
/**
- * lpfc_sli_ringpostbuf_put: Function to add a buffer to postbufq.
+ * lpfc_sli_ringpostbuf_put - Function to add a buffer to postbufq
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @mp: Pointer to driver buffer object.
}
/**
- * lpfc_sli_get_buffer_tag: Tag allocation function for a buffer posted
- * using CMD_QUE_XRI64_CX iocb.
+ * lpfc_sli_get_buffer_tag - allocates a tag for a CMD_QUE_XRI64_CX buffer
* @phba: Pointer to HBA context object.
*
* When HBQ is enabled, buffers are searched based on tags. This function
}
/**
- * lpfc_sli_ring_taggedbuf_get: Search HBQ buffer associated with
- * posted using CMD_QUE_XRI64_CX iocb.
+ * lpfc_sli_ring_taggedbuf_get - find HBQ buffer associated with given tag
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @tag: Buffer tag.
}
/**
- * lpfc_sli_ringpostbuf_get: SLI2 buffer search function for
- * unsolicited ct and els events.
+ * lpfc_sli_ringpostbuf_get - search buffers for unsolicited CT and ELS events
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @phys: DMA address of the buffer.
}
/**
- * lpfc_sli_abort_els_cmpl: Completion handler for the els abort iocbs.
+ * lpfc_sli_abort_els_cmpl - Completion handler for the els abort iocbs
* @phba: Pointer to HBA context object.
* @cmdiocb: Pointer to driver command iocb object.
* @rspiocb: Pointer to driver response iocb object.
}
/**
- * lpfc_ignore_els_cmpl: Completion handler for aborted ELS command.
+ * lpfc_ignore_els_cmpl - Completion handler for aborted ELS command
* @phba: Pointer to HBA context object.
* @cmdiocb: Pointer to driver command iocb object.
* @rspiocb: Pointer to driver response iocb object.
}
/**
- * lpfc_sli_issue_abort_iotag: Abort function for a command iocb.
+ * lpfc_sli_issue_abort_iotag - Abort function for a command iocb
* @phba: Pointer to HBA context object.
* @pring: Pointer to driver SLI ring object.
* @cmdiocb: Pointer to driver command iocb object.
}
/**
- * lpfc_sli_validate_fcp_iocb: Filtering function, used to find commands
- * associated with a vport/SCSI target/lun.
+ * lpfc_sli_validate_fcp_iocb - find commands associated with a vport or LUN
* @iocbq: Pointer to driver iocb object.
* @vport: Pointer to driver virtual port object.
* @tgt_id: SCSI ID of the target.
* @lun_id: LUN ID of the scsi device.
* @ctx_cmd: LPFC_CTX_LUN/LPFC_CTX_TGT/LPFC_CTX_HOST
*
- * This function acts as iocb filter for functions which abort or count
+ * This function acts as an iocb filter for functions which abort or count
* all FCP iocbs pending on a lun/SCSI target/SCSI host. It will return
* 0 if the filtering criteria is met for the given iocb and will return
* 1 if the filtering criteria is not met.
}
/**
- * lpfc_sli_sum_iocb: Function to count the number of FCP iocbs pending.
+ * lpfc_sli_sum_iocb - Function to count the number of FCP iocbs pending
* @vport: Pointer to virtual port.
* @tgt_id: SCSI ID of the target.
* @lun_id: LUN ID of the scsi device.
}
/**
- * lpfc_sli_abort_fcp_cmpl: Completion handler function for an aborted
- * FCP iocb.
+ * lpfc_sli_abort_fcp_cmpl - Completion handler function for aborted FCP IOCBs
* @phba: Pointer to HBA context object
* @cmdiocb: Pointer to command iocb object.
* @rspiocb: Pointer to response iocb object.
}
/**
- * lpfc_sli_abort_iocb: This function issue abort for all SCSI commands
- * pending on a SCSI host(vport)/target/lun.
+ * lpfc_sli_abort_iocb - issue abort for all commands on a host/target/LUN
* @vport: Pointer to virtual port.
* @pring: Pointer to driver SLI ring object.
* @tgt_id: SCSI ID of the target.
}
/**
- * lpfc_sli_wake_iocb_wait: iocb completion handler for iocb issued using
- * lpfc_sli_issue_iocb_wait.
+ * lpfc_sli_wake_iocb_wait - lpfc_sli_issue_iocb_wait's completion handler
* @phba: Pointer to HBA context object.
* @cmdiocbq: Pointer to command iocb.
* @rspiocbq: Pointer to response iocb.
}
/**
- * lpfc_sli_issue_iocb_wait: Synchronous function to issue iocb commands.
+ * lpfc_sli_issue_iocb_wait - Synchronous function to issue iocb commands
* @phba: Pointer to HBA context object..
* @pring: Pointer to sli ring.
* @piocb: Pointer to command iocb.
}
/**
- * lpfc_sli_issue_mbox_wait: Synchronous function to issue mailbox.
+ * lpfc_sli_issue_mbox_wait - Synchronous function to issue mailbox
* @phba: Pointer to HBA context object.
* @pmboxq: Pointer to driver mailbox object.
* @timeout: Timeout in number of seconds.
}
/**
- * lpfc_sli_flush_mbox_queue: mailbox queue cleanup function.
+ * lpfc_sli_flush_mbox_queue - mailbox queue cleanup function
* @phba: Pointer to HBA context.
*
* This function is called to cleanup any pending mailbox
}
/**
- * lpfc_sli_check_eratt: check error attention events
+ * lpfc_sli_check_eratt - check error attention events
* @phba: Pointer to HBA context.
*
* This function is called form timer soft interrupt context to check HBA's
return 0;
}
+ /*
+ * If there is deferred error attention, do not check for error
+ * attention
+ */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irq(&phba->hbalock);
+ return 0;
+ }
+
/* Read chip Host Attention (HA) register */
ha_copy = readl(phba->HAregaddr);
if (ha_copy & HA_ERATT) {
/* Read host status register to retrieve error event */
lpfc_sli_read_hs(phba);
+
+ /* Check if there is a deferred error condition is active */
+ if ((HS_FFER1 & phba->work_hs) &&
+ ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
+ HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+ phba->hba_flag |= DEFER_ERATT;
+ /* Clear all interrupt enable conditions */
+ writel(0, phba->HCregaddr);
+ readl(phba->HCregaddr);
+ }
+
/* Set the driver HA work bitmap */
phba->work_ha |= HA_ERATT;
/* Indicate polling handles this ERATT */
}
/**
- * lpfc_sp_intr_handler: The slow-path interrupt handler of lpfc driver.
+ * lpfc_sp_intr_handler - The slow-path interrupt handler of lpfc driver
* @irq: Interrupt number.
* @dev_id: The device context pointer.
*
/* Indicate interrupt handler handles ERATT */
phba->hba_flag |= HBA_ERATT_HANDLED;
}
+
+ /*
+ * If there is deferred error attention, do not check for any
+ * interrupt.
+ */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irq(&phba->hbalock);
+ return IRQ_NONE;
+ }
+
/* Clear up only attention source related to slow-path */
writel((ha_copy & (HA_MBATT | HA_R2_CLR_MSK)),
phba->HAregaddr);
}
}
spin_lock_irqsave(&phba->hbalock, iflag);
- if (work_ha_copy & HA_ERATT)
+ if (work_ha_copy & HA_ERATT) {
lpfc_sli_read_hs(phba);
+ /*
+ * Check if there is a deferred error condition
+ * is active
+ */
+ if ((HS_FFER1 & phba->work_hs) &&
+ ((HS_FFER2 | HS_FFER3 | HS_FFER4 | HS_FFER5 |
+ HS_FFER6 | HS_FFER7) & phba->work_hs)) {
+ phba->hba_flag |= DEFER_ERATT;
+ /* Clear all interrupt enable conditions */
+ writel(0, phba->HCregaddr);
+ readl(phba->HCregaddr);
+ }
+ }
+
if ((work_ha_copy & HA_MBATT) && (phba->sli.mbox_active)) {
pmb = phba->sli.mbox_active;
pmbox = &pmb->mb;
} /* lpfc_sp_intr_handler */
/**
- * lpfc_fp_intr_handler: The fast-path interrupt handler of lpfc driver.
+ * lpfc_fp_intr_handler - The fast-path interrupt handler of lpfc driver
* @irq: Interrupt number.
* @dev_id: The device context pointer.
*
ha_copy = readl(phba->HAregaddr);
/* Clear up only attention source related to fast-path */
spin_lock_irqsave(&phba->hbalock, iflag);
+ /*
+ * If there is deferred error attention, do not check for
+ * any interrupt.
+ */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irq(&phba->hbalock);
+ return IRQ_NONE;
+ }
writel((ha_copy & (HA_R0_CLR_MSK | HA_R1_CLR_MSK)),
phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
} /* lpfc_fp_intr_handler */
/**
- * lpfc_intr_handler: The device-level interrupt handler of lpfc driver.
+ * lpfc_intr_handler - The device-level interrupt handler of lpfc driver
* @irq: Interrupt number.
* @dev_id: The device context pointer.
*
phba->hba_flag |= HBA_ERATT_HANDLED;
}
+ /*
+ * If there is deferred error attention, do not check for any interrupt.
+ */
+ if (unlikely(phba->hba_flag & DEFER_ERATT)) {
+ spin_unlock_irq(&phba->hbalock);
+ return IRQ_NONE;
+ }
+
/* Clear attention sources except link and error attentions */
writel((phba->ha_copy & ~(HA_LATT | HA_ERATT)), phba->HAregaddr);
readl(phba->HAregaddr); /* flush */
/*******************************************************************
* This file is part of the Emulex Linux Device Driver for *
* Fibre Channel Host Bus Adapters. *
- * Copyright (C) 2004-2008 Emulex. All rights reserved. *
+ * Copyright (C) 2004-2009 Emulex. All rights reserved. *
* EMULEX and SLI are trademarks of Emulex. *
* www.emulex.com *
* *
* included with this package. *
*******************************************************************/
-#define LPFC_DRIVER_VERSION "8.3.0"
+#define LPFC_DRIVER_VERSION "8.3.1"
#define LPFC_DRIVER_NAME "lpfc"
#define LPFC_SP_DRIVER_HANDLER_NAME "lpfc:sp"
#define LPFC_MODULE_DESC "Emulex LightPulse Fibre Channel SCSI driver " \
LPFC_DRIVER_VERSION
-#define LPFC_COPYRIGHT "Copyright(c) 2004-2008 Emulex. All rights reserved."
+#define LPFC_COPYRIGHT "Copyright(c) 2004-2009 Emulex. All rights reserved."
}
/**
- * lpfc_discovery_wait: Wait for driver discovery to quiesce.
+ * lpfc_discovery_wait - Wait for driver discovery to quiesce
* @vport: The virtual port for which this call is being executed.
*
* This driver calls this routine specifically from lpfc_vport_delete
/**
- * lpfc_vport_reset_stat_data: Reset the statistical data for the vport.
+ * lpfc_vport_reset_stat_data - Reset the statistical data for the vport
* @vport: Pointer to vport object.
*
* This function resets the statistical data for the vport. This function
/**
- * lpfc_alloc_bucket: Allocate data buffer required for collecting
- * statistical data.
+ * lpfc_alloc_bucket - Allocate data buffer required for statistical data
* @vport: Pointer to vport object.
*
* This function allocates data buffer required for all the FC
}
/**
- * lpfc_free_bucket: Free data buffer required for collecting
- * statistical data.
+ * lpfc_free_bucket - Free data buffer required for statistical data
* @vport: Pointer to vport object.
*
* Th function frees statistical data buffer of all the FC
static irqreturn_t
_base_interrupt(int irq, void *bus_id)
{
+ union reply_descriptor {
+ u64 word;
+ struct {
+ u32 low;
+ u32 high;
+ } u;
+ };
+ union reply_descriptor rd;
u32 post_index, post_index_next, completed_cmds;
u8 request_desript_type;
u16 smid;
completed_cmds = 0;
do {
- if (ioc->reply_post_free[post_index].Words == ~0ULL)
+ rd.word = ioc->reply_post_free[post_index].Words;
+ if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX)
goto out;
reply = 0;
cb_idx = 0xFF;
for (i = 0 ; i < completed_cmds; i++) {
post_index = post_index_next;
/* poison the reply post descriptor */
- ioc->reply_post_free[post_index_next].Words = ~0ULL;
+ ioc->reply_post_free[post_index_next].Words = ULLONG_MAX;
post_index_next = (post_index ==
(ioc->reply_post_queue_depth - 1))
? 0 : post_index + 1;
&ioc->scsi_lookup_lock);
}
+/**
+ * _base_display_dell_branding - Disply branding string
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_display_dell_branding(struct MPT2SAS_ADAPTER *ioc)
+{
+ char dell_branding[MPT2SAS_DELL_BRANDING_SIZE];
+
+ if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_DELL)
+ return;
+
+ memset(dell_branding, 0, MPT2SAS_DELL_BRANDING_SIZE);
+ switch (ioc->pdev->subsystem_device) {
+ case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID:
+ strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID:
+ strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID:
+ strncpy(dell_branding,
+ MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID:
+ strncpy(dell_branding,
+ MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID:
+ strncpy(dell_branding,
+ MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_PERC_H200_SSDID:
+ strncpy(dell_branding, MPT2SAS_DELL_PERC_H200_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ case MPT2SAS_DELL_6GBPS_SAS_SSDID:
+ strncpy(dell_branding, MPT2SAS_DELL_6GBPS_SAS_BRANDING,
+ MPT2SAS_DELL_BRANDING_SIZE - 1);
+ break;
+ default:
+ sprintf(dell_branding, "0x%4X", ioc->pdev->subsystem_device);
+ break;
+ }
+
+ printk(MPT2SAS_INFO_FMT "%s: Vendor(0x%04X), Device(0x%04X),"
+ " SSVID(0x%04X), SSDID(0x%04X)\n", ioc->name, dell_branding,
+ ioc->pdev->vendor, ioc->pdev->device, ioc->pdev->subsystem_vendor,
+ ioc->pdev->subsystem_device);
+}
+
/**
* _base_display_ioc_capabilities - Disply IOC's capabilities.
* @ioc: per adapter object
i++;
}
+ _base_display_dell_branding(ioc);
+
i = 0;
printk("), ");
printk("Capabilities=(");
/* initialize Reply Post Free Queue */
for (i = 0; i < ioc->reply_post_queue_depth; i++)
- ioc->reply_post_free[i].Words = ~0ULL;
+ ioc->reply_post_free[i].Words = ULLONG_MAX;
r = _base_send_ioc_init(ioc, VF_ID, sleep_flag);
if (r)
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION "00.100.11.16"
+#define MPT2SAS_DRIVER_VERSION "01.100.02.00"
#define MPT2SAS_MAJOR_VERSION 00
#define MPT2SAS_MINOR_VERSION 100
-#define MPT2SAS_BUILD_VERSION 11
-#define MPT2SAS_RELEASE_VERSION 16
+#define MPT2SAS_BUILD_VERSION 02
+#define MPT2SAS_RELEASE_VERSION 00
/*
* Set MPT2SAS_SG_DEPTH value based on user input.
#define MPT2SAS_WARN_FMT KERN_WARNING MPT2SAS_FMT
#define MPT2SAS_ERR_FMT KERN_ERR MPT2SAS_FMT
+/*
+ * Dell HBA branding
+ */
+#define MPT2SAS_DELL_BRANDING_SIZE 32
+
+#define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING "Dell 6Gbps SAS HBA"
+#define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING "Dell PERC H200 Adapter"
+#define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated"
+#define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING "Dell PERC H200 Modular"
+#define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING "Dell PERC H200 Embedded"
+#define MPT2SAS_DELL_PERC_H200_BRANDING "Dell PERC H200"
+#define MPT2SAS_DELL_6GBPS_SAS_BRANDING "Dell 6Gbps SAS"
+
+/*
+ * Dell HBA SSDIDs
+ */
+#define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID 0x1F1C
+#define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID 0x1F1D
+#define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID 0x1F1E
+#define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID 0x1F1F
+#define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID 0x1F20
+#define MPT2SAS_DELL_PERC_H200_SSDID 0x1F21
+#define MPT2SAS_DELL_6GBPS_SAS_SSDID 0x1F22
+
/*
* per target private data
*/
static struct fasync_struct *async_queue;
static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
+static int _ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type,
+ u8 *issue_reset);
+
/**
* enum block_state - blocking state
* @NON_BLOCKING: non blocking
void
mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
{
+ int i;
+ u8 issue_reset;
+
switch (reset_phase) {
case MPT2_IOC_PRE_RESET:
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
"MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
+ for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
+ if (!(ioc->diag_buffer_status[i] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED))
+ continue;
+ if ((ioc->diag_buffer_status[i] &
+ MPT2_DIAG_BUFFER_IS_RELEASED))
+ continue;
+ _ctl_send_release(ioc, i, &issue_reset);
+ }
break;
case MPT2_IOC_AFTER_RESET:
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
case MPT2_IOC_DONE_RESET:
dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
"MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
+
+ for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
+ if (!(ioc->diag_buffer_status[i] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED))
+ continue;
+ if ((ioc->diag_buffer_status[i] &
+ MPT2_DIAG_BUFFER_IS_RELEASED))
+ continue;
+ ioc->diag_buffer_status[i] |=
+ MPT2_DIAG_BUFFER_IS_DIAG_RESET;
+ }
break;
}
}
if (tm_request->TaskType ==
MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
- if (_ctl_do_task_abort(ioc, &karg, tm_request))
+ if (_ctl_do_task_abort(ioc, &karg, tm_request)) {
+ mpt2sas_base_free_smid(ioc, smid);
goto out;
+ }
}
mutex_lock(&ioc->tm_cmds.mutex);
karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
karg.firmware_version = ioc->facts.FWVersion.Word;
- strncpy(karg.driver_version, MPT2SAS_DRIVER_VERSION,
- MPT2_IOCTL_VERSION_LENGTH);
- karg.driver_version[MPT2_IOCTL_VERSION_LENGTH - 1] = '\0';
+ strcpy(karg.driver_version, MPT2SAS_DRIVER_NAME);
+ strcat(karg.driver_version, "-");
+ strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION);
karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
if (copy_to_user(arg, &karg, sizeof(karg))) {
}
/**
- * _ctl_diag_release - request to send Diag Release Message to firmware
- * @arg - user space buffer containing ioctl content
- * @state - NON_BLOCKING or BLOCKING
+ * _ctl_send_release - Diag Release Message
+ * @ioc: per adapter object
+ * @buffer_type - specifies either TRACE or SNAPSHOT
+ * @issue_reset - specifies whether host reset is required.
*
- * This allows ownership of the specified buffer to returned to the driver,
- * allowing an application to read the buffer without fear that firmware is
- * overwritting information in the buffer.
*/
-static long
-_ctl_diag_release(void __user *arg, enum block_state state)
+static int
+_ctl_send_release(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type, u8 *issue_reset)
{
- struct mpt2_diag_release karg;
- struct MPT2SAS_ADAPTER *ioc;
- void *request_data;
- int rc;
Mpi2DiagReleaseRequest_t *mpi_request;
Mpi2DiagReleaseReply_t *mpi_reply;
- u8 buffer_type;
- unsigned long timeleft;
u16 smid;
u16 ioc_status;
- u8 issue_reset = 0;
-
- if (copy_from_user(&karg, arg, sizeof(karg))) {
- printk(KERN_ERR "failure at %s:%d/%s()!\n",
- __FILE__, __LINE__, __func__);
- return -EFAULT;
- }
- if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
- return -ENODEV;
+ u32 ioc_state;
+ int rc;
+ unsigned long timeleft;
dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
__func__));
- buffer_type = karg.unique_id & 0x000000ff;
- if (!_ctl_diag_capability(ioc, buffer_type)) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -EPERM;
- }
-
- if ((ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
- "registered\n", ioc->name, __func__, buffer_type);
- return -EINVAL;
- }
-
- if (karg.unique_id != ioc->unique_id[buffer_type]) {
- printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
- "registered\n", ioc->name, __func__, karg.unique_id);
- return -EINVAL;
- }
-
- if (ioc->diag_buffer_status[buffer_type] &
- MPT2_DIAG_BUFFER_IS_RELEASED) {
- printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
- "is already released\n", ioc->name, __func__,
- buffer_type);
- return 0;
- }
-
- request_data = ioc->diag_buffer[buffer_type];
+ rc = 0;
+ *issue_reset = 0;
- if (!request_data) {
- printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
- "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
- return -ENOMEM;
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "skipping due to FAULT state\n", ioc->name,
+ __func__));
+ rc = -EAGAIN;
+ goto out;
}
- if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
- return -EAGAIN;
- else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
- return -ERESTARTSYS;
-
if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
ioc->name, __func__);
goto out;
}
- rc = 0;
ioc->ctl_cmds.status = MPT2_CMD_PENDING;
memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
_debug_dump_mf(mpi_request,
sizeof(Mpi2DiagReleaseRequest_t)/4);
if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
- issue_reset = 1;
- goto issue_host_reset;
+ *issue_reset = 1;
+ rc = -EFAULT;
+ goto out;
}
/* process the completed Reply Message Frame */
rc = -EFAULT;
}
- issue_host_reset:
+ out:
+ ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
+ return rc;
+}
+
+/**
+ * _ctl_diag_release - request to send Diag Release Message to firmware
+ * @arg - user space buffer containing ioctl content
+ * @state - NON_BLOCKING or BLOCKING
+ *
+ * This allows ownership of the specified buffer to returned to the driver,
+ * allowing an application to read the buffer without fear that firmware is
+ * overwritting information in the buffer.
+ */
+static long
+_ctl_diag_release(void __user *arg, enum block_state state)
+{
+ struct mpt2_diag_release karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ void *request_data;
+ int rc;
+ u8 buffer_type;
+ u8 issue_reset = 0;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ buffer_type = karg.unique_id & 0x000000ff;
+ if (!_ctl_diag_capability(ioc, buffer_type)) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -EPERM;
+ }
+
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
+ "registered\n", ioc->name, __func__, buffer_type);
+ return -EINVAL;
+ }
+
+ if (karg.unique_id != ioc->unique_id[buffer_type]) {
+ printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
+ "registered\n", ioc->name, __func__, karg.unique_id);
+ return -EINVAL;
+ }
+
+ if (ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_RELEASED) {
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
+ "is already released\n", ioc->name, __func__,
+ buffer_type);
+ return 0;
+ }
+
+ request_data = ioc->diag_buffer[buffer_type];
+
+ if (!request_data) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -ENOMEM;
+ }
+
+ /* buffers were released by due to host reset */
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_DIAG_RESET)) {
+ ioc->diag_buffer_status[buffer_type] |=
+ MPT2_DIAG_BUFFER_IS_RELEASED;
+ ioc->diag_buffer_status[buffer_type] &=
+ ~MPT2_DIAG_BUFFER_IS_DIAG_RESET;
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
+ "was released due to host reset\n", ioc->name, __func__,
+ buffer_type);
+ return 0;
+ }
+
+ if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
+ return -EAGAIN;
+ else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
+ return -ERESTARTSYS;
+
+ rc = _ctl_send_release(ioc, buffer_type, &issue_reset);
+
if (issue_reset)
mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
FORCE_BIG_HAMMER);
- out:
-
- ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
mutex_unlock(&ioc->ctl_cmds.mutex);
return rc;
}
#endif
#define MPT2SAS_DEV_NAME "mpt2ctl"
-#define MPT2_MAGIC_NUMBER 'm'
+#define MPT2_MAGIC_NUMBER 'L'
#define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
/**
/* status bits for ioc->diag_buffer_status */
-#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
-#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
+#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
+#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
+#define MPT2_DIAG_BUFFER_IS_DIAG_RESET (0x04)
/* application flags for mpt2_diag_register, mpt2_diag_query */
#define MPT2_APP_FLAGS_APP_OWNED (0x0001)
*/
struct fw_event_work {
struct list_head list;
- struct delayed_work work;
+ struct work_struct work;
struct MPT2SAS_ADAPTER *ioc;
u8 VF_ID;
u8 host_reset_handling;
handle = sas_device->handle;
parent_handle = sas_device->parent_handle;
sas_address = sas_device->sas_address;
- if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) {
+ if (!mpt2sas_transport_port_add(ioc, handle, parent_handle))
_scsih_sas_device_remove(ioc, sas_device);
- } else if (!sas_device->starget) {
- mpt2sas_transport_port_remove(ioc, sas_address, parent_handle);
- _scsih_sas_device_remove(ioc, sas_device);
- }
}
/**
rphy = dev_to_rphy(starget->dev.parent);
sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
rphy->identify.sas_address);
- if (sas_device)
+ if (sas_device && (sas_device->starget == starget) &&
+ (sas_device->id == starget->id) &&
+ (sas_device->channel == starget->channel))
sas_device->starget = NULL;
spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
spin_lock_irqsave(&ioc->fw_event_lock, flags);
list_add_tail(&fw_event->list, &ioc->fw_event_list);
- INIT_DELAYED_WORK(&fw_event->work, _firmware_event_work);
- queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, 1);
+ INIT_WORK(&fw_event->work, _firmware_event_work);
+ queue_work(ioc->firmware_event_thread, &fw_event->work);
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
return;
spin_lock_irqsave(&ioc->fw_event_lock, flags);
- queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, delay);
+ queue_work(ioc->firmware_event_thread, &fw_event->work);
spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
}
struct sense_info data;
const void *sense_data = mpt2sas_base_get_sense_buffer(ioc,
smid);
- memcpy(scmd->sense_buffer, sense_data,
+ u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE,
le32_to_cpu(mpi_reply->SenseCount));
+ memcpy(scmd->sense_buffer, sense_data, sz);
_scsih_normalize_sense(scmd->sense_buffer, &data);
/* failure prediction threshold exceeded */
if (data.asc == 0x5D)
mpt2sas_scsih_issue_tm(ioc, handle, lun,
MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30);
- termination_count += le32_to_cpu(mpi_reply->TerminationCount);
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
if ((mpi_reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) &&
(mpi_reply->ResponseCode ==
continue;
mpt2sas_scsih_issue_tm(ioc, handle, lun,
- MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, smid, 30);
+ MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, 0, 30);
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
termination_count += le32_to_cpu(mpi_reply->TerminationCount);
}
- ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
ioc->broadcast_aen_busy = 0;
mutex_unlock(&ioc->tm_cmds.mutex);
_firmware_event_work(struct work_struct *work)
{
struct fw_event_work *fw_event = container_of(work,
- struct fw_event_work, work.work);
+ struct fw_event_work, work);
unsigned long flags;
struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
osdv2_attr_list_elem_size(len);
}
+static void _osd_req_alist_elem_encode(struct osd_request *or,
+ void *attr_last, const struct osd_attr *oa)
+{
+ if (osd_req_is_ver1(or)) {
+ struct osdv1_attributes_list_element *attr = attr_last;
+
+ attr->attr_page = cpu_to_be32(oa->attr_page);
+ attr->attr_id = cpu_to_be32(oa->attr_id);
+ attr->attr_bytes = cpu_to_be16(oa->len);
+ memcpy(attr->attr_val, oa->val_ptr, oa->len);
+ } else {
+ struct osdv2_attributes_list_element *attr = attr_last;
+
+ attr->attr_page = cpu_to_be32(oa->attr_page);
+ attr->attr_id = cpu_to_be32(oa->attr_id);
+ attr->attr_bytes = cpu_to_be16(oa->len);
+ memcpy(attr->attr_val, oa->val_ptr, oa->len);
+ }
+}
+
+static int _osd_req_alist_elem_decode(struct osd_request *or,
+ void *cur_p, struct osd_attr *oa, unsigned max_bytes)
+{
+ unsigned inc;
+ if (osd_req_is_ver1(or)) {
+ struct osdv1_attributes_list_element *attr = cur_p;
+
+ if (max_bytes < sizeof(*attr))
+ return -1;
+
+ oa->len = be16_to_cpu(attr->attr_bytes);
+ inc = _osd_req_alist_elem_size(or, oa->len);
+ if (inc > max_bytes)
+ return -1;
+
+ oa->attr_page = be32_to_cpu(attr->attr_page);
+ oa->attr_id = be32_to_cpu(attr->attr_id);
+
+ /* OSD1: On empty attributes we return a pointer to 2 bytes
+ * of zeros. This keeps similar behaviour with OSD2.
+ * (See below)
+ */
+ oa->val_ptr = likely(oa->len) ? attr->attr_val :
+ (u8 *)&attr->attr_bytes;
+ } else {
+ struct osdv2_attributes_list_element *attr = cur_p;
+
+ if (max_bytes < sizeof(*attr))
+ return -1;
+
+ oa->len = be16_to_cpu(attr->attr_bytes);
+ inc = _osd_req_alist_elem_size(or, oa->len);
+ if (inc > max_bytes)
+ return -1;
+
+ oa->attr_page = be32_to_cpu(attr->attr_page);
+ oa->attr_id = be32_to_cpu(attr->attr_id);
+
+ /* OSD2: For convenience, on empty attributes, we return 8 bytes
+ * of zeros here. This keeps the same behaviour with OSD2r04,
+ * and is nice with null terminating ASCII fields.
+ * oa->val_ptr == NULL marks the end-of-list, or error.
+ */
+ oa->val_ptr = likely(oa->len) ? attr->attr_val : attr->reserved;
+ }
+ return inc;
+}
+
static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
{
return osd_req_is_ver1(or) ?
struct osd_cdb *ocdb = &or->cdb;
if (osd_req_is_ver1(or))
- return &ocdb->v1.sec_params;
+ return (struct osd_security_parameters *)&ocdb->v1.sec_params;
else
- return &ocdb->v2.sec_params;
+ return (struct osd_security_parameters *)&ocdb->v2.sec_params;
}
void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
WARN_ON(or->in.bio);
bio = bio_map_kern(q, list, len, or->alloc_flags);
- if (!bio) {
+ if (IS_ERR(bio)) {
OSD_ERR("!!! Failed to allocate list_objects BIO\n");
- return -ENOMEM;
+ return PTR_ERR(bio);
}
bio->bi_rw &= ~(1 << BIO_RW);
attr_last = or->set_attr.buff + total_bytes;
for (; nelem; --nelem) {
- struct osd_attributes_list_element *attr;
unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
total_bytes += elem_size;
or->set_attr.buff + or->set_attr.total_bytes;
}
- attr = attr_last;
- attr->attr_page = cpu_to_be32(oa->attr_page);
- attr->attr_id = cpu_to_be32(oa->attr_id);
- attr->attr_bytes = cpu_to_be16(oa->len);
- memcpy(attr->attr_val, oa->val_ptr, oa->len);
+ _osd_req_alist_elem_encode(or, attr_last, oa);
attr_last += elem_size;
++oa;
}
for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
- struct osd_attributes_list_element *attr = cur_p;
- unsigned inc;
+ int inc = _osd_req_alist_elem_decode(or, cur_p, oa,
+ returned_bytes - cur_bytes);
- oa->len = be16_to_cpu(attr->attr_bytes);
- inc = _osd_req_alist_elem_size(or, oa->len);
- OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
- oa->len, inc, cur_bytes);
- cur_bytes += inc;
- if (cur_bytes > returned_bytes) {
+ if (inc < 0) {
OSD_ERR("BAD FOOD from target. list not valid!"
"c=%d r=%d n=%d\n",
cur_bytes, returned_bytes, n);
break;
}
- oa->attr_page = be32_to_cpu(attr->attr_page);
- oa->attr_id = be32_to_cpu(attr->attr_id);
- oa->val_ptr = attr->attr_val;
-
+ cur_bytes += inc;
cur_p += inc;
++oa;
}
return ret;
}
+static inline void osd_sec_parms_set_out_offset(bool is_v1,
+ struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
+{
+ if (is_v1)
+ sec_parms->v1.data_out_integrity_check_offset = offset;
+ else
+ sec_parms->v2.data_out_integrity_check_offset = offset;
+}
+
+static inline void osd_sec_parms_set_in_offset(bool is_v1,
+ struct osd_security_parameters *sec_parms, osd_cdb_offset offset)
+{
+ if (is_v1)
+ sec_parms->v1.data_in_integrity_check_offset = offset;
+ else
+ sec_parms->v2.data_in_integrity_check_offset = offset;
+}
+
static int _osd_req_finalize_data_integrity(struct osd_request *or,
bool has_in, bool has_out, const u8 *cap_key)
{
or->out_data_integ.get_attributes_bytes = cpu_to_be64(
or->enc_get_attr.total_bytes);
- sec_parms->data_out_integrity_check_offset =
- osd_req_encode_offset(or, or->out.total_bytes, &pad);
+ osd_sec_parms_set_out_offset(osd_req_is_ver1(or), sec_parms,
+ osd_req_encode_offset(or, or->out.total_bytes, &pad));
ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
&or->out);
};
unsigned pad;
- sec_parms->data_in_integrity_check_offset =
- osd_req_encode_offset(or, or->in.total_bytes, &pad);
+ osd_sec_parms_set_in_offset(osd_req_is_ver1(or), sec_parms,
+ osd_req_encode_offset(or, or->in.total_bytes, &pad));
ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
&or->in);
if (--starget->target_blocked == 0) {
SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget,
"unblocking target at zero depth\n"));
- } else {
- blk_plug_device(sdev->request_queue);
+ } else
return 0;
- }
}
if (scsi_target_is_busy(starget)) {
#include <linux/string_helpers.h>
#include <linux/async.h>
#include <asm/uaccess.h>
+#include <asm/unaligned.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
return -EINVAL;
}
- sector_size = (buffer[8] << 24) | (buffer[9] << 16) |
- (buffer[10] << 8) | buffer[11];
- lba = (((u64)buffer[0] << 56) | ((u64)buffer[1] << 48) |
- ((u64)buffer[2] << 40) | ((u64)buffer[3] << 32) |
- ((u64)buffer[4] << 24) | ((u64)buffer[5] << 16) |
- ((u64)buffer[6] << 8) | (u64)buffer[7]);
+ sector_size = get_unaligned_be32(&buffer[8]);
+ lba = get_unaligned_be64(&buffer[0]);
sd_read_protection_type(sdkp, buffer);
return -EINVAL;
}
- sector_size = (buffer[4] << 24) | (buffer[5] << 16) |
- (buffer[6] << 8) | buffer[7];
- lba = (buffer[0] << 24) | (buffer[1] << 16) |
- (buffer[2] << 8) | buffer[3];
+ sector_size = get_unaligned_be32(&buffer[4]);
+ lba = get_unaligned_be32(&buffer[0]);
if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) {
sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
/* tasklet or soft irq callback */
static void sg_rq_end_io(struct request *rq, int uptodate);
static int sg_start_req(Sg_request *srp, unsigned char *cmd);
-static void sg_finish_rem_req(Sg_request * srp);
+static int sg_finish_rem_req(Sg_request * srp);
static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
Sg_request * srp);
goto err_out;
}
err_out:
- sg_finish_rem_req(srp);
+ err = sg_finish_rem_req(srp);
return (0 == err) ? count : err;
}
return res;
}
-static void
-sg_finish_rem_req(Sg_request * srp)
+static int sg_finish_rem_req(Sg_request * srp)
{
+ int ret = 0;
+
Sg_fd *sfp = srp->parentfp;
Sg_scatter_hold *req_schp = &srp->data;
if (srp->rq) {
if (srp->bio)
- blk_rq_unmap_user(srp->bio);
+ ret = blk_rq_unmap_user(srp->bio);
blk_put_request(srp->rq);
}
sg_remove_request(sfp, srp);
+
+ return ret;
}
static int
if (0 == sr_test_unit_ready(cd->device, &sshdr))
return CDS_DISC_OK;
+ /* SK/ASC/ASCQ of 2/4/1 means "unit is becoming ready" */
+ if (scsi_sense_valid(&sshdr) && sshdr.sense_key == NOT_READY
+ && sshdr.asc == 0x04 && sshdr.ascq == 0x01)
+ return CDS_DRIVE_NOT_READY;
+
if (!cdrom_get_media_event(cdi, &med)) {
if (med.media_present)
return CDS_DISC_OK;
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/init.h>
-#include <asm/uaccess.h>
#include <linux/kernel.h>
#include <linux/mutex.h>
#include <linux/bitops.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
-#include <asm/io.h>
#include <asm/irq.h>
#include <asm/dma.h>
#include <asm/system.h>
-#include <linux/delay.h>
#include <arch/svinto.h>
#define NR_PORTS (sizeof(rs_table)/sizeof(struct e100_serial))
-static struct ktermios *serial_termios[NR_PORTS];
#ifdef CONFIG_ETRAX_SERIAL_FAST_TIMER
static struct fast_timer fast_timers[NR_PORTS];
#endif
return 0;
}
+#ifdef CONFIG_PROC_FS
/*
* /proc fs routines....
*/
-static int line_info(char *buf, struct e100_serial *info)
+static void seq_line_info(struct seq_file *m, struct e100_serial *info)
{
- char stat_buf[30];
- int ret;
unsigned long tmp;
- ret = sprintf(buf, "%d: uart:E100 port:%lX irq:%d",
- info->line, (unsigned long)info->ioport, info->irq);
+ seq_printf(m, "%d: uart:E100 port:%lX irq:%d",
+ info->line, (unsigned long)info->ioport, info->irq);
if (!info->ioport || (info->type == PORT_UNKNOWN)) {
- ret += sprintf(buf+ret, "\n");
- return ret;
+ seq_printf(m, "\n");
+ return;
}
- stat_buf[0] = 0;
- stat_buf[1] = 0;
- if (!E100_RTS_GET(info))
- strcat(stat_buf, "|RTS");
- if (!E100_CTS_GET(info))
- strcat(stat_buf, "|CTS");
- if (!E100_DTR_GET(info))
- strcat(stat_buf, "|DTR");
- if (!E100_DSR_GET(info))
- strcat(stat_buf, "|DSR");
- if (!E100_CD_GET(info))
- strcat(stat_buf, "|CD");
- if (!E100_RI_GET(info))
- strcat(stat_buf, "|RI");
-
- ret += sprintf(buf+ret, " baud:%d", info->baud);
-
- ret += sprintf(buf+ret, " tx:%lu rx:%lu",
+ seq_printf(m, " baud:%d", info->baud);
+ seq_printf(m, " tx:%lu rx:%lu",
(unsigned long)info->icount.tx,
(unsigned long)info->icount.rx);
tmp = CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
- if (tmp) {
- ret += sprintf(buf+ret, " tx_pend:%lu/%lu",
- (unsigned long)tmp,
- (unsigned long)SERIAL_XMIT_SIZE);
- }
+ if (tmp)
+ seq_printf(m, " tx_pend:%lu/%lu",
+ (unsigned long)tmp,
+ (unsigned long)SERIAL_XMIT_SIZE);
- ret += sprintf(buf+ret, " rx_pend:%lu/%lu",
- (unsigned long)info->recv_cnt,
- (unsigned long)info->max_recv_cnt);
+ seq_printf(m, " rx_pend:%lu/%lu",
+ (unsigned long)info->recv_cnt,
+ (unsigned long)info->max_recv_cnt);
#if 1
if (info->port.tty) {
-
if (info->port.tty->stopped)
- ret += sprintf(buf+ret, " stopped:%i",
- (int)info->port.tty->stopped);
+ seq_printf(m, " stopped:%i",
+ (int)info->port.tty->stopped);
if (info->port.tty->hw_stopped)
- ret += sprintf(buf+ret, " hw_stopped:%i",
- (int)info->port.tty->hw_stopped);
+ seq_printf(m, " hw_stopped:%i",
+ (int)info->port.tty->hw_stopped);
}
{
unsigned char rstat = info->ioport[REG_STATUS];
- if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect) )
- ret += sprintf(buf+ret, " xoff_detect:1");
+ if (rstat & IO_MASK(R_SERIAL0_STATUS, xoff_detect))
+ seq_printf(m, " xoff_detect:1");
}
#endif
-
-
-
if (info->icount.frame)
- ret += sprintf(buf+ret, " fe:%lu",
- (unsigned long)info->icount.frame);
+ seq_printf(m, " fe:%lu", (unsigned long)info->icount.frame);
if (info->icount.parity)
- ret += sprintf(buf+ret, " pe:%lu",
- (unsigned long)info->icount.parity);
+ seq_printf(m, " pe:%lu", (unsigned long)info->icount.parity);
if (info->icount.brk)
- ret += sprintf(buf+ret, " brk:%lu",
- (unsigned long)info->icount.brk);
+ seq_printf(m, " brk:%lu", (unsigned long)info->icount.brk);
if (info->icount.overrun)
- ret += sprintf(buf+ret, " oe:%lu",
- (unsigned long)info->icount.overrun);
+ seq_printf(m, " oe:%lu", (unsigned long)info->icount.overrun);
/*
* Last thing is the RS-232 status lines
*/
- ret += sprintf(buf+ret, " %s\n", stat_buf+1);
- return ret;
+ if (!E100_RTS_GET(info))
+ seq_puts(m, "|RTS");
+ if (!E100_CTS_GET(info))
+ seq_puts(m, "|CTS");
+ if (!E100_DTR_GET(info))
+ seq_puts(m, "|DTR");
+ if (!E100_DSR_GET(info))
+ seq_puts(m, "|DSR");
+ if (!E100_CD_GET(info))
+ seq_puts(m, "|CD");
+ if (!E100_RI_GET(info))
+ seq_puts(m, "|RI");
+ seq_puts(m, "\n");
}
-int rs_read_proc(char *page, char **start, off_t off, int count,
- int *eof, void *data)
+
+static int crisv10_proc_show(struct seq_file *m, void *v)
{
- int i, len = 0, l;
- off_t begin = 0;
+ int i;
- len += sprintf(page, "serinfo:1.0 driver:%s\n",
- serial_version);
- for (i = 0; i < NR_PORTS && len < 4000; i++) {
+ seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
+
+ for (i = 0; i < NR_PORTS; i++) {
if (!rs_table[i].enabled)
continue;
- l = line_info(page + len, &rs_table[i]);
- len += l;
- if (len+begin > off+count)
- goto done;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
+ seq_line_info(m, &rs_table[i]);
}
#ifdef DEBUG_LOG_INCLUDED
for (i = 0; i < debug_log_pos; i++) {
- len += sprintf(page + len, "%-4i %lu.%lu ", i, debug_log[i].time, timer_data_to_ns(debug_log[i].timer_data));
- len += sprintf(page + len, debug_log[i].string, debug_log[i].value);
- if (len+begin > off+count)
- goto done;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
+ seq_printf(m, "%-4i %lu.%lu ",
+ i, debug_log[i].time,
+ timer_data_to_ns(debug_log[i].timer_data));
+ seq_printf(m, debug_log[i].string, debug_log[i].value);
}
- len += sprintf(page + len, "debug_log %i/%i %li bytes\n",
- i, DEBUG_LOG_SIZE, begin+len);
+ seq_printf(m, "debug_log %i/%i\n", i, DEBUG_LOG_SIZE);
debug_log_pos = 0;
#endif
+ return 0;
+}
- *eof = 1;
-done:
- if (off >= len+begin)
- return 0;
- *start = page + (off-begin);
- return ((count < begin+len-off) ? count : begin+len-off);
+static int crisv10_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, crisv10_proc_show, NULL);
}
+static const struct file_operations crisv10_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = crisv10_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+#endif
+
+
/* Finally, routines used to initialize the serial driver. */
-static void
-show_serial_version(void)
+static void show_serial_version(void)
{
printk(KERN_INFO
- "ETRAX 100LX serial-driver %s, (c) 2000-2004 Axis Communications AB\r\n",
+ "ETRAX 100LX serial-driver %s, "
+ "(c) 2000-2004 Axis Communications AB\r\n",
&serial_version[11]); /* "$Revision: x.yy" */
}
.break_ctl = rs_break,
.send_xchar = rs_send_xchar,
.wait_until_sent = rs_wait_until_sent,
- .read_proc = rs_read_proc,
.tiocmget = rs_tiocmget,
- .tiocmset = rs_tiocmset
+ .tiocmset = rs_tiocmset,
+#ifdef CONFIG_PROC_FS
+ .proc_fops = &crisv10_proc_fops,
+#endif
};
-static int __init
-rs_init(void)
+static int __init rs_init(void)
{
int i;
struct e100_serial *info;
struct pci_dev *pci_dev;
u32 maxports; /* MAX ports this board can handle */
- spinlock_t bd_lock; /* Used to protect board */
-
spinlock_t bd_intr_lock; /* Used to protect the poller tasklet and
* the interrupt routine from each other.
*/
else
brd->maxports = 2;
- spin_lock_init(&brd->bd_lock);
spin_lock_init(&brd->bd_intr_lock);
/* store which revision we have */
.name = "Samsung S3C6400 UART",
.type = PORT_S3C6400,
.fifosize = 64,
+ .has_divslot = 1,
.rx_fifomask = S3C2440_UFSTAT_RXMASK,
.rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
.rx_fifofull = S3C2440_UFSTAT_RXFULL,
struct baud_calc {
struct s3c24xx_uart_clksrc *clksrc;
unsigned int calc;
+ unsigned int divslot;
unsigned int quot;
struct clk *src;
};
struct s3c24xx_uart_clksrc *clksrc,
unsigned int baud)
{
+ struct s3c24xx_uart_port *ourport = to_ourport(port);
unsigned long rate;
calc->src = clk_get(port->dev, clksrc->name);
rate /= clksrc->divisor;
calc->clksrc = clksrc;
- calc->quot = (rate + (8 * baud)) / (16 * baud);
- calc->calc = (rate / (calc->quot * 16));
+
+ if (ourport->info->has_divslot) {
+ unsigned long div = rate / baud;
+
+ /* The UDIVSLOT register on the newer UARTs allows us to
+ * get a divisor adjustment of 1/16th on the baud clock.
+ *
+ * We don't keep the UDIVSLOT value (the 16ths we calculated
+ * by not multiplying the baud by 16) as it is easy enough
+ * to recalculate.
+ */
+
+ calc->quot = div / 16;
+ calc->calc = rate / div;
+ } else {
+ calc->quot = (rate + (8 * baud)) / (16 * baud);
+ calc->calc = (rate / (calc->quot * 16));
+ }
calc->quot--;
return 1;
return best->quot;
}
+/* udivslot_table[]
+ *
+ * This table takes the fractional value of the baud divisor and gives
+ * the recommended setting for the UDIVSLOT register.
+ */
+static u16 udivslot_table[16] = {
+ [0] = 0x0000,
+ [1] = 0x0080,
+ [2] = 0x0808,
+ [3] = 0x0888,
+ [4] = 0x2222,
+ [5] = 0x4924,
+ [6] = 0x4A52,
+ [7] = 0x54AA,
+ [8] = 0x5555,
+ [9] = 0xD555,
+ [10] = 0xD5D5,
+ [11] = 0xDDD5,
+ [12] = 0xDDDD,
+ [13] = 0xDFDD,
+ [14] = 0xDFDF,
+ [15] = 0xFFDF,
+};
+
static void s3c24xx_serial_set_termios(struct uart_port *port,
struct ktermios *termios,
struct ktermios *old)
unsigned int baud, quot;
unsigned int ulcon;
unsigned int umcon;
+ unsigned int udivslot = 0;
/*
* We don't support modem control lines.
/* check to see if we need to change clock source */
if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
+ dbg("selecting clock %p\n", clk);
s3c24xx_serial_setsource(port, clksrc);
if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
}
+ if (ourport->info->has_divslot) {
+ unsigned int div = ourport->baudclk_rate / baud;
+
+ udivslot = udivslot_table[div & 15];
+ dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
+ }
+
switch (termios->c_cflag & CSIZE) {
case CS5:
dbg("config: 5bits/char\n");
spin_lock_irqsave(&port->lock, flags);
- dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot);
+ dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
+ ulcon, quot, udivslot);
wr_regl(port, S3C2410_ULCON, ulcon);
wr_regl(port, S3C2410_UBRDIV, quot);
wr_regl(port, S3C2410_UMCON, umcon);
+ if (ourport->info->has_divslot)
+ wr_regl(port, S3C2443_DIVSLOT, udivslot);
+
dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
rd_regl(port, S3C2410_ULCON),
rd_regl(port, S3C2410_UCON),
unsigned long tx_fifoshift;
unsigned long tx_fifofull;
+ /* uart port features */
+
+ unsigned int has_divslot:1;
+
/* clock source control */
int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
obj-$(CONFIG_FB_IMSTT) += imsttfb.o
obj-$(CONFIG_FB_FM2) += fm2fb.o
obj-$(CONFIG_FB_VT8623) += vt8623fb.o
-obj-$(CONFIG_FB_CYBLA) += cyblafb.o
obj-$(CONFIG_FB_TRIDENT) += tridentfb.o
obj-$(CONFIG_FB_LE80578) += vermilion/
obj-$(CONFIG_FB_S3) += s3fb.o
*
* NOTES:
*
- * The code for depths like 24 that don't have integer number of pixels per
- * long is broken and needs to be fixed. For now I turned these types of
- * mode off.
- *
* Also need to add code to deal with cards endians that are different than
* the native cpu endians. I also need to deal with MSB position in the word.
*
// Trailing bits
if (last)
- FB_WRITEL(comp(pat, FB_READL(dst), first), dst);
+ FB_WRITEL(comp(pat, FB_READL(dst), last), dst);
}
}
void cfb_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
{
- unsigned long pat, fg;
+ unsigned long pat, pat2, fg;
unsigned long width = rect->width, height = rect->height;
int bits = BITS_PER_LONG, bytes = bits >> 3;
u32 bpp = p->var.bits_per_pixel;
else
fg = rect->color;
- pat = pixel_to_pat( bpp, fg);
+ pat = pixel_to_pat(bpp, fg);
dst = (unsigned long __iomem *)((unsigned long)p->screen_base & ~(bytes-1));
dst_idx = ((unsigned long)p->screen_base & (bytes - 1))*8;
dst_idx += p->fix.line_length*8;
}
} else {
- int right;
- int r;
- int rot = (left-dst_idx) % bpp;
+ int right, r;
void (*fill_op)(struct fb_info *p, unsigned long __iomem *dst,
int dst_idx, unsigned long pat, int left,
int right, unsigned n, int bits) = NULL;
-
- /* rotate pattern to correct start position */
- pat = pat << rot | pat >> (bpp-rot);
-
- right = bpp-left;
+#ifdef __LITTLE_ENDIAN
+ right = left;
+ left = bpp - right;
+#else
+ right = bpp - left;
+#endif
switch (rect->rop) {
case ROP_XOR:
fill_op = bitfill_unaligned_rev;
fill_op = bitfill_unaligned;
break;
default:
- printk( KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
+ printk(KERN_ERR "cfb_fillrect(): unknown rop, defaulting to ROP_COPY\n");
fill_op = bitfill_unaligned;
break;
}
while (height--) {
- dst += dst_idx >> (ffs(bits) - 1);
+ dst += dst_idx / bits;
dst_idx &= (bits - 1);
- fill_op(p, dst, dst_idx, pat, left, right,
+ r = dst_idx % bpp;
+ /* rotate pattern to the correct start position */
+ pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
+ fill_op(p, dst, dst_idx, pat2, left, right,
width*bpp, bits);
- r = (p->fix.line_length*8) % bpp;
- pat = pat << (bpp-r) | pat >> r;
dst_idx += p->fix.line_length*8;
}
}
font->charcount = vga_512_chars ? 512 : 256;
if (!font->data)
return 0;
- return vgacon_do_font_op(&state, font->data, 0, 0);
+ return vgacon_do_font_op(&state, font->data, 0, vga_512_chars);
}
#else
case 8:
return 0x0101010101010101ul*pixel;
case 12:
- return 0x0001001001001001ul*pixel;
+ return 0x1001001001001001ul*pixel;
case 16:
return 0x0001000100010001ul*pixel;
case 24:
- return 0x0000000001000001ul*pixel;
+ return 0x0001000001000001ul*pixel;
case 32:
return 0x0000000100000001ul*pixel;
default:
case 8:
return 0x01010101ul*pixel;
case 12:
- return 0x00001001ul*pixel;
+ return 0x01001001ul*pixel;
case 16:
return 0x00010001ul*pixel;
case 24:
- return 0x00000001ul*pixel;
+ return 0x01000001ul*pixel;
case 32:
return 0x00000001ul*pixel;
default:
#endif /* CONFIG_FB_CFB_REV_PIXELS_IN_BYTE */
+#define cpu_to_le_long _cpu_to_le_long(BITS_PER_LONG)
+#define _cpu_to_le_long(x) __cpu_to_le_long(x)
+#define __cpu_to_le_long(x) cpu_to_le##x
+
+#define le_long_to_cpu _le_long_to_cpu(BITS_PER_LONG)
+#define _le_long_to_cpu(x) __le_long_to_cpu(x)
+#define __le_long_to_cpu(x) le##x##_to_cpu
+
+static inline unsigned long rolx(unsigned long word, unsigned int shift, unsigned int x)
+{
+ return (word << shift) | (word >> (x - shift));
+}
+
#endif /* FB_DRAW_H */
*/
static int mx3fb_suspend(struct platform_device *pdev, pm_message_t state)
{
- struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
- struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
+ struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
+ struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
acquire_console_sem();
- fb_set_suspend(drv_data->fbi, 1);
+ fb_set_suspend(mx3fb->fbi, 1);
release_console_sem();
if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
*/
static int mx3fb_resume(struct platform_device *pdev)
{
- struct mx3fb_data *drv_data = platform_get_drvdata(pdev);
- struct mx3fb_info *mx3_fbi = drv_data->fbi->par;
+ struct mx3fb_data *mx3fb = platform_get_drvdata(pdev);
+ struct mx3fb_info *mx3_fbi = mx3fb->fbi->par;
if (mx3_fbi->blank == FB_BLANK_UNBLANK) {
sdc_enable_channel(mx3_fbi);
- sdc_set_brightness(mx3fb, drv_data->backlight_level);
+ sdc_set_brightness(mx3fb, mx3fb->backlight_level);
}
acquire_console_sem();
- fb_set_suspend(drv_data->fbi, 0);
+ fb_set_suspend(mx3fb->fbi, 0);
release_console_sem();
return 0;
/* Trailing bits */
if (last)
- *dst = comp(pat, *dst, first);
+ *dst = comp(pat, *dst, last);
}
}
void sys_fillrect(struct fb_info *p, const struct fb_fillrect *rect)
{
- unsigned long pat, fg;
+ unsigned long pat, pat2, fg;
unsigned long width = rect->width, height = rect->height;
int bits = BITS_PER_LONG, bytes = bits >> 3;
u32 bpp = p->var.bits_per_pixel;
dst_idx += p->fix.line_length*8;
}
} else {
- int right;
- int r;
- int rot = (left-dst_idx) % bpp;
+ int right, r;
void (*fill_op)(struct fb_info *p, unsigned long *dst,
int dst_idx, unsigned long pat, int left,
int right, unsigned n, int bits) = NULL;
-
- /* rotate pattern to correct start position */
- pat = pat << rot | pat >> (bpp-rot);
-
- right = bpp-left;
+#ifdef __LITTLE_ENDIAN
+ right = left;
+ left = bpp - right;
+#else
+ right = bpp - left;
+#endif
switch (rect->rop) {
case ROP_XOR:
fill_op = bitfill_unaligned_rev;
fill_op = bitfill_unaligned;
break;
default:
- printk(KERN_ERR "cfb_fillrect(): unknown rop, "
+ printk(KERN_ERR "sys_fillrect(): unknown rop, "
"defaulting to ROP_COPY\n");
fill_op = bitfill_unaligned;
break;
}
while (height--) {
- dst += dst_idx >> (ffs(bits) - 1);
+ dst += dst_idx / bits;
dst_idx &= (bits - 1);
- fill_op(p, dst, dst_idx, pat, left, right,
+ r = dst_idx % bpp;
+ /* rotate pattern to the correct start position */
+ pat2 = le_long_to_cpu(rolx(cpu_to_le_long(pat), r, bpp));
+ fill_op(p, dst, dst_idx, pat2, left, right,
width*bpp, bits);
- r = (p->fix.line_length*8) % bpp;
- pat = pat << (bpp-r) | pat >> r;
dst_idx += p->fix.line_length*8;
}
}
char *buf)
{
return sprintf(buf, "%llu\n",
- (u64)balloon_stats.target_pages << PAGE_SHIFT);
+ (unsigned long long)balloon_stats.target_pages
+ << PAGE_SHIFT);
}
static ssize_t store_target(struct sys_device *dev,
* Otherwise it's an offset mount and we need to check
* if we can umount its mount, if there is one.
*/
- if (!d_mountpoint(dentry))
+ if (!d_mountpoint(dentry)) {
+ status = 0;
goto done;
+ }
}
/* Update the expiry counter if fs is busy */
prstatus->pr_sigpend = p->pending.signal.sig[0];
prstatus->pr_sighold = p->blocked.sig[0];
prstatus->pr_pid = task_pid_vnr(p);
- prstatus->pr_ppid = task_pid_vnr(p->parent);
+ prstatus->pr_ppid = task_pid_vnr(p->real_parent);
prstatus->pr_pgrp = task_pgrp_vnr(p);
prstatus->pr_sid = task_session_vnr(p);
if (thread_group_leader(p)) {
psinfo->pr_psargs[len] = 0;
psinfo->pr_pid = task_pid_vnr(p);
- psinfo->pr_ppid = task_pid_vnr(p->parent);
+ psinfo->pr_ppid = task_pid_vnr(p->real_parent);
psinfo->pr_pgrp = task_pgrp_vnr(p);
psinfo->pr_sid = task_session_vnr(p);
if ((page->mapping != inode->i_mapping) ||
(page_offset(page) > size)) {
/* page got truncated out from underneath us */
- goto out_unlock;
+ unlock_page(page);
+ goto out;
}
/* page is wholly or partially inside EOF */
ret = block_commit_write(page, 0, end);
if (unlikely(ret)) {
+ unlock_page(page);
if (ret == -ENOMEM)
ret = VM_FAULT_OOM;
else /* -ENOSPC, -EIO, etc */
ret = VM_FAULT_SIGBUS;
- }
+ } else
+ ret = VM_FAULT_LOCKED;
-out_unlock:
- unlock_page(page);
+out:
return ret;
}
+Version 1.58
+------------
+Guard against buffer overruns in various UCS-2 to UTF-8 string conversions
+when the UTF-8 string is composed of unusually long (more than 4 byte) converted
+characters. Add support for mounting root of a share which redirects immediately
+to DFS target. Convert string conversion functions from Unicode to more
+accurately mark string length before allocating memory (which may help the
+rare cases where a UTF-8 string is much larger than the UCS2 string that
+we converted from). Fix endianness of the vcnum field used during
+session setup to distinguish multiple mounts to same server from different
+userids. Raw NTLMSSP fixed (it requires /proc/fs/cifs/experimental
+flag to be set to 2, and mount must enable krb5 to turn on extended security).
+
Version 1.57
------------
Improve support for multiple security contexts to the same server. We
signing turned on in case buffer was modified
just before it was sent, also this flag will
be used to use the new experimental directory change
- notification code).
+ notification code). When set to 2 enables
+ an additional experimental feature, "raw ntlmssp"
+ session establishment support (which allows
+ specifying "sec=ntlmssp" on mount). The Linux cifs
+ module will use ntlmv2 authentication encapsulated
+ in "raw ntlmssp" (not using SPNEGO) when
+ "sec=ntlmssp" is specified on mount.
+ This support also requires building cifs with
+ the CONFIG_CIFS_EXPERIMENTAL configuration flag.
These experimental features and tracing can be enabled by changing flags in
/proc/fs/cifs (after the cifs module has been installed or built into the
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
for (i = 0; i < num_referrals; i++) {
+ int len;
dump_referral(referrals+i);
- /* connect to a storage node */
- if (referrals[i].flags & DFSREF_STORAGE_SERVER) {
- int len;
- len = strlen(referrals[i].node_name);
- if (len < 2) {
- cERROR(1, ("%s: Net Address path too short: %s",
+ /* connect to a node */
+ len = strlen(referrals[i].node_name);
+ if (len < 2) {
+ cERROR(1, ("%s: Net Address path too short: %s",
__func__, referrals[i].node_name));
- rc = -EINVAL;
- goto out_err;
- }
- mnt = cifs_dfs_do_refmount(nd->path.mnt,
- nd->path.dentry,
- referrals + i);
- cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p",
- __func__,
+ rc = -EINVAL;
+ goto out_err;
+ }
+ mnt = cifs_dfs_do_refmount(nd->path.mnt,
+ nd->path.dentry, referrals + i);
+ cFYI(1, ("%s: cifs_dfs_do_refmount:%s , mnt:%p", __func__,
referrals[i].node_name, mnt));
- /* complete mount procedure if we accured submount */
- if (!IS_ERR(mnt))
- break;
- }
+ /* complete mount procedure if we accured submount */
+ if (!IS_ERR(mnt))
+ break;
}
/* we need it cause for() above could exit without valid submount */
/*
* fs/cifs/cifs_unicode.c
*
- * Copyright (c) International Business Machines Corp., 2000,2005
+ * Copyright (c) International Business Machines Corp., 2000,2009
* Modified by Steve French (sfrench@us.ibm.com)
*
* This program is free software; you can redistribute it and/or modify
#include "cifs_debug.h"
/*
- * NAME: cifs_strfromUCS()
- *
- * FUNCTION: Convert little-endian unicode string to character string
+ * cifs_ucs2_bytes - how long will a string be after conversion?
+ * @ucs - pointer to input string
+ * @maxbytes - don't go past this many bytes of input string
+ * @codepage - destination codepage
*
+ * Walk a ucs2le string and return the number of bytes that the string will
+ * be after being converted to the given charset, not including any null
+ * termination required. Don't walk past maxbytes in the source buffer.
*/
int
-cifs_strfromUCS_le(char *to, const __le16 *from,
- int len, const struct nls_table *codepage)
+cifs_ucs2_bytes(const __le16 *from, int maxbytes,
+ const struct nls_table *codepage)
{
int i;
- int outlen = 0;
+ int charlen, outlen = 0;
+ int maxwords = maxbytes / 2;
+ char tmp[NLS_MAX_CHARSET_SIZE];
- for (i = 0; (i < len) && from[i]; i++) {
- int charlen;
- /* 2.4.0 kernel or greater */
- charlen =
- codepage->uni2char(le16_to_cpu(from[i]), &to[outlen],
- NLS_MAX_CHARSET_SIZE);
- if (charlen > 0) {
+ for (i = 0; from[i] && i < maxwords; i++) {
+ charlen = codepage->uni2char(le16_to_cpu(from[i]), tmp,
+ NLS_MAX_CHARSET_SIZE);
+ if (charlen > 0)
outlen += charlen;
- } else {
- to[outlen++] = '?';
+ else
+ outlen++;
+ }
+
+ return outlen;
+}
+
+/*
+ * cifs_mapchar - convert a little-endian char to proper char in codepage
+ * @target - where converted character should be copied
+ * @src_char - 2 byte little-endian source character
+ * @cp - codepage to which character should be converted
+ * @mapchar - should character be mapped according to mapchars mount option?
+ *
+ * This function handles the conversion of a single character. It is the
+ * responsibility of the caller to ensure that the target buffer is large
+ * enough to hold the result of the conversion (at least NLS_MAX_CHARSET_SIZE).
+ */
+static int
+cifs_mapchar(char *target, const __le16 src_char, const struct nls_table *cp,
+ bool mapchar)
+{
+ int len = 1;
+
+ if (!mapchar)
+ goto cp_convert;
+
+ /*
+ * BB: Cannot handle remapping UNI_SLASH until all the calls to
+ * build_path_from_dentry are modified, as they use slash as
+ * separator.
+ */
+ switch (le16_to_cpu(src_char)) {
+ case UNI_COLON:
+ *target = ':';
+ break;
+ case UNI_ASTERIK:
+ *target = '*';
+ break;
+ case UNI_QUESTION:
+ *target = '?';
+ break;
+ case UNI_PIPE:
+ *target = '|';
+ break;
+ case UNI_GRTRTHAN:
+ *target = '>';
+ break;
+ case UNI_LESSTHAN:
+ *target = '<';
+ break;
+ default:
+ goto cp_convert;
+ }
+
+out:
+ return len;
+
+cp_convert:
+ len = cp->uni2char(le16_to_cpu(src_char), target,
+ NLS_MAX_CHARSET_SIZE);
+ if (len <= 0) {
+ *target = '?';
+ len = 1;
+ }
+ goto out;
+}
+
+/*
+ * cifs_from_ucs2 - convert utf16le string to local charset
+ * @to - destination buffer
+ * @from - source buffer
+ * @tolen - destination buffer size (in bytes)
+ * @fromlen - source buffer size (in bytes)
+ * @codepage - codepage to which characters should be converted
+ * @mapchar - should characters be remapped according to the mapchars option?
+ *
+ * Convert a little-endian ucs2le string (as sent by the server) to a string
+ * in the provided codepage. The tolen and fromlen parameters are to ensure
+ * that the code doesn't walk off of the end of the buffer (which is always
+ * a danger if the alignment of the source buffer is off). The destination
+ * string is always properly null terminated and fits in the destination
+ * buffer. Returns the length of the destination string in bytes (including
+ * null terminator).
+ *
+ * Note that some windows versions actually send multiword UTF-16 characters
+ * instead of straight UCS-2. The linux nls routines however aren't able to
+ * deal with those characters properly. In the event that we get some of
+ * those characters, they won't be translated properly.
+ */
+int
+cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
+ const struct nls_table *codepage, bool mapchar)
+{
+ int i, charlen, safelen;
+ int outlen = 0;
+ int nullsize = nls_nullsize(codepage);
+ int fromwords = fromlen / 2;
+ char tmp[NLS_MAX_CHARSET_SIZE];
+
+ /*
+ * because the chars can be of varying widths, we need to take care
+ * not to overflow the destination buffer when we get close to the
+ * end of it. Until we get to this offset, we don't need to check
+ * for overflow however.
+ */
+ safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize);
+
+ for (i = 0; i < fromwords && from[i]; i++) {
+ /*
+ * check to see if converting this character might make the
+ * conversion bleed into the null terminator
+ */
+ if (outlen >= safelen) {
+ charlen = cifs_mapchar(tmp, from[i], codepage, mapchar);
+ if ((outlen + charlen) > (tolen - nullsize))
+ break;
}
+
+ /* put converted char into 'to' buffer */
+ charlen = cifs_mapchar(&to[outlen], from[i], codepage, mapchar);
+ outlen += charlen;
}
- to[outlen] = 0;
+
+ /* properly null-terminate string */
+ for (i = 0; i < nullsize; i++)
+ to[outlen++] = 0;
+
return outlen;
}
return i;
}
+/*
+ * cifs_strndup_from_ucs - copy a string from wire format to the local codepage
+ * @src - source string
+ * @maxlen - don't walk past this many bytes in the source string
+ * @is_unicode - is this a unicode string?
+ * @codepage - destination codepage
+ *
+ * Take a string given by the server, convert it to the local codepage and
+ * put it in a new buffer. Returns a pointer to the new string or NULL on
+ * error.
+ */
+char *
+cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode,
+ const struct nls_table *codepage)
+{
+ int len;
+ char *dst;
+
+ if (is_unicode) {
+ len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage);
+ len += nls_nullsize(codepage);
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst)
+ return NULL;
+ cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage,
+ false);
+ } else {
+ len = strnlen(src, maxlen);
+ len++;
+ dst = kmalloc(len, GFP_KERNEL);
+ if (!dst)
+ return NULL;
+ strlcpy(dst, src, len);
+ }
+
+ return dst;
+}
+
* Convert a unicode character to upper or lower case using
* compressed tables.
*
- * Copyright (c) International Business Machines Corp., 2000,2007
+ * Copyright (c) International Business Machines Corp., 2000,2009
*
* 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
#define UNIUPR_NOLOWER /* Example to not expand lower case tables */
+/*
+ * Windows maps these to the user defined 16 bit Unicode range since they are
+ * reserved symbols (along with \ and /), otherwise illegal to store
+ * in filenames in NTFS
+ */
+#define UNI_ASTERIK (__u16) ('*' + 0xF000)
+#define UNI_QUESTION (__u16) ('?' + 0xF000)
+#define UNI_COLON (__u16) (':' + 0xF000)
+#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
+#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
+#define UNI_PIPE (__u16) ('|' + 0xF000)
+#define UNI_SLASH (__u16) ('\\' + 0xF000)
+
/* Just define what we want from uniupr.h. We don't want to define the tables
* in each source file.
*/
#endif /* UNIUPR_NOLOWER */
#ifdef __KERNEL__
-int cifs_strfromUCS_le(char *, const __le16 *, int, const struct nls_table *);
+int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen,
+ const struct nls_table *codepage, bool mapchar);
+int cifs_ucs2_bytes(const __le16 *from, int maxbytes,
+ const struct nls_table *codepage);
int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *);
+char *cifs_strndup_from_ucs(const char *src, const int maxlen,
+ const bool is_unicode,
+ const struct nls_table *codepage);
#endif
/*
extern const struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */
-#define CIFS_VERSION "1.57"
+#define CIFS_VERSION "1.58"
#endif /* _CIFSFS_H */
LANMAN, /* Legacy LANMAN auth */
NTLM, /* Legacy NTLM012 auth with NTLM hash */
NTLMv2, /* Legacy NTLM auth with NTLMv2 hash */
- RawNTLMSSP, /* NTLMSSP without SPNEGO */
- NTLMSSP, /* NTLMSSP via SPNEGO */
+ RawNTLMSSP, /* NTLMSSP without SPNEGO, NTLMv2 hash */
+ NTLMSSP, /* NTLMSSP via SPNEGO, NTLMv2 hash */
Kerberos, /* Kerberos via SPNEGO */
MSKerberos, /* MS Kerberos via SPNEGO */
};
#define CIFSSEC_MAY_PLNTXT 0
#endif /* weak passwords */
#define CIFSSEC_MAY_SEAL 0x00040 /* not supported yet */
+#define CIFSSEC_MAY_NTLMSSP 0x00080 /* raw ntlmssp with ntlmv2 */
#define CIFSSEC_MUST_SIGN 0x01001
/* note that only one of the following can be set so the
#define CIFSSEC_MUST_LANMAN 0x10010
#define CIFSSEC_MUST_PLNTXT 0x20020
#ifdef CONFIG_CIFS_UPCALL
-#define CIFSSEC_MASK 0x3F03F /* allows weak security but also krb5 */
+#define CIFSSEC_MASK 0xAF0AF /* allows weak security but also krb5 */
#else
-#define CIFSSEC_MASK 0x37037 /* current flags supported if weak */
+#define CIFSSEC_MASK 0xA70A7 /* current flags supported if weak */
#endif /* UPCALL */
#else /* do not allow weak pw hash */
#ifdef CONFIG_CIFS_UPCALL
-#define CIFSSEC_MASK 0x0F00F /* flags supported if no weak allowed */
+#define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */
#else
-#define CIFSSEC_MASK 0x07007 /* flags supported if no weak allowed */
+#define CIFSSEC_MASK 0x87087 /* flags supported if no weak allowed */
#endif /* UPCALL */
#endif /* WEAK_PW_HASH */
#define CIFSSEC_MUST_SEAL 0x40040 /* not supported yet */
+#define CIFSSEC_MUST_NTLMSSP 0x80080 /* raw ntlmssp with ntlmv2 */
#define CIFSSEC_DEF (CIFSSEC_MAY_SIGN | CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2)
#define CIFSSEC_MAX (CIFSSEC_MUST_SIGN | CIFSSEC_MUST_NTLMV2)
-#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5)
+#define CIFSSEC_AUTH_MASK (CIFSSEC_MAY_NTLM | CIFSSEC_MAY_NTLMV2 | CIFSSEC_MAY_LANMAN | CIFSSEC_MAY_PLNTXT | CIFSSEC_MAY_KRB5 | CIFSSEC_MAY_NTLMSSP)
/*
*****************************************************************
* All constants go here
const struct nls_table *nls_codepage);
extern int CIFSSMBUnixQuerySymLink(const int xid,
struct cifsTconInfo *tcon,
- const unsigned char *searchName,
- char *syminfo, const int buflen,
+ const unsigned char *searchName, char **syminfo,
const struct nls_table *nls_codepage);
extern int CIFSSMBQueryReparseLinkInfo(const int xid,
struct cifsTconInfo *tcon,
const unsigned char *searchName, __u64 *inode_number,
const struct nls_table *nls_codepage,
int remap_special_chars);
-extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
- const struct nls_table *codepage);
extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen,
const struct nls_table *cp, int mapChars);
/*
* fs/cifs/cifssmb.c
*
- * Copyright (C) International Business Machines Corp., 2002,2008
+ * Copyright (C) International Business Machines Corp., 2002,2009
* Author(s): Steve French (sfrench@us.ibm.com)
*
* Contains the routines for constructing the SMB PDUs themselves
#endif /* CONFIG_CIFS_WEAK_PW_HASH */
#endif /* CIFS_POSIX */
-/* Allocates buffer into dst and copies smb string from src to it.
- * caller is responsible for freeing dst if function returned 0.
- * returns:
- * on success - 0
- * on failure - errno
- */
-static int
-cifs_strncpy_to_host(char **dst, const char *src, const int maxlen,
- const bool is_unicode, const struct nls_table *nls_codepage)
-{
- int plen;
-
- if (is_unicode) {
- plen = UniStrnlen((wchar_t *)src, maxlen);
- *dst = kmalloc(plen + 2, GFP_KERNEL);
- if (!*dst)
- goto cifs_strncpy_to_host_ErrExit;
- cifs_strfromUCS_le(*dst, (__le16 *)src, plen, nls_codepage);
- } else {
- plen = strnlen(src, maxlen);
- *dst = kmalloc(plen + 2, GFP_KERNEL);
- if (!*dst)
- goto cifs_strncpy_to_host_ErrExit;
- strncpy(*dst, src, plen);
- }
- (*dst)[plen] = 0;
- (*dst)[plen+1] = 0; /* harmless for ASCII case, needed for Unicode */
- return 0;
-
-cifs_strncpy_to_host_ErrExit:
- cERROR(1, ("Failed to allocate buffer for string\n"));
- return -ENOMEM;
-}
-
-
/* Mark as invalid, all open files on tree connections since they
were closed when session to server was lost */
static void mark_open_files_invalid(struct cifsTconInfo *pTcon)
cFYI(1, ("Kerberos only mechanism, enable extended security"));
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
}
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ else if ((secFlags & CIFSSEC_MUST_NTLMSSP) == CIFSSEC_MUST_NTLMSSP)
+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ else if ((secFlags & CIFSSEC_AUTH_MASK) == CIFSSEC_MAY_NTLMSSP) {
+ cFYI(1, ("NTLMSSP only mechanism, enable extended security"));
+ pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ }
+#endif
count = 0;
for (i = 0; i < CIFS_NUM_PROT; i++) {
server->secType = NTLMv2;
else if (secFlags & CIFSSEC_MAY_KRB5)
server->secType = Kerberos;
+ else if (secFlags & CIFSSEC_MAY_NTLMSSP)
+ server->secType = NTLMSSP;
else if (secFlags & CIFSSEC_MAY_LANMAN)
server->secType = LANMAN;
/* #ifdef CONFIG_CIFS_EXPERIMENTAL
int
CIFSSMBUnixQuerySymLink(const int xid, struct cifsTconInfo *tcon,
- const unsigned char *searchName,
- char *symlinkinfo, const int buflen,
+ const unsigned char *searchName, char **symlinkinfo,
const struct nls_table *nls_codepage)
{
/* SMB_QUERY_FILE_UNIX_LINK */
int bytes_returned;
int name_len;
__u16 params, byte_count;
+ char *data_start;
cFYI(1, ("In QPathSymLinkInfo (Unix) for path %s", searchName));
/* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);
- if (rc || (pSMBr->ByteCount < 2))
/* BB also check enough total bytes returned */
- rc = -EIO; /* bad smb */
+ if (rc || (pSMBr->ByteCount < 2))
+ rc = -EIO;
else {
- __u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
- __u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+ bool is_unicode;
+ u16 count = le16_to_cpu(pSMBr->t2.DataCount);
+
+ data_start = ((char *) &pSMBr->hdr.Protocol) +
+ le16_to_cpu(pSMBr->t2.DataOffset);
+
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE)
+ is_unicode = true;
+ else
+ is_unicode = false;
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = UniStrnlen((wchar_t *) ((char *)
- &pSMBr->hdr.Protocol + data_offset),
- min_t(const int, buflen, count) / 2);
/* BB FIXME investigate remapping reserved chars here */
- cifs_strfromUCS_le(symlinkinfo,
- (__le16 *) ((char *)&pSMBr->hdr.Protocol
- + data_offset),
- name_len, nls_codepage);
- } else {
- strncpy(symlinkinfo,
- (char *) &pSMBr->hdr.Protocol +
- data_offset,
- min_t(const int, buflen, count));
- }
- symlinkinfo[buflen] = 0;
- /* just in case so calling code does not go off the end of buffer */
+ *symlinkinfo = cifs_strndup_from_ucs(data_start, count,
+ is_unicode, nls_codepage);
+ if (!symlinkinfo)
+ rc = -ENOMEM;
}
}
cifs_buf_release(pSMB);
*pparmlen = parm_count;
return 0;
}
-#endif /* CIFS_EXPERIMENTAL */
int
CIFSSMBQueryReparseLinkInfo(const int xid, struct cifsTconInfo *tcon,
{
int rc = 0;
int bytes_returned;
- int name_len;
struct smb_com_transaction_ioctl_req *pSMB;
struct smb_com_transaction_ioctl_rsp *pSMBr;
} else { /* decode response */
__u32 data_offset = le32_to_cpu(pSMBr->DataOffset);
__u32 data_count = le32_to_cpu(pSMBr->DataCount);
- if ((pSMBr->ByteCount < 2) || (data_offset > 512))
+ if ((pSMBr->ByteCount < 2) || (data_offset > 512)) {
/* BB also check enough total bytes returned */
rc = -EIO; /* bad smb */
- else {
- if (data_count && (data_count < 2048)) {
- char *end_of_smb = 2 /* sizeof byte count */ +
- pSMBr->ByteCount +
- (char *)&pSMBr->ByteCount;
+ goto qreparse_out;
+ }
+ if (data_count && (data_count < 2048)) {
+ char *end_of_smb = 2 /* sizeof byte count */ +
+ pSMBr->ByteCount + (char *)&pSMBr->ByteCount;
- struct reparse_data *reparse_buf =
+ struct reparse_data *reparse_buf =
(struct reparse_data *)
((char *)&pSMBr->hdr.Protocol
+ data_offset);
- if ((char *)reparse_buf >= end_of_smb) {
- rc = -EIO;
- goto qreparse_out;
- }
- if ((reparse_buf->LinkNamesBuf +
- reparse_buf->TargetNameOffset +
- reparse_buf->TargetNameLen) >
- end_of_smb) {
- cFYI(1, ("reparse buf beyond SMB"));
- rc = -EIO;
- goto qreparse_out;
- }
+ if ((char *)reparse_buf >= end_of_smb) {
+ rc = -EIO;
+ goto qreparse_out;
+ }
+ if ((reparse_buf->LinkNamesBuf +
+ reparse_buf->TargetNameOffset +
+ reparse_buf->TargetNameLen) > end_of_smb) {
+ cFYI(1, ("reparse buf beyond SMB"));
+ rc = -EIO;
+ goto qreparse_out;
+ }
- if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
- name_len = UniStrnlen((wchar_t *)
+ if (pSMBr->hdr.Flags2 & SMBFLG2_UNICODE) {
+ cifs_from_ucs2(symlinkinfo, (__le16 *)
(reparse_buf->LinkNamesBuf +
reparse_buf->TargetNameOffset),
- min(buflen/2,
- reparse_buf->TargetNameLen / 2));
- cifs_strfromUCS_le(symlinkinfo,
- (__le16 *) (reparse_buf->LinkNamesBuf +
- reparse_buf->TargetNameOffset),
- name_len, nls_codepage);
- } else { /* ASCII names */
- strncpy(symlinkinfo,
- reparse_buf->LinkNamesBuf +
- reparse_buf->TargetNameOffset,
- min_t(const int, buflen,
- reparse_buf->TargetNameLen));
- }
- } else {
- rc = -EIO;
- cFYI(1, ("Invalid return data count on "
- "get reparse info ioctl"));
+ buflen,
+ reparse_buf->TargetNameLen,
+ nls_codepage, 0);
+ } else { /* ASCII names */
+ strncpy(symlinkinfo,
+ reparse_buf->LinkNamesBuf +
+ reparse_buf->TargetNameOffset,
+ min_t(const int, buflen,
+ reparse_buf->TargetNameLen));
}
- symlinkinfo[buflen] = 0; /* just in case so the caller
- does not go off the end of the buffer */
- cFYI(1, ("readlink result - %s", symlinkinfo));
+ } else {
+ rc = -EIO;
+ cFYI(1, ("Invalid return data count on "
+ "get reparse info ioctl"));
}
+ symlinkinfo[buflen] = 0; /* just in case so the caller
+ does not go off the end of the buffer */
+ cFYI(1, ("readlink result - %s", symlinkinfo));
}
+
qreparse_out:
cifs_buf_release(pSMB);
return rc;
}
+#endif /* CIFS_EXPERIMENTAL */
#ifdef CONFIG_CIFS_POSIX
return rc;
}
-/* computes length of UCS string converted to host codepage
- * @src: UCS string
- * @maxlen: length of the input string in UCS characters
- * (not in bytes)
- *
- * return: size of input string in host codepage
- */
-static int hostlen_fromUCS(const __le16 *src, const int maxlen,
- const struct nls_table *nls_codepage) {
- int i;
- int hostlen = 0;
- char to[4];
- int charlen;
- for (i = 0; (i < maxlen) && src[i]; ++i) {
- charlen = nls_codepage->uni2char(le16_to_cpu(src[i]),
- to, NLS_MAX_CHARSET_SIZE);
- hostlen += charlen > 0 ? charlen : 1;
- }
- return hostlen;
-}
-
/* parses DFS refferal V3 structure
* caller is responsible for freeing target_nodes
* returns:
cFYI(1, ("num_referrals: %d dfs flags: 0x%x ... \n",
*num_of_nodes,
- le16_to_cpu(pSMBr->DFSFlags)));
+ le32_to_cpu(pSMBr->DFSFlags)));
*target_nodes = kzalloc(sizeof(struct dfs_info3_param) *
*num_of_nodes, GFP_KERNEL);
int max_len;
struct dfs_info3_param *node = (*target_nodes)+i;
- node->flags = le16_to_cpu(pSMBr->DFSFlags);
+ node->flags = le32_to_cpu(pSMBr->DFSFlags);
if (is_unicode) {
__le16 *tmp = kmalloc(strlen(searchName)*2 + 2,
GFP_KERNEL);
cifsConvertToUCS((__le16 *) tmp, searchName,
PATH_MAX, nls_codepage, remap);
- node->path_consumed = hostlen_fromUCS(tmp,
- le16_to_cpu(pSMBr->PathConsumed)/2,
+ node->path_consumed = cifs_ucs2_bytes(tmp,
+ le16_to_cpu(pSMBr->PathConsumed),
nls_codepage);
kfree(tmp);
} else
/* copy DfsPath */
temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset);
max_len = data_end - temp;
- rc = cifs_strncpy_to_host(&(node->path_name), temp,
- max_len, is_unicode, nls_codepage);
- if (rc)
+ node->path_name = cifs_strndup_from_ucs(temp, max_len,
+ is_unicode, nls_codepage);
+ if (IS_ERR(node->path_name)) {
+ rc = PTR_ERR(node->path_name);
+ node->path_name = NULL;
goto parse_DFS_referrals_exit;
+ }
/* copy link target UNC */
temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset);
max_len = data_end - temp;
- rc = cifs_strncpy_to_host(&(node->node_name), temp,
- max_len, is_unicode, nls_codepage);
- if (rc)
+ node->node_name = cifs_strndup_from_ucs(temp, max_len,
+ is_unicode, nls_codepage);
+ if (IS_ERR(node->node_name)) {
+ rc = PTR_ERR(node->node_name);
+ node->node_name = NULL;
goto parse_DFS_referrals_exit;
-
- ref += le16_to_cpu(ref->Size);
+ }
}
parse_DFS_referrals_exit:
/*
* fs/cifs/connect.c
*
- * Copyright (C) International Business Machines Corp., 2002,2008
+ * Copyright (C) International Business Machines Corp., 2002,2009
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
#include <linux/kthread.h>
#include <linux/pagevec.h>
#include <linux/freezer.h>
+#include <linux/namei.h>
#include <asm/uaccess.h>
#include <asm/processor.h>
#include <net/ipv6.h>
return 1;
} else if (strnicmp(value, "krb5", 4) == 0) {
vol->secFlg |= CIFSSEC_MAY_KRB5;
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ } else if (strnicmp(value, "ntlmsspi", 8) == 0) {
+ vol->secFlg |= CIFSSEC_MAY_NTLMSSP |
+ CIFSSEC_MUST_SIGN;
+ } else if (strnicmp(value, "ntlmssp", 7) == 0) {
+ vol->secFlg |= CIFSSEC_MAY_NTLMSSP;
+#endif
} else if (strnicmp(value, "ntlmv2i", 7) == 0) {
vol->secFlg |= CIFSSEC_MAY_NTLMV2 |
CIFSSEC_MUST_SIGN;
#ifdef CONFIG_CIFS_DFS_UPCALL
struct dfs_info3_param *referrals = NULL;
unsigned int num_referrals = 0;
+ int referral_walks_count = 0;
try_mount_again:
#endif
full_path = NULL;
/* get referral if needed */
if (rc == -EREMOTE) {
#ifdef CONFIG_CIFS_DFS_UPCALL
+ if (referral_walks_count > MAX_NESTED_LINKS) {
+ /*
+ * BB: when we implement proper loop detection,
+ * we will remove this check. But now we need it
+ * to prevent an indefinite loop if 'DFS tree' is
+ * misconfigured (i.e. has loops).
+ */
+ rc = -ELOOP;
+ goto mount_fail_check;
+ }
/* convert forward to back slashes in prepath here if needed */
if ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) == 0)
convert_delimiter(cifs_sb->prepath,
cleanup_volume_info(&volume_info);
FreeXid(xid);
kfree(full_path);
+ referral_walks_count++;
goto try_mount_again;
}
#else /* No DFS support, return error on mount */
return rc;
}
-static int
-CIFSSessSetup(unsigned int xid, struct cifsSesInfo *ses,
- char session_key[CIFS_SESS_KEY_SIZE],
- const struct nls_table *nls_codepage)
-{
- struct smb_hdr *smb_buffer;
- struct smb_hdr *smb_buffer_response;
- SESSION_SETUP_ANDX *pSMB;
- SESSION_SETUP_ANDX *pSMBr;
- char *bcc_ptr;
- char *user;
- char *domain;
- int rc = 0;
- int remaining_words = 0;
- int bytes_returned = 0;
- int len;
- __u32 capabilities;
- __u16 count;
-
- cFYI(1, ("In sesssetup"));
- if (ses == NULL)
- return -EINVAL;
- user = ses->userName;
- domain = ses->domainName;
- smb_buffer = cifs_buf_get();
-
- if (smb_buffer == NULL)
- return -ENOMEM;
-
- smb_buffer_response = smb_buffer;
- pSMBr = pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
-
- /* send SMBsessionSetup here */
- header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
- NULL /* no tCon exists yet */ , 13 /* wct */ );
-
- smb_buffer->Mid = GetNextMid(ses->server);
- pSMB->req_no_secext.AndXCommand = 0xFF;
- pSMB->req_no_secext.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
- pSMB->req_no_secext.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
-
- if (ses->server->secMode &
- (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
- CAP_LARGE_WRITE_X | CAP_LARGE_READ_X;
- if (ses->capabilities & CAP_UNICODE) {
- smb_buffer->Flags2 |= SMBFLG2_UNICODE;
- capabilities |= CAP_UNICODE;
- }
- if (ses->capabilities & CAP_STATUS32) {
- smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
- capabilities |= CAP_STATUS32;
- }
- if (ses->capabilities & CAP_DFS) {
- smb_buffer->Flags2 |= SMBFLG2_DFS;
- capabilities |= CAP_DFS;
- }
- pSMB->req_no_secext.Capabilities = cpu_to_le32(capabilities);
-
- pSMB->req_no_secext.CaseInsensitivePasswordLength =
- cpu_to_le16(CIFS_SESS_KEY_SIZE);
-
- pSMB->req_no_secext.CaseSensitivePasswordLength =
- cpu_to_le16(CIFS_SESS_KEY_SIZE);
- bcc_ptr = pByteArea(smb_buffer);
- memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
- bcc_ptr += CIFS_SESS_KEY_SIZE;
- memcpy(bcc_ptr, (char *) session_key, CIFS_SESS_KEY_SIZE);
- bcc_ptr += CIFS_SESS_KEY_SIZE;
-
- if (ses->capabilities & CAP_UNICODE) {
- if ((long) bcc_ptr % 2) { /* must be word aligned for Unicode */
- *bcc_ptr = 0;
- bcc_ptr++;
- }
- if (user == NULL)
- bytes_returned = 0; /* skip null user */
- else
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, user, 100,
- nls_codepage);
- /* convert number of 16 bit words to bytes */
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2; /* trailing null */
- if (domain == NULL)
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr,
- "CIFS_LINUX_DOM", 32, nls_codepage);
- else
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
- nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
- 32, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release,
- 32, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
- 64, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2;
- } else {
- if (user != NULL) {
- strncpy(bcc_ptr, user, 200);
- bcc_ptr += strnlen(user, 200);
- }
- *bcc_ptr = 0;
- bcc_ptr++;
- if (domain == NULL) {
- strcpy(bcc_ptr, "CIFS_LINUX_DOM");
- bcc_ptr += strlen("CIFS_LINUX_DOM") + 1;
- } else {
- strncpy(bcc_ptr, domain, 64);
- bcc_ptr += strnlen(domain, 64);
- *bcc_ptr = 0;
- bcc_ptr++;
- }
- strcpy(bcc_ptr, "Linux version ");
- bcc_ptr += strlen("Linux version ");
- strcpy(bcc_ptr, utsname()->release);
- bcc_ptr += strlen(utsname()->release) + 1;
- strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
- bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
- }
- count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
- smb_buffer->smb_buf_length += count;
- pSMB->req_no_secext.ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
- &bytes_returned, CIFS_LONG_OP);
- if (rc) {
-/* rc = map_smb_to_linux_error(smb_buffer_response); now done in SendReceive */
- } else if ((smb_buffer_response->WordCount == 3)
- || (smb_buffer_response->WordCount == 4)) {
- __u16 action = le16_to_cpu(pSMBr->resp.Action);
- __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
- if (action & GUEST_LOGIN)
- cFYI(1, ("Guest login")); /* BB mark SesInfo struct? */
- ses->Suid = smb_buffer_response->Uid; /* UID left in wire format
- (little endian) */
- cFYI(1, ("UID = %d ", ses->Suid));
- /* response can have either 3 or 4 word count - Samba sends 3 */
- bcc_ptr = pByteArea(smb_buffer_response);
- if ((pSMBr->resp.hdr.WordCount == 3)
- || ((pSMBr->resp.hdr.WordCount == 4)
- && (blob_len < pSMBr->resp.ByteCount))) {
- if (pSMBr->resp.hdr.WordCount == 4)
- bcc_ptr += blob_len;
-
- if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
- if ((long) (bcc_ptr) % 2) {
- remaining_words =
- (BCC(smb_buffer_response) - 1) / 2;
- /* Unicode strings must be word
- aligned */
- bcc_ptr++;
- } else {
- remaining_words =
- BCC(smb_buffer_response) / 2;
- }
- len =
- UniStrnlen((wchar_t *) bcc_ptr,
- remaining_words - 1);
-/* We look for obvious messed up bcc or strings in response so we do not go off
- the end since (at least) WIN2K and Windows XP have a major bug in not null
- terminating last Unicode string in response */
- kfree(ses->serverOS);
- ses->serverOS = kzalloc(2 * (len + 1),
- GFP_KERNEL);
- if (ses->serverOS == NULL)
- goto sesssetup_nomem;
- cifs_strfromUCS_le(ses->serverOS,
- (__le16 *)bcc_ptr,
- len, nls_codepage);
- bcc_ptr += 2 * (len + 1);
- remaining_words -= len + 1;
- ses->serverOS[2 * len] = 0;
- ses->serverOS[1 + (2 * len)] = 0;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *)bcc_ptr,
- remaining_words-1);
- kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(2 * (len + 1),
- GFP_KERNEL);
- if (ses->serverNOS == NULL)
- goto sesssetup_nomem;
- cifs_strfromUCS_le(ses->serverNOS,
- (__le16 *)bcc_ptr,
- len, nls_codepage);
- bcc_ptr += 2 * (len + 1);
- ses->serverNOS[2 * len] = 0;
- ses->serverNOS[1 + (2 * len)] = 0;
- if (strncmp(ses->serverNOS,
- "NT LAN Manager 4", 16) == 0) {
- cFYI(1, ("NT4 server"));
- ses->flags |= CIFS_SES_NT4;
- }
- remaining_words -= len + 1;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
- /* last string is not always null terminated
- (for e.g. for Windows XP & 2000) */
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2*(len+1),
- GFP_KERNEL);
- if (ses->serverDomain == NULL)
- goto sesssetup_nomem;
- cifs_strfromUCS_le(ses->serverDomain,
- (__le16 *)bcc_ptr,
- len, nls_codepage);
- bcc_ptr += 2 * (len + 1);
- ses->serverDomain[2*len] = 0;
- ses->serverDomain[1+(2*len)] = 0;
- } else { /* else no more room so create
- dummy domain string */
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2, GFP_KERNEL);
- }
- } else { /* no room so create dummy domain
- and NOS string */
-
- /* if these kcallocs fail not much we
- can do, but better to not fail the
- sesssetup itself */
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2, GFP_KERNEL);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(2, GFP_KERNEL);
- }
- } else { /* ASCII */
- len = strnlen(bcc_ptr, 1024);
- if (((long) bcc_ptr + len) - (long)
- pByteArea(smb_buffer_response)
- <= BCC(smb_buffer_response)) {
- kfree(ses->serverOS);
- ses->serverOS = kzalloc(len + 1,
- GFP_KERNEL);
- if (ses->serverOS == NULL)
- goto sesssetup_nomem;
- strncpy(ses->serverOS, bcc_ptr, len);
-
- bcc_ptr += len;
- /* null terminate the string */
- bcc_ptr[0] = 0;
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(len + 1,
- GFP_KERNEL);
- if (ses->serverNOS == NULL)
- goto sesssetup_nomem;
- strncpy(ses->serverNOS, bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverDomain);
- ses->serverDomain = kzalloc(len + 1,
- GFP_KERNEL);
- if (ses->serverDomain == NULL)
- goto sesssetup_nomem;
- strncpy(ses->serverDomain, bcc_ptr,
- len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
- } else
- cFYI(1,
- ("Variable field of length %d "
- "extends beyond end of smb ",
- len));
- }
- } else {
- cERROR(1, ("Security Blob Length extends beyond "
- "end of SMB"));
- }
- } else {
- cERROR(1, ("Invalid Word count %d: ",
- smb_buffer_response->WordCount));
- rc = -EIO;
- }
-sesssetup_nomem: /* do not return an error on nomem for the info strings,
- since that could make reconnection harder, and
- reconnection might be needed to free memory */
- cifs_buf_release(smb_buffer);
-
- return rc;
-}
-
-static int
-CIFSNTLMSSPNegotiateSessSetup(unsigned int xid,
- struct cifsSesInfo *ses, bool *pNTLMv2_flag,
- const struct nls_table *nls_codepage)
-{
- struct smb_hdr *smb_buffer;
- struct smb_hdr *smb_buffer_response;
- SESSION_SETUP_ANDX *pSMB;
- SESSION_SETUP_ANDX *pSMBr;
- char *bcc_ptr;
- char *domain;
- int rc = 0;
- int remaining_words = 0;
- int bytes_returned = 0;
- int len;
- int SecurityBlobLength = sizeof(NEGOTIATE_MESSAGE);
- PNEGOTIATE_MESSAGE SecurityBlob;
- PCHALLENGE_MESSAGE SecurityBlob2;
- __u32 negotiate_flags, capabilities;
- __u16 count;
-
- cFYI(1, ("In NTLMSSP sesssetup (negotiate)"));
- if (ses == NULL)
- return -EINVAL;
- domain = ses->domainName;
- *pNTLMv2_flag = false;
- smb_buffer = cifs_buf_get();
- if (smb_buffer == NULL) {
- return -ENOMEM;
- }
- smb_buffer_response = smb_buffer;
- pSMB = (SESSION_SETUP_ANDX *) smb_buffer;
- pSMBr = (SESSION_SETUP_ANDX *) smb_buffer_response;
-
- /* send SMBsessionSetup here */
- header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
- NULL /* no tCon exists yet */ , 12 /* wct */ );
-
- smb_buffer->Mid = GetNextMid(ses->server);
- pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
- pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
-
- pSMB->req.AndXCommand = 0xFF;
- pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
- pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
-
- if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
- CAP_EXTENDED_SECURITY;
- if (ses->capabilities & CAP_UNICODE) {
- smb_buffer->Flags2 |= SMBFLG2_UNICODE;
- capabilities |= CAP_UNICODE;
- }
- if (ses->capabilities & CAP_STATUS32) {
- smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
- capabilities |= CAP_STATUS32;
- }
- if (ses->capabilities & CAP_DFS) {
- smb_buffer->Flags2 |= SMBFLG2_DFS;
- capabilities |= CAP_DFS;
- }
- pSMB->req.Capabilities = cpu_to_le32(capabilities);
-
- bcc_ptr = (char *) &pSMB->req.SecurityBlob;
- SecurityBlob = (PNEGOTIATE_MESSAGE) bcc_ptr;
- strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
- SecurityBlob->MessageType = NtLmNegotiate;
- negotiate_flags =
- NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_NEGOTIATE_OEM |
- NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_NTLM |
- NTLMSSP_NEGOTIATE_56 |
- /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN | */ NTLMSSP_NEGOTIATE_128;
- if (sign_CIFS_PDUs)
- negotiate_flags |= NTLMSSP_NEGOTIATE_SIGN;
-/* if (ntlmv2_support)
- negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;*/
- /* setup pointers to domain name and workstation name */
- bcc_ptr += SecurityBlobLength;
-
- SecurityBlob->WorkstationName.Buffer = 0;
- SecurityBlob->WorkstationName.Length = 0;
- SecurityBlob->WorkstationName.MaximumLength = 0;
-
- /* Domain not sent on first Sesssetup in NTLMSSP, instead it is sent
- along with username on auth request (ie the response to challenge) */
- SecurityBlob->DomainName.Buffer = 0;
- SecurityBlob->DomainName.Length = 0;
- SecurityBlob->DomainName.MaximumLength = 0;
- if (ses->capabilities & CAP_UNICODE) {
- if ((long) bcc_ptr % 2) {
- *bcc_ptr = 0;
- bcc_ptr++;
- }
-
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
- 32, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
- nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2; /* null terminate Linux version */
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
- 64, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- *(bcc_ptr + 1) = 0;
- *(bcc_ptr + 2) = 0;
- bcc_ptr += 2; /* null terminate network opsys string */
- *(bcc_ptr + 1) = 0;
- *(bcc_ptr + 2) = 0;
- bcc_ptr += 2; /* null domain */
- } else { /* ASCII */
- strcpy(bcc_ptr, "Linux version ");
- bcc_ptr += strlen("Linux version ");
- strcpy(bcc_ptr, utsname()->release);
- bcc_ptr += strlen(utsname()->release) + 1;
- strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
- bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
- bcc_ptr++; /* empty domain field */
- *bcc_ptr = 0;
- }
- SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
- pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
- count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
- smb_buffer->smb_buf_length += count;
- pSMB->req.ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
- &bytes_returned, CIFS_LONG_OP);
-
- if (smb_buffer_response->Status.CifsError ==
- cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))
- rc = 0;
-
- if (rc) {
-/* rc = map_smb_to_linux_error(smb_buffer_response); *//* done in SendReceive now */
- } else if ((smb_buffer_response->WordCount == 3)
- || (smb_buffer_response->WordCount == 4)) {
- __u16 action = le16_to_cpu(pSMBr->resp.Action);
- __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
-
- if (action & GUEST_LOGIN)
- cFYI(1, ("Guest login"));
- /* Do we want to set anything in SesInfo struct when guest login? */
-
- bcc_ptr = pByteArea(smb_buffer_response);
- /* response can have either 3 or 4 word count - Samba sends 3 */
-
- SecurityBlob2 = (PCHALLENGE_MESSAGE) bcc_ptr;
- if (SecurityBlob2->MessageType != NtLmChallenge) {
- cFYI(1, ("Unexpected NTLMSSP message type received %d",
- SecurityBlob2->MessageType));
- } else if (ses) {
- ses->Suid = smb_buffer_response->Uid; /* UID left in le format */
- cFYI(1, ("UID = %d", ses->Suid));
- if ((pSMBr->resp.hdr.WordCount == 3)
- || ((pSMBr->resp.hdr.WordCount == 4)
- && (blob_len <
- pSMBr->resp.ByteCount))) {
-
- if (pSMBr->resp.hdr.WordCount == 4) {
- bcc_ptr += blob_len;
- cFYI(1, ("Security Blob Length %d",
- blob_len));
- }
-
- cFYI(1, ("NTLMSSP Challenge rcvd"));
-
- memcpy(ses->server->cryptKey,
- SecurityBlob2->Challenge,
- CIFS_CRYPTO_KEY_SIZE);
- if (SecurityBlob2->NegotiateFlags &
- cpu_to_le32(NTLMSSP_NEGOTIATE_NTLMV2))
- *pNTLMv2_flag = true;
-
- if ((SecurityBlob2->NegotiateFlags &
- cpu_to_le32(NTLMSSP_NEGOTIATE_ALWAYS_SIGN))
- || (sign_CIFS_PDUs > 1))
- ses->server->secMode |=
- SECMODE_SIGN_REQUIRED;
- if ((SecurityBlob2->NegotiateFlags &
- cpu_to_le32(NTLMSSP_NEGOTIATE_SIGN)) && (sign_CIFS_PDUs))
- ses->server->secMode |=
- SECMODE_SIGN_ENABLED;
-
- if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
- if ((long) (bcc_ptr) % 2) {
- remaining_words =
- (BCC(smb_buffer_response)
- - 1) / 2;
- /* Must word align unicode strings */
- bcc_ptr++;
- } else {
- remaining_words =
- BCC
- (smb_buffer_response) / 2;
- }
- len =
- UniStrnlen((wchar_t *) bcc_ptr,
- remaining_words - 1);
-/* We look for obvious messed up bcc or strings in response so we do not go off
- the end since (at least) WIN2K and Windows XP have a major bug in not null
- terminating last Unicode string in response */
- kfree(ses->serverOS);
- ses->serverOS =
- kzalloc(2 * (len + 1), GFP_KERNEL);
- cifs_strfromUCS_le(ses->serverOS,
- (__le16 *)
- bcc_ptr, len,
- nls_codepage);
- bcc_ptr += 2 * (len + 1);
- remaining_words -= len + 1;
- ses->serverOS[2 * len] = 0;
- ses->serverOS[1 + (2 * len)] = 0;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *)
- bcc_ptr,
- remaining_words
- - 1);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(2 * (len + 1),
- GFP_KERNEL);
- cifs_strfromUCS_le(ses->
- serverNOS,
- (__le16 *)
- bcc_ptr,
- len,
- nls_codepage);
- bcc_ptr += 2 * (len + 1);
- ses->serverNOS[2 * len] = 0;
- ses->serverNOS[1 +
- (2 * len)] = 0;
- remaining_words -= len + 1;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
- /* last string not always null terminated
- (for e.g. for Windows XP & 2000) */
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2 *
- (len +
- 1),
- GFP_KERNEL);
- cifs_strfromUCS_le
- (ses->serverDomain,
- (__le16 *)bcc_ptr,
- len, nls_codepage);
- bcc_ptr +=
- 2 * (len + 1);
- ses->serverDomain[2*len]
- = 0;
- ses->serverDomain
- [1 + (2 * len)]
- = 0;
- } /* else no more room so create dummy domain string */
- else {
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2,
- GFP_KERNEL);
- }
- } else { /* no room so create dummy domain and NOS string */
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2, GFP_KERNEL);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(2, GFP_KERNEL);
- }
- } else { /* ASCII */
- len = strnlen(bcc_ptr, 1024);
- if (((long) bcc_ptr + len) - (long)
- pByteArea(smb_buffer_response)
- <= BCC(smb_buffer_response)) {
- kfree(ses->serverOS);
- ses->serverOS =
- kzalloc(len + 1,
- GFP_KERNEL);
- strncpy(ses->serverOS,
- bcc_ptr, len);
-
- bcc_ptr += len;
- bcc_ptr[0] = 0; /* null terminate string */
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(len + 1,
- GFP_KERNEL);
- strncpy(ses->serverNOS, bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(len + 1,
- GFP_KERNEL);
- strncpy(ses->serverDomain,
- bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
- } else
- cFYI(1,
- ("field of length %d "
- "extends beyond end of smb",
- len));
- }
- } else {
- cERROR(1, ("Security Blob Length extends beyond"
- " end of SMB"));
- }
- } else {
- cERROR(1, ("No session structure passed in."));
- }
- } else {
- cERROR(1, ("Invalid Word count %d:",
- smb_buffer_response->WordCount));
- rc = -EIO;
- }
-
- cifs_buf_release(smb_buffer);
-
- return rc;
-}
-static int
-CIFSNTLMSSPAuthSessSetup(unsigned int xid, struct cifsSesInfo *ses,
- char *ntlm_session_key, bool ntlmv2_flag,
- const struct nls_table *nls_codepage)
-{
- struct smb_hdr *smb_buffer;
- struct smb_hdr *smb_buffer_response;
- SESSION_SETUP_ANDX *pSMB;
- SESSION_SETUP_ANDX *pSMBr;
- char *bcc_ptr;
- char *user;
- char *domain;
- int rc = 0;
- int remaining_words = 0;
- int bytes_returned = 0;
- int len;
- int SecurityBlobLength = sizeof(AUTHENTICATE_MESSAGE);
- PAUTHENTICATE_MESSAGE SecurityBlob;
- __u32 negotiate_flags, capabilities;
- __u16 count;
-
- cFYI(1, ("In NTLMSSPSessSetup (Authenticate)"));
- if (ses == NULL)
- return -EINVAL;
- user = ses->userName;
- domain = ses->domainName;
- smb_buffer = cifs_buf_get();
- if (smb_buffer == NULL) {
- return -ENOMEM;
- }
- smb_buffer_response = smb_buffer;
- pSMB = (SESSION_SETUP_ANDX *)smb_buffer;
- pSMBr = (SESSION_SETUP_ANDX *)smb_buffer_response;
-
- /* send SMBsessionSetup here */
- header_assemble(smb_buffer, SMB_COM_SESSION_SETUP_ANDX,
- NULL /* no tCon exists yet */ , 12 /* wct */ );
-
- smb_buffer->Mid = GetNextMid(ses->server);
- pSMB->req.hdr.Flags |= (SMBFLG_CASELESS | SMBFLG_CANONICAL_PATH_FORMAT);
- pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
- pSMB->req.AndXCommand = 0xFF;
- pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf);
- pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq);
-
- pSMB->req.hdr.Uid = ses->Suid;
-
- if (ses->server->secMode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
- smb_buffer->Flags2 |= SMBFLG2_SECURITY_SIGNATURE;
-
- capabilities = CAP_LARGE_FILES | CAP_NT_SMBS | CAP_LEVEL_II_OPLOCKS |
- CAP_EXTENDED_SECURITY;
- if (ses->capabilities & CAP_UNICODE) {
- smb_buffer->Flags2 |= SMBFLG2_UNICODE;
- capabilities |= CAP_UNICODE;
- }
- if (ses->capabilities & CAP_STATUS32) {
- smb_buffer->Flags2 |= SMBFLG2_ERR_STATUS;
- capabilities |= CAP_STATUS32;
- }
- if (ses->capabilities & CAP_DFS) {
- smb_buffer->Flags2 |= SMBFLG2_DFS;
- capabilities |= CAP_DFS;
- }
- pSMB->req.Capabilities = cpu_to_le32(capabilities);
-
- bcc_ptr = (char *)&pSMB->req.SecurityBlob;
- SecurityBlob = (PAUTHENTICATE_MESSAGE)bcc_ptr;
- strncpy(SecurityBlob->Signature, NTLMSSP_SIGNATURE, 8);
- SecurityBlob->MessageType = NtLmAuthenticate;
- bcc_ptr += SecurityBlobLength;
- negotiate_flags = NTLMSSP_NEGOTIATE_UNICODE | NTLMSSP_REQUEST_TARGET |
- NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_TARGET_INFO |
- 0x80000000 | NTLMSSP_NEGOTIATE_128;
- if (sign_CIFS_PDUs)
- negotiate_flags |= /* NTLMSSP_NEGOTIATE_ALWAYS_SIGN |*/ NTLMSSP_NEGOTIATE_SIGN;
- if (ntlmv2_flag)
- negotiate_flags |= NTLMSSP_NEGOTIATE_NTLMV2;
-
-/* setup pointers to domain name and workstation name */
-
- SecurityBlob->WorkstationName.Buffer = 0;
- SecurityBlob->WorkstationName.Length = 0;
- SecurityBlob->WorkstationName.MaximumLength = 0;
- SecurityBlob->SessionKey.Length = 0;
- SecurityBlob->SessionKey.MaximumLength = 0;
- SecurityBlob->SessionKey.Buffer = 0;
-
- SecurityBlob->LmChallengeResponse.Length = 0;
- SecurityBlob->LmChallengeResponse.MaximumLength = 0;
- SecurityBlob->LmChallengeResponse.Buffer = 0;
-
- SecurityBlob->NtChallengeResponse.Length =
- cpu_to_le16(CIFS_SESS_KEY_SIZE);
- SecurityBlob->NtChallengeResponse.MaximumLength =
- cpu_to_le16(CIFS_SESS_KEY_SIZE);
- memcpy(bcc_ptr, ntlm_session_key, CIFS_SESS_KEY_SIZE);
- SecurityBlob->NtChallengeResponse.Buffer =
- cpu_to_le32(SecurityBlobLength);
- SecurityBlobLength += CIFS_SESS_KEY_SIZE;
- bcc_ptr += CIFS_SESS_KEY_SIZE;
-
- if (ses->capabilities & CAP_UNICODE) {
- if (domain == NULL) {
- SecurityBlob->DomainName.Buffer = 0;
- SecurityBlob->DomainName.Length = 0;
- SecurityBlob->DomainName.MaximumLength = 0;
- } else {
- __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, domain, 64,
- nls_codepage);
- ln *= 2;
- SecurityBlob->DomainName.MaximumLength =
- cpu_to_le16(ln);
- SecurityBlob->DomainName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- bcc_ptr += ln;
- SecurityBlobLength += ln;
- SecurityBlob->DomainName.Length = cpu_to_le16(ln);
- }
- if (user == NULL) {
- SecurityBlob->UserName.Buffer = 0;
- SecurityBlob->UserName.Length = 0;
- SecurityBlob->UserName.MaximumLength = 0;
- } else {
- __u16 ln = cifs_strtoUCS((__le16 *) bcc_ptr, user, 64,
- nls_codepage);
- ln *= 2;
- SecurityBlob->UserName.MaximumLength =
- cpu_to_le16(ln);
- SecurityBlob->UserName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- bcc_ptr += ln;
- SecurityBlobLength += ln;
- SecurityBlob->UserName.Length = cpu_to_le16(ln);
- }
-
- /* SecurityBlob->WorkstationName.Length =
- cifs_strtoUCS((__le16 *) bcc_ptr, "AMACHINE",64, nls_codepage);
- SecurityBlob->WorkstationName.Length *= 2;
- SecurityBlob->WorkstationName.MaximumLength =
- cpu_to_le16(SecurityBlob->WorkstationName.Length);
- SecurityBlob->WorkstationName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- bcc_ptr += SecurityBlob->WorkstationName.Length;
- SecurityBlobLength += SecurityBlob->WorkstationName.Length;
- SecurityBlob->WorkstationName.Length =
- cpu_to_le16(SecurityBlob->WorkstationName.Length); */
-
- if ((long) bcc_ptr % 2) {
- *bcc_ptr = 0;
- bcc_ptr++;
- }
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, "Linux version ",
- 32, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, utsname()->release, 32,
- nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- bcc_ptr += 2; /* null term version string */
- bytes_returned =
- cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS,
- 64, nls_codepage);
- bcc_ptr += 2 * bytes_returned;
- *(bcc_ptr + 1) = 0;
- *(bcc_ptr + 2) = 0;
- bcc_ptr += 2; /* null terminate network opsys string */
- *(bcc_ptr + 1) = 0;
- *(bcc_ptr + 2) = 0;
- bcc_ptr += 2; /* null domain */
- } else { /* ASCII */
- if (domain == NULL) {
- SecurityBlob->DomainName.Buffer = 0;
- SecurityBlob->DomainName.Length = 0;
- SecurityBlob->DomainName.MaximumLength = 0;
- } else {
- __u16 ln;
- negotiate_flags |= NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED;
- strncpy(bcc_ptr, domain, 63);
- ln = strnlen(domain, 64);
- SecurityBlob->DomainName.MaximumLength =
- cpu_to_le16(ln);
- SecurityBlob->DomainName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- bcc_ptr += ln;
- SecurityBlobLength += ln;
- SecurityBlob->DomainName.Length = cpu_to_le16(ln);
- }
- if (user == NULL) {
- SecurityBlob->UserName.Buffer = 0;
- SecurityBlob->UserName.Length = 0;
- SecurityBlob->UserName.MaximumLength = 0;
- } else {
- __u16 ln;
- strncpy(bcc_ptr, user, 63);
- ln = strnlen(user, 64);
- SecurityBlob->UserName.MaximumLength = cpu_to_le16(ln);
- SecurityBlob->UserName.Buffer =
- cpu_to_le32(SecurityBlobLength);
- bcc_ptr += ln;
- SecurityBlobLength += ln;
- SecurityBlob->UserName.Length = cpu_to_le16(ln);
- }
- /* BB fill in our workstation name if known BB */
-
- strcpy(bcc_ptr, "Linux version ");
- bcc_ptr += strlen("Linux version ");
- strcpy(bcc_ptr, utsname()->release);
- bcc_ptr += strlen(utsname()->release) + 1;
- strcpy(bcc_ptr, CIFS_NETWORK_OPSYS);
- bcc_ptr += strlen(CIFS_NETWORK_OPSYS) + 1;
- bcc_ptr++; /* null domain */
- *bcc_ptr = 0;
- }
- SecurityBlob->NegotiateFlags = cpu_to_le32(negotiate_flags);
- pSMB->req.SecurityBlobLength = cpu_to_le16(SecurityBlobLength);
- count = (long) bcc_ptr - (long) pByteArea(smb_buffer);
- smb_buffer->smb_buf_length += count;
- pSMB->req.ByteCount = cpu_to_le16(count);
-
- rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response,
- &bytes_returned, CIFS_LONG_OP);
- if (rc) {
-/* rc = map_smb_to_linux_error(smb_buffer_response) done in SendReceive now */
- } else if ((smb_buffer_response->WordCount == 3) ||
- (smb_buffer_response->WordCount == 4)) {
- __u16 action = le16_to_cpu(pSMBr->resp.Action);
- __u16 blob_len = le16_to_cpu(pSMBr->resp.SecurityBlobLength);
- if (action & GUEST_LOGIN)
- cFYI(1, ("Guest login")); /* BB Should we set anything
- in SesInfo struct ? */
-/* if (SecurityBlob2->MessageType != NtLm??) {
- cFYI("Unexpected message type on auth response is %d"));
- } */
-
- if (ses) {
- cFYI(1,
- ("Check challenge UID %d vs auth response UID %d",
- ses->Suid, smb_buffer_response->Uid));
- /* UID left in wire format */
- ses->Suid = smb_buffer_response->Uid;
- bcc_ptr = pByteArea(smb_buffer_response);
- /* response can have either 3 or 4 word count - Samba sends 3 */
- if ((pSMBr->resp.hdr.WordCount == 3)
- || ((pSMBr->resp.hdr.WordCount == 4)
- && (blob_len <
- pSMBr->resp.ByteCount))) {
- if (pSMBr->resp.hdr.WordCount == 4) {
- bcc_ptr +=
- blob_len;
- cFYI(1,
- ("Security Blob Length %d ",
- blob_len));
- }
-
- cFYI(1,
- ("NTLMSSP response to Authenticate "));
-
- if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
- if ((long) (bcc_ptr) % 2) {
- remaining_words =
- (BCC(smb_buffer_response)
- - 1) / 2;
- bcc_ptr++; /* Unicode strings must be word aligned */
- } else {
- remaining_words = BCC(smb_buffer_response) / 2;
- }
- len = UniStrnlen((wchar_t *) bcc_ptr,
- remaining_words - 1);
-/* We look for obvious messed up bcc or strings in response so we do not go off
- the end since (at least) WIN2K and Windows XP have a major bug in not null
- terminating last Unicode string in response */
- kfree(ses->serverOS);
- ses->serverOS =
- kzalloc(2 * (len + 1), GFP_KERNEL);
- cifs_strfromUCS_le(ses->serverOS,
- (__le16 *)
- bcc_ptr, len,
- nls_codepage);
- bcc_ptr += 2 * (len + 1);
- remaining_words -= len + 1;
- ses->serverOS[2 * len] = 0;
- ses->serverOS[1 + (2 * len)] = 0;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *)
- bcc_ptr,
- remaining_words
- - 1);
- kfree(ses->serverNOS);
- ses->serverNOS =
- kzalloc(2 * (len + 1),
- GFP_KERNEL);
- cifs_strfromUCS_le(ses->
- serverNOS,
- (__le16 *)
- bcc_ptr,
- len,
- nls_codepage);
- bcc_ptr += 2 * (len + 1);
- ses->serverNOS[2 * len] = 0;
- ses->serverNOS[1+(2*len)] = 0;
- remaining_words -= len + 1;
- if (remaining_words > 0) {
- len = UniStrnlen((wchar_t *) bcc_ptr, remaining_words);
- /* last string not always null terminated (e.g. for Windows XP & 2000) */
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(2 *
- (len +
- 1),
- GFP_KERNEL);
- cifs_strfromUCS_le
- (ses->
- serverDomain,
- (__le16 *)
- bcc_ptr, len,
- nls_codepage);
- bcc_ptr +=
- 2 * (len + 1);
- ses->
- serverDomain[2
- * len]
- = 0;
- ses->
- serverDomain[1
- +
- (2
- *
- len)]
- = 0;
- } /* else no more room so create dummy domain string */
- else {
- kfree(ses->serverDomain);
- ses->serverDomain = kzalloc(2,GFP_KERNEL);
- }
- } else { /* no room so create dummy domain and NOS string */
- kfree(ses->serverDomain);
- ses->serverDomain = kzalloc(2, GFP_KERNEL);
- kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(2, GFP_KERNEL);
- }
- } else { /* ASCII */
- len = strnlen(bcc_ptr, 1024);
- if (((long) bcc_ptr + len) -
- (long) pByteArea(smb_buffer_response)
- <= BCC(smb_buffer_response)) {
- kfree(ses->serverOS);
- ses->serverOS = kzalloc(len + 1, GFP_KERNEL);
- strncpy(ses->serverOS,bcc_ptr, len);
-
- bcc_ptr += len;
- bcc_ptr[0] = 0; /* null terminate the string */
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverNOS);
- ses->serverNOS = kzalloc(len+1,
- GFP_KERNEL);
- strncpy(ses->serverNOS,
- bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
-
- len = strnlen(bcc_ptr, 1024);
- kfree(ses->serverDomain);
- ses->serverDomain =
- kzalloc(len+1,
- GFP_KERNEL);
- strncpy(ses->serverDomain,
- bcc_ptr, len);
- bcc_ptr += len;
- bcc_ptr[0] = 0;
- bcc_ptr++;
- } else
- cFYI(1, ("field of length %d "
- "extends beyond end of smb ",
- len));
- }
- } else {
- cERROR(1, ("Security Blob extends beyond end "
- "of SMB"));
- }
- } else {
- cERROR(1, ("No session structure passed in."));
- }
- } else {
- cERROR(1, ("Invalid Word count %d: ",
- smb_buffer_response->WordCount));
- rc = -EIO;
- }
-
- cifs_buf_release(smb_buffer);
-
- return rc;
-}
-
int
CIFSTCon(unsigned int xid, struct cifsSesInfo *ses,
const char *tree, struct cifsTconInfo *tcon,
TCONX_RSP *pSMBr;
unsigned char *bcc_ptr;
int rc = 0;
- int length;
+ int length, bytes_left;
__u16 count;
if (ses == NULL)
rc = SendReceive(xid, ses, smb_buffer, smb_buffer_response, &length,
CIFS_STD_OP);
- /* if (rc) rc = map_smb_to_linux_error(smb_buffer_response); */
/* above now done in SendReceive */
if ((rc == 0) && (tcon != NULL)) {
+ bool is_unicode;
+
tcon->tidStatus = CifsGood;
tcon->need_reconnect = false;
tcon->tid = smb_buffer_response->Tid;
bcc_ptr = pByteArea(smb_buffer_response);
- length = strnlen(bcc_ptr, BCC(smb_buffer_response) - 2);
+ bytes_left = BCC(smb_buffer_response);
+ length = strnlen(bcc_ptr, bytes_left - 2);
+ if (smb_buffer->Flags2 & SMBFLG2_UNICODE)
+ is_unicode = true;
+ else
+ is_unicode = false;
+
+
/* skip service field (NB: this field is always ASCII) */
if (length == 3) {
if ((bcc_ptr[0] == 'I') && (bcc_ptr[1] == 'P') &&
}
}
bcc_ptr += length + 1;
+ bytes_left -= (length + 1);
strncpy(tcon->treeName, tree, MAX_TREE_SIZE);
- if (smb_buffer->Flags2 & SMBFLG2_UNICODE) {
- length = UniStrnlen((wchar_t *) bcc_ptr, 512);
- if ((bcc_ptr + (2 * length)) -
- pByteArea(smb_buffer_response) <=
- BCC(smb_buffer_response)) {
- kfree(tcon->nativeFileSystem);
- tcon->nativeFileSystem =
- kzalloc((4 * length) + 2, GFP_KERNEL);
- if (tcon->nativeFileSystem) {
- cifs_strfromUCS_le(
- tcon->nativeFileSystem,
- (__le16 *) bcc_ptr,
- length, nls_codepage);
- cFYI(1, ("nativeFileSystem=%s",
- tcon->nativeFileSystem));
- }
- }
- /* else do not bother copying these information fields*/
- } else {
- length = strnlen(bcc_ptr, 1024);
- if ((bcc_ptr + length) -
- pByteArea(smb_buffer_response) <=
- BCC(smb_buffer_response)) {
- kfree(tcon->nativeFileSystem);
- tcon->nativeFileSystem =
- kzalloc(length + 1, GFP_KERNEL);
- if (tcon->nativeFileSystem)
- strncpy(tcon->nativeFileSystem, bcc_ptr,
- length);
- }
- /* else do not bother copying these information fields*/
- }
+
+ /* mostly informational -- no need to fail on error here */
+ tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr,
+ bytes_left, is_unicode,
+ nls_codepage);
+
+ cFYI(1, ("nativeFileSystem=%s", tcon->nativeFileSystem));
+
if ((smb_buffer_response->WordCount == 3) ||
(smb_buffer_response->WordCount == 7))
/* field is in same location */
struct nls_table *nls_info)
{
int rc = 0;
- char ntlm_session_key[CIFS_SESS_KEY_SIZE];
- bool ntlmv2_flag = false;
int first_time = 0;
struct TCP_Server_Info *server = pSesInfo->server;
pSesInfo->capabilities = server->capabilities;
if (linuxExtEnabled == 0)
pSesInfo->capabilities &= (~CAP_UNIX);
- /* pSesInfo->sequence_number = 0;*/
+
cFYI(1, ("Security Mode: 0x%x Capabilities: 0x%x TimeAdjust: %d",
server->secMode, server->capabilities, server->timeAdj));
- if (experimEnabled < 2)
- rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
- else if (extended_security
- && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
- && (server->secType == NTLMSSP)) {
- rc = -EOPNOTSUPP;
- } else if (extended_security
- && (pSesInfo->capabilities & CAP_EXTENDED_SECURITY)
- && (server->secType == RawNTLMSSP)) {
- cFYI(1, ("NTLMSSP sesssetup"));
- rc = CIFSNTLMSSPNegotiateSessSetup(xid, pSesInfo, &ntlmv2_flag,
- nls_info);
- if (!rc) {
- if (ntlmv2_flag) {
- char *v2_response;
- cFYI(1, ("more secure NTLM ver2 hash"));
- if (CalcNTLMv2_partial_mac_key(pSesInfo,
- nls_info)) {
- rc = -ENOMEM;
- goto ss_err_exit;
- } else
- v2_response = kmalloc(16 + 64 /* blob*/,
- GFP_KERNEL);
- if (v2_response) {
- CalcNTLMv2_response(pSesInfo,
- v2_response);
- /* if (first_time)
- cifs_calculate_ntlmv2_mac_key */
- kfree(v2_response);
- /* BB Put dummy sig in SessSetup PDU? */
- } else {
- rc = -ENOMEM;
- goto ss_err_exit;
- }
-
- } else {
- SMBNTencrypt(pSesInfo->password,
- server->cryptKey,
- ntlm_session_key);
-
- if (first_time)
- cifs_calculate_mac_key(
- &server->mac_signing_key,
- ntlm_session_key,
- pSesInfo->password);
- }
- /* for better security the weaker lanman hash not sent
- in AuthSessSetup so we no longer calculate it */
-
- rc = CIFSNTLMSSPAuthSessSetup(xid, pSesInfo,
- ntlm_session_key,
- ntlmv2_flag,
- nls_info);
- }
- } else { /* old style NTLM 0.12 session setup */
- SMBNTencrypt(pSesInfo->password, server->cryptKey,
- ntlm_session_key);
-
- if (first_time)
- cifs_calculate_mac_key(&server->mac_signing_key,
- ntlm_session_key,
- pSesInfo->password);
-
- rc = CIFSSessSetup(xid, pSesInfo, ntlm_session_key, nls_info);
- }
+ rc = CIFS_SessSetup(xid, pSesInfo, first_time, nls_info);
if (rc) {
cERROR(1, ("Send error in SessSetup = %d", rc));
} else {
cFYI(1, ("CIFS Session Established successfully"));
- spin_lock(&GlobalMid_Lock);
- pSesInfo->status = CifsGood;
- pSesInfo->need_reconnect = false;
- spin_unlock(&GlobalMid_Lock);
+ spin_lock(&GlobalMid_Lock);
+ pSesInfo->status = CifsGood;
+ pSesInfo->need_reconnect = false;
+ spin_unlock(&GlobalMid_Lock);
}
ss_err_exit:
int create_options = CREATE_NOT_DIR;
int oplock = 0;
int oflags;
+ bool posix_create = false;
/*
* BB below access is probably too much for mknod to request
* but we have to do query and setpathinfo so requesting
negotation. EREMOTE indicates DFS junction, which is not
handled in posix open */
- if ((rc == 0) && (newinode == NULL))
- goto cifs_create_get_file_info; /* query inode info */
- else if (rc == 0) /* success, no need to query */
- goto cifs_create_set_dentry;
- else if ((rc != -EIO) && (rc != -EREMOTE) &&
+ if (rc == 0) {
+ posix_create = true;
+ if (newinode == NULL) /* query inode info */
+ goto cifs_create_get_file_info;
+ else /* success, no need to query */
+ goto cifs_create_set_dentry;
+ } else if ((rc != -EIO) && (rc != -EREMOTE) &&
(rc != -EOPNOTSUPP)) /* path not found or net err */
goto cifs_create_out;
/* else fallthrough to retry, using older open call, this is
if ((nd == NULL) || (!(nd->flags & LOOKUP_OPEN))) {
/* mknod case - do not leave file open */
CIFSSMBClose(xid, tcon, fileHandle);
- } else if (newinode) {
+ } else if (!(posix_create) && (newinode)) {
cifs_fill_fileinfo(newinode, fileHandle,
cifs_sb->tcon, write_only);
}
struct file *file, struct cifsInodeInfo *pCifsInode,
struct cifsFileInfo *pCifsFile, int oplock, u16 netfid)
{
- struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-/* struct timespec temp; */ /* BB REMOVEME BB */
file->private_data = kmalloc(sizeof(struct cifsFileInfo), GFP_KERNEL);
if (file->private_data == NULL)
return -ENOMEM;
pCifsFile = cifs_init_private(file->private_data, inode, file, netfid);
write_lock(&GlobalSMBSeslock);
- list_add(&pCifsFile->tlist, &cifs_sb->tcon->openFileList);
pCifsInode = CIFS_I(file->f_path.dentry->d_inode);
if (pCifsInode == NULL) {
return -EINVAL;
}
- /* want handles we can use to read with first
- in the list so we do not have to walk the
- list to search for one in write_begin */
- if ((file->f_flags & O_ACCMODE) == O_WRONLY) {
- list_add_tail(&pCifsFile->flist,
- &pCifsInode->openFileList);
- } else {
- list_add(&pCifsFile->flist,
- &pCifsInode->openFileList);
- }
-
if (pCifsInode->clientCanCacheRead) {
/* we have the inode open somewhere else
no need to discard cache data */
goto out_close;
}
+
+/*
+ * If dentry->d_inode is null (usually meaning the cached dentry
+ * is a negative dentry) then we would attempt a standard SMB delete, but
+ * if that fails we can not attempt the fall back mechanisms on EACESS
+ * but will return the EACESS to the caller. Note that the VFS does not call
+ * unlink on negative dentries currently.
+ */
int cifs_unlink(struct inode *dir, struct dentry *dentry)
{
int rc = 0;
int xid;
char *full_path = NULL;
struct inode *inode = dentry->d_inode;
- struct cifsInodeInfo *cifsInode = CIFS_I(inode);
+ struct cifsInodeInfo *cifs_inode;
struct super_block *sb = dir->i_sb;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
struct cifsTconInfo *tcon = cifs_sb->tcon;
rc = cifs_rename_pending_delete(full_path, dentry, xid);
if (rc == 0)
drop_nlink(inode);
- } else if (rc == -EACCES && dosattr == 0) {
+ } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
if (attrs == NULL) {
rc = -ENOMEM;
}
/* try to reset dos attributes */
- origattr = cifsInode->cifsAttrs;
+ cifs_inode = CIFS_I(inode);
+ origattr = cifs_inode->cifsAttrs;
if (origattr == 0)
origattr |= ATTR_NORMAL;
dosattr = origattr & ~ATTR_READONLY;
out_reval:
if (inode) {
- cifsInode = CIFS_I(inode);
- cifsInode->time = 0; /* will force revalidate to get info
+ cifs_inode = CIFS_I(inode);
+ cifs_inode->time = 0; /* will force revalidate to get info
when needed */
inode->i_ctime = current_fs_time(sb);
}
dir->i_ctime = dir->i_mtime = current_fs_time(sb);
- cifsInode = CIFS_I(dir);
+ cifs_inode = CIFS_I(dir);
CIFS_I(dir)->time = 0; /* force revalidate of dir as well */
kfree(full_path);
full_path = build_path_from_dentry(direntry);
if (!full_path)
- goto out_no_free;
+ goto out;
cFYI(1, ("Full path: %s inode = 0x%p", full_path, inode));
cifs_sb = CIFS_SB(inode->i_sb);
pTcon = cifs_sb->tcon;
- target_path = kmalloc(PATH_MAX, GFP_KERNEL);
- if (!target_path) {
- target_path = ERR_PTR(-ENOMEM);
- goto out;
- }
/* We could change this to:
if (pTcon->unix_ext)
if (pTcon->ses->capabilities & CAP_UNIX)
rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
- target_path,
- PATH_MAX-1,
+ &target_path,
cifs_sb->local_nls);
else {
/* BB add read reparse point symlink code here */
/* BB Add MAC style xsymlink check here if enabled */
}
- if (rc == 0) {
-
-/* BB Add special case check for Samba DFS symlinks */
-
- target_path[PATH_MAX-1] = 0;
- } else {
+ if (rc != 0) {
kfree(target_path);
target_path = ERR_PTR(rc);
}
-out:
kfree(full_path);
-out_no_free:
+out:
FreeXid(xid);
nd_set_link(nd, target_path);
- return NULL; /* No cookie */
+ return NULL;
}
int
return rc;
}
-int
-cifs_readlink(struct dentry *direntry, char __user *pBuffer, int buflen)
-{
- struct inode *inode = direntry->d_inode;
- int rc = -EACCES;
- int xid;
- int oplock = 0;
- struct cifs_sb_info *cifs_sb;
- struct cifsTconInfo *pTcon;
- char *full_path = NULL;
- char *tmpbuffer;
- int len;
- __u16 fid;
-
- xid = GetXid();
- cifs_sb = CIFS_SB(inode->i_sb);
- pTcon = cifs_sb->tcon;
-
-/* BB would it be safe against deadlock to grab this sem
- even though rename itself grabs the sem and calls lookup? */
-/* mutex_lock(&inode->i_sb->s_vfs_rename_mutex);*/
- full_path = build_path_from_dentry(direntry);
-/* mutex_unlock(&inode->i_sb->s_vfs_rename_mutex);*/
-
- if (full_path == NULL) {
- FreeXid(xid);
- return -ENOMEM;
- }
-
- cFYI(1,
- ("Full path: %s inode = 0x%p pBuffer = 0x%p buflen = %d",
- full_path, inode, pBuffer, buflen));
- if (buflen > PATH_MAX)
- len = PATH_MAX;
- else
- len = buflen;
- tmpbuffer = kmalloc(len, GFP_KERNEL);
- if (tmpbuffer == NULL) {
- kfree(full_path);
- FreeXid(xid);
- return -ENOMEM;
- }
-
-/* BB add read reparse point symlink code and
- Unix extensions symlink code here BB */
-/* We could disable this based on pTcon->unix_ext flag instead ... but why? */
- if (cifs_sb->tcon->ses->capabilities & CAP_UNIX)
- rc = CIFSSMBUnixQuerySymLink(xid, pTcon, full_path,
- tmpbuffer,
- len - 1,
- cifs_sb->local_nls);
- else if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
- cERROR(1, ("SFU style symlinks not implemented yet"));
- /* add open and read as in fs/cifs/inode.c */
- } else {
- rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, GENERIC_READ,
- OPEN_REPARSE_POINT, &fid, &oplock, NULL,
- cifs_sb->local_nls,
- cifs_sb->mnt_cifs_flags &
- CIFS_MOUNT_MAP_SPECIAL_CHR);
- if (!rc) {
- rc = CIFSSMBQueryReparseLinkInfo(xid, pTcon, full_path,
- tmpbuffer,
- len - 1,
- fid,
- cifs_sb->local_nls);
- if (CIFSSMBClose(xid, pTcon, fid)) {
- cFYI(1, ("Error closing junction point "
- "(open for ioctl)"));
- }
- /* If it is a DFS junction earlier we would have gotten
- PATH_NOT_COVERED returned from server so we do
- not need to request the DFS info here */
- }
- }
- /* BB Anything else to do to handle recursive links? */
- /* BB Should we be using page ops here? */
-
- /* BB null terminate returned string in pBuffer? BB */
- if (rc == 0) {
- rc = vfs_readlink(direntry, pBuffer, len, tmpbuffer);
- cFYI(1,
- ("vfs_readlink called from cifs_readlink returned %d",
- rc));
- }
-
- kfree(tmpbuffer);
- kfree(full_path);
- FreeXid(xid);
- return rc;
-}
-
void cifs_put_link(struct dentry *direntry, struct nameidata *nd, void *cookie)
{
char *p = nd_get_link(nd);
return;
}
-/* Windows maps these to the user defined 16 bit Unicode range since they are
- reserved symbols (along with \ and /), otherwise illegal to store
- in filenames in NTFS */
-#define UNI_ASTERIK (__u16) ('*' + 0xF000)
-#define UNI_QUESTION (__u16) ('?' + 0xF000)
-#define UNI_COLON (__u16) (':' + 0xF000)
-#define UNI_GRTRTHAN (__u16) ('>' + 0xF000)
-#define UNI_LESSTHAN (__u16) ('<' + 0xF000)
-#define UNI_PIPE (__u16) ('|' + 0xF000)
-#define UNI_SLASH (__u16) ('\\' + 0xF000)
-
-/* Convert 16 bit Unicode pathname from wire format to string in current code
- page. Conversion may involve remapping up the seven characters that are
- only legal in POSIX-like OS (if they are present in the string). Path
- names are little endian 16 bit Unicode on the wire */
-int
-cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
- const struct nls_table *cp)
-{
- int i, j, len;
- __u16 src_char;
-
- for (i = 0, j = 0; i < maxlen; i++) {
- src_char = le16_to_cpu(source[i]);
- switch (src_char) {
- case 0:
- goto cUCS_out; /* BB check this BB */
- case UNI_COLON:
- target[j] = ':';
- break;
- case UNI_ASTERIK:
- target[j] = '*';
- break;
- case UNI_QUESTION:
- target[j] = '?';
- break;
- /* BB We can not handle remapping slash until
- all the calls to build_path_from_dentry
- are modified, as they use slash as separator BB */
- /* case UNI_SLASH:
- target[j] = '\\';
- break;*/
- case UNI_PIPE:
- target[j] = '|';
- break;
- case UNI_GRTRTHAN:
- target[j] = '>';
- break;
- case UNI_LESSTHAN:
- target[j] = '<';
- break;
- default:
- len = cp->uni2char(src_char, &target[j],
- NLS_MAX_CHARSET_SIZE);
- if (len > 0) {
- j += len;
- continue;
- } else {
- target[j] = '?';
- }
- }
- j++;
- /* make sure we do not overrun callers allocated temp buffer */
- if (j >= (2 * NAME_MAX))
- break;
- }
-cUCS_out:
- target[j] = 0;
- return j;
-}
-
/* Convert 16 bit Unicode pathname to wire format from string in current code
page. Conversion may involve remapping up the seven characters that are
only legal in POSIX-like OS (if they are present in the string). Path
{ErrQuota, -EDQUOT},
{ErrNotALink, -ENOLINK},
{ERRnetlogonNotStarted, -ENOPROTOOPT},
+ {ERRsymlink, -EOPNOTSUPP},
{ErrTooManyLinks, -EMLINK},
{0, 0}
};
ERRDOS, ERRnoaccess, 0xc000028f}, {
ERRDOS, ERRnoaccess, 0xc0000290}, {
ERRDOS, ERRbadfunc, 0xc000029c}, {
+ ERRDOS, ERRsymlink, NT_STATUS_STOPPED_ON_SYMLINK}, {
ERRDOS, ERRinvlevel, 0x007c0001}, };
/*****************************************************************************
extern const struct nt_err_code_struct nt_errs[];
/* Win32 Status codes. */
-
-#define STATUS_BUFFER_OVERFLOW 0x80000005
#define STATUS_MORE_ENTRIES 0x0105
#define ERROR_INVALID_PARAMETER 0x0057
#define ERROR_INSUFFICIENT_BUFFER 0x007a
#define STATUS_SOME_UNMAPPED 0x0107
#define STATUS_BUFFER_OVERFLOW 0x80000005
#define NT_STATUS_NO_MORE_ENTRIES 0x8000001a
+#define NT_STATUS_MEDIA_CHANGED 0x8000001c
+#define NT_STATUS_END_OF_MEDIA 0x8000001e
+#define NT_STATUS_MEDIA_CHECK 0x80000020
+#define NT_STATUS_NO_DATA_DETECTED 0x8000001c
+#define NT_STATUS_STOPPED_ON_SYMLINK 0x8000002d
+#define NT_STATUS_DEVICE_REQUIRES_CLEANING 0x80000288
+#define NT_STATUS_DEVICE_DOOR_OPEN 0x80000288
#define NT_STATUS_UNSUCCESSFUL 0xC0000000 | 0x0001
#define NT_STATUS_NOT_IMPLEMENTED 0xC0000000 | 0x0002
#define NT_STATUS_INVALID_INFO_CLASS 0xC0000000 | 0x0003
#define UnknownMessage cpu_to_le32(8)
/* Negotiate Flags */
-#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are in unicode */
-#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
-#define NTLMSSP_REQUEST_TARGET 0x04 /* Server return its auth realm */
-#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signature capability */
-#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
-#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
-#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Sign/seal use LM session key */
-#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
-#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000
+#define NTLMSSP_NEGOTIATE_UNICODE 0x01 /* Text strings are unicode */
+#define NTLMSSP_NEGOTIATE_OEM 0x02 /* Text strings are in OEM */
+#define NTLMSSP_REQUEST_TARGET 0x04 /* Srv returns its auth realm */
+/* define reserved9 0x08 */
+#define NTLMSSP_NEGOTIATE_SIGN 0x0010 /* Request signing capability */
+#define NTLMSSP_NEGOTIATE_SEAL 0x0020 /* Request confidentiality */
+#define NTLMSSP_NEGOTIATE_DGRAM 0x0040
+#define NTLMSSP_NEGOTIATE_LM_KEY 0x0080 /* Use LM session key */
+/* defined reserved 8 0x0100 */
+#define NTLMSSP_NEGOTIATE_NTLM 0x0200 /* NTLM authentication */
+#define NTLMSSP_NEGOTIATE_NT_ONLY 0x0400 /* Lanman not allowed */
+#define NTLMSSP_ANONYMOUS 0x0800
+#define NTLMSSP_NEGOTIATE_DOMAIN_SUPPLIED 0x1000 /* reserved6 */
#define NTLMSSP_NEGOTIATE_WORKSTATION_SUPPLIED 0x2000
-#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server on same machine */
-#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign for all security levels */
-#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
-#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
-#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
-#define NTLMSSP_NEGOTIATE_NTLMV2 0x80000
-#define NTLMSSP_REQUEST_INIT_RESP 0x100000
-#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000
-#define NTLMSSP_REQUEST_NOT_NT_KEY 0x400000
+#define NTLMSSP_NEGOTIATE_LOCAL_CALL 0x4000 /* client/server same machine */
+#define NTLMSSP_NEGOTIATE_ALWAYS_SIGN 0x8000 /* Sign. All security levels */
+#define NTLMSSP_TARGET_TYPE_DOMAIN 0x10000
+#define NTLMSSP_TARGET_TYPE_SERVER 0x20000
+#define NTLMSSP_TARGET_TYPE_SHARE 0x40000
+#define NTLMSSP_NEGOTIATE_EXTENDED_SEC 0x80000 /* NB:not related to NTLMv2 pwd*/
+/* #define NTLMSSP_REQUEST_INIT_RESP 0x100000 */
+#define NTLMSSP_NEGOTIATE_IDENTIFY 0x100000
+#define NTLMSSP_REQUEST_ACCEPT_RESP 0x200000 /* reserved5 */
+#define NTLMSSP_REQUEST_NON_NT_KEY 0x400000
#define NTLMSSP_NEGOTIATE_TARGET_INFO 0x800000
-#define NTLMSSP_NEGOTIATE_128 0x20000000
-#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
-#define NTLMSSP_NEGOTIATE_56 0x80000000
+/* #define reserved4 0x1000000 */
+#define NTLMSSP_NEGOTIATE_VERSION 0x2000000 /* we do not set */
+/* #define reserved3 0x4000000 */
+/* #define reserved2 0x8000000 */
+/* #define reserved1 0x10000000 */
+#define NTLMSSP_NEGOTIATE_128 0x20000000
+#define NTLMSSP_NEGOTIATE_KEY_XCH 0x40000000
+#define NTLMSSP_NEGOTIATE_56 0x80000000
/* Although typedefs are not commonly used for structure definitions */
/* in the Linux kernel, in this particular case they are useful */
typedef struct _SECURITY_BUFFER {
__le16 Length;
__le16 MaximumLength;
- __le32 Buffer; /* offset to buffer */
+ __le32 BufferOffset; /* offset to buffer */
} __attribute__((packed)) SECURITY_BUFFER;
typedef struct _NEGOTIATE_MESSAGE {
__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* 1 */
+ __le32 MessageType; /* NtLmNegotiate = 1 */
__le32 NegotiateFlags;
SECURITY_BUFFER DomainName; /* RFC 1001 style and ASCII */
SECURITY_BUFFER WorkstationName; /* RFC 1001 and ASCII */
+ /* SECURITY_BUFFER for version info not present since we
+ do not set the version is present flag */
char DomainString[0];
/* followed by WorkstationString */
} __attribute__((packed)) NEGOTIATE_MESSAGE, *PNEGOTIATE_MESSAGE;
typedef struct _CHALLENGE_MESSAGE {
__u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* 2 */
+ __le32 MessageType; /* NtLmChallenge = 2 */
SECURITY_BUFFER TargetName;
__le32 NegotiateFlags;
__u8 Challenge[CIFS_CRYPTO_KEY_SIZE];
__u8 Reserved[8];
SECURITY_BUFFER TargetInfoArray;
+ /* SECURITY_BUFFER for version info not present since we
+ do not set the version is present flag */
} __attribute__((packed)) CHALLENGE_MESSAGE, *PCHALLENGE_MESSAGE;
typedef struct _AUTHENTICATE_MESSAGE {
- __u8 Signature[sizeof (NTLMSSP_SIGNATURE)];
- __le32 MessageType; /* 3 */
+ __u8 Signature[sizeof(NTLMSSP_SIGNATURE)];
+ __le32 MessageType; /* NtLmsAuthenticate = 3 */
SECURITY_BUFFER LmChallengeResponse;
SECURITY_BUFFER NtChallengeResponse;
SECURITY_BUFFER DomainName;
SECURITY_BUFFER WorkstationName;
SECURITY_BUFFER SessionKey;
__le32 NegotiateFlags;
+ /* SECURITY_BUFFER for version info not present since we
+ do not set the version is present flag */
char UserString[0];
} __attribute__((packed)) AUTHENTICATE_MESSAGE, *PAUTHENTICATE_MESSAGE;
#include "cifs_fs_sb.h"
#include "cifsfs.h"
+/*
+ * To be safe - for UCS to UTF-8 with strings loaded with the rare long
+ * characters alloc more to account for such multibyte target UTF-8
+ * characters.
+ */
+#define UNICODE_NAME_MAX ((4 * NAME_MAX) + 2)
+
#ifdef CONFIG_CIFS_DEBUG2
static void dump_cifs_file_struct(struct file *file, char *label)
{
}
}
+/* BB eventually need to add the following helper function to
+ resolve NT_STATUS_STOPPED_ON_SYMLINK return code when
+ we try to do FindFirst on (NTFS) directory symlinks */
+/*
+int get_symlink_reparse_path(char *full_path, struct cifs_sb_info *cifs_sb,
+ int xid)
+{
+ __u16 fid;
+ int len;
+ int oplock = 0;
+ int rc;
+ struct cifsTconInfo *ptcon = cifs_sb->tcon;
+ char *tmpbuffer;
+
+ rc = CIFSSMBOpen(xid, ptcon, full_path, FILE_OPEN, GENERIC_READ,
+ OPEN_REPARSE_POINT, &fid, &oplock, NULL,
+ cifs_sb->local_nls,
+ cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
+ if (!rc) {
+ tmpbuffer = kmalloc(maxpath);
+ rc = CIFSSMBQueryReparseLinkInfo(xid, ptcon, full_path,
+ tmpbuffer,
+ maxpath -1,
+ fid,
+ cifs_sb->local_nls);
+ if (CIFSSMBClose(xid, ptcon, fid)) {
+ cFYI(1, ("Error closing temporary reparsepoint open)"));
+ }
+ }
+}
+ */
+
static int initiate_cifs_search(const int xid, struct file *file)
{
int rc = 0;
CIFS_MOUNT_MAP_SPECIAL_CHR, CIFS_DIR_SEP(cifs_sb));
if (rc == 0)
cifsFile->invalidHandle = false;
- if ((rc == -EOPNOTSUPP) &&
+ /* BB add following call to handle readdir on new NTFS symlink errors
+ else if STATUS_STOPPED_ON_SYMLINK
+ call get_symlink_reparse_path and retry with new path */
+ else if ((rc == -EOPNOTSUPP) &&
(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) {
cifs_sb->mnt_cifs_flags &= ~CIFS_MOUNT_SERVER_INUM;
goto ffirst_retry;
/* inode num, inode type and filename returned */
static int cifs_get_name_from_search_buf(struct qstr *pqst,
char *current_entry, __u16 level, unsigned int unicode,
- struct cifs_sb_info *cifs_sb, int max_len, __u64 *pinum)
+ struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum)
{
int rc = 0;
unsigned int len = 0;
}
if (unicode) {
- /* BB fixme - test with long names */
- /* Note converted filename can be longer than in unicode */
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR)
- pqst->len = cifs_convertUCSpath((char *)pqst->name,
- (__le16 *)filename, len/2, nlt);
- else
- pqst->len = cifs_strfromUCS_le((char *)pqst->name,
- (__le16 *)filename, len/2, nlt);
+ pqst->len = cifs_from_ucs2((char *) pqst->name,
+ (__le16 *) filename,
+ UNICODE_NAME_MAX,
+ min(len, max_len), nlt,
+ cifs_sb->mnt_cifs_flags &
+ CIFS_MOUNT_MAP_SPECIAL_CHR);
} else {
pqst->name = filename;
pqst->len = len;
return rc;
}
-static int cifs_filldir(char *pfindEntry, struct file *file,
- filldir_t filldir, void *direntry, char *scratch_buf, int max_len)
+static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir,
+ void *direntry, char *scratch_buf, unsigned int max_len)
{
int rc = 0;
struct qstr qstring;
int num_to_fill = 0;
char *tmp_buf = NULL;
char *end_of_smb;
- int max_len;
+ unsigned int max_len;
xid = GetXid();
cifsFile->srch_inf.ntwrk_buf_start);
end_of_smb = cifsFile->srch_inf.ntwrk_buf_start + max_len;
- /* To be safe - for UCS to UTF-8 with strings loaded
- with the rare long characters alloc more to account for
- such multibyte target UTF-8 characters. cifs_unicode.c,
- which actually does the conversion, has the same limit */
- tmp_buf = kmalloc((2 * NAME_MAX) + 4, GFP_KERNEL);
+ tmp_buf = kmalloc(UNICODE_NAME_MAX, GFP_KERNEL);
for (i = 0; (i < num_to_fill) && (rc == 0); i++) {
if (current_entry == NULL) {
/* evaluate whether this case is an error */
*
* SMB/CIFS session setup handling routines
*
- * Copyright (c) International Business Machines Corp., 2006, 2007
+ * Copyright (c) International Business Machines Corp., 2006, 2009
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
get_vc_num_exit:
write_unlock(&cifs_tcp_ses_lock);
- return le16_to_cpu(vcnum);
+ return cpu_to_le16(vcnum);
}
static __u32 cifs_ssetup_hdr(struct cifsSesInfo *ses, SESSION_SETUP_ANDX *pSMB)
*pbcc_area = bcc_ptr;
}
-static int decode_unicode_ssetup(char **pbcc_area, int bleft,
- struct cifsSesInfo *ses,
- const struct nls_table *nls_cp)
+static void
+decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifsSesInfo *ses,
+ const struct nls_table *nls_cp)
{
- int rc = 0;
- int words_left, len;
+ int len;
char *data = *pbcc_area;
cFYI(1, ("bleft %d", bleft));
++bleft;
}
- words_left = bleft / 2;
-
- /* save off server operating system */
- len = UniStrnlen((wchar_t *) data, words_left);
-
- if (len >= words_left)
- return rc;
-
kfree(ses->serverOS);
- /* UTF-8 string will not grow more than four times as big as UCS-16 */
- ses->serverOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
- if (ses->serverOS != NULL) {
- cifs_strfromUCS_le(ses->serverOS, (__le16 *)data, len, nls_cp);
- cFYI(1, ("serverOS=%s", ses->serverOS));
- }
- data += 2 * (len + 1);
- words_left -= len + 1;
-
- /* save off server network operating system */
- len = UniStrnlen((wchar_t *) data, words_left);
-
- if (len >= words_left)
- return rc;
+ ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+ cFYI(1, ("serverOS=%s", ses->serverOS));
+ len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
+ data += len;
+ bleft -= len;
+ if (bleft <= 0)
+ return;
kfree(ses->serverNOS);
- ses->serverNOS = kzalloc((4 * len) + 2 /* trailing null */, GFP_KERNEL);
- if (ses->serverNOS != NULL) {
- cifs_strfromUCS_le(ses->serverNOS, (__le16 *)data, len,
- nls_cp);
- cFYI(1, ("serverNOS=%s", ses->serverNOS));
- if (strncmp(ses->serverNOS, "NT LAN Manager 4", 16) == 0) {
- cFYI(1, ("NT4 server"));
- ses->flags |= CIFS_SES_NT4;
- }
- }
- data += 2 * (len + 1);
- words_left -= len + 1;
-
- /* save off server domain */
- len = UniStrnlen((wchar_t *) data, words_left);
-
- if (len > words_left)
- return rc;
+ ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+ cFYI(1, ("serverNOS=%s", ses->serverNOS));
+ len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2;
+ data += len;
+ bleft -= len;
+ if (bleft <= 0)
+ return;
kfree(ses->serverDomain);
- ses->serverDomain = kzalloc((4 * len) + 2, GFP_KERNEL);
- if (ses->serverDomain != NULL) {
- cifs_strfromUCS_le(ses->serverDomain, (__le16 *)data, len,
- nls_cp);
- cFYI(1, ("serverDomain=%s", ses->serverDomain));
- }
- data += 2 * (len + 1);
- words_left -= len + 1;
-
- cFYI(1, ("words left: %d", words_left));
+ ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp);
+ cFYI(1, ("serverDomain=%s", ses->serverDomain));
- return rc;
+ return;
}
static int decode_ascii_ssetup(char **pbcc_area, int bleft,
return rc;
}
+static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len,
+ struct cifsSesInfo *ses)
+{
+ CHALLENGE_MESSAGE *pblob = (CHALLENGE_MESSAGE *)bcc_ptr;
+
+ if (blob_len < sizeof(CHALLENGE_MESSAGE)) {
+ cERROR(1, ("challenge blob len %d too small", blob_len));
+ return -EINVAL;
+ }
+
+ if (memcmp(pblob->Signature, "NTLMSSP", 8)) {
+ cERROR(1, ("blob signature incorrect %s", pblob->Signature));
+ return -EINVAL;
+ }
+ if (pblob->MessageType != NtLmChallenge) {
+ cERROR(1, ("Incorrect message type %d", pblob->MessageType));
+ return -EINVAL;
+ }
+
+ memcpy(ses->server->cryptKey, pblob->Challenge, CIFS_CRYPTO_KEY_SIZE);
+ /* BB we could decode pblob->NegotiateFlags; some may be useful */
+ /* In particular we can examine sign flags */
+ /* BB spec says that if AvId field of MsvAvTimestamp is populated then
+ we must set the MIC field of the AUTHENTICATE_MESSAGE */
+
+ return 0;
+}
+
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+/* BB Move to ntlmssp.c eventually */
+
+/* We do not malloc the blob, it is passed in pbuffer, because
+ it is fixed size, and small, making this approach cleaner */
+static void build_ntlmssp_negotiate_blob(unsigned char *pbuffer,
+ struct cifsSesInfo *ses)
+{
+ NEGOTIATE_MESSAGE *sec_blob = (NEGOTIATE_MESSAGE *)pbuffer;
+ __u32 flags;
+
+ memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
+ sec_blob->MessageType = NtLmNegotiate;
+
+ /* BB is NTLMV2 session security format easier to use here? */
+ flags = NTLMSSP_NEGOTIATE_56 | NTLMSSP_REQUEST_TARGET |
+ NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
+ if (ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ flags |= NTLMSSP_NEGOTIATE_SIGN;
+ if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
+ flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
+
+ sec_blob->NegotiateFlags |= cpu_to_le32(flags);
+
+ sec_blob->WorkstationName.BufferOffset = 0;
+ sec_blob->WorkstationName.Length = 0;
+ sec_blob->WorkstationName.MaximumLength = 0;
+
+ /* Domain name is sent on the Challenge not Negotiate NTLMSSP request */
+ sec_blob->DomainName.BufferOffset = 0;
+ sec_blob->DomainName.Length = 0;
+ sec_blob->DomainName.MaximumLength = 0;
+}
+
+/* We do not malloc the blob, it is passed in pbuffer, because its
+ maximum possible size is fixed and small, making this approach cleaner.
+ This function returns the length of the data in the blob */
+static int build_ntlmssp_auth_blob(unsigned char *pbuffer,
+ struct cifsSesInfo *ses,
+ const struct nls_table *nls_cp, int first)
+{
+ AUTHENTICATE_MESSAGE *sec_blob = (AUTHENTICATE_MESSAGE *)pbuffer;
+ __u32 flags;
+ unsigned char *tmp;
+ char ntlm_session_key[CIFS_SESS_KEY_SIZE];
+
+ memcpy(sec_blob->Signature, NTLMSSP_SIGNATURE, 8);
+ sec_blob->MessageType = NtLmAuthenticate;
+
+ flags = NTLMSSP_NEGOTIATE_56 |
+ NTLMSSP_REQUEST_TARGET | NTLMSSP_NEGOTIATE_TARGET_INFO |
+ NTLMSSP_NEGOTIATE_128 | NTLMSSP_NEGOTIATE_UNICODE |
+ NTLMSSP_NEGOTIATE_NT_ONLY | NTLMSSP_NEGOTIATE_NTLM;
+ if (ses->server->secMode &
+ (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED))
+ flags |= NTLMSSP_NEGOTIATE_SIGN;
+ if (ses->server->secMode & SECMODE_SIGN_REQUIRED)
+ flags |= NTLMSSP_NEGOTIATE_ALWAYS_SIGN;
+
+ tmp = pbuffer + sizeof(AUTHENTICATE_MESSAGE);
+ sec_blob->NegotiateFlags |= cpu_to_le32(flags);
+
+ sec_blob->LmChallengeResponse.BufferOffset =
+ cpu_to_le32(sizeof(AUTHENTICATE_MESSAGE));
+ sec_blob->LmChallengeResponse.Length = 0;
+ sec_blob->LmChallengeResponse.MaximumLength = 0;
+
+ /* calculate session key, BB what about adding similar ntlmv2 path? */
+ SMBNTencrypt(ses->password, ses->server->cryptKey, ntlm_session_key);
+ if (first)
+ cifs_calculate_mac_key(&ses->server->mac_signing_key,
+ ntlm_session_key, ses->password);
+
+ memcpy(tmp, ntlm_session_key, CIFS_SESS_KEY_SIZE);
+ sec_blob->NtChallengeResponse.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->NtChallengeResponse.Length = cpu_to_le16(CIFS_SESS_KEY_SIZE);
+ sec_blob->NtChallengeResponse.MaximumLength =
+ cpu_to_le16(CIFS_SESS_KEY_SIZE);
+
+ tmp += CIFS_SESS_KEY_SIZE;
+
+ if (ses->domainName == NULL) {
+ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->DomainName.Length = 0;
+ sec_blob->DomainName.MaximumLength = 0;
+ tmp += 2;
+ } else {
+ int len;
+ len = cifs_strtoUCS((__le16 *)tmp, ses->domainName,
+ MAX_USERNAME_SIZE, nls_cp);
+ len *= 2; /* unicode is 2 bytes each */
+ len += 2; /* trailing null */
+ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->DomainName.Length = cpu_to_le16(len);
+ sec_blob->DomainName.MaximumLength = cpu_to_le16(len);
+ tmp += len;
+ }
+
+ if (ses->userName == NULL) {
+ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->UserName.Length = 0;
+ sec_blob->UserName.MaximumLength = 0;
+ tmp += 2;
+ } else {
+ int len;
+ len = cifs_strtoUCS((__le16 *)tmp, ses->userName,
+ MAX_USERNAME_SIZE, nls_cp);
+ len *= 2; /* unicode is 2 bytes each */
+ len += 2; /* trailing null */
+ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->UserName.Length = cpu_to_le16(len);
+ sec_blob->UserName.MaximumLength = cpu_to_le16(len);
+ tmp += len;
+ }
+
+ sec_blob->WorkstationName.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->WorkstationName.Length = 0;
+ sec_blob->WorkstationName.MaximumLength = 0;
+ tmp += 2;
+
+ sec_blob->SessionKey.BufferOffset = cpu_to_le32(tmp - pbuffer);
+ sec_blob->SessionKey.Length = 0;
+ sec_blob->SessionKey.MaximumLength = 0;
+ return tmp - pbuffer;
+}
+
+
+static void setup_ntlmssp_neg_req(SESSION_SETUP_ANDX *pSMB,
+ struct cifsSesInfo *ses)
+{
+ build_ntlmssp_negotiate_blob(&pSMB->req.SecurityBlob[0], ses);
+ pSMB->req.SecurityBlobLength = cpu_to_le16(sizeof(NEGOTIATE_MESSAGE));
+
+ return;
+}
+
+static int setup_ntlmssp_auth_req(SESSION_SETUP_ANDX *pSMB,
+ struct cifsSesInfo *ses,
+ const struct nls_table *nls, int first_time)
+{
+ int bloblen;
+
+ bloblen = build_ntlmssp_auth_blob(&pSMB->req.SecurityBlob[0], ses, nls,
+ first_time);
+ pSMB->req.SecurityBlobLength = cpu_to_le16(bloblen);
+
+ return bloblen;
+}
+#endif
+
int
CIFS_SessSetup(unsigned int xid, struct cifsSesInfo *ses, int first_time,
const struct nls_table *nls_cp)
__u16 action;
int bytes_remaining;
struct key *spnego_key = NULL;
+ __le32 phase = NtLmNegotiate; /* NTLMSSP, if needed, is multistage */
if (ses == NULL)
return -EINVAL;
type = ses->server->secType;
cFYI(1, ("sess setup type %d", type));
+ssetup_ntlmssp_authenticate:
+ if (phase == NtLmChallenge)
+ phase = NtLmAuthenticate; /* if ntlmssp, now final phase */
+
if (type == LANMAN) {
#ifndef CONFIG_CIFS_WEAK_PW_HASH
/* LANMAN and plaintext are less secure and off by default.
goto ssetup_exit;
#endif /* CONFIG_CIFS_UPCALL */
} else {
+#ifdef CONFIG_CIFS_EXPERIMENTAL
+ if ((experimEnabled > 1) && (type == RawNTLMSSP)) {
+ if ((pSMB->req.hdr.Flags2 & SMBFLG2_UNICODE) == 0) {
+ cERROR(1, ("NTLMSSP requires Unicode support"));
+ rc = -ENOSYS;
+ goto ssetup_exit;
+ }
+
+ cFYI(1, ("ntlmssp session setup phase %d", phase));
+ pSMB->req.hdr.Flags2 |= SMBFLG2_EXT_SEC;
+ capabilities |= CAP_EXTENDED_SECURITY;
+ pSMB->req.Capabilities |= cpu_to_le32(capabilities);
+ if (phase == NtLmNegotiate) {
+ setup_ntlmssp_neg_req(pSMB, ses);
+ iov[1].iov_len = sizeof(NEGOTIATE_MESSAGE);
+ } else if (phase == NtLmAuthenticate) {
+ int blob_len;
+ blob_len = setup_ntlmssp_auth_req(pSMB, ses,
+ nls_cp,
+ first_time);
+ iov[1].iov_len = blob_len;
+ /* Make sure that we tell the server that we
+ are using the uid that it just gave us back
+ on the response (challenge) */
+ smb_buf->Uid = ses->Suid;
+ } else {
+ cERROR(1, ("invalid phase %d", phase));
+ rc = -ENOSYS;
+ goto ssetup_exit;
+ }
+ iov[1].iov_base = &pSMB->req.SecurityBlob[0];
+ /* unicode strings must be word aligned */
+ if ((iov[0].iov_len + iov[1].iov_len) % 2) {
+ *bcc_ptr = 0;
+ bcc_ptr++;
+ }
+ unicode_oslm_strings(&bcc_ptr, nls_cp);
+ } else {
+ cERROR(1, ("secType %d not supported!", type));
+ rc = -ENOSYS;
+ goto ssetup_exit;
+ }
+#else
cERROR(1, ("secType %d not supported!", type));
rc = -ENOSYS;
goto ssetup_exit;
+#endif
}
iov[2].iov_base = str_area;
/* SMB request buf freed in SendReceive2 */
cFYI(1, ("ssetup rc from sendrecv2 is %d", rc));
- if (rc)
- goto ssetup_exit;
pSMB = (SESSION_SETUP_ANDX *)iov[0].iov_base;
smb_buf = (struct smb_hdr *)iov[0].iov_base;
+ if ((type == RawNTLMSSP) && (smb_buf->Status.CifsError ==
+ cpu_to_le32(NT_STATUS_MORE_PROCESSING_REQUIRED))) {
+ if (phase != NtLmNegotiate) {
+ cERROR(1, ("Unexpected more processing error"));
+ goto ssetup_exit;
+ }
+ /* NTLMSSP Negotiate sent now processing challenge (response) */
+ phase = NtLmChallenge; /* process ntlmssp challenge */
+ rc = 0; /* MORE_PROC rc is not an error here, but expected */
+ }
+ if (rc)
+ goto ssetup_exit;
+
if ((smb_buf->WordCount != 3) && (smb_buf->WordCount != 4)) {
rc = -EIO;
cERROR(1, ("bad word count %d", smb_buf->WordCount));
if (smb_buf->WordCount == 4) {
__u16 blob_len;
blob_len = le16_to_cpu(pSMB->resp.SecurityBlobLength);
- bcc_ptr += blob_len;
if (blob_len > bytes_remaining) {
cERROR(1, ("bad security blob length %d", blob_len));
rc = -EINVAL;
goto ssetup_exit;
}
+ if (phase == NtLmChallenge) {
+ rc = decode_ntlmssp_challenge(bcc_ptr, blob_len, ses);
+ /* now goto beginning for ntlmssp authenticate phase */
+ if (rc)
+ goto ssetup_exit;
+ }
+ bcc_ptr += blob_len;
bytes_remaining -= blob_len;
}
++bcc_ptr;
--bytes_remaining;
}
- rc = decode_unicode_ssetup(&bcc_ptr, bytes_remaining,
- ses, nls_cp);
+ decode_unicode_ssetup(&bcc_ptr, bytes_remaining, ses, nls_cp);
} else {
rc = decode_ascii_ssetup(&bcc_ptr, bytes_remaining,
ses, nls_cp);
} else if (resp_buf_type == CIFS_LARGE_BUFFER)
cifs_buf_release(iov[0].iov_base);
+ /* if ntlmssp, and negotiate succeeded, proceed to authenticate phase */
+ if ((phase == NtLmChallenge) && (rc == 0))
+ goto ssetup_ntlmssp_authenticate;
+
return rc;
}
/* Below errors are used internally (do not come over the wire) for passthrough
from STATUS codes to POSIX only */
+#define ERRsymlink 0xFFFD
#define ErrTooManyLinks 0xFFFE
/* Following error codes may be generated with the ERRSRV error class.*/
struct path path;
struct configfs_dirent *sd;
struct config_item *parent_item;
- struct config_item *target_item;
+ struct config_item *target_item = NULL;
struct config_item_type *type;
ret = -EPERM; /* What lack-of-symlink returns */
static LIST_HEAD(formats);
static DEFINE_RWLOCK(binfmt_lock);
-int register_binfmt(struct linux_binfmt * fmt)
+int __register_binfmt(struct linux_binfmt * fmt, int insert)
{
if (!fmt)
return -EINVAL;
write_lock(&binfmt_lock);
- list_add(&fmt->lh, &formats);
+ insert ? list_add(&fmt->lh, &formats) :
+ list_add_tail(&fmt->lh, &formats);
write_unlock(&binfmt_lock);
return 0;
}
-EXPORT_SYMBOL(register_binfmt);
+EXPORT_SYMBOL(__register_binfmt);
void unregister_binfmt(struct linux_binfmt * fmt)
{
long long length = 0, map_len = 0;
u64 logical = 0, phys = 0, size = 0;
u32 flags = FIEMAP_EXTENT_MERGED;
- int ret = 0;
+ int ret = 0, past_eof = 0, whole_file = 0;
if ((ret = fiemap_check_flags(fieinfo, FIEMAP_FLAG_SYNC)))
return ret;
start_blk = logical_to_blk(inode, start);
length = (long long)min_t(u64, len, i_size_read(inode));
+ if (length < len)
+ whole_file = 1;
+
map_len = length;
do {
/* HOLE */
if (!buffer_mapped(&tmp)) {
+ length -= blk_to_logical(inode, 1);
+ start_blk++;
+
+ /*
+ * we want to handle the case where there is an
+ * allocated block at the front of the file, and then
+ * nothing but holes up to the end of the file properly,
+ * to make sure that extent at the front gets properly
+ * marked with FIEMAP_EXTENT_LAST
+ */
+ if (!past_eof &&
+ blk_to_logical(inode, start_blk) >=
+ blk_to_logical(inode, 0)+i_size_read(inode))
+ past_eof = 1;
+
/*
* first hole after going past the EOF, this is our
* last extent
*/
- if (length <= 0) {
+ if (past_eof && size) {
flags = FIEMAP_EXTENT_MERGED|FIEMAP_EXTENT_LAST;
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size,
break;
}
- length -= blk_to_logical(inode, 1);
-
/* if we have holes up to/past EOF then we're done */
- if (length <= 0)
+ if (length <= 0 || past_eof)
break;
-
- start_blk++;
} else {
- if (length <= 0 && size) {
+ /*
+ * we have gone over the length of what we wanted to
+ * map, and it wasn't the entire file, so add the extent
+ * we got last time and exit.
+ *
+ * This is for the case where say we want to map all the
+ * way up to the second to the last block in a file, but
+ * the last block is a hole, making the second to last
+ * block FIEMAP_EXTENT_LAST. In this case we want to
+ * see if there is a hole after the second to last block
+ * so we can mark it properly. If we found data after
+ * we exceeded the length we were requesting, then we
+ * are good to go, just add the extent to the fieinfo
+ * and break
+ */
+ if (length <= 0 && !whole_file) {
+ ret = fiemap_fill_next_extent(fieinfo, logical,
+ phys, size,
+ flags);
+ break;
+ }
+
+ /*
+ * if size != 0 then we know we already have an extent
+ * to add, so add it.
+ */
+ if (size) {
ret = fiemap_fill_next_extent(fieinfo, logical,
phys, size,
flags);
start_blk += logical_to_blk(inode, size);
/*
- * if we are past the EOF we need to loop again to see
- * if there is a hole so we can mark this extent as the
- * last one, and if not keep mapping things until we
- * find a hole, or we run out of slots in the extent
- * array
+ * If we are past the EOF, then we need to make sure as
+ * soon as we find a hole that the last extent we found
+ * is marked with FIEMAP_EXTENT_LAST
*/
- if (length <= 0)
- continue;
-
- ret = fiemap_fill_next_extent(fieinfo, logical, phys,
- size, flags);
- if (ret)
- break;
+ if (!past_eof &&
+ logical+size >=
+ blk_to_logical(inode, 0)+i_size_read(inode))
+ past_eof = 1;
}
cond_resched();
} while (1);
ret = nfs_updatepage(filp, page, 0, pagelen);
out_unlock:
+ if (!ret)
+ return VM_FAULT_LOCKED;
unlock_page(page);
- if (ret)
- ret = VM_FAULT_SIGBUS;
- return ret;
+ return VM_FAULT_SIGBUS;
}
static struct vm_operations_struct nfs_file_vm_ops = {
rem = 0;
}
- kevent->name = kmalloc(len + rem, GFP_KERNEL);
+ kevent->name = kmalloc(len + rem, GFP_NOFS);
if (unlikely(!kevent->name)) {
kmem_cache_free(event_cachep, kevent);
return NULL;
else
mlog_errno(ret);
+ /*
+ * In case of error, manually free the allocation and do the iput().
+ * We need to do this because error here means no d_instantiate(),
+ * which means iput() will not be called during dput(dentry).
+ */
+ if (ret < 0 && !alias) {
+ ocfs2_lock_res_free(&dl->dl_lockres);
+ BUG_ON(dl->dl_count != 1);
+ spin_lock(&dentry_attach_lock);
+ dentry->d_fsdata = NULL;
+ spin_unlock(&dentry_attach_lock);
+ kfree(dl);
+ iput(inode);
+ }
+
dput(alias);
return ret;
u32 *num_dx_entries,
struct buffer_head *dirent_bh)
{
- int ret, namelen, i;
+ int ret = 0, namelen, i;
char *de_buf, *limit;
struct ocfs2_dir_entry *de;
struct buffer_head *dx_leaf_bh;
*/
BUG_ON(alloc > 2);
- ret = ocfs2_reserve_clusters(osb, alloc, &data_ac);
+ ret = ocfs2_reserve_clusters(osb, alloc + dx_alloc, &data_ac);
if (ret) {
mlog_errno(ret);
goto out;
/* If the inode allocator bit is clear, this inode must be stale */
if (!set) {
- mlog(0, "inode %llu suballoc bit is clear\n", blkno);
+ mlog(0, "inode %llu suballoc bit is clear\n",
+ (unsigned long long)blkno);
status = -ESTALE;
goto unlock_nfs_sync;
}
if (status < 0) {
if (status == -ESTALE) {
mlog(0, "stale inode ino: %llu generation: %u\n",
- blkno, handle->ih_generation);
+ (unsigned long long)blkno, handle->ih_generation);
}
result = ERR_PTR(status);
goto bail;
check_gen:
if (handle->ih_generation != inode->i_generation) {
iput(inode);
- mlog(0, "stale inode ino: %llu generation: %u\n", blkno,
- handle->ih_generation);
+ mlog(0, "stale inode ino: %llu generation: %u\n",
+ (unsigned long long)blkno, handle->ih_generation);
result = ERR_PTR(-ESTALE);
goto bail;
}
}
/* dinode + orphan dir dinode + inode alloc dinode + orphan dir entry +
- * inode alloc group descriptor + orphan dir index leaf */
-#define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 3)
+ * inode alloc group descriptor + orphan dir index root +
+ * orphan dir index leaf */
+#define OCFS2_DELETE_INODE_CREDITS (3 * OCFS2_INODE_UPDATE_CREDITS + 4)
/* dinode update, old dir dinode update, new dir dinode update, old
* dir dir entry, new dir dir entry, dir entry update for renaming
struct inode *orphan_dir = NULL;
struct ocfs2_dinode *newfe = NULL;
char orphan_name[OCFS2_ORPHAN_NAMELEN + 1];
- struct buffer_head *orphan_entry_bh = NULL;
struct buffer_head *newfe_bh = NULL;
struct buffer_head *old_inode_bh = NULL;
- struct buffer_head *insert_entry_bh = NULL;
struct ocfs2_super *osb = NULL;
u64 newfe_blkno, old_de_ino;
handle_t *handle = NULL;
brelse(old_inode_bh);
brelse(old_dir_bh);
brelse(new_dir_bh);
- brelse(orphan_entry_bh);
- brelse(insert_entry_bh);
mlog_exit(status);
struct buffer_head *inode_bh = NULL;
struct ocfs2_dinode *inode_fe;
- mlog_entry("blkno: %llu\n", blkno);
+ mlog_entry("blkno: %llu\n", (unsigned long long)blkno);
/* dirty read disk */
status = ocfs2_read_blocks_sync(osb, blkno, 1, &inode_bh);
if (status < 0) {
- mlog(ML_ERROR, "read block %llu failed %d\n", blkno, status);
+ mlog(ML_ERROR, "read block %llu failed %d\n",
+ (unsigned long long)blkno, status);
goto bail;
}
inode_fe = (struct ocfs2_dinode *) inode_bh->b_data;
if (!OCFS2_IS_VALID_DINODE(inode_fe)) {
- mlog(ML_ERROR, "invalid inode %llu requested\n", blkno);
+ mlog(ML_ERROR, "invalid inode %llu requested\n",
+ (unsigned long long)blkno);
status = -EINVAL;
goto bail;
}
- if (le16_to_cpu(inode_fe->i_suballoc_slot) != OCFS2_INVALID_SLOT &&
+ if (le16_to_cpu(inode_fe->i_suballoc_slot) != (u16)OCFS2_INVALID_SLOT &&
(u32)le16_to_cpu(inode_fe->i_suballoc_slot) > osb->max_slots - 1) {
mlog(ML_ERROR, "inode %llu has invalid suballoc slot %u\n",
- blkno, (u32)le16_to_cpu(inode_fe->i_suballoc_slot));
+ (unsigned long long)blkno,
+ (u32)le16_to_cpu(inode_fe->i_suballoc_slot));
status = -EINVAL;
goto bail;
}
u64 bg_blkno;
int status;
- mlog_entry("blkno: %llu bit: %u\n", blkno, (unsigned int)bit);
+ mlog_entry("blkno: %llu bit: %u\n", (unsigned long long)blkno,
+ (unsigned int)bit);
alloc_fe = (struct ocfs2_dinode *)alloc_bh->b_data;
if ((bit + 1) > ocfs2_bits_per_group(&alloc_fe->id2.i_chain)) {
status = ocfs2_read_group_descriptor(suballoc, alloc_fe, bg_blkno,
&group_bh);
if (status < 0) {
- mlog(ML_ERROR, "read group %llu failed %d\n", bg_blkno, status);
+ mlog(ML_ERROR, "read group %llu failed %d\n",
+ (unsigned long long)bg_blkno, status);
goto bail;
}
struct inode *inode_alloc_inode;
struct buffer_head *alloc_bh = NULL;
- mlog_entry("blkno: %llu", blkno);
+ mlog_entry("blkno: %llu", (unsigned long long)blkno);
status = ocfs2_get_suballoc_slot_bit(osb, blkno, &suballoc_slot,
&suballoc_bit);
#include <linux/delayacct.h>
#include <linux/seq_file.h>
#include <linux/pid_namespace.h>
+#include <linux/ptrace.h>
#include <linux/tracehook.h>
#include <asm/pgtable.h>
char state;
pid_t ppid = 0, pgid = -1, sid = -1;
int num_threads = 0;
+ int permitted;
struct mm_struct *mm;
unsigned long long start_time;
unsigned long cmin_flt = 0, cmaj_flt = 0;
state = *get_task_state(task);
vsize = eip = esp = 0;
+ permitted = ptrace_may_access(task, PTRACE_MODE_READ);
mm = get_task_mm(task);
if (mm) {
vsize = task_vsize(mm);
- eip = KSTK_EIP(task);
- esp = KSTK_ESP(task);
+ if (permitted) {
+ eip = KSTK_EIP(task);
+ esp = KSTK_ESP(task);
+ }
}
get_task_comm(tcomm, task);
unlock_task_sighand(task, &flags);
}
- if (!whole || num_threads < 2)
+ if (permitted && (!whole || num_threads < 2))
wchan = get_wchan(task);
if (!whole) {
min_flt = task->min_flt;
rsslim,
mm ? mm->start_code : 0,
mm ? mm->end_code : 0,
- mm ? mm->start_stack : 0,
+ (permitted && mm) ? mm->start_stack : 0,
esp,
eip,
/* The signal information here is obsolete.
wchan = get_wchan(task);
if (lookup_symbol_name(wchan, symname) < 0)
- return sprintf(buffer, "%lu", wchan);
+ if (!ptrace_may_access(task, PTRACE_MODE_READ))
+ return 0;
+ else
+ return sprintf(buffer, "%lu", wchan);
else
return sprintf(buffer, "%s", symname);
}
#define K(x) ((x) << (PAGE_SHIFT - 10))
si_meminfo(&i);
si_swapinfo(&i);
- committed = atomic_long_read(&vm_committed_space);
+ committed = percpu_counter_read_positive(&vm_committed_as);
allowed = ((totalram_pages - hugetlb_total_pages())
* sysctl_overcommit_ratio / 100) + total_swap_pages;
goto out_task;
ret = 0;
+
+ if (!count)
+ goto out_task;
+
mm = get_task_mm(task);
if (!mm)
goto out_task;
void *arg) /* formatter arg */
{
__int64_t bmvend; /* last block requested */
- int error; /* return value */
+ int error = 0; /* return value */
__int64_t fixlen; /* length for -1 case */
int i; /* extent number */
int lock; /* lock state */
int nexleft; /* # of user extents left */
int subnex; /* # of bmapi's can do */
int nmap; /* number of map entries */
- struct getbmapx out; /* output structure */
+ struct getbmapx *out; /* output structure */
int whichfork; /* data or attr fork */
int prealloced; /* this is a file with
* preallocated data space */
int iflags; /* interface flags */
int bmapi_flags; /* flags for xfs_bmapi */
+ int cur_ext = 0;
mp = ip->i_mount;
iflags = bmv->bmv_iflags;
-
whichfork = iflags & BMV_IF_ATTRFORK ? XFS_ATTR_FORK : XFS_DATA_FORK;
- /* If the BMV_IF_NO_DMAPI_READ interface bit specified, do not
- * generate a DMAPI read event. Otherwise, if the DM_EVENT_READ
- * bit is set for the file, generate a read event in order
- * that the DMAPI application may do its thing before we return
- * the extents. Usually this means restoring user file data to
- * regions of the file that look like holes.
- *
- * The "old behavior" (from XFS_IOC_GETBMAP) is to not specify
- * BMV_IF_NO_DMAPI_READ so that read events are generated.
- * If this were not true, callers of ioctl( XFS_IOC_GETBMAP )
- * could misinterpret holes in a DMAPI file as true holes,
- * when in fact they may represent offline user data.
- */
- if ((iflags & BMV_IF_NO_DMAPI_READ) == 0 &&
- DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
- whichfork == XFS_DATA_FORK) {
- error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip, 0, 0, 0, NULL);
- if (error)
- return XFS_ERROR(error);
- }
-
if (whichfork == XFS_ATTR_FORK) {
if (XFS_IFORK_Q(ip)) {
if (ip->i_d.di_aformat != XFS_DINODE_FMT_EXTENTS &&
ip->i_mount);
return XFS_ERROR(EFSCORRUPTED);
}
- } else if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
- ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
- ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
- return XFS_ERROR(EINVAL);
- if (whichfork == XFS_DATA_FORK) {
+
+ prealloced = 0;
+ fixlen = 1LL << 32;
+ } else {
+ /*
+ * If the BMV_IF_NO_DMAPI_READ interface bit specified, do
+ * not generate a DMAPI read event. Otherwise, if the
+ * DM_EVENT_READ bit is set for the file, generate a read
+ * event in order that the DMAPI application may do its thing
+ * before we return the extents. Usually this means restoring
+ * user file data to regions of the file that look like holes.
+ *
+ * The "old behavior" (from XFS_IOC_GETBMAP) is to not specify
+ * BMV_IF_NO_DMAPI_READ so that read events are generated.
+ * If this were not true, callers of ioctl(XFS_IOC_GETBMAP)
+ * could misinterpret holes in a DMAPI file as true holes,
+ * when in fact they may represent offline user data.
+ */
+ if (DM_EVENT_ENABLED(ip, DM_EVENT_READ) &&
+ !(iflags & BMV_IF_NO_DMAPI_READ)) {
+ error = XFS_SEND_DATA(mp, DM_EVENT_READ, ip,
+ 0, 0, 0, NULL);
+ if (error)
+ return XFS_ERROR(error);
+ }
+
+ if (ip->i_d.di_format != XFS_DINODE_FMT_EXTENTS &&
+ ip->i_d.di_format != XFS_DINODE_FMT_BTREE &&
+ ip->i_d.di_format != XFS_DINODE_FMT_LOCAL)
+ return XFS_ERROR(EINVAL);
+
if (xfs_get_extsz_hint(ip) ||
ip->i_d.di_flags & (XFS_DIFLAG_PREALLOC|XFS_DIFLAG_APPEND)){
prealloced = 1;
prealloced = 0;
fixlen = ip->i_size;
}
- } else {
- prealloced = 0;
- fixlen = 1LL << 32;
}
if (bmv->bmv_length == -1) {
fixlen = XFS_FSB_TO_BB(mp, XFS_B_TO_FSB(mp, fixlen));
- bmv->bmv_length = MAX( (__int64_t)(fixlen - bmv->bmv_offset),
- (__int64_t)0);
- } else if (bmv->bmv_length < 0)
- return XFS_ERROR(EINVAL);
- if (bmv->bmv_length == 0) {
+ bmv->bmv_length =
+ max_t(__int64_t, fixlen - bmv->bmv_offset, 0);
+ } else if (bmv->bmv_length == 0) {
bmv->bmv_entries = 0;
return 0;
+ } else if (bmv->bmv_length < 0) {
+ return XFS_ERROR(EINVAL);
}
+
nex = bmv->bmv_count - 1;
if (nex <= 0)
return XFS_ERROR(EINVAL);
bmvend = bmv->bmv_offset + bmv->bmv_length;
- xfs_ilock(ip, XFS_IOLOCK_SHARED);
- if (((iflags & BMV_IF_DELALLOC) == 0) &&
- (whichfork == XFS_DATA_FORK) &&
- (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size)) {
- /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */
- error = xfs_flush_pages(ip, (xfs_off_t)0,
- -1, 0, FI_REMAPF);
- if (error) {
- xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- return error;
+ if (bmv->bmv_count > ULONG_MAX / sizeof(struct getbmapx))
+ return XFS_ERROR(ENOMEM);
+ out = kmem_zalloc(bmv->bmv_count * sizeof(struct getbmapx), KM_MAYFAIL);
+ if (!out)
+ return XFS_ERROR(ENOMEM);
+
+ xfs_ilock(ip, XFS_IOLOCK_SHARED);
+ if (whichfork == XFS_DATA_FORK && !(iflags & BMV_IF_DELALLOC)) {
+ if (ip->i_delayed_blks || ip->i_size > ip->i_d.di_size) {
+ error = xfs_flush_pages(ip, 0, -1, 0, FI_REMAPF);
+ if (error)
+ goto out_unlock_iolock;
}
- }
- ASSERT(whichfork == XFS_ATTR_FORK || (iflags & BMV_IF_DELALLOC) ||
- ip->i_delayed_blks == 0);
+ ASSERT(ip->i_delayed_blks == 0);
+ }
lock = xfs_ilock_map_shared(ip);
if (nex > XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1)
nex = XFS_IFORK_NEXTENTS(ip, whichfork) * 2 + 1;
- bmapi_flags = xfs_bmapi_aflag(whichfork) |
- ((iflags & BMV_IF_PREALLOC) ? 0 : XFS_BMAPI_IGSTATE);
+ bmapi_flags = xfs_bmapi_aflag(whichfork);
+ if (!(iflags & BMV_IF_PREALLOC))
+ bmapi_flags |= XFS_BMAPI_IGSTATE;
/*
* Allocate enough space to handle "subnex" maps at a time.
*/
+ error = ENOMEM;
subnex = 16;
- map = kmem_alloc(subnex * sizeof(*map), KM_SLEEP);
+ map = kmem_alloc(subnex * sizeof(*map), KM_MAYFAIL);
+ if (!map)
+ goto out_unlock_ilock;
bmv->bmv_entries = 0;
- if ((XFS_IFORK_NEXTENTS(ip, whichfork) == 0)) {
- if (((iflags & BMV_IF_DELALLOC) == 0) ||
- whichfork == XFS_ATTR_FORK) {
- error = 0;
- goto unlock_and_return;
- }
+ if (XFS_IFORK_NEXTENTS(ip, whichfork) == 0 &&
+ (whichfork == XFS_ATTR_FORK || !(iflags & BMV_IF_DELALLOC))) {
+ error = 0;
+ goto out_free_map;
}
nexleft = nex;
bmapi_flags, NULL, 0, map, &nmap,
NULL, NULL);
if (error)
- goto unlock_and_return;
+ goto out_free_map;
ASSERT(nmap <= subnex);
for (i = 0; i < nmap && nexleft && bmv->bmv_length; i++) {
- out.bmv_oflags = 0;
+ out[cur_ext].bmv_oflags = 0;
if (map[i].br_state == XFS_EXT_UNWRITTEN)
- out.bmv_oflags |= BMV_OF_PREALLOC;
+ out[cur_ext].bmv_oflags |= BMV_OF_PREALLOC;
else if (map[i].br_startblock == DELAYSTARTBLOCK)
- out.bmv_oflags |= BMV_OF_DELALLOC;
- out.bmv_offset = XFS_FSB_TO_BB(mp, map[i].br_startoff);
- out.bmv_length = XFS_FSB_TO_BB(mp, map[i].br_blockcount);
- out.bmv_unused1 = out.bmv_unused2 = 0;
+ out[cur_ext].bmv_oflags |= BMV_OF_DELALLOC;
+ out[cur_ext].bmv_offset =
+ XFS_FSB_TO_BB(mp, map[i].br_startoff);
+ out[cur_ext].bmv_length =
+ XFS_FSB_TO_BB(mp, map[i].br_blockcount);
+ out[cur_ext].bmv_unused1 = 0;
+ out[cur_ext].bmv_unused2 = 0;
ASSERT(((iflags & BMV_IF_DELALLOC) != 0) ||
(map[i].br_startblock != DELAYSTARTBLOCK));
if (map[i].br_startblock == HOLESTARTBLOCK &&
whichfork == XFS_ATTR_FORK) {
/* came to the end of attribute fork */
- out.bmv_oflags |= BMV_OF_LAST;
- goto unlock_and_return;
- } else {
- int full = 0; /* user array is full */
-
- if (!xfs_getbmapx_fix_eof_hole(ip, &out,
- prealloced, bmvend,
- map[i].br_startblock)) {
- goto unlock_and_return;
- }
-
- /* format results & advance arg */
- error = formatter(&arg, &out, &full);
- if (error || full)
- goto unlock_and_return;
- nexleft--;
- bmv->bmv_offset =
- out.bmv_offset + out.bmv_length;
- bmv->bmv_length = MAX((__int64_t)0,
- (__int64_t)(bmvend - bmv->bmv_offset));
- bmv->bmv_entries++;
+ out[cur_ext].bmv_oflags |= BMV_OF_LAST;
+ goto out_free_map;
}
+
+ if (!xfs_getbmapx_fix_eof_hole(ip, &out[cur_ext],
+ prealloced, bmvend,
+ map[i].br_startblock))
+ goto out_free_map;
+
+ nexleft--;
+ bmv->bmv_offset =
+ out[cur_ext].bmv_offset +
+ out[cur_ext].bmv_length;
+ bmv->bmv_length =
+ max_t(__int64_t, 0, bmvend - bmv->bmv_offset);
+ bmv->bmv_entries++;
+ cur_ext++;
}
} while (nmap && nexleft && bmv->bmv_length);
-unlock_and_return:
+ out_free_map:
+ kmem_free(map);
+ out_unlock_ilock:
xfs_iunlock_map_shared(ip, lock);
+ out_unlock_iolock:
xfs_iunlock(ip, XFS_IOLOCK_SHARED);
- kmem_free(map);
+ for (i = 0; i < cur_ext; i++) {
+ int full = 0; /* user array is full */
+
+ /* format results & advance arg */
+ error = formatter(&arg, &out[i], &full);
+ if (error || full)
+ break;
+ }
return error;
}
* necessary.
*/
if (ip->i_df.if_flags & XFS_IFEXTENTS) {
+ xfs_ilock(ip, XFS_ILOCK_SHARED);
error = xfs_bmap_last_offset(NULL, ip, &last_block,
XFS_DATA_FORK);
+ xfs_iunlock(ip, XFS_ILOCK_SHARED);
if (error) {
last_block = 0;
}
sbp->sb_sectsize > XFS_MAX_SECTORSIZE ||
sbp->sb_sectlog < XFS_MIN_SECTORSIZE_LOG ||
sbp->sb_sectlog > XFS_MAX_SECTORSIZE_LOG ||
+ sbp->sb_sectsize != (1 << sbp->sb_sectlog) ||
sbp->sb_blocksize < XFS_MIN_BLOCKSIZE ||
sbp->sb_blocksize > XFS_MAX_BLOCKSIZE ||
sbp->sb_blocklog < XFS_MIN_BLOCKSIZE_LOG ||
sbp->sb_blocklog > XFS_MAX_BLOCKSIZE_LOG ||
+ sbp->sb_blocksize != (1 << sbp->sb_blocklog) ||
sbp->sb_inodesize < XFS_DINODE_MIN_SIZE ||
sbp->sb_inodesize > XFS_DINODE_MAX_SIZE ||
sbp->sb_inodelog < XFS_DINODE_MIN_LOG ||
sbp->sb_inodelog > XFS_DINODE_MAX_LOG ||
+ sbp->sb_inodesize != (1 << sbp->sb_inodelog) ||
(sbp->sb_blocklog - sbp->sb_inodelog != sbp->sb_inopblog) ||
(sbp->sb_rextsize * sbp->sb_blocksize > XFS_MAX_RTEXTSIZE) ||
(sbp->sb_rextsize * sbp->sb_blocksize < XFS_MIN_RTEXTSIZE) ||
#define atomic_long_inc_not_zero(l) atomic64_inc_not_zero((atomic64_t *)(l))
#define atomic_long_cmpxchg(l, old, new) \
- (atomic_cmpxchg((atomic64_t *)(l), (old), (new)))
+ (atomic64_cmpxchg((atomic64_t *)(l), (old), (new)))
#define atomic_long_xchg(v, new) \
- (atomic_xchg((atomic64_t *)(l), (new)))
+ (atomic64_xchg((atomic64_t *)(l), (new)))
#else /* BITS_PER_LONG == 64 */
*/
#ifndef __WARN
#ifndef __ASSEMBLY__
-extern void warn_slowpath(const char *file, const int line,
+extern void warn_slowpath_fmt(const char *file, const int line,
const char *fmt, ...) __attribute__((format(printf, 3, 4)));
+extern void warn_slowpath_null(const char *file, const int line);
#define WANT_WARN_ON_SLOWPATH
#endif
-#define __WARN() warn_slowpath(__FILE__, __LINE__, NULL)
-#define __WARN_printf(arg...) warn_slowpath(__FILE__, __LINE__, arg)
+#define __WARN() warn_slowpath_null(__FILE__, __LINE__)
+#define __WARN_printf(arg...) warn_slowpath_fmt(__FILE__, __LINE__, arg)
#else
#define __WARN_printf(arg...) do { printk(arg); __WARN(); } while (0)
#endif
int hasvdso;
};
-extern int register_binfmt(struct linux_binfmt *);
+extern int __register_binfmt(struct linux_binfmt *fmt, int insert);
+
+/* Registration of default binfmt handlers */
+static inline int register_binfmt(struct linux_binfmt *fmt)
+{
+ return __register_binfmt(fmt, 0);
+}
+/* Same as above, but adds a new binfmt at the top of the list */
+static inline int insert_binfmt(struct linux_binfmt *fmt)
+{
+ return __register_binfmt(fmt, 1);
+}
+
extern void unregister_binfmt(struct linux_binfmt *);
extern int prepare_binprm(struct linux_binprm *);
blk_failfast_driver(rq))
#define blk_rq_started(rq) ((rq)->cmd_flags & REQ_STARTED)
#define blk_rq_io_stat(rq) ((rq)->cmd_flags & REQ_IO_STAT)
+#define blk_rq_quiet(rq) ((rq)->cmd_flags & REQ_QUIET)
#define blk_account_rq(rq) (blk_rq_started(rq) && (blk_fs_request(rq) || blk_discard_rq(rq)))
#define SYN_REPORT 0
#define SYN_CONFIG 1
+#define SYN_MT_REPORT 2
/*
* Keys and buttons
#define BTN_STYLUS2 0x14c
#define BTN_TOOL_DOUBLETAP 0x14d
#define BTN_TOOL_TRIPLETAP 0x14e
+#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */
#define BTN_WHEEL 0x150
#define BTN_GEAR_DOWN 0x150
#define ABS_TOOL_WIDTH 0x1c
#define ABS_VOLUME 0x20
#define ABS_MISC 0x28
+
+#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */
+#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */
+#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */
+#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */
+#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */
+#define ABS_MT_POSITION_X 0x35 /* Center X ellipse position */
+#define ABS_MT_POSITION_Y 0x36 /* Center Y ellipse position */
+#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */
+#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */
+
#define ABS_MAX 0x3f
#define ABS_CNT (ABS_MAX+1)
#define BUS_GSC 0x1A
#define BUS_ATARI 0x1B
+/*
+ * MT_TOOL types
+ */
+#define MT_TOOL_FINGER 0
+#define MT_TOOL_PEN 1
+
/*
* Values describing the status of a force-feedback effect
*/
input_event(dev, EV_SYN, SYN_REPORT, 0);
}
+static inline void input_mt_sync(struct input_dev *dev)
+{
+ input_event(dev, EV_SYN, SYN_MT_REPORT, 0);
+}
+
void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code);
static inline void input_set_abs_params(struct input_dev *dev, int axis, int min, int max, int fuzz, int flat)
enum lru_list from, enum lru_list to);
extern void mem_cgroup_uncharge_page(struct page *page);
extern void mem_cgroup_uncharge_cache_page(struct page *page);
-extern int mem_cgroup_shrink_usage(struct page *page,
+extern int mem_cgroup_shmem_charge_fallback(struct page *page,
struct mm_struct *mm, gfp_t gfp_mask);
extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan,
{
}
-static inline int mem_cgroup_shrink_usage(struct page *page,
+static inline int mem_cgroup_shmem_charge_fallback(struct page *page,
struct mm_struct *mm, gfp_t gfp_mask)
{
return 0;
#ifdef __KERNEL__
#include <linux/mm.h>
+#include <linux/percpu_counter.h>
#include <asm/atomic.h>
extern int sysctl_overcommit_memory;
extern int sysctl_overcommit_ratio;
-extern atomic_long_t vm_committed_space;
+extern struct percpu_counter vm_committed_as;
-#ifdef CONFIG_SMP
-extern void vm_acct_memory(long pages);
-#else
static inline void vm_acct_memory(long pages)
{
- atomic_long_add(pages, &vm_committed_space);
+ percpu_counter_add(&vm_committed_as, pages);
}
-#endif
static inline void vm_unacct_memory(long pages)
{
local_bh_disable();
lock = &__get_cpu_var(xt_info_locks);
- if (!lock->readers++)
+ if (likely(!lock->readers++))
spin_lock(&lock->lock);
}
{
struct xt_info_lock *lock = &__get_cpu_var(xt_info_locks);
- if (!--lock->readers)
+ if (likely(!--lock->readers))
spin_unlock(&lock->lock);
local_bh_enable();
}
return 0;
}
+/*
+ * nls_nullsize - return length of null character for codepage
+ * @codepage - codepage for which to return length of NULL terminator
+ *
+ * Since we can't guarantee that the null terminator will be a particular
+ * length, we have to check against the codepage. If there's a problem
+ * determining it, assume a single-byte NULL terminator.
+ */
+static inline int
+nls_nullsize(const struct nls_table *codepage)
+{
+ int charlen;
+ char tmp[NLS_MAX_CHARSET_SIZE];
+
+ charlen = codepage->uni2char(0, tmp, NLS_MAX_CHARSET_SIZE);
+
+ return charlen > 0 ? charlen : 1;
+}
+
#define MODULE_ALIAS_NLS(name) MODULE_ALIAS("nls_" __stringify(name))
#endif /* _LINUX_NLS_H */
struct bus_type *bus);
extern void of_unregister_driver(struct of_platform_driver *drv);
+/* Platform drivers register/unregister */
+static inline int of_register_platform_driver(struct of_platform_driver *drv)
+{
+ return of_register_driver(drv, &of_platform_bus_type);
+}
+static inline void of_unregister_platform_driver(struct of_platform_driver *drv)
+{
+ of_unregister_driver(drv);
+}
+
#include <asm/of_platform.h>
extern struct of_device *of_find_device_by_node(struct device_node *np);
#define XPRT_BINDING (5)
#define XPRT_CLOSING (6)
#define XPRT_CONNECTION_ABORT (7)
+#define XPRT_CONNECTION_CLOSE (8)
static inline void xprt_set_connected(struct rpc_xprt *xprt)
{
#define USB_CDC_SUBCLASS_DMM 0x09
#define USB_CDC_SUBCLASS_MDLM 0x0a
#define USB_CDC_SUBCLASS_OBEX 0x0b
+#define USB_CDC_SUBCLASS_EEM 0x0c
#define USB_CDC_PROTO_NONE 0
#define USB_CDC_ACM_PROTO_AT_CDMA 6
#define USB_CDC_ACM_PROTO_VENDOR 0xff
+#define USB_CDC_PROTO_EEM 7
+
/*-------------------------------------------------------------------------*/
/*
* compatible drivers/servers. */
#include <linux/types.h>
#include <linux/virtio_config.h>
+#include <linux/if_ether.h>
/* The ID for virtio_net */
#define VIRTIO_ID_NET 1
struct p9_req_t {
int status;
int t_err;
- u16 flush_tag;
wait_queue_head_t *wq;
struct p9_fcall *tc;
struct p9_fcall *rc;
int hci_register_sysfs(struct hci_dev *hdev);
void hci_unregister_sysfs(struct hci_dev *hdev);
+void hci_conn_init_sysfs(struct hci_conn *conn);
void hci_conn_add_sysfs(struct hci_conn *conn);
void hci_conn_del_sysfs(struct hci_conn *conn);
#include <net/ip.h>
#include <net/tcp_states.h>
#include <net/inet_ecn.h>
+#include <net/dst.h>
#include <linux/seq_file.h>
tcp_fast_path_on(tp);
}
+/* Compute the actual rto_min value */
+static inline u32 tcp_rto_min(struct sock *sk)
+{
+ struct dst_entry *dst = __sk_dst_get(sk);
+ u32 rto_min = TCP_RTO_MIN;
+
+ if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
+ rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN);
+ return rto_min;
+}
+
/* Compute the actual receive window we are currently advertising.
* Rcv_nxt can be after the window if our peer push more data
* than the offered window.
wake_up_interruptible(sk->sk_sleep);
if (!inet_csk_ack_scheduled(sk))
inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK,
- (3 * TCP_RTO_MIN) / 4,
+ (3 * tcp_rto_min(sk)) / 4,
TCP_RTO_MAX);
}
return 1;
* Well-known fabric addresses.
*/
enum fc_well_known_fid {
+ FC_FID_NONE = 0x000000, /* No destination */
FC_FID_BCAST = 0xffffff, /* broadcast */
FC_FID_FLOGI = 0xfffffe, /* fabric login */
FC_FID_FCTRL = 0xfffffd, /* fabric controller */
enum fc_disc_event);
struct list_head rports;
+ struct list_head rogue_rports;
struct fc_lport *lport;
struct mutex disc_mutex;
struct fc_gpn_ft_resp partial_buf; /* partial name buffer */
struct scsi_host_template;
struct scsi_device;
struct Scsi_Host;
+struct scsi_target;
struct scsi_cmnd;
struct socket;
struct iscsi_transport;
bool xmit_can_sleep);
extern void iscsi_host_remove(struct Scsi_Host *shost);
extern void iscsi_host_free(struct Scsi_Host *shost);
+extern int iscsi_target_alloc(struct scsi_target *starget);
/*
* session management
OSDv1_ADDITIONAL_CDB_LENGTH = 192,
OSDv1_TOTAL_CDB_LEN = OSDv1_ADDITIONAL_CDB_LENGTH + 8,
OSDv1_CAP_LEN = 80,
+
/* Latest supported version */
-/* OSD_ADDITIONAL_CDB_LENGTH = 216,*/
+ OSDv2_ADDITIONAL_CDB_LENGTH = 228,
OSD_ADDITIONAL_CDB_LENGTH =
- OSDv1_ADDITIONAL_CDB_LENGTH, /* FIXME: Pete rev-001 sup */
+ OSDv2_ADDITIONAL_CDB_LENGTH,
OSD_TOTAL_CDB_LEN = OSD_ADDITIONAL_CDB_LENGTH + 8,
-/* OSD_CAP_LEN = 104,*/
- OSD_CAP_LEN = OSDv1_CAP_LEN,/* FIXME: Pete rev-001 sup */
+ OSD_CAP_LEN = 104,
OSD_SYSTEMID_LEN = 20,
- OSD_CRYPTO_KEYID_SIZE = 20,
- /*FIXME: OSDv2_CRYPTO_KEYID_SIZE = 32,*/
+ OSDv1_CRYPTO_KEYID_SIZE = 20,
+ OSDv2_CRYPTO_KEYID_SIZE = 32,
+ OSD_CRYPTO_KEYID_SIZE = OSDv2_CRYPTO_KEYID_SIZE,
OSD_CRYPTO_SEED_SIZE = 4,
OSD_CRYPTO_NONCE_SIZE = 12,
OSD_MAX_SENSE_LEN = 252, /* from SPC-3 */
/* called allocation_length in some commands */
/*32*/ __be64 length;
/*40*/ __be64 start_address;
-/*48*/ __be32 list_identifier;/* Rarely used */
+ union {
+/*48*/ __be32 list_identifier;/* Rarely used */
+ /* OSD2r05 5.2.5 CDB continuation length */
+/*48*/ __be32 cdb_continuation_length;
+ };
} __packed v2;
};
/*52*/ union { /* selected attributes mode Page/List/Single */
/*80*/
/*160 v1*/
-/*184 v2*/
-struct osd_security_parameters {
-/*160*/u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
+struct osdv1_security_parameters {
+/*160*/u8 integrity_check_value[OSDv1_CRYPTO_KEYID_SIZE];
/*180*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE];
/*192*/osd_cdb_offset data_in_integrity_check_offset;
/*196*/osd_cdb_offset data_out_integrity_check_offset;
} __packed;
/*200 v1*/
-/*224 v2*/
-/* FIXME: osdv2_security_parameters */
+/*184 v2*/
+struct osdv2_security_parameters {
+/*184*/u8 integrity_check_value[OSDv2_CRYPTO_KEYID_SIZE];
+/*216*/u8 request_nonce[OSD_CRYPTO_NONCE_SIZE];
+/*228*/osd_cdb_offset data_in_integrity_check_offset;
+/*232*/osd_cdb_offset data_out_integrity_check_offset;
+} __packed;
+/*236 v2*/
+
+struct osd_security_parameters {
+ union {
+ struct osdv1_security_parameters v1;
+ struct osdv2_security_parameters v2;
+ };
+};
struct osdv1_cdb {
struct osd_cdb_head h;
u8 caps[OSDv1_CAP_LEN];
- struct osd_security_parameters sec_params;
+ struct osdv1_security_parameters sec_params;
} __packed;
struct osdv2_cdb {
struct osd_cdb_head h;
u8 caps[OSD_CAP_LEN];
- struct osd_security_parameters sec_params;
- /* FIXME: osdv2_security_parameters */
+ struct osdv2_security_parameters sec_params;
} __packed;
struct osd_cdb {
__be32 attr_id;
} __packed;
+/*
+ * NOTE: v1: is not aligned.
+ */
+struct osdv1_attributes_list_element {
+ __be32 attr_page;
+ __be32 attr_id;
+ __be16 attr_bytes; /* valid bytes at attr_val without padding */
+ u8 attr_val[0];
+} __packed;
+
/*
* osd2r03: 7.1.3.3 List entry format for retrieved attributes and
* for setting attributes
- * NOTE: v2 is 8-bytes aligned, v1 is not aligned.
+ * NOTE: v2 is 8-bytes aligned
*/
-struct osd_attributes_list_element {
+struct osdv2_attributes_list_element {
__be32 attr_page;
__be32 attr_id;
- __be16 attr_bytes;
+ u8 reserved[6];
+ __be16 attr_bytes; /* valid bytes at attr_val without padding */
u8 attr_val[0];
} __packed;
static inline unsigned osdv1_attr_list_elem_size(unsigned len)
{
- return ALIGN(len + sizeof(struct osd_attributes_list_element),
+ return ALIGN(len + sizeof(struct osdv1_attributes_list_element),
OSDv1_ATTRIBUTES_ELEM_ALIGN);
}
static inline unsigned osdv2_attr_list_elem_size(unsigned len)
{
- return ALIGN(len + sizeof(struct osd_attributes_list_element),
+ return ALIGN(len + sizeof(struct osdv2_attributes_list_element),
OSD_ATTRIBUTES_ELEM_ALIGN);
}
__be64 data_bytes;
__be64 set_attributes_bytes;
__be64 get_attributes_bytes;
- __be64 integrity_check_value;
+ __u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
} __packed;
+/* Same osd_data_out_integrity_info is used for OSD2/OSD1. The only difference
+ * Is the sizeof the structure since in OSD1 the last array is smaller. Use
+ * below for version independent handling of this structure
+ */
+static inline int osd_data_out_integrity_info_sizeof(bool is_ver1)
+{
+ return sizeof(struct osd_data_out_integrity_info) -
+ (is_ver1 * (OSDv2_CRYPTO_KEYID_SIZE - OSDv1_CRYPTO_KEYID_SIZE));
+}
+
struct osd_data_in_integrity_info {
__be64 data_bytes;
__be64 retrieved_attributes_bytes;
- __be64 integrity_check_value;
+ __u8 integrity_check_value[OSD_CRYPTO_KEYID_SIZE];
} __packed;
+/* Same osd_data_in_integrity_info is used for OSD2/OSD1. The only difference
+ * Is the sizeof the structure since in OSD1 the last array is smaller. Use
+ * below for version independent handling of this structure
+ */
+static inline int osd_data_in_integrity_info_sizeof(bool is_ver1)
+{
+ return sizeof(struct osd_data_in_integrity_info) -
+ (is_ver1 * (OSDv2_CRYPTO_KEYID_SIZE - OSDv1_CRYPTO_KEYID_SIZE));
+}
+
struct osd_timestamp {
u8 time[6]; /* number of milliseconds since 1/1/1970 UT (big endian) */
} __packed;
OSD_SEC_CAP_NONE1 = BIT(8),
OSD_SEC_CAP_NONE2 = BIT(9),
- OSD_SEC_CAP_NONE3 = BIT(10),
+ OSD_SEC_GBL_REM = BIT(10), /*v2 only*/
OSD_SEC_CAP_QUERY = BIT(11), /*v2 only*/
OSD_SEC_CAP_M_OBJECT = BIT(12), /*v2 only*/
OSD_SEC_CAP_POL_SEC = BIT(13),
struct osd_capability {
struct osd_capability_head h;
-/* struct osd_cap_object_descriptor od;*/
- struct osdv1_cap_object_descriptor od; /* FIXME: Pete rev-001 sup */
+ struct osd_cap_object_descriptor od;
} __packed;
/**
if (initrd_start) {
#ifdef CONFIG_BLK_DEV_RAM
int fd;
- printk(KERN_INFO "checking if image is initramfs...\n");
+ printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
err = unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start);
if (!err) {
- printk(KERN_INFO "rootfs image is initramfs; unpacking...\n");
free_initrd();
return 0;
} else {
free_initrd();
}
#else
- printk(KERN_INFO "Unpacking initramfs...");
+ printk(KERN_INFO "Unpacking initramfs...\n");
err = unpack_to_rootfs((char *)initrd_start,
initrd_end - initrd_start);
- if (err) {
- printk(" failed!\n");
- printk(KERN_EMERG "%s\n", err);
- } else {
- printk(" done\n");
- }
+ if (err)
+ printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
free_initrd();
#endif
}
if (audit_enabled) {
struct audit_buffer *ab;
- ab = audit_log_start(NULL, GFP_KERNEL,
+ ab = audit_log_start(NULL, GFP_NOFS,
AUDIT_CONFIG_CHANGE);
audit_log_format(ab, "auid=%u ses=%u",
audit_get_loginuid(current),
e = container_of(r, struct audit_entry, rule);
if (audit_enabled) {
struct audit_buffer *ab;
- ab = audit_log_start(NULL, GFP_KERNEL,
+ ab = audit_log_start(NULL, GFP_NOFS,
AUDIT_CONFIG_CHANGE);
audit_log_format(ab, "auid=%u ses=%u",
audit_get_loginuid(current),
irqreturn_t ret, retval = IRQ_NONE;
unsigned int status = 0;
- WARN_ONCE(!in_irq(), "BUG: IRQ handler called from non-hardirq context!");
-
if (!(action->flags & IRQF_DISABLED))
local_irq_enable_in_hardirq();
return NULL;
}
+/* Arm a kprobe with text_mutex */
+static void __kprobes arm_kprobe(struct kprobe *kp)
+{
+ mutex_lock(&text_mutex);
+ arch_arm_kprobe(kp);
+ mutex_unlock(&text_mutex);
+}
+
+/* Disarm a kprobe with text_mutex */
+static void __kprobes disarm_kprobe(struct kprobe *kp)
+{
+ mutex_lock(&text_mutex);
+ arch_disarm_kprobe(kp);
+ mutex_unlock(&text_mutex);
+}
+
/*
* Aggregate handlers for multiple kprobes support - these handlers
* take care of invoking the individual kprobe handlers on p->list
ap->flags &= ~KPROBE_FLAG_DISABLED;
if (!kprobes_all_disarmed)
/* Arm the breakpoint again. */
- arch_arm_kprobe(ap);
+ arm_kprobe(ap);
}
return 0;
}
* enabled and not gone - otherwise, the breakpoint would
* already have been removed. We save on flushing icache.
*/
- if (!kprobes_all_disarmed && !kprobe_disabled(old_p)) {
- mutex_lock(&text_mutex);
- arch_disarm_kprobe(p);
- mutex_unlock(&text_mutex);
- }
+ if (!kprobes_all_disarmed && !kprobe_disabled(old_p))
+ disarm_kprobe(p);
hlist_del_rcu(&old_p->hlist);
} else {
if (p->break_handler && !kprobe_gone(p))
if (!kprobe_disabled(old_p)) {
try_to_disable_aggr_kprobe(old_p);
if (!kprobes_all_disarmed && kprobe_disabled(old_p))
- arch_disarm_kprobe(old_p);
+ disarm_kprobe(old_p);
}
}
return 0;
try_to_disable_aggr_kprobe(p);
if (!kprobes_all_disarmed && kprobe_disabled(p))
- arch_disarm_kprobe(p);
+ disarm_kprobe(p);
out:
mutex_unlock(&kprobe_mutex);
return ret;
}
if (!kprobes_all_disarmed && kprobe_disabled(p))
- arch_arm_kprobe(p);
+ arm_kprobe(p);
p->flags &= ~KPROBE_FLAG_DISABLED;
if (p != kp)
}
#ifdef WANT_WARN_ON_SLOWPATH
-void warn_slowpath(const char *file, int line, const char *fmt, ...)
+void warn_slowpath_fmt(const char *file, int line, const char *fmt, ...)
{
va_list args;
char function[KSYM_SYMBOL_LEN];
if (board)
printk(KERN_WARNING "Hardware name: %s\n", board);
- if (fmt) {
+ if (*fmt) {
va_start(args, fmt);
vprintk(fmt, args);
va_end(args);
print_oops_end_marker();
add_taint(TAINT_WARN);
}
-EXPORT_SYMBOL(warn_slowpath);
+EXPORT_SYMBOL(warn_slowpath_fmt);
+
+void warn_slowpath_null(const char *file, int line)
+{
+ static const char *empty = "";
+ warn_slowpath_fmt(file, line, empty);
+}
+EXPORT_SYMBOL(warn_slowpath_null);
#endif
#ifdef CONFIG_CC_STACKPROTECTOR
* timer call will interfere.
*/
list_for_each_entry_safe(timer, next, &firing, it.cpu.entry) {
- int firing;
+ int cpu_firing;
+
spin_lock(&timer->it_lock);
list_del_init(&timer->it.cpu.entry);
- firing = timer->it.cpu.firing;
+ cpu_firing = timer->it.cpu.firing;
timer->it.cpu.firing = 0;
/*
* The firing flag is -1 if we collided with a reset
* of the timer, which already reported this
* almost-firing as an overrun. So don't generate an event.
*/
- if (likely(firing >= 0)) {
+ if (likely(cpu_firing >= 0))
cpu_timer_fire(timer);
- }
spin_unlock(&timer->it_lock);
}
}
if (user_tick)
account_user_time(p, one_jiffy, one_jiffy_scaled);
- else if (p != rq->idle)
+ else if ((p != rq->idle) || (irq_count() != HARDIRQ_OFFSET))
account_system_time(p, HARDIRQ_OFFSET, one_jiffy,
one_jiffy_scaled);
else
static int one_hundred = 100;
static int one_thousand = 1000;
+/* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */
+static unsigned long dirty_bytes_min = 2 * PAGE_SIZE;
+
/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
static int maxolduid = 65535;
static int minolduid;
.mode = 0644,
.proc_handler = &dirty_bytes_handler,
.strategy = &sysctl_intvec,
- .extra1 = &one_ul,
+ .extra1 = &dirty_bytes_min,
},
{
.procname = "dirty_writeback_centisecs",
for (;;) {
if (!clockevents_program_event(dev, next, ktime_get()))
return;
- tick_periodic(cpu);
+ /*
+ * Have to be careful here. If we're in oneshot mode,
+ * before we call tick_periodic() in a loop, we need
+ * to be sure we're using a real hardware clocksource.
+ * Otherwise we could get trapped in an infinite
+ * loop, as the tick_periodic() increments jiffies,
+ * when then will increment time, posibly causing
+ * the loop to trigger again and again.
+ */
+ if (timekeeping_valid_for_hres())
+ tick_periodic(cpu);
next = ktime_add(next, tick_period);
}
}
if (!ref)
break;
+ ref->ref = 1;
ref->buffer = info->tr->buffer;
ref->page = ring_buffer_alloc_read_page(ref->buffer);
if (!ref->page) {
return -ENOMEM;
}
-static int device_dma_allocations(struct device *dev)
-{
- struct dma_debug_entry *entry;
- unsigned long flags;
- int count = 0, i;
-
- for (i = 0; i < HASH_SIZE; ++i) {
- spin_lock_irqsave(&dma_entry_hash[i].lock, flags);
- list_for_each_entry(entry, &dma_entry_hash[i].list, list) {
- if (entry->dev == dev)
- count += 1;
- }
- spin_unlock_irqrestore(&dma_entry_hash[i].lock, flags);
- }
-
- return count;
-}
-
-static int dma_debug_device_change(struct notifier_block *nb,
- unsigned long action, void *data)
-{
- struct device *dev = data;
- int count;
-
-
- switch (action) {
- case BUS_NOTIFY_UNBIND_DRIVER:
- count = device_dma_allocations(dev);
- if (count == 0)
- break;
- err_printk(dev, NULL, "DMA-API: device driver has pending "
- "DMA allocations while released from device "
- "[count=%d]\n", count);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
void dma_debug_add_bus(struct bus_type *bus)
{
- struct notifier_block *nb;
-
- nb = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
- if (nb == NULL) {
- printk(KERN_ERR "dma_debug_add_bus: out of memory\n");
- return;
- }
-
- nb->notifier_call = dma_debug_device_change;
-
- bus_register_notifier(bus, nb);
+ /* FIXME: register notifier */
}
/*
config MMU_NOTIFIER
bool
+
+config NOMMU_INITIAL_TRIM_EXCESS
+ int "Turn on mmap() excess space trimming before booting"
+ depends on !MMU
+ default 1
+ help
+ The NOMMU mmap() frequently needs to allocate large contiguous chunks
+ of memory on which to store mappings, but it can only ask the system
+ allocator for chunks in 2^N*PAGE_SIZE amounts - which is frequently
+ more than it requires. To deal with this, mmap() is able to trim off
+ the excess and return it to the allocator.
+
+ If trimming is enabled, the excess is trimmed off and returned to the
+ system allocator, which can cause extra fragmentation, particularly
+ if there are a lot of transient processes.
+
+ If trimming is disabled, the excess is kept, but not used, which for
+ long-term mappings means that the space is wasted.
+
+ Trimming can be dynamically controlled through a sysctl option
+ (/proc/sys/vm/nr_trim_pages) which specifies the minimum number of
+ excess pages there must be before trimming should occur, or zero if
+ no trimming is to occur.
+
+ This option specifies the initial value of this option. The default
+ of 1 says that all excess pages should be trimmed.
+
+ See Documentation/nommu-mmap.txt for more information.
if (!file)
return -EBADF;
+ /*
+ * Page cache readahead assumes page cache pages are order-0 which
+ * is not the case for hugetlbfs. Do not give a bad return value
+ * but ignore the advice.
+ */
+ if (vma->vm_flags & VM_HUGETLB)
+ return 0;
+
if (file->f_mapping->a_ops->get_xip_mem) {
/* no bad return value, but ignore advice */
return 0;
return NULL;
pc = lookup_page_cgroup(page);
- /*
- * Used bit of swapcache is solid under page lock.
- */
+ lock_page_cgroup(pc);
if (PageCgroupUsed(pc)) {
mem = pc->mem_cgroup;
if (mem && !css_tryget(&mem->css))
mem = NULL;
rcu_read_unlock();
}
+ unlock_page_cgroup(pc);
return mem;
}
}
/*
- * A call to try to shrink memory usage under specified resource controller.
- * This is typically used for page reclaiming for shmem for reducing side
- * effect of page allocation from shmem, which is used by some mem_cgroup.
+ * A call to try to shrink memory usage on charge failure at shmem's swapin.
+ * Calling hierarchical_reclaim is not enough because we should update
+ * last_oom_jiffies to prevent pagefault_out_of_memory from invoking global OOM.
+ * Moreover considering hierarchy, we should reclaim from the mem_over_limit,
+ * not from the memcg which this page would be charged to.
+ * try_charge_swapin does all of these works properly.
*/
-int mem_cgroup_shrink_usage(struct page *page,
+int mem_cgroup_shmem_charge_fallback(struct page *page,
struct mm_struct *mm,
gfp_t gfp_mask)
{
struct mem_cgroup *mem = NULL;
- int progress = 0;
- int retry = MEM_CGROUP_RECLAIM_RETRIES;
+ int ret;
if (mem_cgroup_disabled())
return 0;
- if (page)
- mem = try_get_mem_cgroup_from_swapcache(page);
- if (!mem && mm)
- mem = try_get_mem_cgroup_from_mm(mm);
- if (unlikely(!mem))
- return 0;
- do {
- progress = mem_cgroup_hierarchical_reclaim(mem,
- gfp_mask, true, false);
- progress += mem_cgroup_check_under_limit(mem);
- } while (!progress && --retry);
+ ret = mem_cgroup_try_charge_swapin(mm, page, gfp_mask, &mem);
+ if (!ret)
+ mem_cgroup_cancel_charge_swapin(mem); /* it does !mem check */
- css_put(&mem->css);
- if (!retry)
- return -ENOMEM;
- return 0;
+ return ret;
}
static DEFINE_MUTEX(set_limit_mutex);
ret = tmp;
goto unwritable_page;
}
+ if (unlikely(!(tmp & VM_FAULT_LOCKED))) {
+ lock_page(old_page);
+ if (!old_page->mapping) {
+ ret = 0; /* retry the fault */
+ unlock_page(old_page);
+ goto unwritable_page;
+ }
+ } else
+ VM_BUG_ON(!PageLocked(old_page));
/*
* Since we dropped the lock we need to revalidate
*/
page_table = pte_offset_map_lock(mm, pmd, address,
&ptl);
- page_cache_release(old_page);
- if (!pte_same(*page_table, orig_pte))
+ if (!pte_same(*page_table, orig_pte)) {
+ unlock_page(old_page);
+ page_cache_release(old_page);
goto unlock;
+ }
page_mkwrite = 1;
}
unlock:
pte_unmap_unlock(page_table, ptl);
if (dirty_page) {
- if (vma->vm_file)
- file_update_time(vma->vm_file);
-
/*
* Yes, Virginia, this is actually required to prevent a race
* with clear_page_dirty_for_io() from clearing the page dirty
*
* do_no_page is protected similarly.
*/
- wait_on_page_locked(dirty_page);
- set_page_dirty_balance(dirty_page, page_mkwrite);
+ if (!page_mkwrite) {
+ wait_on_page_locked(dirty_page);
+ set_page_dirty_balance(dirty_page, page_mkwrite);
+ }
put_page(dirty_page);
+ if (page_mkwrite) {
+ struct address_space *mapping = dirty_page->mapping;
+
+ set_page_dirty(dirty_page);
+ unlock_page(dirty_page);
+ page_cache_release(dirty_page);
+ if (mapping) {
+ /*
+ * Some device drivers do not set page.mapping
+ * but still dirty their pages
+ */
+ balance_dirty_pages_ratelimited(mapping);
+ }
+ }
+
+ /* file_update_time outside page_lock */
+ if (vma->vm_file)
+ file_update_time(vma->vm_file);
}
return ret;
oom_free_new:
page_cache_release(new_page);
oom:
- if (old_page)
+ if (old_page) {
+ if (page_mkwrite) {
+ unlock_page(old_page);
+ page_cache_release(old_page);
+ }
page_cache_release(old_page);
+ }
return VM_FAULT_OOM;
unwritable_page:
if (mem_cgroup_try_charge_swapin(mm, page, GFP_KERNEL, &ptr)) {
ret = VM_FAULT_OOM;
- unlock_page(page);
- goto out;
+ goto out_page;
}
/*
out_nomap:
mem_cgroup_cancel_charge_swapin(ptr);
pte_unmap_unlock(page_table, ptl);
+out_page:
unlock_page(page);
page_cache_release(page);
return ret;
int tmp;
unlock_page(page);
- vmf.flags |= FAULT_FLAG_MKWRITE;
+ vmf.flags = FAULT_FLAG_WRITE|FAULT_FLAG_MKWRITE;
tmp = vma->vm_ops->page_mkwrite(vma, &vmf);
if (unlikely(tmp &
(VM_FAULT_ERROR | VM_FAULT_NOPAGE))) {
ret = tmp;
- anon = 1; /* no anon but release vmf.page */
- goto out_unlocked;
- }
- lock_page(page);
- /*
- * XXX: this is not quite right (racy vs
- * invalidate) to unlock and relock the page
- * like this, however a better fix requires
- * reworking page_mkwrite locking API, which
- * is better done later.
- */
- if (!page->mapping) {
- ret = 0;
- anon = 1; /* no anon but release vmf.page */
- goto out;
+ goto unwritable_page;
}
+ if (unlikely(!(tmp & VM_FAULT_LOCKED))) {
+ lock_page(page);
+ if (!page->mapping) {
+ ret = 0; /* retry the fault */
+ unlock_page(page);
+ goto unwritable_page;
+ }
+ } else
+ VM_BUG_ON(!PageLocked(page));
page_mkwrite = 1;
}
}
pte_unmap_unlock(page_table, ptl);
out:
- unlock_page(vmf.page);
-out_unlocked:
- if (anon)
- page_cache_release(vmf.page);
- else if (dirty_page) {
- if (vma->vm_file)
- file_update_time(vma->vm_file);
+ if (dirty_page) {
+ struct address_space *mapping = page->mapping;
- set_page_dirty_balance(dirty_page, page_mkwrite);
+ if (set_page_dirty(dirty_page))
+ page_mkwrite = 1;
+ unlock_page(dirty_page);
put_page(dirty_page);
+ if (page_mkwrite && mapping) {
+ /*
+ * Some device drivers do not set page.mapping but still
+ * dirty their pages
+ */
+ balance_dirty_pages_ratelimited(mapping);
+ }
+
+ /* file_update_time outside page_lock */
+ if (vma->vm_file)
+ file_update_time(vma->vm_file);
+ } else {
+ unlock_page(vmf.page);
+ if (anon)
+ page_cache_release(vmf.page);
}
return ret;
+
+unwritable_page:
+ page_cache_release(page);
+ return ret;
}
static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
int sysctl_overcommit_ratio = 50; /* default is 50% */
int sysctl_max_map_count __read_mostly = DEFAULT_MAX_MAP_COUNT;
-atomic_long_t vm_committed_space = ATOMIC_LONG_INIT(0);
+struct percpu_counter vm_committed_as;
/*
* Check that a process has enough memory to allocate a new virtual
if (mm)
allowed -= mm->total_vm / 32;
- /*
- * cast `allowed' as a signed long because vm_committed_space
- * sometimes has a negative value
- */
- if (atomic_long_read(&vm_committed_space) < (long)allowed)
+ if (percpu_counter_read_positive(&vm_committed_as) < allowed)
return 0;
error:
vm_unacct_memory(pages);
*/
void __init mmap_init(void)
{
+ int ret;
+
+ ret = percpu_counter_init(&vm_committed_as, 0);
+ VM_BUG_ON(ret);
}
struct page *mem_map;
unsigned long max_mapnr;
unsigned long num_physpages;
-atomic_long_t vm_committed_space = ATOMIC_LONG_INIT(0);
+struct percpu_counter vm_committed_as;
int sysctl_overcommit_memory = OVERCOMMIT_GUESS; /* heuristic overcommit */
int sysctl_overcommit_ratio = 50; /* default is 50% */
int sysctl_max_map_count = DEFAULT_MAX_MAP_COUNT;
-int sysctl_nr_trim_pages = 1; /* page trimming behaviour */
+int sysctl_nr_trim_pages = CONFIG_NOMMU_INITIAL_TRIM_EXCESS;
int heap_stack_gap = 0;
atomic_long_t mmap_pages_allocated;
*/
void __init mmap_init(void)
{
+ int ret;
+
+ ret = percpu_counter_init(&vm_committed_as, 0);
+ VM_BUG_ON(ret);
vm_region_jar = KMEM_CACHE(vm_region, SLAB_PANIC);
}
validate_nommu_regions();
- BUG_ON(region->vm_start & ~PAGE_MASK);
-
parent = NULL;
p = &nommu_region_tree.rb_node;
while (*p) {
if (mm)
allowed -= mm->total_vm / 32;
- /*
- * cast `allowed' as a signed long because vm_committed_space
- * sometimes has a negative value
- */
- if (atomic_long_read(&vm_committed_space) < (long)allowed)
+ if (percpu_counter_read_positive(&vm_committed_as) < allowed)
return 0;
+
error:
vm_unacct_memory(pages);
*/
static void __out_of_memory(gfp_t gfp_mask, int order)
{
- if (sysctl_oom_kill_allocating_task) {
- oom_kill_process(current, gfp_mask, order, 0, NULL,
- "Out of memory (oom_kill_allocating_task)");
-
- } else {
- unsigned long points;
- struct task_struct *p;
-
-retry:
- /*
- * Rambo mode: Shoot down a process and hope it solves whatever
- * issues we may have.
- */
- p = select_bad_process(&points, NULL);
+ struct task_struct *p;
+ unsigned long points;
- if (PTR_ERR(p) == -1UL)
+ if (sysctl_oom_kill_allocating_task)
+ if (!oom_kill_process(current, gfp_mask, order, 0, NULL,
+ "Out of memory (oom_kill_allocating_task)"))
return;
+retry:
+ /*
+ * Rambo mode: Shoot down a process and hope it solves whatever
+ * issues we may have.
+ */
+ p = select_bad_process(&points, NULL);
- /* Found nothing?!?! Either we hang forever, or we panic. */
- if (!p) {
- read_unlock(&tasklist_lock);
- panic("Out of memory and no killable processes...\n");
- }
+ if (PTR_ERR(p) == -1UL)
+ return;
- if (oom_kill_process(p, gfp_mask, order, points, NULL,
- "Out of memory"))
- goto retry;
+ /* Found nothing?!?! Either we hang forever, or we panic. */
+ if (!p) {
+ read_unlock(&tasklist_lock);
+ panic("Out of memory and no killable processes...\n");
}
+
+ if (oom_kill_process(p, gfp_mask, order, points, NULL,
+ "Out of memory"))
+ goto retry;
}
/*
static int zone_batchsize(struct zone *zone)
{
+#ifdef CONFIG_MMU
int batch;
/*
* of pages of one half of the possible page colors
* and the other with pages of the other colors.
*/
- batch = (1 << (fls(batch + batch/2)-1)) - 1;
+ batch = rounddown_pow_of_two(batch + batch/2) - 1;
return batch;
+
+#else
+ /* The deferral and batching of frees should be suppressed under NOMMU
+ * conditions.
+ *
+ * The problem is that NOMMU needs to be able to allocate large chunks
+ * of contiguous memory as there's no hardware page translation to
+ * assemble apparent contiguous memory from discontiguous pages.
+ *
+ * Queueing large contiguous runs of pages for batching, however,
+ * causes the pages to actually be freed in smaller chunks. As there
+ * can be a significant delay between the individual batches being
+ * recycled, this leads to the once large chunks of space being
+ * fragmented and becoming unavailable for high-order allocations.
+ */
+ return 0;
+#endif
}
static void setup_pageset(struct per_cpu_pageset *p, unsigned long batch)
shmem_swp_unmap(entry);
spin_unlock(&info->lock);
if (error == -ENOMEM) {
- /* allow reclaim from this memory cgroup */
- error = mem_cgroup_shrink_usage(swappage,
+ /*
+ * reclaim from proper memory cgroup and
+ * call memcg's OOM if needed.
+ */
+ error = mem_cgroup_shmem_charge_fallback(
+ swappage,
current->mm,
gfp);
if (error) {
EXPORT_SYMBOL(pagevec_lookup_tag);
-#ifdef CONFIG_SMP
-/*
- * We tolerate a little inaccuracy to avoid ping-ponging the counter between
- * CPUs
- */
-#define ACCT_THRESHOLD max(16, NR_CPUS * 2)
-
-static DEFINE_PER_CPU(long, committed_space);
-
-void vm_acct_memory(long pages)
-{
- long *local;
-
- preempt_disable();
- local = &__get_cpu_var(committed_space);
- *local += pages;
- if (*local > ACCT_THRESHOLD || *local < -ACCT_THRESHOLD) {
- atomic_long_add(*local, &vm_committed_space);
- *local = 0;
- }
- preempt_enable();
-}
-
-#ifdef CONFIG_HOTPLUG_CPU
-
-/* Drop the CPU's cached committed space back into the central pool. */
-static int cpu_swap_callback(struct notifier_block *nfb,
- unsigned long action,
- void *hcpu)
-{
- long *committed;
-
- committed = &per_cpu(committed_space, (long)hcpu);
- if (action == CPU_DEAD || action == CPU_DEAD_FROZEN) {
- atomic_long_add(*committed, &vm_committed_space);
- *committed = 0;
- drain_cpu_pagevecs((long)hcpu);
- }
- return NOTIFY_OK;
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-#endif /* CONFIG_SMP */
-
/*
* Perform any setup for the swap system
*/
* Right now other parts of the system means that we
* _really_ don't want to cluster much more
*/
-#ifdef CONFIG_HOTPLUG_CPU
- hotcpu_notifier(cpu_swap_callback, 0);
-#endif
}
printk(KERN_WARNING
"vmap allocation for size %lu failed: "
"use vmalloc=<size> to increase size.\n", size);
+ kfree(va);
return ERR_PTR(-EBUSY);
}
for_each_evictable_lru(l) {
int file = is_file_lru(l);
- int scan;
+ unsigned long scan;
scan = zone_nr_pages(zone, sc, l);
if (priority) {
p9pdu_reset(req->tc);
p9pdu_reset(req->rc);
- req->flush_tag = 0;
req->tc->tag = tag-1;
req->status = REQ_STATUS_ALLOC;
*/
void p9_client_cb(struct p9_client *c, struct p9_req_t *req)
{
- struct p9_req_t *other_req;
- unsigned long flags;
-
P9_DPRINTK(P9_DEBUG_MUX, " tag %d\n", req->tc->tag);
-
- if (req->status == REQ_STATUS_ERROR)
- wake_up(req->wq);
-
- if (req->flush_tag) { /* flush receive path */
- P9_DPRINTK(P9_DEBUG_9P, "<<< RFLUSH %d\n", req->tc->tag);
- spin_lock_irqsave(&c->lock, flags);
- other_req = p9_tag_lookup(c, req->flush_tag);
- if (other_req->status != REQ_STATUS_FLSH) /* stale flush */
- spin_unlock_irqrestore(&c->lock, flags);
- else {
- other_req->status = REQ_STATUS_FLSHD;
- spin_unlock_irqrestore(&c->lock, flags);
- wake_up(other_req->wq);
- }
- p9_free_req(c, req);
- } else { /* normal receive path */
- P9_DPRINTK(P9_DEBUG_MUX, "normal: tag %d\n", req->tc->tag);
- spin_lock_irqsave(&c->lock, flags);
- if (req->status != REQ_STATUS_FLSHD)
- req->status = REQ_STATUS_RCVD;
- spin_unlock_irqrestore(&c->lock, flags);
- wake_up(req->wq);
- P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
- }
+ wake_up(req->wq);
+ P9_DPRINTK(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag);
}
EXPORT_SYMBOL(p9_client_cb);
if (IS_ERR(req))
return PTR_ERR(req);
- req->flush_tag = oldtag;
- /* we don't free anything here because RPC isn't complete */
+ /* if we haven't received a response for oldreq,
+ remove it from the list. */
+ spin_lock(&c->lock);
+ if (oldreq->status == REQ_STATUS_FLSH)
+ list_del(&oldreq->req_list);
+ spin_unlock(&c->lock);
+
+ p9_free_req(c, req);
return 0;
}
struct p9_req_t *req;
unsigned long flags;
int sigpending;
- int flushed = 0;
P9_DPRINTK(P9_DEBUG_MUX, "client %p op %d\n", c, type);
goto reterr;
}
- /* if it was a flush we just transmitted, return our tag */
- if (type == P9_TFLUSH)
- return req;
-again:
P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d\n", req->wq, tag);
err = wait_event_interruptible(*req->wq,
req->status >= REQ_STATUS_RCVD);
- P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d (flushed=%d)\n",
- req->wq, tag, err, flushed);
+ P9_DPRINTK(P9_DEBUG_MUX, "wait %p tag: %d returned %d\n",
+ req->wq, tag, err);
if (req->status == REQ_STATUS_ERROR) {
P9_DPRINTK(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err);
err = req->t_err;
- } else if (err == -ERESTARTSYS && flushed) {
- P9_DPRINTK(P9_DEBUG_MUX, "flushed - going again\n");
- goto again;
- } else if (req->status == REQ_STATUS_FLSHD) {
- P9_DPRINTK(P9_DEBUG_MUX, "flushed - erestartsys\n");
- err = -ERESTARTSYS;
}
- if ((err == -ERESTARTSYS) && (c->status == Connected) && (!flushed)) {
+ if ((err == -ERESTARTSYS) && (c->status == Connected)) {
P9_DPRINTK(P9_DEBUG_MUX, "flushing\n");
- spin_lock_irqsave(&c->lock, flags);
- if (req->status == REQ_STATUS_SENT)
- req->status = REQ_STATUS_FLSH;
- spin_unlock_irqrestore(&c->lock, flags);
sigpending = 1;
- flushed = 1;
clear_thread_flag(TIF_SIGPENDING);
- if (c->trans_mod->cancel(c, req)) {
- err = p9_client_flush(c, req);
- if (err == 0)
- goto again;
- }
+ if (c->trans_mod->cancel(c, req))
+ p9_client_flush(c, req);
+
+ /* if we received the response anyway, don't signal error */
+ if (req->status == REQ_STATUS_RCVD)
+ err = 0;
}
if (sigpending) {
ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
ret->n_uid, ret->n_gid, ret->n_muid);
+ p9_free_req(clnt, req);
+ return ret;
+
free_and_error:
p9_free_req(clnt, req);
error:
- return ret;
+ kfree(ret);
+ return ERR_PTR(err);
}
EXPORT_SYMBOL(p9_client_stat);
+static int p9_client_statsize(struct p9_wstat *wst, int optional)
+{
+ int ret;
+
+ /* size[2] type[2] dev[4] qid[13] */
+ /* mode[4] atime[4] mtime[4] length[8]*/
+ /* name[s] uid[s] gid[s] muid[s] */
+ ret = 2+2+4+13+4+4+4+8+2+2+2+2;
+
+ if (wst->name)
+ ret += strlen(wst->name);
+ if (wst->uid)
+ ret += strlen(wst->uid);
+ if (wst->gid)
+ ret += strlen(wst->gid);
+ if (wst->muid)
+ ret += strlen(wst->muid);
+
+ if (optional) {
+ ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */
+ if (wst->extension)
+ ret += strlen(wst->extension);
+ }
+
+ return ret;
+}
+
int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst)
{
int err;
struct p9_req_t *req;
struct p9_client *clnt;
+ err = 0;
+ clnt = fid->clnt;
+ wst->size = p9_client_statsize(wst, clnt->dotu);
P9_DPRINTK(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid);
P9_DPRINTK(P9_DEBUG_9P,
" sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
wst->atime, wst->mtime, (unsigned long long)wst->length,
wst->name, wst->uid, wst->gid, wst->muid, wst->extension,
wst->n_uid, wst->n_gid, wst->n_muid);
- err = 0;
- clnt = fid->clnt;
- req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, 0, wst);
+ req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size, wst);
if (IS_ERR(req)) {
err = PTR_ERR(req);
goto error;
spin_unlock_irqrestore(&m->client->lock, flags);
list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) {
- list_del(&req->req_list);
P9_DPRINTK(P9_DEBUG_ERROR, "call back req %p\n", req);
+ list_del(&req->req_list);
p9_client_cb(m->client, req);
}
}
"mux %p pkt: size: %d bytes tag: %d\n", m, n, tag);
m->req = p9_tag_lookup(m->client, tag);
- if (!m->req) {
+ if (!m->req || (m->req->status != REQ_STATUS_SENT &&
+ m->req->status != REQ_STATUS_FLSH)) {
P9_DPRINTK(P9_DEBUG_ERROR, "Unexpected packet tag %d\n",
tag);
err = -EIO;
if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */
P9_DPRINTK(P9_DEBUG_TRANS, "got new packet\n");
spin_lock(&m->client->lock);
+ if (m->req->status != REQ_STATUS_ERROR)
+ m->req->status = REQ_STATUS_RCVD;
list_del(&m->req->req_list);
spin_unlock(&m->client->lock);
p9_client_cb(m->client, m->req);
-
m->rbuf = NULL;
m->rpos = 0;
m->rsize = 0;
req = list_entry(m->unsent_req_list.next, struct p9_req_t,
req_list);
req->status = REQ_STATUS_SENT;
+ P9_DPRINTK(P9_DEBUG_TRANS, "move req %p\n", req);
list_move_tail(&req->req_list, &m->req_list);
m->wbuf = req->tc->sdata;
P9_DPRINTK(P9_DEBUG_TRANS, "client %p req %p\n", client, req);
spin_lock(&client->lock);
- list_del(&req->req_list);
if (req->status == REQ_STATUS_UNSENT) {
+ list_del(&req->req_list);
req->status = REQ_STATUS_FLSHD;
ret = 0;
- }
+ } else if (req->status == REQ_STATUS_SENT)
+ req->status = REQ_STATUS_FLSH;
spin_unlock(&client->lock);
goto err_out;
req->rc = c->rc;
+ req->status = REQ_STATUS_RCVD;
p9_client_cb(client, req);
return;
P9_DPRINTK(P9_DEBUG_TRANS, ": rc %p\n", rc);
P9_DPRINTK(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag);
req = p9_tag_lookup(chan->client, rc->tag);
+ req->status = REQ_STATUS_RCVD;
p9_client_cb(chan->client, req);
}
}
struct br2684_dev *brdev = BRPRIV(netdev);
ether_setup(netdev);
+ brdev->net_dev = netdev;
netdev->netdev_ops = &br2684_netdev_ops;
if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_CONN_ADD);
+ hci_conn_init_sysfs(conn);
+
tasklet_enable(&hdev->tx_task);
return conn;
struct class *bt_class = NULL;
EXPORT_SYMBOL_GPL(bt_class);
-static struct workqueue_struct *bluetooth;
+static struct workqueue_struct *bt_workq;
static inline char *link_typetostr(int type)
{
{
struct hci_conn *conn = container_of(work, struct hci_conn, work_add);
- /* ensure previous add/del is complete */
- flush_workqueue(bluetooth);
+ /* ensure previous del is complete */
+ flush_work(&conn->work_del);
if (device_add(&conn->dev) < 0) {
BT_ERR("Failed to register connection device");
}
}
-void hci_conn_add_sysfs(struct hci_conn *conn)
-{
- struct hci_dev *hdev = conn->hdev;
-
- BT_DBG("conn %p", conn);
-
- conn->dev.type = &bt_link;
- conn->dev.class = bt_class;
- conn->dev.parent = &hdev->dev;
-
- dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
-
- dev_set_drvdata(&conn->dev, conn);
-
- device_initialize(&conn->dev);
-
- INIT_WORK(&conn->work_add, add_conn);
-
- queue_work(bluetooth, &conn->work_add);
-}
-
/*
* The rfcomm tty device will possibly retain even when conn
* is down, and sysfs doesn't support move zombie device,
struct hci_conn *conn = container_of(work, struct hci_conn, work_del);
struct hci_dev *hdev = conn->hdev;
- /* ensure previous add/del is complete */
- flush_workqueue(bluetooth);
+ /* ensure previous add is complete */
+ flush_work(&conn->work_add);
+
+ if (!device_is_registered(&conn->dev))
+ return;
while (1) {
struct device *dev;
hci_dev_put(hdev);
}
-void hci_conn_del_sysfs(struct hci_conn *conn)
+void hci_conn_init_sysfs(struct hci_conn *conn)
{
+ struct hci_dev *hdev = conn->hdev;
+
BT_DBG("conn %p", conn);
- if (!device_is_registered(&conn->dev))
- return;
+ conn->dev.type = &bt_link;
+ conn->dev.class = bt_class;
+ conn->dev.parent = &hdev->dev;
+
+ dev_set_drvdata(&conn->dev, conn);
+ device_initialize(&conn->dev);
+
+ INIT_WORK(&conn->work_add, add_conn);
INIT_WORK(&conn->work_del, del_conn);
+}
+
+void hci_conn_add_sysfs(struct hci_conn *conn)
+{
+ struct hci_dev *hdev = conn->hdev;
+
+ BT_DBG("conn %p", conn);
+
+ dev_set_name(&conn->dev, "%s:%d", hdev->name, conn->handle);
+
+ queue_work(bt_workq, &conn->work_add);
+}
+
+void hci_conn_del_sysfs(struct hci_conn *conn)
+{
+ BT_DBG("conn %p", conn);
- queue_work(bluetooth, &conn->work_del);
+ queue_work(bt_workq, &conn->work_del);
}
static inline char *host_typetostr(int type)
int __init bt_sysfs_init(void)
{
- bluetooth = create_singlethread_workqueue("bluetooth");
- if (!bluetooth)
+ bt_workq = create_singlethread_workqueue("bluetooth");
+ if (!bt_workq)
return -ENOMEM;
bt_class = class_create(THIS_MODULE, "bluetooth");
if (IS_ERR(bt_class)) {
- destroy_workqueue(bluetooth);
+ destroy_workqueue(bt_workq);
return PTR_ERR(bt_class);
}
void bt_sysfs_cleanup(void)
{
- destroy_workqueue(bluetooth);
+ destroy_workqueue(bt_workq);
class_destroy(bt_class);
}
{
u32 hash;
- if (skb_rx_queue_recorded(skb)) {
- hash = skb_get_rx_queue(skb);
- } else if (skb->sk && skb->sk->sk_hash) {
+ if (skb_rx_queue_recorded(skb))
+ return skb_get_rx_queue(skb) % dev->real_num_tx_queues;
+
+ if (skb->sk && skb->sk->sk_hash)
hash = skb->sk->sk_hash;
- } else
+ else
hash = skb->protocol;
hash = jhash_1word(hash, skb_tx_hashrnd);
static inline struct page *linear_to_page(struct page *page, unsigned int *len,
unsigned int *offset,
- struct sk_buff *skb)
+ struct sk_buff *skb, struct sock *sk)
{
- struct sock *sk = skb->sk;
struct page *p = sk->sk_sndmsg_page;
unsigned int off;
*/
static inline int spd_fill_page(struct splice_pipe_desc *spd, struct page *page,
unsigned int *len, unsigned int offset,
- struct sk_buff *skb, int linear)
+ struct sk_buff *skb, int linear,
+ struct sock *sk)
{
if (unlikely(spd->nr_pages == PIPE_BUFFERS))
return 1;
if (linear) {
- page = linear_to_page(page, len, &offset, skb);
+ page = linear_to_page(page, len, &offset, skb, sk);
if (!page)
return 1;
} else
static inline int __splice_segment(struct page *page, unsigned int poff,
unsigned int plen, unsigned int *off,
unsigned int *len, struct sk_buff *skb,
- struct splice_pipe_desc *spd, int linear)
+ struct splice_pipe_desc *spd, int linear,
+ struct sock *sk)
{
if (!*len)
return 1;
/* the linear region may spread across several pages */
flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
- if (spd_fill_page(spd, page, &flen, poff, skb, linear))
+ if (spd_fill_page(spd, page, &flen, poff, skb, linear, sk))
return 1;
__segment_seek(&page, &poff, &plen, flen);
* pipe is full or if we already spliced the requested length.
*/
static int __skb_splice_bits(struct sk_buff *skb, unsigned int *offset,
- unsigned int *len,
- struct splice_pipe_desc *spd)
+ unsigned int *len, struct splice_pipe_desc *spd,
+ struct sock *sk)
{
int seg;
if (__splice_segment(virt_to_page(skb->data),
(unsigned long) skb->data & (PAGE_SIZE - 1),
skb_headlen(skb),
- offset, len, skb, spd, 1))
+ offset, len, skb, spd, 1, sk))
return 1;
/*
const skb_frag_t *f = &skb_shinfo(skb)->frags[seg];
if (__splice_segment(f->page, f->page_offset, f->size,
- offset, len, skb, spd, 0))
+ offset, len, skb, spd, 0, sk))
return 1;
}
.ops = &sock_pipe_buf_ops,
.spd_release = sock_spd_release,
};
+ struct sock *sk = skb->sk;
/*
* __skb_splice_bits() only fails if the output has no room left,
* so no point in going over the frag_list for the error case.
*/
- if (__skb_splice_bits(skb, &offset, &tlen, &spd))
+ if (__skb_splice_bits(skb, &offset, &tlen, &spd, sk))
goto done;
else if (!tlen)
goto done;
struct sk_buff *list = skb_shinfo(skb)->frag_list;
for (; list && tlen; list = list->next) {
- if (__skb_splice_bits(list, &offset, &tlen, &spd))
+ if (__skb_splice_bits(list, &offset, &tlen, &spd, sk))
break;
}
}
done:
if (spd.nr_pages) {
- struct sock *sk = skb->sk;
int ret;
/*
tcp_grow_window(sk, skb);
}
-static u32 tcp_rto_min(struct sock *sk)
-{
- struct dst_entry *dst = __sk_dst_get(sk);
- u32 rto_min = TCP_RTO_MIN;
-
- if (dst && dst_metric_locked(dst, RTAX_RTO_MIN))
- rto_min = dst_metric_rtt(dst, RTAX_RTO_MIN);
- return rto_min;
-}
-
/* Called to compute a smoothed rtt estimate. The data fed to this
* routine either comes from timestamps, or from segments that were
* known _not_ to have been retransmitted [see Karn/Partridge
local->hw.conf.long_frame_max_tx_count = 4;
local->hw.conf.short_frame_max_tx_count = 7;
local->hw.conf.radio_enabled = true;
+ local->user_power_level = -1;
INIT_LIST_HEAD(&local->interfaces);
mutex_init(&local->iflist_mtx);
if (result < 0)
goto fail_sta_info;
+ result = ieee80211_wep_init(local);
+ if (result < 0) {
+ printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
+ wiphy_name(local->hw.wiphy), result);
+ goto fail_wep;
+ }
+
rtnl_lock();
result = dev_alloc_name(local->mdev, local->mdev->name);
if (result < 0)
goto fail_rate;
}
- result = ieee80211_wep_init(local);
-
- if (result < 0) {
- printk(KERN_DEBUG "%s: Failed to initialize wep: %d\n",
- wiphy_name(local->hw.wiphy), result);
- goto fail_wep;
- }
-
/* add one default STA interface if supported */
if (local->hw.wiphy->interface_modes & BIT(NL80211_IFTYPE_STATION)) {
result = ieee80211_if_add(local, "wlan%d", NULL,
return 0;
-fail_wep:
- rate_control_deinitialize(local);
fail_rate:
unregister_netdevice(local->mdev);
local->mdev = NULL;
fail_dev:
rtnl_unlock();
+ ieee80211_wep_free(local);
+fail_wep:
sta_info_stop(local);
fail_sta_info:
debugfs_hw_del(local);
depends on NETFILTER_TPROXY
depends on NETFILTER_XTABLES
depends on NETFILTER_ADVANCED
+ depends on !NF_CONNTRACK || NF_CONNTRACK
select NF_DEFRAG_IPV4
help
This option adds a `socket' match, which can be used to match
}
tp->ops = tp_ops;
tp->protocol = protocol;
- tp->prio = nprio ? : tcf_auto_prio(*back);
+ tp->prio = nprio ? : TC_H_MAJ(tcf_auto_prio(*back));
tp->q = q;
tp->classify = tp_ops->classify;
tp->classid = parent;
if (test_and_set_bit(XPRT_LOCKED, &xprt->state))
goto out_abort;
spin_unlock(&xprt->transport_lock);
- if (xprt_connecting(xprt))
- xprt_release_write(xprt, NULL);
- else
- queue_work(rpciod_workqueue, &xprt->task_cleanup);
+ set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
+ queue_work(rpciod_workqueue, &xprt->task_cleanup);
return;
out_abort:
spin_unlock(&xprt->transport_lock);
*
* This is used when all requests are complete; ie, no DRC state remains
* on the server we want to save.
+ *
+ * The caller _must_ be holding XPRT_LOCKED in order to avoid issues with
+ * xs_reset_transport() zeroing the socket from underneath a writer.
*/
static void xs_close(struct rpc_xprt *xprt)
{
xprt_disconnect_done(xprt);
}
+static void xs_tcp_close(struct rpc_xprt *xprt)
+{
+ if (test_and_clear_bit(XPRT_CONNECTION_CLOSE, &xprt->state))
+ xs_close(xprt);
+ else
+ xs_tcp_shutdown(xprt);
+}
+
/**
* xs_destroy - prepare to shutdown a transport
* @xprt: doomed transport
xprt, -status, xprt_connected(xprt),
sock->sk->sk_state);
switch (status) {
+ default:
+ printk("%s: connect returned unhandled error %d\n",
+ __func__, status);
+ case -EADDRNOTAVAIL:
+ /* We're probably in TIME_WAIT. Get rid of existing socket,
+ * and retry
+ */
+ set_bit(XPRT_CONNECTION_CLOSE, &xprt->state);
+ xprt_force_disconnect(xprt);
case -ECONNREFUSED:
case -ECONNRESET:
case -ENETUNREACH:
xprt_clear_connecting(xprt);
return;
}
- /* get rid of existing socket, and retry */
- xs_tcp_shutdown(xprt);
- printk("%s: connect returned unhandled error %d\n",
- __func__, status);
out_eagain:
status = -EAGAIN;
out:
.buf_free = rpc_free,
.send_request = xs_tcp_send_request,
.set_retrans_timeout = xprt_set_retrans_timeout_def,
- .close = xs_tcp_shutdown,
+ .close = xs_tcp_close,
.destroy = xs_destroy,
.print_stats = xs_tcp_print_stats,
};
subdir-$(CONFIG_MODVERSIONS) += genksyms
subdir-y += mod
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
+subdir-$(CONFIG_DTC) += dtc
# Let clean descend into subdirs
subdir- += basic kconfig package selinux
--- /dev/null
+# scripts/dtc makefile
+
+hostprogs-y := dtc
+always := $(hostprogs-y)
+
+dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
+ srcpos.o checks.o
+dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
+
+# Source files need to get at the userspace version of libfdt_env.h to compile
+
+HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt
+
+HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_livetree.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC)
+
+HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
+
+# dependencies on generated files need to be listed explicitly
+$(obj)/dtc-parser.tab.o: $(obj)/dtc-parser.tab.c $(obj)/dtc-parser.tab.h
+$(obj)/dtc-lexer.lex.o: $(obj)/dtc-lexer.lex.c $(obj)/dtc-parser.tab.h
+
+targets += dtc-parser.tab.c dtc-lexer.lex.c
+
+clean-files += dtc-parser.tab.h
+
+# GENERATE_PARSER := 1 # Uncomment to rebuild flex/bison output
+
+ifdef GENERATE_PARSER
+
+BISON = bison
+FLEX = flex
+
+quiet_cmd_bison = BISON $@
+ cmd_bison = $(BISON) -o$@ -d $<; cp $@ $@_shipped
+quiet_cmd_flex = FLEX $@
+ cmd_flex = $(FLEX) -o$@ $<; cp $@ $@_shipped
+
+$(obj)/dtc-parser.tab.c: $(src)/dtc-parser.y FORCE
+ $(call if_changed,bison)
+
+$(obj)/dtc-parser.tab.h: $(obj)/dtc-parser.tab.c
+
+$(obj)/dtc-lexer.lex.c: $(src)/dtc-lexer.l FORCE
+ $(call if_changed,flex)
+
+endif
--- /dev/null
+# Makefile.dtc
+#
+# This is not a complete Makefile of itself. Instead, it is designed to
+# be easily embeddable into other systems of Makefiles.
+#
+DTC_SRCS = dtc.c flattree.c fstree.c data.c livetree.c treesource.c srcpos.c \
+ checks.c
+DTC_GEN_SRCS = dtc-lexer.lex.c dtc-parser.tab.c
+DTC_OBJS = $(DTC_SRCS:%.c=%.o) $(DTC_GEN_SRCS:%.c=%.o)
--- /dev/null
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2007.
+ *
+ *
+ * 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 "dtc.h"
+
+#ifdef TRACE_CHECKS
+#define TRACE(c, ...) \
+ do { \
+ fprintf(stderr, "=== %s: ", (c)->name); \
+ fprintf(stderr, __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ } while (0)
+#else
+#define TRACE(c, fmt, ...) do { } while (0)
+#endif
+
+enum checklevel {
+ IGNORE = 0,
+ WARN = 1,
+ ERROR = 2,
+};
+
+enum checkstatus {
+ UNCHECKED = 0,
+ PREREQ,
+ PASSED,
+ FAILED,
+};
+
+struct check;
+
+typedef void (*tree_check_fn)(struct check *c, struct node *dt);
+typedef void (*node_check_fn)(struct check *c, struct node *dt, struct node *node);
+typedef void (*prop_check_fn)(struct check *c, struct node *dt,
+ struct node *node, struct property *prop);
+
+struct check {
+ const char *name;
+ tree_check_fn tree_fn;
+ node_check_fn node_fn;
+ prop_check_fn prop_fn;
+ void *data;
+ enum checklevel level;
+ enum checkstatus status;
+ int inprogress;
+ int num_prereqs;
+ struct check **prereq;
+};
+
+#define CHECK(nm, tfn, nfn, pfn, d, lvl, ...) \
+ static struct check *nm##_prereqs[] = { __VA_ARGS__ }; \
+ static struct check nm = { \
+ .name = #nm, \
+ .tree_fn = (tfn), \
+ .node_fn = (nfn), \
+ .prop_fn = (pfn), \
+ .data = (d), \
+ .level = (lvl), \
+ .status = UNCHECKED, \
+ .num_prereqs = ARRAY_SIZE(nm##_prereqs), \
+ .prereq = nm##_prereqs, \
+ };
+
+#define TREE_CHECK(nm, d, lvl, ...) \
+ CHECK(nm, check_##nm, NULL, NULL, d, lvl, __VA_ARGS__)
+#define NODE_CHECK(nm, d, lvl, ...) \
+ CHECK(nm, NULL, check_##nm, NULL, d, lvl, __VA_ARGS__)
+#define PROP_CHECK(nm, d, lvl, ...) \
+ CHECK(nm, NULL, NULL, check_##nm, d, lvl, __VA_ARGS__)
+#define BATCH_CHECK(nm, lvl, ...) \
+ CHECK(nm, NULL, NULL, NULL, NULL, lvl, __VA_ARGS__)
+
+#ifdef __GNUC__
+static inline void check_msg(struct check *c, const char *fmt, ...) __attribute__((format (printf, 2, 3)));
+#endif
+static inline void check_msg(struct check *c, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+
+ if ((c->level < WARN) || (c->level <= quiet))
+ return; /* Suppress message */
+
+ fprintf(stderr, "%s (%s): ",
+ (c->level == ERROR) ? "ERROR" : "Warning", c->name);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+}
+
+#define FAIL(c, ...) \
+ do { \
+ TRACE((c), "\t\tFAILED at %s:%d", __FILE__, __LINE__); \
+ (c)->status = FAILED; \
+ check_msg((c), __VA_ARGS__); \
+ } while (0)
+
+static void check_nodes_props(struct check *c, struct node *dt, struct node *node)
+{
+ struct node *child;
+ struct property *prop;
+
+ TRACE(c, "%s", node->fullpath);
+ if (c->node_fn)
+ c->node_fn(c, dt, node);
+
+ if (c->prop_fn)
+ for_each_property(node, prop) {
+ TRACE(c, "%s\t'%s'", node->fullpath, prop->name);
+ c->prop_fn(c, dt, node, prop);
+ }
+
+ for_each_child(node, child)
+ check_nodes_props(c, dt, child);
+}
+
+static int run_check(struct check *c, struct node *dt)
+{
+ int error = 0;
+ int i;
+
+ assert(!c->inprogress);
+
+ if (c->status != UNCHECKED)
+ goto out;
+
+ c->inprogress = 1;
+
+ for (i = 0; i < c->num_prereqs; i++) {
+ struct check *prq = c->prereq[i];
+ error |= run_check(prq, dt);
+ if (prq->status != PASSED) {
+ c->status = PREREQ;
+ check_msg(c, "Failed prerequisite '%s'",
+ c->prereq[i]->name);
+ }
+ }
+
+ if (c->status != UNCHECKED)
+ goto out;
+
+ if (c->node_fn || c->prop_fn)
+ check_nodes_props(c, dt, dt);
+
+ if (c->tree_fn)
+ c->tree_fn(c, dt);
+ if (c->status == UNCHECKED)
+ c->status = PASSED;
+
+ TRACE(c, "\tCompleted, status %d", c->status);
+
+out:
+ c->inprogress = 0;
+ if ((c->status != PASSED) && (c->level == ERROR))
+ error = 1;
+ return error;
+}
+
+/*
+ * Utility check functions
+ */
+
+static void check_is_string(struct check *c, struct node *root,
+ struct node *node)
+{
+ struct property *prop;
+ char *propname = c->data;
+
+ prop = get_property(node, propname);
+ if (!prop)
+ return; /* Not present, assumed ok */
+
+ if (!data_is_one_string(prop->val))
+ FAIL(c, "\"%s\" property in %s is not a string",
+ propname, node->fullpath);
+}
+#define CHECK_IS_STRING(nm, propname, lvl) \
+ CHECK(nm, NULL, check_is_string, NULL, (propname), (lvl))
+
+static void check_is_cell(struct check *c, struct node *root,
+ struct node *node)
+{
+ struct property *prop;
+ char *propname = c->data;
+
+ prop = get_property(node, propname);
+ if (!prop)
+ return; /* Not present, assumed ok */
+
+ if (prop->val.len != sizeof(cell_t))
+ FAIL(c, "\"%s\" property in %s is not a single cell",
+ propname, node->fullpath);
+}
+#define CHECK_IS_CELL(nm, propname, lvl) \
+ CHECK(nm, NULL, check_is_cell, NULL, (propname), (lvl))
+
+/*
+ * Structural check functions
+ */
+
+static void check_duplicate_node_names(struct check *c, struct node *dt,
+ struct node *node)
+{
+ struct node *child, *child2;
+
+ for_each_child(node, child)
+ for (child2 = child->next_sibling;
+ child2;
+ child2 = child2->next_sibling)
+ if (streq(child->name, child2->name))
+ FAIL(c, "Duplicate node name %s",
+ child->fullpath);
+}
+NODE_CHECK(duplicate_node_names, NULL, ERROR);
+
+static void check_duplicate_property_names(struct check *c, struct node *dt,
+ struct node *node)
+{
+ struct property *prop, *prop2;
+
+ for_each_property(node, prop)
+ for (prop2 = prop->next; prop2; prop2 = prop2->next)
+ if (streq(prop->name, prop2->name))
+ FAIL(c, "Duplicate property name %s in %s",
+ prop->name, node->fullpath);
+}
+NODE_CHECK(duplicate_property_names, NULL, ERROR);
+
+#define LOWERCASE "abcdefghijklmnopqrstuvwxyz"
+#define UPPERCASE "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+#define DIGITS "0123456789"
+#define PROPNODECHARS LOWERCASE UPPERCASE DIGITS ",._+*#?-"
+
+static void check_node_name_chars(struct check *c, struct node *dt,
+ struct node *node)
+{
+ int n = strspn(node->name, c->data);
+
+ if (n < strlen(node->name))
+ FAIL(c, "Bad character '%c' in node %s",
+ node->name[n], node->fullpath);
+}
+NODE_CHECK(node_name_chars, PROPNODECHARS "@", ERROR);
+
+static void check_node_name_format(struct check *c, struct node *dt,
+ struct node *node)
+{
+ if (strchr(get_unitname(node), '@'))
+ FAIL(c, "Node %s has multiple '@' characters in name",
+ node->fullpath);
+}
+NODE_CHECK(node_name_format, NULL, ERROR, &node_name_chars);
+
+static void check_property_name_chars(struct check *c, struct node *dt,
+ struct node *node, struct property *prop)
+{
+ int n = strspn(prop->name, c->data);
+
+ if (n < strlen(prop->name))
+ FAIL(c, "Bad character '%c' in property name \"%s\", node %s",
+ prop->name[n], prop->name, node->fullpath);
+}
+PROP_CHECK(property_name_chars, PROPNODECHARS, ERROR);
+
+static void check_explicit_phandles(struct check *c, struct node *root,
+ struct node *node)
+{
+ struct property *prop;
+ struct node *other;
+ cell_t phandle;
+
+ prop = get_property(node, "linux,phandle");
+ if (! prop)
+ return; /* No phandle, that's fine */
+
+ if (prop->val.len != sizeof(cell_t)) {
+ FAIL(c, "%s has bad length (%d) linux,phandle property",
+ node->fullpath, prop->val.len);
+ return;
+ }
+
+ phandle = propval_cell(prop);
+ if ((phandle == 0) || (phandle == -1)) {
+ FAIL(c, "%s has invalid linux,phandle value 0x%x",
+ node->fullpath, phandle);
+ return;
+ }
+
+ other = get_node_by_phandle(root, phandle);
+ if (other) {
+ FAIL(c, "%s has duplicated phandle 0x%x (seen before at %s)",
+ node->fullpath, phandle, other->fullpath);
+ return;
+ }
+
+ node->phandle = phandle;
+}
+NODE_CHECK(explicit_phandles, NULL, ERROR);
+
+static void check_name_properties(struct check *c, struct node *root,
+ struct node *node)
+{
+ struct property **pp, *prop = NULL;
+
+ for (pp = &node->proplist; *pp; pp = &((*pp)->next))
+ if (streq((*pp)->name, "name")) {
+ prop = *pp;
+ break;
+ }
+
+ if (!prop)
+ return; /* No name property, that's fine */
+
+ if ((prop->val.len != node->basenamelen+1)
+ || (memcmp(prop->val.val, node->name, node->basenamelen) != 0)) {
+ FAIL(c, "\"name\" property in %s is incorrect (\"%s\" instead"
+ " of base node name)", node->fullpath, prop->val.val);
+ } else {
+ /* The name property is correct, and therefore redundant.
+ * Delete it */
+ *pp = prop->next;
+ free(prop->name);
+ data_free(prop->val);
+ free(prop);
+ }
+}
+CHECK_IS_STRING(name_is_string, "name", ERROR);
+NODE_CHECK(name_properties, NULL, ERROR, &name_is_string);
+
+/*
+ * Reference fixup functions
+ */
+
+static void fixup_phandle_references(struct check *c, struct node *dt,
+ struct node *node, struct property *prop)
+{
+ struct marker *m = prop->val.markers;
+ struct node *refnode;
+ cell_t phandle;
+
+ for_each_marker_of_type(m, REF_PHANDLE) {
+ assert(m->offset + sizeof(cell_t) <= prop->val.len);
+
+ refnode = get_node_by_ref(dt, m->ref);
+ if (! refnode) {
+ FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+ m->ref);
+ continue;
+ }
+
+ phandle = get_node_phandle(dt, refnode);
+ *((cell_t *)(prop->val.val + m->offset)) = cpu_to_fdt32(phandle);
+ }
+}
+CHECK(phandle_references, NULL, NULL, fixup_phandle_references, NULL, ERROR,
+ &duplicate_node_names, &explicit_phandles);
+
+static void fixup_path_references(struct check *c, struct node *dt,
+ struct node *node, struct property *prop)
+{
+ struct marker *m = prop->val.markers;
+ struct node *refnode;
+ char *path;
+
+ for_each_marker_of_type(m, REF_PATH) {
+ assert(m->offset <= prop->val.len);
+
+ refnode = get_node_by_ref(dt, m->ref);
+ if (!refnode) {
+ FAIL(c, "Reference to non-existent node or label \"%s\"\n",
+ m->ref);
+ continue;
+ }
+
+ path = refnode->fullpath;
+ prop->val = data_insert_at_marker(prop->val, m, path,
+ strlen(path) + 1);
+ }
+}
+CHECK(path_references, NULL, NULL, fixup_path_references, NULL, ERROR,
+ &duplicate_node_names);
+
+/*
+ * Semantic checks
+ */
+CHECK_IS_CELL(address_cells_is_cell, "#address-cells", WARN);
+CHECK_IS_CELL(size_cells_is_cell, "#size-cells", WARN);
+CHECK_IS_CELL(interrupt_cells_is_cell, "#interrupt-cells", WARN);
+
+CHECK_IS_STRING(device_type_is_string, "device_type", WARN);
+CHECK_IS_STRING(model_is_string, "model", WARN);
+CHECK_IS_STRING(status_is_string, "status", WARN);
+
+static void fixup_addr_size_cells(struct check *c, struct node *dt,
+ struct node *node)
+{
+ struct property *prop;
+
+ node->addr_cells = -1;
+ node->size_cells = -1;
+
+ prop = get_property(node, "#address-cells");
+ if (prop)
+ node->addr_cells = propval_cell(prop);
+
+ prop = get_property(node, "#size-cells");
+ if (prop)
+ node->size_cells = propval_cell(prop);
+}
+CHECK(addr_size_cells, NULL, fixup_addr_size_cells, NULL, NULL, WARN,
+ &address_cells_is_cell, &size_cells_is_cell);
+
+#define node_addr_cells(n) \
+ (((n)->addr_cells == -1) ? 2 : (n)->addr_cells)
+#define node_size_cells(n) \
+ (((n)->size_cells == -1) ? 1 : (n)->size_cells)
+
+static void check_reg_format(struct check *c, struct node *dt,
+ struct node *node)
+{
+ struct property *prop;
+ int addr_cells, size_cells, entrylen;
+
+ prop = get_property(node, "reg");
+ if (!prop)
+ return; /* No "reg", that's fine */
+
+ if (!node->parent) {
+ FAIL(c, "Root node has a \"reg\" property");
+ return;
+ }
+
+ if (prop->val.len == 0)
+ FAIL(c, "\"reg\" property in %s is empty", node->fullpath);
+
+ addr_cells = node_addr_cells(node->parent);
+ size_cells = node_size_cells(node->parent);
+ entrylen = (addr_cells + size_cells) * sizeof(cell_t);
+
+ if ((prop->val.len % entrylen) != 0)
+ FAIL(c, "\"reg\" property in %s has invalid length (%d bytes) "
+ "(#address-cells == %d, #size-cells == %d)",
+ node->fullpath, prop->val.len, addr_cells, size_cells);
+}
+NODE_CHECK(reg_format, NULL, WARN, &addr_size_cells);
+
+static void check_ranges_format(struct check *c, struct node *dt,
+ struct node *node)
+{
+ struct property *prop;
+ int c_addr_cells, p_addr_cells, c_size_cells, p_size_cells, entrylen;
+
+ prop = get_property(node, "ranges");
+ if (!prop)
+ return;
+
+ if (!node->parent) {
+ FAIL(c, "Root node has a \"ranges\" property");
+ return;
+ }
+
+ p_addr_cells = node_addr_cells(node->parent);
+ p_size_cells = node_size_cells(node->parent);
+ c_addr_cells = node_addr_cells(node);
+ c_size_cells = node_size_cells(node);
+ entrylen = (p_addr_cells + c_addr_cells + c_size_cells) * sizeof(cell_t);
+
+ if (prop->val.len == 0) {
+ if (p_addr_cells != c_addr_cells)
+ FAIL(c, "%s has empty \"ranges\" property but its "
+ "#address-cells (%d) differs from %s (%d)",
+ node->fullpath, c_addr_cells, node->parent->fullpath,
+ p_addr_cells);
+ if (p_size_cells != c_size_cells)
+ FAIL(c, "%s has empty \"ranges\" property but its "
+ "#size-cells (%d) differs from %s (%d)",
+ node->fullpath, c_size_cells, node->parent->fullpath,
+ p_size_cells);
+ } else if ((prop->val.len % entrylen) != 0) {
+ FAIL(c, "\"ranges\" property in %s has invalid length (%d bytes) "
+ "(parent #address-cells == %d, child #address-cells == %d, "
+ "#size-cells == %d)", node->fullpath, prop->val.len,
+ p_addr_cells, c_addr_cells, c_size_cells);
+ }
+}
+NODE_CHECK(ranges_format, NULL, WARN, &addr_size_cells);
+
+/*
+ * Style checks
+ */
+static void check_avoid_default_addr_size(struct check *c, struct node *dt,
+ struct node *node)
+{
+ struct property *reg, *ranges;
+
+ if (!node->parent)
+ return; /* Ignore root node */
+
+ reg = get_property(node, "reg");
+ ranges = get_property(node, "ranges");
+
+ if (!reg && !ranges)
+ return;
+
+ if ((node->parent->addr_cells == -1))
+ FAIL(c, "Relying on default #address-cells value for %s",
+ node->fullpath);
+
+ if ((node->parent->size_cells == -1))
+ FAIL(c, "Relying on default #size-cells value for %s",
+ node->fullpath);
+}
+NODE_CHECK(avoid_default_addr_size, NULL, WARN, &addr_size_cells);
+
+static void check_obsolete_chosen_interrupt_controller(struct check *c,
+ struct node *dt)
+{
+ struct node *chosen;
+ struct property *prop;
+
+ chosen = get_node_by_path(dt, "/chosen");
+ if (!chosen)
+ return;
+
+ prop = get_property(chosen, "interrupt-controller");
+ if (prop)
+ FAIL(c, "/chosen has obsolete \"interrupt-controller\" "
+ "property");
+}
+TREE_CHECK(obsolete_chosen_interrupt_controller, NULL, WARN);
+
+static struct check *check_table[] = {
+ &duplicate_node_names, &duplicate_property_names,
+ &node_name_chars, &node_name_format, &property_name_chars,
+ &name_is_string, &name_properties,
+ &explicit_phandles,
+ &phandle_references, &path_references,
+
+ &address_cells_is_cell, &size_cells_is_cell, &interrupt_cells_is_cell,
+ &device_type_is_string, &model_is_string, &status_is_string,
+
+ &addr_size_cells, ®_format, &ranges_format,
+
+ &avoid_default_addr_size,
+ &obsolete_chosen_interrupt_controller,
+};
+
+void process_checks(int force, struct boot_info *bi)
+{
+ struct node *dt = bi->dt;
+ int i;
+ int error = 0;
+
+ for (i = 0; i < ARRAY_SIZE(check_table); i++) {
+ struct check *c = check_table[i];
+
+ if (c->level != IGNORE)
+ error = error || run_check(c, dt);
+ }
+
+ if (error) {
+ if (!force) {
+ fprintf(stderr, "ERROR: Input tree has errors, aborting "
+ "(use -f to force output)\n");
+ exit(2);
+ } else if (quiet < 3) {
+ fprintf(stderr, "Warning: Input tree has errors, "
+ "output forced\n");
+ }
+ }
+}
--- /dev/null
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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 "dtc.h"
+
+void data_free(struct data d)
+{
+ struct marker *m, *nm;
+
+ m = d.markers;
+ while (m) {
+ nm = m->next;
+ free(m->ref);
+ free(m);
+ m = nm;
+ }
+
+ if (d.val)
+ free(d.val);
+}
+
+struct data data_grow_for(struct data d, int xlen)
+{
+ struct data nd;
+ int newsize;
+
+ if (xlen == 0)
+ return d;
+
+ nd = d;
+
+ newsize = xlen;
+
+ while ((d.len + xlen) > newsize)
+ newsize *= 2;
+
+ nd.val = xrealloc(d.val, newsize);
+
+ return nd;
+}
+
+struct data data_copy_mem(const char *mem, int len)
+{
+ struct data d;
+
+ d = data_grow_for(empty_data, len);
+
+ d.len = len;
+ memcpy(d.val, mem, len);
+
+ return d;
+}
+
+static char get_oct_char(const char *s, int *i)
+{
+ char x[4];
+ char *endx;
+ long val;
+
+ x[3] = '\0';
+ strncpy(x, s + *i, 3);
+
+ val = strtol(x, &endx, 8);
+
+ assert(endx > x);
+
+ (*i) += endx - x;
+ return val;
+}
+
+static char get_hex_char(const char *s, int *i)
+{
+ char x[3];
+ char *endx;
+ long val;
+
+ x[2] = '\0';
+ strncpy(x, s + *i, 2);
+
+ val = strtol(x, &endx, 16);
+ if (!(endx > x))
+ die("\\x used with no following hex digits\n");
+
+ (*i) += endx - x;
+ return val;
+}
+
+struct data data_copy_escape_string(const char *s, int len)
+{
+ int i = 0;
+ struct data d;
+ char *q;
+
+ d = data_grow_for(empty_data, strlen(s)+1);
+
+ q = d.val;
+ while (i < len) {
+ char c = s[i++];
+
+ if (c != '\\') {
+ q[d.len++] = c;
+ continue;
+ }
+
+ c = s[i++];
+ assert(c);
+ switch (c) {
+ case 'a':
+ q[d.len++] = '\a';
+ break;
+ case 'b':
+ q[d.len++] = '\b';
+ break;
+ case 't':
+ q[d.len++] = '\t';
+ break;
+ case 'n':
+ q[d.len++] = '\n';
+ break;
+ case 'v':
+ q[d.len++] = '\v';
+ break;
+ case 'f':
+ q[d.len++] = '\f';
+ break;
+ case 'r':
+ q[d.len++] = '\r';
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ i--; /* need to re-read the first digit as
+ * part of the octal value */
+ q[d.len++] = get_oct_char(s, &i);
+ break;
+ case 'x':
+ q[d.len++] = get_hex_char(s, &i);
+ break;
+ default:
+ q[d.len++] = c;
+ }
+ }
+
+ q[d.len++] = '\0';
+ return d;
+}
+
+struct data data_copy_file(FILE *f, size_t maxlen)
+{
+ struct data d = empty_data;
+
+ while (!feof(f) && (d.len < maxlen)) {
+ size_t chunksize, ret;
+
+ if (maxlen == -1)
+ chunksize = 4096;
+ else
+ chunksize = maxlen - d.len;
+
+ d = data_grow_for(d, chunksize);
+ ret = fread(d.val + d.len, 1, chunksize, f);
+
+ if (ferror(f))
+ die("Error reading file into data: %s", strerror(errno));
+
+ if (d.len + ret < d.len)
+ die("Overflow reading file into data\n");
+
+ d.len += ret;
+ }
+
+ return d;
+}
+
+struct data data_append_data(struct data d, const void *p, int len)
+{
+ d = data_grow_for(d, len);
+ memcpy(d.val + d.len, p, len);
+ d.len += len;
+ return d;
+}
+
+struct data data_insert_at_marker(struct data d, struct marker *m,
+ const void *p, int len)
+{
+ d = data_grow_for(d, len);
+ memmove(d.val + m->offset + len, d.val + m->offset, d.len - m->offset);
+ memcpy(d.val + m->offset, p, len);
+ d.len += len;
+
+ /* Adjust all markers after the one we're inserting at */
+ m = m->next;
+ for_each_marker(m)
+ m->offset += len;
+ return d;
+}
+
+struct data data_append_markers(struct data d, struct marker *m)
+{
+ struct marker **mp = &d.markers;
+
+ /* Find the end of the markerlist */
+ while (*mp)
+ mp = &((*mp)->next);
+ *mp = m;
+ return d;
+}
+
+struct data data_merge(struct data d1, struct data d2)
+{
+ struct data d;
+ struct marker *m2 = d2.markers;
+
+ d = data_append_markers(data_append_data(d1, d2.val, d2.len), m2);
+
+ /* Adjust for the length of d1 */
+ for_each_marker(m2)
+ m2->offset += d1.len;
+
+ d2.markers = NULL; /* So data_free() doesn't clobber them */
+ data_free(d2);
+
+ return d;
+}
+
+struct data data_append_cell(struct data d, cell_t word)
+{
+ cell_t beword = cpu_to_fdt32(word);
+
+ return data_append_data(d, &beword, sizeof(beword));
+}
+
+struct data data_append_re(struct data d, const struct fdt_reserve_entry *re)
+{
+ struct fdt_reserve_entry bere;
+
+ bere.address = cpu_to_fdt64(re->address);
+ bere.size = cpu_to_fdt64(re->size);
+
+ return data_append_data(d, &bere, sizeof(bere));
+}
+
+struct data data_append_addr(struct data d, uint64_t addr)
+{
+ uint64_t beaddr = cpu_to_fdt64(addr);
+
+ return data_append_data(d, &beaddr, sizeof(beaddr));
+}
+
+struct data data_append_byte(struct data d, uint8_t byte)
+{
+ return data_append_data(d, &byte, 1);
+}
+
+struct data data_append_zeroes(struct data d, int len)
+{
+ d = data_grow_for(d, len);
+
+ memset(d.val + d.len, 0, len);
+ d.len += len;
+ return d;
+}
+
+struct data data_append_align(struct data d, int align)
+{
+ int newlen = ALIGN(d.len, align);
+ return data_append_zeroes(d, newlen - d.len);
+}
+
+struct data data_add_marker(struct data d, enum markertype type, char *ref)
+{
+ struct marker *m;
+
+ m = xmalloc(sizeof(*m));
+ m->offset = d.len;
+ m->type = type;
+ m->ref = ref;
+ m->next = NULL;
+
+ return data_append_markers(d, m);
+}
+
+int data_is_one_string(struct data d)
+{
+ int i;
+ int len = d.len;
+
+ if (len == 0)
+ return 0;
+
+ for (i = 0; i < len-1; i++)
+ if (d.val[i] == '\0')
+ return 0;
+
+ if (d.val[len-1] != '\0')
+ return 0;
+
+ return 1;
+}
--- /dev/null
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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
+ */
+
+%option noyywrap nounput yylineno
+
+%x INCLUDE
+%x BYTESTRING
+%x PROPNODENAME
+%s V1
+
+PROPNODECHAR [a-zA-Z0-9,._+*#?@-]
+PATHCHAR ({PROPNODECHAR}|[/])
+LABEL [a-zA-Z_][a-zA-Z0-9_]*
+STRING \"([^\\"]|\\.)*\"
+WS [[:space:]]
+COMMENT "/*"([^*]|\*+[^*/])*\*+"/"
+LINECOMMENT "//".*\n
+
+%{
+#include "dtc.h"
+#include "srcpos.h"
+#include "dtc-parser.tab.h"
+
+
+/*#define LEXDEBUG 1*/
+
+#ifdef LEXDEBUG
+#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
+#else
+#define DPRINT(fmt, ...) do { } while (0)
+#endif
+
+static int dts_version; /* = 0 */
+
+#define BEGIN_DEFAULT() if (dts_version == 0) { \
+ DPRINT("<INITIAL>\n"); \
+ BEGIN(INITIAL); \
+ } else { \
+ DPRINT("<V1>\n"); \
+ BEGIN(V1); \
+ }
+
+static void push_input_file(const char *filename);
+static int pop_input_file(void);
+%}
+
+%%
+<*>"/include/"{WS}*{STRING} {
+ char *name = strchr(yytext, '\"') + 1;
+ yytext[yyleng-1] = '\0';
+ push_input_file(name);
+ }
+
+<*><<EOF>> {
+ if (!pop_input_file()) {
+ yyterminate();
+ }
+ }
+
+<*>{STRING} {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("String: %s\n", yytext);
+ yylval.data = data_copy_escape_string(yytext+1,
+ yyleng-2);
+ yylloc.first_line = yylineno;
+ return DT_STRING;
+ }
+
+<*>"/dts-v1/" {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Keyword: /dts-v1/\n");
+ dts_version = 1;
+ BEGIN_DEFAULT();
+ return DT_V1;
+ }
+
+<*>"/memreserve/" {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Keyword: /memreserve/\n");
+ BEGIN_DEFAULT();
+ return DT_MEMRESERVE;
+ }
+
+<*>{LABEL}: {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Label: %s\n", yytext);
+ yylval.labelref = strdup(yytext);
+ yylval.labelref[yyleng-1] = '\0';
+ return DT_LABEL;
+ }
+
+<INITIAL>[bodh]# {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ if (*yytext == 'b')
+ yylval.cbase = 2;
+ else if (*yytext == 'o')
+ yylval.cbase = 8;
+ else if (*yytext == 'd')
+ yylval.cbase = 10;
+ else
+ yylval.cbase = 16;
+ DPRINT("Base: %d\n", yylval.cbase);
+ return DT_BASE;
+ }
+
+<INITIAL>[0-9a-fA-F]+ {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ yylval.literal = strdup(yytext);
+ DPRINT("Literal: '%s'\n", yylval.literal);
+ return DT_LEGACYLITERAL;
+ }
+
+<V1>[0-9]+|0[xX][0-9a-fA-F]+ {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ yylval.literal = strdup(yytext);
+ DPRINT("Literal: '%s'\n", yylval.literal);
+ return DT_LITERAL;
+ }
+
+\&{LABEL} { /* label reference */
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Ref: %s\n", yytext+1);
+ yylval.labelref = strdup(yytext+1);
+ return DT_REF;
+ }
+
+"&{/"{PATHCHAR}+\} { /* new-style path reference */
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ yytext[yyleng-1] = '\0';
+ DPRINT("Ref: %s\n", yytext+2);
+ yylval.labelref = strdup(yytext+2);
+ return DT_REF;
+ }
+
+<INITIAL>"&/"{PATHCHAR}+ { /* old-style path reference */
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Ref: %s\n", yytext+1);
+ yylval.labelref = strdup(yytext+1);
+ return DT_REF;
+ }
+
+<BYTESTRING>[0-9a-fA-F]{2} {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ yylval.byte = strtol(yytext, NULL, 16);
+ DPRINT("Byte: %02x\n", (int)yylval.byte);
+ return DT_BYTE;
+ }
+
+<BYTESTRING>"]" {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("/BYTESTRING\n");
+ BEGIN_DEFAULT();
+ return ']';
+ }
+
+<PROPNODENAME>{PROPNODECHAR}+ {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("PropNodeName: %s\n", yytext);
+ yylval.propnodename = strdup(yytext);
+ BEGIN_DEFAULT();
+ return DT_PROPNODENAME;
+ }
+
+"/incbin/" {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Binary Include\n");
+ return DT_INCBIN;
+ }
+
+<*>{WS}+ /* eat whitespace */
+<*>{COMMENT}+ /* eat C-style comments */
+<*>{LINECOMMENT}+ /* eat C++-style comments */
+
+<*>. {
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Char: %c (\\x%02x)\n", yytext[0],
+ (unsigned)yytext[0]);
+ if (yytext[0] == '[') {
+ DPRINT("<BYTESTRING>\n");
+ BEGIN(BYTESTRING);
+ }
+ if ((yytext[0] == '{')
+ || (yytext[0] == ';')) {
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ }
+ return yytext[0];
+ }
+
+%%
+
+
+/*
+ * Stack of nested include file contexts.
+ */
+
+struct incl_file {
+ struct dtc_file *file;
+ YY_BUFFER_STATE yy_prev_buf;
+ int yy_prev_lineno;
+ struct incl_file *prev;
+};
+
+static struct incl_file *incl_file_stack;
+
+
+/*
+ * Detect infinite include recursion.
+ */
+#define MAX_INCLUDE_DEPTH (100)
+
+static int incl_depth = 0;
+
+
+static void push_input_file(const char *filename)
+{
+ struct incl_file *incl_file;
+ struct dtc_file *newfile;
+ struct search_path search, *searchptr = NULL;
+
+ assert(filename);
+
+ if (incl_depth++ >= MAX_INCLUDE_DEPTH)
+ die("Includes nested too deeply");
+
+ if (srcpos_file) {
+ search.dir = srcpos_file->dir;
+ search.next = NULL;
+ search.prev = NULL;
+ searchptr = &search;
+ }
+
+ newfile = dtc_open_file(filename, searchptr);
+
+ incl_file = xmalloc(sizeof(struct incl_file));
+
+ /*
+ * Save current context.
+ */
+ incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
+ incl_file->yy_prev_lineno = yylineno;
+ incl_file->file = srcpos_file;
+ incl_file->prev = incl_file_stack;
+
+ incl_file_stack = incl_file;
+
+ /*
+ * Establish new context.
+ */
+ srcpos_file = newfile;
+ yylineno = 1;
+ yyin = newfile->file;
+ yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
+}
+
+
+static int pop_input_file(void)
+{
+ struct incl_file *incl_file;
+
+ if (incl_file_stack == 0)
+ return 0;
+
+ dtc_close_file(srcpos_file);
+
+ /*
+ * Pop.
+ */
+ --incl_depth;
+ incl_file = incl_file_stack;
+ incl_file_stack = incl_file->prev;
+
+ /*
+ * Recover old context.
+ */
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(incl_file->yy_prev_buf);
+ yylineno = incl_file->yy_prev_lineno;
+ srcpos_file = incl_file->file;
+ yyin = incl_file->file ? incl_file->file->file : NULL;
+
+ /*
+ * Free old state.
+ */
+ free(incl_file);
+
+ return 1;
+}
--- /dev/null
+#line 2 "dtc-lexer.lex.c"
+
+#line 4 "dtc-lexer.lex.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 34
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+/* C99 requires __STDC__ to be defined as 1. */
+#if defined (__STDC__)
+
+#define YY_USE_CONST
+
+#endif /* defined (__STDC__) */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN (yy_start) = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START (((yy_start) - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE yyrestart(yyin )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+extern int yyleng;
+
+extern FILE *yyin, *yyout;
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ * access to the local variable yy_act. Since yyless() is a macro, it would break
+ * existing scanners that call yyless() from OUTSIDE yylex.
+ * One obvious solution it to make yy_act a global. I tried that, and saw
+ * a 5% performance hit in a non-yylineno scanner, because yy_act is
+ * normally declared as a register variable-- so it is not worth it.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < yyleng; ++yyl )\
+ if ( yytext[yyl] == '\n' )\
+ --yylineno;\
+ }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = (yy_hold_char); \
+ YY_RESTORE_YY_MORE_OFFSET \
+ (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, (yytext_ptr) )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ * Given that the standard has decreed that size_t exists since 1989,
+ * I guess we can afford to depend on it. Manoj.
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* Stack of input buffers. */
+static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+ ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+
+/* yy_hold_char holds the character lost when yytext is formed. */
+static char yy_hold_char;
+static int yy_n_chars; /* number of characters read into yy_ch_buf */
+int yyleng;
+
+/* Points to current character in buffer. */
+static char *yy_c_buf_p = (char *) 0;
+static int yy_init = 0; /* whether we need to initialize */
+static int yy_start = 0; /* start state number */
+
+/* Flag which is used to allow yywrap()'s to do buffer switches
+ * instead of setting up a fresh yyin. A bit of a hack ...
+ */
+static int yy_did_buffer_switch_on_eof;
+
+void yyrestart (FILE *input_file );
+void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
+void yy_delete_buffer (YY_BUFFER_STATE b );
+void yy_flush_buffer (YY_BUFFER_STATE b );
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
+void yypop_buffer_state (void );
+
+static void yyensure_buffer_stack (void );
+static void yy_load_buffer_state (void );
+static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
+
+#define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+
+YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
+YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
+YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,int len );
+
+void *yyalloc (yy_size_t );
+void *yyrealloc (void *,yy_size_t );
+void yyfree (void * );
+
+#define yy_new_buffer yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ yyensure_buffer_stack (); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ yy_create_buffer(yyin,YY_BUF_SIZE ); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+#define yywrap(n) 1
+#define YY_SKIP_YYWRAP
+
+typedef unsigned char YY_CHAR;
+
+FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+
+typedef int yy_state_type;
+
+extern int yylineno;
+
+int yylineno = 1;
+
+extern char *yytext;
+#define yytext_ptr yytext
+
+static yy_state_type yy_get_previous_state (void );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+static int yy_get_next_buffer (void );
+static void yy_fatal_error (yyconst char msg[] );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ (yytext_ptr) = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ (yy_hold_char) = *yy_cp; \
+ *yy_cp = '\0'; \
+ (yy_c_buf_p) = yy_cp;
+
+#define YY_NUM_RULES 20
+#define YY_END_OF_BUFFER 21
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_accept[104] =
+ { 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 21, 19, 16, 16, 19, 19, 19, 7, 7, 19,
+ 7, 19, 19, 19, 19, 13, 14, 14, 19, 8,
+ 8, 16, 0, 2, 0, 0, 9, 0, 0, 0,
+ 0, 0, 0, 7, 7, 5, 0, 6, 0, 12,
+ 12, 14, 14, 8, 0, 11, 9, 0, 0, 0,
+ 0, 18, 0, 0, 0, 0, 8, 0, 17, 0,
+ 0, 0, 0, 0, 10, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 3, 15,
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+
+ 0, 4, 0
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 2, 2, 2, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 2, 1, 4, 5, 1, 1, 6, 1, 1,
+ 1, 7, 8, 8, 9, 8, 10, 11, 12, 13,
+ 13, 13, 13, 13, 13, 13, 13, 14, 1, 1,
+ 1, 1, 8, 8, 15, 15, 15, 15, 15, 15,
+ 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+ 16, 16, 16, 16, 16, 16, 16, 17, 16, 16,
+ 1, 18, 19, 1, 16, 1, 15, 20, 21, 22,
+
+ 23, 15, 16, 24, 25, 16, 16, 26, 27, 28,
+ 24, 16, 16, 29, 30, 31, 32, 33, 16, 17,
+ 16, 16, 34, 1, 35, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[36] =
+ { 0,
+ 1, 1, 1, 1, 2, 1, 2, 2, 2, 3,
+ 4, 4, 4, 5, 6, 7, 7, 1, 1, 6,
+ 6, 6, 6, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 8, 1
+ } ;
+
+static yyconst flex_int16_t yy_base[117] =
+ { 0,
+ 0, 0, 30, 0, 44, 0, 67, 0, 97, 105,
+ 302, 303, 35, 44, 40, 94, 112, 0, 129, 152,
+ 296, 295, 159, 0, 176, 303, 0, 116, 95, 165,
+ 49, 46, 102, 303, 296, 0, 0, 288, 290, 293,
+ 264, 266, 270, 0, 0, 303, 0, 303, 264, 303,
+ 0, 0, 195, 101, 0, 0, 0, 0, 284, 125,
+ 277, 265, 225, 230, 216, 218, 0, 202, 224, 221,
+ 217, 107, 196, 188, 303, 206, 179, 186, 178, 185,
+ 183, 162, 161, 150, 169, 160, 145, 125, 303, 303,
+ 137, 109, 190, 103, 203, 167, 108, 197, 303, 123,
+
+ 29, 303, 303, 215, 221, 226, 229, 234, 240, 246,
+ 250, 257, 265, 270, 275, 282
+ } ;
+
+static yyconst flex_int16_t yy_def[117] =
+ { 0,
+ 103, 1, 1, 3, 3, 5, 103, 7, 3, 3,
+ 103, 103, 103, 103, 104, 105, 103, 106, 103, 19,
+ 19, 20, 103, 107, 20, 103, 108, 109, 105, 103,
+ 103, 103, 104, 103, 104, 110, 111, 103, 112, 113,
+ 103, 103, 103, 106, 19, 103, 20, 103, 103, 103,
+ 20, 108, 109, 103, 114, 110, 111, 115, 112, 112,
+ 113, 103, 103, 103, 103, 103, 114, 115, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 116, 103, 116, 103, 116,
+
+ 103, 103, 0, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103
+ } ;
+
+static yyconst flex_int16_t yy_nxt[339] =
+ { 0,
+ 12, 13, 14, 15, 12, 16, 12, 12, 12, 17,
+ 18, 18, 18, 12, 19, 20, 20, 12, 12, 21,
+ 19, 21, 19, 22, 20, 20, 20, 20, 20, 20,
+ 20, 20, 20, 12, 12, 12, 32, 32, 102, 23,
+ 12, 12, 12, 34, 20, 32, 32, 32, 32, 20,
+ 20, 20, 20, 20, 24, 24, 24, 35, 25, 54,
+ 54, 54, 26, 25, 25, 25, 25, 12, 13, 14,
+ 15, 27, 12, 27, 27, 27, 23, 27, 27, 27,
+ 12, 28, 28, 28, 12, 12, 28, 28, 28, 28,
+ 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,
+
+ 12, 12, 29, 36, 103, 34, 17, 30, 31, 31,
+ 29, 54, 54, 54, 17, 30, 31, 31, 39, 35,
+ 52, 40, 52, 52, 52, 103, 78, 38, 38, 46,
+ 101, 60, 79, 41, 69, 97, 42, 94, 43, 45,
+ 45, 45, 46, 45, 47, 47, 93, 92, 45, 45,
+ 45, 45, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 39, 47, 91, 40, 90,
+ 99, 47, 47, 47, 47, 54, 54, 54, 89, 88,
+ 41, 55, 87, 49, 100, 43, 51, 51, 51, 86,
+ 51, 95, 95, 96, 85, 51, 51, 51, 51, 52,
+
+ 99, 52, 52, 52, 95, 95, 96, 84, 46, 83,
+ 82, 81, 39, 79, 100, 33, 33, 33, 33, 33,
+ 33, 33, 33, 37, 80, 77, 37, 37, 37, 44,
+ 40, 44, 50, 76, 50, 52, 75, 52, 74, 52,
+ 52, 53, 73, 53, 53, 53, 53, 56, 56, 56,
+ 72, 56, 56, 57, 71, 57, 57, 59, 59, 59,
+ 59, 59, 59, 59, 59, 61, 61, 61, 61, 61,
+ 61, 61, 61, 67, 70, 67, 68, 68, 68, 62,
+ 68, 68, 98, 98, 98, 98, 98, 98, 98, 98,
+ 60, 66, 65, 64, 63, 62, 60, 58, 103, 48,
+
+ 48, 103, 11, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103
+ } ;
+
+static yyconst flex_int16_t yy_chk[339] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 3, 13, 13, 101, 3,
+ 3, 3, 3, 15, 3, 14, 14, 32, 32, 3,
+ 3, 3, 3, 3, 5, 5, 5, 15, 5, 31,
+ 31, 31, 5, 5, 5, 5, 5, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+
+ 7, 7, 9, 16, 29, 33, 9, 9, 9, 9,
+ 10, 54, 54, 54, 10, 10, 10, 10, 17, 33,
+ 28, 17, 28, 28, 28, 100, 72, 16, 29, 28,
+ 97, 60, 72, 17, 60, 94, 17, 92, 17, 19,
+ 19, 19, 19, 19, 19, 19, 91, 88, 19, 19,
+ 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+ 19, 19, 20, 20, 20, 23, 20, 87, 23, 86,
+ 96, 20, 20, 20, 20, 30, 30, 30, 85, 84,
+ 23, 30, 83, 23, 96, 23, 25, 25, 25, 82,
+ 25, 93, 93, 93, 81, 25, 25, 25, 25, 53,
+
+ 98, 53, 53, 53, 95, 95, 95, 80, 53, 79,
+ 78, 77, 76, 74, 98, 104, 104, 104, 104, 104,
+ 104, 104, 104, 105, 73, 71, 105, 105, 105, 106,
+ 70, 106, 107, 69, 107, 108, 68, 108, 66, 108,
+ 108, 109, 65, 109, 109, 109, 109, 110, 110, 110,
+ 64, 110, 110, 111, 63, 111, 111, 112, 112, 112,
+ 112, 112, 112, 112, 112, 113, 113, 113, 113, 113,
+ 113, 113, 113, 114, 62, 114, 115, 115, 115, 61,
+ 115, 115, 116, 116, 116, 116, 116, 116, 116, 116,
+ 59, 49, 43, 42, 41, 40, 39, 38, 35, 22,
+
+ 21, 11, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103, 103, 103,
+ 103, 103, 103, 103, 103, 103, 103, 103
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[21] =
+ { 0,
+1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0,
+ 0, };
+
+static yy_state_type yy_last_accepting_state;
+static char *yy_last_accepting_cpos;
+
+extern int yy_flex_debug;
+int yy_flex_debug = 0;
+
+/* The intent behind this definition is that it'll catch
+ * any uses of REJECT which flex missed.
+ */
+#define REJECT reject_used_but_not_detected
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+char *yytext;
+#line 1 "dtc-lexer.l"
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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
+ */
+
+
+
+
+#line 37 "dtc-lexer.l"
+#include "dtc.h"
+#include "srcpos.h"
+#include "dtc-parser.tab.h"
+
+
+/*#define LEXDEBUG 1*/
+
+#ifdef LEXDEBUG
+#define DPRINT(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
+#else
+#define DPRINT(fmt, ...) do { } while (0)
+#endif
+
+static int dts_version; /* = 0 */
+
+#define BEGIN_DEFAULT() if (dts_version == 0) { \
+ DPRINT("<INITIAL>\n"); \
+ BEGIN(INITIAL); \
+ } else { \
+ DPRINT("<V1>\n"); \
+ BEGIN(V1); \
+ }
+
+static void push_input_file(const char *filename);
+static int pop_input_file(void);
+#line 638 "dtc-lexer.lex.c"
+
+#define INITIAL 0
+#define INCLUDE 1
+#define BYTESTRING 2
+#define PROPNODENAME 3
+#define V1 4
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+static int yy_init_globals (void );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int yywrap (void );
+#else
+extern int yywrap (void );
+#endif
+#endif
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int );
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * );
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (void );
+#else
+static int input (void );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ int n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int yylex (void);
+
+#define YY_DECL int yylex (void)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+
+#line 64 "dtc-lexer.l"
+
+#line 795 "dtc-lexer.lex.c"
+
+ if ( !(yy_init) )
+ {
+ (yy_init) = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ if ( ! (yy_start) )
+ (yy_start) = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
+
+ yy_load_buffer_state( );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = (yy_c_buf_p);
+
+ /* Support of yytext. */
+ *yy_cp = (yy_hold_char);
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = (yy_start);
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 104 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 303 );
+
+yy_find_action:
+ yy_act = yy_accept[yy_current_state];
+ if ( yy_act == 0 )
+ { /* have to back up */
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ yy_act = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ int yyl;
+ for ( yyl = 0; yyl < yyleng; ++yyl )
+ if ( yytext[yyl] == '\n' )
+
+ yylineno++;
+;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+ case 0: /* must back up */
+ /* undo the effects of YY_DO_BEFORE_ACTION */
+ *yy_cp = (yy_hold_char);
+ yy_cp = (yy_last_accepting_cpos);
+ yy_current_state = (yy_last_accepting_state);
+ goto yy_find_action;
+
+case 1:
+/* rule 1 can match eol */
+YY_RULE_SETUP
+#line 65 "dtc-lexer.l"
+{
+ char *name = strchr(yytext, '\"') + 1;
+ yytext[yyleng-1] = '\0';
+ push_input_file(name);
+ }
+ YY_BREAK
+case YY_STATE_EOF(INITIAL):
+case YY_STATE_EOF(INCLUDE):
+case YY_STATE_EOF(BYTESTRING):
+case YY_STATE_EOF(PROPNODENAME):
+case YY_STATE_EOF(V1):
+#line 71 "dtc-lexer.l"
+{
+ if (!pop_input_file()) {
+ yyterminate();
+ }
+ }
+ YY_BREAK
+case 2:
+/* rule 2 can match eol */
+YY_RULE_SETUP
+#line 77 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("String: %s\n", yytext);
+ yylval.data = data_copy_escape_string(yytext+1,
+ yyleng-2);
+ yylloc.first_line = yylineno;
+ return DT_STRING;
+ }
+ YY_BREAK
+case 3:
+YY_RULE_SETUP
+#line 87 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Keyword: /dts-v1/\n");
+ dts_version = 1;
+ BEGIN_DEFAULT();
+ return DT_V1;
+ }
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 96 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Keyword: /memreserve/\n");
+ BEGIN_DEFAULT();
+ return DT_MEMRESERVE;
+ }
+ YY_BREAK
+case 5:
+YY_RULE_SETUP
+#line 104 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Label: %s\n", yytext);
+ yylval.labelref = strdup(yytext);
+ yylval.labelref[yyleng-1] = '\0';
+ return DT_LABEL;
+ }
+ YY_BREAK
+case 6:
+YY_RULE_SETUP
+#line 113 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ if (*yytext == 'b')
+ yylval.cbase = 2;
+ else if (*yytext == 'o')
+ yylval.cbase = 8;
+ else if (*yytext == 'd')
+ yylval.cbase = 10;
+ else
+ yylval.cbase = 16;
+ DPRINT("Base: %d\n", yylval.cbase);
+ return DT_BASE;
+ }
+ YY_BREAK
+case 7:
+YY_RULE_SETUP
+#line 128 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ yylval.literal = strdup(yytext);
+ DPRINT("Literal: '%s'\n", yylval.literal);
+ return DT_LEGACYLITERAL;
+ }
+ YY_BREAK
+case 8:
+YY_RULE_SETUP
+#line 136 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ yylval.literal = strdup(yytext);
+ DPRINT("Literal: '%s'\n", yylval.literal);
+ return DT_LITERAL;
+ }
+ YY_BREAK
+case 9:
+YY_RULE_SETUP
+#line 144 "dtc-lexer.l"
+{ /* label reference */
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Ref: %s\n", yytext+1);
+ yylval.labelref = strdup(yytext+1);
+ return DT_REF;
+ }
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 152 "dtc-lexer.l"
+{ /* new-style path reference */
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ yytext[yyleng-1] = '\0';
+ DPRINT("Ref: %s\n", yytext+2);
+ yylval.labelref = strdup(yytext+2);
+ return DT_REF;
+ }
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 161 "dtc-lexer.l"
+{ /* old-style path reference */
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Ref: %s\n", yytext+1);
+ yylval.labelref = strdup(yytext+1);
+ return DT_REF;
+ }
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 169 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ yylval.byte = strtol(yytext, NULL, 16);
+ DPRINT("Byte: %02x\n", (int)yylval.byte);
+ return DT_BYTE;
+ }
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 177 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("/BYTESTRING\n");
+ BEGIN_DEFAULT();
+ return ']';
+ }
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 185 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("PropNodeName: %s\n", yytext);
+ yylval.propnodename = strdup(yytext);
+ BEGIN_DEFAULT();
+ return DT_PROPNODENAME;
+ }
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 194 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Binary Include\n");
+ return DT_INCBIN;
+ }
+ YY_BREAK
+case 16:
+/* rule 16 can match eol */
+YY_RULE_SETUP
+#line 201 "dtc-lexer.l"
+/* eat whitespace */
+ YY_BREAK
+case 17:
+/* rule 17 can match eol */
+YY_RULE_SETUP
+#line 202 "dtc-lexer.l"
+/* eat C-style comments */
+ YY_BREAK
+case 18:
+/* rule 18 can match eol */
+YY_RULE_SETUP
+#line 203 "dtc-lexer.l"
+/* eat C++-style comments */
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 205 "dtc-lexer.l"
+{
+ yylloc.file = srcpos_file;
+ yylloc.first_line = yylineno;
+ DPRINT("Char: %c (\\x%02x)\n", yytext[0],
+ (unsigned)yytext[0]);
+ if (yytext[0] == '[') {
+ DPRINT("<BYTESTRING>\n");
+ BEGIN(BYTESTRING);
+ }
+ if ((yytext[0] == '{')
+ || (yytext[0] == ';')) {
+ DPRINT("<PROPNODENAME>\n");
+ BEGIN(PROPNODENAME);
+ }
+ return yytext[0];
+ }
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 222 "dtc-lexer.l"
+ECHO;
+ YY_BREAK
+#line 1120 "dtc-lexer.lex.c"
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = (yy_hold_char);
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state );
+
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++(yy_c_buf_p);
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = (yy_c_buf_p);
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ (yy_did_buffer_switch_on_eof) = 0;
+
+ if ( yywrap( ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) =
+ (yytext_ptr) + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ (yy_c_buf_p) =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+
+ yy_current_state = yy_get_previous_state( );
+
+ yy_cp = (yy_c_buf_p);
+ yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (void)
+{
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = (yytext_ptr);
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ /* just a shorter name for the current buffer */
+ YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+
+ int yy_c_buf_p_offset =
+ (int) ((yy_c_buf_p) - b->yy_ch_buf);
+
+ if ( b->yy_is_our_buffer )
+ {
+ int new_size = b->yy_buf_size * 2;
+
+ if ( new_size <= 0 )
+ b->yy_buf_size += b->yy_buf_size / 8;
+ else
+ b->yy_buf_size *= 2;
+
+ b->yy_ch_buf = (char *)
+ /* Include room in for 2 EOB chars. */
+ yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 );
+ }
+ else
+ /* Can't grow it, we don't own it. */
+ b->yy_ch_buf = 0;
+
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR(
+ "fatal error - scanner input buffer overflow" );
+
+ (yy_c_buf_p) = &b->yy_ch_buf[yy_c_buf_p_offset];
+
+ num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size -
+ number_to_move - 1;
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ (yy_n_chars), (size_t) num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ if ( (yy_n_chars) == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ yyrestart(yyin );
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+ /* Extend the array by 50%, plus the number we really need. */
+ yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
+ if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+ }
+
+ (yy_n_chars) += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+
+ (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (void)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+
+ yy_current_state = (yy_start);
+
+ for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 104 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+{
+ register int yy_is_jam;
+ register char *yy_cp = (yy_c_buf_p);
+
+ register YY_CHAR yy_c = 1;
+ if ( yy_accept[yy_current_state] )
+ {
+ (yy_last_accepting_state) = yy_current_state;
+ (yy_last_accepting_cpos) = yy_cp;
+ }
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 104 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 103);
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (void)
+#else
+ static int input (void)
+#endif
+
+{
+ int c;
+
+ *(yy_c_buf_p) = (yy_hold_char);
+
+ if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+ /* This was really a NUL. */
+ *(yy_c_buf_p) = '\0';
+
+ else
+ { /* need more input */
+ int offset = (yy_c_buf_p) - (yytext_ptr);
+ ++(yy_c_buf_p);
+
+ switch ( yy_get_next_buffer( ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ yyrestart(yyin );
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( yywrap( ) )
+ return EOF;
+
+ if ( ! (yy_did_buffer_switch_on_eof) )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput();
+#else
+ return input();
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ (yy_c_buf_p) = (yytext_ptr) + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+ *(yy_c_buf_p) = '\0'; /* preserve yytext */
+ (yy_hold_char) = *++(yy_c_buf_p);
+
+ if ( c == '\n' )
+
+ yylineno++;
+;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ *
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void yyrestart (FILE * input_file )
+{
+
+ if ( ! YY_CURRENT_BUFFER ){
+ yyensure_buffer_stack ();
+ YY_CURRENT_BUFFER_LVALUE =
+ yy_create_buffer(yyin,YY_BUF_SIZE );
+ }
+
+ yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+ yy_load_buffer_state( );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ *
+ */
+ void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+{
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * yypop_buffer_state();
+ * yypush_buffer_state(new_buffer);
+ */
+ yyensure_buffer_stack ();
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ yy_load_buffer_state( );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (yywrap()) processing, but the only time this flag
+ * is looked at is after yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+static void yy_load_buffer_state (void)
+{
+ (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ (yy_hold_char) = *(yy_c_buf_p);
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ *
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ yy_init_buffer(b,file );
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with yy_create_buffer()
+ *
+ */
+ void yy_delete_buffer (YY_BUFFER_STATE b )
+{
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ yyfree((void *) b->yy_ch_buf );
+
+ yyfree((void *) b );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a yyrestart() or at EOF.
+ */
+ static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+
+{
+ int oerrno = errno;
+
+ yy_flush_buffer(b );
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then yy_init_buffer was _probably_
+ * called from yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ *
+ */
+ void yy_flush_buffer (YY_BUFFER_STATE b )
+{
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ yy_load_buffer_state( );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ *
+ */
+void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+{
+ if (new_buffer == NULL)
+ return;
+
+ yyensure_buffer_stack();
+
+ /* This block is copied from yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *(yy_c_buf_p) = (yy_hold_char);
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ (yy_buffer_stack_top)++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from yy_switch_to_buffer. */
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ *
+ */
+void yypop_buffer_state (void)
+{
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if ((yy_buffer_stack_top) > 0)
+ --(yy_buffer_stack_top);
+
+ if (YY_CURRENT_BUFFER) {
+ yy_load_buffer_state( );
+ (yy_did_buffer_switch_on_eof) = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void yyensure_buffer_stack (void)
+{
+ int num_to_alloc;
+
+ if (!(yy_buffer_stack)) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ (yy_buffer_stack_max) = num_to_alloc;
+ (yy_buffer_stack_top) = 0;
+ return;
+ }
+
+ if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = (yy_buffer_stack_max) + grow_size;
+ (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+ ((yy_buffer_stack),
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ );
+ if ( ! (yy_buffer_stack) )
+ YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+
+ /* zero only the new slots.*/
+ memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+ (yy_buffer_stack_max) = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ yy_switch_to_buffer(b );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ *
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+{
+
+ return yy_scan_bytes(yystr,strlen(yystr) );
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ *
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, int _yybytes_len )
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) yyalloc(n );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = yy_scan_buffer(buf,n );
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg )
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = (yy_hold_char); \
+ (yy_c_buf_p) = yytext + yyless_macro_arg; \
+ (yy_hold_char) = *(yy_c_buf_p); \
+ *(yy_c_buf_p) = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the current line number.
+ *
+ */
+int yyget_lineno (void)
+{
+
+ return yylineno;
+}
+
+/** Get the input stream.
+ *
+ */
+FILE *yyget_in (void)
+{
+ return yyin;
+}
+
+/** Get the output stream.
+ *
+ */
+FILE *yyget_out (void)
+{
+ return yyout;
+}
+
+/** Get the length of the current token.
+ *
+ */
+int yyget_leng (void)
+{
+ return yyleng;
+}
+
+/** Get the current token.
+ *
+ */
+
+char *yyget_text (void)
+{
+ return yytext;
+}
+
+/** Set the current line number.
+ * @param line_number
+ *
+ */
+void yyset_lineno (int line_number )
+{
+
+ yylineno = line_number;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ *
+ * @see yy_switch_to_buffer
+ */
+void yyset_in (FILE * in_str )
+{
+ yyin = in_str ;
+}
+
+void yyset_out (FILE * out_str )
+{
+ yyout = out_str ;
+}
+
+int yyget_debug (void)
+{
+ return yy_flex_debug;
+}
+
+void yyset_debug (int bdebug )
+{
+ yy_flex_debug = bdebug ;
+}
+
+static int yy_init_globals (void)
+{
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from yylex_destroy(), so don't allocate here.
+ */
+
+ /* We do not touch yylineno unless the option is enabled. */
+ yylineno = 1;
+
+ (yy_buffer_stack) = 0;
+ (yy_buffer_stack_top) = 0;
+ (yy_buffer_stack_max) = 0;
+ (yy_c_buf_p) = (char *) 0;
+ (yy_init) = 0;
+ (yy_start) = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * yylex_init()
+ */
+ return 0;
+}
+
+/* yylex_destroy is for both reentrant and non-reentrant scanners. */
+int yylex_destroy (void)
+{
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ yy_delete_buffer(YY_CURRENT_BUFFER );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ yypop_buffer_state();
+ }
+
+ /* Destroy the stack itself. */
+ yyfree((yy_buffer_stack) );
+ (yy_buffer_stack) = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * yylex() is called, initialization will occur. */
+ yy_init_globals( );
+
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s )
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *yyalloc (yy_size_t size )
+{
+ return (void *) malloc( size );
+}
+
+void *yyrealloc (void * ptr, yy_size_t size )
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void yyfree (void * ptr )
+{
+ free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 222 "dtc-lexer.l"
+
+
+
+
+/*
+ * Stack of nested include file contexts.
+ */
+
+struct incl_file {
+ struct dtc_file *file;
+ YY_BUFFER_STATE yy_prev_buf;
+ int yy_prev_lineno;
+ struct incl_file *prev;
+};
+
+static struct incl_file *incl_file_stack;
+
+
+/*
+ * Detect infinite include recursion.
+ */
+#define MAX_INCLUDE_DEPTH (100)
+
+static int incl_depth = 0;
+
+
+static void push_input_file(const char *filename)
+{
+ struct incl_file *incl_file;
+ struct dtc_file *newfile;
+ struct search_path search, *searchptr = NULL;
+
+ assert(filename);
+
+ if (incl_depth++ >= MAX_INCLUDE_DEPTH)
+ die("Includes nested too deeply");
+
+ if (srcpos_file) {
+ search.dir = srcpos_file->dir;
+ search.next = NULL;
+ search.prev = NULL;
+ searchptr = &search;
+ }
+
+ newfile = dtc_open_file(filename, searchptr);
+
+ incl_file = xmalloc(sizeof(struct incl_file));
+
+ /*
+ * Save current context.
+ */
+ incl_file->yy_prev_buf = YY_CURRENT_BUFFER;
+ incl_file->yy_prev_lineno = yylineno;
+ incl_file->file = srcpos_file;
+ incl_file->prev = incl_file_stack;
+
+ incl_file_stack = incl_file;
+
+ /*
+ * Establish new context.
+ */
+ srcpos_file = newfile;
+ yylineno = 1;
+ yyin = newfile->file;
+ yy_switch_to_buffer(yy_create_buffer(yyin,YY_BUF_SIZE));
+}
+
+
+static int pop_input_file(void)
+{
+ struct incl_file *incl_file;
+
+ if (incl_file_stack == 0)
+ return 0;
+
+ dtc_close_file(srcpos_file);
+
+ /*
+ * Pop.
+ */
+ --incl_depth;
+ incl_file = incl_file_stack;
+ incl_file_stack = incl_file->prev;
+
+ /*
+ * Recover old context.
+ */
+ yy_delete_buffer(YY_CURRENT_BUFFER);
+ yy_switch_to_buffer(incl_file->yy_prev_buf);
+ yylineno = incl_file->yy_prev_lineno;
+ srcpos_file = incl_file->file;
+ yyin = incl_file->file ? incl_file->file->file : NULL;
+
+ /*
+ * Free old state.
+ */
+ free(incl_file);
+
+ return 1;
+}
+
--- /dev/null
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ 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, 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 0
+
+/* Using locations. */
+#define YYLSP_NEEDED 1
+
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ DT_V1 = 258,
+ DT_MEMRESERVE = 259,
+ DT_PROPNODENAME = 260,
+ DT_LITERAL = 261,
+ DT_LEGACYLITERAL = 262,
+ DT_BASE = 263,
+ DT_BYTE = 264,
+ DT_STRING = 265,
+ DT_LABEL = 266,
+ DT_REF = 267,
+ DT_INCBIN = 268
+ };
+#endif
+/* Tokens. */
+#define DT_V1 258
+#define DT_MEMRESERVE 259
+#define DT_PROPNODENAME 260
+#define DT_LITERAL 261
+#define DT_LEGACYLITERAL 262
+#define DT_BASE 263
+#define DT_BYTE 264
+#define DT_STRING 265
+#define DT_LABEL 266
+#define DT_REF 267
+#define DT_INCBIN 268
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 23 "dtc-parser.y"
+
+#include <stdio.h>
+
+#include "dtc.h"
+#include "srcpos.h"
+
+extern int yylex(void);
+
+extern struct boot_info *the_boot_info;
+extern int treesource_error;
+
+static unsigned long long eval_literal(const char *s, int base, int bits);
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 37 "dtc-parser.y"
+{
+ char *propnodename;
+ char *literal;
+ char *labelref;
+ unsigned int cbase;
+ uint8_t byte;
+ struct data data;
+
+ uint64_t addr;
+ cell_t cell;
+ struct property *prop;
+ struct property *proplist;
+ struct node *node;
+ struct node *nodelist;
+ struct reserve_info *re;
+}
+/* Line 187 of yacc.c. */
+#line 153 "dtc-parser.tab.c"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 216 of yacc.c. */
+#line 178 "dtc-parser.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
+#endif
+{
+ return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL \
+ && defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ YYLTYPE yyls;
+};
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \
+ + 2 * YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 9
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 73
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 27
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 20
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 45
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 76
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 268
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 24, 26, 2, 2, 25, 15, 2, 16, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 14,
+ 20, 19, 21, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 22, 2, 23, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 17, 2, 18, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 8, 11, 12, 15, 21, 22, 25,
+ 27, 34, 36, 38, 41, 47, 48, 51, 57, 61,
+ 64, 69, 74, 77, 87, 93, 96, 97, 100, 103,
+ 104, 107, 110, 113, 114, 116, 118, 121, 122, 125,
+ 128, 129, 132, 135, 139, 140
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 28, 0, -1, 3, 14, 29, 34, -1, 31, 34,
+ -1, -1, 30, 29, -1, 46, 4, 33, 33, 14,
+ -1, -1, 32, 31, -1, 30, -1, 46, 4, 33,
+ 15, 33, 14, -1, 6, -1, 7, -1, 16, 35,
+ -1, 17, 36, 44, 18, 14, -1, -1, 36, 37,
+ -1, 46, 5, 19, 38, 14, -1, 46, 5, 14,
+ -1, 39, 10, -1, 39, 20, 40, 21, -1, 39,
+ 22, 43, 23, -1, 39, 12, -1, 39, 13, 24,
+ 10, 25, 33, 25, 33, 26, -1, 39, 13, 24,
+ 10, 26, -1, 38, 11, -1, -1, 38, 25, -1,
+ 39, 11, -1, -1, 40, 42, -1, 40, 12, -1,
+ 40, 11, -1, -1, 8, -1, 6, -1, 41, 7,
+ -1, -1, 43, 9, -1, 43, 11, -1, -1, 45,
+ 44, -1, 45, 37, -1, 46, 5, 35, -1, -1,
+ 11, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 89, 89, 93, 101, 104, 111, 119, 122, 129,
+ 133, 140, 144, 151, 158, 166, 169, 176, 180, 187,
+ 191, 195, 199, 203, 220, 231, 239, 242, 246, 254,
+ 257, 261, 266, 274, 277, 281, 285, 293, 296, 300,
+ 308, 311, 315, 323, 331, 334
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "DT_V1", "DT_MEMRESERVE",
+ "DT_PROPNODENAME", "DT_LITERAL", "DT_LEGACYLITERAL", "DT_BASE",
+ "DT_BYTE", "DT_STRING", "DT_LABEL", "DT_REF", "DT_INCBIN", "';'", "'-'",
+ "'/'", "'{'", "'}'", "'='", "'<'", "'>'", "'['", "']'", "'('", "','",
+ "')'", "$accept", "sourcefile", "memreserves", "memreserve",
+ "v0_memreserves", "v0_memreserve", "addr", "devicetree", "nodedef",
+ "proplist", "propdef", "propdata", "propdataprefix", "celllist",
+ "cellbase", "cellval", "bytestring", "subnodes", "subnode", "label", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 59, 45, 47, 123, 125, 61,
+ 60, 62, 91, 93, 40, 44, 41
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 27, 28, 28, 29, 29, 30, 31, 31, 32,
+ 32, 33, 33, 34, 35, 36, 36, 37, 37, 38,
+ 38, 38, 38, 38, 38, 38, 39, 39, 39, 40,
+ 40, 40, 40, 41, 41, 42, 42, 43, 43, 43,
+ 44, 44, 44, 45, 46, 46
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 4, 2, 0, 2, 5, 0, 2, 1,
+ 6, 1, 1, 2, 5, 0, 2, 5, 3, 2,
+ 4, 4, 2, 9, 5, 2, 0, 2, 2, 0,
+ 2, 2, 2, 0, 1, 1, 2, 0, 2, 2,
+ 0, 2, 2, 3, 0, 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 7, 0, 45, 0, 9, 0, 7, 0, 4, 1,
+ 0, 3, 8, 0, 0, 4, 0, 15, 13, 11,
+ 12, 0, 2, 5, 0, 40, 0, 0, 0, 16,
+ 0, 40, 0, 0, 6, 0, 42, 41, 0, 10,
+ 14, 18, 26, 43, 0, 0, 25, 17, 27, 19,
+ 28, 22, 0, 29, 37, 0, 33, 0, 0, 35,
+ 34, 32, 31, 20, 0, 30, 38, 39, 21, 0,
+ 24, 36, 0, 0, 0, 23
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 3, 14, 4, 5, 6, 27, 11, 18, 25,
+ 29, 44, 45, 56, 64, 65, 57, 30, 31, 7
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -14
+static const yytype_int8 yypact[] =
+{
+ 30, -11, -14, 7, -14, -1, 27, 13, 27, -14,
+ 8, -14, -14, 40, -1, 27, 35, -14, -14, -14,
+ -14, 21, -14, -14, 40, 24, 40, 28, 40, -14,
+ 32, 24, 46, 38, -14, 39, -14, -14, 26, -14,
+ -14, -14, -14, -14, -9, 10, -14, -14, -14, -14,
+ -14, -14, 31, -14, -14, 44, -2, 3, 23, -14,
+ -14, -14, -14, -14, 50, -14, -14, -14, -14, 40,
+ -14, -14, 33, 40, 36, -14
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -14, -14, 48, 29, 53, -14, -13, 47, 34, -14,
+ 37, -14, -14, -14, -14, -14, -14, 42, -14, -7
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -45
+static const yytype_int8 yytable[] =
+{
+ 21, 16, 46, 8, 59, 47, 60, 9, 16, 61,
+ 62, 28, 66, 33, 67, 10, 48, 13, 32, 63,
+ 49, 50, 51, 52, 32, 17, 68, 19, 20, -44,
+ 53, -44, 54, 1, -44, 2, 26, 15, 2, 24,
+ 41, 2, 34, 17, 15, 42, 19, 20, 69, 70,
+ 35, 38, 39, 40, 58, 55, 72, 71, 73, 12,
+ 74, 22, 75, 23, 0, 0, 0, 0, 36, 0,
+ 0, 0, 43, 37
+};
+
+static const yytype_int8 yycheck[] =
+{
+ 13, 8, 11, 14, 6, 14, 8, 0, 15, 11,
+ 12, 24, 9, 26, 11, 16, 25, 4, 25, 21,
+ 10, 11, 12, 13, 31, 17, 23, 6, 7, 5,
+ 20, 4, 22, 3, 4, 11, 15, 8, 11, 4,
+ 14, 11, 14, 17, 15, 19, 6, 7, 25, 26,
+ 18, 5, 14, 14, 10, 24, 69, 7, 25, 6,
+ 73, 14, 26, 15, -1, -1, -1, -1, 31, -1,
+ -1, -1, 38, 31
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 11, 28, 30, 31, 32, 46, 14, 0,
+ 16, 34, 31, 4, 29, 30, 46, 17, 35, 6,
+ 7, 33, 34, 29, 4, 36, 15, 33, 33, 37,
+ 44, 45, 46, 33, 14, 18, 37, 44, 5, 14,
+ 14, 14, 19, 35, 38, 39, 11, 14, 25, 10,
+ 11, 12, 13, 20, 22, 24, 40, 43, 10, 6,
+ 8, 11, 12, 21, 41, 42, 9, 11, 23, 25,
+ 26, 7, 33, 25, 33, 26
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (YYLEX_PARAM)
+#else
+# define YYLEX yylex ()
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, Location); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+#endif
+{
+ if (!yyvaluep)
+ return;
+ YYUSE (yylocationp);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, YYLTYPE const * const yylocationp)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, yylocationp)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ YYLTYPE const * const yylocationp;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ YY_LOCATION_PRINT (yyoutput, *yylocationp);
+ YYFPRINTF (yyoutput, ": ");
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, yylocationp);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ yytype_int16 *bottom;
+ yytype_int16 *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, YYLTYPE *yylsp, int yyrule)
+#else
+static void
+yy_reduce_print (yyvsp, yylsp, yyrule)
+ YYSTYPE *yyvsp;
+ YYLTYPE *yylsp;
+ int yyrule;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , &(yylsp[(yyi + 1) - (yynrhs)]) );
+ fprintf (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, yylsp, Rule); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+\f
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+\f
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, YYLTYPE *yylocationp)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, yylocationp)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ YYLTYPE *yylocationp;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (yylocationp);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+\f
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+/* The look-ahead symbol. */
+int yychar;
+
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+/* Location data for the look-ahead symbol. */
+YYLTYPE yylloc;
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void)
+#else
+int
+yyparse ()
+
+#endif
+#endif
+{
+
+ int yystate;
+ int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+ /* The location stack. */
+ YYLTYPE yylsa[YYINITDEPTH];
+ YYLTYPE *yyls = yylsa;
+ YYLTYPE *yylsp;
+ /* The locations where the error started and ended. */
+ YYLTYPE yyerror_range[2];
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N), yylsp -= (N))
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+ YYLTYPE yyloc;
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+ yylsp = yyls;
+#if YYLTYPE_IS_TRIVIAL
+ /* Initialize the default location before parsing starts. */
+ yylloc.first_line = yylloc.last_line = 1;
+ yylloc.first_column = yylloc.last_column = 0;
+#endif
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+ YYLTYPE *yyls1 = yyls;
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+ &yyls1, yysize * sizeof (*yylsp),
+ &yystacksize);
+ yyls = yyls1;
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+ YYSTACK_RELOCATE (yyls);
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+ yylsp = yyls + yysize - 1;
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+ *++yylsp = yylloc;
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+ /* Default location. */
+ YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen);
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 2:
+#line 90 "dtc-parser.y"
+ {
+ the_boot_info = build_boot_info((yyvsp[(3) - (4)].re), (yyvsp[(4) - (4)].node), 0);
+ ;}
+ break;
+
+ case 3:
+#line 94 "dtc-parser.y"
+ {
+ the_boot_info = build_boot_info((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].node), 0);
+ ;}
+ break;
+
+ case 4:
+#line 101 "dtc-parser.y"
+ {
+ (yyval.re) = NULL;
+ ;}
+ break;
+
+ case 5:
+#line 105 "dtc-parser.y"
+ {
+ (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
+ ;}
+ break;
+
+ case 6:
+#line 112 "dtc-parser.y"
+ {
+ (yyval.re) = build_reserve_entry((yyvsp[(3) - (5)].addr), (yyvsp[(4) - (5)].addr), (yyvsp[(1) - (5)].labelref));
+ ;}
+ break;
+
+ case 7:
+#line 119 "dtc-parser.y"
+ {
+ (yyval.re) = NULL;
+ ;}
+ break;
+
+ case 8:
+#line 123 "dtc-parser.y"
+ {
+ (yyval.re) = chain_reserve_entry((yyvsp[(1) - (2)].re), (yyvsp[(2) - (2)].re));
+ ;}
+ break;
+
+ case 9:
+#line 130 "dtc-parser.y"
+ {
+ (yyval.re) = (yyvsp[(1) - (1)].re);
+ ;}
+ break;
+
+ case 10:
+#line 134 "dtc-parser.y"
+ {
+ (yyval.re) = build_reserve_entry((yyvsp[(3) - (6)].addr), (yyvsp[(5) - (6)].addr) - (yyvsp[(3) - (6)].addr) + 1, (yyvsp[(1) - (6)].labelref));
+ ;}
+ break;
+
+ case 11:
+#line 141 "dtc-parser.y"
+ {
+ (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 0, 64);
+ ;}
+ break;
+
+ case 12:
+#line 145 "dtc-parser.y"
+ {
+ (yyval.addr) = eval_literal((yyvsp[(1) - (1)].literal), 16, 64);
+ ;}
+ break;
+
+ case 13:
+#line 152 "dtc-parser.y"
+ {
+ (yyval.node) = name_node((yyvsp[(2) - (2)].node), "", NULL);
+ ;}
+ break;
+
+ case 14:
+#line 159 "dtc-parser.y"
+ {
+ (yyval.node) = build_node((yyvsp[(2) - (5)].proplist), (yyvsp[(3) - (5)].nodelist));
+ ;}
+ break;
+
+ case 15:
+#line 166 "dtc-parser.y"
+ {
+ (yyval.proplist) = NULL;
+ ;}
+ break;
+
+ case 16:
+#line 170 "dtc-parser.y"
+ {
+ (yyval.proplist) = chain_property((yyvsp[(2) - (2)].prop), (yyvsp[(1) - (2)].proplist));
+ ;}
+ break;
+
+ case 17:
+#line 177 "dtc-parser.y"
+ {
+ (yyval.prop) = build_property((yyvsp[(2) - (5)].propnodename), (yyvsp[(4) - (5)].data), (yyvsp[(1) - (5)].labelref));
+ ;}
+ break;
+
+ case 18:
+#line 181 "dtc-parser.y"
+ {
+ (yyval.prop) = build_property((yyvsp[(2) - (3)].propnodename), empty_data, (yyvsp[(1) - (3)].labelref));
+ ;}
+ break;
+
+ case 19:
+#line 188 "dtc-parser.y"
+ {
+ (yyval.data) = data_merge((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].data));
+ ;}
+ break;
+
+ case 20:
+#line 192 "dtc-parser.y"
+ {
+ (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+ ;}
+ break;
+
+ case 21:
+#line 196 "dtc-parser.y"
+ {
+ (yyval.data) = data_merge((yyvsp[(1) - (4)].data), (yyvsp[(3) - (4)].data));
+ ;}
+ break;
+
+ case 22:
+#line 200 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), REF_PATH, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+ case 23:
+#line 204 "dtc-parser.y"
+ {
+ struct search_path path = { srcpos_file->dir, NULL, NULL };
+ struct dtc_file *file = dtc_open_file((yyvsp[(4) - (9)].data).val, &path);
+ struct data d = empty_data;
+
+ if ((yyvsp[(6) - (9)].addr) != 0)
+ if (fseek(file->file, (yyvsp[(6) - (9)].addr), SEEK_SET) != 0)
+ yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
+ (unsigned long long)(yyvsp[(6) - (9)].addr),
+ (yyvsp[(4) - (9)].data).val, strerror(errno));
+
+ d = data_copy_file(file->file, (yyvsp[(8) - (9)].addr));
+
+ (yyval.data) = data_merge((yyvsp[(1) - (9)].data), d);
+ dtc_close_file(file);
+ ;}
+ break;
+
+ case 24:
+#line 221 "dtc-parser.y"
+ {
+ struct search_path path = { srcpos_file->dir, NULL, NULL };
+ struct dtc_file *file = dtc_open_file((yyvsp[(4) - (5)].data).val, &path);
+ struct data d = empty_data;
+
+ d = data_copy_file(file->file, -1);
+
+ (yyval.data) = data_merge((yyvsp[(1) - (5)].data), d);
+ dtc_close_file(file);
+ ;}
+ break;
+
+ case 25:
+#line 232 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+ case 26:
+#line 239 "dtc-parser.y"
+ {
+ (yyval.data) = empty_data;
+ ;}
+ break;
+
+ case 27:
+#line 243 "dtc-parser.y"
+ {
+ (yyval.data) = (yyvsp[(1) - (2)].data);
+ ;}
+ break;
+
+ case 28:
+#line 247 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+ case 29:
+#line 254 "dtc-parser.y"
+ {
+ (yyval.data) = empty_data;
+ ;}
+ break;
+
+ case 30:
+#line 258 "dtc-parser.y"
+ {
+ (yyval.data) = data_append_cell((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].cell));
+ ;}
+ break;
+
+ case 31:
+#line 262 "dtc-parser.y"
+ {
+ (yyval.data) = data_append_cell(data_add_marker((yyvsp[(1) - (2)].data), REF_PHANDLE,
+ (yyvsp[(2) - (2)].labelref)), -1);
+ ;}
+ break;
+
+ case 32:
+#line 267 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+ case 33:
+#line 274 "dtc-parser.y"
+ {
+ (yyval.cbase) = 16;
+ ;}
+ break;
+
+ case 35:
+#line 282 "dtc-parser.y"
+ {
+ (yyval.cell) = eval_literal((yyvsp[(1) - (1)].literal), 0, 32);
+ ;}
+ break;
+
+ case 36:
+#line 286 "dtc-parser.y"
+ {
+ (yyval.cell) = eval_literal((yyvsp[(2) - (2)].literal), (yyvsp[(1) - (2)].cbase), 32);
+ ;}
+ break;
+
+ case 37:
+#line 293 "dtc-parser.y"
+ {
+ (yyval.data) = empty_data;
+ ;}
+ break;
+
+ case 38:
+#line 297 "dtc-parser.y"
+ {
+ (yyval.data) = data_append_byte((yyvsp[(1) - (2)].data), (yyvsp[(2) - (2)].byte));
+ ;}
+ break;
+
+ case 39:
+#line 301 "dtc-parser.y"
+ {
+ (yyval.data) = data_add_marker((yyvsp[(1) - (2)].data), LABEL, (yyvsp[(2) - (2)].labelref));
+ ;}
+ break;
+
+ case 40:
+#line 308 "dtc-parser.y"
+ {
+ (yyval.nodelist) = NULL;
+ ;}
+ break;
+
+ case 41:
+#line 312 "dtc-parser.y"
+ {
+ (yyval.nodelist) = chain_node((yyvsp[(1) - (2)].node), (yyvsp[(2) - (2)].nodelist));
+ ;}
+ break;
+
+ case 42:
+#line 316 "dtc-parser.y"
+ {
+ yyerror("syntax error: properties must precede subnodes");
+ YYERROR;
+ ;}
+ break;
+
+ case 43:
+#line 324 "dtc-parser.y"
+ {
+ (yyval.node) = name_node((yyvsp[(3) - (3)].node), (yyvsp[(2) - (3)].propnodename), (yyvsp[(1) - (3)].labelref));
+ ;}
+ break;
+
+ case 44:
+#line 331 "dtc-parser.y"
+ {
+ (yyval.labelref) = NULL;
+ ;}
+ break;
+
+ case 45:
+#line 335 "dtc-parser.y"
+ {
+ (yyval.labelref) = (yyvsp[(1) - (1)].labelref);
+ ;}
+ break;
+
+
+/* Line 1267 of yacc.c. */
+#line 1780 "dtc-parser.tab.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+ *++yylsp = yyloc;
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (yymsg);
+ }
+ else
+ {
+ yyerror (YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+ yyerror_range[0] = yylloc;
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, &yylloc);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ yyerror_range[0] = yylsp[1-yylen];
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+ yyerror_range[0] = *yylsp;
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, yylsp);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ *++yyvsp = yylval;
+
+ yyerror_range[1] = yylloc;
+ /* Using YYLLOC is tempting, but would change the location of
+ the look-ahead. YYLOC is available though. */
+ YYLLOC_DEFAULT (yyloc, (yyerror_range - 1), 2);
+ *++yylsp = yyloc;
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, &yylloc);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, yylsp);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+#line 340 "dtc-parser.y"
+
+
+void yyerrorf(char const *s, ...)
+{
+ const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
+ va_list va;
+ va_start(va, s);
+
+ if (strcmp(fname, "-") == 0)
+ fname = "stdin";
+
+ fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
+ vfprintf(stderr, s, va);
+ fprintf(stderr, "\n");
+
+ treesource_error = 1;
+ va_end(va);
+}
+
+void yyerror (char const *s)
+{
+ yyerrorf("%s", s);
+}
+
+static unsigned long long eval_literal(const char *s, int base, int bits)
+{
+ unsigned long long val;
+ char *e;
+
+ errno = 0;
+ val = strtoull(s, &e, base);
+ if (*e)
+ yyerror("bad characters in literal");
+ else if ((errno == ERANGE)
+ || ((bits < 64) && (val >= (1ULL << bits))))
+ yyerror("literal out of range");
+ else if (errno != 0)
+ yyerror("bad literal");
+ return val;
+}
+
--- /dev/null
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ 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, 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ DT_V1 = 258,
+ DT_MEMRESERVE = 259,
+ DT_PROPNODENAME = 260,
+ DT_LITERAL = 261,
+ DT_LEGACYLITERAL = 262,
+ DT_BASE = 263,
+ DT_BYTE = 264,
+ DT_STRING = 265,
+ DT_LABEL = 266,
+ DT_REF = 267,
+ DT_INCBIN = 268
+ };
+#endif
+/* Tokens. */
+#define DT_V1 258
+#define DT_MEMRESERVE 259
+#define DT_PROPNODENAME 260
+#define DT_LITERAL 261
+#define DT_LEGACYLITERAL 262
+#define DT_BASE 263
+#define DT_BYTE 264
+#define DT_STRING 265
+#define DT_LABEL 266
+#define DT_REF 267
+#define DT_INCBIN 268
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 37 "dtc-parser.y"
+{
+ char *propnodename;
+ char *literal;
+ char *labelref;
+ unsigned int cbase;
+ uint8_t byte;
+ struct data data;
+
+ uint64_t addr;
+ cell_t cell;
+ struct property *prop;
+ struct property *proplist;
+ struct node *node;
+ struct node *nodelist;
+ struct reserve_info *re;
+}
+/* Line 1489 of yacc.c. */
+#line 92 "dtc-parser.tab.h"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYSTYPE yylval;
+
+#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED
+typedef struct YYLTYPE
+{
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+} YYLTYPE;
+# define yyltype YYLTYPE /* obsolescent; will be withdrawn */
+# define YYLTYPE_IS_DECLARED 1
+# define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+extern YYLTYPE yylloc;
--- /dev/null
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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
+ */
+
+%locations
+
+%{
+#include <stdio.h>
+
+#include "dtc.h"
+#include "srcpos.h"
+
+extern int yylex(void);
+
+extern struct boot_info *the_boot_info;
+extern int treesource_error;
+
+static unsigned long long eval_literal(const char *s, int base, int bits);
+%}
+
+%union {
+ char *propnodename;
+ char *literal;
+ char *labelref;
+ unsigned int cbase;
+ uint8_t byte;
+ struct data data;
+
+ uint64_t addr;
+ cell_t cell;
+ struct property *prop;
+ struct property *proplist;
+ struct node *node;
+ struct node *nodelist;
+ struct reserve_info *re;
+}
+
+%token DT_V1
+%token DT_MEMRESERVE
+%token <propnodename> DT_PROPNODENAME
+%token <literal> DT_LITERAL
+%token <literal> DT_LEGACYLITERAL
+%token <cbase> DT_BASE
+%token <byte> DT_BYTE
+%token <data> DT_STRING
+%token <labelref> DT_LABEL
+%token <labelref> DT_REF
+%token DT_INCBIN
+
+%type <data> propdata
+%type <data> propdataprefix
+%type <re> memreserve
+%type <re> memreserves
+%type <re> v0_memreserve
+%type <re> v0_memreserves
+%type <addr> addr
+%type <data> celllist
+%type <cbase> cellbase
+%type <cell> cellval
+%type <data> bytestring
+%type <prop> propdef
+%type <proplist> proplist
+
+%type <node> devicetree
+%type <node> nodedef
+%type <node> subnode
+%type <nodelist> subnodes
+%type <labelref> label
+
+%%
+
+sourcefile:
+ DT_V1 ';' memreserves devicetree
+ {
+ the_boot_info = build_boot_info($3, $4, 0);
+ }
+ | v0_memreserves devicetree
+ {
+ the_boot_info = build_boot_info($1, $2, 0);
+ }
+ ;
+
+memreserves:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | memreserve memreserves
+ {
+ $$ = chain_reserve_entry($1, $2);
+ }
+ ;
+
+memreserve:
+ label DT_MEMRESERVE addr addr ';'
+ {
+ $$ = build_reserve_entry($3, $4, $1);
+ }
+ ;
+
+v0_memreserves:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | v0_memreserve v0_memreserves
+ {
+ $$ = chain_reserve_entry($1, $2);
+ };
+ ;
+
+v0_memreserve:
+ memreserve
+ {
+ $$ = $1;
+ }
+ | label DT_MEMRESERVE addr '-' addr ';'
+ {
+ $$ = build_reserve_entry($3, $5 - $3 + 1, $1);
+ }
+ ;
+
+addr:
+ DT_LITERAL
+ {
+ $$ = eval_literal($1, 0, 64);
+ }
+ | DT_LEGACYLITERAL
+ {
+ $$ = eval_literal($1, 16, 64);
+ }
+ ;
+
+devicetree:
+ '/' nodedef
+ {
+ $$ = name_node($2, "", NULL);
+ }
+ ;
+
+nodedef:
+ '{' proplist subnodes '}' ';'
+ {
+ $$ = build_node($2, $3);
+ }
+ ;
+
+proplist:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | proplist propdef
+ {
+ $$ = chain_property($2, $1);
+ }
+ ;
+
+propdef:
+ label DT_PROPNODENAME '=' propdata ';'
+ {
+ $$ = build_property($2, $4, $1);
+ }
+ | label DT_PROPNODENAME ';'
+ {
+ $$ = build_property($2, empty_data, $1);
+ }
+ ;
+
+propdata:
+ propdataprefix DT_STRING
+ {
+ $$ = data_merge($1, $2);
+ }
+ | propdataprefix '<' celllist '>'
+ {
+ $$ = data_merge($1, $3);
+ }
+ | propdataprefix '[' bytestring ']'
+ {
+ $$ = data_merge($1, $3);
+ }
+ | propdataprefix DT_REF
+ {
+ $$ = data_add_marker($1, REF_PATH, $2);
+ }
+ | propdataprefix DT_INCBIN '(' DT_STRING ',' addr ',' addr ')'
+ {
+ struct search_path path = { srcpos_file->dir, NULL, NULL };
+ struct dtc_file *file = dtc_open_file($4.val, &path);
+ struct data d = empty_data;
+
+ if ($6 != 0)
+ if (fseek(file->file, $6, SEEK_SET) != 0)
+ yyerrorf("Couldn't seek to offset %llu in \"%s\": %s",
+ (unsigned long long)$6,
+ $4.val, strerror(errno));
+
+ d = data_copy_file(file->file, $8);
+
+ $$ = data_merge($1, d);
+ dtc_close_file(file);
+ }
+ | propdataprefix DT_INCBIN '(' DT_STRING ')'
+ {
+ struct search_path path = { srcpos_file->dir, NULL, NULL };
+ struct dtc_file *file = dtc_open_file($4.val, &path);
+ struct data d = empty_data;
+
+ d = data_copy_file(file->file, -1);
+
+ $$ = data_merge($1, d);
+ dtc_close_file(file);
+ }
+ | propdata DT_LABEL
+ {
+ $$ = data_add_marker($1, LABEL, $2);
+ }
+ ;
+
+propdataprefix:
+ /* empty */
+ {
+ $$ = empty_data;
+ }
+ | propdata ','
+ {
+ $$ = $1;
+ }
+ | propdataprefix DT_LABEL
+ {
+ $$ = data_add_marker($1, LABEL, $2);
+ }
+ ;
+
+celllist:
+ /* empty */
+ {
+ $$ = empty_data;
+ }
+ | celllist cellval
+ {
+ $$ = data_append_cell($1, $2);
+ }
+ | celllist DT_REF
+ {
+ $$ = data_append_cell(data_add_marker($1, REF_PHANDLE,
+ $2), -1);
+ }
+ | celllist DT_LABEL
+ {
+ $$ = data_add_marker($1, LABEL, $2);
+ }
+ ;
+
+cellbase:
+ /* empty */
+ {
+ $$ = 16;
+ }
+ | DT_BASE
+ ;
+
+cellval:
+ DT_LITERAL
+ {
+ $$ = eval_literal($1, 0, 32);
+ }
+ | cellbase DT_LEGACYLITERAL
+ {
+ $$ = eval_literal($2, $1, 32);
+ }
+ ;
+
+bytestring:
+ /* empty */
+ {
+ $$ = empty_data;
+ }
+ | bytestring DT_BYTE
+ {
+ $$ = data_append_byte($1, $2);
+ }
+ | bytestring DT_LABEL
+ {
+ $$ = data_add_marker($1, LABEL, $2);
+ }
+ ;
+
+subnodes:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | subnode subnodes
+ {
+ $$ = chain_node($1, $2);
+ }
+ | subnode propdef
+ {
+ yyerror("syntax error: properties must precede subnodes");
+ YYERROR;
+ }
+ ;
+
+subnode:
+ label DT_PROPNODENAME nodedef
+ {
+ $$ = name_node($3, $2, $1);
+ }
+ ;
+
+label:
+ /* empty */
+ {
+ $$ = NULL;
+ }
+ | DT_LABEL
+ {
+ $$ = $1;
+ }
+ ;
+
+%%
+
+void yyerrorf(char const *s, ...)
+{
+ const char *fname = srcpos_file ? srcpos_file->name : "<no-file>";
+ va_list va;
+ va_start(va, s);
+
+ if (strcmp(fname, "-") == 0)
+ fname = "stdin";
+
+ fprintf(stderr, "%s:%d ", fname, yylloc.first_line);
+ vfprintf(stderr, s, va);
+ fprintf(stderr, "\n");
+
+ treesource_error = 1;
+ va_end(va);
+}
+
+void yyerror (char const *s)
+{
+ yyerrorf("%s", s);
+}
+
+static unsigned long long eval_literal(const char *s, int base, int bits)
+{
+ unsigned long long val;
+ char *e;
+
+ errno = 0;
+ val = strtoull(s, &e, base);
+ if (*e)
+ yyerror("bad characters in literal");
+ else if ((errno == ERANGE)
+ || ((bits < 64) && (val >= (1ULL << bits))))
+ yyerror("literal out of range");
+ else if (errno != 0)
+ yyerror("bad literal");
+ return val;
+}
--- /dev/null
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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 "dtc.h"
+#include "srcpos.h"
+
+#include "version_gen.h"
+
+/*
+ * Command line options
+ */
+int quiet; /* Level of quietness */
+int reservenum; /* Number of memory reservation slots */
+int minsize; /* Minimum blob size */
+int padsize; /* Additional padding to blob */
+
+char *join_path(const char *path, const char *name)
+{
+ int lenp = strlen(path);
+ int lenn = strlen(name);
+ int len;
+ int needslash = 1;
+ char *str;
+
+ len = lenp + lenn + 2;
+ if ((lenp > 0) && (path[lenp-1] == '/')) {
+ needslash = 0;
+ len--;
+ }
+
+ str = xmalloc(len);
+ memcpy(str, path, lenp);
+ if (needslash) {
+ str[lenp] = '/';
+ lenp++;
+ }
+ memcpy(str+lenp, name, lenn+1);
+ return str;
+}
+
+static void fill_fullpaths(struct node *tree, const char *prefix)
+{
+ struct node *child;
+ const char *unit;
+
+ tree->fullpath = join_path(prefix, tree->name);
+
+ unit = strchr(tree->name, '@');
+ if (unit)
+ tree->basenamelen = unit - tree->name;
+ else
+ tree->basenamelen = strlen(tree->name);
+
+ for_each_child(tree, child)
+ fill_fullpaths(child, tree->fullpath);
+}
+
+static void __attribute__ ((noreturn)) usage(void)
+{
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\tdtc [options] <input file>\n");
+ fprintf(stderr, "\nOptions:\n");
+ fprintf(stderr, "\t-h\n");
+ fprintf(stderr, "\t\tThis help text\n");
+ fprintf(stderr, "\t-q\n");
+ fprintf(stderr, "\t\tQuiet: -q suppress warnings, -qq errors, -qqq all\n");
+ fprintf(stderr, "\t-I <input format>\n");
+ fprintf(stderr, "\t\tInput formats are:\n");
+ fprintf(stderr, "\t\t\tdts - device tree source text\n");
+ fprintf(stderr, "\t\t\tdtb - device tree blob\n");
+ fprintf(stderr, "\t\t\tfs - /proc/device-tree style directory\n");
+ fprintf(stderr, "\t-o <output file>\n");
+ fprintf(stderr, "\t-O <output format>\n");
+ fprintf(stderr, "\t\tOutput formats are:\n");
+ fprintf(stderr, "\t\t\tdts - device tree source text\n");
+ fprintf(stderr, "\t\t\tdtb - device tree blob\n");
+ fprintf(stderr, "\t\t\tasm - assembler source\n");
+ fprintf(stderr, "\t-V <output version>\n");
+ fprintf(stderr, "\t\tBlob version to produce, defaults to %d (relevant for dtb\n\t\tand asm output only)\n", DEFAULT_FDT_VERSION);
+ fprintf(stderr, "\t-R <number>\n");
+ fprintf(stderr, "\t\tMake space for <number> reserve map entries (relevant for \n\t\tdtb and asm output only)\n");
+ fprintf(stderr, "\t-S <bytes>\n");
+ fprintf(stderr, "\t\tMake the blob at least <bytes> long (extra space)\n");
+ fprintf(stderr, "\t-p <bytes>\n");
+ fprintf(stderr, "\t\tAdd padding to the blob of <bytes> long (extra space)\n");
+ fprintf(stderr, "\t-b <number>\n");
+ fprintf(stderr, "\t\tSet the physical boot cpu\n");
+ fprintf(stderr, "\t-f\n");
+ fprintf(stderr, "\t\tForce - try to produce output even if the input tree has errors\n");
+ fprintf(stderr, "\t-v\n");
+ fprintf(stderr, "\t\tPrint DTC version and exit\n");
+ exit(3);
+}
+
+int main(int argc, char *argv[])
+{
+ struct boot_info *bi;
+ const char *inform = "dts";
+ const char *outform = "dts";
+ const char *outname = "-";
+ int force = 0, check = 0;
+ const char *arg;
+ int opt;
+ FILE *outf = NULL;
+ int outversion = DEFAULT_FDT_VERSION;
+ long long cmdline_boot_cpuid = -1;
+
+ quiet = 0;
+ reservenum = 0;
+ minsize = 0;
+ padsize = 0;
+
+ while ((opt = getopt(argc, argv, "hI:O:o:V:R:S:p:fcqb:v")) != EOF) {
+ switch (opt) {
+ case 'I':
+ inform = optarg;
+ break;
+ case 'O':
+ outform = optarg;
+ break;
+ case 'o':
+ outname = optarg;
+ break;
+ case 'V':
+ outversion = strtol(optarg, NULL, 0);
+ break;
+ case 'R':
+ reservenum = strtol(optarg, NULL, 0);
+ break;
+ case 'S':
+ minsize = strtol(optarg, NULL, 0);
+ break;
+ case 'p':
+ padsize = strtol(optarg, NULL, 0);
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'c':
+ check = 1;
+ break;
+ case 'q':
+ quiet++;
+ break;
+ case 'b':
+ cmdline_boot_cpuid = strtoll(optarg, NULL, 0);
+ break;
+ case 'v':
+ printf("Version: %s\n", DTC_VERSION);
+ exit(0);
+ case 'h':
+ default:
+ usage();
+ }
+ }
+
+ if (argc > (optind+1))
+ usage();
+ else if (argc < (optind+1))
+ arg = "-";
+ else
+ arg = argv[optind];
+
+ /* minsize and padsize are mutually exclusive */
+ if (minsize && padsize)
+ die("Can't set both -p and -S\n");
+
+ fprintf(stderr, "DTC: %s->%s on file \"%s\"\n",
+ inform, outform, arg);
+
+ if (streq(inform, "dts"))
+ bi = dt_from_source(arg);
+ else if (streq(inform, "fs"))
+ bi = dt_from_fs(arg);
+ else if(streq(inform, "dtb"))
+ bi = dt_from_blob(arg);
+ else
+ die("Unknown input format \"%s\"\n", inform);
+
+ if (cmdline_boot_cpuid != -1)
+ bi->boot_cpuid_phys = cmdline_boot_cpuid;
+
+ fill_fullpaths(bi->dt, "");
+ process_checks(force, bi);
+
+
+ if (streq(outname, "-")) {
+ outf = stdout;
+ } else {
+ outf = fopen(outname, "w");
+ if (! outf)
+ die("Couldn't open output file %s: %s\n",
+ outname, strerror(errno));
+ }
+
+ if (streq(outform, "dts")) {
+ dt_to_source(outf, bi);
+ } else if (streq(outform, "dtb")) {
+ dt_to_blob(outf, bi, outversion);
+ } else if (streq(outform, "asm")) {
+ dt_to_asm(outf, bi, outversion);
+ } else if (streq(outform, "null")) {
+ /* do nothing */
+ } else {
+ die("Unknown output format \"%s\"\n", outform);
+ }
+
+ exit(0);
+}
--- /dev/null
+#ifndef _DTC_H
+#define _DTC_H
+
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <libfdt_env.h>
+#include <fdt.h>
+
+#define DEFAULT_FDT_VERSION 17
+/*
+ * Command line options
+ */
+extern int quiet; /* Level of quietness */
+extern int reservenum; /* Number of memory reservation slots */
+extern int minsize; /* Minimum blob size */
+extern int padsize; /* Additional padding to blob */
+
+static inline void __attribute__((noreturn)) die(char * str, ...)
+{
+ va_list ap;
+
+ va_start(ap, str);
+ fprintf(stderr, "FATAL ERROR: ");
+ vfprintf(stderr, str, ap);
+ exit(1);
+}
+
+static inline void *xmalloc(size_t len)
+{
+ void *new = malloc(len);
+
+ if (! new)
+ die("malloc() failed\n");
+
+ return new;
+}
+
+static inline void *xrealloc(void *p, size_t len)
+{
+ void *new = realloc(p, len);
+
+ if (! new)
+ die("realloc() failed (len=%d)\n", len);
+
+ return new;
+}
+
+typedef uint32_t cell_t;
+
+
+#define streq(a, b) (strcmp((a), (b)) == 0)
+#define strneq(a, b, n) (strncmp((a), (b), (n)) == 0)
+
+#define ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+/* Data blobs */
+enum markertype {
+ REF_PHANDLE,
+ REF_PATH,
+ LABEL,
+};
+
+struct marker {
+ enum markertype type;
+ int offset;
+ char *ref;
+ struct marker *next;
+};
+
+struct data {
+ int len;
+ char *val;
+ struct marker *markers;
+};
+
+
+#define empty_data ((struct data){ /* all .members = 0 or NULL */ })
+
+#define for_each_marker(m) \
+ for (; (m); (m) = (m)->next)
+#define for_each_marker_of_type(m, t) \
+ for_each_marker(m) \
+ if ((m)->type == (t))
+
+void data_free(struct data d);
+
+struct data data_grow_for(struct data d, int xlen);
+
+struct data data_copy_mem(const char *mem, int len);
+struct data data_copy_escape_string(const char *s, int len);
+struct data data_copy_file(FILE *f, size_t len);
+
+struct data data_append_data(struct data d, const void *p, int len);
+struct data data_insert_at_marker(struct data d, struct marker *m,
+ const void *p, int len);
+struct data data_merge(struct data d1, struct data d2);
+struct data data_append_cell(struct data d, cell_t word);
+struct data data_append_re(struct data d, const struct fdt_reserve_entry *re);
+struct data data_append_addr(struct data d, uint64_t addr);
+struct data data_append_byte(struct data d, uint8_t byte);
+struct data data_append_zeroes(struct data d, int len);
+struct data data_append_align(struct data d, int align);
+
+struct data data_add_marker(struct data d, enum markertype type, char *ref);
+
+int data_is_one_string(struct data d);
+
+/* DT constraints */
+
+#define MAX_PROPNAME_LEN 31
+#define MAX_NODENAME_LEN 31
+
+/* Live trees */
+struct property {
+ char *name;
+ struct data val;
+
+ struct property *next;
+
+ char *label;
+};
+
+struct node {
+ char *name;
+ struct property *proplist;
+ struct node *children;
+
+ struct node *parent;
+ struct node *next_sibling;
+
+ char *fullpath;
+ int basenamelen;
+
+ cell_t phandle;
+ int addr_cells, size_cells;
+
+ char *label;
+};
+
+#define for_each_property(n, p) \
+ for ((p) = (n)->proplist; (p); (p) = (p)->next)
+
+#define for_each_child(n, c) \
+ for ((c) = (n)->children; (c); (c) = (c)->next_sibling)
+
+struct property *build_property(char *name, struct data val, char *label);
+struct property *chain_property(struct property *first, struct property *list);
+struct property *reverse_properties(struct property *first);
+
+struct node *build_node(struct property *proplist, struct node *children);
+struct node *name_node(struct node *node, char *name, char *label);
+struct node *chain_node(struct node *first, struct node *list);
+
+void add_property(struct node *node, struct property *prop);
+void add_child(struct node *parent, struct node *child);
+
+const char *get_unitname(struct node *node);
+struct property *get_property(struct node *node, const char *propname);
+cell_t propval_cell(struct property *prop);
+struct node *get_subnode(struct node *node, const char *nodename);
+struct node *get_node_by_path(struct node *tree, const char *path);
+struct node *get_node_by_label(struct node *tree, const char *label);
+struct node *get_node_by_phandle(struct node *tree, cell_t phandle);
+struct node *get_node_by_ref(struct node *tree, const char *ref);
+cell_t get_node_phandle(struct node *root, struct node *node);
+
+/* Boot info (tree plus memreserve information */
+
+struct reserve_info {
+ struct fdt_reserve_entry re;
+
+ struct reserve_info *next;
+
+ char *label;
+};
+
+struct reserve_info *build_reserve_entry(uint64_t start, uint64_t len, char *label);
+struct reserve_info *chain_reserve_entry(struct reserve_info *first,
+ struct reserve_info *list);
+struct reserve_info *add_reserve_entry(struct reserve_info *list,
+ struct reserve_info *new);
+
+
+struct boot_info {
+ struct reserve_info *reservelist;
+ struct node *dt; /* the device tree */
+ uint32_t boot_cpuid_phys;
+};
+
+struct boot_info *build_boot_info(struct reserve_info *reservelist,
+ struct node *tree, uint32_t boot_cpuid_phys);
+
+/* Checks */
+
+void process_checks(int force, struct boot_info *bi);
+
+/* Flattened trees */
+
+void dt_to_blob(FILE *f, struct boot_info *bi, int version);
+void dt_to_asm(FILE *f, struct boot_info *bi, int version);
+
+struct boot_info *dt_from_blob(const char *fname);
+
+/* Tree source */
+
+void dt_to_source(FILE *f, struct boot_info *bi);
+struct boot_info *dt_from_source(const char *f);
+
+/* FS trees */
+
+struct boot_info *dt_from_fs(const char *dirname);
+
+/* misc */
+
+char *join_path(const char *path, const char *name);
+
+#endif /* _DTC_H */
--- /dev/null
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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 "dtc.h"
+#include "srcpos.h"
+
+#define FTF_FULLPATH 0x1
+#define FTF_VARALIGN 0x2
+#define FTF_NAMEPROPS 0x4
+#define FTF_BOOTCPUID 0x8
+#define FTF_STRTABSIZE 0x10
+#define FTF_STRUCTSIZE 0x20
+#define FTF_NOPS 0x40
+
+static struct version_info {
+ int version;
+ int last_comp_version;
+ int hdr_size;
+ int flags;
+} version_table[] = {
+ {1, 1, FDT_V1_SIZE,
+ FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS},
+ {2, 1, FDT_V2_SIZE,
+ FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID},
+ {3, 1, FDT_V3_SIZE,
+ FTF_FULLPATH|FTF_VARALIGN|FTF_NAMEPROPS|FTF_BOOTCPUID|FTF_STRTABSIZE},
+ {16, 16, FDT_V3_SIZE,
+ FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_NOPS},
+ {17, 16, FDT_V17_SIZE,
+ FTF_BOOTCPUID|FTF_STRTABSIZE|FTF_STRUCTSIZE|FTF_NOPS},
+};
+
+struct emitter {
+ void (*cell)(void *, cell_t);
+ void (*string)(void *, char *, int);
+ void (*align)(void *, int);
+ void (*data)(void *, struct data);
+ void (*beginnode)(void *, const char *);
+ void (*endnode)(void *, const char *);
+ void (*property)(void *, const char *);
+};
+
+static void bin_emit_cell(void *e, cell_t val)
+{
+ struct data *dtbuf = e;
+
+ *dtbuf = data_append_cell(*dtbuf, val);
+}
+
+static void bin_emit_string(void *e, char *str, int len)
+{
+ struct data *dtbuf = e;
+
+ if (len == 0)
+ len = strlen(str);
+
+ *dtbuf = data_append_data(*dtbuf, str, len);
+ *dtbuf = data_append_byte(*dtbuf, '\0');
+}
+
+static void bin_emit_align(void *e, int a)
+{
+ struct data *dtbuf = e;
+
+ *dtbuf = data_append_align(*dtbuf, a);
+}
+
+static void bin_emit_data(void *e, struct data d)
+{
+ struct data *dtbuf = e;
+
+ *dtbuf = data_append_data(*dtbuf, d.val, d.len);
+}
+
+static void bin_emit_beginnode(void *e, const char *label)
+{
+ bin_emit_cell(e, FDT_BEGIN_NODE);
+}
+
+static void bin_emit_endnode(void *e, const char *label)
+{
+ bin_emit_cell(e, FDT_END_NODE);
+}
+
+static void bin_emit_property(void *e, const char *label)
+{
+ bin_emit_cell(e, FDT_PROP);
+}
+
+static struct emitter bin_emitter = {
+ .cell = bin_emit_cell,
+ .string = bin_emit_string,
+ .align = bin_emit_align,
+ .data = bin_emit_data,
+ .beginnode = bin_emit_beginnode,
+ .endnode = bin_emit_endnode,
+ .property = bin_emit_property,
+};
+
+static void emit_label(FILE *f, const char *prefix, const char *label)
+{
+ fprintf(f, "\t.globl\t%s_%s\n", prefix, label);
+ fprintf(f, "%s_%s:\n", prefix, label);
+ fprintf(f, "_%s_%s:\n", prefix, label);
+}
+
+static void emit_offset_label(FILE *f, const char *label, int offset)
+{
+ fprintf(f, "\t.globl\t%s\n", label);
+ fprintf(f, "%s\t= . + %d\n", label, offset);
+}
+
+static void asm_emit_cell(void *e, cell_t val)
+{
+ FILE *f = e;
+
+ fprintf(f, "\t.long\t0x%x\n", val);
+}
+
+static void asm_emit_string(void *e, char *str, int len)
+{
+ FILE *f = e;
+ char c = 0;
+
+ if (len != 0) {
+ /* XXX: ewww */
+ c = str[len];
+ str[len] = '\0';
+ }
+
+ fprintf(f, "\t.string\t\"%s\"\n", str);
+
+ if (len != 0) {
+ str[len] = c;
+ }
+}
+
+static void asm_emit_align(void *e, int a)
+{
+ FILE *f = e;
+
+ fprintf(f, "\t.balign\t%d\n", a);
+}
+
+static void asm_emit_data(void *e, struct data d)
+{
+ FILE *f = e;
+ int off = 0;
+ struct marker *m = d.markers;
+
+ for_each_marker_of_type(m, LABEL)
+ emit_offset_label(f, m->ref, m->offset);
+
+ while ((d.len - off) >= sizeof(uint32_t)) {
+ fprintf(f, "\t.long\t0x%x\n",
+ fdt32_to_cpu(*((uint32_t *)(d.val+off))));
+ off += sizeof(uint32_t);
+ }
+
+ while ((d.len - off) >= 1) {
+ fprintf(f, "\t.byte\t0x%hhx\n", d.val[off]);
+ off += 1;
+ }
+
+ assert(off == d.len);
+}
+
+static void asm_emit_beginnode(void *e, const char *label)
+{
+ FILE *f = e;
+
+ if (label) {
+ fprintf(f, "\t.globl\t%s\n", label);
+ fprintf(f, "%s:\n", label);
+ }
+ fprintf(f, "\t.long\tFDT_BEGIN_NODE\n");
+}
+
+static void asm_emit_endnode(void *e, const char *label)
+{
+ FILE *f = e;
+
+ fprintf(f, "\t.long\tFDT_END_NODE\n");
+ if (label) {
+ fprintf(f, "\t.globl\t%s_end\n", label);
+ fprintf(f, "%s_end:\n", label);
+ }
+}
+
+static void asm_emit_property(void *e, const char *label)
+{
+ FILE *f = e;
+
+ if (label) {
+ fprintf(f, "\t.globl\t%s\n", label);
+ fprintf(f, "%s:\n", label);
+ }
+ fprintf(f, "\t.long\tFDT_PROP\n");
+}
+
+static struct emitter asm_emitter = {
+ .cell = asm_emit_cell,
+ .string = asm_emit_string,
+ .align = asm_emit_align,
+ .data = asm_emit_data,
+ .beginnode = asm_emit_beginnode,
+ .endnode = asm_emit_endnode,
+ .property = asm_emit_property,
+};
+
+static int stringtable_insert(struct data *d, const char *str)
+{
+ int i;
+
+ /* FIXME: do this more efficiently? */
+
+ for (i = 0; i < d->len; i++) {
+ if (streq(str, d->val + i))
+ return i;
+ }
+
+ *d = data_append_data(*d, str, strlen(str)+1);
+ return i;
+}
+
+static void flatten_tree(struct node *tree, struct emitter *emit,
+ void *etarget, struct data *strbuf,
+ struct version_info *vi)
+{
+ struct property *prop;
+ struct node *child;
+ int seen_name_prop = 0;
+
+ emit->beginnode(etarget, tree->label);
+
+ if (vi->flags & FTF_FULLPATH)
+ emit->string(etarget, tree->fullpath, 0);
+ else
+ emit->string(etarget, tree->name, 0);
+
+ emit->align(etarget, sizeof(cell_t));
+
+ for_each_property(tree, prop) {
+ int nameoff;
+
+ if (streq(prop->name, "name"))
+ seen_name_prop = 1;
+
+ nameoff = stringtable_insert(strbuf, prop->name);
+
+ emit->property(etarget, prop->label);
+ emit->cell(etarget, prop->val.len);
+ emit->cell(etarget, nameoff);
+
+ if ((vi->flags & FTF_VARALIGN) && (prop->val.len >= 8))
+ emit->align(etarget, 8);
+
+ emit->data(etarget, prop->val);
+ emit->align(etarget, sizeof(cell_t));
+ }
+
+ if ((vi->flags & FTF_NAMEPROPS) && !seen_name_prop) {
+ emit->property(etarget, NULL);
+ emit->cell(etarget, tree->basenamelen+1);
+ emit->cell(etarget, stringtable_insert(strbuf, "name"));
+
+ if ((vi->flags & FTF_VARALIGN) && ((tree->basenamelen+1) >= 8))
+ emit->align(etarget, 8);
+
+ emit->string(etarget, tree->name, tree->basenamelen);
+ emit->align(etarget, sizeof(cell_t));
+ }
+
+ for_each_child(tree, child) {
+ flatten_tree(child, emit, etarget, strbuf, vi);
+ }
+
+ emit->endnode(etarget, tree->label);
+}
+
+static struct data flatten_reserve_list(struct reserve_info *reservelist,
+ struct version_info *vi)
+{
+ struct reserve_info *re;
+ struct data d = empty_data;
+ static struct fdt_reserve_entry null_re = {0,0};
+ int j;
+
+ for (re = reservelist; re; re = re->next) {
+ d = data_append_re(d, &re->re);
+ }
+ /*
+ * Add additional reserved slots if the user asked for them.
+ */
+ for (j = 0; j < reservenum; j++) {
+ d = data_append_re(d, &null_re);
+ }
+
+ return d;
+}
+
+static void make_fdt_header(struct fdt_header *fdt,
+ struct version_info *vi,
+ int reservesize, int dtsize, int strsize,
+ int boot_cpuid_phys)
+{
+ int reserve_off;
+
+ reservesize += sizeof(struct fdt_reserve_entry);
+
+ memset(fdt, 0xff, sizeof(*fdt));
+
+ fdt->magic = cpu_to_fdt32(FDT_MAGIC);
+ fdt->version = cpu_to_fdt32(vi->version);
+ fdt->last_comp_version = cpu_to_fdt32(vi->last_comp_version);
+
+ /* Reserve map should be doubleword aligned */
+ reserve_off = ALIGN(vi->hdr_size, 8);
+
+ fdt->off_mem_rsvmap = cpu_to_fdt32(reserve_off);
+ fdt->off_dt_struct = cpu_to_fdt32(reserve_off + reservesize);
+ fdt->off_dt_strings = cpu_to_fdt32(reserve_off + reservesize
+ + dtsize);
+ fdt->totalsize = cpu_to_fdt32(reserve_off + reservesize + dtsize + strsize);
+
+ if (vi->flags & FTF_BOOTCPUID)
+ fdt->boot_cpuid_phys = cpu_to_fdt32(boot_cpuid_phys);
+ if (vi->flags & FTF_STRTABSIZE)
+ fdt->size_dt_strings = cpu_to_fdt32(strsize);
+ if (vi->flags & FTF_STRUCTSIZE)
+ fdt->size_dt_struct = cpu_to_fdt32(dtsize);
+}
+
+void dt_to_blob(FILE *f, struct boot_info *bi, int version)
+{
+ struct version_info *vi = NULL;
+ int i;
+ struct data blob = empty_data;
+ struct data reservebuf = empty_data;
+ struct data dtbuf = empty_data;
+ struct data strbuf = empty_data;
+ struct fdt_header fdt;
+ int padlen = 0;
+
+ for (i = 0; i < ARRAY_SIZE(version_table); i++) {
+ if (version_table[i].version == version)
+ vi = &version_table[i];
+ }
+ if (!vi)
+ die("Unknown device tree blob version %d\n", version);
+
+ flatten_tree(bi->dt, &bin_emitter, &dtbuf, &strbuf, vi);
+ bin_emit_cell(&dtbuf, FDT_END);
+
+ reservebuf = flatten_reserve_list(bi->reservelist, vi);
+
+ /* Make header */
+ make_fdt_header(&fdt, vi, reservebuf.len, dtbuf.len, strbuf.len,
+ bi->boot_cpuid_phys);
+
+ /*
+ * If the user asked for more space than is used, adjust the totalsize.
+ */
+ if (minsize > 0) {
+ padlen = minsize - fdt32_to_cpu(fdt.totalsize);
+ if ((padlen < 0) && (quiet < 1))
+ fprintf(stderr,
+ "Warning: blob size %d >= minimum size %d\n",
+ fdt32_to_cpu(fdt.totalsize), minsize);
+ }
+
+ if (padsize > 0)
+ padlen = padsize;
+
+ if (padlen > 0) {
+ int tsize = fdt32_to_cpu(fdt.totalsize);
+ tsize += padlen;
+ fdt.totalsize = cpu_to_fdt32(tsize);
+ }
+
+ /*
+ * Assemble the blob: start with the header, add with alignment
+ * the reserve buffer, add the reserve map terminating zeroes,
+ * the device tree itself, and finally the strings.
+ */
+ blob = data_append_data(blob, &fdt, vi->hdr_size);
+ blob = data_append_align(blob, 8);
+ blob = data_merge(blob, reservebuf);
+ blob = data_append_zeroes(blob, sizeof(struct fdt_reserve_entry));
+ blob = data_merge(blob, dtbuf);
+ blob = data_merge(blob, strbuf);
+
+ /*
+ * If the user asked for more space than is used, pad out the blob.
+ */
+ if (padlen > 0)
+ blob = data_append_zeroes(blob, padlen);
+
+ fwrite(blob.val, blob.len, 1, f);
+
+ if (ferror(f))
+ die("Error writing device tree blob: %s\n", strerror(errno));
+
+ /*
+ * data_merge() frees the right-hand element so only the blob
+ * remains to be freed.
+ */
+ data_free(blob);
+}
+
+static void dump_stringtable_asm(FILE *f, struct data strbuf)
+{
+ const char *p;
+ int len;
+
+ p = strbuf.val;
+
+ while (p < (strbuf.val + strbuf.len)) {
+ len = strlen(p);
+ fprintf(f, "\t.string \"%s\"\n", p);
+ p += len+1;
+ }
+}
+
+void dt_to_asm(FILE *f, struct boot_info *bi, int version)
+{
+ struct version_info *vi = NULL;
+ int i;
+ struct data strbuf = empty_data;
+ struct reserve_info *re;
+ const char *symprefix = "dt";
+
+ for (i = 0; i < ARRAY_SIZE(version_table); i++) {
+ if (version_table[i].version == version)
+ vi = &version_table[i];
+ }
+ if (!vi)
+ die("Unknown device tree blob version %d\n", version);
+
+ fprintf(f, "/* autogenerated by dtc, do not edit */\n\n");
+ fprintf(f, "#define FDT_MAGIC 0x%x\n", FDT_MAGIC);
+ fprintf(f, "#define FDT_BEGIN_NODE 0x%x\n", FDT_BEGIN_NODE);
+ fprintf(f, "#define FDT_END_NODE 0x%x\n", FDT_END_NODE);
+ fprintf(f, "#define FDT_PROP 0x%x\n", FDT_PROP);
+ fprintf(f, "#define FDT_END 0x%x\n", FDT_END);
+ fprintf(f, "\n");
+
+ emit_label(f, symprefix, "blob_start");
+ emit_label(f, symprefix, "header");
+ fprintf(f, "\t.long\tFDT_MAGIC\t\t\t\t/* magic */\n");
+ fprintf(f, "\t.long\t_%s_blob_abs_end - _%s_blob_start\t/* totalsize */\n",
+ symprefix, symprefix);
+ fprintf(f, "\t.long\t_%s_struct_start - _%s_blob_start\t/* off_dt_struct */\n",
+ symprefix, symprefix);
+ fprintf(f, "\t.long\t_%s_strings_start - _%s_blob_start\t/* off_dt_strings */\n",
+ symprefix, symprefix);
+ fprintf(f, "\t.long\t_%s_reserve_map - _%s_blob_start\t/* off_dt_strings */\n",
+ symprefix, symprefix);
+ fprintf(f, "\t.long\t%d\t\t\t\t\t/* version */\n", vi->version);
+ fprintf(f, "\t.long\t%d\t\t\t\t\t/* last_comp_version */\n",
+ vi->last_comp_version);
+
+ if (vi->flags & FTF_BOOTCPUID)
+ fprintf(f, "\t.long\t%i\t\t\t\t\t/* boot_cpuid_phys */\n",
+ bi->boot_cpuid_phys);
+
+ if (vi->flags & FTF_STRTABSIZE)
+ fprintf(f, "\t.long\t_%s_strings_end - _%s_strings_start\t/* size_dt_strings */\n",
+ symprefix, symprefix);
+
+ if (vi->flags & FTF_STRUCTSIZE)
+ fprintf(f, "\t.long\t_%s_struct_end - _%s_struct_start\t/* size_dt_struct */\n",
+ symprefix, symprefix);
+
+ /*
+ * Reserve map entries.
+ * Align the reserve map to a doubleword boundary.
+ * Each entry is an (address, size) pair of u64 values.
+ * Always supply a zero-sized temination entry.
+ */
+ asm_emit_align(f, 8);
+ emit_label(f, symprefix, "reserve_map");
+
+ fprintf(f, "/* Memory reserve map from source file */\n");
+
+ /*
+ * Use .long on high and low halfs of u64s to avoid .quad
+ * as it appears .quad isn't available in some assemblers.
+ */
+ for (re = bi->reservelist; re; re = re->next) {
+ if (re->label) {
+ fprintf(f, "\t.globl\t%s\n", re->label);
+ fprintf(f, "%s:\n", re->label);
+ }
+ fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
+ (unsigned int)(re->re.address >> 32),
+ (unsigned int)(re->re.address & 0xffffffff));
+ fprintf(f, "\t.long\t0x%08x, 0x%08x\n",
+ (unsigned int)(re->re.size >> 32),
+ (unsigned int)(re->re.size & 0xffffffff));
+ }
+ for (i = 0; i < reservenum; i++) {
+ fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
+ }
+
+ fprintf(f, "\t.long\t0, 0\n\t.long\t0, 0\n");
+
+ emit_label(f, symprefix, "struct_start");
+ flatten_tree(bi->dt, &asm_emitter, f, &strbuf, vi);
+ fprintf(f, "\t.long\tFDT_END\n");
+ emit_label(f, symprefix, "struct_end");
+
+ emit_label(f, symprefix, "strings_start");
+ dump_stringtable_asm(f, strbuf);
+ emit_label(f, symprefix, "strings_end");
+
+ emit_label(f, symprefix, "blob_end");
+
+ /*
+ * If the user asked for more space than is used, pad it out.
+ */
+ if (minsize > 0) {
+ fprintf(f, "\t.space\t%d - (_%s_blob_end - _%s_blob_start), 0\n",
+ minsize, symprefix, symprefix);
+ }
+ if (padsize > 0) {
+ fprintf(f, "\t.space\t%d, 0\n", padsize);
+ }
+ emit_label(f, symprefix, "blob_abs_end");
+
+ data_free(strbuf);
+}
+
+struct inbuf {
+ char *base, *limit, *ptr;
+};
+
+static void inbuf_init(struct inbuf *inb, void *base, void *limit)
+{
+ inb->base = base;
+ inb->limit = limit;
+ inb->ptr = inb->base;
+}
+
+static void flat_read_chunk(struct inbuf *inb, void *p, int len)
+{
+ if ((inb->ptr + len) > inb->limit)
+ die("Premature end of data parsing flat device tree\n");
+
+ memcpy(p, inb->ptr, len);
+
+ inb->ptr += len;
+}
+
+static uint32_t flat_read_word(struct inbuf *inb)
+{
+ uint32_t val;
+
+ assert(((inb->ptr - inb->base) % sizeof(val)) == 0);
+
+ flat_read_chunk(inb, &val, sizeof(val));
+
+ return fdt32_to_cpu(val);
+}
+
+static void flat_realign(struct inbuf *inb, int align)
+{
+ int off = inb->ptr - inb->base;
+
+ inb->ptr = inb->base + ALIGN(off, align);
+ if (inb->ptr > inb->limit)
+ die("Premature end of data parsing flat device tree\n");
+}
+
+static char *flat_read_string(struct inbuf *inb)
+{
+ int len = 0;
+ const char *p = inb->ptr;
+ char *str;
+
+ do {
+ if (p >= inb->limit)
+ die("Premature end of data parsing flat device tree\n");
+ len++;
+ } while ((*p++) != '\0');
+
+ str = strdup(inb->ptr);
+
+ inb->ptr += len;
+
+ flat_realign(inb, sizeof(uint32_t));
+
+ return str;
+}
+
+static struct data flat_read_data(struct inbuf *inb, int len)
+{
+ struct data d = empty_data;
+
+ if (len == 0)
+ return empty_data;
+
+ d = data_grow_for(d, len);
+ d.len = len;
+
+ flat_read_chunk(inb, d.val, len);
+
+ flat_realign(inb, sizeof(uint32_t));
+
+ return d;
+}
+
+static char *flat_read_stringtable(struct inbuf *inb, int offset)
+{
+ const char *p;
+
+ p = inb->base + offset;
+ while (1) {
+ if (p >= inb->limit || p < inb->base)
+ die("String offset %d overruns string table\n",
+ offset);
+
+ if (*p == '\0')
+ break;
+
+ p++;
+ }
+
+ return strdup(inb->base + offset);
+}
+
+static struct property *flat_read_property(struct inbuf *dtbuf,
+ struct inbuf *strbuf, int flags)
+{
+ uint32_t proplen, stroff;
+ char *name;
+ struct data val;
+
+ proplen = flat_read_word(dtbuf);
+ stroff = flat_read_word(dtbuf);
+
+ name = flat_read_stringtable(strbuf, stroff);
+
+ if ((flags & FTF_VARALIGN) && (proplen >= 8))
+ flat_realign(dtbuf, 8);
+
+ val = flat_read_data(dtbuf, proplen);
+
+ return build_property(name, val, NULL);
+}
+
+
+static struct reserve_info *flat_read_mem_reserve(struct inbuf *inb)
+{
+ struct reserve_info *reservelist = NULL;
+ struct reserve_info *new;
+ const char *p;
+ struct fdt_reserve_entry re;
+
+ /*
+ * Each entry is a pair of u64 (addr, size) values for 4 cell_t's.
+ * List terminates at an entry with size equal to zero.
+ *
+ * First pass, count entries.
+ */
+ p = inb->ptr;
+ while (1) {
+ flat_read_chunk(inb, &re, sizeof(re));
+ re.address = fdt64_to_cpu(re.address);
+ re.size = fdt64_to_cpu(re.size);
+ if (re.size == 0)
+ break;
+
+ new = build_reserve_entry(re.address, re.size, NULL);
+ reservelist = add_reserve_entry(reservelist, new);
+ }
+
+ return reservelist;
+}
+
+
+static char *nodename_from_path(const char *ppath, const char *cpath)
+{
+ int plen;
+
+ plen = strlen(ppath);
+
+ if (!strneq(ppath, cpath, plen))
+ die("Path \"%s\" is not valid as a child of \"%s\"\n",
+ cpath, ppath);
+
+ /* root node is a special case */
+ if (!streq(ppath, "/"))
+ plen++;
+
+ return strdup(cpath + plen);
+}
+
+static struct node *unflatten_tree(struct inbuf *dtbuf,
+ struct inbuf *strbuf,
+ const char *parent_flatname, int flags)
+{
+ struct node *node;
+ char *flatname;
+ uint32_t val;
+
+ node = build_node(NULL, NULL);
+
+ flatname = flat_read_string(dtbuf);
+
+ if (flags & FTF_FULLPATH)
+ node->name = nodename_from_path(parent_flatname, flatname);
+ else
+ node->name = flatname;
+
+ do {
+ struct property *prop;
+ struct node *child;
+
+ val = flat_read_word(dtbuf);
+ switch (val) {
+ case FDT_PROP:
+ if (node->children)
+ fprintf(stderr, "Warning: Flat tree input has "
+ "subnodes preceding a property.\n");
+ prop = flat_read_property(dtbuf, strbuf, flags);
+ add_property(node, prop);
+ break;
+
+ case FDT_BEGIN_NODE:
+ child = unflatten_tree(dtbuf,strbuf, flatname, flags);
+ add_child(node, child);
+ break;
+
+ case FDT_END_NODE:
+ break;
+
+ case FDT_END:
+ die("Premature FDT_END in device tree blob\n");
+ break;
+
+ case FDT_NOP:
+ if (!(flags & FTF_NOPS))
+ fprintf(stderr, "Warning: NOP tag found in flat tree"
+ " version <16\n");
+
+ /* Ignore */
+ break;
+
+ default:
+ die("Invalid opcode word %08x in device tree blob\n",
+ val);
+ }
+ } while (val != FDT_END_NODE);
+
+ return node;
+}
+
+
+struct boot_info *dt_from_blob(const char *fname)
+{
+ struct dtc_file *dtcf;
+ uint32_t magic, totalsize, version, size_dt, boot_cpuid_phys;
+ uint32_t off_dt, off_str, off_mem_rsvmap;
+ int rc;
+ char *blob;
+ struct fdt_header *fdt;
+ char *p;
+ struct inbuf dtbuf, strbuf;
+ struct inbuf memresvbuf;
+ int sizeleft;
+ struct reserve_info *reservelist;
+ struct node *tree;
+ uint32_t val;
+ int flags = 0;
+
+ dtcf = dtc_open_file(fname, NULL);
+
+ rc = fread(&magic, sizeof(magic), 1, dtcf->file);
+ if (ferror(dtcf->file))
+ die("Error reading DT blob magic number: %s\n",
+ strerror(errno));
+ if (rc < 1) {
+ if (feof(dtcf->file))
+ die("EOF reading DT blob magic number\n");
+ else
+ die("Mysterious short read reading magic number\n");
+ }
+
+ magic = fdt32_to_cpu(magic);
+ if (magic != FDT_MAGIC)
+ die("Blob has incorrect magic number\n");
+
+ rc = fread(&totalsize, sizeof(totalsize), 1, dtcf->file);
+ if (ferror(dtcf->file))
+ die("Error reading DT blob size: %s\n", strerror(errno));
+ if (rc < 1) {
+ if (feof(dtcf->file))
+ die("EOF reading DT blob size\n");
+ else
+ die("Mysterious short read reading blob size\n");
+ }
+
+ totalsize = fdt32_to_cpu(totalsize);
+ if (totalsize < FDT_V1_SIZE)
+ die("DT blob size (%d) is too small\n", totalsize);
+
+ blob = xmalloc(totalsize);
+
+ fdt = (struct fdt_header *)blob;
+ fdt->magic = cpu_to_fdt32(magic);
+ fdt->totalsize = cpu_to_fdt32(totalsize);
+
+ sizeleft = totalsize - sizeof(magic) - sizeof(totalsize);
+ p = blob + sizeof(magic) + sizeof(totalsize);
+
+ while (sizeleft) {
+ if (feof(dtcf->file))
+ die("EOF before reading %d bytes of DT blob\n",
+ totalsize);
+
+ rc = fread(p, 1, sizeleft, dtcf->file);
+ if (ferror(dtcf->file))
+ die("Error reading DT blob: %s\n",
+ strerror(errno));
+
+ sizeleft -= rc;
+ p += rc;
+ }
+
+ off_dt = fdt32_to_cpu(fdt->off_dt_struct);
+ off_str = fdt32_to_cpu(fdt->off_dt_strings);
+ off_mem_rsvmap = fdt32_to_cpu(fdt->off_mem_rsvmap);
+ version = fdt32_to_cpu(fdt->version);
+ boot_cpuid_phys = fdt32_to_cpu(fdt->boot_cpuid_phys);
+
+ if (off_mem_rsvmap >= totalsize)
+ die("Mem Reserve structure offset exceeds total size\n");
+
+ if (off_dt >= totalsize)
+ die("DT structure offset exceeds total size\n");
+
+ if (off_str > totalsize)
+ die("String table offset exceeds total size\n");
+
+ if (version >= 3) {
+ uint32_t size_str = fdt32_to_cpu(fdt->size_dt_strings);
+ if (off_str+size_str > totalsize)
+ die("String table extends past total size\n");
+ inbuf_init(&strbuf, blob + off_str, blob + off_str + size_str);
+ } else {
+ inbuf_init(&strbuf, blob + off_str, blob + totalsize);
+ }
+
+ if (version >= 17) {
+ size_dt = fdt32_to_cpu(fdt->size_dt_struct);
+ if (off_dt+size_dt > totalsize)
+ die("Structure block extends past total size\n");
+ }
+
+ if (version < 16) {
+ flags |= FTF_FULLPATH | FTF_NAMEPROPS | FTF_VARALIGN;
+ } else {
+ flags |= FTF_NOPS;
+ }
+
+ inbuf_init(&memresvbuf,
+ blob + off_mem_rsvmap, blob + totalsize);
+ inbuf_init(&dtbuf, blob + off_dt, blob + totalsize);
+
+ reservelist = flat_read_mem_reserve(&memresvbuf);
+
+ val = flat_read_word(&dtbuf);
+
+ if (val != FDT_BEGIN_NODE)
+ die("Device tree blob doesn't begin with FDT_BEGIN_NODE (begins with 0x%08x)\n", val);
+
+ tree = unflatten_tree(&dtbuf, &strbuf, "", flags);
+
+ val = flat_read_word(&dtbuf);
+ if (val != FDT_END)
+ die("Device tree blob doesn't end with FDT_END\n");
+
+ free(blob);
+
+ dtc_close_file(dtcf);
+
+ return build_boot_info(reservelist, tree, boot_cpuid_phys);
+}
--- /dev/null
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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 "dtc.h"
+
+#include <dirent.h>
+#include <sys/stat.h>
+
+static struct node *read_fstree(const char *dirname)
+{
+ DIR *d;
+ struct dirent *de;
+ struct stat st;
+ struct node *tree;
+
+ d = opendir(dirname);
+ if (!d)
+ die("Couldn't opendir() \"%s\": %s\n", dirname, strerror(errno));
+
+ tree = build_node(NULL, NULL);
+
+ while ((de = readdir(d)) != NULL) {
+ char *tmpnam;
+
+ if (streq(de->d_name, ".")
+ || streq(de->d_name, ".."))
+ continue;
+
+ tmpnam = join_path(dirname, de->d_name);
+
+ if (lstat(tmpnam, &st) < 0)
+ die("stat(%s): %s\n", tmpnam, strerror(errno));
+
+ if (S_ISREG(st.st_mode)) {
+ struct property *prop;
+ FILE *pfile;
+
+ pfile = fopen(tmpnam, "r");
+ if (! pfile) {
+ fprintf(stderr,
+ "WARNING: Cannot open %s: %s\n",
+ tmpnam, strerror(errno));
+ } else {
+ prop = build_property(strdup(de->d_name),
+ data_copy_file(pfile,
+ st.st_size),
+ NULL);
+ add_property(tree, prop);
+ fclose(pfile);
+ }
+ } else if (S_ISDIR(st.st_mode)) {
+ struct node *newchild;
+
+ newchild = read_fstree(tmpnam);
+ newchild = name_node(newchild, strdup(de->d_name),
+ NULL);
+ add_child(tree, newchild);
+ }
+
+ free(tmpnam);
+ }
+
+ return tree;
+}
+
+struct boot_info *dt_from_fs(const char *dirname)
+{
+ struct node *tree;
+
+ tree = read_fstree(dirname);
+ tree = name_node(tree, "", NULL);
+
+ return build_boot_info(NULL, tree, 0);
+}
+
--- /dev/null
+# Makefile.libfdt
+#
+# This is not a complete Makefile of itself. Instead, it is designed to
+# be easily embeddable into other systems of Makefiles.
+#
+LIBFDT_INCLUDES = fdt.h libfdt.h
+LIBFDT_SRCS = fdt.c fdt_ro.c fdt_wip.c fdt_sw.c fdt_rw.c fdt_strerror.c
+LIBFDT_OBJS = $(LIBFDT_SRCS:%.c=%.o)
--- /dev/null
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_check_header(const void *fdt)
+{
+ if (fdt_magic(fdt) == FDT_MAGIC) {
+ /* Complete tree */
+ if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ if (fdt_last_comp_version(fdt) > FDT_LAST_SUPPORTED_VERSION)
+ return -FDT_ERR_BADVERSION;
+ } else if (fdt_magic(fdt) == FDT_SW_MAGIC) {
+ /* Unfinished sequential-write blob */
+ if (fdt_size_dt_struct(fdt) == 0)
+ return -FDT_ERR_BADSTATE;
+ } else {
+ return -FDT_ERR_BADMAGIC;
+ }
+
+ return 0;
+}
+
+const void *fdt_offset_ptr(const void *fdt, int offset, int len)
+{
+ const char *p;
+
+ if (fdt_version(fdt) >= 0x11)
+ if (((offset + len) < offset)
+ || ((offset + len) > fdt_size_dt_struct(fdt)))
+ return NULL;
+
+ p = _fdt_offset_ptr(fdt, offset);
+
+ if (p + len < p)
+ return NULL;
+ return p;
+}
+
+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset)
+{
+ const uint32_t *tagp, *lenp;
+ uint32_t tag;
+ const char *p;
+
+ if (offset % FDT_TAGSIZE)
+ return -1;
+
+ tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
+ if (! tagp)
+ return FDT_END; /* premature end */
+ tag = fdt32_to_cpu(*tagp);
+ offset += FDT_TAGSIZE;
+
+ switch (tag) {
+ case FDT_BEGIN_NODE:
+ /* skip name */
+ do {
+ p = fdt_offset_ptr(fdt, offset++, 1);
+ } while (p && (*p != '\0'));
+ if (! p)
+ return FDT_END;
+ break;
+ case FDT_PROP:
+ lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp));
+ if (! lenp)
+ return FDT_END;
+ /* skip name offset, length and value */
+ offset += 2*FDT_TAGSIZE + fdt32_to_cpu(*lenp);
+ break;
+ }
+
+ if (nextoffset)
+ *nextoffset = FDT_TAGALIGN(offset);
+
+ return tag;
+}
+
+int _fdt_check_node_offset(const void *fdt, int offset)
+{
+ if ((offset < 0) || (offset % FDT_TAGSIZE)
+ || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE))
+ return -FDT_ERR_BADOFFSET;
+
+ return offset;
+}
+
+int fdt_next_node(const void *fdt, int offset, int *depth)
+{
+ int nextoffset = 0;
+ uint32_t tag;
+
+ if (offset >= 0)
+ if ((nextoffset = _fdt_check_node_offset(fdt, offset)) < 0)
+ return nextoffset;
+
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_PROP:
+ case FDT_NOP:
+ break;
+
+ case FDT_BEGIN_NODE:
+ if (depth)
+ (*depth)++;
+ break;
+
+ case FDT_END_NODE:
+ if (depth)
+ (*depth)--;
+ break;
+
+ case FDT_END:
+ return -FDT_ERR_NOTFOUND;
+
+ default:
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+ } while (tag != FDT_BEGIN_NODE);
+
+ return offset;
+}
+
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s)
+{
+ int len = strlen(s) + 1;
+ const char *last = strtab + tabsize - len;
+ const char *p;
+
+ for (p = strtab; p <= last; p++)
+ if (memcmp(p, s, len) == 0)
+ return p;
+ return NULL;
+}
+
+int fdt_move(const void *fdt, void *buf, int bufsize)
+{
+ FDT_CHECK_HEADER(fdt);
+
+ if (fdt_totalsize(fdt) > bufsize)
+ return -FDT_ERR_NOSPACE;
+
+ memmove(buf, fdt, fdt_totalsize(fdt));
+ return 0;
+}
--- /dev/null
+#ifndef _FDT_H
+#define _FDT_H
+
+#ifndef __ASSEMBLY__
+
+struct fdt_header {
+ uint32_t magic; /* magic word FDT_MAGIC */
+ uint32_t totalsize; /* total size of DT block */
+ uint32_t off_dt_struct; /* offset to structure */
+ uint32_t off_dt_strings; /* offset to strings */
+ uint32_t off_mem_rsvmap; /* offset to memory reserve map */
+ uint32_t version; /* format version */
+ uint32_t last_comp_version; /* last compatible version */
+
+ /* version 2 fields below */
+ uint32_t boot_cpuid_phys; /* Which physical CPU id we're
+ booting on */
+ /* version 3 fields below */
+ uint32_t size_dt_strings; /* size of the strings block */
+
+ /* version 17 fields below */
+ uint32_t size_dt_struct; /* size of the structure block */
+};
+
+struct fdt_reserve_entry {
+ uint64_t address;
+ uint64_t size;
+};
+
+struct fdt_node_header {
+ uint32_t tag;
+ char name[0];
+};
+
+struct fdt_property {
+ uint32_t tag;
+ uint32_t len;
+ uint32_t nameoff;
+ char data[0];
+};
+
+#endif /* !__ASSEMBLY */
+
+#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */
+#define FDT_TAGSIZE sizeof(uint32_t)
+
+#define FDT_BEGIN_NODE 0x1 /* Start node: full name */
+#define FDT_END_NODE 0x2 /* End node */
+#define FDT_PROP 0x3 /* Property: name off,
+ size, content */
+#define FDT_NOP 0x4 /* nop */
+#define FDT_END 0x9
+
+#define FDT_V1_SIZE (7*sizeof(uint32_t))
+#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(uint32_t))
+#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(uint32_t))
+#define FDT_V16_SIZE FDT_V3_SIZE
+#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(uint32_t))
+
+#endif /* _FDT_H */
--- /dev/null
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_nodename_eq(const void *fdt, int offset,
+ const char *s, int len)
+{
+ const char *p = fdt_offset_ptr(fdt, offset + FDT_TAGSIZE, len+1);
+
+ if (! p)
+ /* short match */
+ return 0;
+
+ if (memcmp(p, s, len) != 0)
+ return 0;
+
+ if (p[len] == '\0')
+ return 1;
+ else if (!memchr(s, '@', len) && (p[len] == '@'))
+ return 1;
+ else
+ return 0;
+}
+
+const char *fdt_string(const void *fdt, int stroffset)
+{
+ return (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset;
+}
+
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
+{
+ FDT_CHECK_HEADER(fdt);
+ *address = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->address);
+ *size = fdt64_to_cpu(_fdt_mem_rsv(fdt, n)->size);
+ return 0;
+}
+
+int fdt_num_mem_rsv(const void *fdt)
+{
+ int i = 0;
+
+ while (fdt64_to_cpu(_fdt_mem_rsv(fdt, i)->size) != 0)
+ i++;
+ return i;
+}
+
+int fdt_subnode_offset_namelen(const void *fdt, int offset,
+ const char *name, int namelen)
+{
+ int depth;
+
+ FDT_CHECK_HEADER(fdt);
+
+ for (depth = 0, offset = fdt_next_node(fdt, offset, &depth);
+ (offset >= 0) && (depth > 0);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ if (depth < 0)
+ return -FDT_ERR_NOTFOUND;
+ else if ((depth == 1)
+ && _fdt_nodename_eq(fdt, offset, name, namelen))
+ return offset;
+ }
+
+ if (offset < 0)
+ return offset; /* error */
+ else
+ return -FDT_ERR_NOTFOUND;
+}
+
+int fdt_subnode_offset(const void *fdt, int parentoffset,
+ const char *name)
+{
+ return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_path_offset(const void *fdt, const char *path)
+{
+ const char *end = path + strlen(path);
+ const char *p = path;
+ int offset = 0;
+
+ FDT_CHECK_HEADER(fdt);
+
+ if (*path != '/')
+ return -FDT_ERR_BADPATH;
+
+ while (*p) {
+ const char *q;
+
+ while (*p == '/')
+ p++;
+ if (! *p)
+ return offset;
+ q = strchr(p, '/');
+ if (! q)
+ q = end;
+
+ offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p);
+ if (offset < 0)
+ return offset;
+
+ p = q;
+ }
+
+ return offset;
+}
+
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *len)
+{
+ const struct fdt_node_header *nh = _fdt_offset_ptr(fdt, nodeoffset);
+ int err;
+
+ if (((err = fdt_check_header(fdt)) != 0)
+ || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+ goto fail;
+
+ if (len)
+ *len = strlen(nh->name);
+
+ return nh->name;
+
+ fail:
+ if (len)
+ *len = err;
+ return NULL;
+}
+
+const struct fdt_property *fdt_get_property(const void *fdt,
+ int nodeoffset,
+ const char *name, int *lenp)
+{
+ uint32_t tag;
+ const struct fdt_property *prop;
+ int namestroff;
+ int offset, nextoffset;
+ int err;
+
+ if (((err = fdt_check_header(fdt)) != 0)
+ || ((err = _fdt_check_node_offset(fdt, nodeoffset)) < 0))
+ goto fail;
+
+ nextoffset = err;
+ do {
+ offset = nextoffset;
+
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+ switch (tag) {
+ case FDT_END:
+ err = -FDT_ERR_TRUNCATED;
+ goto fail;
+
+ case FDT_BEGIN_NODE:
+ case FDT_END_NODE:
+ case FDT_NOP:
+ break;
+
+ case FDT_PROP:
+ err = -FDT_ERR_BADSTRUCTURE;
+ prop = fdt_offset_ptr(fdt, offset, sizeof(*prop));
+ if (! prop)
+ goto fail;
+ namestroff = fdt32_to_cpu(prop->nameoff);
+ if (strcmp(fdt_string(fdt, namestroff), name) == 0) {
+ /* Found it! */
+ int len = fdt32_to_cpu(prop->len);
+ prop = fdt_offset_ptr(fdt, offset,
+ sizeof(*prop)+len);
+ if (! prop)
+ goto fail;
+
+ if (lenp)
+ *lenp = len;
+
+ return prop;
+ }
+ break;
+
+ default:
+ err = -FDT_ERR_BADSTRUCTURE;
+ goto fail;
+ }
+ } while ((tag != FDT_BEGIN_NODE) && (tag != FDT_END_NODE));
+
+ err = -FDT_ERR_NOTFOUND;
+ fail:
+ if (lenp)
+ *lenp = err;
+ return NULL;
+}
+
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ const struct fdt_property *prop;
+
+ prop = fdt_get_property(fdt, nodeoffset, name, lenp);
+ if (! prop)
+ return NULL;
+
+ return prop->data;
+}
+
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset)
+{
+ const uint32_t *php;
+ int len;
+
+ php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len);
+ if (!php || (len != sizeof(*php)))
+ return 0;
+
+ return fdt32_to_cpu(*php);
+}
+
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen)
+{
+ int pdepth = 0, p = 0;
+ int offset, depth, namelen;
+ const char *name;
+
+ FDT_CHECK_HEADER(fdt);
+
+ if (buflen < 2)
+ return -FDT_ERR_NOSPACE;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ if (pdepth < depth)
+ continue; /* overflowed buffer */
+
+ while (pdepth > depth) {
+ do {
+ p--;
+ } while (buf[p-1] != '/');
+ pdepth--;
+ }
+
+ name = fdt_get_name(fdt, offset, &namelen);
+ if (!name)
+ return namelen;
+ if ((p + namelen + 1) <= buflen) {
+ memcpy(buf + p, name, namelen);
+ p += namelen;
+ buf[p++] = '/';
+ pdepth++;
+ }
+
+ if (offset == nodeoffset) {
+ if (pdepth < (depth + 1))
+ return -FDT_ERR_NOSPACE;
+
+ if (p > 1) /* special case so that root path is "/", not "" */
+ p--;
+ buf[p] = '\0';
+ return p;
+ }
+ }
+
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+ int supernodedepth, int *nodedepth)
+{
+ int offset, depth;
+ int supernodeoffset = -FDT_ERR_INTERNAL;
+
+ FDT_CHECK_HEADER(fdt);
+
+ if (supernodedepth < 0)
+ return -FDT_ERR_NOTFOUND;
+
+ for (offset = 0, depth = 0;
+ (offset >= 0) && (offset <= nodeoffset);
+ offset = fdt_next_node(fdt, offset, &depth)) {
+ if (depth == supernodedepth)
+ supernodeoffset = offset;
+
+ if (offset == nodeoffset) {
+ if (nodedepth)
+ *nodedepth = depth;
+
+ if (supernodedepth > depth)
+ return -FDT_ERR_NOTFOUND;
+ else
+ return supernodeoffset;
+ }
+ }
+
+ if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0))
+ return -FDT_ERR_BADOFFSET;
+ else if (offset == -FDT_ERR_BADOFFSET)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_depth(const void *fdt, int nodeoffset)
+{
+ int nodedepth;
+ int err;
+
+ err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth);
+ if (err)
+ return (err < 0) ? err : -FDT_ERR_INTERNAL;
+ return nodedepth;
+}
+
+int fdt_parent_offset(const void *fdt, int nodeoffset)
+{
+ int nodedepth = fdt_node_depth(fdt, nodeoffset);
+
+ if (nodedepth < 0)
+ return nodedepth;
+ return fdt_supernode_atdepth_offset(fdt, nodeoffset,
+ nodedepth - 1, NULL);
+}
+
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen)
+{
+ int offset;
+ const void *val;
+ int len;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_getprop(), then if that didn't
+ * find what we want, we scan over them again making our way
+ * to the next node. Still it's the easiest to implement
+ * approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ val = fdt_getprop(fdt, offset, propname, &len);
+ if (val && (len == proplen)
+ && (memcmp(val, propval, len) == 0))
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
+
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle)
+{
+ if ((phandle == 0) || (phandle == -1))
+ return -FDT_ERR_BADPHANDLE;
+ phandle = cpu_to_fdt32(phandle);
+ return fdt_node_offset_by_prop_value(fdt, -1, "linux,phandle",
+ &phandle, sizeof(phandle));
+}
+
+int _stringlist_contains(const char *strlist, int listlen, const char *str)
+{
+ int len = strlen(str);
+ const char *p;
+
+ while (listlen >= len) {
+ if (memcmp(str, strlist, len+1) == 0)
+ return 1;
+ p = memchr(strlist, '\0', listlen);
+ if (!p)
+ return 0; /* malformed strlist.. */
+ listlen -= (p-strlist) + 1;
+ strlist = p + 1;
+ }
+ return 0;
+}
+
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+ const char *compatible)
+{
+ const void *prop;
+ int len;
+
+ prop = fdt_getprop(fdt, nodeoffset, "compatible", &len);
+ if (!prop)
+ return len;
+ if (_stringlist_contains(prop, len, compatible))
+ return 0;
+ else
+ return 1;
+}
+
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+ const char *compatible)
+{
+ int offset, err;
+
+ FDT_CHECK_HEADER(fdt);
+
+ /* FIXME: The algorithm here is pretty horrible: we scan each
+ * property of a node in fdt_node_check_compatible(), then if
+ * that didn't find what we want, we scan over them again
+ * making our way to the next node. Still it's the easiest to
+ * implement approach; performance can come later. */
+ for (offset = fdt_next_node(fdt, startoffset, NULL);
+ offset >= 0;
+ offset = fdt_next_node(fdt, offset, NULL)) {
+ err = fdt_node_check_compatible(fdt, offset, compatible);
+ if ((err < 0) && (err != -FDT_ERR_NOTFOUND))
+ return err;
+ else if (err == 0)
+ return offset;
+ }
+
+ return offset; /* error from fdt_next_node() */
+}
--- /dev/null
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_blocks_misordered(const void *fdt,
+ int mem_rsv_size, int struct_size)
+{
+ return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8))
+ || (fdt_off_dt_struct(fdt) <
+ (fdt_off_mem_rsvmap(fdt) + mem_rsv_size))
+ || (fdt_off_dt_strings(fdt) <
+ (fdt_off_dt_struct(fdt) + struct_size))
+ || (fdt_totalsize(fdt) <
+ (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt)));
+}
+
+static int _fdt_rw_check_header(void *fdt)
+{
+ FDT_CHECK_HEADER(fdt);
+
+ if (fdt_version(fdt) < 17)
+ return -FDT_ERR_BADVERSION;
+ if (_fdt_blocks_misordered(fdt, sizeof(struct fdt_reserve_entry),
+ fdt_size_dt_struct(fdt)))
+ return -FDT_ERR_BADLAYOUT;
+ if (fdt_version(fdt) > 17)
+ fdt_set_version(fdt, 17);
+
+ return 0;
+}
+
+#define FDT_RW_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = _fdt_rw_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+static inline int _fdt_data_size(void *fdt)
+{
+ return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+}
+
+static int _fdt_splice(void *fdt, void *splicepoint, int oldlen, int newlen)
+{
+ char *p = splicepoint;
+ char *end = (char *)fdt + _fdt_data_size(fdt);
+
+ if (((p + oldlen) < p) || ((p + oldlen) > end))
+ return -FDT_ERR_BADOFFSET;
+ if ((end - oldlen + newlen) > ((char *)fdt + fdt_totalsize(fdt)))
+ return -FDT_ERR_NOSPACE;
+ memmove(p + newlen, p + oldlen, end - p - oldlen);
+ return 0;
+}
+
+static int _fdt_splice_mem_rsv(void *fdt, struct fdt_reserve_entry *p,
+ int oldn, int newn)
+{
+ int delta = (newn - oldn) * sizeof(*p);
+ int err;
+ err = _fdt_splice(fdt, p, oldn * sizeof(*p), newn * sizeof(*p));
+ if (err)
+ return err;
+ fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta);
+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+ return 0;
+}
+
+static int _fdt_splice_struct(void *fdt, void *p,
+ int oldlen, int newlen)
+{
+ int delta = newlen - oldlen;
+ int err;
+
+ if ((err = _fdt_splice(fdt, p, oldlen, newlen)))
+ return err;
+
+ fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta);
+ fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta);
+ return 0;
+}
+
+static int _fdt_splice_string(void *fdt, int newlen)
+{
+ void *p = (char *)fdt
+ + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt);
+ int err;
+
+ if ((err = _fdt_splice(fdt, p, 0, newlen)))
+ return err;
+
+ fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen);
+ return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+ char *strtab = (char *)fdt + fdt_off_dt_strings(fdt);
+ const char *p;
+ char *new;
+ int len = strlen(s) + 1;
+ int err;
+
+ p = _fdt_find_string(strtab, fdt_size_dt_strings(fdt), s);
+ if (p)
+ /* found it */
+ return (p - strtab);
+
+ new = strtab + fdt_size_dt_strings(fdt);
+ err = _fdt_splice_string(fdt, len);
+ if (err)
+ return err;
+
+ memcpy(new, s, len);
+ return (new - strtab);
+}
+
+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size)
+{
+ struct fdt_reserve_entry *re;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ re = _fdt_mem_rsv_w(fdt, fdt_num_mem_rsv(fdt));
+ err = _fdt_splice_mem_rsv(fdt, re, 0, 1);
+ if (err)
+ return err;
+
+ re->address = cpu_to_fdt64(address);
+ re->size = cpu_to_fdt64(size);
+ return 0;
+}
+
+int fdt_del_mem_rsv(void *fdt, int n)
+{
+ struct fdt_reserve_entry *re = _fdt_mem_rsv_w(fdt, n);
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ if (n >= fdt_num_mem_rsv(fdt))
+ return -FDT_ERR_NOTFOUND;
+
+ err = _fdt_splice_mem_rsv(fdt, re, 1, 0);
+ if (err)
+ return err;
+ return 0;
+}
+
+static int _fdt_resize_property(void *fdt, int nodeoffset, const char *name,
+ int len, struct fdt_property **prop)
+{
+ int oldlen;
+ int err;
+
+ *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen);
+ if (! (*prop))
+ return oldlen;
+
+ if ((err = _fdt_splice_struct(fdt, (*prop)->data, FDT_TAGALIGN(oldlen),
+ FDT_TAGALIGN(len))))
+ return err;
+
+ (*prop)->len = cpu_to_fdt32(len);
+ return 0;
+}
+
+static int _fdt_add_property(void *fdt, int nodeoffset, const char *name,
+ int len, struct fdt_property **prop)
+{
+ int proplen;
+ int nextoffset;
+ int namestroff;
+ int err;
+
+ if ((nextoffset = _fdt_check_node_offset(fdt, nodeoffset)) < 0)
+ return nextoffset;
+
+ namestroff = _fdt_find_add_string(fdt, name);
+ if (namestroff < 0)
+ return namestroff;
+
+ *prop = _fdt_offset_ptr_w(fdt, nextoffset);
+ proplen = sizeof(**prop) + FDT_TAGALIGN(len);
+
+ err = _fdt_splice_struct(fdt, *prop, 0, proplen);
+ if (err)
+ return err;
+
+ (*prop)->tag = cpu_to_fdt32(FDT_PROP);
+ (*prop)->nameoff = cpu_to_fdt32(namestroff);
+ (*prop)->len = cpu_to_fdt32(len);
+ return 0;
+}
+
+int fdt_set_name(void *fdt, int nodeoffset, const char *name)
+{
+ char *namep;
+ int oldlen, newlen;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen);
+ if (!namep)
+ return oldlen;
+
+ newlen = strlen(name);
+
+ err = _fdt_splice_struct(fdt, namep, FDT_TAGALIGN(oldlen+1),
+ FDT_TAGALIGN(newlen+1));
+ if (err)
+ return err;
+
+ memcpy(namep, name, newlen+1);
+ return 0;
+}
+
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ struct fdt_property *prop;
+ int err;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ err = _fdt_resize_property(fdt, nodeoffset, name, len, &prop);
+ if (err == -FDT_ERR_NOTFOUND)
+ err = _fdt_add_property(fdt, nodeoffset, name, len, &prop);
+ if (err)
+ return err;
+
+ memcpy(prop->data, val, len);
+ return 0;
+}
+
+int fdt_delprop(void *fdt, int nodeoffset, const char *name)
+{
+ struct fdt_property *prop;
+ int len, proplen;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+ if (! prop)
+ return len;
+
+ proplen = sizeof(*prop) + FDT_TAGALIGN(len);
+ return _fdt_splice_struct(fdt, prop, proplen, 0);
+}
+
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+ const char *name, int namelen)
+{
+ struct fdt_node_header *nh;
+ int offset, nextoffset;
+ int nodelen;
+ int err;
+ uint32_t tag;
+ uint32_t *endtag;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen);
+ if (offset >= 0)
+ return -FDT_ERR_EXISTS;
+ else if (offset != -FDT_ERR_NOTFOUND)
+ return offset;
+
+ /* Try to place the new node after the parent's properties */
+ fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+ } while ((tag == FDT_PROP) || (tag == FDT_NOP));
+
+ nh = _fdt_offset_ptr_w(fdt, offset);
+ nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE;
+
+ err = _fdt_splice_struct(fdt, nh, 0, nodelen);
+ if (err)
+ return err;
+
+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+ memset(nh->name, 0, FDT_TAGALIGN(namelen+1));
+ memcpy(nh->name, name, namelen);
+ endtag = (uint32_t *)((char *)nh + nodelen - FDT_TAGSIZE);
+ *endtag = cpu_to_fdt32(FDT_END_NODE);
+
+ return offset;
+}
+
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name)
+{
+ return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name));
+}
+
+int fdt_del_node(void *fdt, int nodeoffset)
+{
+ int endoffset;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ if (endoffset < 0)
+ return endoffset;
+
+ return _fdt_splice_struct(fdt, _fdt_offset_ptr_w(fdt, nodeoffset),
+ endoffset - nodeoffset, 0);
+}
+
+static void _fdt_packblocks(const char *old, char *new,
+ int mem_rsv_size, int struct_size)
+{
+ int mem_rsv_off, struct_off, strings_off;
+
+ mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
+ struct_off = mem_rsv_off + mem_rsv_size;
+ strings_off = struct_off + struct_size;
+
+ memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size);
+ fdt_set_off_mem_rsvmap(new, mem_rsv_off);
+
+ memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size);
+ fdt_set_off_dt_struct(new, struct_off);
+ fdt_set_size_dt_struct(new, struct_size);
+
+ memmove(new + strings_off, old + fdt_off_dt_strings(old),
+ fdt_size_dt_strings(old));
+ fdt_set_off_dt_strings(new, strings_off);
+ fdt_set_size_dt_strings(new, fdt_size_dt_strings(old));
+}
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize)
+{
+ int err;
+ int mem_rsv_size, struct_size;
+ int newsize;
+ const char *fdtstart = fdt;
+ const char *fdtend = fdtstart + fdt_totalsize(fdt);
+ char *tmp;
+
+ FDT_CHECK_HEADER(fdt);
+
+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+ * sizeof(struct fdt_reserve_entry);
+
+ if (fdt_version(fdt) >= 17) {
+ struct_size = fdt_size_dt_struct(fdt);
+ } else {
+ struct_size = 0;
+ while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END)
+ ;
+ }
+
+ if (!_fdt_blocks_misordered(fdt, mem_rsv_size, struct_size)) {
+ /* no further work necessary */
+ err = fdt_move(fdt, buf, bufsize);
+ if (err)
+ return err;
+ fdt_set_version(buf, 17);
+ fdt_set_size_dt_struct(buf, struct_size);
+ fdt_set_totalsize(buf, bufsize);
+ return 0;
+ }
+
+ /* Need to reorder */
+ newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size
+ + struct_size + fdt_size_dt_strings(fdt);
+
+ if (bufsize < newsize)
+ return -FDT_ERR_NOSPACE;
+
+ /* First attempt to build converted tree at beginning of buffer */
+ tmp = buf;
+ /* But if that overlaps with the old tree... */
+ if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) {
+ /* Try right after the old tree instead */
+ tmp = (char *)(uintptr_t)fdtend;
+ if ((tmp + newsize) > ((char *)buf + bufsize))
+ return -FDT_ERR_NOSPACE;
+ }
+
+ _fdt_packblocks(fdt, tmp, mem_rsv_size, struct_size);
+ memmove(buf, tmp, newsize);
+
+ fdt_set_magic(buf, FDT_MAGIC);
+ fdt_set_totalsize(buf, bufsize);
+ fdt_set_version(buf, 17);
+ fdt_set_last_comp_version(buf, 16);
+ fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt));
+
+ return 0;
+}
+
+int fdt_pack(void *fdt)
+{
+ int mem_rsv_size;
+
+ FDT_RW_CHECK_HEADER(fdt);
+
+ mem_rsv_size = (fdt_num_mem_rsv(fdt)+1)
+ * sizeof(struct fdt_reserve_entry);
+ _fdt_packblocks(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt));
+ fdt_set_totalsize(fdt, _fdt_data_size(fdt));
+
+ return 0;
+}
--- /dev/null
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+struct fdt_errtabent {
+ const char *str;
+};
+
+#define FDT_ERRTABENT(val) \
+ [(val)] = { .str = #val, }
+
+static struct fdt_errtabent fdt_errtable[] = {
+ FDT_ERRTABENT(FDT_ERR_NOTFOUND),
+ FDT_ERRTABENT(FDT_ERR_EXISTS),
+ FDT_ERRTABENT(FDT_ERR_NOSPACE),
+
+ FDT_ERRTABENT(FDT_ERR_BADOFFSET),
+ FDT_ERRTABENT(FDT_ERR_BADPATH),
+ FDT_ERRTABENT(FDT_ERR_BADSTATE),
+
+ FDT_ERRTABENT(FDT_ERR_TRUNCATED),
+ FDT_ERRTABENT(FDT_ERR_BADMAGIC),
+ FDT_ERRTABENT(FDT_ERR_BADVERSION),
+ FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE),
+ FDT_ERRTABENT(FDT_ERR_BADLAYOUT),
+};
+#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))
+
+const char *fdt_strerror(int errval)
+{
+ if (errval > 0)
+ return "<valid offset/length>";
+ else if (errval == 0)
+ return "<no error>";
+ else if (errval > -FDT_ERRTABSIZE) {
+ const char *s = fdt_errtable[-errval].str;
+
+ if (s)
+ return s;
+ }
+
+ return "<unknown error>";
+}
--- /dev/null
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static int _fdt_sw_check_header(void *fdt)
+{
+ if (fdt_magic(fdt) != FDT_SW_MAGIC)
+ return -FDT_ERR_BADMAGIC;
+ /* FIXME: should check more details about the header state */
+ return 0;
+}
+
+#define FDT_SW_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = _fdt_sw_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+static void *_fdt_grab_space(void *fdt, int len)
+{
+ int offset = fdt_size_dt_struct(fdt);
+ int spaceleft;
+
+ spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt)
+ - fdt_size_dt_strings(fdt);
+
+ if ((offset + len < offset) || (offset + len > spaceleft))
+ return NULL;
+
+ fdt_set_size_dt_struct(fdt, offset + len);
+ return fdt_offset_ptr_w(fdt, offset, len);
+}
+
+int fdt_create(void *buf, int bufsize)
+{
+ void *fdt = buf;
+
+ if (bufsize < sizeof(struct fdt_header))
+ return -FDT_ERR_NOSPACE;
+
+ memset(buf, 0, bufsize);
+
+ fdt_set_magic(fdt, FDT_SW_MAGIC);
+ fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION);
+ fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION);
+ fdt_set_totalsize(fdt, bufsize);
+
+ fdt_set_off_mem_rsvmap(fdt, FDT_ALIGN(sizeof(struct fdt_header),
+ sizeof(struct fdt_reserve_entry)));
+ fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt));
+ fdt_set_off_dt_strings(fdt, bufsize);
+
+ return 0;
+}
+
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size)
+{
+ struct fdt_reserve_entry *re;
+ int offset;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ if (fdt_size_dt_struct(fdt))
+ return -FDT_ERR_BADSTATE;
+
+ offset = fdt_off_dt_struct(fdt);
+ if ((offset + sizeof(*re)) > fdt_totalsize(fdt))
+ return -FDT_ERR_NOSPACE;
+
+ re = (struct fdt_reserve_entry *)((char *)fdt + offset);
+ re->address = cpu_to_fdt64(addr);
+ re->size = cpu_to_fdt64(size);
+
+ fdt_set_off_dt_struct(fdt, offset + sizeof(*re));
+
+ return 0;
+}
+
+int fdt_finish_reservemap(void *fdt)
+{
+ return fdt_add_reservemap_entry(fdt, 0, 0);
+}
+
+int fdt_begin_node(void *fdt, const char *name)
+{
+ struct fdt_node_header *nh;
+ int namelen = strlen(name) + 1;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ nh = _fdt_grab_space(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen));
+ if (! nh)
+ return -FDT_ERR_NOSPACE;
+
+ nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE);
+ memcpy(nh->name, name, namelen);
+ return 0;
+}
+
+int fdt_end_node(void *fdt)
+{
+ uint32_t *en;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ en = _fdt_grab_space(fdt, FDT_TAGSIZE);
+ if (! en)
+ return -FDT_ERR_NOSPACE;
+
+ *en = cpu_to_fdt32(FDT_END_NODE);
+ return 0;
+}
+
+static int _fdt_find_add_string(void *fdt, const char *s)
+{
+ char *strtab = (char *)fdt + fdt_totalsize(fdt);
+ const char *p;
+ int strtabsize = fdt_size_dt_strings(fdt);
+ int len = strlen(s) + 1;
+ int struct_top, offset;
+
+ p = _fdt_find_string(strtab - strtabsize, strtabsize, s);
+ if (p)
+ return p - strtab;
+
+ /* Add it */
+ offset = -strtabsize - len;
+ struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+ if (fdt_totalsize(fdt) + offset < struct_top)
+ return 0; /* no more room :( */
+
+ memcpy(strtab + offset, s, len);
+ fdt_set_size_dt_strings(fdt, strtabsize + len);
+ return offset;
+}
+
+int fdt_property(void *fdt, const char *name, const void *val, int len)
+{
+ struct fdt_property *prop;
+ int nameoff;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ nameoff = _fdt_find_add_string(fdt, name);
+ if (nameoff == 0)
+ return -FDT_ERR_NOSPACE;
+
+ prop = _fdt_grab_space(fdt, sizeof(*prop) + FDT_TAGALIGN(len));
+ if (! prop)
+ return -FDT_ERR_NOSPACE;
+
+ prop->tag = cpu_to_fdt32(FDT_PROP);
+ prop->nameoff = cpu_to_fdt32(nameoff);
+ prop->len = cpu_to_fdt32(len);
+ memcpy(prop->data, val, len);
+ return 0;
+}
+
+int fdt_finish(void *fdt)
+{
+ char *p = (char *)fdt;
+ uint32_t *end;
+ int oldstroffset, newstroffset;
+ uint32_t tag;
+ int offset, nextoffset;
+
+ FDT_SW_CHECK_HEADER(fdt);
+
+ /* Add terminator */
+ end = _fdt_grab_space(fdt, sizeof(*end));
+ if (! end)
+ return -FDT_ERR_NOSPACE;
+ *end = cpu_to_fdt32(FDT_END);
+
+ /* Relocate the string table */
+ oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt);
+ newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt);
+ memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt));
+ fdt_set_off_dt_strings(fdt, newstroffset);
+
+ /* Walk the structure, correcting string offsets */
+ offset = 0;
+ while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) {
+ if (tag == FDT_PROP) {
+ struct fdt_property *prop =
+ fdt_offset_ptr_w(fdt, offset, sizeof(*prop));
+ int nameoff;
+
+ if (! prop)
+ return -FDT_ERR_BADSTRUCTURE;
+
+ nameoff = fdt32_to_cpu(prop->nameoff);
+ nameoff += fdt_size_dt_strings(fdt);
+ prop->nameoff = cpu_to_fdt32(nameoff);
+ }
+ offset = nextoffset;
+ }
+
+ /* Finally, adjust the header */
+ fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt));
+ fdt_set_magic(fdt, FDT_MAGIC);
+ return 0;
+}
--- /dev/null
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len)
+{
+ void *propval;
+ int proplen;
+
+ propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+ if (! propval)
+ return proplen;
+
+ if (proplen != len)
+ return -FDT_ERR_NOSPACE;
+
+ memcpy(propval, val, len);
+ return 0;
+}
+
+static void _fdt_nop_region(void *start, int len)
+{
+ uint32_t *p;
+
+ for (p = start; (char *)p < ((char *)start + len); p++)
+ *p = cpu_to_fdt32(FDT_NOP);
+}
+
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name)
+{
+ struct fdt_property *prop;
+ int len;
+
+ prop = fdt_get_property_w(fdt, nodeoffset, name, &len);
+ if (! prop)
+ return len;
+
+ _fdt_nop_region(prop, len + sizeof(*prop));
+
+ return 0;
+}
+
+int _fdt_node_end_offset(void *fdt, int nodeoffset)
+{
+ int level = 0;
+ uint32_t tag;
+ int offset, nextoffset;
+
+ tag = fdt_next_tag(fdt, nodeoffset, &nextoffset);
+ if (tag != FDT_BEGIN_NODE)
+ return -FDT_ERR_BADOFFSET;
+ do {
+ offset = nextoffset;
+ tag = fdt_next_tag(fdt, offset, &nextoffset);
+
+ switch (tag) {
+ case FDT_END:
+ return offset;
+
+ case FDT_BEGIN_NODE:
+ level++;
+ break;
+
+ case FDT_END_NODE:
+ level--;
+ break;
+
+ case FDT_PROP:
+ case FDT_NOP:
+ break;
+
+ default:
+ return -FDT_ERR_BADSTRUCTURE;
+ }
+ } while (level >= 0);
+
+ return nextoffset;
+}
+
+int fdt_nop_node(void *fdt, int nodeoffset)
+{
+ int endoffset;
+
+ endoffset = _fdt_node_end_offset(fdt, nodeoffset);
+ if (endoffset < 0)
+ return endoffset;
+
+ _fdt_nop_region(fdt_offset_ptr_w(fdt, nodeoffset, 0),
+ endoffset - nodeoffset);
+ return 0;
+}
--- /dev/null
+#ifndef _LIBFDT_H
+#define _LIBFDT_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <libfdt_env.h>
+#include <fdt.h>
+
+#define FDT_FIRST_SUPPORTED_VERSION 0x10
+#define FDT_LAST_SUPPORTED_VERSION 0x11
+
+/* Error codes: informative error codes */
+#define FDT_ERR_NOTFOUND 1
+ /* FDT_ERR_NOTFOUND: The requested node or property does not exist */
+#define FDT_ERR_EXISTS 2
+ /* FDT_ERR_EXISTS: Attemped to create a node or property which
+ * already exists */
+#define FDT_ERR_NOSPACE 3
+ /* FDT_ERR_NOSPACE: Operation needed to expand the device
+ * tree, but its buffer did not have sufficient space to
+ * contain the expanded tree. Use fdt_open_into() to move the
+ * device tree to a buffer with more space. */
+
+/* Error codes: codes for bad parameters */
+#define FDT_ERR_BADOFFSET 4
+ /* FDT_ERR_BADOFFSET: Function was passed a structure block
+ * offset which is out-of-bounds, or which points to an
+ * unsuitable part of the structure for the operation. */
+#define FDT_ERR_BADPATH 5
+ /* FDT_ERR_BADPATH: Function was passed a badly formatted path
+ * (e.g. missing a leading / for a function which requires an
+ * absolute path) */
+#define FDT_ERR_BADPHANDLE 6
+ /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle
+ * value. phandle values of 0 and -1 are not permitted. */
+#define FDT_ERR_BADSTATE 7
+ /* FDT_ERR_BADSTATE: Function was passed an incomplete device
+ * tree created by the sequential-write functions, which is
+ * not sufficiently complete for the requested operation. */
+
+/* Error codes: codes for bad device tree blobs */
+#define FDT_ERR_TRUNCATED 8
+ /* FDT_ERR_TRUNCATED: Structure block of the given device tree
+ * ends without an FDT_END tag. */
+#define FDT_ERR_BADMAGIC 9
+ /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a
+ * device tree at all - it is missing the flattened device
+ * tree magic number. */
+#define FDT_ERR_BADVERSION 10
+ /* FDT_ERR_BADVERSION: Given device tree has a version which
+ * can't be handled by the requested operation. For
+ * read-write functions, this may mean that fdt_open_into() is
+ * required to convert the tree to the expected version. */
+#define FDT_ERR_BADSTRUCTURE 11
+ /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt
+ * structure block or other serious error (e.g. misnested
+ * nodes, or subnodes preceding properties). */
+#define FDT_ERR_BADLAYOUT 12
+ /* FDT_ERR_BADLAYOUT: For read-write functions, the given
+ * device tree has it's sub-blocks in an order that the
+ * function can't handle (memory reserve map, then structure,
+ * then strings). Use fdt_open_into() to reorganize the tree
+ * into a form suitable for the read-write operations. */
+
+/* "Can't happen" error indicating a bug in libfdt */
+#define FDT_ERR_INTERNAL 13
+ /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion.
+ * Should never be returned, if it is, it indicates a bug in
+ * libfdt itself. */
+
+#define FDT_ERR_MAX 13
+
+/**********************************************************************/
+/* Low-level functions (you probably don't need these) */
+/**********************************************************************/
+
+const void *fdt_offset_ptr(const void *fdt, int offset, int checklen);
+static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen)
+{
+ return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen);
+}
+
+uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset);
+
+/**********************************************************************/
+/* Traversal functions */
+/**********************************************************************/
+
+int fdt_next_node(const void *fdt, int offset, int *depth);
+
+/**********************************************************************/
+/* General functions */
+/**********************************************************************/
+
+#define fdt_get_header(fdt, field) \
+ (fdt32_to_cpu(((const struct fdt_header *)(fdt))->field))
+#define fdt_magic(fdt) (fdt_get_header(fdt, magic))
+#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize))
+#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct))
+#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings))
+#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap))
+#define fdt_version(fdt) (fdt_get_header(fdt, version))
+#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version))
+#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys))
+#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings))
+#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct))
+
+#define __fdt_set_hdr(name) \
+ static inline void fdt_set_##name(void *fdt, uint32_t val) \
+ { \
+ struct fdt_header *fdth = fdt; \
+ fdth->name = cpu_to_fdt32(val); \
+ }
+__fdt_set_hdr(magic);
+__fdt_set_hdr(totalsize);
+__fdt_set_hdr(off_dt_struct);
+__fdt_set_hdr(off_dt_strings);
+__fdt_set_hdr(off_mem_rsvmap);
+__fdt_set_hdr(version);
+__fdt_set_hdr(last_comp_version);
+__fdt_set_hdr(boot_cpuid_phys);
+__fdt_set_hdr(size_dt_strings);
+__fdt_set_hdr(size_dt_struct);
+#undef __fdt_set_hdr
+
+/**
+ * fdt_check_header - sanity check a device tree or possible device tree
+ * @fdt: pointer to data which might be a flattened device tree
+ *
+ * fdt_check_header() checks that the given buffer contains what
+ * appears to be a flattened device tree with sane information in its
+ * header.
+ *
+ * returns:
+ * 0, if the buffer appears to contain a valid device tree
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings, as above
+ */
+int fdt_check_header(const void *fdt);
+
+/**
+ * fdt_move - move a device tree around in memory
+ * @fdt: pointer to the device tree to move
+ * @buf: pointer to memory where the device is to be moved
+ * @bufsize: size of the memory space at buf
+ *
+ * fdt_move() relocates, if possible, the device tree blob located at
+ * fdt to the buffer at buf of size bufsize. The buffer may overlap
+ * with the existing device tree blob at fdt. Therefore,
+ * fdt_move(fdt, fdt, fdt_totalsize(fdt))
+ * should always succeed.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_move(const void *fdt, void *buf, int bufsize);
+
+/**********************************************************************/
+/* Read-only functions */
+/**********************************************************************/
+
+/**
+ * fdt_string - retrieve a string from the strings block of a device tree
+ * @fdt: pointer to the device tree blob
+ * @stroffset: offset of the string within the strings block (native endian)
+ *
+ * fdt_string() retrieves a pointer to a single string from the
+ * strings block of the device tree blob at fdt.
+ *
+ * returns:
+ * a pointer to the string, on success
+ * NULL, if stroffset is out of bounds
+ */
+const char *fdt_string(const void *fdt, int stroffset);
+
+/**
+ * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
+ * @fdt: pointer to the device tree blob
+ *
+ * Returns the number of entries in the device tree blob's memory
+ * reservation map. This does not include the terminating 0,0 entry
+ * or any other (0,0) entries reserved for expansion.
+ *
+ * returns:
+ * the number of entries
+ */
+int fdt_num_mem_rsv(const void *fdt);
+
+/**
+ * fdt_get_mem_rsv - retrieve one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: pointers to 64-bit variables
+ *
+ * On success, *address and *size will contain the address and size of
+ * the n-th reserve map entry from the device tree blob, in
+ * native-endian format.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size);
+
+/**
+ * fdt_subnode_offset_namelen - find a subnode based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_subnode_offset(), but only examine the first
+ * namelen characters of name for matching the subnode name. This is
+ * useful for finding subnodes based on a portion of a larger string,
+ * such as a full path.
+ */
+int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
+ const char *name, int namelen);
+/**
+ * fdt_subnode_offset - find a subnode of a given node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_subnode_offset() finds a subnode of the node at structure block
+ * offset parentoffset with the given name. name may include a unit
+ * address, in which case fdt_subnode_offset() will find the subnode
+ * with that unit address, or the unit address may be omitted, in
+ * which case fdt_subnode_offset() will find an arbitrary subnode
+ * whose name excluding unit address matches the given name.
+ *
+ * returns:
+ * structure block offset of the requested subnode (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_path_offset - find a tree node by its full path
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ *
+ * fdt_path_offset() finds a node of a given path in the device tree.
+ * Each path component may omit the unit address portion, but the
+ * results of this are undefined if any such path component is
+ * ambiguous (that is if there are multiple nodes at the relevant
+ * level matching the given component, differentiated only by unit
+ * address).
+ *
+ * returns:
+ * structure block offset of the node with the requested path (>=0), on success
+ * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid
+ * -FDT_ERR_NOTFOUND, if the requested node does not exist
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_path_offset(const void *fdt, const char *path);
+
+/**
+ * fdt_get_name - retrieve the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the starting node
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_name() retrieves the name (including unit address) of the
+ * device tree node at structure block offset nodeoffset. If lenp is
+ * non-NULL, the length of this name is also returned, in the integer
+ * pointed to by lenp.
+ *
+ * returns:
+ * pointer to the node's name, on success
+ * If lenp is non-NULL, *lenp contains the length of that name (>=0)
+ * NULL, on error
+ * if lenp is non-NULL *lenp contains an error code (<0):
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp);
+
+/**
+ * fdt_get_property - find a given property in a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_get_property() retrieves a pointer to the fdt_property
+ * structure within the device tree blob corresponding to the property
+ * named 'name' of the node at offset nodeoffset. If lenp is
+ * non-NULL, the length of the property value is also returned, in the
+ * integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the structure representing the property
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_NOTFOUND, node does not have named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset,
+ const char *name, int *lenp);
+static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset,
+ const char *name,
+ int *lenp)
+{
+ return (struct fdt_property *)(uintptr_t)
+ fdt_get_property(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_getprop - retrieve the value of a given property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to find
+ * @name: name of the property to find
+ * @lenp: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_getprop() retrieves a pointer to the value of the property
+ * named 'name' of the node at offset nodeoffset (this will be a
+ * pointer to within the device blob itself, not a copy of the value).
+ * If lenp is non-NULL, the length of the property value is also
+ * returned, in the integer pointed to by lenp.
+ *
+ * returns:
+ * pointer to the property's value
+ * if lenp is non-NULL, *lenp contains the length of the property
+ * value (>=0)
+ * NULL, on error
+ * if lenp is non-NULL, *lenp contains an error code (<0):
+ * -FDT_ERR_NOTFOUND, node does not have named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+const void *fdt_getprop(const void *fdt, int nodeoffset,
+ const char *name, int *lenp);
+static inline void *fdt_getprop_w(void *fdt, int nodeoffset,
+ const char *name, int *lenp)
+{
+ return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp);
+}
+
+/**
+ * fdt_get_phandle - retrieve the phandle of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of the node
+ *
+ * fdt_get_phandle() retrieves the phandle of the device tree node at
+ * structure block offset nodeoffset.
+ *
+ * returns:
+ * the phandle of the node at nodeoffset, on success (!= 0, != -1)
+ * 0, if the node has no phandle, or another error occurs
+ */
+uint32_t fdt_get_phandle(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_get_path - determine the full path of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose path to find
+ * @buf: character buffer to contain the returned path (will be overwritten)
+ * @buflen: size of the character buffer at buf
+ *
+ * fdt_get_path() computes the full path of the node at offset
+ * nodeoffset, and records that path in the buffer at buf.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ * 0, on success
+ * buf contains the absolute path of the node at
+ * nodeoffset, as a NUL-terminated string.
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1)
+ * characters and will not fit in the given buffer.
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen);
+
+/**
+ * fdt_supernode_atdepth_offset - find a specific ancestor of a node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ * @supernodedepth: depth of the ancestor to find
+ * @nodedepth: pointer to an integer variable (will be overwritten) or NULL
+ *
+ * fdt_supernode_atdepth_offset() finds an ancestor of the given node
+ * at a specific depth from the root (where the root itself has depth
+ * 0, its immediate subnodes depth 1 and so forth). So
+ * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL);
+ * will always return 0, the offset of the root node. If the node at
+ * nodeoffset has depth D, then:
+ * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL);
+ * will return nodeoffset itself.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+
+ * structure block offset of the node at node offset's ancestor
+ * of depth supernodedepth (>=0), on success
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+* -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of nodeoffset
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset,
+ int supernodedepth, int *nodedepth);
+
+/**
+ * fdt_node_depth - find the depth of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_node_depth() finds the depth of a given node. The root node
+ * has depth 0, its immediate subnodes depth 1 and so forth.
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset.
+ *
+ * returns:
+ * depth of the node at nodeoffset (>=0), on success
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_depth(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_parent_offset - find the parent of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose parent to find
+ *
+ * fdt_parent_offset() locates the parent node of a given node (that
+ * is, it finds the offset of the node which contains the node at
+ * nodeoffset as a subnode).
+ *
+ * NOTE: This function is expensive, as it must scan the device tree
+ * structure from the start to nodeoffset, *twice*.
+ *
+ * returns:
+ * structure block offset of the parent of the node at nodeoffset
+ * (>=0), on success
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_parent_offset(const void *fdt, int nodeoffset);
+
+/**
+ * fdt_node_offset_by_prop_value - find nodes with a given property value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @propname: property name to check
+ * @propval: property value to search for
+ * @proplen: length of the value in propval
+ *
+ * fdt_node_offset_by_prop_value() returns the offset of the first
+ * node after startoffset, which has a property named propname whose
+ * value is of length proplen and has value equal to propval; or if
+ * startoffset is -1, the very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ * offset = fdt_node_offset_by_prop_value(fdt, -1, propname,
+ * propval, proplen);
+ * while (offset != -FDT_ERR_NOTFOUND) {
+ * // other code here
+ * offset = fdt_node_offset_by_prop_value(fdt, offset, propname,
+ * propval, proplen);
+ * }
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0, >startoffset),
+ * on success
+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ * tree after startoffset
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_prop_value(const void *fdt, int startoffset,
+ const char *propname,
+ const void *propval, int proplen);
+
+/**
+ * fdt_node_offset_by_phandle - find the node with a given phandle
+ * @fdt: pointer to the device tree blob
+ * @phandle: phandle value
+ *
+ * fdt_node_offset_by_phandle() returns the offset of the node
+ * which has the given phandle value. If there is more than one node
+ * in the tree with the given phandle (an invalid tree), results are
+ * undefined.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0), on success
+ * -FDT_ERR_NOTFOUND, no node with that phandle exists
+ * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1)
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle);
+
+/**
+ * fdt_node_check_compatible: check a node's compatible property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of a tree node
+ * @compatible: string to match against
+ *
+ *
+ * fdt_node_check_compatible() returns 0 if the given node contains a
+ * 'compatible' property with the given string as one of its elements,
+ * it returns non-zero otherwise, or on error.
+ *
+ * returns:
+ * 0, if the node has a 'compatible' property listing the given string
+ * 1, if the node has a 'compatible' property, but it does not list
+ * the given string
+ * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property
+ * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_check_compatible(const void *fdt, int nodeoffset,
+ const char *compatible);
+
+/**
+ * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value
+ * @fdt: pointer to the device tree blob
+ * @startoffset: only find nodes after this offset
+ * @compatible: 'compatible' string to match against
+ *
+ * fdt_node_offset_by_compatible() returns the offset of the first
+ * node after startoffset, which has a 'compatible' property which
+ * lists the given compatible string; or if startoffset is -1, the
+ * very first such node in the tree.
+ *
+ * To iterate through all nodes matching the criterion, the following
+ * idiom can be used:
+ * offset = fdt_node_offset_by_compatible(fdt, -1, compatible);
+ * while (offset != -FDT_ERR_NOTFOUND) {
+ * // other code here
+ * offset = fdt_node_offset_by_compatible(fdt, offset, compatible);
+ * }
+ *
+ * Note the -1 in the first call to the function, if 0 is used here
+ * instead, the function will never locate the root node, even if it
+ * matches the criterion.
+ *
+ * returns:
+ * structure block offset of the located node (>= 0, >startoffset),
+ * on success
+ * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the
+ * tree after startoffset
+ * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE, standard meanings
+ */
+int fdt_node_offset_by_compatible(const void *fdt, int startoffset,
+ const char *compatible);
+
+/**********************************************************************/
+/* Write-in-place functions */
+/**********************************************************************/
+
+/**
+ * fdt_setprop_inplace - change a property's value, but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * fdt_setprop_inplace() replaces the value of a given property with
+ * the data in val, of length len. This function cannot change the
+ * size of a property, and so will only work if len is equal to the
+ * current length of the property.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, if len is not equal to the property's current length
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len);
+
+/**
+ * fdt_setprop_inplace_cell - change the value of a single-cell property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: cell (32-bit integer) value to replace the property with
+ *
+ * fdt_setprop_inplace_cell() replaces the value of a given property
+ * with the 32-bit integer cell value in val, converting val to
+ * big-endian if necessary. This function cannot change the size of a
+ * property, and so will only work if the property already exists and
+ * has length 4.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the given property value, and will not alter or move any other part
+ * of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, if the property's length is not equal to 4
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset,
+ const char *name, uint32_t val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_setprop_inplace(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_nop_property - replace a property with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_nop_property() will replace a given property's representation
+ * in the blob with FDT_NOP tags, effectively removing it from the
+ * tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the property, and will not alter or move any other part of the
+ * tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_property(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_nop_node - replace a node (subtree) with nop tags
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_nop_node() will replace a given node's representation in the
+ * blob, including all its subnodes, if any, with FDT_NOP tags,
+ * effectively removing it from the tree.
+ *
+ * This function will alter only the bytes in the blob which contain
+ * the node and its properties and subnodes, and will not alter or
+ * move any other part of the tree.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_nop_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Sequential write functions */
+/**********************************************************************/
+
+int fdt_create(void *buf, int bufsize);
+int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size);
+int fdt_finish_reservemap(void *fdt);
+int fdt_begin_node(void *fdt, const char *name);
+int fdt_property(void *fdt, const char *name, const void *val, int len);
+static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_property(fdt, name, &val, sizeof(val));
+}
+#define fdt_property_string(fdt, name, str) \
+ fdt_property(fdt, name, str, strlen(str)+1)
+int fdt_end_node(void *fdt);
+int fdt_finish(void *fdt);
+
+/**********************************************************************/
+/* Read-write functions */
+/**********************************************************************/
+
+int fdt_open_into(const void *fdt, void *buf, int bufsize);
+int fdt_pack(void *fdt);
+
+/**
+ * fdt_add_mem_rsv - add one memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @address, @size: 64-bit values (native endian)
+ *
+ * Adds a reserve map entry to the given blob reserving a region at
+ * address address of length size.
+ *
+ * This function will insert data into the reserve map and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new reservation entry
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size);
+
+/**
+ * fdt_del_mem_rsv - remove a memory reserve map entry
+ * @fdt: pointer to the device tree blob
+ * @n: entry to remove
+ *
+ * fdt_del_mem_rsv() removes the n-th memory reserve map entry from
+ * the blob.
+ *
+ * This function will delete data from the reservation table and will
+ * therefore change the indexes of some entries in the table.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there
+ * are less than n+1 reserve map entries)
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_mem_rsv(void *fdt, int n);
+
+/**
+ * fdt_set_name - change the name of a given node
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: structure block offset of a node
+ * @name: name to give the node
+ *
+ * fdt_set_name() replaces the name (including unit address, if any)
+ * of the given node with the given string. NOTE: this function can't
+ * efficiently check if the new name is unique amongst the given
+ * node's siblings; results are undefined if this function is invoked
+ * with a name equal to one of the given node's siblings.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob
+ * to contain the new name
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE, standard meanings
+ */
+int fdt_set_name(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_setprop - create or change a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: pointer to data to set the property value to
+ * @len: length of the property value
+ *
+ * fdt_setprop() sets the value of the named property in the given
+ * node to the given value and length, creating the property if it
+ * does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_setprop(void *fdt, int nodeoffset, const char *name,
+ const void *val, int len);
+
+/**
+ * fdt_setprop_cell - set a property to a single cell value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @val: 32-bit integer value for the property (native endian)
+ *
+ * fdt_setprop_cell() sets the value of the named property in the
+ * given node to the given cell value (converting to big-endian if
+ * necessary), or creates a new property with that value if it does
+ * not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name,
+ uint32_t val)
+{
+ val = cpu_to_fdt32(val);
+ return fdt_setprop(fdt, nodeoffset, name, &val, sizeof(val));
+}
+
+/**
+ * fdt_setprop_string - set a property to a string value
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @str: string value for the property
+ *
+ * fdt_setprop_string() sets the value of the named property in the
+ * given node to the given string value (using the length of the
+ * string to determine the new length of the property), or creates a
+ * new property with that value if it does not already exist.
+ *
+ * This function may insert or delete data from the blob, and will
+ * therefore change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to
+ * contain the new property value
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+#define fdt_setprop_string(fdt, nodeoffset, name, str) \
+ fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1)
+
+/**
+ * fdt_delprop - delete a property
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to nop
+ * @name: name of the property to nop
+ *
+ * fdt_del_property() will delete the given property.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_NOTFOUND, node does not have the named property
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_delprop(void *fdt, int nodeoffset, const char *name);
+
+/**
+ * fdt_add_subnode_namelen - creates a new node based on substring
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_add_subnode(), but use only the first namelen
+ * characters of name as the name of the new node. This is useful for
+ * creating subnodes based on a portion of a larger string, such as a
+ * full path.
+ */
+int fdt_add_subnode_namelen(void *fdt, int parentoffset,
+ const char *name, int namelen);
+
+/**
+ * fdt_add_subnode - creates a new node
+ * @fdt: pointer to the device tree blob
+ * @parentoffset: structure block offset of a node
+ * @name: name of the subnode to locate
+ *
+ * fdt_add_subnode() creates a new node as a subnode of the node at
+ * structure block offset parentoffset, with the given name (which
+ * should include the unit address, if any).
+ *
+ * This function will insert data into the blob, and will therefore
+ * change the offsets of some existing nodes.
+
+ * returns:
+ * structure block offset of the created nodeequested subnode (>=0), on success
+ * -FDT_ERR_NOTFOUND, if the requested subnode does not exist
+ * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE tag
+ * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of
+ * the given name
+ * -FDT_ERR_NOSPACE, if there is insufficient free space in the
+ * blob to contain the new node
+ * -FDT_ERR_NOSPACE
+ * -FDT_ERR_BADLAYOUT
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings.
+ */
+int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
+
+/**
+ * fdt_del_node - delete a node (subtree)
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node to nop
+ *
+ * fdt_del_node() will remove the given node, including all its
+ * subnodes if any, from the blob.
+ *
+ * This function will delete data from the blob, and will therefore
+ * change the offsets of some existing nodes.
+ *
+ * returns:
+ * 0, on success
+ * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag
+ * -FDT_ERR_BADLAYOUT,
+ * -FDT_ERR_BADMAGIC,
+ * -FDT_ERR_BADVERSION,
+ * -FDT_ERR_BADSTATE,
+ * -FDT_ERR_BADSTRUCTURE,
+ * -FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_del_node(void *fdt, int nodeoffset);
+
+/**********************************************************************/
+/* Debugging / informational functions */
+/**********************************************************************/
+
+const char *fdt_strerror(int errval);
+
+#endif /* _LIBFDT_H */
--- /dev/null
+#ifndef _LIBFDT_ENV_H
+#define _LIBFDT_ENV_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#define _B(n) ((unsigned long long)((uint8_t *)&x)[n])
+static inline uint32_t fdt32_to_cpu(uint32_t x)
+{
+ return (_B(0) << 24) | (_B(1) << 16) | (_B(2) << 8) | _B(3);
+}
+#define cpu_to_fdt32(x) fdt32_to_cpu(x)
+
+static inline uint64_t fdt64_to_cpu(uint64_t x)
+{
+ return (_B(0) << 56) | (_B(1) << 48) | (_B(2) << 40) | (_B(3) << 32)
+ | (_B(4) << 24) | (_B(5) << 16) | (_B(6) << 8) | _B(7);
+}
+#define cpu_to_fdt64(x) fdt64_to_cpu(x)
+#undef _B
+
+#endif /* _LIBFDT_ENV_H */
--- /dev/null
+#ifndef _LIBFDT_INTERNAL_H
+#define _LIBFDT_INTERNAL_H
+/*
+ * libfdt - Flat Device Tree manipulation
+ * Copyright (C) 2006 David Gibson, IBM Corporation.
+ *
+ * libfdt is dual licensed: you can use it either under the terms of
+ * the GPL, or the BSD license, at your option.
+ *
+ * a) This library 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 library 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 library; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * Alternatively,
+ *
+ * b) Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <fdt.h>
+
+#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1))
+#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE))
+
+#define FDT_CHECK_HEADER(fdt) \
+ { \
+ int err; \
+ if ((err = fdt_check_header(fdt)) != 0) \
+ return err; \
+ }
+
+uint32_t _fdt_next_tag(const void *fdt, int startoffset, int *nextoffset);
+int _fdt_check_node_offset(const void *fdt, int offset);
+const char *_fdt_find_string(const char *strtab, int tabsize, const char *s);
+int _fdt_node_end_offset(void *fdt, int nodeoffset);
+
+static inline const void *_fdt_offset_ptr(const void *fdt, int offset)
+{
+ return (const char *)fdt + fdt_off_dt_struct(fdt) + offset;
+}
+
+static inline void *_fdt_offset_ptr_w(void *fdt, int offset)
+{
+ return (void *)(uintptr_t)_fdt_offset_ptr(fdt, offset);
+}
+
+static inline const struct fdt_reserve_entry *_fdt_mem_rsv(const void *fdt, int n)
+{
+ const struct fdt_reserve_entry *rsv_table =
+ (const struct fdt_reserve_entry *)
+ ((const char *)fdt + fdt_off_mem_rsvmap(fdt));
+
+ return rsv_table + n;
+}
+static inline struct fdt_reserve_entry *_fdt_mem_rsv_w(void *fdt, int n)
+{
+ return (void *)(uintptr_t)_fdt_mem_rsv(fdt, n);
+}
+
+#define FDT_SW_MAGIC (~FDT_MAGIC)
+
+#endif /* _LIBFDT_INTERNAL_H */
--- /dev/null
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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 "dtc.h"
+
+/*
+ * Tree building functions
+ */
+
+struct property *build_property(char *name, struct data val, char *label)
+{
+ struct property *new = xmalloc(sizeof(*new));
+
+ new->name = name;
+ new->val = val;
+
+ new->next = NULL;
+
+ new->label = label;
+
+ return new;
+}
+
+struct property *chain_property(struct property *first, struct property *list)
+{
+ assert(first->next == NULL);
+
+ first->next = list;
+ return first;
+}
+
+struct property *reverse_properties(struct property *first)
+{
+ struct property *p = first;
+ struct property *head = NULL;
+ struct property *next;
+
+ while (p) {
+ next = p->next;
+ p->next = head;
+ head = p;
+ p = next;
+ }
+ return head;
+}
+
+struct node *build_node(struct property *proplist, struct node *children)
+{
+ struct node *new = xmalloc(sizeof(*new));
+ struct node *child;
+
+ memset(new, 0, sizeof(*new));
+
+ new->proplist = reverse_properties(proplist);
+ new->children = children;
+
+ for_each_child(new, child) {
+ child->parent = new;
+ }
+
+ return new;
+}
+
+struct node *name_node(struct node *node, char *name, char * label)
+{
+ assert(node->name == NULL);
+
+ node->name = name;
+
+ node->label = label;
+
+ return node;
+}
+
+struct node *chain_node(struct node *first, struct node *list)
+{
+ assert(first->next_sibling == NULL);
+
+ first->next_sibling = list;
+ return first;
+}
+
+void add_property(struct node *node, struct property *prop)
+{
+ struct property **p;
+
+ prop->next = NULL;
+
+ p = &node->proplist;
+ while (*p)
+ p = &((*p)->next);
+
+ *p = prop;
+}
+
+void add_child(struct node *parent, struct node *child)
+{
+ struct node **p;
+
+ child->next_sibling = NULL;
+ child->parent = parent;
+
+ p = &parent->children;
+ while (*p)
+ p = &((*p)->next_sibling);
+
+ *p = child;
+}
+
+struct reserve_info *build_reserve_entry(uint64_t address, uint64_t size,
+ char *label)
+{
+ struct reserve_info *new = xmalloc(sizeof(*new));
+
+ new->re.address = address;
+ new->re.size = size;
+
+ new->next = NULL;
+
+ new->label = label;
+
+ return new;
+}
+
+struct reserve_info *chain_reserve_entry(struct reserve_info *first,
+ struct reserve_info *list)
+{
+ assert(first->next == NULL);
+
+ first->next = list;
+ return first;
+}
+
+struct reserve_info *add_reserve_entry(struct reserve_info *list,
+ struct reserve_info *new)
+{
+ struct reserve_info *last;
+
+ new->next = NULL;
+
+ if (! list)
+ return new;
+
+ for (last = list; last->next; last = last->next)
+ ;
+
+ last->next = new;
+
+ return list;
+}
+
+struct boot_info *build_boot_info(struct reserve_info *reservelist,
+ struct node *tree, uint32_t boot_cpuid_phys)
+{
+ struct boot_info *bi;
+
+ bi = xmalloc(sizeof(*bi));
+ bi->reservelist = reservelist;
+ bi->dt = tree;
+ bi->boot_cpuid_phys = boot_cpuid_phys;
+
+ return bi;
+}
+
+/*
+ * Tree accessor functions
+ */
+
+const char *get_unitname(struct node *node)
+{
+ if (node->name[node->basenamelen] == '\0')
+ return "";
+ else
+ return node->name + node->basenamelen + 1;
+}
+
+struct property *get_property(struct node *node, const char *propname)
+{
+ struct property *prop;
+
+ for_each_property(node, prop)
+ if (streq(prop->name, propname))
+ return prop;
+
+ return NULL;
+}
+
+cell_t propval_cell(struct property *prop)
+{
+ assert(prop->val.len == sizeof(cell_t));
+ return fdt32_to_cpu(*((cell_t *)prop->val.val));
+}
+
+struct node *get_subnode(struct node *node, const char *nodename)
+{
+ struct node *child;
+
+ for_each_child(node, child)
+ if (streq(child->name, nodename))
+ return child;
+
+ return NULL;
+}
+
+struct node *get_node_by_path(struct node *tree, const char *path)
+{
+ const char *p;
+ struct node *child;
+
+ if (!path || ! (*path))
+ return tree;
+
+ while (path[0] == '/')
+ path++;
+
+ p = strchr(path, '/');
+
+ for_each_child(tree, child) {
+ if (p && strneq(path, child->name, p-path))
+ return get_node_by_path(child, p+1);
+ else if (!p && streq(path, child->name))
+ return child;
+ }
+
+ return NULL;
+}
+
+struct node *get_node_by_label(struct node *tree, const char *label)
+{
+ struct node *child, *node;
+
+ assert(label && (strlen(label) > 0));
+
+ if (tree->label && streq(tree->label, label))
+ return tree;
+
+ for_each_child(tree, child) {
+ node = get_node_by_label(child, label);
+ if (node)
+ return node;
+ }
+
+ return NULL;
+}
+
+struct node *get_node_by_phandle(struct node *tree, cell_t phandle)
+{
+ struct node *child, *node;
+
+ assert((phandle != 0) && (phandle != -1));
+
+ if (tree->phandle == phandle)
+ return tree;
+
+ for_each_child(tree, child) {
+ node = get_node_by_phandle(child, phandle);
+ if (node)
+ return node;
+ }
+
+ return NULL;
+}
+
+struct node *get_node_by_ref(struct node *tree, const char *ref)
+{
+ if (ref[0] == '/')
+ return get_node_by_path(tree, ref);
+ else
+ return get_node_by_label(tree, ref);
+}
+
+cell_t get_node_phandle(struct node *root, struct node *node)
+{
+ static cell_t phandle = 1; /* FIXME: ick, static local */
+
+ if ((node->phandle != 0) && (node->phandle != -1))
+ return node->phandle;
+
+ assert(! get_property(node, "linux,phandle"));
+
+ while (get_node_by_phandle(root, phandle))
+ phandle++;
+
+ node->phandle = phandle;
+ add_property(node,
+ build_property("linux,phandle",
+ data_append_cell(empty_data, phandle),
+ NULL));
+
+ return node->phandle;
+}
--- /dev/null
+/*
+ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * 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 "dtc.h"
+#include "srcpos.h"
+
+/*
+ * Like yylineno, this is the current open file pos.
+ */
+
+struct dtc_file *srcpos_file;
+
+static int dtc_open_one(struct dtc_file *file,
+ const char *search,
+ const char *fname)
+{
+ char *fullname;
+
+ if (search) {
+ fullname = xmalloc(strlen(search) + strlen(fname) + 2);
+
+ strcpy(fullname, search);
+ strcat(fullname, "/");
+ strcat(fullname, fname);
+ } else {
+ fullname = strdup(fname);
+ }
+
+ file->file = fopen(fullname, "r");
+ if (!file->file) {
+ free(fullname);
+ return 0;
+ }
+
+ file->name = fullname;
+ return 1;
+}
+
+
+struct dtc_file *dtc_open_file(const char *fname,
+ const struct search_path *search)
+{
+ static const struct search_path default_search = { NULL, NULL, NULL };
+
+ struct dtc_file *file;
+ const char *slash;
+
+ file = xmalloc(sizeof(struct dtc_file));
+
+ slash = strrchr(fname, '/');
+ if (slash) {
+ char *dir = xmalloc(slash - fname + 1);
+
+ memcpy(dir, fname, slash - fname);
+ dir[slash - fname] = 0;
+ file->dir = dir;
+ } else {
+ file->dir = NULL;
+ }
+
+ if (streq(fname, "-")) {
+ file->name = "stdin";
+ file->file = stdin;
+ return file;
+ }
+
+ if (fname[0] == '/') {
+ file->file = fopen(fname, "r");
+ if (!file->file)
+ goto fail;
+
+ file->name = strdup(fname);
+ return file;
+ }
+
+ if (!search)
+ search = &default_search;
+
+ while (search) {
+ if (dtc_open_one(file, search->dir, fname))
+ return file;
+
+ if (errno != ENOENT)
+ goto fail;
+
+ search = search->next;
+ }
+
+fail:
+ die("Couldn't open \"%s\": %s\n", fname, strerror(errno));
+}
+
+void dtc_close_file(struct dtc_file *file)
+{
+ if (fclose(file->file))
+ die("Error closing \"%s\": %s\n", file->name, strerror(errno));
+
+ free(file->dir);
+ free(file);
+}
--- /dev/null
+/*
+ * Copyright 2007 Jon Loeliger, Freescale Semiconductor, Inc.
+ *
+ * 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
+ */
+
+/*
+ * Augment the standard YYLTYPE with a filenum index into an
+ * array of all opened filenames.
+ */
+
+#include <stdio.h>
+
+struct dtc_file {
+ char *dir;
+ const char *name;
+ FILE *file;
+};
+
+#if ! defined(YYLTYPE) && ! defined(YYLTYPE_IS_DECLARED)
+typedef struct YYLTYPE {
+ int first_line;
+ int first_column;
+ int last_line;
+ int last_column;
+ struct dtc_file *file;
+} YYLTYPE;
+
+#define YYLTYPE_IS_DECLARED 1
+#define YYLTYPE_IS_TRIVIAL 1
+#endif
+
+/* Cater to old parser templates. */
+#ifndef YYID
+#define YYID(n) (n)
+#endif
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ (Current).file = YYRHSLOC (Rhs, N).file; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ (Current).file = YYRHSLOC (Rhs, 0).file; \
+ } \
+ while (YYID (0))
+
+
+
+extern void yyerror(char const *);
+extern void yyerrorf(char const *, ...) __attribute__((format(printf, 1, 2)));
+
+extern struct dtc_file *srcpos_file;
+
+struct search_path {
+ const char *dir; /* NULL for current directory */
+ struct search_path *prev, *next;
+};
+
+extern struct dtc_file *dtc_open_file(const char *fname,
+ const struct search_path *search);
+extern void dtc_close_file(struct dtc_file *file);
--- /dev/null
+/*
+ * (C) Copyright David Gibson <dwg@au1.ibm.com>, IBM Corporation. 2005.
+ *
+ *
+ * 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 "dtc.h"
+#include "srcpos.h"
+
+extern FILE *yyin;
+extern int yyparse(void);
+
+struct boot_info *the_boot_info;
+int treesource_error;
+
+struct boot_info *dt_from_source(const char *fname)
+{
+ the_boot_info = NULL;
+ treesource_error = 0;
+
+ srcpos_file = dtc_open_file(fname, NULL);
+ yyin = srcpos_file->file;
+
+ if (yyparse() != 0)
+ die("Unable to parse input tree\n");
+
+ if (treesource_error)
+ die("Syntax error parsing input tree\n");
+
+ return the_boot_info;
+}
+
+static void write_prefix(FILE *f, int level)
+{
+ int i;
+
+ for (i = 0; i < level; i++)
+ fputc('\t', f);
+}
+
+int isstring(char c)
+{
+ return (isprint(c)
+ || (c == '\0')
+ || strchr("\a\b\t\n\v\f\r", c));
+}
+
+static void write_propval_string(FILE *f, struct data val)
+{
+ const char *str = val.val;
+ int i;
+ int newchunk = 1;
+ struct marker *m = val.markers;
+
+ assert(str[val.len-1] == '\0');
+
+ for (i = 0; i < (val.len-1); i++) {
+ char c = str[i];
+
+ if (newchunk) {
+ while (m && (m->offset <= i)) {
+ if (m->type == LABEL) {
+ assert(m->offset == i);
+ fprintf(f, "%s: ", m->ref);
+ }
+ m = m->next;
+ }
+ fprintf(f, "\"");
+ newchunk = 0;
+ }
+
+ switch (c) {
+ case '\a':
+ fprintf(f, "\\a");
+ break;
+ case '\b':
+ fprintf(f, "\\b");
+ break;
+ case '\t':
+ fprintf(f, "\\t");
+ break;
+ case '\n':
+ fprintf(f, "\\n");
+ break;
+ case '\v':
+ fprintf(f, "\\v");
+ break;
+ case '\f':
+ fprintf(f, "\\f");
+ break;
+ case '\r':
+ fprintf(f, "\\r");
+ break;
+ case '\\':
+ fprintf(f, "\\\\");
+ break;
+ case '\"':
+ fprintf(f, "\\\"");
+ break;
+ case '\0':
+ fprintf(f, "\", ");
+ newchunk = 1;
+ break;
+ default:
+ if (isprint(c))
+ fprintf(f, "%c", c);
+ else
+ fprintf(f, "\\x%02hhx", c);
+ }
+ }
+ fprintf(f, "\"");
+
+ /* Wrap up any labels at the end of the value */
+ for_each_marker_of_type(m, LABEL) {
+ assert (m->offset == val.len);
+ fprintf(f, " %s:", m->ref);
+ }
+}
+
+static void write_propval_cells(FILE *f, struct data val)
+{
+ void *propend = val.val + val.len;
+ cell_t *cp = (cell_t *)val.val;
+ struct marker *m = val.markers;
+
+ fprintf(f, "<");
+ for (;;) {
+ while (m && (m->offset <= ((char *)cp - val.val))) {
+ if (m->type == LABEL) {
+ assert(m->offset == ((char *)cp - val.val));
+ fprintf(f, "%s: ", m->ref);
+ }
+ m = m->next;
+ }
+
+ fprintf(f, "0x%x", fdt32_to_cpu(*cp++));
+ if ((void *)cp >= propend)
+ break;
+ fprintf(f, " ");
+ }
+
+ /* Wrap up any labels at the end of the value */
+ for_each_marker_of_type(m, LABEL) {
+ assert (m->offset == val.len);
+ fprintf(f, " %s:", m->ref);
+ }
+ fprintf(f, ">");
+}
+
+static void write_propval_bytes(FILE *f, struct data val)
+{
+ void *propend = val.val + val.len;
+ const char *bp = val.val;
+ struct marker *m = val.markers;
+
+ fprintf(f, "[");
+ for (;;) {
+ while (m && (m->offset == (bp-val.val))) {
+ if (m->type == LABEL)
+ fprintf(f, "%s: ", m->ref);
+ m = m->next;
+ }
+
+ fprintf(f, "%02hhx", *bp++);
+ if ((const void *)bp >= propend)
+ break;
+ fprintf(f, " ");
+ }
+
+ /* Wrap up any labels at the end of the value */
+ for_each_marker_of_type(m, LABEL) {
+ assert (m->offset == val.len);
+ fprintf(f, " %s:", m->ref);
+ }
+ fprintf(f, "]");
+}
+
+static void write_propval(FILE *f, struct property *prop)
+{
+ int len = prop->val.len;
+ const char *p = prop->val.val;
+ struct marker *m = prop->val.markers;
+ int nnotstring = 0, nnul = 0;
+ int nnotstringlbl = 0, nnotcelllbl = 0;
+ int i;
+
+ if (len == 0) {
+ fprintf(f, ";\n");
+ return;
+ }
+
+ for (i = 0; i < len; i++) {
+ if (! isstring(p[i]))
+ nnotstring++;
+ if (p[i] == '\0')
+ nnul++;
+ }
+
+ for_each_marker_of_type(m, LABEL) {
+ if ((m->offset > 0) && (prop->val.val[m->offset - 1] != '\0'))
+ nnotstringlbl++;
+ if ((m->offset % sizeof(cell_t)) != 0)
+ nnotcelllbl++;
+ }
+
+ fprintf(f, " = ");
+ if ((p[len-1] == '\0') && (nnotstring == 0) && (nnul < (len-nnul))
+ && (nnotstringlbl == 0)) {
+ write_propval_string(f, prop->val);
+ } else if (((len % sizeof(cell_t)) == 0) && (nnotcelllbl == 0)) {
+ write_propval_cells(f, prop->val);
+ } else {
+ write_propval_bytes(f, prop->val);
+ }
+
+ fprintf(f, ";\n");
+}
+
+static void write_tree_source_node(FILE *f, struct node *tree, int level)
+{
+ struct property *prop;
+ struct node *child;
+
+ write_prefix(f, level);
+ if (tree->label)
+ fprintf(f, "%s: ", tree->label);
+ if (tree->name && (*tree->name))
+ fprintf(f, "%s {\n", tree->name);
+ else
+ fprintf(f, "/ {\n");
+
+ for_each_property(tree, prop) {
+ write_prefix(f, level+1);
+ if (prop->label)
+ fprintf(f, "%s: ", prop->label);
+ fprintf(f, "%s", prop->name);
+ write_propval(f, prop);
+ }
+ for_each_child(tree, child) {
+ fprintf(f, "\n");
+ write_tree_source_node(f, child, level+1);
+ }
+ write_prefix(f, level);
+ fprintf(f, "};\n");
+}
+
+
+void dt_to_source(FILE *f, struct boot_info *bi)
+{
+ struct reserve_info *re;
+
+ fprintf(f, "/dts-v1/;\n\n");
+
+ for (re = bi->reservelist; re; re = re->next) {
+ if (re->label)
+ fprintf(f, "%s: ", re->label);
+ fprintf(f, "/memreserve/\t0x%016llx 0x%016llx;\n",
+ (unsigned long long)re->re.address,
+ (unsigned long long)re->re.size);
+ }
+
+ write_tree_source_node(f, bi->dt, 0);
+}
+
--- /dev/null
+#define DTC_VERSION "DTC 1.2.0"
my $file = shift;
my $nested;
- if ($x =~/(struct|union)\s+(\w+)\s*{(.*)}/) {
+ if ($x =~ /(struct|union)\s+(\w+)\s*{(.*)}/) {
+ #my $decl_type = $1;
$declaration_name = $2;
my $members = $3;
$nested = $1;
# ignore members marked private:
- $members =~ s/\/\*.*?private:.*?public:.*?\*\///gos;
- $members =~ s/\/\*.*?private:.*//gos;
+ $members =~ s/\/\*\s*private:.*?\/\*\s*public:.*?\*\///gos;
+ $members =~ s/\/\*\s*private:.*//gos;
# strip comments:
$members =~ s/\/\*.*?\*\///gos;
$nested =~ s/\/\*.*?\*\///gos;
return 0;
}
/* Fix endianness in ELF header */
- hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
- hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
- hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
- hdr->e_machine = TO_NATIVE(hdr->e_machine);
- hdr->e_type = TO_NATIVE(hdr->e_type);
+ hdr->e_type = TO_NATIVE(hdr->e_type);
+ hdr->e_machine = TO_NATIVE(hdr->e_machine);
+ hdr->e_version = TO_NATIVE(hdr->e_version);
+ hdr->e_entry = TO_NATIVE(hdr->e_entry);
+ hdr->e_phoff = TO_NATIVE(hdr->e_phoff);
+ hdr->e_shoff = TO_NATIVE(hdr->e_shoff);
+ hdr->e_flags = TO_NATIVE(hdr->e_flags);
+ hdr->e_ehsize = TO_NATIVE(hdr->e_ehsize);
+ hdr->e_phentsize = TO_NATIVE(hdr->e_phentsize);
+ hdr->e_phnum = TO_NATIVE(hdr->e_phnum);
+ hdr->e_shentsize = TO_NATIVE(hdr->e_shentsize);
+ hdr->e_shnum = TO_NATIVE(hdr->e_shnum);
+ hdr->e_shstrndx = TO_NATIVE(hdr->e_shstrndx);
sechdrs = (void *)hdr + hdr->e_shoff;
info->sechdrs = sechdrs;
/* Fix endianness in section headers */
for (i = 0; i < hdr->e_shnum; i++) {
- sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
- sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
- sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
- sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
- sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
- sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info);
- sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr);
+ sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name);
+ sechdrs[i].sh_type = TO_NATIVE(sechdrs[i].sh_type);
+ sechdrs[i].sh_flags = TO_NATIVE(sechdrs[i].sh_flags);
+ sechdrs[i].sh_addr = TO_NATIVE(sechdrs[i].sh_addr);
+ sechdrs[i].sh_offset = TO_NATIVE(sechdrs[i].sh_offset);
+ sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size);
+ sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link);
+ sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info);
+ sechdrs[i].sh_addralign = TO_NATIVE(sechdrs[i].sh_addralign);
+ sechdrs[i].sh_entsize = TO_NATIVE(sechdrs[i].sh_entsize);
}
/* Find symbol table. */
for (i = 1; i < hdr->e_shnum; i++) {
/* sections that we do not want to do full section mismatch check on */
static const char *section_white_list[] =
- { ".debug*", ".stab*", ".note*", ".got*", ".toc*", NULL };
+{
+ ".comment*",
+ ".debug*",
+ ".mdebug*", /* alpha, score, mips etc. */
+ ".pdr", /* alpha, score, mips etc. */
+ ".stab*",
+ ".note*",
+ ".got*",
+ ".toc*",
+ NULL
+};
/*
- * Is this section one we do not want to check?
- * This is often debug sections.
- * If we are going to check this section then
- * test if section name ends with a dot and a number.
- * This is used to find sections where the linker have
- * appended a dot-number to make the name unique.
+ * This is used to find sections missing the SHF_ALLOC flag.
* The cause of this is often a section specified in assembler
- * without "ax" / "aw" and the same section used in .c
- * code where gcc add these.
+ * without "ax" / "aw".
*/
-static int check_section(const char *modname, const char *sec)
-{
- const char *e = sec + strlen(sec) - 1;
- if (match(sec, section_white_list))
- return 1;
-
- if (*e && isdigit(*e)) {
- /* consume all digits */
- while (*e && e != sec && isdigit(*e))
- e--;
- if (*e == '.' && !strstr(sec, ".linkonce")) {
- warn("%s (%s): unexpected section name.\n"
- "The (.[number]+) following section name are "
- "ld generated and not expected.\n"
- "Did you forget to use \"ax\"/\"aw\" "
- "in a .S file?\n"
- "Note that for example <linux/init.h> contains\n"
- "section definitions for use in .S files.\n\n",
- modname, sec);
- }
+static void check_section(const char *modname, struct elf_info *elf,
+ Elf_Shdr *sechdr)
+{
+ const char *sec = sech_name(elf, sechdr);
+
+ if (sechdr->sh_type == SHT_PROGBITS &&
+ !(sechdr->sh_flags & SHF_ALLOC) &&
+ !match(sec, section_white_list)) {
+ warn("%s (%s): unexpected non-allocatable section.\n"
+ "Did you forget to use \"ax\"/\"aw\" in a .S file?\n"
+ "Note that for example <linux/init.h> contains\n"
+ "section definitions for use in .S files.\n\n",
+ modname, sec);
}
- return 0;
}
* *probe_one, *_console, *_timer
*
* Pattern 3:
- * Whitelist all refereces from .text.head to .init.data
- * Whitelist all refereces from .text.head to .init.text
+ * Whitelist all references from .head.text to any init section
*
* Pattern 4:
* Some symbols belong to init section but still it is ok to reference
fromsec = sech_name(elf, sechdr);
fromsec += strlen(".rela");
/* if from section (name) is know good then skip it */
- if (check_section(modname, fromsec))
+ if (match(fromsec, section_white_list))
return;
for (rela = start; rela < stop; rela++) {
fromsec = sech_name(elf, sechdr);
fromsec += strlen(".rel");
/* if from section (name) is know good then skip it */
- if (check_section(modname, fromsec))
+ if (match(fromsec, section_white_list))
return;
for (rel = start; rel < stop; rel++) {
/* Walk through all sections */
for (i = 0; i < elf->hdr->e_shnum; i++) {
+ check_section(modname, elf, &elf->sechdrs[i]);
/* We want to process only relocation sections and not .init */
if (sechdrs[i].sh_type == SHT_RELA)
section_rela(modname, elf, &elf->sechdrs[i]);
if (!mod->skip)
add_marker(mod, marker, fmt);
}
+ release_file(file, size);
return;
fail:
fatal("parse error in markers list file\n");
# Check for git and a git repo.
if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then
- # Do we have an untagged version?
- if git name-rev --tags HEAD | grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then
- if tag=`git describe 2>/dev/null`; then
- echo $tag | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
- else
- printf '%s%s' -g $head
- fi
+ # Do we have an untagged tag?
+ if atag=`git describe 2>/dev/null`; then
+ echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
+ # add -g${head}, if there is no usable tag
+ else
+ printf '%s%s' -g $head
fi
# Is this git on svn?
;;
"tags")
+ rm -f tags
xtags ctags
;;
"TAGS")
+ rm -f TAGS
xtags etags
;;
esac
struct fown_struct *fown, int signum)
{
struct file *file;
- u32 sid = current_sid();
+ u32 sid = task_sid(tsk);
u32 perm;
struct file_security_struct *fsec;
new_hw_ptr = hw_base + pos;
}
}
+ /* Skip the jiffies check for hardwares with BATCH flag.
+ * Such hardware usually just increases the position at each IRQ,
+ * thus it can't give any strange position.
+ */
+ if (runtime->hw.info & SNDRV_PCM_INFO_BATCH)
+ goto no_jiffies_check;
hdelta = new_hw_ptr - old_hw_ptr;
jdelta = jiffies - runtime->hw_ptr_jiffies;
if (((hdelta * HZ) / runtime->rate) > jdelta + HZ/100) {
hw_base -= hw_base % runtime->buffer_size;
delta = 0;
}
+ no_jiffies_check:
if (delta > runtime->period_size + runtime->period_size / 2) {
hw_ptr_error(substream,
"Lost interrupts? "
static struct snd_pcm_hardware snd_msnd_playback = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_8000_48000,
.rate_min = 8000,
static struct snd_pcm_hardware snd_msnd_capture = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE,
.rates = SNDRV_PCM_RATE_8000_48000,
.rate_min = 8000,
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = 0, /* set at runtime */
.channels_min = 2,
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8,
.rates = SNDRV_PCM_RATE_KNOT,
.rate_min = ANALOG_CLOCK / CLOCK_DIV_MAX,
.rates = SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_64000 |
SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000,
.rate_min = 32000,
.rates = SNDRV_PCM_RATE_32000 |
SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_64000 |
SNDRV_PCM_RATE_88200 |
SNDRV_PCM_RATE_96000,
.rate_min = 32000,
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED),
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BATCH),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
{
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED),
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BATCH),
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.rates = (SNDRV_PCM_RATE_44100 |
SNDRV_PCM_RATE_48000),
static struct snd_pcm_hardware pdacf_pcm_capture_hw = {
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH),
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE,
/* PCM hardware DMA capabilities - platform specific */
static const struct snd_pcm_hardware au1xpsc_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED,
+ SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH,
.formats = AU1XPSC_PCM_FMTS,
.period_bytes_min = AU1XPSC_PERIOD_MIN_BYTES,
.period_bytes_max = 4096 * 1024 - 1,
*/
static DECLARE_TLV_DB_SCALE(output_tvl, -1200, 600, 1);
+/*
+ * Gain control for earpiece amplifier
+ * 0 dB to 12 dB in 6 dB steps (mute instead of -6)
+ */
+static DECLARE_TLV_DB_SCALE(output_ear_tvl, -600, 600, 1);
+
/*
* Capture gain after the ADCs
* from 0 dB to 31 dB in 1 dB steps
4, 3, 0, output_tvl),
SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
- TWL4030_REG_EAR_CTL, 4, 3, 0, output_tvl),
+ TWL4030_REG_EAR_CTL, 4, 3, 0, output_ear_tvl),
/* Common capture gain controls */
SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume",
* required for LRC in master mode. The DACs or ADCs need a
* valid audio path i.e. pin -> ADC or DAC -> pin before
* the LRC will be enabled in master mode. */
- if (!master && cmd != SNDRV_PCM_TRIGGER_START)
+ if (!master || cmd != SNDRV_PCM_TRIGGER_START)
return 0;
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
static const struct snd_pcm_hardware psc_i2s_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |
SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE,
.rate_min = 8000,
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH),
.formats = DMABRG_FMTS,
.rates = DMABRG_RATES,
.rate_min = 8000,
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH,
.formats = SNDRV_PCM_FMTBIT_MU_LAW |
SNDRV_PCM_FMTBIT_A_LAW |
SNDRV_PCM_FMTBIT_U8 |
{
.info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
- SNDRV_PCM_INFO_MMAP_VALID),
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_BATCH),
.formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_3LE,
.rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
.rate_min = 44100,