+++ /dev/null
-#ifndef __UM_SMPLOCK_H
-#define __UM_SMPLOCK_H
-
-#include "asm/arch/smplock.h"
-
-#endif
+++ /dev/null
-/*
- * KLOG Generic Logging facility built upon the relayfs infrastructure
- *
- * Authors: Hubertus Frankeh (frankeh@us.ibm.com)
- * Tom Zanussi (zanussi@us.ibm.com)
- *
- * Please direct all questions/comments to zanussi@us.ibm.com
- *
- * Copyright (C) 2003, IBM Corp
- *
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#ifndef _LINUX_KLOG_H
-#define _LINUX_KLOG_H
-
-extern int klog(const char *fmt, ...);
-extern int klog_raw(const char *buf,int len);
-
-#endif /* _LINUX_KLOG_H */
+++ /dev/null
-/*
- * linux/include/linux/relayfs_fs.h
- *
- * Copyright (C) 2002, 2003 - Tom Zanussi (zanussi@us.ibm.com), IBM Corp
- * Copyright (C) 1999, 2000, 2001, 2002 - Karim Yaghmour (karim@opersys.com)
- *
- * RelayFS definitions and declarations
- *
- * Please see Documentation/filesystems/relayfs.txt for more info.
- */
-
-#ifndef _LINUX_RELAYFS_FS_H
-#define _LINUX_RELAYFS_FS_H
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/wait.h>
-#include <linux/list.h>
-#include <linux/fs.h>
-
-/*
- * Tracks changes to rchan struct
- */
-#define RELAYFS_CHANNEL_VERSION 1
-
-/*
- * Maximum number of simultaneously open channels
- */
-#define RELAY_MAX_CHANNELS 256
-
-/*
- * Relay properties
- */
-#define RELAY_MIN_BUFS 2
-#define RELAY_MIN_BUFSIZE 4096
-#define RELAY_MAX_BUFS 256
-#define RELAY_MAX_BUF_SIZE 0x1000000
-#define RELAY_MAX_TOTAL_BUF_SIZE 0x8000000
-
-/*
- * Lockless scheme utility macros
- */
-#define RELAY_MAX_BUFNO(bufno_bits) (1UL << (bufno_bits))
-#define RELAY_BUF_SIZE(offset_bits) (1UL << (offset_bits))
-#define RELAY_BUF_OFFSET_MASK(offset_bits) (RELAY_BUF_SIZE(offset_bits) - 1)
-#define RELAY_BUFNO_GET(index, offset_bits) ((index) >> (offset_bits))
-#define RELAY_BUF_OFFSET_GET(index, mask) ((index) & (mask))
-#define RELAY_BUF_OFFSET_CLEAR(index, mask) ((index) & ~(mask))
-
-/*
- * Flags returned by relay_reserve()
- */
-#define RELAY_BUFFER_SWITCH_NONE 0x0
-#define RELAY_WRITE_DISCARD_NONE 0x0
-#define RELAY_BUFFER_SWITCH 0x1
-#define RELAY_WRITE_DISCARD 0x2
-#define RELAY_WRITE_TOO_LONG 0x4
-
-/*
- * Relay attribute flags
- */
-#define RELAY_DELIVERY_BULK 0x1
-#define RELAY_DELIVERY_PACKET 0x2
-#define RELAY_SCHEME_LOCKLESS 0x4
-#define RELAY_SCHEME_LOCKING 0x8
-#define RELAY_SCHEME_ANY 0xC
-#define RELAY_TIMESTAMP_TSC 0x10
-#define RELAY_TIMESTAMP_GETTIMEOFDAY 0x20
-#define RELAY_TIMESTAMP_ANY 0x30
-#define RELAY_USAGE_SMP 0x40
-#define RELAY_USAGE_GLOBAL 0x80
-#define RELAY_MODE_CONTINUOUS 0x100
-#define RELAY_MODE_NO_OVERWRITE 0x200
-
-/*
- * Flags for needs_resize() callback
- */
-#define RELAY_RESIZE_NONE 0x0
-#define RELAY_RESIZE_EXPAND 0x1
-#define RELAY_RESIZE_SHRINK 0x2
-#define RELAY_RESIZE_REPLACE 0x4
-#define RELAY_RESIZE_REPLACED 0x8
-
-/*
- * Values for fileop_notify() callback
- */
-enum relay_fileop
-{
- RELAY_FILE_OPEN,
- RELAY_FILE_CLOSE,
- RELAY_FILE_MAP,
- RELAY_FILE_UNMAP
-};
-
-/*
- * Data structure returned by relay_info()
- */
-struct rchan_info
-{
- u32 flags; /* relay attribute flags for channel */
- u32 buf_size; /* channel's sub-buffer size */
- char *buf_addr; /* address of channel start */
- u32 alloc_size; /* total buffer size actually allocated */
- u32 n_bufs; /* number of sub-buffers in channel */
- u32 cur_idx; /* current write index into channel */
- u32 bufs_produced; /* current count of sub-buffers produced */
- u32 bufs_consumed; /* current count of sub-buffers consumed */
- u32 buf_id; /* buf_id of current sub-buffer */
- int buffer_complete[RELAY_MAX_BUFS]; /* boolean per sub-buffer */
- int unused_bytes[RELAY_MAX_BUFS]; /* count per sub-buffer */
-};
-
-/*
- * Relay channel client callbacks
- */
-struct rchan_callbacks
-{
- /*
- * buffer_start - called at the beginning of a new sub-buffer
- * @rchan_id: the channel id
- * @current_write_pos: position in sub-buffer client should write to
- * @buffer_id: the id of the new sub-buffer
- * @start_time: the timestamp associated with the start of sub-buffer
- * @start_tsc: the TSC associated with the timestamp, if using_tsc
- * @using_tsc: boolean, indicates whether start_tsc is valid
- *
- * Return value should be the number of bytes written by the client.
- *
- * See Documentation/filesystems/relayfs.txt for details.
- */
- int (*buffer_start) (int rchan_id,
- char *current_write_pos,
- u32 buffer_id,
- struct timeval start_time,
- u32 start_tsc,
- int using_tsc);
-
- /*
- * buffer_end - called at the end of a sub-buffer
- * @rchan_id: the channel id
- * @current_write_pos: position in sub-buffer of end of data
- * @end_of_buffer: the position of the end of the sub-buffer
- * @end_time: the timestamp associated with the end of the sub-buffer
- * @end_tsc: the TSC associated with the end_time, if using_tsc
- * @using_tsc: boolean, indicates whether end_tsc is valid
- *
- * Return value should be the number of bytes written by the client.
- *
- * See Documentation/filesystems/relayfs.txt for details.
- */
- int (*buffer_end) (int rchan_id,
- char *current_write_pos,
- char *end_of_buffer,
- struct timeval end_time,
- u32 end_tsc,
- int using_tsc);
-
- /*
- * deliver - called when data is ready for the client
- * @rchan_id: the channel id
- * @from: the start of the delivered data
- * @len: the length of the delivered data
- *
- * See Documentation/filesystems/relayfs.txt for details.
- */
- void (*deliver) (int rchan_id, char *from, u32 len);
-
- /*
- * user_deliver - called when data has been written from userspace
- * @rchan_id: the channel id
- * @from: the start of the delivered data
- * @len: the length of the delivered data
- *
- * See Documentation/filesystems/relayfs.txt for details.
- */
- void (*user_deliver) (int rchan_id, char *from, u32 len);
-
- /*
- * needs_resize - called when a resizing event occurs
- * @rchan_id: the channel id
- * @resize_type: the type of resizing event
- * @suggested_buf_size: the suggested new sub-buffer size
- * @suggested_buf_size: the suggested new number of sub-buffers
- *
- * See Documentation/filesystems/relayfs.txt for details.
- */
- void (*needs_resize)(int rchan_id,
- int resize_type,
- u32 suggested_buf_size,
- u32 suggested_n_bufs);
-
- /*
- * fileop_notify - called on open/close/mmap/munmap of a relayfs file
- * @rchan_id: the channel id
- * @filp: relayfs file pointer
- * @fileop: which file operation is in progress
- *
- * The return value can direct the outcome of the operation.
- *
- * See Documentation/filesystems/relayfs.txt for details.
- */
- int (*fileop_notify)(int rchan_id,
- struct file *filp,
- enum relay_fileop fileop);
-
- /*
- * ioctl - called in ioctl context from userspace
- * @rchan_id: the channel id
- * @cmd: ioctl cmd
- * @arg: ioctl cmd arg
- *
- * The return value is returned as the value from the ioctl call.
- *
- * See Documentation/filesystems/relayfs.txt for details.
- */
- int (*ioctl) (int rchan_id, unsigned int cmd, unsigned long arg);
-};
-
-/*
- * Lockless scheme-specific data
- */
-struct lockless_rchan
-{
- u8 bufno_bits; /* # bits used for sub-buffer id */
- u8 offset_bits; /* # bits used for offset within sub-buffer */
- u32 index; /* current index = sub-buffer id and offset */
- u32 offset_mask; /* used to obtain offset portion of index */
- u32 index_mask; /* used to mask off unused bits index */
- atomic_t fill_count[RELAY_MAX_BUFS]; /* fill count per sub-buffer */
-};
-
-/*
- * Locking scheme-specific data
- */
-struct locking_rchan
-{
- char *write_buf; /* start of write sub-buffer */
- char *write_buf_end; /* end of write sub-buffer */
- char *current_write_pos; /* current write pointer */
- char *write_limit; /* takes reserves into account */
- char *in_progress_event_pos; /* used for interrupted writes */
- u16 in_progress_event_size; /* used for interrupted writes */
- char *interrupted_pos; /* used for interrupted writes */
- u16 interrupting_size; /* used for interrupted writes */
- spinlock_t lock; /* channel lock for locking scheme */
-};
-
-struct relay_ops;
-
-/*
- * Offset resizing data structure
- */
-struct resize_offset
-{
- u32 ge;
- u32 le;
- int delta;
-};
-
-/*
- * Relay channel data structure
- */
-struct rchan
-{
- u32 version; /* the version of this struct */
- char *buf; /* the channel buffer */
- union
- {
- struct lockless_rchan lockless;
- struct locking_rchan locking;
- } scheme; /* scheme-specific channel data */
-
- int id; /* the channel id */
- struct rchan_callbacks *callbacks; /* client callbacks */
- u32 flags; /* relay channel attributes */
- u32 buf_id; /* current sub-buffer id */
- u32 buf_idx; /* current sub-buffer index */
-
- atomic_t mapped; /* map count */
-
- atomic_t suspended; /* channel suspended i.e full? */
- int half_switch; /* used internally for suspend */
-
- struct timeval buf_start_time; /* current sub-buffer start time */
- u32 buf_start_tsc; /* current sub-buffer start TSC */
-
- u32 buf_size; /* sub-buffer size */
- u32 alloc_size; /* total buffer size allocated */
- u32 n_bufs; /* number of sub-buffers */
-
- u32 bufs_produced; /* count of sub-buffers produced */
- u32 bufs_consumed; /* count of sub-buffers consumed */
- u32 bytes_consumed; /* bytes consumed in cur sub-buffer */
-
- int initialized; /* first buffer initialized? */
- int finalized; /* channel finalized? */
-
- u32 start_reserve; /* reserve at start of sub-buffers */
- u32 end_reserve; /* reserve at end of sub-buffers */
- u32 rchan_start_reserve; /* additional reserve sub-buffer 0 */
-
- struct dentry *dentry; /* channel file dentry */
-
- wait_queue_head_t read_wait; /* VFS read wait queue */
- wait_queue_head_t write_wait; /* VFS write wait queue */
- struct work_struct wake_readers; /* reader wake-up work struct */
- struct work_struct wake_writers; /* reader wake-up work struct */
- atomic_t refcount; /* channel refcount */
-
- struct relay_ops *relay_ops; /* scheme-specific channel ops */
-
- int unused_bytes[RELAY_MAX_BUFS]; /* unused count per sub-buffer */
-
- struct semaphore resize_sem; /* serializes alloc/repace */
- struct work_struct work; /* resize allocation work struct */
-
- struct list_head open_readers; /* open readers for this channel */
- rwlock_t open_readers_lock; /* protection for open_readers list */
-
- char *init_buf; /* init channel buffer, if non-NULL */
-
- u32 resize_min; /* minimum resized total buffer size */
- u32 resize_max; /* maximum resized total buffer size */
- char *resize_buf; /* for autosize alloc/free */
- u32 resize_buf_size; /* resized sub-buffer size */
- u32 resize_n_bufs; /* resized number of sub-buffers */
- u32 resize_alloc_size; /* resized actual total size */
- int resizing; /* is resizing in progress? */
- int resize_err; /* resizing err code */
- int resize_failures; /* number of resize failures */
- int replace_buffer; /* is the alloced buffer ready? */
- struct resize_offset resize_offset; /* offset change */
- struct timer_list shrink_timer; /* timer used for shrinking */
- int resize_order; /* size of last resize */
- u32 expand_buf_id; /* subbuf id expand will occur at */
-
- struct page **buf_page_array; /* array of current buffer pages */
- int buf_page_count; /* number of current buffer pages */
- struct page **expand_page_array;/* new pages to be inserted */
- int expand_page_count; /* number of new pages */
- struct page **shrink_page_array;/* old pages to be freed */
- int shrink_page_count; /* number of old pages */
- struct page **resize_page_array;/* will become current pages */
- int resize_page_count; /* number of resize pages */
- struct page **old_buf_page_array; /* hold for freeing */
-} ____cacheline_aligned;
-
-/*
- * Relay channel reader struct
- */
-struct rchan_reader
-{
- struct list_head list; /* for list inclusion */
- struct rchan *rchan; /* the channel we're reading from */
- int auto_consume; /* does this reader auto-consume? */
- u32 bufs_consumed; /* buffers this reader has consumed */
- u32 bytes_consumed; /* bytes consumed in cur sub-buffer */
- int offset_changed; /* have channel offsets changed? */
- int vfs_reader; /* are we a VFS reader? */
- int map_reader; /* are we an mmap reader? */
-
- union
- {
- struct file *file;
- u32 f_pos;
- } pos; /* current read offset */
-};
-
-/*
- * These help make union member access less tedious
- */
-#define channel_buffer(rchan) ((rchan)->buf)
-#define idx(rchan) ((rchan)->scheme.lockless.index)
-#define bufno_bits(rchan) ((rchan)->scheme.lockless.bufno_bits)
-#define offset_bits(rchan) ((rchan)->scheme.lockless.offset_bits)
-#define offset_mask(rchan) ((rchan)->scheme.lockless.offset_mask)
-#define idx_mask(rchan) ((rchan)->scheme.lockless.index_mask)
-#define bulk_delivery(rchan) (((rchan)->flags & RELAY_DELIVERY_BULK) ? 1 : 0)
-#define packet_delivery(rchan) (((rchan)->flags & RELAY_DELIVERY_PACKET) ? 1 : 0)
-#define using_lockless(rchan) (((rchan)->flags & RELAY_SCHEME_LOCKLESS) ? 1 : 0)
-#define using_locking(rchan) (((rchan)->flags & RELAY_SCHEME_LOCKING) ? 1 : 0)
-#define using_tsc(rchan) (((rchan)->flags & RELAY_TIMESTAMP_TSC) ? 1 : 0)
-#define using_gettimeofday(rchan) (((rchan)->flags & RELAY_TIMESTAMP_GETTIMEOFDAY) ? 1 : 0)
-#define usage_smp(rchan) (((rchan)->flags & RELAY_USAGE_SMP) ? 1 : 0)
-#define usage_global(rchan) (((rchan)->flags & RELAY_USAGE_GLOBAL) ? 1 : 0)
-#define mode_continuous(rchan) (((rchan)->flags & RELAY_MODE_CONTINUOUS) ? 1 : 0)
-#define fill_count(rchan, i) ((rchan)->scheme.lockless.fill_count[(i)])
-#define write_buf(rchan) ((rchan)->scheme.locking.write_buf)
-#define read_buf(rchan) ((rchan)->scheme.locking.read_buf)
-#define write_buf_end(rchan) ((rchan)->scheme.locking.write_buf_end)
-#define read_buf_end(rchan) ((rchan)->scheme.locking.read_buf_end)
-#define cur_write_pos(rchan) ((rchan)->scheme.locking.current_write_pos)
-#define read_limit(rchan) ((rchan)->scheme.locking.read_limit)
-#define write_limit(rchan) ((rchan)->scheme.locking.write_limit)
-#define in_progress_event_pos(rchan) ((rchan)->scheme.locking.in_progress_event_pos)
-#define in_progress_event_size(rchan) ((rchan)->scheme.locking.in_progress_event_size)
-#define interrupted_pos(rchan) ((rchan)->scheme.locking.interrupted_pos)
-#define interrupting_size(rchan) ((rchan)->scheme.locking.interrupting_size)
-#define channel_lock(rchan) ((rchan)->scheme.locking.lock)
-
-
-/**
- * calc_time_delta - utility function for time delta calculation
- * @now: current time
- * @start: start time
- *
- * Returns the time delta produced by subtracting start time from now.
- */
-static inline u32
-calc_time_delta(struct timeval *now,
- struct timeval *start)
-{
- return (now->tv_sec - start->tv_sec) * 1000000
- + (now->tv_usec - start->tv_usec);
-}
-
-/**
- * recalc_time_delta - utility function for time delta recalculation
- * @now: current time
- * @new_delta: the new time delta calculated
- * @cpu: the associated CPU id
- */
-static inline void
-recalc_time_delta(struct timeval *now,
- u32 *new_delta,
- struct rchan *rchan)
-{
- if (using_tsc(rchan) == 0)
- *new_delta = calc_time_delta(now, &rchan->buf_start_time);
-}
-
-/**
- * have_cmpxchg - does this architecture have a cmpxchg?
- *
- * Returns 1 if this architecture has a cmpxchg useable by
- * the lockless scheme, 0 otherwise.
- */
-static inline int
-have_cmpxchg(void)
-{
-#if defined(__HAVE_ARCH_CMPXCHG)
- return 1;
-#else
- return 0;
-#endif
-}
-
-/**
- * relay_write_direct - write data directly into destination buffer
- */
-#define relay_write_direct(DEST, SRC, SIZE) \
-do\
-{\
- memcpy(DEST, SRC, SIZE);\
- DEST += SIZE;\
-} while (0);
-
-/**
- * relay_lock_channel - lock the relay channel if applicable
- *
- * This macro only affects the locking scheme. If the locking scheme
- * is in use and the channel usage is SMP, does a local_irq_save. If the
- * locking sheme is in use and the channel usage is GLOBAL, uses
- * spin_lock_irqsave. FLAGS is initialized to 0 since we know that
- * it is being initialized prior to use and we avoid the compiler warning.
- */
-#define relay_lock_channel(RCHAN, FLAGS) \
-do\
-{\
- FLAGS = 0;\
- if (using_locking(RCHAN)) {\
- if (usage_smp(RCHAN)) {\
- local_irq_save(FLAGS); \
- } else {\
- spin_lock_irqsave(&(RCHAN)->scheme.locking.lock, FLAGS); \
- }\
- }\
-} while (0);
-
-/**
- * relay_unlock_channel - unlock the relay channel if applicable
- *
- * This macro only affects the locking scheme. See relay_lock_channel.
- */
-#define relay_unlock_channel(RCHAN, FLAGS) \
-do\
-{\
- if (using_locking(RCHAN)) {\
- if (usage_smp(RCHAN)) {\
- local_irq_restore(FLAGS); \
- } else {\
- spin_unlock_irqrestore(&(RCHAN)->scheme.locking.lock, FLAGS); \
- }\
- }\
-} while (0);
-
-/*
- * Define cmpxchg if we don't have it
- */
-#ifndef __HAVE_ARCH_CMPXCHG
-#define cmpxchg(p,o,n) 0
-#endif
-
-/*
- * High-level relayfs kernel API, fs/relayfs/relay.c
- */
-extern int
-relay_open(const char *chanpath,
- int bufsize,
- int nbufs,
- u32 flags,
- struct rchan_callbacks *channel_callbacks,
- u32 start_reserve,
- u32 end_reserve,
- u32 rchan_start_reserve,
- u32 resize_min,
- u32 resize_max,
- int mode,
- char *init_buf,
- u32 init_buf_size);
-
-extern int
-relay_close(int rchan_id);
-
-extern int
-relay_write(int rchan_id,
- const void *data_ptr,
- size_t count,
- int td_offset,
- void **wrote_pos);
-
-extern ssize_t
-relay_read(struct rchan_reader *reader,
- char *buf,
- size_t count,
- int wait,
- u32 *actual_read_offset);
-
-extern int
-relay_discard_init_buf(int rchan_id);
-
-extern struct rchan_reader *
-add_rchan_reader(int rchan_id, int autoconsume);
-
-extern int
-remove_rchan_reader(struct rchan_reader *reader);
-
-extern struct rchan_reader *
-add_map_reader(int rchan_id);
-
-extern int
-remove_map_reader(struct rchan_reader *reader);
-
-extern int
-relay_info(int rchan_id, struct rchan_info *rchan_info);
-
-extern void
-relay_buffers_consumed(struct rchan_reader *reader, u32 buffers_consumed);
-
-extern void
-relay_bytes_consumed(struct rchan_reader *reader, u32 bytes_consumed, u32 read_offset);
-
-extern ssize_t
-relay_bytes_avail(struct rchan_reader *reader);
-
-extern int
-relay_realloc_buffer(int rchan_id, u32 new_nbufs, int in_background);
-
-extern int
-relay_replace_buffer(int rchan_id);
-
-extern int
-rchan_empty(struct rchan_reader *reader);
-
-extern int
-rchan_full(struct rchan_reader *reader);
-
-extern void
-update_readers_consumed(struct rchan *rchan, u32 bufs_consumed, u32 bytes_consumed);
-
-extern int
-__relay_mmap_buffer(struct rchan *rchan, struct vm_area_struct *vma);
-
-extern struct rchan_reader *
-__add_rchan_reader(struct rchan *rchan, struct file *filp, int auto_consume, int map_reader);
-
-extern void
-__remove_rchan_reader(struct rchan_reader *reader);
-
-/*
- * Low-level relayfs kernel API, fs/relayfs/relay.c
- */
-extern struct rchan *
-rchan_get(int rchan_id);
-
-extern void
-rchan_put(struct rchan *rchan);
-
-extern char *
-relay_reserve(struct rchan *rchan,
- u32 data_len,
- struct timeval *time_stamp,
- u32 *time_delta,
- int *errcode,
- int *interrupting);
-
-extern void
-relay_commit(struct rchan *rchan,
- char *from,
- u32 len,
- int reserve_code,
- int interrupting);
-
-extern u32
-relay_get_offset(struct rchan *rchan, u32 *max_offset);
-
-extern int
-relay_reset(int rchan_id);
-
-/*
- * VFS functions, fs/relayfs/inode.c
- */
-extern int
-relayfs_create_dir(const char *name,
- struct dentry *parent,
- struct dentry **dentry);
-
-extern int
-relayfs_create_file(const char * name,
- struct dentry *parent,
- struct dentry **dentry,
- void * data,
- int mode);
-
-extern int
-relayfs_remove_file(struct dentry *dentry);
-
-extern int
-reset_index(struct rchan *rchan, u32 old_index);
-
-
-/*
- * klog functions, fs/relayfs/klog.c
- */
-extern int
-create_klog_channel(void);
-
-extern int
-remove_klog_channel(void);
-
-/*
- * Scheme-specific channel ops
- */
-struct relay_ops
-{
- char * (*reserve) (struct rchan *rchan,
- u32 slot_len,
- struct timeval *time_stamp,
- u32 *tsc,
- int * errcode,
- int * interrupting);
-
- void (*commit) (struct rchan *rchan,
- char *from,
- u32 len,
- int deliver,
- int interrupting);
-
- u32 (*get_offset) (struct rchan *rchan,
- u32 *max_offset);
-
- void (*resume) (struct rchan *rchan);
- void (*finalize) (struct rchan *rchan);
- void (*reset) (struct rchan *rchan,
- int init);
- int (*reset_index) (struct rchan *rchan,
- u32 old_index);
-};
-
-#endif /* _LINUX_RELAYFS_FS_H */
-
-
-
-
-
+++ /dev/null
-#ifndef __SOUND_SNDMAGIC_H
-#define __SOUND_SNDMAGIC_H
-
-/*
- * Magic allocation, deallocation, check
- * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
- *
- *
- * 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
- *
- */
-
-
-#ifdef CONFIG_SND_DEBUG_MEMORY
-
-void *_snd_magic_kcalloc(unsigned long magic, size_t size, int flags);
-void *_snd_magic_kmalloc(unsigned long magic, size_t size, int flags);
-
-/**
- * snd_magic_kmalloc - allocate a record with a magic-prefix
- * @type: the type to allocate a record (like xxx_t)
- * @extra: the extra size to allocate in bytes
- * @flags: the allocation condition (GFP_XXX)
- *
- * Allocates a record of the given type with the extra space and
- * returns its pointer. The allocated record has a secret magic-key
- * to be checked via snd_magic_cast() for safe casts.
- *
- * The allocated pointer must be released via snd_magic_kfree().
- *
- * The "struct xxx" style cannot be used as the type argument
- * because the magic-key constant is generated from the type-name
- * string.
- */
-#define snd_magic_kmalloc(type, extra, flags) \
- (type *) _snd_magic_kmalloc(type##_magic, sizeof(type) + extra, flags)
-/**
- * snd_magic_kcalloc - allocate a record with a magic-prefix and initialize
- * @type: the type to allocate a record (like xxx_t)
- * @extra: the extra size to allocate in bytes
- * @flags: the allocation condition (GFP_XXX)
- *
- * Works like snd_magic_kmalloc() but this clears the area with zero
- * automatically.
- */
-#define snd_magic_kcalloc(type, extra, flags) \
- (type *) _snd_magic_kcalloc(type##_magic, sizeof(type) + extra, flags)
-
-/**
- * snd_magic_kfree - release the allocated area
- * @ptr: the pointer allocated via snd_magic_kmalloc() or snd_magic_kcalloc()
- *
- * Releases the memory area allocated via snd_magic_kmalloc() or
- * snd_magic_kcalloc() function.
- */
-void snd_magic_kfree(void *ptr);
-
-static inline unsigned long _snd_magic_value(void *obj)
-{
- return obj == NULL ? (unsigned long)-1 : *(((unsigned long *)obj) - 1);
-}
-
-static inline int _snd_magic_bad(void *obj, unsigned long magic)
-{
- return _snd_magic_value(obj) != magic;
-}
-
-#define snd_magic_cast1(t, expr, cmd) snd_magic_cast(t, expr, cmd)
-
-/**
- * snd_magic_cast - check and cast the magic-allocated pointer
- * @type: the type of record to cast
- * @ptr: the magic-allocated pointer
- * @action...: the action to do if failed
- *
- * This macro provides a safe cast for the given type, which was
- * allocated via snd_magic_kmalloc() or snd_magic_kcallc().
- * If the pointer is invalid, i.e. the cast-type doesn't match,
- * the action arguments are called with a debug message.
- */
-#define snd_magic_cast(type, ptr, action...) \
- (type *) ({\
- void *__ptr = ptr;\
- unsigned long __magic = _snd_magic_value(__ptr);\
- if (__magic != type##_magic) {\
- snd_printk("bad MAGIC (0x%lx)\n", __magic);\
- action;\
- }\
- __ptr;\
-})
-
-#define snd_device_t_magic 0xa15a00ff
-#define snd_pcm_t_magic 0xa15a0101
-#define snd_pcm_file_t_magic 0xa15a0102
-#define snd_pcm_substream_t_magic 0xa15a0103
-#define snd_pcm_proc_private_t_magic 0xa15a0104
-#define snd_pcm_oss_file_t_magic 0xa15a0105
-#define snd_mixer_oss_t_magic 0xa15a0106
-// #define snd_pcm_sgbuf_t_magic 0xa15a0107
-
-#define snd_info_private_data_t_magic 0xa15a0201
-#define snd_info_entry_t_magic 0xa15a0202
-#define snd_ctl_file_t_magic 0xa15a0301
-#define snd_kcontrol_t_magic 0xa15a0302
-#define snd_rawmidi_t_magic 0xa15a0401
-#define snd_rawmidi_file_t_magic 0xa15a0402
-#define snd_virmidi_t_magic 0xa15a0403
-#define snd_virmidi_dev_t_magic 0xa15a0404
-#define snd_timer_t_magic 0xa15a0501
-#define snd_timer_user_t_magic 0xa15a0502
-#define snd_hwdep_t_magic 0xa15a0601
-#define snd_seq_device_t_magic 0xa15a0701
-
-#define es18xx_t_magic 0xa15a1101
-#define trident_t_magic 0xa15a1201
-#define es1938_t_magic 0xa15a1301
-#define cs46xx_t_magic 0xa15a1401
-#define cs46xx_pcm_t_magic 0xa15a1402
-#define ensoniq_t_magic 0xa15a1501
-#define sonicvibes_t_magic 0xa15a1601
-#define mpu401_t_magic 0xa15a1701
-#define fm801_t_magic 0xa15a1801
-#define ac97_t_magic 0xa15a1901
-#define ac97_bus_t_magic 0xa15a1902
-#define ak4531_t_magic 0xa15a1a01
-#define snd_uart16550_t_magic 0xa15a1b01
-#define emu10k1_t_magic 0xa15a1c01
-#define emu10k1_pcm_t_magic 0xa15a1c02
-#define emu10k1_midi_t_magic 0xa15a1c03
-#define snd_gus_card_t_magic 0xa15a1d01
-#define gus_pcm_private_t_magic 0xa15a1d02
-#define gus_proc_private_t_magic 0xa15a1d03
-#define tea6330t_t_magic 0xa15a1e01
-#define ad1848_t_magic 0xa15a1f01
-#define cs4231_t_magic 0xa15a2001
-#define es1688_t_magic 0xa15a2101
-#define opti93x_t_magic 0xa15a2201
-#define emu8000_t_magic 0xa15a2301
-#define emu8000_proc_private_t_magic 0xa15a2302
-#define snd_emux_t_magic 0xa15a2303
-#define snd_emux_port_t_magic 0xa15a2304
-#define sb_t_magic 0xa15a2401
-#define snd_sb_csp_t_magic 0xa15a2402
-#define snd_card_dummy_t_magic 0xa15a2501
-#define snd_card_dummy_pcm_t_magic 0xa15a2502
-#define opl3_t_magic 0xa15a2601
-#define opl4_t_magic 0xa15a2602
-#define snd_seq_dummy_port_t_magic 0xa15a2701
-#define ice1712_t_magic 0xa15a2801
-#define ad1816a_t_magic 0xa15a2901
-#define intel8x0_t_magic 0xa15a2a01
-#define es1968_t_magic 0xa15a2b01
-#define esschan_t_magic 0xa15a2b02
-#define via82xx_t_magic 0xa15a2c01
-#define pdplus_t_magic 0xa15a2d01
-#define cmipci_t_magic 0xa15a2e01
-#define ymfpci_t_magic 0xa15a2f01
-#define ymfpci_pcm_t_magic 0xa15a2f02
-#define cs4281_t_magic 0xa15a3001
-#define snd_i2c_bus_t_magic 0xa15a3101
-#define snd_i2c_device_t_magic 0xa15a3102
-#define cs8427_t_magic 0xa15a3111
-#define m3_t_magic 0xa15a3201
-#define m3_dma_t_magic 0xa15a3202
-#define nm256_t_magic 0xa15a3301
-#define nm256_dma_t_magic 0xa15a3302
-#define sam9407_t_magic 0xa15a3401
-#define pmac_t_magic 0xa15a3501
-#define ali_t_magic 0xa15a3601
-#define mtpav_t_magic 0xa15a3701
-#define mtpav_port_t_magic 0xa15a3702
-#define korg1212_t_magic 0xa15a3800
-#define opl3sa2_t_magic 0xa15a3900
-#define serialmidi_t_magic 0xa15a3a00
-#define sa11xx_uda1341_t_magic 0xa15a3b00
-#define uda1341_t_magic 0xa15a3c00
-#define l3_client_t_magic 0xa15a3d00
-#define snd_usb_audio_t_magic 0xa15a3e01
-#define usb_mixer_elem_info_t_magic 0xa15a3e02
-#define snd_usb_stream_t_magic 0xa15a3e03
-#define snd_usb_midi_t_magic 0xa15a3f01
-#define snd_usb_midi_out_endpoint_t_magic 0xa15a3f02
-#define snd_usb_midi_in_endpoint_t_magic 0xa15a3f03
-#define ak4117_t_magic 0xa15a4000
-#define psic_t_magic 0xa15a4100
-#define vx_core_t_magic 0xa15a4110
-#define vx_pipe_t_magic 0xa15a4112
-#define azf3328_t_magic 0xa15a4200
-#define snd_card_harmony_t_magic 0xa15a4300
-#define bt87x_t_magic 0xa15a4400
-#define pdacf_t_magic 0xa15a4500
-#define vortex_t_magic 0xa15a4601
-#define atiixp_t_magic 0xa15a4701
-#define amd7930_t_magic 0xa15a4801
-
-#else
-
-#define snd_magic_kcalloc(type, extra, flags) (type *) snd_kcalloc(sizeof(type) + extra, flags)
-#define snd_magic_kmalloc(type, extra, flags) (type *) kmalloc(sizeof(type) + extra, flags)
-#define snd_magic_cast(type, ptr, retval) (type *) ptr
-#define snd_magic_cast1(type, ptr, retval) snd_magic_cast(type, ptr, retval)
-#define snd_magic_kfree kfree
-
-#endif
-
-#endif /* __SOUND_SNDMAGIC_H */
+++ /dev/null
-/*
- * kernel/power/pmdisk.c - Suspend-to-disk implmentation
- *
- * This STD implementation is initially derived from swsusp (suspend-to-swap).
- * The original copyright on that was:
- *
- * Copyright (C) 1998-2001 Gabor Kuti <seasons@fornax.hu>
- * Copyright (C) 1998,2001,2002 Pavel Machek <pavel@suse.cz>
- *
- * The additional parts are:
- *
- * Copyright (C) 2003 Patrick Mochel
- * Copyright (C) 2003 Open Source Development Lab
- *
- * This file is released under the GPLv2.
- *
- * For more information, please see the text files in Documentation/power/
- *
- */
-
-#undef DEBUG
-
-#include <linux/mm.h>
-#include <linux/bio.h>
-#include <linux/suspend.h>
-#include <linux/version.h>
-#include <linux/reboot.h>
-#include <linux/device.h>
-#include <linux/swapops.h>
-#include <linux/bootmem.h>
-#include <linux/utsname.h>
-
-#include <asm/mmu_context.h>
-
-#include "power.h"
-
-
-extern asmlinkage int pmdisk_arch_suspend(int resume);
-
-#define __ADDRESS(x) ((unsigned long) phys_to_virt(x))
-#define ADDRESS(x) __ADDRESS((x) << PAGE_SHIFT)
-#define ADDRESS2(x) __ADDRESS(__pa(x)) /* Needed for x86-64 where some pages are in memory twice */
-
-/* References to section boundaries */
-extern char __nosave_begin, __nosave_end;
-
-extern int is_head_of_free_region(struct page *);
-
-/* Variables to be preserved over suspend */
-static int pagedir_order_check;
-static int nr_copy_pages_check;
-
-/* For resume= kernel option */
-static char resume_file[256] = CONFIG_PM_DISK_PARTITION;
-
-static dev_t resume_device;
-/* Local variables that should not be affected by save */
-unsigned int pmdisk_pages __nosavedata = 0;
-
-/* Suspend pagedir is allocated before final copy, therefore it
- must be freed after resume
-
- Warning: this is evil. There are actually two pagedirs at time of
- resume. One is "pagedir_save", which is empty frame allocated at
- time of suspend, that must be freed. Second is "pagedir_nosave",
- allocated at time of resume, that travels through memory not to
- collide with anything.
- */
-suspend_pagedir_t *pm_pagedir_nosave __nosavedata = NULL;
-static suspend_pagedir_t *pagedir_save;
-static int pagedir_order __nosavedata = 0;
-
-
-struct pmdisk_info {
- struct new_utsname uts;
- u32 version_code;
- unsigned long num_physpages;
- int cpus;
- unsigned long image_pages;
- unsigned long pagedir_pages;
- swp_entry_t pagedir[768];
-} __attribute__((aligned(PAGE_SIZE))) pmdisk_info;
-
-
-
-#define PMDISK_SIG "pmdisk-swap1"
-
-struct pmdisk_header {
- char reserved[PAGE_SIZE - 20 - sizeof(swp_entry_t)];
- swp_entry_t pmdisk_info;
- char orig_sig[10];
- char sig[10];
-} __attribute__((packed, aligned(PAGE_SIZE))) pmdisk_header;
-
-/*
- * XXX: We try to keep some more pages free so that I/O operations succeed
- * without paging. Might this be more?
- */
-#define PAGES_FOR_IO 512
-
-
-/*
- * Saving part...
- */
-
-
-/* We memorize in swapfile_used what swap devices are used for suspension */
-#define SWAPFILE_UNUSED 0
-#define SWAPFILE_SUSPEND 1 /* This is the suspending device */
-#define SWAPFILE_IGNORED 2 /* Those are other swap devices ignored for suspension */
-
-static unsigned short swapfile_used[MAX_SWAPFILES];
-static unsigned short root_swap;
-
-
-static int mark_swapfiles(swp_entry_t prev)
-{
- int error;
-
- rw_swap_page_sync(READ,
- swp_entry(root_swap, 0),
- virt_to_page((unsigned long)&pmdisk_header));
- if (!memcmp("SWAP-SPACE",pmdisk_header.sig,10) ||
- !memcmp("SWAPSPACE2",pmdisk_header.sig,10)) {
- memcpy(pmdisk_header.orig_sig,pmdisk_header.sig,10);
- memcpy(pmdisk_header.sig,PMDISK_SIG,10);
- pmdisk_header.pmdisk_info = prev;
- error = rw_swap_page_sync(WRITE,
- swp_entry(root_swap, 0),
- virt_to_page((unsigned long)
- &pmdisk_header));
- } else {
- pr_debug("pmdisk: Partition is not swap space.\n");
- error = -ENODEV;
- }
- return error;
-}
-
-static int read_swapfiles(void) /* This is called before saving image */
-{
- int i, len;
-
- len=strlen(resume_file);
- root_swap = 0xFFFF;
-
- swap_list_lock();
- for(i=0; i<MAX_SWAPFILES; i++) {
- if (swap_info[i].flags == 0) {
- swapfile_used[i]=SWAPFILE_UNUSED;
- } else {
- if(!len) {
- pr_debug("pmdisk: Default resume partition not set.\n");
- if(root_swap == 0xFFFF) {
- swapfile_used[i] = SWAPFILE_SUSPEND;
- root_swap = i;
- } else
- swapfile_used[i] = SWAPFILE_IGNORED;
- } else {
- /* we ignore all swap devices that are not the resume_file */
- if (1) {
-// FIXME if(resume_device == swap_info[i].swap_device) {
- swapfile_used[i] = SWAPFILE_SUSPEND;
- root_swap = i;
- } else
- swapfile_used[i] = SWAPFILE_IGNORED;
- }
- }
- }
- swap_list_unlock();
- return (root_swap != 0xffff) ? 0 : -ENODEV;
-}
-
-
-/* This is called after saving image so modification
- will be lost after resume... and that's what we want. */
-static void lock_swapdevices(void)
-{
- int i;
-
- swap_list_lock();
- for(i = 0; i< MAX_SWAPFILES; i++)
- if(swapfile_used[i] == SWAPFILE_IGNORED) {
- swap_info[i].flags ^= 0xFF; /* we make the device unusable. A new call to
- lock_swapdevices can unlock the devices. */
- }
- swap_list_unlock();
-}
-
-
-
-/**
- * write_swap_page - Write one page to a fresh swap location.
- * @addr: Address we're writing.
- * @loc: Place to store the entry we used.
- *
- * Allocate a new swap entry and 'sync' it. Note we discard -EIO
- * errors. That is an artifact left over from swsusp. It did not
- * check the return of rw_swap_page_sync() at all, since most pages
- * written back to swap would return -EIO.
- * This is a partial improvement, since we will at least return other
- * errors, though we need to eventually fix the damn code.
- */
-
-static int write_swap_page(unsigned long addr, swp_entry_t * loc)
-{
- swp_entry_t entry;
- int error = 0;
-
- entry = get_swap_page();
- if (swp_offset(entry) &&
- swapfile_used[swp_type(entry)] == SWAPFILE_SUSPEND) {
- error = rw_swap_page_sync(WRITE, entry,
- virt_to_page(addr));
- if (error == -EIO)
- error = 0;
- if (!error)
- *loc = entry;
- } else
- error = -ENOSPC;
- return error;
-}
-
-
-/**
- * free_data - Free the swap entries used by the saved image.
- *
- * Walk the list of used swap entries and free each one.
- */
-
-static void free_data(void)
-{
- swp_entry_t entry;
- int i;
-
- for (i = 0; i < pmdisk_pages; i++) {
- entry = (pm_pagedir_nosave + i)->swap_address;
- if (entry.val)
- swap_free(entry);
- else
- break;
- (pm_pagedir_nosave + i)->swap_address = (swp_entry_t){0};
- }
-}
-
-
-/**
- * write_data - Write saved image to swap.
- *
- * Walk the list of pages in the image and sync each one to swap.
- */
-
-static int write_data(void)
-{
- int error = 0;
- int i;
-
- printk( "Writing data to swap (%d pages): ", pmdisk_pages );
- for (i = 0; i < pmdisk_pages && !error; i++) {
- if (!(i%100))
- printk( "." );
- error = write_swap_page((pm_pagedir_nosave+i)->address,
- &((pm_pagedir_nosave+i)->swap_address));
- }
- printk(" %d Pages done.\n",i);
- return error;
-}
-
-
-/**
- * free_pagedir - Free pages used by the page directory.
- */
-
-static void free_pagedir_entries(void)
-{
- int num = pmdisk_info.pagedir_pages;
- int i;
-
- for (i = 0; i < num; i++)
- swap_free(pmdisk_info.pagedir[i]);
-}
-
-
-/**
- * write_pagedir - Write the array of pages holding the page directory.
- * @last: Last swap entry we write (needed for header).
- */
-
-static int write_pagedir(void)
-{
- unsigned long addr = (unsigned long)pm_pagedir_nosave;
- int error = 0;
- int n = SUSPEND_PD_PAGES(pmdisk_pages);
- int i;
-
- pmdisk_info.pagedir_pages = n;
- printk( "Writing pagedir (%d pages)\n", n);
- for (i = 0; i < n && !error; i++, addr += PAGE_SIZE)
- error = write_swap_page(addr,&pmdisk_info.pagedir[i]);
- return error;
-}
-
-
-#ifdef DEBUG
-static void dump_pmdisk_info(void)
-{
- printk(" pmdisk: Version: %u\n",pmdisk_info.version_code);
- printk(" pmdisk: Num Pages: %ld\n",pmdisk_info.num_physpages);
- printk(" pmdisk: UTS Sys: %s\n",pmdisk_info.uts.sysname);
- printk(" pmdisk: UTS Node: %s\n",pmdisk_info.uts.nodename);
- printk(" pmdisk: UTS Release: %s\n",pmdisk_info.uts.release);
- printk(" pmdisk: UTS Version: %s\n",pmdisk_info.uts.version);
- printk(" pmdisk: UTS Machine: %s\n",pmdisk_info.uts.machine);
- printk(" pmdisk: UTS Domain: %s\n",pmdisk_info.uts.domainname);
- printk(" pmdisk: CPUs: %d\n",pmdisk_info.cpus);
- printk(" pmdisk: Image: %ld Pages\n",pmdisk_info.image_pages);
- printk(" pmdisk: Pagedir: %ld Pages\n",pmdisk_info.pagedir_pages);
-}
-#else
-static void dump_pmdisk_info(void)
-{
-
-}
-#endif
-
-static void init_header(void)
-{
- memset(&pmdisk_info,0,sizeof(pmdisk_info));
- pmdisk_info.version_code = LINUX_VERSION_CODE;
- pmdisk_info.num_physpages = num_physpages;
- memcpy(&pmdisk_info.uts,&system_utsname,sizeof(system_utsname));
-
- pmdisk_info.cpus = num_online_cpus();
- pmdisk_info.image_pages = pmdisk_pages;
-}
-
-/**
- * write_header - Fill and write the suspend header.
- * @entry: Location of the last swap entry used.
- *
- * Allocate a page, fill header, write header.
- *
- * @entry is the location of the last pagedir entry written on
- * entrance. On exit, it contains the location of the header.
- */
-
-static int write_header(swp_entry_t * entry)
-{
- dump_pmdisk_info();
- return write_swap_page((unsigned long)&pmdisk_info,entry);
-}
-
-
-
-/**
- * write_suspend_image - Write entire image and metadata.
- *
- */
-
-static int write_suspend_image(void)
-{
- int error;
- swp_entry_t prev = { 0 };
-
- init_header();
-
- if ((error = write_data()))
- goto FreeData;
-
- if ((error = write_pagedir()))
- goto FreePagedir;
-
- if ((error = write_header(&prev)))
- goto FreePagedir;
-
- error = mark_swapfiles(prev);
- Done:
- return error;
- FreePagedir:
- free_pagedir_entries();
- FreeData:
- free_data();
- goto Done;
-}
-
-
-
-/**
- * saveable - Determine whether a page should be cloned or not.
- * @pfn: The page
- *
- * We save a page if it's Reserved, and not in the range of pages
- * statically defined as 'unsaveable', or if it isn't reserved, and
- * isn't part of a free chunk of pages.
- * If it is part of a free chunk, we update @pfn to point to the last
- * page of the chunk.
- */
-
-static int saveable(unsigned long * pfn)
-{
- struct page * page = pfn_to_page(*pfn);
-
- if (PageNosave(page))
- return 0;
-
- if (!PageReserved(page)) {
- int chunk_size;
-
- if ((chunk_size = is_head_of_free_region(page))) {
- *pfn += chunk_size - 1;
- return 0;
- }
- } else if (PageReserved(page)) {
- /* Just copy whole code segment.
- * Hopefully it is not that big.
- */
- if ((ADDRESS(*pfn) >= (unsigned long) ADDRESS2(&__nosave_begin)) &&
- (ADDRESS(*pfn) < (unsigned long) ADDRESS2(&__nosave_end))) {
- pr_debug("[nosave %lx]\n", ADDRESS(*pfn));
- return 0;
- }
- /* Hmm, perhaps copying all reserved pages is not
- * too healthy as they may contain
- * critical bios data?
- */
- }
- return 1;
-}
-
-
-
-/**
- * count_pages - Determine size of page directory.
- *
- * Iterate over all the pages in the system and tally the number
- * we need to clone.
- */
-
-static void count_pages(void)
-{
- unsigned long pfn;
- int n = 0;
-
- for (pfn = 0; pfn < max_pfn; pfn++) {
- if (saveable(&pfn))
- n++;
- }
- pmdisk_pages = n;
-}
-
-
-/**
- * copy_pages - Atomically snapshot memory.
- *
- * Iterate over all the pages in the system and copy each one
- * into its corresponding location in the pagedir.
- * We rely on the fact that the number of pages that we're snap-
- * shotting hasn't changed since we counted them.
- */
-
-static void copy_pages(void)
-{
- struct pbe * p = pagedir_save;
- unsigned long pfn;
- int n = 0;
-
- for (pfn = 0; pfn < max_pfn; pfn++) {
- if (saveable(&pfn)) {
- n++;
- p->orig_address = ADDRESS(pfn);
- copy_page((void *) p->address,
- (void *) p->orig_address);
- p++;
- }
- }
- BUG_ON(n != pmdisk_pages);
-}
-
-
-/**
- * free_image_pages - Free each page allocated for snapshot.
- */
-
-static void free_image_pages(void)
-{
- struct pbe * p;
- int i;
-
- for (i = 0, p = pagedir_save; i < pmdisk_pages; i++, p++) {
- ClearPageNosave(virt_to_page(p->address));
- free_page(p->address);
- }
-}
-
-
-/**
- * free_pagedir - Free the page directory.
- */
-
-static void free_pagedir(void)
-{
- free_image_pages();
- free_pages((unsigned long)pagedir_save, pagedir_order);
-}
-
-
-static void calc_order(void)
-{
- int diff;
- int order;
-
- order = get_bitmask_order(SUSPEND_PD_PAGES(pmdisk_pages));
- pmdisk_pages += 1 << order;
- do {
- diff = get_bitmask_order(SUSPEND_PD_PAGES(pmdisk_pages)) - order;
- if (diff) {
- order += diff;
- pmdisk_pages += 1 << diff;
- }
- } while(diff);
- pagedir_order = order;
-}
-
-
-/**
- * alloc_pagedir - Allocate the page directory.
- *
- * First, determine exactly how many contiguous pages we need,
- * allocate them, then mark each 'unsavable'.
- */
-
-static int alloc_pagedir(void)
-{
- calc_order();
- pagedir_save = (suspend_pagedir_t *)__get_free_pages(GFP_ATOMIC | __GFP_COLD,
- pagedir_order);
- if(!pagedir_save)
- return -ENOMEM;
- memset(pagedir_save,0,(1 << pagedir_order) * PAGE_SIZE);
- pm_pagedir_nosave = pagedir_save;
- return 0;
-}
-
-
-/**
- * alloc_image_pages - Allocate pages for the snapshot.
- *
- */
-
-static int alloc_image_pages(void)
-{
- struct pbe * p;
- int i;
-
- for (i = 0, p = pagedir_save; i < pmdisk_pages; i++, p++) {
- p->address = get_zeroed_page(GFP_ATOMIC | __GFP_COLD);
- if(!p->address)
- goto Error;
- SetPageNosave(virt_to_page(p->address));
- }
- return 0;
- Error:
- do {
- if (p->address)
- free_page(p->address);
- p->address = 0;
- } while (p-- > pagedir_save);
- return -ENOMEM;
-}
-
-
-/**
- * enough_free_mem - Make sure we enough free memory to snapshot.
- *
- * Returns TRUE or FALSE after checking the number of available
- * free pages.
- */
-
-static int enough_free_mem(void)
-{
- if(nr_free_pages() < (pmdisk_pages + PAGES_FOR_IO)) {
- pr_debug("pmdisk: Not enough free pages: Have %d\n",
- nr_free_pages());
- return 0;
- }
- return 1;
-}
-
-
-/**
- * enough_swap - Make sure we have enough swap to save the image.
- *
- * Returns TRUE or FALSE after checking the total amount of swap
- * space avaiable.
- *
- * FIXME: si_swapinfo(&i) returns all swap devices information.
- * We should only consider resume_device.
- */
-
-static int enough_swap(void)
-{
- struct sysinfo i;
-
- si_swapinfo(&i);
- if (i.freeswap < (pmdisk_pages + PAGES_FOR_IO)) {
- pr_debug("pmdisk: Not enough swap. Need %ld\n",i.freeswap);
- return 0;
- }
- return 1;
-}
-
-
-/**
- * pmdisk_suspend - Atomically snapshot the system.
- *
- * This must be called with interrupts disabled, to prevent the
- * system changing at all from underneath us.
- *
- * To do this, we count the number of pages in the system that we
- * need to save; make sure we have enough memory and swap to clone
- * the pages and save them in swap, allocate the space to hold them,
- * and then snapshot them all.
- */
-
-int pmdisk_suspend(void)
-{
- int error = 0;
-
- if ((error = read_swapfiles()))
- return error;
-
- drain_local_pages();
-
- pm_pagedir_nosave = NULL;
- pr_debug("pmdisk: Counting pages to copy.\n" );
- count_pages();
-
- pr_debug("pmdisk: (pages needed: %d + %d free: %d)\n",
- pmdisk_pages,PAGES_FOR_IO,nr_free_pages());
-
- if (!enough_free_mem())
- return -ENOMEM;
-
- if (!enough_swap())
- return -ENOSPC;
-
- if ((error = alloc_pagedir())) {
- pr_debug("pmdisk: Allocating pagedir failed.\n");
- return error;
- }
- if ((error = alloc_image_pages())) {
- pr_debug("pmdisk: Allocating image pages failed.\n");
- free_pagedir();
- return error;
- }
-
- nr_copy_pages_check = pmdisk_pages;
- pagedir_order_check = pagedir_order;
-
- /* During allocating of suspend pagedir, new cold pages may appear.
- * Kill them
- */
- drain_local_pages();
-
- /* copy */
- copy_pages();
-
- /*
- * End of critical section. From now on, we can write to memory,
- * but we should not touch disk. This specially means we must _not_
- * touch swap space! Except we must write out our image of course.
- */
-
- pr_debug("pmdisk: %d pages copied\n", pmdisk_pages );
- return 0;
-}
-
-
-/**
- * suspend_save_image - Prepare and write saved image to swap.
- *
- * IRQs are re-enabled here so we can resume devices and safely write
- * to the swap devices. We disable them again before we leave.
- *
- * The second lock_swapdevices() will unlock ignored swap devices since
- * writing is finished.
- * It is important _NOT_ to umount filesystems at this point. We want
- * them synced (in case something goes wrong) but we DO not want to mark
- * filesystem clean: it is not. (And it does not matter, if we resume
- * correctly, we'll mark system clean, anyway.)
- */
-
-static int suspend_save_image(void)
-{
- int error;
- device_resume();
- lock_swapdevices();
- error = write_suspend_image();
- lock_swapdevices();
- return error;
-}
-
-/*
- * Magic happens here
- */
-
-int pmdisk_resume(void)
-{
- BUG_ON (nr_copy_pages_check != pmdisk_pages);
- BUG_ON (pagedir_order_check != pagedir_order);
-
- /* Even mappings of "global" things (vmalloc) need to be fixed */
- __flush_tlb_global();
- return 0;
-}
-
-/* pmdisk_arch_suspend() is implemented in arch/?/power/pmdisk.S,
- and basically does:
-
- if (!resume) {
- save_processor_state();
- SAVE_REGISTERS
- return pmdisk_suspend();
- }
- GO_TO_SWAPPER_PAGE_TABLES
- COPY_PAGES_BACK
- RESTORE_REGISTERS
- restore_processor_state();
- return pmdisk_resume();
-
- */
-
-
-/* More restore stuff */
-
-#define does_collide(addr) does_collide_order(pm_pagedir_nosave, addr, 0)
-
-/*
- * Returns true if given address/order collides with any orig_address
- */
-static int __init does_collide_order(suspend_pagedir_t *pagedir,
- unsigned long addr, int order)
-{
- int i;
- unsigned long addre = addr + (PAGE_SIZE<<order);
-
- for(i=0; i < pmdisk_pages; i++)
- if((pagedir+i)->orig_address >= addr &&
- (pagedir+i)->orig_address < addre)
- return 1;
-
- return 0;
-}
-
-/*
- * We check here that pagedir & pages it points to won't collide with pages
- * where we're going to restore from the loaded pages later
- */
-static int __init check_pagedir(void)
-{
- int i;
-
- for(i=0; i < pmdisk_pages; i++) {
- unsigned long addr;
-
- do {
- addr = get_zeroed_page(GFP_ATOMIC);
- if(!addr)
- return -ENOMEM;
- } while (does_collide(addr));
-
- (pm_pagedir_nosave+i)->address = addr;
- }
- return 0;
-}
-
-static int __init relocate_pagedir(void)
-{
- /*
- * We have to avoid recursion (not to overflow kernel stack),
- * and that's why code looks pretty cryptic
- */
- suspend_pagedir_t *old_pagedir = pm_pagedir_nosave;
- void **eaten_memory = NULL;
- void **c = eaten_memory, *m, *f;
- int err;
-
- pr_debug("pmdisk: Relocating pagedir\n");
-
- if(!does_collide_order(old_pagedir, (unsigned long)old_pagedir, pagedir_order)) {
- pr_debug("pmdisk: Relocation not necessary\n");
- return 0;
- }
-
- err = -ENOMEM;
- while ((m = (void *) __get_free_pages(GFP_ATOMIC, pagedir_order)) != NULL) {
- if (!does_collide_order(old_pagedir, (unsigned long)m,
- pagedir_order)) {
- pm_pagedir_nosave =
- memcpy(m, old_pagedir,
- PAGE_SIZE << pagedir_order);
- err = 0;
- break;
- }
- eaten_memory = m;
- printk( "." );
- *eaten_memory = c;
- c = eaten_memory;
- }
-
- c = eaten_memory;
- while(c) {
- printk(":");
- f = c;
- c = *c;
- free_pages((unsigned long)f, pagedir_order);
- }
- printk("|\n");
- return err;
-}
-
-
-static struct block_device * resume_bdev;
-
-
-/**
- * Using bio to read from swap.
- * This code requires a bit more work than just using buffer heads
- * but, it is the recommended way for 2.5/2.6.
- * The following are to signal the beginning and end of I/O. Bios
- * finish asynchronously, while we want them to happen synchronously.
- * A simple atomic_t, and a wait loop take care of this problem.
- */
-
-static atomic_t io_done = ATOMIC_INIT(0);
-
-static void start_io(void)
-{
- atomic_set(&io_done,1);
-}
-
-static int end_io(struct bio * bio, unsigned int num, int err)
-{
- atomic_set(&io_done,0);
- return 0;
-}
-
-static void wait_io(void)
-{
- while(atomic_read(&io_done))
- io_schedule();
-}
-
-
-/**
- * submit - submit BIO request.
- * @rw: READ or WRITE.
- * @off physical offset of page.
- * @page: page we're reading or writing.
- *
- * Straight from the textbook - allocate and initialize the bio.
- * If we're writing, make sure the page is marked as dirty.
- * Then submit it and wait.
- */
-
-static int submit(int rw, pgoff_t page_off, void * page)
-{
- int error = 0;
- struct bio * bio;
-
- bio = bio_alloc(GFP_ATOMIC,1);
- if (!bio)
- return -ENOMEM;
- bio->bi_sector = page_off * (PAGE_SIZE >> 9);
- bio_get(bio);
- bio->bi_bdev = resume_bdev;
- bio->bi_end_io = end_io;
-
- if (bio_add_page(bio, virt_to_page(page), PAGE_SIZE, 0) < PAGE_SIZE) {
- printk("pmdisk: ERROR: adding page to bio at %ld\n",page_off);
- error = -EFAULT;
- goto Done;
- }
-
- if (rw == WRITE)
- bio_set_pages_dirty(bio);
- start_io();
- submit_bio(rw | (1 << BIO_RW_SYNC), bio);
- wait_io();
- Done:
- bio_put(bio);
- return error;
-}
-
-static int
-read_page(pgoff_t page_off, void * page)
-{
- return submit(READ,page_off,page);
-}
-
-static int
-write_page(pgoff_t page_off, void * page)
-{
- return submit(WRITE,page_off,page);
-}
-
-
-extern dev_t __init name_to_dev_t(const char *line);
-
-
-static int __init check_sig(void)
-{
- int error;
-
- memset(&pmdisk_header,0,sizeof(pmdisk_header));
- if ((error = read_page(0,&pmdisk_header)))
- return error;
- if (!memcmp(PMDISK_SIG,pmdisk_header.sig,10)) {
- memcpy(pmdisk_header.sig,pmdisk_header.orig_sig,10);
-
- /*
- * Reset swap signature now.
- */
- error = write_page(0,&pmdisk_header);
- } else {
- pr_debug(KERN_ERR "pmdisk: Invalid partition type.\n");
- return -EINVAL;
- }
- if (!error)
- pr_debug("pmdisk: Signature found, resuming\n");
- return error;
-}
-
-
-/*
- * Sanity check if this image makes sense with this kernel/swap context
- * I really don't think that it's foolproof but more than nothing..
- */
-
-static const char * __init sanity_check(void)
-{
- dump_pmdisk_info();
- if(pmdisk_info.version_code != LINUX_VERSION_CODE)
- return "kernel version";
- if(pmdisk_info.num_physpages != num_physpages)
- return "memory size";
- if (strcmp(pmdisk_info.uts.sysname,system_utsname.sysname))
- return "system type";
- if (strcmp(pmdisk_info.uts.release,system_utsname.release))
- return "kernel release";
- if (strcmp(pmdisk_info.uts.version,system_utsname.version))
- return "version";
- if (strcmp(pmdisk_info.uts.machine,system_utsname.machine))
- return "machine";
- if(pmdisk_info.cpus != num_online_cpus())
- return "number of cpus";
- return NULL;
-}
-
-
-static int __init check_header(void)
-{
- const char * reason = NULL;
- int error;
-
- init_header();
-
- if ((error = read_page(swp_offset(pmdisk_header.pmdisk_info),
- &pmdisk_info)))
- return error;
-
- /* Is this same machine? */
- if ((reason = sanity_check())) {
- printk(KERN_ERR "pmdisk: Resume mismatch: %s\n",reason);
- return -EPERM;
- }
- pmdisk_pages = pmdisk_info.image_pages;
- return error;
-}
-
-
-static int __init read_pagedir(void)
-{
- unsigned long addr;
- int i, n = pmdisk_info.pagedir_pages;
- int error = 0;
-
- pagedir_order = get_bitmask_order(n);
-
- addr =__get_free_pages(GFP_ATOMIC, pagedir_order);
- if (!addr)
- return -ENOMEM;
- pm_pagedir_nosave = (struct pbe *)addr;
-
- pr_debug("pmdisk: Reading pagedir (%d Pages)\n",n);
-
- for (i = 0; i < n && !error; i++, addr += PAGE_SIZE) {
- unsigned long offset = swp_offset(pmdisk_info.pagedir[i]);
- if (offset)
- error = read_page(offset, (void *)addr);
- else
- error = -EFAULT;
- }
- if (error)
- free_pages((unsigned long)pm_pagedir_nosave,pagedir_order);
- return error;
-}
-
-
-/**
- * read_image_data - Read image pages from swap.
- *
- * You do not need to check for overlaps, check_pagedir()
- * already did that.
- */
-
-static int __init read_image_data(void)
-{
- struct pbe * p;
- int error = 0;
- int i;
-
- printk( "Reading image data (%d pages): ", pmdisk_pages );
- for(i = 0, p = pm_pagedir_nosave; i < pmdisk_pages && !error; i++, p++) {
- if (!(i%100))
- printk( "." );
- error = read_page(swp_offset(p->swap_address),
- (void *)p->address);
- }
- printk(" %d done.\n",i);
- return error;
-}
-
-
-static int __init read_suspend_image(void)
-{
- int error = 0;
-
- if ((error = check_sig()))
- return error;
- if ((error = check_header()))
- return error;
- if ((error = read_pagedir()))
- return error;
- if ((error = relocate_pagedir()))
- goto FreePagedir;
- if ((error = check_pagedir()))
- goto FreePagedir;
- if ((error = read_image_data()))
- goto FreePagedir;
- Done:
- return error;
- FreePagedir:
- free_pages((unsigned long)pm_pagedir_nosave,pagedir_order);
- goto Done;
-}
-
-/**
- * pmdisk_save - Snapshot memory
- */
-
-int pmdisk_save(void)
-{
- int error;
-
-#if defined (CONFIG_HIGHMEM) || defined (CONFIG_DISCONTIGMEM)
- pr_debug("pmdisk: not supported with high- or discontig-mem.\n");
- return -EPERM;
-#endif
- if ((error = arch_prepare_suspend()))
- return error;
- local_irq_disable();
- save_processor_state();
- error = pmdisk_arch_suspend(0);
- restore_processor_state();
- local_irq_enable();
- return error;
-}
-
-
-/**
- * pmdisk_write - Write saved memory image to swap.
- *
- * pmdisk_arch_suspend(0) returns after system is resumed.
- *
- * pmdisk_arch_suspend() copies all "used" memory to "free" memory,
- * then unsuspends all device drivers, and writes memory to disk
- * using normal kernel mechanism.
- */
-
-int pmdisk_write(void)
-{
- return suspend_save_image();
-}
-
-
-/**
- * pmdisk_read - Read saved image from swap.
- */
-
-int __init pmdisk_read(void)
-{
- int error;
-
- if (!strlen(resume_file))
- return -ENOENT;
-
- resume_device = name_to_dev_t(resume_file);
- pr_debug("pmdisk: Resume From Partition: %s\n", resume_file);
-
- resume_bdev = open_by_devnum(resume_device, FMODE_READ);
- if (!IS_ERR(resume_bdev)) {
- set_blocksize(resume_bdev, PAGE_SIZE);
- error = read_suspend_image();
- blkdev_put(resume_bdev);
- } else
- error = PTR_ERR(resume_bdev);
-
- if (!error)
- pr_debug("Reading resume file was successful\n");
- else
- pr_debug("pmdisk: Error %d resuming\n", error);
- return error;
-}
-
-
-/**
- * pmdisk_restore - Replace running kernel with saved image.
- */
-
-int __init pmdisk_restore(void)
-{
- int error;
- local_irq_disable();
- save_processor_state();
- error = pmdisk_arch_suspend(1);
- restore_processor_state();
- local_irq_enable();
- return error;
-}
-
-
-/**
- * pmdisk_free - Free memory allocated to hold snapshot.
- */
-
-int pmdisk_free(void)
-{
- pr_debug( "Freeing prev allocated pagedir\n" );
- free_pagedir();
- return 0;
-}
-
-static int __init pmdisk_setup(char *str)
-{
- if (strlen(str)) {
- if (!strcmp(str,"off"))
- resume_file[0] = '\0';
- else
- strncpy(resume_file, str, 255);
- } else
- resume_file[0] = '\0';
- return 1;
-}
-
-__setup("pmdisk=", pmdisk_setup);
-
+++ /dev/null
-/* inffixed.h -- table for decoding fixed codes
- * Generated automatically by the maketree.c program
- */
-
-/* WARNING: this file should *not* be used by applications. It is
- part of the implementation of the compression library and is
- subject to change. Applications should only use zlib.h.
- */
-
-static uInt fixed_bl = 9;
-static uInt fixed_bd = 5;
-static inflate_huft fixed_tl[] = {
- {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
- {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
- {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
- {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
- {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
- {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
- {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
- {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
- {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
- {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
- {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
- {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
- {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
- {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
- {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
- {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
- {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
- {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
- {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
- {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
- {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
- {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
- {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
- {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
- {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
- {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
- {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
- {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
- {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
- {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
- {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
- {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
- {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
- {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
- {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
- {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
- {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
- {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
- {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
- {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
- {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
- {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
- {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
- {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
- {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
- {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
- {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
- {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
- {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
- {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
- {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
- {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
- {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
- {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
- {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
- {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
- {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
- {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
- {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
- {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
- {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
- {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
- {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
- {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
- {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
- {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
- {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
- {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
- {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
- {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
- {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
- {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
- {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
- {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
- {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
- {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
- {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
- {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
- {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
- {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
- {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
- {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
- {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
- {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
- {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
- {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
- {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
- {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
- {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
- {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
- {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
- {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
- {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
- {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
- {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
- {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
- {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
- {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
- {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
- {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
- {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
- {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
- {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
- {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
- {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
- {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
- {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
- {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
- {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
- {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
- {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
- {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
- {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
- {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
- {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
- {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
- {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
- {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
- {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
- {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
- {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
- {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
- {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
- {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
- {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
- {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
- {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
- {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
- };
-static inflate_huft fixed_td[] = {
- {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
- {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
- {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
- {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
- {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
- {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
- {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
- {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
- };
}
asmlinkage long
-do_mprotect(struct mm_struct *mm, unsigned long start, size_t len,
- unsigned long prot)
+sys_mprotect(unsigned long start, size_t len, unsigned long prot)
{
unsigned long vm_flags, nstart, end, tmp, reqprot;
struct vm_area_struct *vma, *prev;
vm_flags = calc_vm_prot_bits(prot);
- down_write(&mm->mmap_sem);
+ down_write(¤t->mm->mmap_sem);
- vma = find_vma_prev(mm, start, &prev);
+ vma = find_vma_prev(current->mm, start, &prev);
error = -ENOMEM;
if (!vma)
goto out;
}
}
out:
- up_write(&mm->mmap_sem);
+ up_write(¤t->mm->mmap_sem);
return error;
}
-
-asmlinkage long sys_mprotect(unsigned long start, size_t len, unsigned long prot)
-{
- return(do_mprotect(current->mm, start, len, prot));
-}
+++ /dev/null
-/*
- * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
- * Licensed under the GPL
- */
-
-#include "linux/mm.h"
-#include "linux/init.h"
-#include "linux/proc_fs.h"
-#include "linux/proc_mm.h"
-#include "linux/file.h"
-#include "asm/uaccess.h"
-#include "asm/mmu_context.h"
-
-static struct file_operations proc_mm_fops;
-
-struct mm_struct *proc_mm_get_mm(int fd)
-{
- struct mm_struct *ret = ERR_PTR(-EBADF);
- struct file *file;
-
- file = fget(fd);
- if (!file)
- goto out;
-
- ret = ERR_PTR(-EINVAL);
- if(file->f_op != &proc_mm_fops)
- goto out_fput;
-
- ret = file->private_data;
- out_fput:
- fput(file);
- out:
- return(ret);
-}
-
-extern long do_mmap2(struct mm_struct *mm, unsigned long addr,
- unsigned long len, unsigned long prot,
- unsigned long flags, unsigned long fd,
- unsigned long pgoff);
-
-static ssize_t write_proc_mm(struct file *file, const char *buffer,
- size_t count, loff_t *ppos)
-{
- struct mm_struct *mm = file->private_data;
- struct proc_mm_op req;
- int n, ret;
-
- if(count > sizeof(req))
- return(-EINVAL);
-
- n = copy_from_user(&req, buffer, count);
- if(n != 0)
- return(-EFAULT);
-
- ret = count;
- switch(req.op){
- case MM_MMAP: {
- struct mm_mmap *map = &req.u.mmap;
-
- ret = do_mmap2(mm, map->addr, map->len, map->prot,
- map->flags, map->fd, map->offset >> PAGE_SHIFT);
- if((ret & ~PAGE_MASK) == 0)
- ret = count;
-
- break;
- }
- case MM_MUNMAP: {
- struct mm_munmap *unmap = &req.u.munmap;
-
- down_write(&mm->mmap_sem);
- ret = do_munmap(mm, unmap->addr, unmap->len);
- up_write(&mm->mmap_sem);
-
- if(ret == 0)
- ret = count;
- break;
- }
- case MM_MPROTECT: {
- struct mm_mprotect *protect = &req.u.mprotect;
-
- ret = do_mprotect(mm, protect->addr, protect->len,
- protect->prot);
- if(ret == 0)
- ret = count;
- break;
- }
-
- case MM_COPY_SEGMENTS: {
- struct mm_struct *from = proc_mm_get_mm(req.u.copy_segments);
-
- if(IS_ERR(from)){
- ret = PTR_ERR(from);
- break;
- }
-
- mm_copy_segments(from, mm);
- break;
- }
- default:
- ret = -EINVAL;
- break;
- }
-
- return(ret);
-}
-
-static int open_proc_mm(struct inode *inode, struct file *file)
-{
- struct mm_struct *mm = mm_alloc();
- int ret;
-
- ret = -ENOMEM;
- if(mm == NULL)
- goto out_mem;
-
- ret = init_new_context(current, mm);
- if(ret)
- goto out_free;
-
- spin_lock(&mmlist_lock);
- list_add(&mm->mmlist, ¤t->mm->mmlist);
- mmlist_nr++;
- spin_unlock(&mmlist_lock);
-
- file->private_data = mm;
-
- return(0);
-
- out_free:
- mmput(mm);
- out_mem:
- return(ret);
-}
-
-static int release_proc_mm(struct inode *inode, struct file *file)
-{
- struct mm_struct *mm = file->private_data;
-
- mmput(mm);
- return(0);
-}
-
-static struct file_operations proc_mm_fops = {
- .open = open_proc_mm,
- .release = release_proc_mm,
- .write = write_proc_mm,
-};
-
-static int make_proc_mm(void)
-{
- struct proc_dir_entry *ent;
-
- ent = create_proc_entry("mm", 0222, &proc_root);
- if(ent == NULL){
- printk("make_proc_mm : Failed to register /proc/mm\n");
- return(0);
- }
- ent->proc_fops = &proc_mm_fops;
-
- return(0);
-}
-
-__initcall(make_proc_mm);
-
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only. This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+++ /dev/null
-/*
- * linux/mm/usercopy.c
- *
- * (C) Copyright 2003 Ingo Molnar
- *
- * Generic implementation of all the user-VM access functions, without
- * relying on being able to access the VM directly.
- */
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/mm.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-#include <linux/smp_lock.h>
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
-
-#include <asm/pgtable.h>
-#include <asm/uaccess.h>
-#include <asm/atomic_kmap.h>
-
-/*
- * Get kernel address of the user page and pin it.
- */
-static inline struct page *pin_page(unsigned long addr, int write)
-{
- struct mm_struct *mm = current->mm ? : &init_mm;
- struct page *page = NULL;
- int ret;
-
- /*
- * Do a quick atomic lookup first - this is the fastpath.
- */
-retry:
- page = follow_page(mm, addr, write);
- if (likely(page != NULL)) {
- if (!PageReserved(page))
- get_page(page);
- return page;
- }
-
- /*
- * No luck - bad address or need to fault in the page:
- */
-
- /* Release the lock so get_user_pages can sleep */
- spin_unlock(&mm->page_table_lock);
-
- /*
- * In the context of filemap_copy_from_user(), we are not allowed
- * to sleep. We must fail this usercopy attempt and allow
- * filemap_copy_from_user() to recover: drop its atomic kmap and use
- * a sleeping kmap instead.
- */
- if (in_atomic()) {
- spin_lock(&mm->page_table_lock);
- return NULL;
- }
-
- down_read(&mm->mmap_sem);
- ret = get_user_pages(current, mm, addr, 1, write, 0, NULL, NULL);
- up_read(&mm->mmap_sem);
- spin_lock(&mm->page_table_lock);
-
- if (ret <= 0)
- return NULL;
-
- /*
- * Go try the follow_page again.
- */
- goto retry;
-}
-
-static inline void unpin_page(struct page *page)
-{
- put_page(page);
-}
-
-/*
- * Access another process' address space.
- * Source/target buffer must be kernel space,
- * Do not walk the page table directly, use get_user_pages
- */
-static int rw_vm(unsigned long addr, void *buf, int len, int write)
-{
- struct mm_struct *mm = current->mm ? : &init_mm;
-
- if (!len)
- return 0;
-
- spin_lock(&mm->page_table_lock);
-
- /* ignore errors, just check how much was sucessfully transfered */
- while (len) {
- struct page *page = NULL;
- int bytes, offset;
- void *maddr;
-
- page = pin_page(addr, write);
- if (!page)
- break;
-
- bytes = len;
- offset = addr & (PAGE_SIZE-1);
- if (bytes > PAGE_SIZE-offset)
- bytes = PAGE_SIZE-offset;
-
- maddr = kmap_atomic(page, KM_USER_COPY);
-
-#define HANDLE_TYPE(type) \
- case sizeof(type): *(type *)(maddr+offset) = *(type *)(buf); break;
-
- if (write) {
- switch (bytes) {
- HANDLE_TYPE(char);
- HANDLE_TYPE(int);
- HANDLE_TYPE(long long);
- default:
- memcpy(maddr + offset, buf, bytes);
- }
- } else {
-#undef HANDLE_TYPE
-#define HANDLE_TYPE(type) \
- case sizeof(type): *(type *)(buf) = *(type *)(maddr+offset); break;
- switch (bytes) {
- HANDLE_TYPE(char);
- HANDLE_TYPE(int);
- HANDLE_TYPE(long long);
- default:
- memcpy(buf, maddr + offset, bytes);
- }
-#undef HANDLE_TYPE
- }
- kunmap_atomic(maddr, KM_USER_COPY);
- unpin_page(page);
- len -= bytes;
- buf += bytes;
- addr += bytes;
- }
- spin_unlock(&mm->page_table_lock);
-
- return len;
-}
-
-static int str_vm(unsigned long addr, void *buf0, int len, int copy)
-{
- struct mm_struct *mm = current->mm ? : &init_mm;
- struct page *page;
- void *buf = buf0;
-
- if (!len)
- return len;
-
- spin_lock(&mm->page_table_lock);
-
- /* ignore errors, just check how much was sucessfully transfered */
- while (len) {
- int bytes, offset, left, copied;
- char *maddr;
-
- page = pin_page(addr, copy == 2);
- if (!page) {
- spin_unlock(&mm->page_table_lock);
- return -EFAULT;
- }
- bytes = len;
- offset = addr & (PAGE_SIZE-1);
- if (bytes > PAGE_SIZE-offset)
- bytes = PAGE_SIZE-offset;
-
- maddr = kmap_atomic(page, KM_USER_COPY);
- if (copy == 2) {
- memset(maddr + offset, 0, bytes);
- copied = bytes;
- left = 0;
- } else if (copy == 1) {
- left = strncpy_count(buf, maddr + offset, bytes);
- copied = bytes - left;
- } else {
- copied = strnlen(maddr + offset, bytes);
- left = bytes - copied;
- }
- BUG_ON(bytes < 0 || copied < 0);
- kunmap_atomic(maddr, KM_USER_COPY);
- unpin_page(page);
- len -= copied;
- buf += copied;
- addr += copied;
- if (left)
- break;
- }
- spin_unlock(&mm->page_table_lock);
-
- return len;
-}
-
-/*
- * Copies memory from userspace (ptr) into kernelspace (val).
- *
- * returns # of bytes not copied.
- */
-int get_user_size(unsigned int size, void *val, const void *ptr)
-{
- int ret;
-
- if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
- ret = __direct_copy_from_user(val, ptr, size);
- else
- ret = rw_vm((unsigned long)ptr, val, size, 0);
- if (ret)
- /*
- * Zero the rest:
- */
- memset(val + size - ret, 0, ret);
- return ret;
-}
-
-/*
- * Copies memory from kernelspace (val) into userspace (ptr).
- *
- * returns # of bytes not copied.
- */
-int put_user_size(unsigned int size, const void *val, void *ptr)
-{
- if (unlikely(segment_eq(get_fs(), KERNEL_DS)))
- return __direct_copy_to_user(ptr, val, size);
- else
- return rw_vm((unsigned long)ptr, (void *)val, size, 1);
-}
-
-int copy_str_fromuser_size(unsigned int size, void *val, const void *ptr)
-{
- int copied, left;
-
- if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
- left = strncpy_count(val, ptr, size);
- copied = size - left;
- BUG_ON(copied < 0);
-
- return copied;
- }
- left = str_vm((unsigned long)ptr, val, size, 1);
- if (left < 0)
- return left;
- copied = size - left;
- BUG_ON(copied < 0);
-
- return copied;
-}
-
-int strlen_fromuser_size(unsigned int size, const void *ptr)
-{
- int copied, left;
-
- if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
- copied = strnlen(ptr, size) + 1;
- BUG_ON(copied < 0);
-
- return copied;
- }
- left = str_vm((unsigned long)ptr, NULL, size, 0);
- if (left < 0)
- return 0;
- copied = size - left + 1;
- BUG_ON(copied < 0);
-
- return copied;
-}
-
-int zero_user_size(unsigned int size, void *ptr)
-{
- int left;
-
- if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
- memset(ptr, 0, size);
- return 0;
- }
- left = str_vm((unsigned long)ptr, NULL, size, 2);
- if (left < 0)
- return size;
- return left;
-}
-
-EXPORT_SYMBOL(get_user_size);
-EXPORT_SYMBOL(put_user_size);
-EXPORT_SYMBOL(zero_user_size);
-EXPORT_SYMBOL(copy_str_fromuser_size);
-EXPORT_SYMBOL(strlen_fromuser_size);
for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++)
printk(" O=0x%8.8X", *opt++);
- printk(" MARK=%lu (0x%lu)",
+ printk(" MARK=%lu (0x%lx)",
(long unsigned int)skb->nfmark,
(long unsigned int)skb->nfmark);
printk("\n");
+++ /dev/null
-/*
- * INET An implementation of the TCP/IP protocol suite for the LINUX
- * operating system. INET is implemented using the BSD Socket
- * interface as the means of communication with the user level.
- *
- * Dumb Network Address Translation.
- *
- * Version: $Id: ip_nat_dumb.c,v 1.11 2000/12/13 18:31:48 davem Exp $
- *
- * Authors: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru>
- *
- * 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.
- *
- * Fixes:
- * Rani Assaf : A zero checksum is a special case
- * only in UDP
- * Rani Assaf : Added ICMP messages rewriting
- * Rani Assaf : Repaired wrong changes, made by ANK.
- *
- *
- * NOTE: It is just working model of real NAT.
- */
-
-#include <linux/config.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/ip.h>
-#include <linux/icmp.h>
-#include <linux/netdevice.h>
-#include <net/sock.h>
-#include <net/ip.h>
-#include <net/icmp.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
-#include <net/checksum.h>
-#include <linux/route.h>
-#include <net/route.h>
-#include <net/ip_fib.h>
-
-
-int
-ip_do_nat(struct sk_buff *skb)
-{
- struct rtable *rt = (struct rtable*)skb->dst;
- struct iphdr *iph = skb->nh.iph;
- u32 odaddr = iph->daddr;
- u32 osaddr = iph->saddr;
- u16 check;
-
- IPCB(skb)->flags |= IPSKB_TRANSLATED;
-
- /* Rewrite IP header */
- iph->daddr = rt->rt_dst_map;
- iph->saddr = rt->rt_src_map;
- iph->check = 0;
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
- /* If it is the first fragment, rewrite protocol headers */
-
- if (!(iph->frag_off & htons(IP_OFFSET))) {
- u16 *cksum;
-
- switch(iph->protocol) {
- case IPPROTO_TCP:
- cksum = (u16*)&((struct tcphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
- if ((u8*)(cksum+1) > skb->tail)
- goto truncated;
- check = *cksum;
- if (skb->ip_summed != CHECKSUM_HW)
- check = ~check;
- check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, check);
- check = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
- if (skb->ip_summed == CHECKSUM_HW)
- check = ~check;
- *cksum = check;
- break;
- case IPPROTO_UDP:
- cksum = (u16*)&((struct udphdr*)(((char*)iph) + (iph->ihl<<2)))->check;
- if ((u8*)(cksum+1) > skb->tail)
- goto truncated;
- if ((check = *cksum) != 0) {
- check = csum_tcpudp_magic(iph->saddr, iph->daddr, 0, 0, ~check);
- check = csum_tcpudp_magic(~osaddr, ~odaddr, 0, 0, ~check);
- *cksum = check ? : 0xFFFF;
- }
- break;
- case IPPROTO_ICMP:
- {
- struct icmphdr *icmph = (struct icmphdr*)((char*)iph + (iph->ihl<<2));
- struct iphdr *ciph;
- u32 idaddr, isaddr;
- int updated;
-
- if ((icmph->type != ICMP_DEST_UNREACH) &&
- (icmph->type != ICMP_TIME_EXCEEDED) &&
- (icmph->type != ICMP_PARAMETERPROB))
- break;
-
- ciph = (struct iphdr *) (icmph + 1);
-
- if ((u8*)(ciph+1) > skb->tail)
- goto truncated;
-
- isaddr = ciph->saddr;
- idaddr = ciph->daddr;
- updated = 0;
-
- if (rt->rt_flags&RTCF_DNAT && ciph->saddr == odaddr) {
- ciph->saddr = iph->daddr;
- updated = 1;
- }
- if (rt->rt_flags&RTCF_SNAT) {
- if (ciph->daddr != osaddr) {
- struct fib_result res;
- unsigned flags = 0;
- struct flowi fl = {
- .iif = skb->dev->ifindex,
- .nl_u =
- { .ip4_u =
- { .daddr = ciph->saddr,
- .saddr = ciph->daddr,
-#ifdef CONFIG_IP_ROUTE_TOS
- .tos = RT_TOS(ciph->tos)
-#endif
- } },
- .proto = ciph->protocol };
-
- /* Use fib_lookup() until we get our own
- * hash table of NATed hosts -- Rani
- */
- if (fib_lookup(&fl, &res) == 0) {
- if (res.r) {
- ciph->daddr = fib_rules_policy(ciph->daddr, &res, &flags);
- if (ciph->daddr != idaddr)
- updated = 1;
- }
- fib_res_put(&res);
- }
- } else {
- ciph->daddr = iph->saddr;
- updated = 1;
- }
- }
- if (updated) {
- cksum = &icmph->checksum;
- /* Using tcpudp primitive. Why not? */
- check = csum_tcpudp_magic(ciph->saddr, ciph->daddr, 0, 0, ~(*cksum));
- *cksum = csum_tcpudp_magic(~isaddr, ~idaddr, 0, 0, ~check);
- }
- break;
- }
- default:
- break;
- }
- }
- return NET_RX_SUCCESS;
-
-truncated:
- /* should be return NET_RX_BAD; */
- return -EINVAL;
-}