diff --git a/[refs] b/[refs] index 054857b9d369..cef958b8b5d0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: ab8d64d7d4ea49cf664ca5562263a8ba78f4541e +refs/heads/master: d8e7b2b3ac5319fcee616488c628c2bbe7e2937b diff --git a/trunk/Documentation/cgroups/cgroups.txt b/trunk/Documentation/cgroups/cgroups.txt index 455d4e6d346d..0b33bfe7dde9 100644 --- a/trunk/Documentation/cgroups/cgroups.txt +++ b/trunk/Documentation/cgroups/cgroups.txt @@ -227,7 +227,14 @@ as the path relative to the root of the cgroup file system. Each cgroup is represented by a directory in the cgroup file system containing the following files describing that cgroup: - - tasks: list of tasks (by pid) attached to that cgroup + - tasks: list of tasks (by pid) attached to that cgroup. This list + is not guaranteed to be sorted. Writing a thread id into this file + moves the thread into this cgroup. + - cgroup.procs: list of tgids in the cgroup. This list is not + guaranteed to be sorted or free of duplicate tgids, and userspace + should sort/uniquify the list if this property is required. + Writing a tgid into this file moves all threads with that tgid into + this cgroup. - notify_on_release flag: run the release agent on exit? - release_agent: the path to use for release notifications (this file exists in the top cgroup only) @@ -374,7 +381,7 @@ Now you want to do something with this cgroup. In this directory you can find several files: # ls -notify_on_release tasks +cgroup.procs notify_on_release tasks (plus whatever files added by the attached subsystems) Now attach your shell to this cgroup: diff --git a/trunk/Documentation/isdn/INTERFACE.CAPI b/trunk/Documentation/isdn/INTERFACE.CAPI index 686e107923ec..5fe8de5cc727 100644 --- a/trunk/Documentation/isdn/INTERFACE.CAPI +++ b/trunk/Documentation/isdn/INTERFACE.CAPI @@ -60,10 +60,9 @@ open() operation on regular files or character devices. After a successful return from register_appl(), CAPI messages from the application may be passed to the driver for the device via calls to the -send_message() callback function. The CAPI message to send is stored in the -data portion of an skb. Conversely, the driver may call Kernel CAPI's -capi_ctr_handle_message() function to pass a received CAPI message to Kernel -CAPI for forwarding to an application, specifying its ApplID. +send_message() callback function. Conversely, the driver may call Kernel +CAPI's capi_ctr_handle_message() function to pass a received CAPI message to +Kernel CAPI for forwarding to an application, specifying its ApplID. Deregistration requests (CAPI operation CAPI_RELEASE) from applications are forwarded as calls to the release_appl() callback function, passing the same @@ -142,6 +141,7 @@ u16 (*send_message)(struct capi_ctr *ctrlr, struct sk_buff *skb) to accepting or queueing the message. Errors occurring during the actual processing of the message should be signaled with an appropriate reply message. + May be called in process or interrupt context. Calls to this function are not serialized by Kernel CAPI, ie. it must be prepared to be re-entered. @@ -154,7 +154,8 @@ read_proc_t *ctr_read_proc system entry, /proc/capi/controllers/; will be called with a pointer to the device's capi_ctr structure as the last (data) argument -Note: Callback functions are never called in interrupt context. +Note: Callback functions except send_message() are never called in interrupt +context. - to be filled in before calling capi_ctr_ready(): @@ -171,14 +172,40 @@ u8 serial[CAPI_SERIAL_LEN] value to return for CAPI_GET_SERIAL -4.3 The _cmsg Structure +4.3 SKBs + +CAPI messages are passed between Kernel CAPI and the driver via send_message() +and capi_ctr_handle_message(), stored in the data portion of a socket buffer +(skb). Each skb contains a single CAPI message coded according to the CAPI 2.0 +standard. + +For the data transfer messages, DATA_B3_REQ and DATA_B3_IND, the actual +payload data immediately follows the CAPI message itself within the same skb. +The Data and Data64 parameters are not used for processing. The Data64 +parameter may be omitted by setting the length field of the CAPI message to 22 +instead of 30. + + +4.4 The _cmsg Structure (declared in ) The _cmsg structure stores the contents of a CAPI 2.0 message in an easily -accessible form. It contains members for all possible CAPI 2.0 parameters, of -which only those appearing in the message type currently being processed are -actually used. Unused members should be set to zero. +accessible form. It contains members for all possible CAPI 2.0 parameters, +including subparameters of the Additional Info and B Protocol structured +parameters, with the following exceptions: + +* second Calling party number (CONNECT_IND) + +* Data64 (DATA_B3_REQ and DATA_B3_IND) + +* Sending complete (subparameter of Additional Info, CONNECT_REQ and INFO_REQ) + +* Global Configuration (subparameter of B Protocol, CONNECT_REQ, CONNECT_RESP + and SELECT_B_PROTOCOL_REQ) + +Only those parameters appearing in the message type currently being processed +are actually used. Unused members should be set to zero. Members are named after the CAPI 2.0 standard names of the parameters they represent. See for the exact spelling. Member data @@ -190,18 +217,19 @@ u16 for CAPI parameters of type 'word' u32 for CAPI parameters of type 'dword' -_cstruct for CAPI parameters of type 'struct' not containing any - variably-sized (struct) subparameters (eg. 'Called Party Number') +_cstruct for CAPI parameters of type 'struct' The member is a pointer to a buffer containing the parameter in CAPI encoding (length + content). It may also be NULL, which will be taken to represent an empty (zero length) parameter. + Subparameters are stored in encoded form within the content part. -_cmstruct for CAPI parameters of type 'struct' containing 'struct' - subparameters ('Additional Info' and 'B Protocol') +_cmstruct alternative representation for CAPI parameters of type 'struct' + (used only for the 'Additional Info' and 'B Protocol' parameters) The representation is a single byte containing one of the values: - CAPI_DEFAULT: the parameter is empty - CAPI_COMPOSE: the values of the subparameters are stored - individually in the corresponding _cmsg structure members + CAPI_DEFAULT: The parameter is empty/absent. + CAPI_COMPOSE: The parameter is present. + Subparameter values are stored individually in the corresponding + _cmsg structure members. Functions capi_cmsg2message() and capi_message2cmsg() are provided to convert messages between their transport encoding described in the CAPI 2.0 standard @@ -297,3 +325,26 @@ char *capi_cmd2str(u8 Command, u8 Subcommand) be NULL if the command/subcommand is not one of those defined in the CAPI 2.0 standard. + +7. Debugging + +The module kernelcapi has a module parameter showcapimsgs controlling some +debugging output produced by the module. It can only be set when the module is +loaded, via a parameter "showcapimsgs=" to the modprobe command, either on +the command line or in the configuration file. + +If the lowest bit of showcapimsgs is set, kernelcapi logs controller and +application up and down events. + +In addition, every registered CAPI controller has an associated traceflag +parameter controlling how CAPI messages sent from and to tha controller are +logged. The traceflag parameter is initialized with the value of the +showcapimsgs parameter when the controller is registered, but can later be +changed via the MANUFACTURER_REQ command KCAPI_CMD_TRACE. + +If the value of traceflag is non-zero, CAPI messages are logged. +DATA_B3 messages are only logged if the value of traceflag is > 2. + +If the lowest bit of traceflag is set, only the command/subcommand and message +length are logged. Otherwise, kernelcapi logs a readable representation of +the entire message. diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 6fa7292947e5..9107b387e91f 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -671,6 +671,7 @@ and is between 256 and 4096 characters. It is defined in the file earlyprintk= [X86,SH,BLACKFIN] earlyprintk=vga earlyprintk=serial[,ttySn[,baudrate]] + earlyprintk=ttySn[,baudrate] earlyprintk=dbgp[debugController#] Append ",keep" to not disable it when the real console diff --git a/trunk/Documentation/networking/pktgen.txt b/trunk/Documentation/networking/pktgen.txt index c6cf4a3c16e0..61bb645d50e0 100644 --- a/trunk/Documentation/networking/pktgen.txt +++ b/trunk/Documentation/networking/pktgen.txt @@ -90,6 +90,11 @@ Examples: pgset "dstmac 00:00:00:00:00:00" sets MAC destination address pgset "srcmac 00:00:00:00:00:00" sets MAC source address + pgset "queue_map_min 0" Sets the min value of tx queue interval + pgset "queue_map_max 7" Sets the max value of tx queue interval, for multiqueue devices + To select queue 1 of a given device, + use queue_map_min=1 and queue_map_max=1 + pgset "src_mac_count 1" Sets the number of MACs we'll range through. The 'minimum' MAC is what you set with srcmac. @@ -101,6 +106,9 @@ Examples: IPDST_RND, UDPSRC_RND, UDPDST_RND, MACSRC_RND, MACDST_RND MPLS_RND, VID_RND, SVID_RND + QUEUE_MAP_RND # queue map random + QUEUE_MAP_CPU # queue map mirrors smp_processor_id() + pgset "udp_src_min 9" set UDP source port min, If < udp_src_max, then cycle through the port range. diff --git a/trunk/Documentation/vm/ksm.txt b/trunk/Documentation/vm/ksm.txt index 72a22f65960e..262d8e6793a3 100644 --- a/trunk/Documentation/vm/ksm.txt +++ b/trunk/Documentation/vm/ksm.txt @@ -52,15 +52,15 @@ The KSM daemon is controlled by sysfs files in /sys/kernel/mm/ksm/, readable by all but writable only by root: max_kernel_pages - set to maximum number of kernel pages that KSM may use - e.g. "echo 2000 > /sys/kernel/mm/ksm/max_kernel_pages" + e.g. "echo 100000 > /sys/kernel/mm/ksm/max_kernel_pages" Value 0 imposes no limit on the kernel pages KSM may use; but note that any process using MADV_MERGEABLE can cause KSM to allocate these pages, unswappable until it exits. - Default: 2000 (chosen for demonstration purposes) + Default: quarter of memory (chosen to not pin too much) pages_to_scan - how many present pages to scan before ksmd goes to sleep - e.g. "echo 200 > /sys/kernel/mm/ksm/pages_to_scan" - Default: 200 (chosen for demonstration purposes) + e.g. "echo 100 > /sys/kernel/mm/ksm/pages_to_scan" + Default: 100 (chosen for demonstration purposes) sleep_millisecs - how many milliseconds ksmd should sleep before next scan e.g. "echo 20 > /sys/kernel/mm/ksm/sleep_millisecs" @@ -70,7 +70,8 @@ run - set 0 to stop ksmd from running but keep merged pages, set 1 to run ksmd e.g. "echo 1 > /sys/kernel/mm/ksm/run", set 2 to stop ksmd and unmerge all pages currently merged, but leave mergeable areas registered for next run - Default: 1 (for immediate use by apps which register) + Default: 0 (must be changed to 1 to activate KSM, + except if CONFIG_SYSFS is disabled) The effectiveness of KSM and MADV_MERGEABLE is shown in /sys/kernel/mm/ksm/: @@ -86,4 +87,4 @@ pages_volatile embraces several different kinds of activity, but a high proportion there would also indicate poor use of madvise MADV_MERGEABLE. Izik Eidus, -Hugh Dickins, 30 July 2009 +Hugh Dickins, 24 Sept 2009 diff --git a/trunk/Documentation/vm/page-types.c b/trunk/Documentation/vm/page-types.c index fa1a30d9e9d5..3ec4f2a22585 100644 --- a/trunk/Documentation/vm/page-types.c +++ b/trunk/Documentation/vm/page-types.c @@ -2,7 +2,10 @@ * page-types: Tool for querying page flags * * Copyright (C) 2009 Intel corporation - * Copyright (C) 2009 Wu Fengguang + * + * Authors: Wu Fengguang + * + * Released under the General Public License (GPL). */ #define _LARGEFILE64_SOURCE @@ -69,7 +72,9 @@ #define KPF_COMPOUND_TAIL 16 #define KPF_HUGE 17 #define KPF_UNEVICTABLE 18 +#define KPF_HWPOISON 19 #define KPF_NOPAGE 20 +#define KPF_KSM 21 /* [32-] kernel hacking assistances */ #define KPF_RESERVED 32 @@ -116,7 +121,9 @@ static char *page_flag_names[] = { [KPF_COMPOUND_TAIL] = "T:compound_tail", [KPF_HUGE] = "G:huge", [KPF_UNEVICTABLE] = "u:unevictable", + [KPF_HWPOISON] = "X:hwpoison", [KPF_NOPAGE] = "n:nopage", + [KPF_KSM] = "x:ksm", [KPF_RESERVED] = "r:reserved", [KPF_MLOCKED] = "m:mlocked", @@ -152,9 +159,6 @@ static unsigned long opt_size[MAX_ADDR_RANGES]; static int nr_vmas; static unsigned long pg_start[MAX_VMAS]; static unsigned long pg_end[MAX_VMAS]; -static unsigned long voffset; - -static int pagemap_fd; #define MAX_BIT_FILTERS 64 static int nr_bit_filters; @@ -163,9 +167,16 @@ static uint64_t opt_bits[MAX_BIT_FILTERS]; static int page_size; -#define PAGES_BATCH (64 << 10) /* 64k pages */ +static int pagemap_fd; static int kpageflags_fd; +static int opt_hwpoison; +static int opt_unpoison; + +static char *hwpoison_debug_fs = "/debug/hwpoison"; +static int hwpoison_inject_fd; +static int hwpoison_forget_fd; + #define HASH_SHIFT 13 #define HASH_SIZE (1 << HASH_SHIFT) #define HASH_MASK (HASH_SIZE - 1) @@ -207,6 +218,74 @@ static void fatal(const char *x, ...) exit(EXIT_FAILURE); } +int checked_open(const char *pathname, int flags) +{ + int fd = open(pathname, flags); + + if (fd < 0) { + perror(pathname); + exit(EXIT_FAILURE); + } + + return fd; +} + +/* + * pagemap/kpageflags routines + */ + +static unsigned long do_u64_read(int fd, char *name, + uint64_t *buf, + unsigned long index, + unsigned long count) +{ + long bytes; + + if (index > ULONG_MAX / 8) + fatal("index overflow: %lu\n", index); + + if (lseek(fd, index * 8, SEEK_SET) < 0) { + perror(name); + exit(EXIT_FAILURE); + } + + bytes = read(fd, buf, count * 8); + if (bytes < 0) { + perror(name); + exit(EXIT_FAILURE); + } + if (bytes % 8) + fatal("partial read: %lu bytes\n", bytes); + + return bytes / 8; +} + +static unsigned long kpageflags_read(uint64_t *buf, + unsigned long index, + unsigned long pages) +{ + return do_u64_read(kpageflags_fd, PROC_KPAGEFLAGS, buf, index, pages); +} + +static unsigned long pagemap_read(uint64_t *buf, + unsigned long index, + unsigned long pages) +{ + return do_u64_read(pagemap_fd, "/proc/pid/pagemap", buf, index, pages); +} + +static unsigned long pagemap_pfn(uint64_t val) +{ + unsigned long pfn; + + if (val & PM_PRESENT) + pfn = PM_PFRAME(val); + else + pfn = 0; + + return pfn; +} + /* * page flag names @@ -255,7 +334,8 @@ static char *page_flag_longname(uint64_t flags) * page list and summary */ -static void show_page_range(unsigned long offset, uint64_t flags) +static void show_page_range(unsigned long voffset, + unsigned long offset, uint64_t flags) { static uint64_t flags0; static unsigned long voff; @@ -281,7 +361,8 @@ static void show_page_range(unsigned long offset, uint64_t flags) count = 1; } -static void show_page(unsigned long offset, uint64_t flags) +static void show_page(unsigned long voffset, + unsigned long offset, uint64_t flags) { if (opt_pid) printf("%lx\t", voffset); @@ -362,6 +443,62 @@ static uint64_t well_known_flags(uint64_t flags) return flags; } +static uint64_t kpageflags_flags(uint64_t flags) +{ + flags = expand_overloaded_flags(flags); + + if (!opt_raw) + flags = well_known_flags(flags); + + return flags; +} + +/* + * page actions + */ + +static void prepare_hwpoison_fd(void) +{ + char buf[100]; + + if (opt_hwpoison && !hwpoison_inject_fd) { + sprintf(buf, "%s/corrupt-pfn", hwpoison_debug_fs); + hwpoison_inject_fd = checked_open(buf, O_WRONLY); + } + + if (opt_unpoison && !hwpoison_forget_fd) { + sprintf(buf, "%s/renew-pfn", hwpoison_debug_fs); + hwpoison_forget_fd = checked_open(buf, O_WRONLY); + } +} + +static int hwpoison_page(unsigned long offset) +{ + char buf[100]; + int len; + + len = sprintf(buf, "0x%lx\n", offset); + len = write(hwpoison_inject_fd, buf, len); + if (len < 0) { + perror("hwpoison inject"); + return len; + } + return 0; +} + +static int unpoison_page(unsigned long offset) +{ + char buf[100]; + int len; + + len = sprintf(buf, "0x%lx\n", offset); + len = write(hwpoison_forget_fd, buf, len); + if (len < 0) { + perror("hwpoison forget"); + return len; + } + return 0; +} /* * page frame walker @@ -394,104 +531,83 @@ static int hash_slot(uint64_t flags) exit(EXIT_FAILURE); } -static void add_page(unsigned long offset, uint64_t flags) +static void add_page(unsigned long voffset, + unsigned long offset, uint64_t flags) { - flags = expand_overloaded_flags(flags); - - if (!opt_raw) - flags = well_known_flags(flags); + flags = kpageflags_flags(flags); if (!bit_mask_ok(flags)) return; + if (opt_hwpoison) + hwpoison_page(offset); + if (opt_unpoison) + unpoison_page(offset); + if (opt_list == 1) - show_page_range(offset, flags); + show_page_range(voffset, offset, flags); else if (opt_list == 2) - show_page(offset, flags); + show_page(voffset, offset, flags); nr_pages[hash_slot(flags)]++; total_pages++; } -static void walk_pfn(unsigned long index, unsigned long count) +#define KPAGEFLAGS_BATCH (64 << 10) /* 64k pages */ +static void walk_pfn(unsigned long voffset, + unsigned long index, + unsigned long count) { + uint64_t buf[KPAGEFLAGS_BATCH]; unsigned long batch; - unsigned long n; + unsigned long pages; unsigned long i; - if (index > ULONG_MAX / KPF_BYTES) - fatal("index overflow: %lu\n", index); - - lseek(kpageflags_fd, index * KPF_BYTES, SEEK_SET); - while (count) { - uint64_t kpageflags_buf[KPF_BYTES * PAGES_BATCH]; - - batch = min_t(unsigned long, count, PAGES_BATCH); - n = read(kpageflags_fd, kpageflags_buf, batch * KPF_BYTES); - if (n == 0) + batch = min_t(unsigned long, count, KPAGEFLAGS_BATCH); + pages = kpageflags_read(buf, index, batch); + if (pages == 0) break; - if (n < 0) { - perror(PROC_KPAGEFLAGS); - exit(EXIT_FAILURE); - } - if (n % KPF_BYTES != 0) - fatal("partial read: %lu bytes\n", n); - n = n / KPF_BYTES; + for (i = 0; i < pages; i++) + add_page(voffset + i, index + i, buf[i]); - for (i = 0; i < n; i++) - add_page(index + i, kpageflags_buf[i]); - - index += batch; - count -= batch; + index += pages; + count -= pages; } } - -#define PAGEMAP_BATCH 4096 -static unsigned long task_pfn(unsigned long pgoff) +#define PAGEMAP_BATCH (64 << 10) +static void walk_vma(unsigned long index, unsigned long count) { - static uint64_t buf[PAGEMAP_BATCH]; - static unsigned long start; - static long count; - uint64_t pfn; + uint64_t buf[PAGEMAP_BATCH]; + unsigned long batch; + unsigned long pages; + unsigned long pfn; + unsigned long i; - if (pgoff < start || pgoff >= start + count) { - if (lseek64(pagemap_fd, - (uint64_t)pgoff * PM_ENTRY_BYTES, - SEEK_SET) < 0) { - perror("pagemap seek"); - exit(EXIT_FAILURE); - } - count = read(pagemap_fd, buf, sizeof(buf)); - if (count == 0) - return 0; - if (count < 0) { - perror("pagemap read"); - exit(EXIT_FAILURE); - } - if (count % PM_ENTRY_BYTES) { - fatal("pagemap read not aligned.\n"); - exit(EXIT_FAILURE); - } - count /= PM_ENTRY_BYTES; - start = pgoff; - } + while (count) { + batch = min_t(unsigned long, count, PAGEMAP_BATCH); + pages = pagemap_read(buf, index, batch); + if (pages == 0) + break; - pfn = buf[pgoff - start]; - if (pfn & PM_PRESENT) - pfn = PM_PFRAME(pfn); - else - pfn = 0; + for (i = 0; i < pages; i++) { + pfn = pagemap_pfn(buf[i]); + if (pfn) + walk_pfn(index + i, pfn, 1); + } - return pfn; + index += pages; + count -= pages; + } } static void walk_task(unsigned long index, unsigned long count) { - int i = 0; const unsigned long end = index + count; + unsigned long start; + int i = 0; while (index < end) { @@ -501,15 +617,11 @@ static void walk_task(unsigned long index, unsigned long count) if (pg_start[i] >= end) return; - voffset = max_t(unsigned long, pg_start[i], index); - index = min_t(unsigned long, pg_end[i], end); + start = max_t(unsigned long, pg_start[i], index); + index = min_t(unsigned long, pg_end[i], end); - assert(voffset < index); - for (; voffset < index; voffset++) { - unsigned long pfn = task_pfn(voffset); - if (pfn) - walk_pfn(pfn, 1); - } + assert(start < index); + walk_vma(start, index - start); } } @@ -527,18 +639,14 @@ static void walk_addr_ranges(void) { int i; - kpageflags_fd = open(PROC_KPAGEFLAGS, O_RDONLY); - if (kpageflags_fd < 0) { - perror(PROC_KPAGEFLAGS); - exit(EXIT_FAILURE); - } + kpageflags_fd = checked_open(PROC_KPAGEFLAGS, O_RDONLY); if (!nr_addr_ranges) add_addr_range(0, ULONG_MAX); for (i = 0; i < nr_addr_ranges; i++) if (!opt_pid) - walk_pfn(opt_offset[i], opt_size[i]); + walk_pfn(0, opt_offset[i], opt_size[i]); else walk_task(opt_offset[i], opt_size[i]); @@ -575,6 +683,8 @@ static void usage(void) " -l|--list Show page details in ranges\n" " -L|--list-each Show page details one by one\n" " -N|--no-summary Don't show summay info\n" +" -X|--hwpoison hwpoison pages\n" +" -x|--unpoison unpoison pages\n" " -h|--help Show this usage message\n" "addr-spec:\n" " N one page at offset N (unit: pages)\n" @@ -624,11 +734,7 @@ static void parse_pid(const char *str) opt_pid = parse_number(str); sprintf(buf, "/proc/%d/pagemap", opt_pid); - pagemap_fd = open(buf, O_RDONLY); - if (pagemap_fd < 0) { - perror(buf); - exit(EXIT_FAILURE); - } + pagemap_fd = checked_open(buf, O_RDONLY); sprintf(buf, "/proc/%d/maps", opt_pid); file = fopen(buf, "r"); @@ -788,6 +894,8 @@ static struct option opts[] = { { "list" , 0, NULL, 'l' }, { "list-each" , 0, NULL, 'L' }, { "no-summary", 0, NULL, 'N' }, + { "hwpoison" , 0, NULL, 'X' }, + { "unpoison" , 0, NULL, 'x' }, { "help" , 0, NULL, 'h' }, { NULL , 0, NULL, 0 } }; @@ -799,7 +907,7 @@ int main(int argc, char *argv[]) page_size = getpagesize(); while ((c = getopt_long(argc, argv, - "rp:f:a:b:lLNh", opts, NULL)) != -1) { + "rp:f:a:b:lLNXxh", opts, NULL)) != -1) { switch (c) { case 'r': opt_raw = 1; @@ -825,6 +933,14 @@ int main(int argc, char *argv[]) case 'N': opt_no_summary = 1; break; + case 'X': + opt_hwpoison = 1; + prepare_hwpoison_fd(); + break; + case 'x': + opt_unpoison = 1; + prepare_hwpoison_fd(); + break; case 'h': usage(); exit(0); @@ -844,7 +960,7 @@ int main(int argc, char *argv[]) walk_addr_ranges(); if (opt_list == 1) - show_page_range(0, 0); /* drain the buffer */ + show_page_range(0, 0, 0); /* drain the buffer */ if (opt_no_summary) return 0; diff --git a/trunk/Documentation/vm/pagemap.txt b/trunk/Documentation/vm/pagemap.txt index 600a304a828c..df09b9650a81 100644 --- a/trunk/Documentation/vm/pagemap.txt +++ b/trunk/Documentation/vm/pagemap.txt @@ -57,7 +57,9 @@ There are three components to pagemap: 16. COMPOUND_TAIL 16. HUGE 18. UNEVICTABLE + 19. HWPOISON 20. NOPAGE + 21. KSM Short descriptions to the page flags: @@ -86,9 +88,15 @@ Short descriptions to the page flags: 17. HUGE this is an integral part of a HugeTLB page +19. HWPOISON + hardware detected memory corruption on this page: don't touch the data! + 20. NOPAGE no page frame exists at the requested address +21. KSM + identical memory pages dynamically shared between one or more processes + [IO related page flags] 1. ERROR IO error occurred 3. UPTODATE page has up-to-date data diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 09a2028bab7f..e1da925b38c8 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -3643,6 +3643,13 @@ F: Documentation/blockdev/nbd.txt F: drivers/block/nbd.c F: include/linux/nbd.h +NETWORK DROP MONITOR +M: Neil Horman +L: netdev@vger.kernel.org +S: Maintained +W: https://fedorahosted.org/dropwatch/ +F: net/core/drop_monitor.c + NETWORKING [GENERAL] M: "David S. Miller" L: netdev@vger.kernel.org @@ -3973,6 +3980,7 @@ F: drivers/block/paride/ PARISC ARCHITECTURE M: Kyle McMartin M: Helge Deller +M: "James E.J. Bottomley" L: linux-parisc@vger.kernel.org W: http://www.parisc-linux.org/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/kyle/parisc-2.6.git diff --git a/trunk/arch/m68knommu/kernel/asm-offsets.c b/trunk/arch/m68knommu/kernel/asm-offsets.c index 594ee0e657fe..9a8876f715d8 100644 --- a/trunk/arch/m68knommu/kernel/asm-offsets.c +++ b/trunk/arch/m68knommu/kernel/asm-offsets.c @@ -45,25 +45,25 @@ int main(void) DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate)); /* offsets into the pt_regs */ - DEFINE(PT_D0, offsetof(struct pt_regs, d0)); - DEFINE(PT_ORIG_D0, offsetof(struct pt_regs, orig_d0)); - DEFINE(PT_D1, offsetof(struct pt_regs, d1)); - DEFINE(PT_D2, offsetof(struct pt_regs, d2)); - DEFINE(PT_D3, offsetof(struct pt_regs, d3)); - DEFINE(PT_D4, offsetof(struct pt_regs, d4)); - DEFINE(PT_D5, offsetof(struct pt_regs, d5)); - DEFINE(PT_A0, offsetof(struct pt_regs, a0)); - DEFINE(PT_A1, offsetof(struct pt_regs, a1)); - DEFINE(PT_A2, offsetof(struct pt_regs, a2)); - DEFINE(PT_PC, offsetof(struct pt_regs, pc)); - DEFINE(PT_SR, offsetof(struct pt_regs, sr)); + DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0)); + DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0)); + DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1)); + DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2)); + DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3)); + DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4)); + DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5)); + DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0)); + DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1)); + DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2)); + DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc)); + DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr)); #ifdef CONFIG_COLDFIRE /* bitfields are a bit difficult */ - DEFINE(PT_FORMATVEC, offsetof(struct pt_regs, sr) - 2); + DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, sr) - 2); #else /* bitfields are a bit difficult */ - DEFINE(PT_VECTOR, offsetof(struct pt_regs, pc) + 4); + DEFINE(PT_OFF_VECTOR, offsetof(struct pt_regs, pc) + 4); #endif /* signal defines */ diff --git a/trunk/arch/m68knommu/kernel/entry.S b/trunk/arch/m68knommu/kernel/entry.S index f56faa5c9cd9..56043ade3941 100644 --- a/trunk/arch/m68knommu/kernel/entry.S +++ b/trunk/arch/m68knommu/kernel/entry.S @@ -46,7 +46,7 @@ ENTRY(buserr) SAVE_ALL moveq #-1,%d0 - movel %d0,%sp@(PT_ORIG_D0) + movel %d0,%sp@(PT_OFF_ORIG_D0) movel %sp,%sp@- /* stack frame pointer argument */ jsr buserr_c addql #4,%sp @@ -55,7 +55,7 @@ ENTRY(buserr) ENTRY(trap) SAVE_ALL moveq #-1,%d0 - movel %d0,%sp@(PT_ORIG_D0) + movel %d0,%sp@(PT_OFF_ORIG_D0) movel %sp,%sp@- /* stack frame pointer argument */ jsr trap_c addql #4,%sp @@ -67,7 +67,7 @@ ENTRY(trap) ENTRY(dbginterrupt) SAVE_ALL moveq #-1,%d0 - movel %d0,%sp@(PT_ORIG_D0) + movel %d0,%sp@(PT_OFF_ORIG_D0) movel %sp,%sp@- /* stack frame pointer argument */ jsr dbginterrupt_c addql #4,%sp diff --git a/trunk/arch/m68knommu/mm/init.c b/trunk/arch/m68knommu/mm/init.c index b1703c67a4f1..f3236d0b522d 100644 --- a/trunk/arch/m68knommu/mm/init.c +++ b/trunk/arch/m68knommu/mm/init.c @@ -162,7 +162,7 @@ void free_initrd_mem(unsigned long start, unsigned long end) totalram_pages++; pages++; } - printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages); + printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages * (PAGE_SIZE / 1024)); } #endif diff --git a/trunk/arch/m68knommu/platform/5206e/config.c b/trunk/arch/m68knommu/platform/5206e/config.c index 0f41ba82a3b5..942397984c66 100644 --- a/trunk/arch/m68knommu/platform/5206e/config.c +++ b/trunk/arch/m68knommu/platform/5206e/config.c @@ -17,7 +17,6 @@ #include #include #include -#include /***************************************************************************/ diff --git a/trunk/arch/m68knommu/platform/68328/entry.S b/trunk/arch/m68knommu/platform/68328/entry.S index b1aef72f3baf..9d80d2c42866 100644 --- a/trunk/arch/m68knommu/platform/68328/entry.S +++ b/trunk/arch/m68knommu/platform/68328/entry.S @@ -39,17 +39,17 @@ .globl inthandler7 badsys: - movel #-ENOSYS,%sp@(PT_D0) + movel #-ENOSYS,%sp@(PT_OFF_D0) jra ret_from_exception do_trace: - movel #-ENOSYS,%sp@(PT_D0) /* needed for strace*/ + movel #-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/ subql #4,%sp SAVE_SWITCH_STACK jbsr syscall_trace RESTORE_SWITCH_STACK addql #4,%sp - movel %sp@(PT_ORIG_D0),%d1 + movel %sp@(PT_OFF_ORIG_D0),%d1 movel #-ENOSYS,%d0 cmpl #NR_syscalls,%d1 jcc 1f @@ -57,7 +57,7 @@ do_trace: lea sys_call_table, %a0 jbsr %a0@(%d1) -1: movel %d0,%sp@(PT_D0) /* save the return value */ +1: movel %d0,%sp@(PT_OFF_D0) /* save the return value */ subql #4,%sp /* dummy return address */ SAVE_SWITCH_STACK jbsr syscall_trace @@ -75,7 +75,7 @@ ENTRY(system_call) jbsr set_esp0 addql #4,%sp - movel %sp@(PT_ORIG_D0),%d0 + movel %sp@(PT_OFF_ORIG_D0),%d0 movel %sp,%d1 /* get thread_info pointer */ andl #-THREAD_SIZE,%d1 @@ -88,10 +88,10 @@ ENTRY(system_call) lea sys_call_table,%a0 movel %a0@(%d0), %a0 jbsr %a0@ - movel %d0,%sp@(PT_D0) /* save the return value*/ + movel %d0,%sp@(PT_OFF_D0) /* save the return value*/ ret_from_exception: - btst #5,%sp@(PT_SR) /* check if returning to kernel*/ + btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel*/ jeq Luser_return /* if so, skip resched, signals*/ Lkernel_return: @@ -133,7 +133,7 @@ Lreturn: */ inthandler1: SAVE_ALL - movew %sp@(PT_VECTOR), %d0 + movew %sp@(PT_OFF_VECTOR), %d0 and #0x3ff, %d0 movel %sp,%sp@- @@ -144,7 +144,7 @@ inthandler1: inthandler2: SAVE_ALL - movew %sp@(PT_VECTOR), %d0 + movew %sp@(PT_OFF_VECTOR), %d0 and #0x3ff, %d0 movel %sp,%sp@- @@ -155,7 +155,7 @@ inthandler2: inthandler3: SAVE_ALL - movew %sp@(PT_VECTOR), %d0 + movew %sp@(PT_OFF_VECTOR), %d0 and #0x3ff, %d0 movel %sp,%sp@- @@ -166,7 +166,7 @@ inthandler3: inthandler4: SAVE_ALL - movew %sp@(PT_VECTOR), %d0 + movew %sp@(PT_OFF_VECTOR), %d0 and #0x3ff, %d0 movel %sp,%sp@- @@ -177,7 +177,7 @@ inthandler4: inthandler5: SAVE_ALL - movew %sp@(PT_VECTOR), %d0 + movew %sp@(PT_OFF_VECTOR), %d0 and #0x3ff, %d0 movel %sp,%sp@- @@ -188,7 +188,7 @@ inthandler5: inthandler6: SAVE_ALL - movew %sp@(PT_VECTOR), %d0 + movew %sp@(PT_OFF_VECTOR), %d0 and #0x3ff, %d0 movel %sp,%sp@- @@ -199,7 +199,7 @@ inthandler6: inthandler7: SAVE_ALL - movew %sp@(PT_VECTOR), %d0 + movew %sp@(PT_OFF_VECTOR), %d0 and #0x3ff, %d0 movel %sp,%sp@- @@ -210,7 +210,7 @@ inthandler7: inthandler: SAVE_ALL - movew %sp@(PT_VECTOR), %d0 + movew %sp@(PT_OFF_VECTOR), %d0 and #0x3ff, %d0 movel %sp,%sp@- @@ -224,7 +224,7 @@ ret_from_interrupt: 2: RESTORE_ALL 1: - moveb %sp@(PT_SR), %d0 + moveb %sp@(PT_OFF_SR), %d0 and #7, %d0 jhi 2b diff --git a/trunk/arch/m68knommu/platform/68360/entry.S b/trunk/arch/m68knommu/platform/68360/entry.S index 55dfefe38642..6d3460a39cac 100644 --- a/trunk/arch/m68knommu/platform/68360/entry.S +++ b/trunk/arch/m68knommu/platform/68360/entry.S @@ -35,17 +35,17 @@ .globl inthandler badsys: - movel #-ENOSYS,%sp@(PT_D0) + movel #-ENOSYS,%sp@(PT_OFF_D0) jra ret_from_exception do_trace: - movel #-ENOSYS,%sp@(PT_D0) /* needed for strace*/ + movel #-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/ subql #4,%sp SAVE_SWITCH_STACK jbsr syscall_trace RESTORE_SWITCH_STACK addql #4,%sp - movel %sp@(PT_ORIG_D0),%d1 + movel %sp@(PT_OFF_ORIG_D0),%d1 movel #-ENOSYS,%d0 cmpl #NR_syscalls,%d1 jcc 1f @@ -53,7 +53,7 @@ do_trace: lea sys_call_table, %a0 jbsr %a0@(%d1) -1: movel %d0,%sp@(PT_D0) /* save the return value */ +1: movel %d0,%sp@(PT_OFF_D0) /* save the return value */ subql #4,%sp /* dummy return address */ SAVE_SWITCH_STACK jbsr syscall_trace @@ -79,10 +79,10 @@ ENTRY(system_call) lea sys_call_table,%a0 movel %a0@(%d0), %a0 jbsr %a0@ - movel %d0,%sp@(PT_D0) /* save the return value*/ + movel %d0,%sp@(PT_OFF_D0) /* save the return value*/ ret_from_exception: - btst #5,%sp@(PT_SR) /* check if returning to kernel*/ + btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel*/ jeq Luser_return /* if so, skip resched, signals*/ Lkernel_return: @@ -124,7 +124,7 @@ Lreturn: */ inthandler: SAVE_ALL - movew %sp@(PT_VECTOR), %d0 + movew %sp@(PT_OFF_VECTOR), %d0 and.l #0x3ff, %d0 lsr.l #0x02, %d0 @@ -139,7 +139,7 @@ ret_from_interrupt: 2: RESTORE_ALL 1: - moveb %sp@(PT_SR), %d0 + moveb %sp@(PT_OFF_SR), %d0 and #7, %d0 jhi 2b /* check if we need to do software interrupts */ diff --git a/trunk/arch/m68knommu/platform/coldfire/entry.S b/trunk/arch/m68knommu/platform/coldfire/entry.S index 3b471c0da24a..dd7d591f70ea 100644 --- a/trunk/arch/m68knommu/platform/coldfire/entry.S +++ b/trunk/arch/m68knommu/platform/coldfire/entry.S @@ -81,11 +81,11 @@ ENTRY(system_call) movel %d3,%a0 jbsr %a0@ - movel %d0,%sp@(PT_D0) /* save the return value */ + movel %d0,%sp@(PT_OFF_D0) /* save the return value */ jra ret_from_exception 1: - movel #-ENOSYS,%d2 /* strace needs -ENOSYS in PT_D0 */ - movel %d2,PT_D0(%sp) /* on syscall entry */ + movel #-ENOSYS,%d2 /* strace needs -ENOSYS in PT_OFF_D0 */ + movel %d2,PT_OFF_D0(%sp) /* on syscall entry */ subql #4,%sp SAVE_SWITCH_STACK jbsr syscall_trace @@ -93,7 +93,7 @@ ENTRY(system_call) addql #4,%sp movel %d3,%a0 jbsr %a0@ - movel %d0,%sp@(PT_D0) /* save the return value */ + movel %d0,%sp@(PT_OFF_D0) /* save the return value */ subql #4,%sp /* dummy return address */ SAVE_SWITCH_STACK jbsr syscall_trace @@ -104,7 +104,7 @@ ret_from_signal: ret_from_exception: move #0x2700,%sr /* disable intrs */ - btst #5,%sp@(PT_SR) /* check if returning to kernel */ + btst #5,%sp@(PT_OFF_SR) /* check if returning to kernel */ jeq Luser_return /* if so, skip resched, signals */ #ifdef CONFIG_PREEMPT @@ -142,8 +142,8 @@ Luser_return: Lreturn: move #0x2700,%sr /* disable intrs */ movel sw_usp,%a0 /* get usp */ - movel %sp@(PT_PC),%a0@- /* copy exception program counter */ - movel %sp@(PT_FORMATVEC),%a0@-/* copy exception format/vector/sr */ + movel %sp@(PT_OFF_PC),%a0@- /* copy exception program counter */ + movel %sp@(PT_OFF_FORMATVEC),%a0@- /* copy exception format/vector/sr */ moveml %sp@,%d1-%d5/%a0-%a2 lea %sp@(32),%sp /* space for 8 regs */ movel %sp@+,%d0 @@ -181,9 +181,9 @@ Lsignal_return: ENTRY(inthandler) SAVE_ALL moveq #-1,%d0 - movel %d0,%sp@(PT_ORIG_D0) + movel %d0,%sp@(PT_OFF_ORIG_D0) - movew %sp@(PT_FORMATVEC),%d0 /* put exception # in d0 */ + movew %sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */ andl #0x03fc,%d0 /* mask out vector only */ movel %sp,%sp@- /* push regs arg */ @@ -203,7 +203,7 @@ ENTRY(inthandler) ENTRY(fasthandler) SAVE_LOCAL - movew %sp@(PT_FORMATVEC),%d0 + movew %sp@(PT_OFF_FORMATVEC),%d0 andl #0x03fc,%d0 /* mask out vector only */ movel %sp,%sp@- /* push regs arg */ diff --git a/trunk/arch/microblaze/kernel/entry.S b/trunk/arch/microblaze/kernel/entry.S index acc1f05d1e2c..e3ecb36dd554 100644 --- a/trunk/arch/microblaze/kernel/entry.S +++ b/trunk/arch/microblaze/kernel/entry.S @@ -592,6 +592,8 @@ C_ENTRY(full_exception_trap): nop mfs r7, rfsr; /* save FSR */ nop + mts rfsr, r0; /* Clear sticky fsr */ + nop la r12, r0, full_exception set_vms; rtbd r12, 0; diff --git a/trunk/arch/microblaze/kernel/hw_exception_handler.S b/trunk/arch/microblaze/kernel/hw_exception_handler.S index 6b0288ebccd6..2b86c03aa841 100644 --- a/trunk/arch/microblaze/kernel/hw_exception_handler.S +++ b/trunk/arch/microblaze/kernel/hw_exception_handler.S @@ -384,7 +384,7 @@ handle_other_ex: /* Handle Other exceptions here */ addk r8, r17, r0; /* Load exception address */ bralid r15, full_exception; /* Branch to the handler */ nop; - mts r0, rfsr; /* Clear sticky fsr */ + mts rfsr, r0; /* Clear sticky fsr */ nop /* diff --git a/trunk/arch/microblaze/kernel/process.c b/trunk/arch/microblaze/kernel/process.c index 4201c743cc9f..c592d475b3d8 100644 --- a/trunk/arch/microblaze/kernel/process.c +++ b/trunk/arch/microblaze/kernel/process.c @@ -235,7 +235,9 @@ void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long usp) regs->pc = pc; regs->r1 = usp; regs->pt_mode = 0; +#ifdef CONFIG_MMU regs->msr |= MSR_UMS; +#endif } #ifdef CONFIG_MMU diff --git a/trunk/arch/parisc/Kconfig b/trunk/arch/parisc/Kconfig index f388dc68f605..524d9352f17e 100644 --- a/trunk/arch/parisc/Kconfig +++ b/trunk/arch/parisc/Kconfig @@ -18,6 +18,7 @@ config PARISC select BUG select HAVE_PERF_EVENTS select GENERIC_ATOMIC64 if !64BIT + select HAVE_ARCH_TRACEHOOK help The PA-RISC microprocessor is designed by Hewlett-Packard and used in many of their workstations & servers (HP9000 700 and 800 series, diff --git a/trunk/arch/parisc/include/asm/fixmap.h b/trunk/arch/parisc/include/asm/fixmap.h index de3fe3a18229..6fec4d4a1a18 100644 --- a/trunk/arch/parisc/include/asm/fixmap.h +++ b/trunk/arch/parisc/include/asm/fixmap.h @@ -21,9 +21,9 @@ #define KERNEL_MAP_END (TMPALIAS_MAP_START) #ifndef __ASSEMBLY__ -extern void *vmalloc_start; +extern void *parisc_vmalloc_start; #define PCXL_DMA_MAP_SIZE (8*1024*1024) -#define VMALLOC_START ((unsigned long)vmalloc_start) +#define VMALLOC_START ((unsigned long)parisc_vmalloc_start) #define VMALLOC_END (KERNEL_MAP_END) #endif /*__ASSEMBLY__*/ diff --git a/trunk/arch/parisc/include/asm/hardirq.h b/trunk/arch/parisc/include/asm/hardirq.h index ce93133d5112..0d68184a76cb 100644 --- a/trunk/arch/parisc/include/asm/hardirq.h +++ b/trunk/arch/parisc/include/asm/hardirq.h @@ -1,29 +1,11 @@ /* hardirq.h: PA-RISC hard IRQ support. * * Copyright (C) 2001 Matthew Wilcox - * - * The locking is really quite interesting. There's a cpu-local - * count of how many interrupts are being handled, and a global - * lock. An interrupt can only be serviced if the global lock - * is free. You can't be sure no more interrupts are being - * serviced until you've acquired the lock and then checked - * all the per-cpu interrupt counts are all zero. It's a specialised - * br_lock, and that's exactly how Sparc does it. We don't because - * it's more locking for us. This way is lock-free in the interrupt path. */ #ifndef _PARISC_HARDIRQ_H #define _PARISC_HARDIRQ_H -#include -#include - -typedef struct { - unsigned long __softirq_pending; /* set_bit is used on this */ -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - -void ack_bad_irq(unsigned int irq); +#include #endif /* _PARISC_HARDIRQ_H */ diff --git a/trunk/arch/parisc/include/asm/ptrace.h b/trunk/arch/parisc/include/asm/ptrace.h index 302f68dc889c..aead40b16dd8 100644 --- a/trunk/arch/parisc/include/asm/ptrace.h +++ b/trunk/arch/parisc/include/asm/ptrace.h @@ -59,8 +59,11 @@ void user_enable_block_step(struct task_struct *task); #define user_mode(regs) (((regs)->iaoq[0] & 3) ? 1 : 0) #define user_space(regs) (((regs)->iasq[1] != 0) ? 1 : 0) #define instruction_pointer(regs) ((regs)->iaoq[0] & ~3) +#define user_stack_pointer(regs) ((regs)->gr[30]) unsigned long profile_pc(struct pt_regs *); extern void show_regs(struct pt_regs *); -#endif + + +#endif /* __KERNEL__ */ #endif diff --git a/trunk/arch/parisc/include/asm/syscall.h b/trunk/arch/parisc/include/asm/syscall.h new file mode 100644 index 000000000000..8bdfd2c8c39f --- /dev/null +++ b/trunk/arch/parisc/include/asm/syscall.h @@ -0,0 +1,40 @@ +/* syscall.h */ + +#ifndef _ASM_PARISC_SYSCALL_H_ +#define _ASM_PARISC_SYSCALL_H_ + +#include +#include + +static inline long syscall_get_nr(struct task_struct *tsk, + struct pt_regs *regs) +{ + return regs->gr[20]; +} + +static inline void syscall_get_arguments(struct task_struct *tsk, + struct pt_regs *regs, unsigned int i, + unsigned int n, unsigned long *args) +{ + BUG_ON(i); + + switch (n) { + case 6: + args[5] = regs->gr[21]; + case 5: + args[4] = regs->gr[22]; + case 4: + args[3] = regs->gr[23]; + case 3: + args[2] = regs->gr[24]; + case 2: + args[1] = regs->gr[25]; + case 1: + args[0] = regs->gr[26]; + break; + default: + BUG(); + } +} + +#endif /*_ASM_PARISC_SYSCALL_H_*/ diff --git a/trunk/arch/parisc/include/asm/thread_info.h b/trunk/arch/parisc/include/asm/thread_info.h index ac775a76bff7..7ecc1039cfed 100644 --- a/trunk/arch/parisc/include/asm/thread_info.h +++ b/trunk/arch/parisc/include/asm/thread_info.h @@ -32,6 +32,11 @@ struct thread_info { #define init_thread_info (init_thread_union.thread_info) #define init_stack (init_thread_union.stack) +/* how to get the thread information struct from C */ +#define current_thread_info() ((struct thread_info *)mfctl(30)) + +#endif /* !__ASSEMBLY */ + /* thread information allocation */ #define THREAD_SIZE_ORDER 2 @@ -40,11 +45,6 @@ struct thread_info { #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) #define THREAD_SHIFT (PAGE_SHIFT + THREAD_SIZE_ORDER) -/* how to get the thread information struct from C */ -#define current_thread_info() ((struct thread_info *)mfctl(30)) - -#endif /* !__ASSEMBLY */ - #define PREEMPT_ACTIVE_BIT 28 #define PREEMPT_ACTIVE (1 << PREEMPT_ACTIVE_BIT) @@ -60,6 +60,8 @@ struct thread_info { #define TIF_RESTORE_SIGMASK 6 /* restore saved signal mask */ #define TIF_FREEZE 7 /* is freezing for suspend */ #define TIF_NOTIFY_RESUME 8 /* callback before returning to user */ +#define TIF_SINGLESTEP 9 /* single stepping? */ +#define TIF_BLOCKSTEP 10 /* branch stepping? */ #define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) @@ -69,6 +71,8 @@ struct thread_info { #define _TIF_RESTORE_SIGMASK (1 << TIF_RESTORE_SIGMASK) #define _TIF_FREEZE (1 << TIF_FREEZE) #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) +#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) +#define _TIF_BLOCKSTEP (1 << TIF_BLOCKSTEP) #define _TIF_USER_WORK_MASK (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \ _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK) diff --git a/trunk/arch/parisc/kernel/asm-offsets.c b/trunk/arch/parisc/kernel/asm-offsets.c index 699cf8ef2118..fcd3c707bf12 100644 --- a/trunk/arch/parisc/kernel/asm-offsets.c +++ b/trunk/arch/parisc/kernel/asm-offsets.c @@ -270,8 +270,8 @@ int main(void) DEFINE(DTLB_OFF_COUNT, offsetof(struct pdc_cache_info, dt_off_count)); DEFINE(DTLB_LOOP, offsetof(struct pdc_cache_info, dt_loop)); BLANK(); - DEFINE(PA_BLOCKSTEP_BIT, 31-PT_BLOCKSTEP_BIT); - DEFINE(PA_SINGLESTEP_BIT, 31-PT_SINGLESTEP_BIT); + DEFINE(TIF_BLOCKSTEP_PA_BIT, 31-TIF_BLOCKSTEP); + DEFINE(TIF_SINGLESTEP_PA_BIT, 31-TIF_SINGLESTEP); BLANK(); DEFINE(ASM_PMD_SHIFT, PMD_SHIFT); DEFINE(ASM_PGDIR_SHIFT, PGDIR_SHIFT); diff --git a/trunk/arch/parisc/kernel/entry.S b/trunk/arch/parisc/kernel/entry.S index 8c4712b74dc1..3a44f7f704fa 100644 --- a/trunk/arch/parisc/kernel/entry.S +++ b/trunk/arch/parisc/kernel/entry.S @@ -2047,12 +2047,13 @@ syscall_do_signal: b,n syscall_check_sig syscall_restore: - /* Are we being ptraced? */ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 - ldw TASK_PTRACE(%r1), %r19 - bb,< %r19,31,syscall_restore_rfi - nop + /* Are we being ptraced? */ + ldw TASK_FLAGS(%r1),%r19 + ldi (_TIF_SINGLESTEP|_TIF_BLOCKSTEP),%r2 + and,COND(=) %r19,%r2,%r0 + b,n syscall_restore_rfi ldo TASK_PT_FR31(%r1),%r19 /* reload fpregs */ rest_fp %r19 @@ -2113,16 +2114,16 @@ syscall_restore_rfi: ldi 0x0b,%r20 /* Create new PSW */ depi -1,13,1,%r20 /* C, Q, D, and I bits */ - /* The values of PA_SINGLESTEP_BIT and PA_BLOCKSTEP_BIT are - * set in include/linux/ptrace.h and converted to PA bitmap + /* The values of SINGLESTEP_BIT and BLOCKSTEP_BIT are + * set in thread_info.h and converted to PA bitmap * numbers in asm-offsets.c */ - /* if ((%r19.PA_SINGLESTEP_BIT)) { %r20.27=1} */ - extru,= %r19,PA_SINGLESTEP_BIT,1,%r0 + /* if ((%r19.SINGLESTEP_BIT)) { %r20.27=1} */ + extru,= %r19,TIF_SINGLESTEP_PA_BIT,1,%r0 depi -1,27,1,%r20 /* R bit */ - /* if ((%r19.PA_BLOCKSTEP_BIT)) { %r20.7=1} */ - extru,= %r19,PA_BLOCKSTEP_BIT,1,%r0 + /* if ((%r19.BLOCKSTEP_BIT)) { %r20.7=1} */ + extru,= %r19,TIF_BLOCKSTEP_PA_BIT,1,%r0 depi -1,7,1,%r20 /* T bit */ STREG %r20,TASK_PT_PSW(%r1) diff --git a/trunk/arch/parisc/kernel/irq.c b/trunk/arch/parisc/kernel/irq.c index 330f536a9324..2e7610cb33d5 100644 --- a/trunk/arch/parisc/kernel/irq.c +++ b/trunk/arch/parisc/kernel/irq.c @@ -423,8 +423,3 @@ void __init init_IRQ(void) set_eiem(cpu_eiem); /* EIEM : enable all external intr */ } - -void ack_bad_irq(unsigned int irq) -{ - printk(KERN_WARNING "unexpected IRQ %d\n", irq); -} diff --git a/trunk/arch/parisc/kernel/module.c b/trunk/arch/parisc/kernel/module.c index 61ee0eec4e69..212074653df7 100644 --- a/trunk/arch/parisc/kernel/module.c +++ b/trunk/arch/parisc/kernel/module.c @@ -893,7 +893,7 @@ int module_finalize(const Elf_Ehdr *hdr, * ourselves */ for (i = 1; i < hdr->e_shnum; i++) { if(sechdrs[i].sh_type == SHT_SYMTAB - && (sechdrs[i].sh_type & SHF_ALLOC)) { + && (sechdrs[i].sh_flags & SHF_ALLOC)) { int strindex = sechdrs[i].sh_link; /* FIXME: AWFUL HACK * The cast is to drop the const from diff --git a/trunk/arch/parisc/kernel/ptrace.c b/trunk/arch/parisc/kernel/ptrace.c index 927db3668b6f..c4f49e45129d 100644 --- a/trunk/arch/parisc/kernel/ptrace.c +++ b/trunk/arch/parisc/kernel/ptrace.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -35,7 +36,8 @@ */ void ptrace_disable(struct task_struct *task) { - task->ptrace &= ~(PT_SINGLESTEP|PT_BLOCKSTEP); + clear_tsk_thread_flag(task, TIF_SINGLESTEP); + clear_tsk_thread_flag(task, TIF_BLOCKSTEP); /* make sure the trap bits are not set */ pa_psw(task)->r = 0; @@ -55,8 +57,8 @@ void user_disable_single_step(struct task_struct *task) void user_enable_single_step(struct task_struct *task) { - task->ptrace &= ~PT_BLOCKSTEP; - task->ptrace |= PT_SINGLESTEP; + clear_tsk_thread_flag(task, TIF_BLOCKSTEP); + set_tsk_thread_flag(task, TIF_SINGLESTEP); if (pa_psw(task)->n) { struct siginfo si; @@ -98,8 +100,8 @@ void user_enable_single_step(struct task_struct *task) void user_enable_block_step(struct task_struct *task) { - task->ptrace &= ~PT_SINGLESTEP; - task->ptrace |= PT_BLOCKSTEP; + clear_tsk_thread_flag(task, TIF_SINGLESTEP); + set_tsk_thread_flag(task, TIF_BLOCKSTEP); /* Enable taken branch trap. */ pa_psw(task)->r = 0; @@ -263,22 +265,20 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, } #endif +long do_syscall_trace_enter(struct pt_regs *regs) +{ + if (test_thread_flag(TIF_SYSCALL_TRACE) && + tracehook_report_syscall_entry(regs)) + return -1L; + + return regs->gr[20]; +} -void syscall_trace(void) +void do_syscall_trace_exit(struct pt_regs *regs) { - if (!test_thread_flag(TIF_SYSCALL_TRACE)) - return; - if (!(current->ptrace & PT_PTRACED)) - return; - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) - ? 0x80 : 0)); - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (current->exit_code) { - send_sig(current->exit_code, current, 1); - current->exit_code = 0; - } + int stepping = test_thread_flag(TIF_SINGLESTEP) || + test_thread_flag(TIF_BLOCKSTEP); + + if (stepping || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, stepping); } diff --git a/trunk/arch/parisc/kernel/signal.c b/trunk/arch/parisc/kernel/signal.c index 8eb3c63c407a..e8467e4aa8d1 100644 --- a/trunk/arch/parisc/kernel/signal.c +++ b/trunk/arch/parisc/kernel/signal.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -34,7 +35,6 @@ #include #ifdef CONFIG_COMPAT -#include #include "signal32.h" #endif @@ -468,6 +468,9 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, sigaddset(¤t->blocked,sig); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); + + tracehook_signal_handler(sig, info, ka, regs, 0); + return 1; } diff --git a/trunk/arch/parisc/kernel/syscall.S b/trunk/arch/parisc/kernel/syscall.S index 59fc1a43ec3e..f5f96021caa0 100644 --- a/trunk/arch/parisc/kernel/syscall.S +++ b/trunk/arch/parisc/kernel/syscall.S @@ -288,18 +288,23 @@ tracesys: STREG %r18,PT_GR18(%r2) /* Finished saving things for the debugger */ - ldil L%syscall_trace,%r1 + copy %r2,%r26 + ldil L%do_syscall_trace_enter,%r1 ldil L%tracesys_next,%r2 - be R%syscall_trace(%sr7,%r1) + be R%do_syscall_trace_enter(%sr7,%r1) ldo R%tracesys_next(%r2),%r2 -tracesys_next: +tracesys_next: + /* do_syscall_trace_enter either returned the syscallno, or -1L, + * so we skip restoring the PT_GR20 below, since we pulled it from + * task->thread.regs.gr[20] above. + */ + copy %ret0,%r20 ldil L%sys_call_table,%r1 ldo R%sys_call_table(%r1), %r19 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ LDREG TI_TASK(%r1), %r1 - LDREG TASK_PT_GR20(%r1), %r20 LDREG TASK_PT_GR26(%r1), %r26 /* Restore the users args */ LDREG TASK_PT_GR25(%r1), %r25 LDREG TASK_PT_GR24(%r1), %r24 @@ -336,7 +341,8 @@ tracesys_exit: #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ #endif - bl syscall_trace, %r2 + ldo TASK_REGS(%r1),%r26 + bl do_syscall_trace_exit,%r2 STREG %r28,TASK_PT_GR28(%r1) /* save return value now */ ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ LDREG TI_TASK(%r1), %r1 @@ -353,12 +359,12 @@ tracesys_exit: tracesys_sigexit: ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ - LDREG 0(%r1), %r1 + LDREG TI_TASK(%r1), %r1 #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ #endif - bl syscall_trace, %r2 - nop + bl do_syscall_trace_exit,%r2 + ldo TASK_REGS(%r1),%r26 ldil L%syscall_exit_rfi,%r1 be,n R%syscall_exit_rfi(%sr7,%r1) diff --git a/trunk/arch/parisc/kernel/vmlinux.lds.S b/trunk/arch/parisc/kernel/vmlinux.lds.S index 775be2791bc2..fda4baa059b5 100644 --- a/trunk/arch/parisc/kernel/vmlinux.lds.S +++ b/trunk/arch/parisc/kernel/vmlinux.lds.S @@ -28,6 +28,7 @@ #include #include #include +#include /* ld script to make hppa Linux kernel */ #ifndef CONFIG_64BIT @@ -134,6 +135,15 @@ SECTIONS __init_begin = .; INIT_TEXT_SECTION(16384) INIT_DATA_SECTION(16) + /* we have to discard exit text and such at runtime, not link time */ + .exit.text : + { + EXIT_TEXT + } + .exit.data : + { + EXIT_DATA + } PERCPU(PAGE_SIZE) . = ALIGN(PAGE_SIZE); diff --git a/trunk/arch/parisc/mm/init.c b/trunk/arch/parisc/mm/init.c index d5aca31fddbb..13b6e3e59b99 100644 --- a/trunk/arch/parisc/mm/init.c +++ b/trunk/arch/parisc/mm/init.c @@ -434,8 +434,8 @@ void mark_rodata_ro(void) #define SET_MAP_OFFSET(x) ((void *)(((unsigned long)(x) + VM_MAP_OFFSET) \ & ~(VM_MAP_OFFSET-1))) -void *vmalloc_start __read_mostly; -EXPORT_SYMBOL(vmalloc_start); +void *parisc_vmalloc_start __read_mostly; +EXPORT_SYMBOL(parisc_vmalloc_start); #ifdef CONFIG_PA11 unsigned long pcxl_dma_start __read_mostly; @@ -496,13 +496,14 @@ void __init mem_init(void) #ifdef CONFIG_PA11 if (hppa_dma_ops == &pcxl_dma_ops) { pcxl_dma_start = (unsigned long)SET_MAP_OFFSET(MAP_START); - vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + PCXL_DMA_MAP_SIZE); + parisc_vmalloc_start = SET_MAP_OFFSET(pcxl_dma_start + + PCXL_DMA_MAP_SIZE); } else { pcxl_dma_start = 0; - vmalloc_start = SET_MAP_OFFSET(MAP_START); + parisc_vmalloc_start = SET_MAP_OFFSET(MAP_START); } #else - vmalloc_start = SET_MAP_OFFSET(MAP_START); + parisc_vmalloc_start = SET_MAP_OFFSET(MAP_START); #endif printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init)\n", diff --git a/trunk/arch/s390/kvm/kvm-s390.h b/trunk/arch/s390/kvm/kvm-s390.h index ec5eee7c25d8..06cce8285ba0 100644 --- a/trunk/arch/s390/kvm/kvm-s390.h +++ b/trunk/arch/s390/kvm/kvm-s390.h @@ -58,7 +58,7 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action); -static inline int kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu) +static inline long kvm_s390_vcpu_get_memsize(struct kvm_vcpu *vcpu) { return vcpu->arch.sie_block->gmslm - vcpu->arch.sie_block->gmsor diff --git a/trunk/arch/sparc/include/asm/hardirq_32.h b/trunk/arch/sparc/include/asm/hardirq_32.h index 4f63ed8df551..162007643cdc 100644 --- a/trunk/arch/sparc/include/asm/hardirq_32.h +++ b/trunk/arch/sparc/include/asm/hardirq_32.h @@ -7,17 +7,7 @@ #ifndef __SPARC_HARDIRQ_H #define __SPARC_HARDIRQ_H -#include -#include -#include - -/* entry.S is sensitive to the offsets of these fields */ /* XXX P3 Is it? */ -typedef struct { - unsigned int __softirq_pending; -} ____cacheline_aligned irq_cpustat_t; - -#include /* Standard mappings for irq_cpustat_t above */ - #define HARDIRQ_BITS 8 +#include #endif /* __SPARC_HARDIRQ_H */ diff --git a/trunk/arch/sparc/include/asm/irq_32.h b/trunk/arch/sparc/include/asm/irq_32.h index ea43057d4763..cbf4801deaaf 100644 --- a/trunk/arch/sparc/include/asm/irq_32.h +++ b/trunk/arch/sparc/include/asm/irq_32.h @@ -6,10 +6,10 @@ #ifndef _SPARC_IRQ_H #define _SPARC_IRQ_H -#include - #define NR_IRQS 16 +#include + #define irq_canonicalize(irq) (irq) extern void __init init_IRQ(void); diff --git a/trunk/arch/sparc/include/asm/pgtable_64.h b/trunk/arch/sparc/include/asm/pgtable_64.h index 0ff92fa22064..f3cb790fa2ae 100644 --- a/trunk/arch/sparc/include/asm/pgtable_64.h +++ b/trunk/arch/sparc/include/asm/pgtable_64.h @@ -41,8 +41,8 @@ #define LOW_OBP_ADDRESS _AC(0x00000000f0000000,UL) #define HI_OBP_ADDRESS _AC(0x0000000100000000,UL) #define VMALLOC_START _AC(0x0000000100000000,UL) -#define VMALLOC_END _AC(0x0000000200000000,UL) -#define VMEMMAP_BASE _AC(0x0000000200000000,UL) +#define VMALLOC_END _AC(0x0000010000000000,UL) +#define VMEMMAP_BASE _AC(0x0000010000000000,UL) #define vmemmap ((struct page *)VMEMMAP_BASE) diff --git a/trunk/arch/sparc/kernel/ktlb.S b/trunk/arch/sparc/kernel/ktlb.S index 3ea6e8cde8c5..1d361477d7d6 100644 --- a/trunk/arch/sparc/kernel/ktlb.S +++ b/trunk/arch/sparc/kernel/ktlb.S @@ -280,8 +280,8 @@ kvmap_dtlb_nonlinear: #ifdef CONFIG_SPARSEMEM_VMEMMAP /* Do not use the TSB for vmemmap. */ - mov (VMEMMAP_BASE >> 24), %g5 - sllx %g5, 24, %g5 + mov (VMEMMAP_BASE >> 40), %g5 + sllx %g5, 40, %g5 cmp %g4,%g5 bgeu,pn %xcc, kvmap_vmemmap nop @@ -293,8 +293,8 @@ kvmap_dtlb_tsbmiss: sethi %hi(MODULES_VADDR), %g5 cmp %g4, %g5 blu,pn %xcc, kvmap_dtlb_longpath - mov (VMALLOC_END >> 24), %g5 - sllx %g5, 24, %g5 + mov (VMALLOC_END >> 40), %g5 + sllx %g5, 40, %g5 cmp %g4, %g5 bgeu,pn %xcc, kvmap_dtlb_longpath nop diff --git a/trunk/arch/sparc/kernel/perf_event.c b/trunk/arch/sparc/kernel/perf_event.c index 2d6a1b10c81d..04db92743896 100644 --- a/trunk/arch/sparc/kernel/perf_event.c +++ b/trunk/arch/sparc/kernel/perf_event.c @@ -56,7 +56,8 @@ struct cpu_hw_events { struct perf_event *events[MAX_HWEVENTS]; unsigned long used_mask[BITS_TO_LONGS(MAX_HWEVENTS)]; unsigned long active_mask[BITS_TO_LONGS(MAX_HWEVENTS)]; - int enabled; + u64 pcr; + int enabled; }; DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .enabled = 1, }; @@ -68,8 +69,30 @@ struct perf_event_map { #define PIC_LOWER 0x02 }; +static unsigned long perf_event_encode(const struct perf_event_map *pmap) +{ + return ((unsigned long) pmap->encoding << 16) | pmap->pic_mask; +} + +static void perf_event_decode(unsigned long val, u16 *enc, u8 *msk) +{ + *msk = val & 0xff; + *enc = val >> 16; +} + +#define C(x) PERF_COUNT_HW_CACHE_##x + +#define CACHE_OP_UNSUPPORTED 0xfffe +#define CACHE_OP_NONSENSE 0xffff + +typedef struct perf_event_map cache_map_t + [PERF_COUNT_HW_CACHE_MAX] + [PERF_COUNT_HW_CACHE_OP_MAX] + [PERF_COUNT_HW_CACHE_RESULT_MAX]; + struct sparc_pmu { const struct perf_event_map *(*event_map)(int); + const cache_map_t *cache_map; int max_events; int upper_shift; int lower_shift; @@ -80,21 +103,109 @@ struct sparc_pmu { int lower_nop; }; -static const struct perf_event_map ultra3i_perfmon_event_map[] = { +static const struct perf_event_map ultra3_perfmon_event_map[] = { [PERF_COUNT_HW_CPU_CYCLES] = { 0x0000, PIC_UPPER | PIC_LOWER }, [PERF_COUNT_HW_INSTRUCTIONS] = { 0x0001, PIC_UPPER | PIC_LOWER }, [PERF_COUNT_HW_CACHE_REFERENCES] = { 0x0009, PIC_LOWER }, [PERF_COUNT_HW_CACHE_MISSES] = { 0x0009, PIC_UPPER }, }; -static const struct perf_event_map *ultra3i_event_map(int event_id) +static const struct perf_event_map *ultra3_event_map(int event_id) { - return &ultra3i_perfmon_event_map[event_id]; + return &ultra3_perfmon_event_map[event_id]; } -static const struct sparc_pmu ultra3i_pmu = { - .event_map = ultra3i_event_map, - .max_events = ARRAY_SIZE(ultra3i_perfmon_event_map), +static const cache_map_t ultra3_cache_map = { +[C(L1D)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x09, PIC_LOWER, }, + [C(RESULT_MISS)] = { 0x09, PIC_UPPER, }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { 0x0a, PIC_LOWER }, + [C(RESULT_MISS)] = { 0x0a, PIC_UPPER }, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(L1I)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x09, PIC_LOWER, }, + [C(RESULT_MISS)] = { 0x09, PIC_UPPER, }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_NONSENSE }, + [ C(RESULT_MISS) ] = { CACHE_OP_NONSENSE }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(LL)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x0c, PIC_LOWER, }, + [C(RESULT_MISS)] = { 0x0c, PIC_UPPER, }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { 0x0c, PIC_LOWER }, + [C(RESULT_MISS)] = { 0x0c, PIC_UPPER }, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(DTLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0x12, PIC_UPPER, }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(ITLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0x11, PIC_UPPER, }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(BPU)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +}; + +static const struct sparc_pmu ultra3_pmu = { + .event_map = ultra3_event_map, + .cache_map = &ultra3_cache_map, + .max_events = ARRAY_SIZE(ultra3_perfmon_event_map), .upper_shift = 11, .lower_shift = 4, .event_mask = 0x3f, @@ -102,6 +213,121 @@ static const struct sparc_pmu ultra3i_pmu = { .lower_nop = 0x14, }; +/* Niagara1 is very limited. The upper PIC is hard-locked to count + * only instructions, so it is free running which creates all kinds of + * problems. Some hardware designs make one wonder if the creator + * even looked at how this stuff gets used by software. + */ +static const struct perf_event_map niagara1_perfmon_event_map[] = { + [PERF_COUNT_HW_CPU_CYCLES] = { 0x00, PIC_UPPER }, + [PERF_COUNT_HW_INSTRUCTIONS] = { 0x00, PIC_UPPER }, + [PERF_COUNT_HW_CACHE_REFERENCES] = { 0, PIC_NONE }, + [PERF_COUNT_HW_CACHE_MISSES] = { 0x03, PIC_LOWER }, +}; + +static const struct perf_event_map *niagara1_event_map(int event_id) +{ + return &niagara1_perfmon_event_map[event_id]; +} + +static const cache_map_t niagara1_cache_map = { +[C(L1D)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0x03, PIC_LOWER, }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0x03, PIC_LOWER, }, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(L1I)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x00, PIC_UPPER }, + [C(RESULT_MISS)] = { 0x02, PIC_LOWER, }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_NONSENSE }, + [ C(RESULT_MISS) ] = { CACHE_OP_NONSENSE }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(LL)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0x07, PIC_LOWER, }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0x07, PIC_LOWER, }, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(DTLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0x05, PIC_LOWER, }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(ITLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0x04, PIC_LOWER, }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(BPU)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +}; + +static const struct sparc_pmu niagara1_pmu = { + .event_map = niagara1_event_map, + .cache_map = &niagara1_cache_map, + .max_events = ARRAY_SIZE(niagara1_perfmon_event_map), + .upper_shift = 0, + .lower_shift = 4, + .event_mask = 0x7, + .upper_nop = 0x0, + .lower_nop = 0x0, +}; + static const struct perf_event_map niagara2_perfmon_event_map[] = { [PERF_COUNT_HW_CPU_CYCLES] = { 0x02ff, PIC_UPPER | PIC_LOWER }, [PERF_COUNT_HW_INSTRUCTIONS] = { 0x02ff, PIC_UPPER | PIC_LOWER }, @@ -116,8 +342,96 @@ static const struct perf_event_map *niagara2_event_map(int event_id) return &niagara2_perfmon_event_map[event_id]; } +static const cache_map_t niagara2_cache_map = { +[C(L1D)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x0208, PIC_UPPER | PIC_LOWER, }, + [C(RESULT_MISS)] = { 0x0302, PIC_UPPER | PIC_LOWER, }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { 0x0210, PIC_UPPER | PIC_LOWER, }, + [C(RESULT_MISS)] = { 0x0302, PIC_UPPER | PIC_LOWER, }, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(L1I)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x02ff, PIC_UPPER | PIC_LOWER, }, + [C(RESULT_MISS)] = { 0x0301, PIC_UPPER | PIC_LOWER, }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_NONSENSE }, + [ C(RESULT_MISS) ] = { CACHE_OP_NONSENSE }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(LL)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { 0x0208, PIC_UPPER | PIC_LOWER, }, + [C(RESULT_MISS)] = { 0x0330, PIC_UPPER | PIC_LOWER, }, + }, + [C(OP_WRITE)] = { + [C(RESULT_ACCESS)] = { 0x0210, PIC_UPPER | PIC_LOWER, }, + [C(RESULT_MISS)] = { 0x0320, PIC_UPPER | PIC_LOWER, }, + }, + [C(OP_PREFETCH)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(DTLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0x0b08, PIC_UPPER | PIC_LOWER, }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(ITLB)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { 0xb04, PIC_UPPER | PIC_LOWER, }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +[C(BPU)] = { + [C(OP_READ)] = { + [C(RESULT_ACCESS)] = { CACHE_OP_UNSUPPORTED }, + [C(RESULT_MISS)] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_WRITE) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, + [ C(OP_PREFETCH) ] = { + [ C(RESULT_ACCESS) ] = { CACHE_OP_UNSUPPORTED }, + [ C(RESULT_MISS) ] = { CACHE_OP_UNSUPPORTED }, + }, +}, +}; + static const struct sparc_pmu niagara2_pmu = { .event_map = niagara2_event_map, + .cache_map = &niagara2_cache_map, .max_events = ARRAY_SIZE(niagara2_perfmon_event_map), .upper_shift = 19, .lower_shift = 6, @@ -151,23 +465,30 @@ static u64 nop_for_index(int idx) sparc_pmu->lower_nop, idx); } -static inline void sparc_pmu_enable_event(struct hw_perf_event *hwc, - int idx) +static inline void sparc_pmu_enable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx) { u64 val, mask = mask_for_index(idx); - val = pcr_ops->read(); - pcr_ops->write((val & ~mask) | hwc->config); + val = cpuc->pcr; + val &= ~mask; + val |= hwc->config; + cpuc->pcr = val; + + pcr_ops->write(cpuc->pcr); } -static inline void sparc_pmu_disable_event(struct hw_perf_event *hwc, - int idx) +static inline void sparc_pmu_disable_event(struct cpu_hw_events *cpuc, struct hw_perf_event *hwc, int idx) { u64 mask = mask_for_index(idx); u64 nop = nop_for_index(idx); - u64 val = pcr_ops->read(); + u64 val; - pcr_ops->write((val & ~mask) | nop); + val = cpuc->pcr; + val &= ~mask; + val |= nop; + cpuc->pcr = val; + + pcr_ops->write(cpuc->pcr); } void hw_perf_enable(void) @@ -182,7 +503,7 @@ void hw_perf_enable(void) cpuc->enabled = 1; barrier(); - val = pcr_ops->read(); + val = cpuc->pcr; for (i = 0; i < MAX_HWEVENTS; i++) { struct perf_event *cp = cpuc->events[i]; @@ -194,7 +515,9 @@ void hw_perf_enable(void) val |= hwc->config_base; } - pcr_ops->write(val); + cpuc->pcr = val; + + pcr_ops->write(cpuc->pcr); } void hw_perf_disable(void) @@ -207,10 +530,12 @@ void hw_perf_disable(void) cpuc->enabled = 0; - val = pcr_ops->read(); + val = cpuc->pcr; val &= ~(PCR_UTRACE | PCR_STRACE | sparc_pmu->hv_bit | sparc_pmu->irq_bit); - pcr_ops->write(val); + cpuc->pcr = val; + + pcr_ops->write(cpuc->pcr); } static u32 read_pmc(int idx) @@ -242,7 +567,7 @@ static void write_pmc(int idx, u64 val) } static int sparc_perf_event_set_period(struct perf_event *event, - struct hw_perf_event *hwc, int idx) + struct hw_perf_event *hwc, int idx) { s64 left = atomic64_read(&hwc->period_left); s64 period = hwc->sample_period; @@ -282,19 +607,19 @@ static int sparc_pmu_enable(struct perf_event *event) if (test_and_set_bit(idx, cpuc->used_mask)) return -EAGAIN; - sparc_pmu_disable_event(hwc, idx); + sparc_pmu_disable_event(cpuc, hwc, idx); cpuc->events[idx] = event; set_bit(idx, cpuc->active_mask); sparc_perf_event_set_period(event, hwc, idx); - sparc_pmu_enable_event(hwc, idx); + sparc_pmu_enable_event(cpuc, hwc, idx); perf_event_update_userpage(event); return 0; } static u64 sparc_perf_event_update(struct perf_event *event, - struct hw_perf_event *hwc, int idx) + struct hw_perf_event *hwc, int idx) { int shift = 64 - 32; u64 prev_raw_count, new_raw_count; @@ -324,7 +649,7 @@ static void sparc_pmu_disable(struct perf_event *event) int idx = hwc->idx; clear_bit(idx, cpuc->active_mask); - sparc_pmu_disable_event(hwc, idx); + sparc_pmu_disable_event(cpuc, hwc, idx); barrier(); @@ -338,18 +663,29 @@ static void sparc_pmu_disable(struct perf_event *event) static void sparc_pmu_read(struct perf_event *event) { struct hw_perf_event *hwc = &event->hw; + sparc_perf_event_update(event, hwc, hwc->idx); } static void sparc_pmu_unthrottle(struct perf_event *event) { + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); struct hw_perf_event *hwc = &event->hw; - sparc_pmu_enable_event(hwc, hwc->idx); + + sparc_pmu_enable_event(cpuc, hwc, hwc->idx); } static atomic_t active_events = ATOMIC_INIT(0); static DEFINE_MUTEX(pmc_grab_mutex); +static void perf_stop_nmi_watchdog(void *unused) +{ + struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events); + + stop_nmi_watchdog(NULL); + cpuc->pcr = pcr_ops->read(); +} + void perf_event_grab_pmc(void) { if (atomic_inc_not_zero(&active_events)) @@ -358,7 +694,7 @@ void perf_event_grab_pmc(void) mutex_lock(&pmc_grab_mutex); if (atomic_read(&active_events) == 0) { if (atomic_read(&nmi_active) > 0) { - on_each_cpu(stop_nmi_watchdog, NULL, 1); + on_each_cpu(perf_stop_nmi_watchdog, NULL, 1); BUG_ON(atomic_read(&nmi_active) != 0); } atomic_inc(&active_events); @@ -375,30 +711,160 @@ void perf_event_release_pmc(void) } } +static const struct perf_event_map *sparc_map_cache_event(u64 config) +{ + unsigned int cache_type, cache_op, cache_result; + const struct perf_event_map *pmap; + + if (!sparc_pmu->cache_map) + return ERR_PTR(-ENOENT); + + cache_type = (config >> 0) & 0xff; + if (cache_type >= PERF_COUNT_HW_CACHE_MAX) + return ERR_PTR(-EINVAL); + + cache_op = (config >> 8) & 0xff; + if (cache_op >= PERF_COUNT_HW_CACHE_OP_MAX) + return ERR_PTR(-EINVAL); + + cache_result = (config >> 16) & 0xff; + if (cache_result >= PERF_COUNT_HW_CACHE_RESULT_MAX) + return ERR_PTR(-EINVAL); + + pmap = &((*sparc_pmu->cache_map)[cache_type][cache_op][cache_result]); + + if (pmap->encoding == CACHE_OP_UNSUPPORTED) + return ERR_PTR(-ENOENT); + + if (pmap->encoding == CACHE_OP_NONSENSE) + return ERR_PTR(-EINVAL); + + return pmap; +} + static void hw_perf_event_destroy(struct perf_event *event) { perf_event_release_pmc(); } +/* Make sure all events can be scheduled into the hardware at + * the same time. This is simplified by the fact that we only + * need to support 2 simultaneous HW events. + */ +static int sparc_check_constraints(unsigned long *events, int n_ev) +{ + if (n_ev <= perf_max_events) { + u8 msk1, msk2; + u16 dummy; + + if (n_ev == 1) + return 0; + BUG_ON(n_ev != 2); + perf_event_decode(events[0], &dummy, &msk1); + perf_event_decode(events[1], &dummy, &msk2); + + /* If both events can go on any counter, OK. */ + if (msk1 == (PIC_UPPER | PIC_LOWER) && + msk2 == (PIC_UPPER | PIC_LOWER)) + return 0; + + /* If one event is limited to a specific counter, + * and the other can go on both, OK. + */ + if ((msk1 == PIC_UPPER || msk1 == PIC_LOWER) && + msk2 == (PIC_UPPER | PIC_LOWER)) + return 0; + if ((msk2 == PIC_UPPER || msk2 == PIC_LOWER) && + msk1 == (PIC_UPPER | PIC_LOWER)) + return 0; + + /* If the events are fixed to different counters, OK. */ + if ((msk1 == PIC_UPPER && msk2 == PIC_LOWER) || + (msk1 == PIC_LOWER && msk2 == PIC_UPPER)) + return 0; + + /* Otherwise, there is a conflict. */ + } + + return -1; +} + +static int check_excludes(struct perf_event **evts, int n_prev, int n_new) +{ + int eu = 0, ek = 0, eh = 0; + struct perf_event *event; + int i, n, first; + + n = n_prev + n_new; + if (n <= 1) + return 0; + + first = 1; + for (i = 0; i < n; i++) { + event = evts[i]; + if (first) { + eu = event->attr.exclude_user; + ek = event->attr.exclude_kernel; + eh = event->attr.exclude_hv; + first = 0; + } else if (event->attr.exclude_user != eu || + event->attr.exclude_kernel != ek || + event->attr.exclude_hv != eh) { + return -EAGAIN; + } + } + + return 0; +} + +static int collect_events(struct perf_event *group, int max_count, + struct perf_event *evts[], unsigned long *events) +{ + struct perf_event *event; + int n = 0; + + if (!is_software_event(group)) { + if (n >= max_count) + return -1; + evts[n] = group; + events[n++] = group->hw.event_base; + } + list_for_each_entry(event, &group->sibling_list, group_entry) { + if (!is_software_event(event) && + event->state != PERF_EVENT_STATE_OFF) { + if (n >= max_count) + return -1; + evts[n] = event; + events[n++] = event->hw.event_base; + } + } + return n; +} + static int __hw_perf_event_init(struct perf_event *event) { struct perf_event_attr *attr = &event->attr; + struct perf_event *evts[MAX_HWEVENTS]; struct hw_perf_event *hwc = &event->hw; + unsigned long events[MAX_HWEVENTS]; const struct perf_event_map *pmap; u64 enc; + int n; if (atomic_read(&nmi_active) < 0) return -ENODEV; - if (attr->type != PERF_TYPE_HARDWARE) + if (attr->type == PERF_TYPE_HARDWARE) { + if (attr->config >= sparc_pmu->max_events) + return -EINVAL; + pmap = sparc_pmu->event_map(attr->config); + } else if (attr->type == PERF_TYPE_HW_CACHE) { + pmap = sparc_map_cache_event(attr->config); + if (IS_ERR(pmap)) + return PTR_ERR(pmap); + } else return -EOPNOTSUPP; - if (attr->config >= sparc_pmu->max_events) - return -EINVAL; - - perf_event_grab_pmc(); - event->destroy = hw_perf_event_destroy; - /* We save the enable bits in the config_base. So to * turn off sampling just write 'config', and to enable * things write 'config | config_base'. @@ -411,15 +877,39 @@ static int __hw_perf_event_init(struct perf_event *event) if (!attr->exclude_hv) hwc->config_base |= sparc_pmu->hv_bit; + hwc->event_base = perf_event_encode(pmap); + + enc = pmap->encoding; + + n = 0; + if (event->group_leader != event) { + n = collect_events(event->group_leader, + perf_max_events - 1, + evts, events); + if (n < 0) + return -EINVAL; + } + events[n] = hwc->event_base; + evts[n] = event; + + if (check_excludes(evts, n, 1)) + return -EINVAL; + + if (sparc_check_constraints(events, n + 1)) + return -EINVAL; + + /* Try to do all error checking before this point, as unwinding + * state after grabbing the PMC is difficult. + */ + perf_event_grab_pmc(); + event->destroy = hw_perf_event_destroy; + if (!hwc->sample_period) { hwc->sample_period = MAX_PERIOD; hwc->last_period = hwc->sample_period; atomic64_set(&hwc->period_left, hwc->sample_period); } - pmap = sparc_pmu->event_map(attr->config); - - enc = pmap->encoding; if (pmap->pic_mask & PIC_UPPER) { hwc->idx = PIC_UPPER_INDEX; enc <<= sparc_pmu->upper_shift; @@ -472,7 +962,7 @@ void perf_event_print_debug(void) } static int __kprobes perf_event_nmi_handler(struct notifier_block *self, - unsigned long cmd, void *__args) + unsigned long cmd, void *__args) { struct die_args *args = __args; struct perf_sample_data data; @@ -513,7 +1003,7 @@ static int __kprobes perf_event_nmi_handler(struct notifier_block *self, continue; if (perf_event_overflow(event, 1, &data, regs)) - sparc_pmu_disable_event(hwc, idx); + sparc_pmu_disable_event(cpuc, hwc, idx); } return NOTIFY_STOP; @@ -525,8 +1015,15 @@ static __read_mostly struct notifier_block perf_event_nmi_notifier = { static bool __init supported_pmu(void) { - if (!strcmp(sparc_pmu_type, "ultra3i")) { - sparc_pmu = &ultra3i_pmu; + if (!strcmp(sparc_pmu_type, "ultra3") || + !strcmp(sparc_pmu_type, "ultra3+") || + !strcmp(sparc_pmu_type, "ultra3i") || + !strcmp(sparc_pmu_type, "ultra4+")) { + sparc_pmu = &ultra3_pmu; + return true; + } + if (!strcmp(sparc_pmu_type, "niagara")) { + sparc_pmu = &niagara1_pmu; return true; } if (!strcmp(sparc_pmu_type, "niagara2")) { diff --git a/trunk/arch/sparc/oprofile/init.c b/trunk/arch/sparc/oprofile/init.c index f97cb8b6ee5f..f9024bccff16 100644 --- a/trunk/arch/sparc/oprofile/init.c +++ b/trunk/arch/sparc/oprofile/init.c @@ -11,6 +11,7 @@ #include #include #include +#include /* for HZ */ #ifdef CONFIG_SPARC64 #include diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 8da93745c087..c876bace8fdc 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -86,10 +86,6 @@ config STACKTRACE_SUPPORT config HAVE_LATENCYTOP_SUPPORT def_bool y -config FAST_CMPXCHG_LOCAL - bool - default y - config MMU def_bool y diff --git a/trunk/arch/x86/Kconfig.cpu b/trunk/arch/x86/Kconfig.cpu index 527519b8a9f9..f2824fb8c79c 100644 --- a/trunk/arch/x86/Kconfig.cpu +++ b/trunk/arch/x86/Kconfig.cpu @@ -400,7 +400,7 @@ config X86_TSC config X86_CMPXCHG64 def_bool y - depends on X86_PAE || X86_64 + depends on X86_PAE || X86_64 || MCORE2 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MATOM # this should be set for all -march=.. options where the compiler # generates cmov. @@ -412,6 +412,7 @@ config X86_MINIMUM_CPU_FAMILY int default "64" if X86_64 default "6" if X86_32 && X86_P6_NOP + default "5" if X86_32 && X86_CMPXCHG64 default "4" if X86_32 && (X86_XADD || X86_CMPXCHG || X86_BSWAP || X86_WP_WORKS_OK) default "3" diff --git a/trunk/arch/x86/ia32/ia32entry.S b/trunk/arch/x86/ia32/ia32entry.S index 74619c4f9fda..1733f9f65e82 100644 --- a/trunk/arch/x86/ia32/ia32entry.S +++ b/trunk/arch/x86/ia32/ia32entry.S @@ -21,8 +21,8 @@ #define __AUDIT_ARCH_LE 0x40000000 #ifndef CONFIG_AUDITSYSCALL -#define sysexit_audit int_ret_from_sys_call -#define sysretl_audit int_ret_from_sys_call +#define sysexit_audit ia32_ret_from_sys_call +#define sysretl_audit ia32_ret_from_sys_call #endif #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8) @@ -39,12 +39,12 @@ .endm /* clobbers %eax */ - .macro CLEAR_RREGS _r9=rax + .macro CLEAR_RREGS offset=0, _r9=rax xorl %eax,%eax - movq %rax,R11(%rsp) - movq %rax,R10(%rsp) - movq %\_r9,R9(%rsp) - movq %rax,R8(%rsp) + movq %rax,\offset+R11(%rsp) + movq %rax,\offset+R10(%rsp) + movq %\_r9,\offset+R9(%rsp) + movq %rax,\offset+R8(%rsp) .endm /* @@ -172,6 +172,10 @@ sysexit_from_sys_call: movl RIP-R11(%rsp),%edx /* User %eip */ CFI_REGISTER rip,rdx RESTORE_ARGS 1,24,1,1,1,1 + xorq %r8,%r8 + xorq %r9,%r9 + xorq %r10,%r10 + xorq %r11,%r11 popfq CFI_ADJUST_CFA_OFFSET -8 /*CFI_RESTORE rflags*/ @@ -202,7 +206,7 @@ sysexit_from_sys_call: .macro auditsys_exit exit,ebpsave=RBP testl $(_TIF_ALLWORK_MASK & ~_TIF_SYSCALL_AUDIT),TI_flags(%r10) - jnz int_ret_from_sys_call + jnz ia32_ret_from_sys_call TRACE_IRQS_ON sti movl %eax,%esi /* second arg, syscall return value */ @@ -218,8 +222,9 @@ sysexit_from_sys_call: cli TRACE_IRQS_OFF testl %edi,TI_flags(%r10) - jnz int_with_check - jmp \exit + jz \exit + CLEAR_RREGS -ARGOFFSET + jmp int_with_check .endm sysenter_auditsys: @@ -329,6 +334,9 @@ sysretl_from_sys_call: CFI_REGISTER rip,rcx movl EFLAGS-ARGOFFSET(%rsp),%r11d /*CFI_REGISTER rflags,r11*/ + xorq %r10,%r10 + xorq %r9,%r9 + xorq %r8,%r8 TRACE_IRQS_ON movl RSP-ARGOFFSET(%rsp),%esp CFI_RESTORE rsp @@ -353,7 +361,7 @@ cstar_tracesys: #endif xchgl %r9d,%ebp SAVE_REST - CLEAR_RREGS r9 + CLEAR_RREGS 0, r9 movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */ movq %rsp,%rdi /* &pt_regs -> arg1 */ call syscall_trace_enter @@ -425,6 +433,8 @@ ia32_do_call: call *ia32_sys_call_table(,%rax,8) # xxx: rip relative ia32_sysret: movq %rax,RAX-ARGOFFSET(%rsp) +ia32_ret_from_sys_call: + CLEAR_RREGS -ARGOFFSET jmp int_ret_from_sys_call ia32_tracesys: @@ -442,8 +452,8 @@ END(ia32_syscall) ia32_badsys: movq $0,ORIG_RAX-ARGOFFSET(%rsp) - movq $-ENOSYS,RAX-ARGOFFSET(%rsp) - jmp int_ret_from_sys_call + movq $-ENOSYS,%rax + jmp ia32_sysret quiet_ni_syscall: movq $-ENOSYS,%rax diff --git a/trunk/arch/x86/include/asm/kvm_host.h b/trunk/arch/x86/include/asm/kvm_host.h index 3be000435fad..d83892226f73 100644 --- a/trunk/arch/x86/include/asm/kvm_host.h +++ b/trunk/arch/x86/include/asm/kvm_host.h @@ -796,6 +796,7 @@ asmlinkage void kvm_handle_fault_on_reboot(void); #define KVM_ARCH_WANT_MMU_NOTIFIER int kvm_unmap_hva(struct kvm *kvm, unsigned long hva); int kvm_age_hva(struct kvm *kvm, unsigned long hva); +void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte); int cpuid_maxphyaddr(struct kvm_vcpu *vcpu); int kvm_cpu_has_interrupt(struct kvm_vcpu *vcpu); int kvm_arch_interrupt_allowed(struct kvm_vcpu *vcpu); diff --git a/trunk/arch/x86/kernel/early_printk.c b/trunk/arch/x86/kernel/early_printk.c index 41fd965c80c6..b9c830c12b4a 100644 --- a/trunk/arch/x86/kernel/early_printk.c +++ b/trunk/arch/x86/kernel/early_printk.c @@ -206,8 +206,11 @@ static int __init setup_early_printk(char *buf) while (*buf != '\0') { if (!strncmp(buf, "serial", 6)) { - early_serial_init(buf + 6); + buf += 6; + early_serial_init(buf); early_console_register(&early_serial_console, keep); + if (!strncmp(buf, ",ttyS", 5)) + buf += 5; } if (!strncmp(buf, "ttyS", 4)) { early_serial_init(buf + 4); diff --git a/trunk/arch/x86/kernel/i386_ksyms_32.c b/trunk/arch/x86/kernel/i386_ksyms_32.c index 1736c5a725aa..9c3bd4a2050e 100644 --- a/trunk/arch/x86/kernel/i386_ksyms_32.c +++ b/trunk/arch/x86/kernel/i386_ksyms_32.c @@ -15,8 +15,10 @@ EXPORT_SYMBOL(mcount); * the export, but dont use it from C code, it is used * by assembly code and is not using C calling convention! */ +#ifndef CONFIG_X86_CMPXCHG64 extern void cmpxchg8b_emu(void); EXPORT_SYMBOL(cmpxchg8b_emu); +#endif /* Networking helper routines. */ EXPORT_SYMBOL(csum_partial_copy_generic); diff --git a/trunk/arch/x86/kvm/lapic.c b/trunk/arch/x86/kvm/lapic.c index 1ae5ceba7eb2..7024224f0fc8 100644 --- a/trunk/arch/x86/kvm/lapic.c +++ b/trunk/arch/x86/kvm/lapic.c @@ -664,7 +664,7 @@ static void start_apic_timer(struct kvm_lapic *apic) { ktime_t now = apic->lapic_timer.timer.base->get_time(); - apic->lapic_timer.period = apic_get_reg(apic, APIC_TMICT) * + apic->lapic_timer.period = (u64)apic_get_reg(apic, APIC_TMICT) * APIC_BUS_CYCLE_NS * apic->divide_count; atomic_set(&apic->lapic_timer.pending, 0); diff --git a/trunk/arch/x86/kvm/mmu.c b/trunk/arch/x86/kvm/mmu.c index eca41ae9f453..685a4ffac8e6 100644 --- a/trunk/arch/x86/kvm/mmu.c +++ b/trunk/arch/x86/kvm/mmu.c @@ -156,6 +156,8 @@ module_param(oos_shadow, bool, 0644); #define CREATE_TRACE_POINTS #include "mmutrace.h" +#define SPTE_HOST_WRITEABLE (1ULL << PT_FIRST_AVAIL_BITS_SHIFT) + #define SHADOW_PT_INDEX(addr, level) PT64_INDEX(addr, level) struct kvm_rmap_desc { @@ -634,9 +636,7 @@ static void rmap_remove(struct kvm *kvm, u64 *spte) if (*spte & shadow_accessed_mask) kvm_set_pfn_accessed(pfn); if (is_writeble_pte(*spte)) - kvm_release_pfn_dirty(pfn); - else - kvm_release_pfn_clean(pfn); + kvm_set_pfn_dirty(pfn); rmapp = gfn_to_rmap(kvm, sp->gfns[spte - sp->spt], sp->role.level); if (!*rmapp) { printk(KERN_ERR "rmap_remove: %p %llx 0->BUG\n", spte, *spte); @@ -748,7 +748,7 @@ static int rmap_write_protect(struct kvm *kvm, u64 gfn) return write_protected; } -static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp) +static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp, u64 data) { u64 *spte; int need_tlb_flush = 0; @@ -763,8 +763,45 @@ static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp) return need_tlb_flush; } -static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, - int (*handler)(struct kvm *kvm, unsigned long *rmapp)) +static int kvm_set_pte_rmapp(struct kvm *kvm, unsigned long *rmapp, u64 data) +{ + int need_flush = 0; + u64 *spte, new_spte; + pte_t *ptep = (pte_t *)data; + pfn_t new_pfn; + + WARN_ON(pte_huge(*ptep)); + new_pfn = pte_pfn(*ptep); + spte = rmap_next(kvm, rmapp, NULL); + while (spte) { + BUG_ON(!is_shadow_present_pte(*spte)); + rmap_printk("kvm_set_pte_rmapp: spte %p %llx\n", spte, *spte); + need_flush = 1; + if (pte_write(*ptep)) { + rmap_remove(kvm, spte); + __set_spte(spte, shadow_trap_nonpresent_pte); + spte = rmap_next(kvm, rmapp, NULL); + } else { + new_spte = *spte &~ (PT64_BASE_ADDR_MASK); + new_spte |= (u64)new_pfn << PAGE_SHIFT; + + new_spte &= ~PT_WRITABLE_MASK; + new_spte &= ~SPTE_HOST_WRITEABLE; + if (is_writeble_pte(*spte)) + kvm_set_pfn_dirty(spte_to_pfn(*spte)); + __set_spte(spte, new_spte); + spte = rmap_next(kvm, rmapp, spte); + } + } + if (need_flush) + kvm_flush_remote_tlbs(kvm); + + return 0; +} + +static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, u64 data, + int (*handler)(struct kvm *kvm, unsigned long *rmapp, + u64 data)) { int i, j; int retval = 0; @@ -786,13 +823,15 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, if (hva >= start && hva < end) { gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT; - retval |= handler(kvm, &memslot->rmap[gfn_offset]); + retval |= handler(kvm, &memslot->rmap[gfn_offset], + data); for (j = 0; j < KVM_NR_PAGE_SIZES - 1; ++j) { int idx = gfn_offset; idx /= KVM_PAGES_PER_HPAGE(PT_DIRECTORY_LEVEL + j); retval |= handler(kvm, - &memslot->lpage_info[j][idx].rmap_pde); + &memslot->lpage_info[j][idx].rmap_pde, + data); } } } @@ -802,10 +841,15 @@ static int kvm_handle_hva(struct kvm *kvm, unsigned long hva, int kvm_unmap_hva(struct kvm *kvm, unsigned long hva) { - return kvm_handle_hva(kvm, hva, kvm_unmap_rmapp); + return kvm_handle_hva(kvm, hva, 0, kvm_unmap_rmapp); } -static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp) +void kvm_set_spte_hva(struct kvm *kvm, unsigned long hva, pte_t pte) +{ + kvm_handle_hva(kvm, hva, (u64)&pte, kvm_set_pte_rmapp); +} + +static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp, u64 data) { u64 *spte; int young = 0; @@ -841,13 +885,13 @@ static void rmap_recycle(struct kvm_vcpu *vcpu, u64 *spte, gfn_t gfn) gfn = unalias_gfn(vcpu->kvm, gfn); rmapp = gfn_to_rmap(vcpu->kvm, gfn, sp->role.level); - kvm_unmap_rmapp(vcpu->kvm, rmapp); + kvm_unmap_rmapp(vcpu->kvm, rmapp, 0); kvm_flush_remote_tlbs(vcpu->kvm); } int kvm_age_hva(struct kvm *kvm, unsigned long hva) { - return kvm_handle_hva(kvm, hva, kvm_age_rmapp); + return kvm_handle_hva(kvm, hva, 0, kvm_age_rmapp); } #ifdef MMU_DEBUG @@ -1756,7 +1800,7 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, unsigned pte_access, int user_fault, int write_fault, int dirty, int level, gfn_t gfn, pfn_t pfn, bool speculative, - bool can_unsync) + bool can_unsync, bool reset_host_protection) { u64 spte; int ret = 0; @@ -1783,6 +1827,9 @@ static int set_spte(struct kvm_vcpu *vcpu, u64 *sptep, spte |= kvm_x86_ops->get_mt_mask(vcpu, gfn, kvm_is_mmio_pfn(pfn)); + if (reset_host_protection) + spte |= SPTE_HOST_WRITEABLE; + spte |= (u64)pfn << PAGE_SHIFT; if ((pte_access & ACC_WRITE_MASK) @@ -1828,7 +1875,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, unsigned pt_access, unsigned pte_access, int user_fault, int write_fault, int dirty, int *ptwrite, int level, gfn_t gfn, - pfn_t pfn, bool speculative) + pfn_t pfn, bool speculative, + bool reset_host_protection) { int was_rmapped = 0; int was_writeble = is_writeble_pte(*sptep); @@ -1860,7 +1908,8 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, } if (set_spte(vcpu, sptep, pte_access, user_fault, write_fault, - dirty, level, gfn, pfn, speculative, true)) { + dirty, level, gfn, pfn, speculative, true, + reset_host_protection)) { if (write_fault) *ptwrite = 1; kvm_x86_ops->tlb_flush(vcpu); @@ -1877,8 +1926,7 @@ static void mmu_set_spte(struct kvm_vcpu *vcpu, u64 *sptep, page_header_update_slot(vcpu->kvm, sptep, gfn); if (!was_rmapped) { rmap_count = rmap_add(vcpu, sptep, gfn); - if (!is_rmap_spte(*sptep)) - kvm_release_pfn_clean(pfn); + kvm_release_pfn_clean(pfn); if (rmap_count > RMAP_RECYCLE_THRESHOLD) rmap_recycle(vcpu, sptep, gfn); } else { @@ -1909,7 +1957,7 @@ static int __direct_map(struct kvm_vcpu *vcpu, gpa_t v, int write, if (iterator.level == level) { mmu_set_spte(vcpu, iterator.sptep, ACC_ALL, ACC_ALL, 0, write, 1, &pt_write, - level, gfn, pfn, false); + level, gfn, pfn, false, true); ++vcpu->stat.pf_fixed; break; } diff --git a/trunk/arch/x86/kvm/paging_tmpl.h b/trunk/arch/x86/kvm/paging_tmpl.h index d2fec9c12d22..72558f8ff3f5 100644 --- a/trunk/arch/x86/kvm/paging_tmpl.h +++ b/trunk/arch/x86/kvm/paging_tmpl.h @@ -273,9 +273,13 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page, if (mmu_notifier_retry(vcpu, vcpu->arch.update_pte.mmu_seq)) return; kvm_get_pfn(pfn); + /* + * we call mmu_set_spte() with reset_host_protection = true beacuse that + * vcpu->arch.update_pte.pfn was fetched from get_user_pages(write = 1). + */ mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0, gpte & PT_DIRTY_MASK, NULL, PT_PAGE_TABLE_LEVEL, - gpte_to_gfn(gpte), pfn, true); + gpte_to_gfn(gpte), pfn, true, true); } /* @@ -308,7 +312,7 @@ static u64 *FNAME(fetch)(struct kvm_vcpu *vcpu, gva_t addr, user_fault, write_fault, gw->ptes[gw->level-1] & PT_DIRTY_MASK, ptwrite, level, - gw->gfn, pfn, false); + gw->gfn, pfn, false, true); break; } @@ -558,6 +562,7 @@ static void FNAME(prefetch_page)(struct kvm_vcpu *vcpu, static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) { int i, offset, nr_present; + bool reset_host_protection; offset = nr_present = 0; @@ -595,9 +600,16 @@ static int FNAME(sync_page)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp) nr_present++; pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte); + if (!(sp->spt[i] & SPTE_HOST_WRITEABLE)) { + pte_access &= ~ACC_WRITE_MASK; + reset_host_protection = 0; + } else { + reset_host_protection = 1; + } set_spte(vcpu, &sp->spt[i], pte_access, 0, 0, is_dirty_gpte(gpte), PT_PAGE_TABLE_LEVEL, gfn, - spte_to_pfn(sp->spt[i]), true, false); + spte_to_pfn(sp->spt[i]), true, false, + reset_host_protection); } return !nr_present; diff --git a/trunk/arch/x86/kvm/svm.c b/trunk/arch/x86/kvm/svm.c index 944cc9c04b3c..c17404add91f 100644 --- a/trunk/arch/x86/kvm/svm.c +++ b/trunk/arch/x86/kvm/svm.c @@ -767,6 +767,8 @@ static void svm_vcpu_load(struct kvm_vcpu *vcpu, int cpu) rdtscll(tsc_this); delta = vcpu->arch.host_tsc - tsc_this; svm->vmcb->control.tsc_offset += delta; + if (is_nested(svm)) + svm->nested.hsave->control.tsc_offset += delta; vcpu->cpu = cpu; kvm_migrate_timers(vcpu); svm->asid_generation = 0; @@ -2057,10 +2059,14 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) switch (ecx) { case MSR_IA32_TSC: { - u64 tsc; + u64 tsc_offset; + + if (is_nested(svm)) + tsc_offset = svm->nested.hsave->control.tsc_offset; + else + tsc_offset = svm->vmcb->control.tsc_offset; - rdtscll(tsc); - *data = svm->vmcb->control.tsc_offset + tsc; + *data = tsc_offset + native_read_tsc(); break; } case MSR_K6_STAR: @@ -2146,10 +2152,17 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) switch (ecx) { case MSR_IA32_TSC: { - u64 tsc; + u64 tsc_offset = data - native_read_tsc(); + u64 g_tsc_offset = 0; + + if (is_nested(svm)) { + g_tsc_offset = svm->vmcb->control.tsc_offset - + svm->nested.hsave->control.tsc_offset; + svm->nested.hsave->control.tsc_offset = tsc_offset; + } + + svm->vmcb->control.tsc_offset = tsc_offset + g_tsc_offset; - rdtscll(tsc); - svm->vmcb->control.tsc_offset = data - tsc; break; } case MSR_K6_STAR: diff --git a/trunk/arch/x86/kvm/vmx.c b/trunk/arch/x86/kvm/vmx.c index f3812014bd0b..ed53b42caba1 100644 --- a/trunk/arch/x86/kvm/vmx.c +++ b/trunk/arch/x86/kvm/vmx.c @@ -709,7 +709,7 @@ static void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) if (vcpu->cpu != cpu) { vcpu_clear(vmx); kvm_migrate_timers(vcpu); - vpid_sync_vcpu_all(vmx); + set_bit(KVM_REQ_TLB_FLUSH, &vcpu->requests); local_irq_disable(); list_add(&vmx->local_vcpus_link, &per_cpu(vcpus_on_cpu, cpu)); diff --git a/trunk/arch/x86/kvm/x86.c b/trunk/arch/x86/kvm/x86.c index be451ee44249..9b9695322f56 100644 --- a/trunk/arch/x86/kvm/x86.c +++ b/trunk/arch/x86/kvm/x86.c @@ -1591,6 +1591,8 @@ static int kvm_dev_ioctl_get_supported_cpuid(struct kvm_cpuid2 *cpuid, if (cpuid->nent < 1) goto out; + if (cpuid->nent > KVM_MAX_CPUID_ENTRIES) + cpuid->nent = KVM_MAX_CPUID_ENTRIES; r = -ENOMEM; cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry2) * cpuid->nent); if (!cpuid_entries) diff --git a/trunk/arch/x86/lib/Makefile b/trunk/arch/x86/lib/Makefile index 3e549b8ec8c9..85f5db95c60f 100644 --- a/trunk/arch/x86/lib/Makefile +++ b/trunk/arch/x86/lib/Makefile @@ -15,8 +15,10 @@ ifeq ($(CONFIG_X86_32),y) obj-y += atomic64_32.o lib-y += checksum_32.o lib-y += strstr_32.o - lib-y += semaphore_32.o string_32.o cmpxchg8b_emu.o - + lib-y += semaphore_32.o string_32.o +ifneq ($(CONFIG_X86_CMPXCHG64),y) + lib-y += cmpxchg8b_emu.o +endif lib-$(CONFIG_X86_USE_3DNOW) += mmx_32.o else obj-y += io_64.o iomap_copy_64.o diff --git a/trunk/drivers/char/agp/parisc-agp.c b/trunk/drivers/char/agp/parisc-agp.c index 60ab75104da9..1c129211302d 100644 --- a/trunk/drivers/char/agp/parisc-agp.c +++ b/trunk/drivers/char/agp/parisc-agp.c @@ -217,7 +217,7 @@ static const struct agp_bridge_driver parisc_agp_driver = { .configure = parisc_agp_configure, .fetch_size = parisc_agp_fetch_size, .tlb_flush = parisc_agp_tlbflush, - .mask_memory = parisc_agp_page_mask_memory, + .mask_memory = parisc_agp_mask_memory, .masks = parisc_agp_masks, .agp_enable = parisc_agp_enable, .cache_flush = global_cache_flush, diff --git a/trunk/drivers/connector/cn_proc.c b/trunk/drivers/connector/cn_proc.c index abf4a2529f80..60697909ebdb 100644 --- a/trunk/drivers/connector/cn_proc.c +++ b/trunk/drivers/connector/cn_proc.c @@ -227,7 +227,8 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) * cn_proc_mcast_ctl * @data: message sent from userspace via the connector */ -static void cn_proc_mcast_ctl(struct cn_msg *msg) +static void cn_proc_mcast_ctl(struct cn_msg *msg, + struct netlink_skb_parms *nsp) { enum proc_cn_mcast_op *mc_op = NULL; int err = 0; diff --git a/trunk/drivers/edac/amd64_edac.c b/trunk/drivers/edac/amd64_edac.c index 4e551e63b6dc..4f4ac82382f7 100644 --- a/trunk/drivers/edac/amd64_edac.c +++ b/trunk/drivers/edac/amd64_edac.c @@ -15,8 +15,8 @@ module_param(ecc_enable_override, int, 0644); /* Lookup table for all possible MC control instances */ struct amd64_pvt; -static struct mem_ctl_info *mci_lookup[MAX_NUMNODES]; -static struct amd64_pvt *pvt_lookup[MAX_NUMNODES]; +static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES]; +static struct amd64_pvt *pvt_lookup[EDAC_MAX_NUMNODES]; /* * See F2x80 for K8 and F2x[1,0]80 for Fam10 and later. The table below is only @@ -189,7 +189,10 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) /* Map from a CSROW entry to the mask entry that operates on it */ static inline u32 amd64_map_to_dcs_mask(struct amd64_pvt *pvt, int csrow) { - return csrow >> (pvt->num_dcsm >> 3); + if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_F) + return csrow; + else + return csrow >> 1; } /* return the 'base' address the i'th CS entry of the 'dct' DRAM controller */ @@ -279,29 +282,26 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, intlv_en = pvt->dram_IntlvEn[0]; if (intlv_en == 0) { - for (node_id = 0; ; ) { + for (node_id = 0; node_id < DRAM_REG_COUNT; node_id++) { if (amd64_base_limit_match(pvt, sys_addr, node_id)) - break; - - if (++node_id >= DRAM_REG_COUNT) - goto err_no_match; + goto found; } - goto found; + goto err_no_match; } - if (unlikely((intlv_en != (0x01 << 8)) && - (intlv_en != (0x03 << 8)) && - (intlv_en != (0x07 << 8)))) { + if (unlikely((intlv_en != 0x01) && + (intlv_en != 0x03) && + (intlv_en != 0x07))) { amd64_printk(KERN_WARNING, "junk value of 0x%x extracted from " "IntlvEn field of DRAM Base Register for node 0: " - "This probably indicates a BIOS bug.\n", intlv_en); + "this probably indicates a BIOS bug.\n", intlv_en); return NULL; } bits = (((u32) sys_addr) >> 12) & intlv_en; for (node_id = 0; ; ) { - if ((pvt->dram_limit[node_id] & intlv_en) == bits) + if ((pvt->dram_IntlvSel[node_id] & intlv_en) == bits) break; /* intlv_sel field matches */ if (++node_id >= DRAM_REG_COUNT) @@ -311,10 +311,10 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, /* sanity test for sys_addr */ if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { amd64_printk(KERN_WARNING, - "%s(): sys_addr 0x%lx falls outside base/limit " - "address range for node %d with node interleaving " - "enabled.\n", __func__, (unsigned long)sys_addr, - node_id); + "%s(): sys_addr 0x%llx falls outside base/limit " + "address range for node %d with node interleaving " + "enabled.\n", + __func__, sys_addr, node_id); return NULL; } @@ -377,7 +377,7 @@ static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr) * base/mask register pair, test the condition shown near the start of * section 3.5.4 (p. 84, BKDG #26094, K8, revA-E). */ - for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) { + for (csrow = 0; csrow < pvt->cs_count; csrow++) { /* This DRAM chip select is disabled on this node */ if ((pvt->dcsb0[csrow] & K8_DCSB_CS_ENABLE) == 0) @@ -734,7 +734,7 @@ static void find_csrow_limits(struct mem_ctl_info *mci, int csrow, u64 base, mask; pvt = mci->pvt_info; - BUG_ON((csrow < 0) || (csrow >= CHIPSELECT_COUNT)); + BUG_ON((csrow < 0) || (csrow >= pvt->cs_count)); base = base_from_dct_base(pvt, csrow); mask = mask_from_dct_mask(pvt, csrow); @@ -962,35 +962,27 @@ static void amd64_read_dbam_reg(struct amd64_pvt *pvt) */ static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt) { - if (pvt->ext_model >= OPTERON_CPU_REV_F) { + + if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_F) { + pvt->dcsb_base = REV_E_DCSB_BASE_BITS; + pvt->dcsm_mask = REV_E_DCSM_MASK_BITS; + pvt->dcs_mask_notused = REV_E_DCS_NOTUSED_BITS; + pvt->dcs_shift = REV_E_DCS_SHIFT; + pvt->cs_count = 8; + pvt->num_dcsm = 8; + } else { pvt->dcsb_base = REV_F_F1Xh_DCSB_BASE_BITS; pvt->dcsm_mask = REV_F_F1Xh_DCSM_MASK_BITS; pvt->dcs_mask_notused = REV_F_F1Xh_DCS_NOTUSED_BITS; pvt->dcs_shift = REV_F_F1Xh_DCS_SHIFT; - switch (boot_cpu_data.x86) { - case 0xf: - pvt->num_dcsm = REV_F_DCSM_COUNT; - break; - - case 0x10: - pvt->num_dcsm = F10_DCSM_COUNT; - break; - - case 0x11: - pvt->num_dcsm = F11_DCSM_COUNT; - break; - - default: - amd64_printk(KERN_ERR, "Unsupported family!\n"); - break; + if (boot_cpu_data.x86 == 0x11) { + pvt->cs_count = 4; + pvt->num_dcsm = 2; + } else { + pvt->cs_count = 8; + pvt->num_dcsm = 4; } - } else { - pvt->dcsb_base = REV_E_DCSB_BASE_BITS; - pvt->dcsm_mask = REV_E_DCSM_MASK_BITS; - pvt->dcs_mask_notused = REV_E_DCS_NOTUSED_BITS; - pvt->dcs_shift = REV_E_DCS_SHIFT; - pvt->num_dcsm = REV_E_DCSM_COUNT; } } @@ -1003,7 +995,7 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) amd64_set_dct_base_and_mask(pvt); - for (cs = 0; cs < CHIPSELECT_COUNT; cs++) { + for (cs = 0; cs < pvt->cs_count; cs++) { reg = K8_DCSB0 + (cs * 4); err = pci_read_config_dword(pvt->dram_f2_ctl, reg, &pvt->dcsb0[cs]); @@ -1130,7 +1122,7 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram) debugf0("Reading K8_DRAM_BASE_LOW failed\n"); /* Extract parts into separate data entries */ - pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8; + pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 24; pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7; pvt->dram_rw_en[dram] = (low & 0x3); @@ -1143,7 +1135,7 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram) * Extract parts into separate data entries. Limit is the HIGHEST memory * location of the region, so lower 24 bits need to be all ones */ - pvt->dram_limit[dram] = (((u64) low & 0xFFFF0000) << 8) | 0x00FFFFFF; + pvt->dram_limit[dram] = (((u64) low & 0xFFFF0000) << 24) | 0x00FFFFFF; pvt->dram_IntlvSel[dram] = (low >> 8) & 0x7; pvt->dram_DstNode[dram] = (low & 0x7); } @@ -1193,7 +1185,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, * different from the node that detected the error. */ src_mci = find_mc_by_sys_addr(mci, SystemAddress); - if (src_mci) { + if (!src_mci) { amd64_mc_printk(mci, KERN_ERR, "failed to map error address 0x%lx to a node\n", (unsigned long)SystemAddress); @@ -1376,8 +1368,8 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) pvt->dram_IntlvEn[dram] = (low_base >> 8) & 0x7; - pvt->dram_base[dram] = (((((u64) high_base & 0x000000FF) << 32) | - ((u64) low_base & 0xFFFF0000))) << 8; + pvt->dram_base[dram] = (((u64)high_base & 0x000000FF) << 40) | + (((u64)low_base & 0xFFFF0000) << 24); low_offset = K8_DRAM_LIMIT_LOW + (dram << 3); high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); @@ -1398,9 +1390,9 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) * Extract address values and form a LIMIT address. Limit is the HIGHEST * memory location of the region, so low 24 bits need to be all ones. */ - low_limit |= 0x0000FFFF; - pvt->dram_limit[dram] = - ((((u64) high_limit << 32) + (u64) low_limit) << 8) | (0xFF); + pvt->dram_limit[dram] = (((u64)high_limit & 0x000000FF) << 40) | + (((u64) low_limit & 0xFFFF0000) << 24) | + 0x00FFFFFF; } static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) @@ -1566,7 +1558,7 @@ static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs) debugf1("InputAddr=0x%x channelselect=%d\n", in_addr, cs); - for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) { + for (csrow = 0; csrow < pvt->cs_count; csrow++) { cs_base = amd64_get_dct_base(pvt, cs, csrow); if (!(cs_base & K8_DCSB_CS_ENABLE)) @@ -2497,7 +2489,7 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) * NOTE: CPU Revision Dependent code * * Input: - * @csrow_nr ChipSelect Row Number (0..CHIPSELECT_COUNT-1) + * @csrow_nr ChipSelect Row Number (0..pvt->cs_count-1) * k8 private pointer to --> * DRAM Bank Address mapping register * node_id @@ -2577,7 +2569,7 @@ static int amd64_init_csrows(struct mem_ctl_info *mci) (pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled" ); - for (i = 0; i < CHIPSELECT_COUNT; i++) { + for (i = 0; i < pvt->cs_count; i++) { csrow = &mci->csrows[i]; if ((pvt->dcsb0[i] & K8_DCSB_CS_ENABLE) == 0) { @@ -2988,7 +2980,7 @@ static int amd64_init_2nd_stage(struct amd64_pvt *pvt) goto err_exit; ret = -ENOMEM; - mci = edac_mc_alloc(0, CHIPSELECT_COUNT, pvt->channel_count, node_id); + mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, node_id); if (!mci) goto err_exit; diff --git a/trunk/drivers/edac/amd64_edac.h b/trunk/drivers/edac/amd64_edac.h index 8ea07e2715dc..c6f359a85207 100644 --- a/trunk/drivers/edac/amd64_edac.h +++ b/trunk/drivers/edac/amd64_edac.h @@ -132,6 +132,8 @@ #define EDAC_AMD64_VERSION " Ver: 3.2.0 " __DATE__ #define EDAC_MOD_STR "amd64_edac" +#define EDAC_MAX_NUMNODES 8 + /* Extended Model from CPUID, for CPU Revision numbers */ #define OPTERON_CPU_LE_REV_C 0 #define OPTERON_CPU_REV_D 1 @@ -142,7 +144,7 @@ #define OPTERON_CPU_REV_FA 5 /* Hardware limit on ChipSelect rows per MC and processors per system */ -#define CHIPSELECT_COUNT 8 +#define MAX_CS_COUNT 8 #define DRAM_REG_COUNT 8 @@ -193,7 +195,6 @@ */ #define REV_E_DCSB_BASE_BITS (0xFFE0FE00ULL) #define REV_E_DCS_SHIFT 4 -#define REV_E_DCSM_COUNT 8 #define REV_F_F1Xh_DCSB_BASE_BITS (0x1FF83FE0ULL) #define REV_F_F1Xh_DCS_SHIFT 8 @@ -204,9 +205,6 @@ */ #define REV_F_DCSB_BASE_BITS (0x1FF83FE0ULL) #define REV_F_DCS_SHIFT 8 -#define REV_F_DCSM_COUNT 4 -#define F10_DCSM_COUNT 4 -#define F11_DCSM_COUNT 2 /* DRAM CS Mask Registers */ #define K8_DCSM0 0x60 @@ -374,13 +372,11 @@ enum { #define SET_NB_DRAM_INJECTION_WRITE(word, bits) \ (BIT(((word) & 0xF) + 20) | \ - BIT(17) | \ - ((bits) & 0xF)) + BIT(17) | bits) #define SET_NB_DRAM_INJECTION_READ(word, bits) \ (BIT(((word) & 0xF) + 20) | \ - BIT(16) | \ - ((bits) & 0xF)) + BIT(16) | bits) #define K8_NBCAP 0xE8 #define K8_NBCAP_CORES (BIT(12)|BIT(13)) @@ -445,12 +441,12 @@ struct amd64_pvt { u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */ /* DRAM CS Base Address Registers F2x[1,0][5C:40] */ - u32 dcsb0[CHIPSELECT_COUNT]; - u32 dcsb1[CHIPSELECT_COUNT]; + u32 dcsb0[MAX_CS_COUNT]; + u32 dcsb1[MAX_CS_COUNT]; /* DRAM CS Mask Registers F2x[1,0][6C:60] */ - u32 dcsm0[CHIPSELECT_COUNT]; - u32 dcsm1[CHIPSELECT_COUNT]; + u32 dcsm0[MAX_CS_COUNT]; + u32 dcsm1[MAX_CS_COUNT]; /* * Decoded parts of DRAM BASE and LIMIT Registers @@ -470,6 +466,7 @@ struct amd64_pvt { */ u32 dcsb_base; /* DCSB base bits */ u32 dcsm_mask; /* DCSM mask bits */ + u32 cs_count; /* num chip selects (== num DCSB registers) */ u32 num_dcsm; /* Number of DCSM registers */ u32 dcs_mask_notused; /* DCSM notused mask bits */ u32 dcs_shift; /* DCSB and DCSM shift value */ diff --git a/trunk/drivers/edac/amd64_edac_inj.c b/trunk/drivers/edac/amd64_edac_inj.c index d3675b76b3a7..29f1f7a612d9 100644 --- a/trunk/drivers/edac/amd64_edac_inj.c +++ b/trunk/drivers/edac/amd64_edac_inj.c @@ -1,5 +1,11 @@ #include "amd64_edac.h" +static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf) +{ + struct amd64_pvt *pvt = mci->pvt_info; + return sprintf(buf, "0x%x\n", pvt->injection.section); +} + /* * store error injection section value which refers to one of 4 16-byte sections * within a 64-byte cacheline @@ -15,12 +21,26 @@ static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci, ret = strict_strtoul(data, 10, &value); if (ret != -EINVAL) { + + if (value > 3) { + amd64_printk(KERN_WARNING, + "%s: invalid section 0x%lx\n", + __func__, value); + return -EINVAL; + } + pvt->injection.section = (u32) value; return count; } return ret; } +static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf) +{ + struct amd64_pvt *pvt = mci->pvt_info; + return sprintf(buf, "0x%x\n", pvt->injection.word); +} + /* * store error injection word value which refers to one of 9 16-bit word of the * 16-byte (128-bit + ECC bits) section @@ -37,14 +57,25 @@ static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci, ret = strict_strtoul(data, 10, &value); if (ret != -EINVAL) { - value = (value <= 8) ? value : 0; - pvt->injection.word = (u32) value; + if (value > 8) { + amd64_printk(KERN_WARNING, + "%s: invalid word 0x%lx\n", + __func__, value); + return -EINVAL; + } + pvt->injection.word = (u32) value; return count; } return ret; } +static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf) +{ + struct amd64_pvt *pvt = mci->pvt_info; + return sprintf(buf, "0x%x\n", pvt->injection.bit_map); +} + /* * store 16 bit error injection vector which enables injecting errors to the * corresponding bit within the error injection word above. When used during a @@ -60,8 +91,14 @@ static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci, ret = strict_strtoul(data, 16, &value); if (ret != -EINVAL) { - pvt->injection.bit_map = (u32) value & 0xFFFF; + if (value & 0xFFFF0000) { + amd64_printk(KERN_WARNING, + "%s: invalid EccVector: 0x%lx\n", + __func__, value); + return -EINVAL; + } + pvt->injection.bit_map = (u32) value; return count; } return ret; @@ -147,7 +184,7 @@ struct mcidev_sysfs_attribute amd64_inj_attrs[] = { .name = "inject_section", .mode = (S_IRUGO | S_IWUSR) }, - .show = NULL, + .show = amd64_inject_section_show, .store = amd64_inject_section_store, }, { @@ -155,7 +192,7 @@ struct mcidev_sysfs_attribute amd64_inj_attrs[] = { .name = "inject_word", .mode = (S_IRUGO | S_IWUSR) }, - .show = NULL, + .show = amd64_inject_word_show, .store = amd64_inject_word_store, }, { @@ -163,7 +200,7 @@ struct mcidev_sysfs_attribute amd64_inj_attrs[] = { .name = "inject_ecc_vector", .mode = (S_IRUGO | S_IWUSR) }, - .show = NULL, + .show = amd64_inject_ecc_vector_show, .store = amd64_inject_ecc_vector_store, }, { diff --git a/trunk/drivers/firmware/iscsi_ibft.c b/trunk/drivers/firmware/iscsi_ibft.c index 420a96e7f2db..051d1ebbd287 100644 --- a/trunk/drivers/firmware/iscsi_ibft.c +++ b/trunk/drivers/firmware/iscsi_ibft.c @@ -939,7 +939,7 @@ static int __init ibft_init(void) if (ibft_addr) { printk(KERN_INFO "iBFT detected at 0x%llx.\n", - (u64)virt_to_phys((void *)ibft_addr)); + (u64)isa_virt_to_bus(ibft_addr)); rc = ibft_check_device(); if (rc) diff --git a/trunk/drivers/firmware/iscsi_ibft_find.c b/trunk/drivers/firmware/iscsi_ibft_find.c index d53fbbfefa3e..dfb15c06c88f 100644 --- a/trunk/drivers/firmware/iscsi_ibft_find.c +++ b/trunk/drivers/firmware/iscsi_ibft_find.c @@ -65,10 +65,10 @@ void __init reserve_ibft_region(void) * so skip that area */ if (pos == VGA_MEM) pos += VGA_SIZE; - virt = phys_to_virt(pos); + virt = isa_bus_to_virt(pos); if (memcmp(virt, IBFT_SIGN, IBFT_SIGN_LEN) == 0) { unsigned long *addr = - (unsigned long *)phys_to_virt(pos + 4); + (unsigned long *)isa_bus_to_virt(pos + 4); len = *addr; /* if the length of the table extends past 1M, * the table cannot be valid. */ diff --git a/trunk/drivers/hwmon/lis3lv02d_spi.c b/trunk/drivers/hwmon/lis3lv02d_spi.c index ecd739534f6a..82b16808a274 100644 --- a/trunk/drivers/hwmon/lis3lv02d_spi.c +++ b/trunk/drivers/hwmon/lis3lv02d_spi.c @@ -83,7 +83,8 @@ static int __devexit lis302dl_spi_remove(struct spi_device *spi) struct lis3lv02d *lis3 = spi_get_drvdata(spi); lis3lv02d_joystick_disable(); lis3lv02d_poweroff(lis3); - return 0; + + return lis3lv02d_remove_fs(&lis3_dev); } #ifdef CONFIG_PM diff --git a/trunk/drivers/ide/ide-proc.c b/trunk/drivers/ide/ide-proc.c index 28d09a5d8450..017c09540c2f 100644 --- a/trunk/drivers/ide/ide-proc.c +++ b/trunk/drivers/ide/ide-proc.c @@ -273,14 +273,8 @@ static const struct ide_proc_devset ide_generic_settings[] = { static void proc_ide_settings_warn(void) { - static int warned; - - if (warned) - return; - - printk(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is " + printk_once(KERN_WARNING "Warning: /proc/ide/hd?/settings interface is " "obsolete, and will be removed soon!\n"); - warned = 1; } static int ide_settings_proc_show(struct seq_file *m, void *v) diff --git a/trunk/drivers/ide/sis5513.c b/trunk/drivers/ide/sis5513.c index afca22beaadf..3b88eba04c9c 100644 --- a/trunk/drivers/ide/sis5513.c +++ b/trunk/drivers/ide/sis5513.c @@ -2,7 +2,7 @@ * Copyright (C) 1999-2000 Andre Hedrick * Copyright (C) 2002 Lionel Bouton , Maintainer * Copyright (C) 2003 Vojtech Pavlik - * Copyright (C) 2007 Bartlomiej Zolnierkiewicz + * Copyright (C) 2007-2009 Bartlomiej Zolnierkiewicz * * May be copied or modified under the terms of the GNU General Public License * @@ -281,11 +281,13 @@ static void config_drive_art_rwp(ide_drive_t *drive) pci_read_config_byte(dev, 0x4b, ®4bh); + rw_prefetch = reg4bh & ~(0x11 << drive->dn); + if (drive->media == ide_disk) - rw_prefetch = 0x11 << drive->dn; + rw_prefetch |= 0x11 << drive->dn; - if ((reg4bh & (0x11 << drive->dn)) != rw_prefetch) - pci_write_config_byte(dev, 0x4b, reg4bh|rw_prefetch); + if (reg4bh != rw_prefetch) + pci_write_config_byte(dev, 0x4b, rw_prefetch); } static void sis_set_pio_mode(ide_drive_t *drive, const u8 pio) diff --git a/trunk/drivers/isdn/capi/capi.c b/trunk/drivers/isdn/capi/capi.c index 2d8352419c0d..65bf91e16a42 100644 --- a/trunk/drivers/isdn/capi/capi.c +++ b/trunk/drivers/isdn/capi/capi.c @@ -603,7 +603,7 @@ static void capi_recv_message(struct capi20_appl *ap, struct sk_buff *skb) if (CAPIMSG_CMD(skb->data) == CAPI_CONNECT_B3_CONF) { u16 info = CAPIMSG_U16(skb->data, 12); // Info field - if (info == 0) { + if ((info & 0xff00) == 0) { mutex_lock(&cdev->ncci_list_mtx); capincci_alloc(cdev, CAPIMSG_NCCI(skb->data)); mutex_unlock(&cdev->ncci_list_mtx); diff --git a/trunk/drivers/isdn/capi/capidrv.c b/trunk/drivers/isdn/capi/capidrv.c index 650120261abf..3e6d17f42a98 100644 --- a/trunk/drivers/isdn/capi/capidrv.c +++ b/trunk/drivers/isdn/capi/capidrv.c @@ -40,7 +40,7 @@ static int debugmode = 0; MODULE_DESCRIPTION("CAPI4Linux: Interface to ISDN4Linux"); MODULE_AUTHOR("Carsten Paeth"); MODULE_LICENSE("GPL"); -module_param(debugmode, uint, 0); +module_param(debugmode, uint, S_IRUGO|S_IWUSR); /* -------- type definitions ----------------------------------------- */ @@ -671,8 +671,8 @@ static void n0(capidrv_contr * card, capidrv_ncci * ncci) NULL, /* Useruserdata */ /* $$$$ */ NULL /* Facilitydataarray */ ); - send_message(card, &cmsg); plci_change_state(card, ncci->plcip, EV_PLCI_DISCONNECT_REQ); + send_message(card, &cmsg); cmd.command = ISDN_STAT_BHUP; cmd.driver = card->myid; @@ -924,8 +924,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg) */ capi_cmsg_answer(cmsg); cmsg->Reject = 1; /* ignore */ - send_message(card, cmsg); plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); + send_message(card, cmsg); printk(KERN_INFO "capidrv-%d: incoming call %s,%d,%d,%s ignored\n", card->contrnr, cmd.parm.setup.phone, @@ -974,8 +974,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg) case 2: /* Call will be rejected. */ capi_cmsg_answer(cmsg); cmsg->Reject = 2; /* reject call, normal call clearing */ - send_message(card, cmsg); plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); + send_message(card, cmsg); break; default: @@ -983,8 +983,8 @@ static void handle_incoming_call(capidrv_contr * card, _cmsg * cmsg) capi_cmsg_answer(cmsg); cmsg->Reject = 8; /* reject call, destination out of order */ - send_message(card, cmsg); plci_change_state(card, plcip, EV_PLCI_CONNECT_REJECT); + send_message(card, cmsg); break; } return; @@ -1020,8 +1020,8 @@ static void handle_plci(_cmsg * cmsg) card->bchans[plcip->chan].disconnecting = 1; plci_change_state(card, plcip, EV_PLCI_DISCONNECT_IND); capi_cmsg_answer(cmsg); - send_message(card, cmsg); plci_change_state(card, plcip, EV_PLCI_DISCONNECT_RESP); + send_message(card, cmsg); break; case CAPI_DISCONNECT_CONF: /* plci */ @@ -1078,8 +1078,8 @@ static void handle_plci(_cmsg * cmsg) if (card->bchans[plcip->chan].incoming) { capi_cmsg_answer(cmsg); - send_message(card, cmsg); plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND); + send_message(card, cmsg); } else { capidrv_ncci *nccip; capi_cmsg_answer(cmsg); @@ -1098,13 +1098,14 @@ static void handle_plci(_cmsg * cmsg) NULL /* NCPI */ ); nccip->msgid = cmsg->Messagenumber; + plci_change_state(card, plcip, + EV_PLCI_CONNECT_ACTIVE_IND); + ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ); send_message(card, cmsg); cmd.command = ISDN_STAT_DCONN; cmd.driver = card->myid; cmd.arg = plcip->chan; card->interface.statcallb(&cmd); - plci_change_state(card, plcip, EV_PLCI_CONNECT_ACTIVE_IND); - ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_REQ); } break; @@ -1193,8 +1194,8 @@ static void handle_ncci(_cmsg * cmsg) goto notfound; capi_cmsg_answer(cmsg); - send_message(card, cmsg); ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_ACTIVE_IND); + send_message(card, cmsg); cmd.command = ISDN_STAT_BCONN; cmd.driver = card->myid; @@ -1222,8 +1223,8 @@ static void handle_ncci(_cmsg * cmsg) 0, /* Reject */ NULL /* NCPI */ ); - send_message(card, cmsg); ncci_change_state(card, nccip, EV_NCCI_CONNECT_B3_RESP); + send_message(card, cmsg); break; } printk(KERN_ERR "capidrv-%d: no mem for ncci, sorry\n", card->contrnr); @@ -1299,8 +1300,8 @@ static void handle_ncci(_cmsg * cmsg) card->bchans[nccip->chan].disconnecting = 1; ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_IND); capi_cmsg_answer(cmsg); - send_message(card, cmsg); ncci_change_state(card, nccip, EV_NCCI_DISCONNECT_B3_RESP); + send_message(card, cmsg); break; case CAPI_DISCONNECT_B3_CONF: /* ncci */ @@ -2014,8 +2015,8 @@ static void send_listen(capidrv_contr *card) card->cipmask, card->cipmask2, NULL, NULL); - send_message(card, &cmdcmsg); listen_change_state(card, EV_LISTEN_REQ); + send_message(card, &cmdcmsg); } static void listentimerfunc(unsigned long x) diff --git a/trunk/drivers/isdn/gigaset/asyncdata.c b/trunk/drivers/isdn/gigaset/asyncdata.c index 234cc5d53312..44a58e6f8f65 100644 --- a/trunk/drivers/isdn/gigaset/asyncdata.c +++ b/trunk/drivers/isdn/gigaset/asyncdata.c @@ -334,7 +334,14 @@ static inline int iraw_loop(unsigned char c, unsigned char *src, int numbytes, return startbytes - numbytes; } -/* process a block of data received from the device +/** + * gigaset_m10x_input() - process a block of data received from the device + * @inbuf: received data and device descriptor structure. + * + * Called by hardware module {ser,usb}_gigaset with a block of received + * bytes. Separates the bytes received over the serial data channel into + * user data and command replies (locked/unlocked) according to the + * current state of the interface. */ void gigaset_m10x_input(struct inbuf_t *inbuf) { @@ -543,16 +550,17 @@ static struct sk_buff *iraw_encode(struct sk_buff *skb, int head, int tail) return iraw_skb; } -/* gigaset_send_skb - * called by common.c to queue an skb for sending - * and start transmission if necessary - * parameters: - * B Channel control structure - * skb +/** + * gigaset_m10x_send_skb() - queue an skb for sending + * @bcs: B channel descriptor structure. + * @skb: data to send. + * + * Called by i4l.c to encode and queue an skb for sending, and start + * transmission if necessary. + * * Return value: - * number of bytes accepted for sending - * (skb->len if ok, 0 if out of buffer space) - * or error code (< 0, eg. -EINVAL) + * number of bytes accepted for sending (skb->len) if ok, + * error code < 0 (eg. -ENOMEM) on error */ int gigaset_m10x_send_skb(struct bc_state *bcs, struct sk_buff *skb) { diff --git a/trunk/drivers/isdn/gigaset/bas-gigaset.c b/trunk/drivers/isdn/gigaset/bas-gigaset.c index 781c4041f7b0..5ed1d99eb9f3 100644 --- a/trunk/drivers/isdn/gigaset/bas-gigaset.c +++ b/trunk/drivers/isdn/gigaset/bas-gigaset.c @@ -134,6 +134,7 @@ struct bas_cardstate { #define BS_ATRDPEND 0x040 /* urb_cmd_in in use */ #define BS_ATWRPEND 0x080 /* urb_cmd_out in use */ #define BS_SUSPEND 0x100 /* USB port suspended */ +#define BS_RESETTING 0x200 /* waiting for HD_RESET_INTERRUPT_PIPE_ACK */ static struct gigaset_driver *driver = NULL; @@ -319,6 +320,21 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) return -EINVAL; } +/* set/clear bits in base connection state, return previous state + */ +static inline int update_basstate(struct bas_cardstate *ucs, + int set, int clear) +{ + unsigned long flags; + int state; + + spin_lock_irqsave(&ucs->lock, flags); + state = ucs->basstate; + ucs->basstate = (state & ~clear) | set; + spin_unlock_irqrestore(&ucs->lock, flags); + return state; +} + /* error_hangup * hang up any existing connection because of an unrecoverable error * This function may be called from any context and takes care of scheduling @@ -350,12 +366,9 @@ static inline void error_hangup(struct bc_state *bcs) */ static inline void error_reset(struct cardstate *cs) { - /* close AT command channel to recover (ignore errors) */ - req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); - - //FIXME try to recover without bothering the user - dev_err(cs->dev, - "unrecoverable error - please disconnect Gigaset base to reset\n"); + /* reset interrupt pipe to recover (ignore errors) */ + update_basstate(cs->hw.bas, BS_RESETTING, 0); + req_submit(cs->bcs, HD_RESET_INTERRUPT_PIPE, 0, BAS_TIMEOUT); } /* check_pending @@ -398,8 +411,13 @@ static void check_pending(struct bas_cardstate *ucs) case HD_DEVICE_INIT_ACK: /* no reply expected */ ucs->pending = 0; break; - /* HD_READ_ATMESSAGE, HD_WRITE_ATMESSAGE, HD_RESET_INTERRUPTPIPE - * are handled separately and should never end up here + case HD_RESET_INTERRUPT_PIPE: + if (!(ucs->basstate & BS_RESETTING)) + ucs->pending = 0; + break; + /* + * HD_READ_ATMESSAGE and HD_WRITE_ATMESSAGE are handled separately + * and should never end up here */ default: dev_warn(&ucs->interface->dev, @@ -449,21 +467,6 @@ static void cmd_in_timeout(unsigned long data) error_reset(cs); } -/* set/clear bits in base connection state, return previous state - */ -inline static int update_basstate(struct bas_cardstate *ucs, - int set, int clear) -{ - unsigned long flags; - int state; - - spin_lock_irqsave(&ucs->lock, flags); - state = ucs->basstate; - ucs->basstate = (state & ~clear) | set; - spin_unlock_irqrestore(&ucs->lock, flags); - return state; -} - /* read_ctrl_callback * USB completion handler for control pipe input * called by the USB subsystem in interrupt context @@ -762,7 +765,8 @@ static void read_int_callback(struct urb *urb) break; case HD_RESET_INTERRUPT_PIPE_ACK: - gig_dbg(DEBUG_USBREQ, "HD_RESET_INTERRUPT_PIPE_ACK"); + update_basstate(ucs, 0, BS_RESETTING); + dev_notice(cs->dev, "interrupt pipe reset\n"); break; case HD_SUSPEND_END: @@ -1331,28 +1335,24 @@ static void read_iso_tasklet(unsigned long data) rcvbuf = urb->transfer_buffer; totleft = urb->actual_length; for (frame = 0; totleft > 0 && frame < BAS_NUMFRAMES; frame++) { - if (unlikely(urb->iso_frame_desc[frame].status)) { + numbytes = urb->iso_frame_desc[frame].actual_length; + if (unlikely(urb->iso_frame_desc[frame].status)) dev_warn(cs->dev, - "isochronous read: frame %d: %s\n", - frame, + "isochronous read: frame %d[%d]: %s\n", + frame, numbytes, get_usb_statmsg( urb->iso_frame_desc[frame].status)); - break; - } - numbytes = urb->iso_frame_desc[frame].actual_length; - if (unlikely(numbytes > BAS_MAXFRAME)) { + if (unlikely(numbytes > BAS_MAXFRAME)) dev_warn(cs->dev, "isochronous read: frame %d: " "numbytes (%d) > BAS_MAXFRAME\n", frame, numbytes); - break; - } if (unlikely(numbytes > totleft)) { dev_warn(cs->dev, "isochronous read: frame %d: " "numbytes (%d) > totleft (%d)\n", frame, numbytes, totleft); - break; + numbytes = totleft; } offset = urb->iso_frame_desc[frame].offset; if (unlikely(offset + numbytes > BAS_INBUFSIZE)) { @@ -1361,7 +1361,7 @@ static void read_iso_tasklet(unsigned long data) "offset (%d) + numbytes (%d) " "> BAS_INBUFSIZE\n", frame, offset, numbytes); - break; + numbytes = BAS_INBUFSIZE - offset; } gigaset_isoc_receive(rcvbuf + offset, numbytes, bcs); totleft -= numbytes; @@ -1433,6 +1433,7 @@ static void req_timeout(unsigned long data) case HD_CLOSE_ATCHANNEL: dev_err(bcs->cs->dev, "timeout closing AT channel\n"); + error_reset(bcs->cs); break; case HD_CLOSE_B2CHANNEL: @@ -1442,6 +1443,13 @@ static void req_timeout(unsigned long data) error_reset(bcs->cs); break; + case HD_RESET_INTERRUPT_PIPE: + /* error recovery escalation */ + dev_err(bcs->cs->dev, + "reset interrupt pipe timeout, attempting USB reset\n"); + usb_queue_reset_device(bcs->cs->hw.bas->interface); + break; + default: dev_warn(bcs->cs->dev, "request 0x%02x timed out, clearing\n", pending); @@ -1934,6 +1942,15 @@ static int gigaset_write_cmd(struct cardstate *cs, goto notqueued; } + /* translate "+++" escape sequence sent as a single separate command + * into "close AT channel" command for error recovery + * The next command will reopen the AT channel automatically. + */ + if (len == 3 && !memcmp(buf, "+++", 3)) { + rc = req_submit(cs->bcs, HD_CLOSE_ATCHANNEL, 0, BAS_TIMEOUT); + goto notqueued; + } + if (len > IF_WRITEBUF) len = IF_WRITEBUF; if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { diff --git a/trunk/drivers/isdn/gigaset/common.c b/trunk/drivers/isdn/gigaset/common.c index e4141bf8b2f3..33dcd8d72b7c 100644 --- a/trunk/drivers/isdn/gigaset/common.c +++ b/trunk/drivers/isdn/gigaset/common.c @@ -22,6 +22,12 @@ #define DRIVER_AUTHOR "Hansjoerg Lipp , Tilman Schmidt , Stefan Eilers" #define DRIVER_DESC "Driver for Gigaset 307x" +#ifdef CONFIG_GIGASET_DEBUG +#define DRIVER_DESC_DEBUG " (debug build)" +#else +#define DRIVER_DESC_DEBUG "" +#endif + /* Module parameters */ int gigaset_debuglevel = DEBUG_DEFAULT; EXPORT_SYMBOL_GPL(gigaset_debuglevel); @@ -32,6 +38,17 @@ MODULE_PARM_DESC(debug, "debug level"); #define VALID_MINOR 0x01 #define VALID_ID 0x02 +/** + * gigaset_dbg_buffer() - dump data in ASCII and hex for debugging + * @level: debugging level. + * @msg: message prefix. + * @len: number of bytes to dump. + * @buf: data to dump. + * + * If the current debugging level includes one of the bits set in @level, + * @len bytes starting at @buf are logged to dmesg at KERN_DEBUG prio, + * prefixed by the text @msg. + */ void gigaset_dbg_buffer(enum debuglevel level, const unsigned char *msg, size_t len, const unsigned char *buf) { @@ -274,6 +291,20 @@ static void clear_events(struct cardstate *cs) spin_unlock_irqrestore(&cs->ev_lock, flags); } +/** + * gigaset_add_event() - add event to device event queue + * @cs: device descriptor structure. + * @at_state: connection state structure. + * @type: event type. + * @ptr: pointer parameter for event. + * @parameter: integer parameter for event. + * @arg: pointer parameter for event. + * + * Allocate an event queue entry from the device's event queue, and set it up + * with the parameters given. + * + * Return value: added event + */ struct event_t *gigaset_add_event(struct cardstate *cs, struct at_state_t *at_state, int type, void *ptr, int parameter, void *arg) @@ -398,6 +429,15 @@ static void make_invalid(struct cardstate *cs, unsigned mask) spin_unlock_irqrestore(&drv->lock, flags); } +/** + * gigaset_freecs() - free all associated ressources of a device + * @cs: device descriptor structure. + * + * Stops all tasklets and timers, unregisters the device from all + * subsystems it was registered to, deallocates the device structure + * @cs and all structures referenced from it. + * Operations on the device should be stopped before calling this. + */ void gigaset_freecs(struct cardstate *cs) { int i; @@ -506,7 +546,12 @@ static void gigaset_inbuf_init(struct inbuf_t *inbuf, struct bc_state *bcs, inbuf->inputstate = inputstate; } -/* append received bytes to inbuf */ +/** + * gigaset_fill_inbuf() - append received data to input buffer + * @inbuf: buffer structure. + * @src: received data. + * @numbytes: number of bytes received. + */ int gigaset_fill_inbuf(struct inbuf_t *inbuf, const unsigned char *src, unsigned numbytes) { @@ -606,20 +651,22 @@ static struct bc_state *gigaset_initbcs(struct bc_state *bcs, return NULL; } -/* gigaset_initcs +/** + * gigaset_initcs() - initialize device structure + * @drv: hardware driver the device belongs to + * @channels: number of B channels supported by device + * @onechannel: !=0 if B channel data and AT commands share one + * communication channel (M10x), + * ==0 if B channels have separate communication channels (base) + * @ignoreframes: number of frames to ignore after setting up B channel + * @cidmode: !=0: start in CallID mode + * @modulename: name of driver module for LL registration + * * Allocate and initialize cardstate structure for Gigaset driver * Calls hardware dependent gigaset_initcshw() function * Calls B channel initialization function gigaset_initbcs() for each B channel - * parameters: - * drv hardware driver the device belongs to - * channels number of B channels supported by device - * onechannel !=0: B channel data and AT commands share one - * communication channel - * ==0: B channels have separate communication channels - * ignoreframes number of frames to ignore after setting up B channel - * cidmode !=0: start in CallID mode - * modulename name of driver module (used for I4L registration) - * return value: + * + * Return value: * pointer to cardstate structure */ struct cardstate *gigaset_initcs(struct gigaset_driver *drv, int channels, @@ -837,6 +884,17 @@ static void cleanup_cs(struct cardstate *cs) } +/** + * gigaset_start() - start device operations + * @cs: device descriptor structure. + * + * Prepares the device for use by setting up communication parameters, + * scheduling an EV_START event to initiate device initialization, and + * waiting for completion of the initialization. + * + * Return value: + * 1 - success, 0 - error + */ int gigaset_start(struct cardstate *cs) { unsigned long flags; @@ -879,9 +937,15 @@ int gigaset_start(struct cardstate *cs) } EXPORT_SYMBOL_GPL(gigaset_start); -/* gigaset_shutdown - * check if a device is associated to the cardstate structure and stop it - * return value: 0 if ok, -1 if no device was associated +/** + * gigaset_shutdown() - shut down device operations + * @cs: device descriptor structure. + * + * Deactivates the device by scheduling an EV_SHUTDOWN event and + * waiting for completion of the shutdown. + * + * Return value: + * 0 - success, -1 - error (no device associated) */ int gigaset_shutdown(struct cardstate *cs) { @@ -912,6 +976,13 @@ int gigaset_shutdown(struct cardstate *cs) } EXPORT_SYMBOL_GPL(gigaset_shutdown); +/** + * gigaset_stop() - stop device operations + * @cs: device descriptor structure. + * + * Stops operations on the device by scheduling an EV_STOP event and + * waiting for completion of the shutdown. + */ void gigaset_stop(struct cardstate *cs) { mutex_lock(&cs->mutex); @@ -1020,6 +1091,14 @@ struct cardstate *gigaset_get_cs_by_tty(struct tty_struct *tty) return gigaset_get_cs_by_minor(tty->index + tty->driver->minor_start); } +/** + * gigaset_freedriver() - free all associated ressources of a driver + * @drv: driver descriptor structure. + * + * Unregisters the driver from the system and deallocates the driver + * structure @drv and all structures referenced from it. + * All devices should be shut down before calling this. + */ void gigaset_freedriver(struct gigaset_driver *drv) { unsigned long flags; @@ -1035,14 +1114,16 @@ void gigaset_freedriver(struct gigaset_driver *drv) } EXPORT_SYMBOL_GPL(gigaset_freedriver); -/* gigaset_initdriver +/** + * gigaset_initdriver() - initialize driver structure + * @minor: First minor number + * @minors: Number of minors this driver can handle + * @procname: Name of the driver + * @devname: Name of the device files (prefix without minor number) + * * Allocate and initialize gigaset_driver structure. Initialize interface. - * parameters: - * minor First minor number - * minors Number of minors this driver can handle - * procname Name of the driver - * devname Name of the device files (prefix without minor number) - * return value: + * + * Return value: * Pointer to the gigaset_driver structure on success, NULL on failure. */ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, @@ -1095,6 +1176,13 @@ struct gigaset_driver *gigaset_initdriver(unsigned minor, unsigned minors, } EXPORT_SYMBOL_GPL(gigaset_initdriver); +/** + * gigaset_blockdriver() - block driver + * @drv: driver descriptor structure. + * + * Prevents the driver from attaching new devices, in preparation for + * deregistration. + */ void gigaset_blockdriver(struct gigaset_driver *drv) { drv->blocked = 1; @@ -1110,7 +1198,7 @@ static int __init gigaset_init_module(void) if (gigaset_debuglevel == 1) gigaset_debuglevel = DEBUG_DEFAULT; - pr_info(DRIVER_DESC "\n"); + pr_info(DRIVER_DESC DRIVER_DESC_DEBUG "\n"); return 0; } diff --git a/trunk/drivers/isdn/gigaset/ev-layer.c b/trunk/drivers/isdn/gigaset/ev-layer.c index 2d91049571a4..cc768caa38f5 100644 --- a/trunk/drivers/isdn/gigaset/ev-layer.c +++ b/trunk/drivers/isdn/gigaset/ev-layer.c @@ -207,7 +207,6 @@ struct reply_t gigaset_tab_nocid[] = /* leave dle mode */ {RSP_INIT, 0, 0,SEQ_DLE0, 201, 5, {0}, "^SDLE=0\r"}, {RSP_OK, 201,201, -1, 202,-1}, - //{RSP_ZDLE, 202,202, 0, 202, 0, {ACT_ERROR}},//DELETE {RSP_ZDLE, 202,202, 0, 0, 0, {ACT_DLE0}}, {RSP_NODEV, 200,249, -1, 0, 0, {ACT_FAKEDLE0}}, {RSP_ERROR, 200,249, -1, 0, 0, {ACT_FAILDLE0}}, @@ -265,6 +264,7 @@ struct reply_t gigaset_tab_nocid[] = {EV_SHUTDOWN, -1, -1, -1, -1,-1, {ACT_SHUTDOWN}}, //FIXME /* misc. */ + {RSP_ERROR, -1, -1, -1, -1, -1, {ACT_ERROR} }, {RSP_EMPTY, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME {RSP_ZCFGT, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME {RSP_ZCFG, -1, -1, -1, -1,-1, {ACT_DEBUG}}, //FIXME @@ -328,10 +328,9 @@ struct reply_t gigaset_tab_cid[] = {RSP_INIT, -1, -1,SEQ_HUP, 401, 5, {0}, "+VLS=0\r"}, /* hang up */ //-1,-1? {RSP_OK, 401,401, -1, 402, 5}, {RSP_ZVLS, 402,402, 0, 403, 5}, - {RSP_ZSAU, 403,403,ZSAU_DISCONNECT_REQ, -1,-1, {ACT_DEBUG}}, /* if not remote hup */ - //{RSP_ZSAU, 403,403,ZSAU_NULL, 401, 0, {ACT_ERROR}}, //DELETE//FIXME -> DLE0 // should we do this _before_ hanging up for base driver? - {RSP_ZSAU, 403,403,ZSAU_NULL, 0, 0, {ACT_DISCONNECT}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver? - {RSP_NODEV, 401,403, -1, 0, 0, {ACT_FAKEHUP}}, //FIXME -> DLE0 // should we do this _before_ hanging up for base driver? + {RSP_ZSAU, 403, 403, ZSAU_DISCONNECT_REQ, -1, -1, {ACT_DEBUG} }, + {RSP_ZSAU, 403, 403, ZSAU_NULL, 0, 0, {ACT_DISCONNECT} }, + {RSP_NODEV, 401, 403, -1, 0, 0, {ACT_FAKEHUP} }, {RSP_ERROR, 401,401, -1, 0, 0, {ACT_ABORTHUP}}, {EV_TIMEOUT, 401,403, -1, 0, 0, {ACT_ABORTHUP}}, @@ -474,8 +473,13 @@ static int cid_of_response(char *s) //FIXME is ;+ at end of non-CID response really impossible? } -/* This function will be called via task queue from the callback handler. - * We received a modem response and have to handle it.. +/** + * gigaset_handle_modem_response() - process received modem response + * @cs: device descriptor structure. + * + * Called by asyncdata/isocdata if a block of data received from the + * device must be processed as a modem command response. The data is + * already in the cs structure. */ void gigaset_handle_modem_response(struct cardstate *cs) { @@ -707,6 +711,11 @@ static void disconnect(struct at_state_t **at_state_p) if (bcs) { /* B channel assigned: invoke hardware specific handler */ cs->ops->close_bchannel(bcs); + /* notify LL */ + if (bcs->chstate & (CHS_D_UP | CHS_NOTIFY_LL)) { + bcs->chstate &= ~(CHS_D_UP | CHS_NOTIFY_LL); + gigaset_i4l_channel_cmd(bcs, ISDN_STAT_DHUP); + } } else { /* no B channel assigned: just deallocate */ spin_lock_irqsave(&cs->lock, flags); @@ -1429,11 +1438,12 @@ static void do_action(int action, struct cardstate *cs, cs->gotfwver = -1; dev_err(cs->dev, "could not read firmware version.\n"); break; -#ifdef CONFIG_GIGASET_DEBUG case ACT_ERROR: - *p_genresp = 1; - *p_resp_code = RSP_ERROR; + gig_dbg(DEBUG_ANY, "%s: ERROR response in ConState %d", + __func__, at_state->ConState); + cs->cur_at_seq = SEQ_NONE; break; +#ifdef CONFIG_GIGASET_DEBUG case ACT_TEST: { static int count = 3; //2; //1; diff --git a/trunk/drivers/isdn/gigaset/i4l.c b/trunk/drivers/isdn/gigaset/i4l.c index 9b22f9cf2f33..654489d836cd 100644 --- a/trunk/drivers/isdn/gigaset/i4l.c +++ b/trunk/drivers/isdn/gigaset/i4l.c @@ -51,6 +51,12 @@ static int writebuf_from_LL(int driverID, int channel, int ack, return -ENODEV; } bcs = &cs->bcs[channel]; + + /* can only handle linear sk_buffs */ + if (skb_linearize(skb) < 0) { + dev_err(cs->dev, "%s: skb_linearize failed\n", __func__); + return -ENOMEM; + } len = skb->len; gig_dbg(DEBUG_LLDATA, @@ -79,6 +85,14 @@ static int writebuf_from_LL(int driverID, int channel, int ack, return cs->ops->send_skb(bcs, skb); } +/** + * gigaset_skb_sent() - acknowledge sending an skb + * @bcs: B channel descriptor structure. + * @skb: sent data. + * + * Called by hardware module {bas,ser,usb}_gigaset when the data in a + * skb has been successfully sent, for signalling completion to the LL. + */ void gigaset_skb_sent(struct bc_state *bcs, struct sk_buff *skb) { unsigned len; @@ -455,6 +469,15 @@ int gigaset_isdn_setup_accept(struct at_state_t *at_state) return 0; } +/** + * gigaset_isdn_icall() - signal incoming call + * @at_state: connection state structure. + * + * Called by main module to notify the LL that an incoming call has been + * received. @at_state contains the parameters of the call. + * + * Return value: call disposition (ICALL_*) + */ int gigaset_isdn_icall(struct at_state_t *at_state) { struct cardstate *cs = at_state->cs; diff --git a/trunk/drivers/isdn/gigaset/interface.c b/trunk/drivers/isdn/gigaset/interface.c index f33ac27de643..6a8e1384e7bd 100644 --- a/trunk/drivers/isdn/gigaset/interface.c +++ b/trunk/drivers/isdn/gigaset/interface.c @@ -616,6 +616,15 @@ void gigaset_if_free(struct cardstate *cs) tty_unregister_device(drv->tty, cs->minor_index); } +/** + * gigaset_if_receive() - pass a received block of data to the tty device + * @cs: device descriptor structure. + * @buffer: received data. + * @len: number of bytes received. + * + * Called by asyncdata/isocdata if a block of data received from the + * device must be sent to userspace through the ttyG* device. + */ void gigaset_if_receive(struct cardstate *cs, unsigned char *buffer, size_t len) { diff --git a/trunk/drivers/isdn/gigaset/isocdata.c b/trunk/drivers/isdn/gigaset/isocdata.c index bed38fcc432b..9f3ef7b4248c 100644 --- a/trunk/drivers/isdn/gigaset/isocdata.c +++ b/trunk/drivers/isdn/gigaset/isocdata.c @@ -429,7 +429,7 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, return -EAGAIN; } - dump_bytes(DEBUG_STREAM, "snd data", in, count); + dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count); /* bitstuff and checksum input data */ fcs = PPP_INITFCS; @@ -448,7 +448,6 @@ static inline int hdlc_buildframe(struct isowbuf_t *iwb, /* put closing flag and repeat byte for flag idle */ isowbuf_putflag(iwb); end = isowbuf_donewrite(iwb); - dump_bytes(DEBUG_STREAM_DUMP, "isowbuf", iwb->data, end + 1); return end; } @@ -482,6 +481,8 @@ static inline int trans_buildframe(struct isowbuf_t *iwb, } gig_dbg(DEBUG_STREAM, "put %d bytes", count); + dump_bytes(DEBUG_STREAM_DUMP, "snd data", in, count); + write = iwb->write; do { c = bitrev8(*in++); @@ -583,7 +584,7 @@ static inline void hdlc_done(struct bc_state *bcs) procskb->tail -= 2; gig_dbg(DEBUG_ISO, "%s: good frame (%d octets)", __func__, procskb->len); - dump_bytes(DEBUG_STREAM, + dump_bytes(DEBUG_STREAM_DUMP, "rcv data", procskb->data, procskb->len); bcs->hw.bas->goodbytes += procskb->len; gigaset_rcv_skb(procskb, bcs->cs, bcs); @@ -878,6 +879,8 @@ static inline void trans_receive(unsigned char *src, unsigned count, dobytes--; } if (dobytes == 0) { + dump_bytes(DEBUG_STREAM_DUMP, + "rcv data", skb->data, skb->len); gigaset_rcv_skb(skb, bcs->cs, bcs); bcs->skb = skb = dev_alloc_skb(SBUFSIZE + HW_HDR_LEN); if (!skb) { @@ -973,16 +976,17 @@ void gigaset_isoc_input(struct inbuf_t *inbuf) /* == data output ========================================================== */ -/* gigaset_send_skb - * called by common.c to queue an skb for sending - * and start transmission if necessary - * parameters: - * B Channel control structure - * skb - * return value: - * number of bytes accepted for sending - * (skb->len if ok, 0 if out of buffer space) - * or error code (< 0, eg. -EINVAL) +/** + * gigaset_isoc_send_skb() - queue an skb for sending + * @bcs: B channel descriptor structure. + * @skb: data to send. + * + * Called by i4l.c to queue an skb for sending, and start transmission if + * necessary. + * + * Return value: + * number of bytes accepted for sending (skb->len) if ok, + * error code < 0 (eg. -ENODEV) on error */ int gigaset_isoc_send_skb(struct bc_state *bcs, struct sk_buff *skb) { diff --git a/trunk/drivers/mmc/core/sdio_cis.c b/trunk/drivers/mmc/core/sdio_cis.c index e1035c895808..f85dcd536508 100644 --- a/trunk/drivers/mmc/core/sdio_cis.c +++ b/trunk/drivers/mmc/core/sdio_cis.c @@ -29,6 +29,8 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func, unsigned i, nr_strings; char **buffer, *string; + /* Find all null-terminated (including zero length) strings in + the TPLLV1_INFO field. Trailing garbage is ignored. */ buf += 2; size -= 2; @@ -39,11 +41,8 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func, if (buf[i] == 0) nr_strings++; } - - if (nr_strings < 4) { - printk(KERN_WARNING "SDIO: ignoring broken CISTPL_VERS_1\n"); + if (nr_strings == 0) return 0; - } size = i; diff --git a/trunk/drivers/net/au1000_eth.c b/trunk/drivers/net/au1000_eth.c index fdf5937233fc..04f63c77071d 100644 --- a/trunk/drivers/net/au1000_eth.c +++ b/trunk/drivers/net/au1000_eth.c @@ -721,7 +721,7 @@ static inline void update_rx_stats(struct net_device *dev, u32 status) ps->rx_errors++; if (status & RX_MISSED_FRAME) ps->rx_missed_errors++; - if (status & (RX_OVERLEN | RX_OVERLEN | RX_LEN_ERROR)) + if (status & (RX_OVERLEN | RX_RUNT | RX_LEN_ERROR)) ps->rx_length_errors++; if (status & RX_CRC_ERROR) ps->rx_crc_errors++; @@ -794,8 +794,6 @@ static int au1000_rx(struct net_device *dev) printk("rx len error\n"); if (status & RX_U_CNTRL_FRAME) printk("rx u control frame\n"); - if (status & RX_MISSED_FRAME) - printk("rx miss\n"); } } prxd->buff_stat = (u32)(pDB->dma_addr | RX_DMA_ENABLE); diff --git a/trunk/drivers/net/benet/be_cmds.c b/trunk/drivers/net/benet/be_cmds.c index 79d35d122c08..89876ade5e33 100644 --- a/trunk/drivers/net/benet/be_cmds.c +++ b/trunk/drivers/net/benet/be_cmds.c @@ -1129,7 +1129,6 @@ int be_cmd_write_flashrom(struct be_adapter *adapter, struct be_dma_mem *cmd, spin_lock_bh(&adapter->mcc_lock); wrb = wrb_from_mccq(adapter); - req = embedded_payload(wrb); sge = nonembedded_sgl(wrb); be_wrb_hdr_prepare(wrb, cmd->size, false, 1); diff --git a/trunk/drivers/net/benet/be_cmds.h b/trunk/drivers/net/benet/be_cmds.h index 8b4c2cb9ad62..a86f917f85f4 100644 --- a/trunk/drivers/net/benet/be_cmds.h +++ b/trunk/drivers/net/benet/be_cmds.h @@ -62,7 +62,7 @@ enum { MCC_STATUS_QUEUE_FLUSHING = 0x4, /* The command is completing with a DMA error */ MCC_STATUS_DMA_FAILED = 0x5, - MCC_STATUS_NOT_SUPPORTED = 0x66 + MCC_STATUS_NOT_SUPPORTED = 66 }; #define CQE_STATUS_COMPL_MASK 0xFFFF diff --git a/trunk/drivers/net/benet/be_ethtool.c b/trunk/drivers/net/benet/be_ethtool.c index 11445df3dbc0..cda5bf2fc50a 100644 --- a/trunk/drivers/net/benet/be_ethtool.c +++ b/trunk/drivers/net/benet/be_ethtool.c @@ -358,7 +358,7 @@ const struct ethtool_ops be_ethtool_ops = { .get_rx_csum = be_get_rx_csum, .set_rx_csum = be_set_rx_csum, .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, + .set_tx_csum = ethtool_op_set_tx_hw_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, .get_tso = ethtool_op_get_tso, diff --git a/trunk/drivers/net/benet/be_main.c b/trunk/drivers/net/benet/be_main.c index 2f9b50156e0c..6d5e81f7046f 100644 --- a/trunk/drivers/net/benet/be_main.c +++ b/trunk/drivers/net/benet/be_main.c @@ -197,7 +197,7 @@ void netdev_stats_update(struct be_adapter *adapter) /* no space available in linux */ dev_stats->tx_dropped = 0; - dev_stats->multicast = port_stats->tx_multicastframes; + dev_stats->multicast = port_stats->rx_multicast_frames; dev_stats->collisions = 0; /* detailed tx_errors */ @@ -1899,8 +1899,8 @@ static void be_netdev_init(struct net_device *netdev) struct be_adapter *adapter = netdev_priv(netdev); netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM | NETIF_F_GRO; + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_HW_CSUM | + NETIF_F_GRO; netdev->flags |= IFF_MULTICAST; diff --git a/trunk/drivers/net/e1000e/82571.c b/trunk/drivers/net/e1000e/82571.c index b53b40ba88a8..d1e0563a67df 100644 --- a/trunk/drivers/net/e1000e/82571.c +++ b/trunk/drivers/net/e1000e/82571.c @@ -1803,7 +1803,7 @@ struct e1000_info e1000_82574_info = { | FLAG_HAS_AMT | FLAG_HAS_CTRLEXT_ON_LOAD, .pba = 20, - .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, + .max_hw_frame_size = DEFAULT_JUMBO, .get_variants = e1000_get_variants_82571, .mac_ops = &e82571_mac_ops, .phy_ops = &e82_phy_ops_bm, @@ -1820,7 +1820,7 @@ struct e1000_info e1000_82583_info = { | FLAG_HAS_AMT | FLAG_HAS_CTRLEXT_ON_LOAD, .pba = 20, - .max_hw_frame_size = DEFAULT_JUMBO, + .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, .get_variants = e1000_get_variants_82571, .mac_ops = &e82571_mac_ops, .phy_ops = &e82_phy_ops_bm, diff --git a/trunk/drivers/net/ethoc.c b/trunk/drivers/net/ethoc.c index b7311bc00258..34d0c69e67f7 100644 --- a/trunk/drivers/net/ethoc.c +++ b/trunk/drivers/net/ethoc.c @@ -19,6 +19,10 @@ #include #include +static int buffer_size = 0x8000; /* 32 KBytes */ +module_param(buffer_size, int, 0); +MODULE_PARM_DESC(buffer_size, "DMA buffer allocation size"); + /* register offsets */ #define MODER 0x00 #define INT_SOURCE 0x04 @@ -167,6 +171,7 @@ * struct ethoc - driver-private device structure * @iobase: pointer to I/O memory region * @membase: pointer to buffer memory region + * @dma_alloc: dma allocated buffer size * @num_tx: number of send buffers * @cur_tx: last send buffer written * @dty_tx: last buffer actually sent @@ -185,6 +190,7 @@ struct ethoc { void __iomem *iobase; void __iomem *membase; + int dma_alloc; unsigned int num_tx; unsigned int cur_tx; @@ -284,7 +290,7 @@ static int ethoc_init_ring(struct ethoc *dev) dev->cur_rx = 0; /* setup transmission buffers */ - bd.addr = 0; + bd.addr = virt_to_phys(dev->membase); bd.stat = TX_BD_IRQ | TX_BD_CRC; for (i = 0; i < dev->num_tx; i++) { @@ -295,7 +301,6 @@ static int ethoc_init_ring(struct ethoc *dev) bd.addr += ETHOC_BUFSIZ; } - bd.addr = dev->num_tx * ETHOC_BUFSIZ; bd.stat = RX_BD_EMPTY | RX_BD_IRQ; for (i = 0; i < dev->num_rx; i++) { @@ -400,8 +405,12 @@ static int ethoc_rx(struct net_device *dev, int limit) if (ethoc_update_rx_stats(priv, &bd) == 0) { int size = bd.stat >> 16; struct sk_buff *skb = netdev_alloc_skb(dev, size); + + size -= 4; /* strip the CRC */ + skb_reserve(skb, 2); /* align TCP/IP header */ + if (likely(skb)) { - void *src = priv->membase + bd.addr; + void *src = phys_to_virt(bd.addr); memcpy_fromio(skb_put(skb, size), src, size); skb->protocol = eth_type_trans(skb, dev); priv->stats.rx_packets++; @@ -653,9 +662,9 @@ static int ethoc_open(struct net_device *dev) if (ret) return ret; - /* calculate the number of TX/RX buffers */ - num_bd = (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ; - priv->num_tx = min(min_tx, num_bd / 4); + /* calculate the number of TX/RX buffers, maximum 128 supported */ + num_bd = min(128, (dev->mem_end - dev->mem_start + 1) / ETHOC_BUFSIZ); + priv->num_tx = max(min_tx, num_bd / 4); priv->num_rx = num_bd - priv->num_tx; ethoc_write(priv, TX_BD_NUM, priv->num_tx); @@ -823,7 +832,7 @@ static netdev_tx_t ethoc_start_xmit(struct sk_buff *skb, struct net_device *dev) else bd.stat &= ~TX_BD_PAD; - dest = priv->membase + bd.addr; + dest = phys_to_virt(bd.addr); memcpy_toio(dest, skb->data, skb->len); bd.stat &= ~(TX_BD_STATS | TX_BD_LEN_MASK); @@ -903,22 +912,19 @@ static int ethoc_probe(struct platform_device *pdev) /* obtain buffer memory space */ res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - if (!res) { - dev_err(&pdev->dev, "cannot obtain memory space\n"); - ret = -ENXIO; - goto free; - } - - mem = devm_request_mem_region(&pdev->dev, res->start, + if (res) { + mem = devm_request_mem_region(&pdev->dev, res->start, res->end - res->start + 1, res->name); - if (!mem) { - dev_err(&pdev->dev, "cannot request memory space\n"); - ret = -ENXIO; - goto free; + if (!mem) { + dev_err(&pdev->dev, "cannot request memory space\n"); + ret = -ENXIO; + goto free; + } + + netdev->mem_start = mem->start; + netdev->mem_end = mem->end; } - netdev->mem_start = mem->start; - netdev->mem_end = mem->end; /* obtain device IRQ number */ res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); @@ -933,6 +939,7 @@ static int ethoc_probe(struct platform_device *pdev) /* setup driver-private data */ priv = netdev_priv(netdev); priv->netdev = netdev; + priv->dma_alloc = 0; priv->iobase = devm_ioremap_nocache(&pdev->dev, netdev->base_addr, mmio->end - mmio->start + 1); @@ -942,12 +949,27 @@ static int ethoc_probe(struct platform_device *pdev) goto error; } - priv->membase = devm_ioremap_nocache(&pdev->dev, netdev->mem_start, - mem->end - mem->start + 1); - if (!priv->membase) { - dev_err(&pdev->dev, "cannot remap memory space\n"); - ret = -ENXIO; - goto error; + if (netdev->mem_end) { + priv->membase = devm_ioremap_nocache(&pdev->dev, + netdev->mem_start, mem->end - mem->start + 1); + if (!priv->membase) { + dev_err(&pdev->dev, "cannot remap memory space\n"); + ret = -ENXIO; + goto error; + } + } else { + /* Allocate buffer memory */ + priv->membase = dma_alloc_coherent(NULL, + buffer_size, (void *)&netdev->mem_start, + GFP_KERNEL); + if (!priv->membase) { + dev_err(&pdev->dev, "cannot allocate %dB buffer\n", + buffer_size); + ret = -ENOMEM; + goto error; + } + netdev->mem_end = netdev->mem_start + buffer_size; + priv->dma_alloc = buffer_size; } /* Allow the platform setup code to pass in a MAC address. */ @@ -1034,6 +1056,9 @@ static int ethoc_probe(struct platform_device *pdev) kfree(priv->mdio->irq); mdiobus_free(priv->mdio); free: + if (priv->dma_alloc) + dma_free_coherent(NULL, priv->dma_alloc, priv->membase, + netdev->mem_start); free_netdev(netdev); out: return ret; @@ -1059,7 +1084,9 @@ static int ethoc_remove(struct platform_device *pdev) kfree(priv->mdio->irq); mdiobus_free(priv->mdio); } - + if (priv->dma_alloc) + dma_free_coherent(NULL, priv->dma_alloc, priv->membase, + netdev->mem_start); unregister_netdev(netdev); free_netdev(netdev); } diff --git a/trunk/drivers/net/ixgbe/ixgbe_82599.c b/trunk/drivers/net/ixgbe/ixgbe_82599.c index 2ec58dcdb82b..34b04924c8a1 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_82599.c +++ b/trunk/drivers/net/ixgbe/ixgbe_82599.c @@ -330,6 +330,8 @@ static enum ixgbe_media_type ixgbe_get_media_type_82599(struct ixgbe_hw *hw) switch (hw->device_id) { case IXGBE_DEV_ID_82599_KX4: + case IXGBE_DEV_ID_82599_KX4_MEZZ: + case IXGBE_DEV_ID_82599_COMBO_BACKPLANE: case IXGBE_DEV_ID_82599_XAUI_LOM: /* Default device ID is mezzanine card KX/KX4 */ media_type = ixgbe_media_type_backplane; diff --git a/trunk/drivers/net/ixgbe/ixgbe_main.c b/trunk/drivers/net/ixgbe/ixgbe_main.c index 28fbb9d281f9..cbb143ca1eb8 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_main.c +++ b/trunk/drivers/net/ixgbe/ixgbe_main.c @@ -97,8 +97,12 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_SFP), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_KX4_MEZZ), + board_82599 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_CX4), board_82599 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82599_COMBO_BACKPLANE), + board_82599 }, /* required last entry */ {0, } diff --git a/trunk/drivers/net/ixgbe/ixgbe_type.h b/trunk/drivers/net/ixgbe/ixgbe_type.h index 7c93e923bf2e..ef4bdd58e016 100644 --- a/trunk/drivers/net/ixgbe/ixgbe_type.h +++ b/trunk/drivers/net/ixgbe/ixgbe_type.h @@ -49,9 +49,11 @@ #define IXGBE_DEV_ID_82598_SR_DUAL_PORT_EM 0x10E1 #define IXGBE_DEV_ID_82598EB_XF_LR 0x10F4 #define IXGBE_DEV_ID_82599_KX4 0x10F7 +#define IXGBE_DEV_ID_82599_KX4_MEZZ 0x1514 #define IXGBE_DEV_ID_82599_CX4 0x10F9 #define IXGBE_DEV_ID_82599_SFP 0x10FB #define IXGBE_DEV_ID_82599_XAUI_LOM 0x10FC +#define IXGBE_DEV_ID_82599_COMBO_BACKPLANE 0x10F8 /* General Registers */ #define IXGBE_CTRL 0x00000 diff --git a/trunk/drivers/net/netxen/netxen_nic_main.c b/trunk/drivers/net/netxen/netxen_nic_main.c index b5aa974827e5..9b9eab107704 100644 --- a/trunk/drivers/net/netxen/netxen_nic_main.c +++ b/trunk/drivers/net/netxen/netxen_nic_main.c @@ -1714,7 +1714,7 @@ netxen_nic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) /* 4 fragments per cmd des */ no_of_desc = (frag_count + 3) >> 2; - if (unlikely(no_of_desc + 2) > netxen_tx_avail(tx_ring)) { + if (unlikely(no_of_desc + 2 > netxen_tx_avail(tx_ring))) { netif_stop_queue(netdev); return NETDEV_TX_BUSY; } diff --git a/trunk/drivers/net/pasemi_mac_ethtool.c b/trunk/drivers/net/pasemi_mac_ethtool.c index 064a4fe1dd90..28a86224879d 100644 --- a/trunk/drivers/net/pasemi_mac_ethtool.c +++ b/trunk/drivers/net/pasemi_mac_ethtool.c @@ -71,6 +71,9 @@ pasemi_mac_ethtool_get_settings(struct net_device *netdev, struct pasemi_mac *mac = netdev_priv(netdev); struct phy_device *phydev = mac->phydev; + if (!phydev) + return -EOPNOTSUPP; + return phy_ethtool_gset(phydev, cmd); } diff --git a/trunk/drivers/net/pcmcia/pcnet_cs.c b/trunk/drivers/net/pcmcia/pcnet_cs.c index 474876c879cb..bd3447f04902 100644 --- a/trunk/drivers/net/pcmcia/pcnet_cs.c +++ b/trunk/drivers/net/pcmcia/pcnet_cs.c @@ -1754,14 +1754,14 @@ static struct pcmcia_device_id pcnet_ids[] = { PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(0, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"), - PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "DP83903.cis"), + PCMCIA_MFC_DEVICE_CIS_PROD_ID12(0, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"), + PCMCIA_MFC_DEVICE_CIS_PROD_ID4(0, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(0, 0x0175, 0x0000, "cis/DP83903.cis"), PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "cis/LA-PCM.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "NE2K.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "tamarack.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"), PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b), PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0", 0xb4be14e3, 0x43ac239b, 0x0877b627), diff --git a/trunk/drivers/net/qlge/qlge.h b/trunk/drivers/net/qlge/qlge.h index 30d5585beeee..3ec6e85587a2 100644 --- a/trunk/drivers/net/qlge/qlge.h +++ b/trunk/drivers/net/qlge/qlge.h @@ -9,6 +9,7 @@ #include #include +#include /* * General definitions... @@ -135,9 +136,9 @@ enum { RST_FO_TFO = (1 << 0), RST_FO_RR_MASK = 0x00060000, RST_FO_RR_CQ_CAM = 0x00000000, - RST_FO_RR_DROP = 0x00000001, - RST_FO_RR_DQ = 0x00000002, - RST_FO_RR_RCV_FUNC_CQ = 0x00000003, + RST_FO_RR_DROP = 0x00000002, + RST_FO_RR_DQ = 0x00000004, + RST_FO_RR_RCV_FUNC_CQ = 0x00000006, RST_FO_FRB = (1 << 12), RST_FO_MOP = (1 << 13), RST_FO_REG = (1 << 14), @@ -1477,7 +1478,6 @@ struct ql_adapter { u32 mailbox_in; u32 mailbox_out; struct mbox_params idc_mbc; - struct mutex mpi_mutex; int tx_ring_size; int rx_ring_size; diff --git a/trunk/drivers/net/qlge/qlge_ethtool.c b/trunk/drivers/net/qlge/qlge_ethtool.c index 68f9bd280f86..52073946bce3 100644 --- a/trunk/drivers/net/qlge/qlge_ethtool.c +++ b/trunk/drivers/net/qlge/qlge_ethtool.c @@ -45,7 +45,6 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) if (!netif_running(qdev->ndev)) return status; - spin_lock(&qdev->hw_lock); /* Skip the default queue, and update the outbound handler * queues if they changed. */ @@ -92,7 +91,6 @@ static int ql_update_ring_coalescing(struct ql_adapter *qdev) } } exit: - spin_unlock(&qdev->hw_lock); return status; } diff --git a/trunk/drivers/net/qlge/qlge_main.c b/trunk/drivers/net/qlge/qlge_main.c index 3d0efea32111..61680715cde0 100644 --- a/trunk/drivers/net/qlge/qlge_main.c +++ b/trunk/drivers/net/qlge/qlge_main.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -1926,12 +1925,10 @@ static void ql_vlan_rx_add_vid(struct net_device *ndev, u16 vid) status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); if (status) return; - spin_lock(&qdev->hw_lock); if (ql_set_mac_addr_reg (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { QPRINTK(qdev, IFUP, ERR, "Failed to init vlan address.\n"); } - spin_unlock(&qdev->hw_lock); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); } @@ -1945,12 +1942,10 @@ static void ql_vlan_rx_kill_vid(struct net_device *ndev, u16 vid) if (status) return; - spin_lock(&qdev->hw_lock); if (ql_set_mac_addr_reg (qdev, (u8 *) &enable_bit, MAC_ADDR_TYPE_VLAN, vid)) { QPRINTK(qdev, IFUP, ERR, "Failed to clear vlan address.\n"); } - spin_unlock(&qdev->hw_lock); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); } @@ -2001,15 +1996,17 @@ static irqreturn_t qlge_isr(int irq, void *dev_id) /* * Check MPI processor activity. */ - if (var & STS_PI) { + if ((var & STS_PI) && + (ql_read32(qdev, INTR_MASK) & INTR_MASK_PI)) { /* * We've got an async event or mailbox completion. * Handle it and clear the source of the interrupt. */ QPRINTK(qdev, INTR, ERR, "Got MPI processor interrupt.\n"); ql_disable_completion_interrupt(qdev, intr_context->intr); - queue_delayed_work_on(smp_processor_id(), qdev->workqueue, - &qdev->mpi_work, 0); + ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); + queue_delayed_work_on(smp_processor_id(), + qdev->workqueue, &qdev->mpi_work, 0); work_done++; } @@ -3585,7 +3582,6 @@ static void qlge_set_multicast_list(struct net_device *ndev) status = ql_sem_spinlock(qdev, SEM_RT_IDX_MASK); if (status) return; - spin_lock(&qdev->hw_lock); /* * Set or clear promiscuous mode if a * transition is taking place. @@ -3662,7 +3658,6 @@ static void qlge_set_multicast_list(struct net_device *ndev) } } exit: - spin_unlock(&qdev->hw_lock); ql_sem_unlock(qdev, SEM_RT_IDX_MASK); } @@ -3682,10 +3677,8 @@ static int qlge_set_mac_address(struct net_device *ndev, void *p) status = ql_sem_spinlock(qdev, SEM_MAC_ADDR_MASK); if (status) return status; - spin_lock(&qdev->hw_lock); status = ql_set_mac_addr_reg(qdev, (u8 *) ndev->dev_addr, MAC_ADDR_TYPE_CAM_MAC, qdev->func * MAX_CQ); - spin_unlock(&qdev->hw_lock); if (status) QPRINTK(qdev, HW, ERR, "Failed to load MAC address.\n"); ql_sem_unlock(qdev, SEM_MAC_ADDR_MASK); @@ -3928,7 +3921,6 @@ static int __devinit ql_init_device(struct pci_dev *pdev, INIT_DELAYED_WORK(&qdev->mpi_work, ql_mpi_work); INIT_DELAYED_WORK(&qdev->mpi_port_cfg_work, ql_mpi_port_cfg_work); INIT_DELAYED_WORK(&qdev->mpi_idc_work, ql_mpi_idc_work); - mutex_init(&qdev->mpi_mutex); init_completion(&qdev->ide_completion); if (!cards_found) { diff --git a/trunk/drivers/net/qlge/qlge_mpi.c b/trunk/drivers/net/qlge/qlge_mpi.c index 6685bd97da91..c2e43073047e 100644 --- a/trunk/drivers/net/qlge/qlge_mpi.c +++ b/trunk/drivers/net/qlge/qlge_mpi.c @@ -472,7 +472,6 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) { int status, count; - mutex_lock(&qdev->mpi_mutex); /* Begin polled mode for MPI */ ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16)); @@ -541,7 +540,6 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp) status = -EIO; } end: - mutex_unlock(&qdev->mpi_mutex); /* End polled mode for MPI */ ql_write32(qdev, INTR_MASK, (INTR_MASK_PI << 16) | INTR_MASK_PI); return status; @@ -776,7 +774,9 @@ static int ql_idc_wait(struct ql_adapter *qdev) static int ql_set_port_cfg(struct ql_adapter *qdev) { int status; + rtnl_lock(); status = ql_mb_set_port_cfg(qdev); + rtnl_unlock(); if (status) return status; status = ql_idc_wait(qdev); @@ -797,7 +797,9 @@ void ql_mpi_port_cfg_work(struct work_struct *work) container_of(work, struct ql_adapter, mpi_port_cfg_work.work); int status; + rtnl_lock(); status = ql_mb_get_port_cfg(qdev); + rtnl_unlock(); if (status) { QPRINTK(qdev, DRV, ERR, "Bug: Failed to get port config data.\n"); @@ -855,7 +857,9 @@ void ql_mpi_idc_work(struct work_struct *work) * needs to be set. * */ set_bit(QL_CAM_RT_SET, &qdev->flags); + rtnl_lock(); status = ql_mb_idc_ack(qdev); + rtnl_unlock(); if (status) { QPRINTK(qdev, DRV, ERR, "Bug: No pending IDC!\n"); @@ -871,7 +875,7 @@ void ql_mpi_work(struct work_struct *work) struct mbox_params *mbcp = &mbc; int err = 0; - mutex_lock(&qdev->mpi_mutex); + rtnl_lock(); while (ql_read32(qdev, STS) & STS_PI) { memset(mbcp, 0, sizeof(struct mbox_params)); @@ -884,7 +888,7 @@ void ql_mpi_work(struct work_struct *work) break; } - mutex_unlock(&qdev->mpi_mutex); + rtnl_unlock(); ql_enable_completion_interrupt(qdev, 0); } diff --git a/trunk/drivers/net/tg3.c b/trunk/drivers/net/tg3.c index f09bc5dfe8b2..ba5d3fe753b6 100644 --- a/trunk/drivers/net/tg3.c +++ b/trunk/drivers/net/tg3.c @@ -902,11 +902,12 @@ static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg) struct tg3 *tp = bp->priv; u32 val; - if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) - return -EAGAIN; + spin_lock_bh(&tp->lock); if (tg3_readphy(tp, reg, &val)) - return -EIO; + val = -EIO; + + spin_unlock_bh(&tp->lock); return val; } @@ -914,14 +915,16 @@ static int tg3_mdio_read(struct mii_bus *bp, int mii_id, int reg) static int tg3_mdio_write(struct mii_bus *bp, int mii_id, int reg, u16 val) { struct tg3 *tp = bp->priv; + u32 ret = 0; - if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_PAUSED) - return -EAGAIN; + spin_lock_bh(&tp->lock); if (tg3_writephy(tp, reg, val)) - return -EIO; + ret = -EIO; - return 0; + spin_unlock_bh(&tp->lock); + + return ret; } static int tg3_mdio_reset(struct mii_bus *bp) @@ -1011,12 +1014,6 @@ static void tg3_mdio_config_5785(struct tg3 *tp) static void tg3_mdio_start(struct tg3 *tp) { - if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { - mutex_lock(&tp->mdio_bus->mdio_lock); - tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED; - mutex_unlock(&tp->mdio_bus->mdio_lock); - } - tp->mi_mode &= ~MAC_MI_MODE_AUTO_POLL; tw32_f(MAC_MI_MODE, tp->mi_mode); udelay(80); @@ -1041,15 +1038,6 @@ static void tg3_mdio_start(struct tg3 *tp) tg3_mdio_config_5785(tp); } -static void tg3_mdio_stop(struct tg3 *tp) -{ - if (tp->tg3_flags3 & TG3_FLG3_MDIOBUS_INITED) { - mutex_lock(&tp->mdio_bus->mdio_lock); - tp->tg3_flags3 |= TG3_FLG3_MDIOBUS_PAUSED; - mutex_unlock(&tp->mdio_bus->mdio_lock); - } -} - static int tg3_mdio_init(struct tg3 *tp) { int i; @@ -1141,7 +1129,6 @@ static void tg3_mdio_fini(struct tg3 *tp) tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_INITED; mdiobus_unregister(tp->mdio_bus); mdiobus_free(tp->mdio_bus); - tp->tg3_flags3 &= ~TG3_FLG3_MDIOBUS_PAUSED; } } @@ -1363,7 +1350,7 @@ static void tg3_adjust_link(struct net_device *dev) struct tg3 *tp = netdev_priv(dev); struct phy_device *phydev = tp->mdio_bus->phy_map[PHY_ADDR]; - spin_lock(&tp->lock); + spin_lock_bh(&tp->lock); mac_mode = tp->mac_mode & ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX); @@ -1431,7 +1418,7 @@ static void tg3_adjust_link(struct net_device *dev) tp->link_config.active_speed = phydev->speed; tp->link_config.active_duplex = phydev->duplex; - spin_unlock(&tp->lock); + spin_unlock_bh(&tp->lock); if (linkmesg) tg3_link_report(tp); @@ -6392,8 +6379,6 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_nvram_lock(tp); - tg3_mdio_stop(tp); - tg3_ape_lock(tp, TG3_APE_LOCK_GRC); /* No matching tg3_nvram_unlock() after this because @@ -8698,6 +8683,8 @@ static int tg3_close(struct net_device *dev) del_timer_sync(&tp->timer); + tg3_phy_stop(tp); + tg3_full_lock(tp, 1); #if 0 tg3_dump_state(tp); diff --git a/trunk/drivers/net/tg3.h b/trunk/drivers/net/tg3.h index 524691cd9896..bab7940158e6 100644 --- a/trunk/drivers/net/tg3.h +++ b/trunk/drivers/net/tg3.h @@ -2748,7 +2748,6 @@ struct tg3 { #define TG3_FLG3_5701_DMA_BUG 0x00000008 #define TG3_FLG3_USE_PHYLIB 0x00000010 #define TG3_FLG3_MDIOBUS_INITED 0x00000020 -#define TG3_FLG3_MDIOBUS_PAUSED 0x00000040 #define TG3_FLG3_PHY_CONNECTED 0x00000080 #define TG3_FLG3_RGMII_STD_IBND_DISABLE 0x00000100 #define TG3_FLG3_RGMII_EXT_IBND_RX_EN 0x00000200 diff --git a/trunk/drivers/net/usb/rndis_host.c b/trunk/drivers/net/usb/rndis_host.c index d032bba9bc4c..0caa8008c51c 100644 --- a/trunk/drivers/net/usb/rndis_host.c +++ b/trunk/drivers/net/usb/rndis_host.c @@ -418,6 +418,7 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags) goto halt_fail_and_release; } memcpy(net->dev_addr, bp, ETH_ALEN); + memcpy(net->perm_addr, bp, ETH_ALEN); /* set a nonzero filter to enable data transfers */ memset(u.set, 0, sizeof *u.set); diff --git a/trunk/drivers/serial/serial_cs.c b/trunk/drivers/serial/serial_cs.c index a3bb49031a7f..ff4617e21426 100644 --- a/trunk/drivers/serial/serial_cs.c +++ b/trunk/drivers/serial/serial_cs.c @@ -873,10 +873,10 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet", 0xf5f025c2, 0x338e8155, "cis/PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "Psion Dacom", "Gold Card V34 Ethernet GSM", 0xf5f025c2, 0x4ae85d35, "cis/PCMLM28.cis"), PCMCIA_PFC_DEVICE_CIS_PROD_ID12(1, "LINKSYS", "PCMLM28", 0xf7cb0b07, 0x66881874, "cis/PCMLM28.cis"), - PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "DP83903.cis"), - PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "DP83903.cis"), + PCMCIA_MFC_DEVICE_CIS_PROD_ID12(1, "DAYNA COMMUNICATIONS", "LAN AND MODEM MULTIFUNCTION", 0x8fdf8f89, 0xdd5ed9e8, "cis/DP83903.cis"), + PCMCIA_MFC_DEVICE_CIS_PROD_ID4(1, "NSC MF LAN/Modem", 0x58fc6056, "cis/DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0556, "cis/3CCFEM556.cis"), - PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"), + PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */ @@ -884,9 +884,9 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */ PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */ PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "COMpad2.cis"), - PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), - PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"), + PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"), + PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "cis/COMpad2.cis"), PCMCIA_DEVICE_CIS_PROD_ID2("RS-COM 2P", 0xad20b156, "cis/RS-COM-2P.cis"), PCMCIA_DEVICE_CIS_MANF_CARD(0x0013, 0x0000, "GLOBETROTTER.cis"), PCMCIA_DEVICE_PROD_ID12("ELAN DIGITAL SYSTEMS LTD, c1997.","SERIAL CARD: SL100 1.00.",0x19ca78af,0xf964f42b), diff --git a/trunk/drivers/video/da8xx-fb.c b/trunk/drivers/video/da8xx-fb.c index 42e1005e2916..d065894ce38f 100644 --- a/trunk/drivers/video/da8xx-fb.c +++ b/trunk/drivers/video/da8xx-fb.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include